1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 04:46:40 +07:00

fixed tag autocomplete behaviour

This commit is contained in:
Fedor Katurov 2022-01-09 19:55:02 +07:00
parent 9dc83b0db8
commit 85d20e5009
8 changed files with 25 additions and 20 deletions

View file

@ -13,10 +13,10 @@ type IProps = IEditorComponentProps & {};
const EditorUploadCoverButton: FC<IProps> = () => { const EditorUploadCoverButton: FC<IProps> = () => {
const { values, setFieldValue } = useNodeFormContext(); const { values, setFieldValue } = useNodeFormContext();
const { uploadFiles, files, pendingImages } = useUploader( const { uploadFile, files, pendingImages } = useUploader(
UploadSubject.Editor, UploadSubject.Editor,
UploadTarget.Nodes, UploadTarget.Nodes,
[] values.cover ? [values.cover] : []
); );
const background = values.cover ? getURL(values.cover, PRESETS['300']) : null; const background = values.cover ? getURL(values.cover, PRESETS['300']) : null;
@ -27,14 +27,15 @@ const EditorUploadCoverButton: FC<IProps> = () => {
}, [setFieldValue]); }, [setFieldValue]);
const onInputChange = useCallback( const onInputChange = useCallback(
(event: ChangeEvent<HTMLInputElement>) => { async (event: ChangeEvent<HTMLInputElement>) => {
const files = Array.from(event.target.files || []) const files = Array.from(event.target.files || [])
.filter(file => getFileType(file) === UploadType.Image) .filter(file => getFileType(file) === UploadType.Image)
.slice(0, 1); .slice(0, 1);
uploadFiles(files); const result = await uploadFile(files[0]);
setFieldValue('cover', result);
}, },
[uploadFiles] [uploadFile, setFieldValue]
); );
useEffect(() => { useEffect(() => {

View file

@ -11,6 +11,7 @@ interface TagAutocompleteProps {
onSelect: (val: string) => void; onSelect: (val: string) => void;
search: string; search: string;
options: string[]; options: string[];
visible: boolean;
} }
const TagAutocomplete: VFC<TagAutocompleteProps> = ({ const TagAutocomplete: VFC<TagAutocompleteProps> = ({
@ -19,6 +20,7 @@ const TagAutocomplete: VFC<TagAutocompleteProps> = ({
onSelect, onSelect,
search, search,
options, options,
visible,
}) => { }) => {
const [selected, setSelected] = useState(-1); const [selected, setSelected] = useState(-1);
const [categories, tags] = useMemo( const [categories, tags] = useMemo(
@ -82,7 +84,7 @@ const TagAutocomplete: VFC<TagAutocompleteProps> = ({
return ( return (
<div <div
className={classNames(styles.window)} className={classNames(styles.window, { [styles.visible]: visible })}
ref={wrapper} ref={wrapper}
style={pop.styles.popper} style={pop.styles.popper}
{...pop.attributes.popper} {...pop.attributes.popper}

View file

@ -18,6 +18,11 @@ $row_height: 24px;
z-index: 10; z-index: 10;
border-radius: 4px; border-radius: 4px;
animation: appear 0.25s forwards; animation: appear 0.25s forwards;
visibility: hidden;
&.visible {
visibility: visible;
}
} }
.scroll { .scroll {

View file

@ -132,8 +132,9 @@ const TagInput: FC<IProps> = ({ exclude, onAppend, onClearTag, onSubmit }) => {
/> />
</TagWrapper> </TagWrapper>
{focused && input?.length > 0 && ref.current && ( {!!ref.current && (
<TagAutocomplete <TagAutocomplete
visible={focused && input?.length > 0}
exclude={exclude} exclude={exclude}
input={ref.current} input={ref.current}
onSelect={onAutocompleteSelect} onSelect={onAutocompleteSelect}

View file

@ -4,8 +4,10 @@ import { ITag } from '~/types';
import { URLS } from '~/constants/urls'; import { URLS } from '~/constants/urls';
import { useLoadNode } from '~/hooks/node/useLoadNode'; import { useLoadNode } from '~/hooks/node/useLoadNode';
import { apiDeleteNodeTag, apiPostNodeTags } from '~/api/node'; import { apiDeleteNodeTag, apiPostNodeTags } from '~/api/node';
import { useGetNodeRelated } from '~/hooks/node/useGetNodeRelated';
export const useNodeTags = (id: number) => { export const useNodeTags = (id: number) => {
const { refresh: refreshRelated } = useGetNodeRelated(id);
const { update } = useLoadNode(id); const { update } = useLoadNode(id);
const history = useHistory(); const history = useHistory();
@ -14,11 +16,12 @@ export const useNodeTags = (id: number) => {
try { try {
const result = await apiPostNodeTags({ id, tags }); const result = await apiPostNodeTags({ id, tags });
await update({ tags: result.node.tags }); await update({ tags: result.node.tags });
await refreshRelated();
} catch (error) { } catch (error) {
console.warn(error); console.warn(error);
} }
}, },
[id, update] [id, update, refreshRelated]
); );
const onClick = useCallback( const onClick = useCallback(
@ -37,11 +40,12 @@ export const useNodeTags = (id: number) => {
try { try {
const result = await apiDeleteNodeTag({ id, tagId }); const result = await apiDeleteNodeTag({ id, tagId });
await update({ tags: result.tags }); await update({ tags: result.tags });
await refreshRelated();
} catch (e) { } catch (e) {
console.warn(e); console.warn(e);
} }
}, },
[id, update] [id, update, refreshRelated]
); );
return { onDelete, onChange, onClick }; return { onDelete, onChange, onClick };

View file

@ -42,7 +42,7 @@ const NodeLayout: FC<IProps> = () => {
title={node.title} title={node.title}
username={node.user?.username} username={node.user?.username}
likeCount={node?.like_count || 0} likeCount={node?.like_count || 0}
isHeroic={!!node.is_promoted} isHeroic={!!node.is_heroic}
isLiked={!!node.is_liked} isLiked={!!node.is_liked}
isLocked={!!node.deleted_at} isLocked={!!node.deleted_at}
isLoading={isLoading} isLoading={isLoading}

View file

@ -15,5 +15,5 @@ export const canLikeNode = (node?: Partial<INode>, user?: Partial<IUser>): boole
export const canStarNode = (node?: Partial<INode>, user?: Partial<IUser>): boolean => export const canStarNode = (node?: Partial<INode>, user?: Partial<IUser>): boolean =>
path(['type'], node) === NODE_TYPES.IMAGE && path(['type'], node) === NODE_TYPES.IMAGE &&
path(['is_promoted'], node) === false && path(['is_promoted'], node) === true &&
path(['role'], user) === Role.Admin; path(['role'], user) === Role.Admin;

View file

@ -15,15 +15,7 @@ const defaultValue: INodeRelated = {
}; };
const NodeRelatedProvider: FC<NodeRelatedProviderProps> = ({ id, children, tags }) => { const NodeRelatedProvider: FC<NodeRelatedProviderProps> = ({ id, children, tags }) => {
const { related, isLoading, refresh } = useGetNodeRelated(id); const { related, isLoading } = useGetNodeRelated(id);
useEffect(
() => {
refresh();
},
// eslint-disable-next-line
[tags]
);
return ( return (
<NodeRelatedContextProvider related={related || defaultValue} isLoading={isLoading}> <NodeRelatedContextProvider related={related || defaultValue} isLoading={isLoading}>