From c25c57ab6194c7f70c0efada290247c741aa5b0d Mon Sep 17 00:00:00 2001 From: Steven Date: Sat, 18 May 2024 07:52:35 +0800 Subject: [PATCH] feat: support updating display time --- server/router/api/v1/memo_service.go | 11 +++++ web/src/components/Dialog/BaseDialog.tsx | 6 +-- .../ExploreSidebar/ExploreSidebar.tsx | 2 +- .../components/HomeSidebar/TagsSection.tsx | 6 +-- web/src/components/MemoContent/Code.tsx | 2 +- .../MemoEditor/MemoEditorDialog.tsx | 46 +++++++++++++++---- web/src/components/MemoEditor/index.tsx | 17 ++++--- web/src/pages/Home.tsx | 13 +----- 8 files changed, 65 insertions(+), 38 deletions(-) diff --git a/server/router/api/v1/memo_service.go b/server/router/api/v1/memo_service.go index ac985af9..54e6da10 100644 --- a/server/router/api/v1/memo_service.go +++ b/server/router/api/v1/memo_service.go @@ -277,6 +277,17 @@ func (s *APIV1Service) UpdateMemo(ctx context.Context, request *v1pb.UpdateMemoR } else if path == "created_ts" { createdTs := request.Memo.CreateTime.AsTime().Unix() update.CreatedTs = &createdTs + } else if path == "display_ts" { + displayTs := request.Memo.DisplayTime.AsTime().Unix() + memoRelatedSetting, err := s.Store.GetWorkspaceMemoRelatedSetting(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get workspace memo related setting") + } + if memoRelatedSetting.DisplayWithUpdateTime { + update.UpdatedTs = &displayTs + } else { + update.CreatedTs = &displayTs + } } else if path == "pinned" { if _, err := s.Store.UpsertMemoOrganizer(ctx, &store.MemoOrganizer{ MemoID: id, diff --git a/web/src/components/Dialog/BaseDialog.tsx b/web/src/components/Dialog/BaseDialog.tsx index 156bc807..fea14bd5 100644 --- a/web/src/components/Dialog/BaseDialog.tsx +++ b/web/src/components/Dialog/BaseDialog.tsx @@ -77,10 +77,8 @@ export function generateDialog( const cbs: DialogCallback = { destroy: () => { document.body.style.removeProperty("overflow"); - setTimeout(() => { - dialog.unmount(); - tempDiv.remove(); - }); + dialog.unmount(); + tempDiv.remove(); }, }; diff --git a/web/src/components/ExploreSidebar/ExploreSidebar.tsx b/web/src/components/ExploreSidebar/ExploreSidebar.tsx index 5eeabf23..ae2ef4ad 100644 --- a/web/src/components/ExploreSidebar/ExploreSidebar.tsx +++ b/web/src/components/ExploreSidebar/ExploreSidebar.tsx @@ -15,7 +15,7 @@ const ExploreSidebar = (props: Props) => { )} > - + ); }; diff --git a/web/src/components/HomeSidebar/TagsSection.tsx b/web/src/components/HomeSidebar/TagsSection.tsx index edb2eb6d..01eca763 100644 --- a/web/src/components/HomeSidebar/TagsSection.tsx +++ b/web/src/components/HomeSidebar/TagsSection.tsx @@ -14,7 +14,7 @@ import Icon from "../Icon"; import showRenameTagDialog from "../RenameTagDialog"; interface Props { - hideTips?: boolean; + readonly?: boolean; } const TagsSection = (props: Props) => { @@ -62,7 +62,7 @@ const TagsSection = (props: Props) => {
{t("common.tags")} - {!props.hideTips && ( + {!props.readonly && (
0 ? "hidden" : "")}> { ))}
) : ( - !props.hideTips && ( + !props.readonly && (

{t("tag.create-tags-guide")}

diff --git a/web/src/components/MemoContent/Code.tsx b/web/src/components/MemoContent/Code.tsx index b974d9ed..697b5315 100644 --- a/web/src/components/MemoContent/Code.tsx +++ b/web/src/components/MemoContent/Code.tsx @@ -3,7 +3,7 @@ interface Props { } const Code: React.FC = ({ content }: Props) => { - return {content}; + return {content}; }; export default Code; diff --git a/web/src/components/MemoEditor/MemoEditorDialog.tsx b/web/src/components/MemoEditor/MemoEditorDialog.tsx index f0ae7069..2f14f30c 100644 --- a/web/src/components/MemoEditor/MemoEditorDialog.tsx +++ b/web/src/components/MemoEditor/MemoEditorDialog.tsx @@ -1,6 +1,8 @@ import { IconButton } from "@mui/joy"; -import { useEffect } from "react"; -import { useTagStore } from "@/store/v1"; +import clsx from "clsx"; +import { useEffect, useRef, useState } from "react"; +import { useMemoStore, useTagStore } from "@/store/v1"; +import { Memo } from "@/types/proto/api/v1/memo_service"; import MemoEditor, { Props as MemoEditorProps } from "."; import { generateDialog } from "../Dialog"; import Icon from "../Icon"; @@ -8,7 +10,7 @@ import Icon from "../Icon"; interface Props extends DialogProps, MemoEditorProps {} const MemoEditorDialog: React.FC = ({ - memoName: memo, + memoName, parentMemoName, placeholder, cacheKey, @@ -17,11 +19,21 @@ const MemoEditorDialog: React.FC = ({ destroy, }: Props) => { const tagStore = useTagStore(); + const memoStore = useMemoStore(); + const [displayTime, setDisplayTime] = useState(memoStore.getMemoByName(memoName || "")?.displayTime?.toISOString()); + const memoPatchRef = useRef>({ + displayTime: memoStore.getMemoByName(memoName || "")?.displayTime, + }); useEffect(() => { tagStore.fetchTags(undefined, { skipCache: false }); }, []); + const updateDisplayTime = (displayTime: string) => { + setDisplayTime(displayTime); + memoPatchRef.current.displayTime = new Date(displayTime); + }; + const handleCloseBtnClick = () => { destroy(); }; @@ -35,10 +47,25 @@ const MemoEditorDialog: React.FC = ({ return ( <> -
-
- -

Memos

+
+
+ {displayTime ? ( +
+ {new Date(displayTime).toLocaleString()} + e.target.showPicker()} + onChange={(e) => updateDisplayTime(e.target.value)} + /> +
+ ) : ( + <> + +

Memos

+ + )}
@@ -47,11 +74,12 @@ const MemoEditorDialog: React.FC = ({
diff --git a/web/src/components/MemoEditor/index.tsx b/web/src/components/MemoEditor/index.tsx index 901d6f5e..03c61738 100644 --- a/web/src/components/MemoEditor/index.tsx +++ b/web/src/components/MemoEditor/index.tsx @@ -9,7 +9,7 @@ import { isValidUrl } from "@/helpers/utils"; import useCurrentUser from "@/hooks/useCurrentUser"; import { useMemoStore, useResourceStore, useUserStore, useWorkspaceSettingStore } from "@/store/v1"; import { MemoRelation, MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service"; -import { Visibility } from "@/types/proto/api/v1/memo_service"; +import { Memo, Visibility } from "@/types/proto/api/v1/memo_service"; import { Resource } from "@/types/proto/api/v1/resource_service"; import { UserSetting } from "@/types/proto/api/v1/user_service"; import { WorkspaceMemoRelatedSetting } from "@/types/proto/api/v1/workspace_setting_service"; @@ -36,8 +36,8 @@ export interface Props { parentMemoName?: string; relationList?: MemoRelation[]; autoFocus?: boolean; + memoPatchRef?: React.MutableRefObject>; onConfirm?: (memoName: string) => void; - onEditPrevious?: () => void; } interface State { @@ -159,12 +159,6 @@ const MemoEditor = (props: Props) => { } return; } - - if (!!props.onEditPrevious && event.key === "ArrowDown" && !state.isComposing && editorRef.current.getContent() === "") { - event.preventDefault(); - props.onEditPrevious(); - return; - } }; const handleMemoVisibilityChange = (visibility: Visibility) => { @@ -293,13 +287,18 @@ const MemoEditor = (props: Props) => { if (memoName) { const prevMemo = await memoStore.getOrFetchMemoByName(memoName); if (prevMemo) { + const updateMask = ["content", "visibility"]; + if (props.memoPatchRef?.current?.displayTime) { + updateMask.push("display_ts"); + } const memo = await memoStore.updateMemo( { name: prevMemo.name, content, visibility: state.memoVisibility, + ...props.memoPatchRef?.current, }, - ["content", "visibility"], + updateMask, ); await memoServiceClient.setMemoResources({ name: memo.name, diff --git a/web/src/pages/Home.tsx b/web/src/pages/Home.tsx index e71ade3e..98e07026 100644 --- a/web/src/pages/Home.tsx +++ b/web/src/pages/Home.tsx @@ -1,11 +1,10 @@ import { Button } from "@mui/joy"; import clsx from "clsx"; -import { useCallback, useEffect, useState } from "react"; +import { useEffect, useState } from "react"; import Empty from "@/components/Empty"; import { HomeSidebar, HomeSidebarDrawer } from "@/components/HomeSidebar"; import Icon from "@/components/Icon"; import MemoEditor from "@/components/MemoEditor"; -import showMemoEditorDialog from "@/components/MemoEditor/MemoEditorDialog"; import MemoFilter from "@/components/MemoFilter"; import MemoView from "@/components/MemoView"; import MobileHeader from "@/components/MobileHeader"; @@ -59,14 +58,6 @@ const Home = () => { setNextPageToken(response.nextPageToken); }; - const handleEditPrevious = useCallback(() => { - const lastMemo = memoList.value[memoList.value.length - 1]; - showMemoEditorDialog({ - memoName: lastMemo.name, - cacheKey: `${lastMemo.name}-${lastMemo.displayTime}`, - }); - }, [memoList]); - return (
{!md && ( @@ -76,7 +67,7 @@ const Home = () => { )}
- +
{sortedMemos.map((memo) => (