feat: support set embedded content in UI

This commit is contained in:
Steven
2024-01-26 22:51:57 +08:00
parent e1977df14b
commit bc2d2d0cde
6 changed files with 182 additions and 84 deletions

View File

@ -1,5 +1,4 @@
import { Select, Option, Button, IconButton, Divider } from "@mui/joy";
import { uniqBy } from "lodash-es";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { toast } from "react-hot-toast";
import { useTranslation } from "react-i18next";
@ -15,16 +14,17 @@ import { Resource } from "@/types/proto/api/v2/resource_service";
import { UserSetting } from "@/types/proto/api/v2/user_service";
import { useTranslate } from "@/utils/i18n";
import { convertVisibilityFromString, convertVisibilityToString } from "@/utils/memo";
import showCreateMemoRelationDialog from "../CreateMemoRelationDialog";
import showCreateResourceDialog from "../CreateResourceDialog";
import Icon from "../Icon";
import VisibilityIcon from "../VisibilityIcon";
import AddMemoRelationButton from "./ActionButton/AddMemoRelationButton";
import MarkdownMenu from "./ActionButton/MarkdownMenu";
import TagSelector from "./ActionButton/TagSelector";
import Editor, { EditorRefActions } from "./Editor";
import RelationListView from "./RelationListView";
import ResourceListView from "./ResourceListView";
import { handleEditorKeydownWithMarkdownShortcuts, hyperlinkHighlightedText } from "./handlers";
import { MemoEditorContext } from "./types";
interface Props {
className?: string;
@ -158,23 +158,6 @@ const MemoEditor = (props: Props) => {
});
};
const handleAddMemoRelationBtnClick = () => {
showCreateMemoRelationDialog({
onConfirm: (memoIdList) => {
setState((prevState) => ({
...prevState,
relationList: uniqBy(
[
...memoIdList.map((id) => ({ memoId: memoId || UNKNOWN_ID, relatedMemoId: id, type: MemoRelation_Type.REFERENCE })),
...state.relationList,
].filter((relation) => relation.relatedMemoId !== (memoId || UNKNOWN_ID)),
"relatedMemoId"
),
}));
},
});
};
const handleSetResourceList = (resourceList: Resource[]) => {
setState((prevState) => ({
...prevState,
@ -371,62 +354,73 @@ const MemoEditor = (props: Props) => {
const allowSave = (hasContent || state.resourceList.length > 0) && !state.isUploadingResource && !state.isRequesting;
return (
<div
className={`${
className ?? ""
} relative w-full flex flex-col justify-start items-start bg-white dark:bg-zinc-800 px-4 pt-4 rounded-lg border border-gray-200 dark:border-zinc-700`}
tabIndex={0}
onKeyDown={handleKeyDown}
onDrop={handleDropEvent}
onFocus={handleEditorFocus}
<MemoEditorContext.Provider
value={{
relationList: state.relationList,
setRelationList: (relationList: MemoRelation[]) => {
setState((prevState) => ({
...prevState,
relationList,
}));
},
memoId,
}}
>
<Editor ref={editorRef} {...editorConfig} />
<ResourceListView resourceList={state.resourceList} setResourceList={handleSetResourceList} />
<RelationListView relationList={referenceRelations} setRelationList={handleSetRelationList} />
<div className="relative w-full flex flex-row justify-between items-center pt-2" onFocus={(e) => e.stopPropagation()}>
<div className="flex flex-row justify-start items-center opacity-80">
<TagSelector editorRef={editorRef} />
<MarkdownMenu editorRef={editorRef} />
<IconButton size="sm" onClick={handleUploadFileBtnClick}>
<Icon.Image className="w-5 h-5 mx-auto" />
</IconButton>
<IconButton size="sm" onClick={handleAddMemoRelationBtnClick}>
<Icon.Link className="w-5 h-5 mx-auto" />
</IconButton>
<div
className={`${
className ?? ""
} relative w-full flex flex-col justify-start items-start bg-white dark:bg-zinc-800 px-4 pt-4 rounded-lg border border-gray-200 dark:border-zinc-700`}
tabIndex={0}
onKeyDown={handleKeyDown}
onDrop={handleDropEvent}
onFocus={handleEditorFocus}
>
<Editor ref={editorRef} {...editorConfig} />
<ResourceListView resourceList={state.resourceList} setResourceList={handleSetResourceList} />
<RelationListView relationList={referenceRelations} setRelationList={handleSetRelationList} />
<div className="relative w-full flex flex-row justify-between items-center pt-2" onFocus={(e) => e.stopPropagation()}>
<div className="flex flex-row justify-start items-center opacity-80">
<TagSelector editorRef={editorRef} />
<MarkdownMenu editorRef={editorRef} />
<IconButton size="sm" onClick={handleUploadFileBtnClick}>
<Icon.Image className="w-5 h-5 mx-auto" />
</IconButton>
<AddMemoRelationButton editorRef={editorRef} />
</div>
</div>
<Divider className="!mt-2" />
<div className="w-full flex flex-row justify-between items-center py-3 dark:border-t-zinc-500">
<div className="relative flex flex-row justify-start items-center" onFocus={(e) => e.stopPropagation()}>
<Select
variant="plain"
value={state.memoVisibility}
startDecorator={<VisibilityIcon visibility={state.memoVisibility} />}
onChange={(_, visibility) => {
if (visibility) {
handleMemoVisibilityChange(visibility);
}
}}
>
{[Visibility.PRIVATE, Visibility.PROTECTED, Visibility.PUBLIC].map((item) => (
<Option key={item} value={item} className="whitespace-nowrap">
{t(`memo.visibility.${convertVisibilityToString(item).toLowerCase()}` as any)}
</Option>
))}
</Select>
</div>
<div className="shrink-0 flex flex-row justify-end items-center">
<Button
disabled={!allowSave}
loading={state.isRequesting}
endDecorator={<Icon.Send className="w-4 h-auto" />}
onClick={handleSaveBtnClick}
>
{t("editor.save")}
</Button>
</div>
</div>
</div>
<Divider className="!mt-2" />
<div className="w-full flex flex-row justify-between items-center py-3 dark:border-t-zinc-500">
<div className="relative flex flex-row justify-start items-center" onFocus={(e) => e.stopPropagation()}>
<Select
variant="plain"
value={state.memoVisibility}
startDecorator={<VisibilityIcon visibility={state.memoVisibility} />}
onChange={(_, visibility) => {
if (visibility) {
handleMemoVisibilityChange(visibility);
}
}}
>
{[Visibility.PRIVATE, Visibility.PROTECTED, Visibility.PUBLIC].map((item) => (
<Option key={item} value={item} className="whitespace-nowrap">
{t(`memo.visibility.${convertVisibilityToString(item).toLowerCase()}` as any)}
</Option>
))}
</Select>
</div>
<div className="shrink-0 flex flex-row justify-end items-center">
<Button
disabled={!allowSave}
loading={state.isRequesting}
endDecorator={<Icon.Send className="w-4 h-auto" />}
onClick={handleSaveBtnClick}
>
{t("editor.save")}
</Button>
</div>
</div>
</div>
</MemoEditorContext.Provider>
);
};