mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
fixed tag autocomplete behaviour
This commit is contained in:
parent
9dc83b0db8
commit
85d20e5009
8 changed files with 25 additions and 20 deletions
|
@ -13,10 +13,10 @@ type IProps = IEditorComponentProps & {};
|
|||
|
||||
const EditorUploadCoverButton: FC<IProps> = () => {
|
||||
const { values, setFieldValue } = useNodeFormContext();
|
||||
const { uploadFiles, files, pendingImages } = useUploader(
|
||||
const { uploadFile, files, pendingImages } = useUploader(
|
||||
UploadSubject.Editor,
|
||||
UploadTarget.Nodes,
|
||||
[]
|
||||
values.cover ? [values.cover] : []
|
||||
);
|
||||
|
||||
const background = values.cover ? getURL(values.cover, PRESETS['300']) : null;
|
||||
|
@ -27,14 +27,15 @@ const EditorUploadCoverButton: FC<IProps> = () => {
|
|||
}, [setFieldValue]);
|
||||
|
||||
const onInputChange = useCallback(
|
||||
(event: ChangeEvent<HTMLInputElement>) => {
|
||||
async (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const files = Array.from(event.target.files || [])
|
||||
.filter(file => getFileType(file) === UploadType.Image)
|
||||
.slice(0, 1);
|
||||
|
||||
uploadFiles(files);
|
||||
const result = await uploadFile(files[0]);
|
||||
setFieldValue('cover', result);
|
||||
},
|
||||
[uploadFiles]
|
||||
[uploadFile, setFieldValue]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -11,6 +11,7 @@ interface TagAutocompleteProps {
|
|||
onSelect: (val: string) => void;
|
||||
search: string;
|
||||
options: string[];
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
const TagAutocomplete: VFC<TagAutocompleteProps> = ({
|
||||
|
@ -19,6 +20,7 @@ const TagAutocomplete: VFC<TagAutocompleteProps> = ({
|
|||
onSelect,
|
||||
search,
|
||||
options,
|
||||
visible,
|
||||
}) => {
|
||||
const [selected, setSelected] = useState(-1);
|
||||
const [categories, tags] = useMemo(
|
||||
|
@ -82,7 +84,7 @@ const TagAutocomplete: VFC<TagAutocompleteProps> = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.window)}
|
||||
className={classNames(styles.window, { [styles.visible]: visible })}
|
||||
ref={wrapper}
|
||||
style={pop.styles.popper}
|
||||
{...pop.attributes.popper}
|
||||
|
|
|
@ -18,6 +18,11 @@ $row_height: 24px;
|
|||
z-index: 10;
|
||||
border-radius: 4px;
|
||||
animation: appear 0.25s forwards;
|
||||
visibility: hidden;
|
||||
|
||||
&.visible {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll {
|
||||
|
|
|
@ -132,8 +132,9 @@ const TagInput: FC<IProps> = ({ exclude, onAppend, onClearTag, onSubmit }) => {
|
|||
/>
|
||||
</TagWrapper>
|
||||
|
||||
{focused && input?.length > 0 && ref.current && (
|
||||
{!!ref.current && (
|
||||
<TagAutocomplete
|
||||
visible={focused && input?.length > 0}
|
||||
exclude={exclude}
|
||||
input={ref.current}
|
||||
onSelect={onAutocompleteSelect}
|
||||
|
|
|
@ -4,8 +4,10 @@ import { ITag } from '~/types';
|
|||
import { URLS } from '~/constants/urls';
|
||||
import { useLoadNode } from '~/hooks/node/useLoadNode';
|
||||
import { apiDeleteNodeTag, apiPostNodeTags } from '~/api/node';
|
||||
import { useGetNodeRelated } from '~/hooks/node/useGetNodeRelated';
|
||||
|
||||
export const useNodeTags = (id: number) => {
|
||||
const { refresh: refreshRelated } = useGetNodeRelated(id);
|
||||
const { update } = useLoadNode(id);
|
||||
const history = useHistory();
|
||||
|
||||
|
@ -14,11 +16,12 @@ export const useNodeTags = (id: number) => {
|
|||
try {
|
||||
const result = await apiPostNodeTags({ id, tags });
|
||||
await update({ tags: result.node.tags });
|
||||
await refreshRelated();
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
}
|
||||
},
|
||||
[id, update]
|
||||
[id, update, refreshRelated]
|
||||
);
|
||||
|
||||
const onClick = useCallback(
|
||||
|
@ -37,11 +40,12 @@ export const useNodeTags = (id: number) => {
|
|||
try {
|
||||
const result = await apiDeleteNodeTag({ id, tagId });
|
||||
await update({ tags: result.tags });
|
||||
await refreshRelated();
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
},
|
||||
[id, update]
|
||||
[id, update, refreshRelated]
|
||||
);
|
||||
|
||||
return { onDelete, onChange, onClick };
|
||||
|
|
|
@ -42,7 +42,7 @@ const NodeLayout: FC<IProps> = () => {
|
|||
title={node.title}
|
||||
username={node.user?.username}
|
||||
likeCount={node?.like_count || 0}
|
||||
isHeroic={!!node.is_promoted}
|
||||
isHeroic={!!node.is_heroic}
|
||||
isLiked={!!node.is_liked}
|
||||
isLocked={!!node.deleted_at}
|
||||
isLoading={isLoading}
|
||||
|
|
|
@ -15,5 +15,5 @@ export const canLikeNode = (node?: Partial<INode>, user?: Partial<IUser>): boole
|
|||
|
||||
export const canStarNode = (node?: Partial<INode>, user?: Partial<IUser>): boolean =>
|
||||
path(['type'], node) === NODE_TYPES.IMAGE &&
|
||||
path(['is_promoted'], node) === false &&
|
||||
path(['is_promoted'], node) === true &&
|
||||
path(['role'], user) === Role.Admin;
|
||||
|
|
|
@ -15,15 +15,7 @@ const defaultValue: INodeRelated = {
|
|||
};
|
||||
|
||||
const NodeRelatedProvider: FC<NodeRelatedProviderProps> = ({ id, children, tags }) => {
|
||||
const { related, isLoading, refresh } = useGetNodeRelated(id);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
refresh();
|
||||
},
|
||||
// eslint-disable-next-line
|
||||
[tags]
|
||||
);
|
||||
const { related, isLoading } = useGetNodeRelated(id);
|
||||
|
||||
return (
|
||||
<NodeRelatedContextProvider related={related || defaultValue} isLoading={isLoading}>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue