feat: add inputs for og metadata

This commit is contained in:
Steven 2023-07-21 21:27:26 +08:00
parent a91997683b
commit 04c0f47559
2 changed files with 129 additions and 31 deletions

View File

@ -29,9 +29,15 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
description: "", description: "",
visibility: "PRIVATE", visibility: "PRIVATE",
tags: [], tags: [],
openGraphMetadata: {
title: "",
description: "",
image: "",
},
}, },
}); });
const [showDescriptionAndTag, setShowDescriptionAndTag] = useState<boolean>(false); const [showDescriptionAndTag, setShowDescriptionAndTag] = useState<boolean>(false);
const [showOpenGraphMetadata, setShowOpenGraphMetadata] = useState<boolean>(false);
const [tag, setTag] = useState<string>(""); const [tag, setTag] = useState<string>("");
const requestState = useLoading(false); const requestState = useLoading(false);
const isCreating = isUndefined(shortcutId); const isCreating = isUndefined(shortcutId);
@ -47,12 +53,10 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
link: shortcut.link, link: shortcut.link,
description: shortcut.description, description: shortcut.description,
visibility: shortcut.visibility, visibility: shortcut.visibility,
openGraphMetadata: shortcut.openGraphMetadata,
}), }),
}); });
setTag(shortcut.tags.join(" ")); setTag(shortcut.tags.join(" "));
if (shortcut.description !== "" || shortcut.tags.length > 0) {
setShowDescriptionAndTag(true);
}
} }
} }
}, [shortcutId]); }, [shortcutId]);
@ -80,6 +84,14 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
}); });
}; };
const handleVisibilityInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setPartialState({
shortcutCreate: Object.assign(state.shortcutCreate, {
visibility: e.target.value,
}),
});
};
const handleDescriptionInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleDescriptionInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setPartialState({ setPartialState({
shortcutCreate: Object.assign(state.shortcutCreate, { shortcutCreate: Object.assign(state.shortcutCreate, {
@ -93,10 +105,35 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
setTag(text); setTag(text);
}; };
const handleVisibilityInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleOpenGraphMetadataImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setPartialState({ setPartialState({
shortcutCreate: Object.assign(state.shortcutCreate, { shortcutCreate: Object.assign(state.shortcutCreate, {
visibility: e.target.value, openGraphMetadata: {
...state.shortcutCreate.openGraphMetadata,
image: e.target.value,
},
}),
});
};
const handleOpenGraphMetadataTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setPartialState({
shortcutCreate: Object.assign(state.shortcutCreate, {
openGraphMetadata: {
...state.shortcutCreate.openGraphMetadata,
title: e.target.value,
},
}),
});
};
const handleOpenGraphMetadataDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setPartialState({
shortcutCreate: Object.assign(state.shortcutCreate, {
openGraphMetadata: {
...state.shortcutCreate.openGraphMetadata,
description: e.target.value,
},
}), }),
}); });
}; };
@ -116,6 +153,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
description: state.shortcutCreate.description, description: state.shortcutCreate.description,
visibility: state.shortcutCreate.visibility, visibility: state.shortcutCreate.visibility,
tags: tag.split(" "), tags: tag.split(" "),
openGraphMetadata: state.shortcutCreate.openGraphMetadata,
}); });
} else { } else {
await shortcutService.createShortcut({ await shortcutService.createShortcut({
@ -144,7 +182,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
<Icon.X className="w-5 h-auto text-gray-600" /> <Icon.X className="w-5 h-auto text-gray-600" />
</Button> </Button>
</div> </div>
<div> <div className="overflow-y-auto">
<div className="w-full flex flex-col justify-start items-start mb-3"> <div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2"> <span className="mb-2">
Name <span className="text-red-600">*</span> Name <span className="text-red-600">*</span>
@ -187,33 +225,84 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
</p> </p>
</div> </div>
<Divider className="text-gray-500">Optional</Divider> <Divider className="text-gray-500">Optional</Divider>
<div <div className="w-full flex flex-col justify-start items-start border rounded-md overflow-hidden my-2">
className="w-full flex flex-row justify-between items-center my-3" <div
onClick={() => setShowDescriptionAndTag(!showDescriptionAndTag)} className={`w-full flex flex-row justify-between items-center px-2 py-1 cursor-pointer hover:bg-gray-100 ${
> showDescriptionAndTag ? "bg-gray-100" : ""
<span className={`${showDescriptionAndTag ? "" : "text-gray-500"}`}>Description and tags</span> }`}
<button className="w-7 h-7 p-1 rounded-md hover:bg-gray-100"> onClick={() => setShowDescriptionAndTag(!showDescriptionAndTag)}
<Icon.ChevronDown className={`w-5 h-auto text-gray-500 ${showDescriptionAndTag ? "transform rotate-180" : ""}`} /> >
</button> <span className="text-sm">Description and tags</span>
<button className="w-7 h-7 p-1 rounded-md">
<Icon.ChevronDown className={`w-4 h-auto text-gray-500 ${showDescriptionAndTag ? "transform rotate-180" : ""}`} />
</button>
</div>
{showDescriptionAndTag && (
<div className="w-full px-2 py-1">
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">Description</span>
<Input
className="w-full"
type="text"
placeholder="Something to describe the url"
value={state.shortcutCreate.description}
onChange={handleDescriptionInputChange}
/>
</div>
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">Tags</span>
<Input className="w-full" type="text" placeholder="Separated by spaces" value={tag} onChange={handleTagsInputChange} />
</div>
</div>
)}
</div> </div>
{showDescriptionAndTag && ( <div className="w-full flex flex-col justify-start items-start border rounded-md overflow-hidden">
<> <div
<div className="w-full flex flex-col justify-start items-start mb-3"> className={`w-full flex flex-row justify-between items-center px-2 py-1 cursor-pointer hover:bg-gray-100 ${
<span className="mb-2">Description</span> showOpenGraphMetadata ? "bg-gray-100" : ""
<Input }`}
className="w-full" onClick={() => setShowOpenGraphMetadata(!showOpenGraphMetadata)}
type="text" >
placeholder="Something to describe the url" <span className="text-sm">Social media metadata</span>
value={state.shortcutCreate.description} <button className="w-7 h-7 p-1 rounded-md">
onChange={handleDescriptionInputChange} <Icon.ChevronDown className={`w-5 h-auto text-gray-500 ${showOpenGraphMetadata ? "transform rotate-180" : ""}`} />
/> </button>
</div>
{showOpenGraphMetadata && (
<div className="w-full px-2 py-1">
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">Image URL</span>
<Input
className="w-full"
type="text"
placeholder="The image url"
value={state.shortcutCreate.openGraphMetadata.image}
onChange={handleOpenGraphMetadataImageChange}
/>
</div>
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">Title</span>
<Input
className="w-full"
type="text"
placeholder="Slash - A bookmarking and url shortener"
value={state.shortcutCreate.openGraphMetadata.title}
onChange={handleOpenGraphMetadataTitleChange}
/>
</div>
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">Description</span>
<Input
className="w-full"
type="text"
placeholder="A bookmarking and url shortener, save and share your links very easily."
value={state.shortcutCreate.openGraphMetadata.description}
onChange={handleOpenGraphMetadataDescriptionChange}
/>
</div>
</div> </div>
<div className="w-full flex flex-col justify-start items-start mb-3"> )}
<span className="mb-2">Tags</span> </div>
<Input className="w-full" type="text" placeholder="Separated by spaces" value={tag} onChange={handleTagsInputChange} />
</div>
</>
)}
<div className="w-full flex flex-row justify-end items-center mt-4 space-x-2"> <div className="w-full flex flex-row justify-end items-center mt-4 space-x-2">
<Button color="neutral" variant="plain" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={onClose}> <Button color="neutral" variant="plain" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={onClose}>

View File

@ -2,6 +2,12 @@ type ShortcutId = number;
type Visibility = "PRIVATE" | "WORKSPACE" | "PUBLIC"; type Visibility = "PRIVATE" | "WORKSPACE" | "PUBLIC";
interface OpenGraphMetadata {
title: string;
description: string;
image: string;
}
interface Shortcut { interface Shortcut {
id: ShortcutId; id: ShortcutId;
@ -16,6 +22,7 @@ interface Shortcut {
description: string; description: string;
visibility: Visibility; visibility: Visibility;
tags: string[]; tags: string[];
openGraphMetadata: OpenGraphMetadata;
view: number; view: number;
} }
@ -25,6 +32,7 @@ interface ShortcutCreate {
description: string; description: string;
visibility: Visibility; visibility: Visibility;
tags: string[]; tags: string[];
openGraphMetadata: OpenGraphMetadata;
} }
interface ShortcutPatch { interface ShortcutPatch {
@ -35,6 +43,7 @@ interface ShortcutPatch {
description?: string; description?: string;
visibility?: Visibility; visibility?: Visibility;
tags?: string[]; tags?: string[];
openGraphMetadata?: OpenGraphMetadata;
} }
interface ShortcutFind { interface ShortcutFind {