mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 04:46:40 +07:00
submitting tags
This commit is contained in:
parent
7fa5c17def
commit
770a256ab8
2 changed files with 34 additions and 10 deletions
|
@ -1,10 +1,4 @@
|
||||||
import React, {
|
import React, { FC, ChangeEventHandler, KeyboardEventHandler, FocusEventHandler } from 'react';
|
||||||
FC,
|
|
||||||
ReactElement,
|
|
||||||
ChangeEvent,
|
|
||||||
ChangeEventHandler,
|
|
||||||
KeyboardEventHandler,
|
|
||||||
} from 'react';
|
|
||||||
import * as styles from './styles.scss';
|
import * as styles from './styles.scss';
|
||||||
import { ITag } from '~/redux/types';
|
import { ITag } from '~/redux/types';
|
||||||
|
|
||||||
|
@ -17,6 +11,7 @@ interface IProps {
|
||||||
is_hoverable?: boolean;
|
is_hoverable?: boolean;
|
||||||
onInput?: ChangeEventHandler<HTMLInputElement>;
|
onInput?: ChangeEventHandler<HTMLInputElement>;
|
||||||
onKeyUp?: KeyboardEventHandler;
|
onKeyUp?: KeyboardEventHandler;
|
||||||
|
onBlur?: FocusEventHandler<HTMLInputElement>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Tag: FC<IProps> = ({
|
const Tag: FC<IProps> = ({
|
||||||
|
@ -26,6 +21,7 @@ const Tag: FC<IProps> = ({
|
||||||
is_hoverable,
|
is_hoverable,
|
||||||
onInput,
|
onInput,
|
||||||
onKeyUp,
|
onKeyUp,
|
||||||
|
onBlur,
|
||||||
}) => (
|
}) => (
|
||||||
<div className={classNames(styles.tag, feature, { is_hoverable, input: !!onInput })}>
|
<div className={classNames(styles.tag, feature, { is_hoverable, input: !!onInput })}>
|
||||||
<div className={styles.hole} />
|
<div className={styles.hole} />
|
||||||
|
@ -40,6 +36,7 @@ const Tag: FC<IProps> = ({
|
||||||
maxLength={24}
|
maxLength={24}
|
||||||
onChange={onInput}
|
onChange={onInput}
|
||||||
onKeyUp={onKeyUp}
|
onKeyUp={onKeyUp}
|
||||||
|
onBlur={onBlur}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,11 +6,20 @@ import React, {
|
||||||
useEffect,
|
useEffect,
|
||||||
KeyboardEvent,
|
KeyboardEvent,
|
||||||
ChangeEvent,
|
ChangeEvent,
|
||||||
|
useRef,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { TagField } from '~/components/containers/TagField';
|
import { TagField } from '~/components/containers/TagField';
|
||||||
import { ITag } from '~/redux/types';
|
import { ITag } from '~/redux/types';
|
||||||
import { Tag } from '~/components/node/Tag';
|
import { Tag } from '~/components/node/Tag';
|
||||||
import uniq from 'ramda/es/uniq';
|
import uniq from 'ramda/es/uniq';
|
||||||
|
import equals from 'ramda/es/equals';
|
||||||
|
import { setTimeout } from 'timers';
|
||||||
|
import identity from 'ramda/es/identity';
|
||||||
|
import countBy from 'ramda/es/countBy';
|
||||||
|
import eqBy from 'ramda/es/eqBy';
|
||||||
|
import length from 'ramda/es/length';
|
||||||
|
import isEmpty from 'ramda/es/isEmpty';
|
||||||
|
import symmetricDifference from 'ramda/es/symmetricDifference';
|
||||||
|
|
||||||
type IProps = HTMLAttributes<HTMLDivElement> & {
|
type IProps = HTMLAttributes<HTMLDivElement> & {
|
||||||
tags: ITag[];
|
tags: ITag[];
|
||||||
|
@ -18,15 +27,17 @@ type IProps = HTMLAttributes<HTMLDivElement> & {
|
||||||
onTagsChange?: (tags: string[]) => void;
|
onTagsChange?: (tags: string[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Tags: FC<IProps> = ({ tags, is_editable, onChange, ...props }) => {
|
export const Tags: FC<IProps> = ({ tags, is_editable, onTagsChange, ...props }) => {
|
||||||
const [input, setInput] = useState('');
|
const [input, setInput] = useState('');
|
||||||
const [data, setData] = useState(tags);
|
const [data, setData] = useState(tags);
|
||||||
|
const timer = useRef(null);
|
||||||
|
|
||||||
const onInput = useCallback(
|
const onInput = useCallback(
|
||||||
({ target: { value } }: ChangeEvent<HTMLInputElement>) => {
|
({ target: { value } }: ChangeEvent<HTMLInputElement>) => {
|
||||||
setInput(value);
|
setInput(value);
|
||||||
|
if (timer) clearTimeout(timer.current);
|
||||||
},
|
},
|
||||||
[setInput]
|
[setInput, timer]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onKeyUp = useCallback(
|
const onKeyUp = useCallback(
|
||||||
|
@ -55,7 +66,23 @@ export const Tags: FC<IProps> = ({ tags, is_editable, onChange, ...props }) => {
|
||||||
[input, setInput, data, setData]
|
[input, setInput, data, setData]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onSubmit = useCallback(() => {
|
||||||
|
if (length(tags) === length(data) && isEmpty(symmetricDifference(tags, data))) return;
|
||||||
|
|
||||||
|
onTagsChange(data.map(tag => tag.title));
|
||||||
|
}, [tags, data, onTagsChange]);
|
||||||
|
|
||||||
|
const onBlur = useCallback(() => {
|
||||||
|
clearTimeout(timer.current);
|
||||||
|
onSubmit();
|
||||||
|
}, [onSubmit, timer]);
|
||||||
|
|
||||||
useEffect(() => setData(tags), [tags]);
|
useEffect(() => setData(tags), [tags]);
|
||||||
|
useEffect(() => {
|
||||||
|
timer.current = setTimeout(onSubmit, 3000);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer.current);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TagField {...props}>
|
<TagField {...props}>
|
||||||
|
@ -63,7 +90,7 @@ export const Tags: FC<IProps> = ({ tags, is_editable, onChange, ...props }) => {
|
||||||
<Tag key={tag.title} title={tag.title} feature={tag.feature} />
|
<Tag key={tag.title} title={tag.title} feature={tag.feature} />
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{is_editable && <Tag title={input} onInput={onInput} onKeyUp={onKeyUp} />}
|
{is_editable && <Tag title={input} onInput={onInput} onKeyUp={onKeyUp} onBlur={onBlur} />}
|
||||||
</TagField>
|
</TagField>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue