mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
chore: update archived page
This commit is contained in:
@ -24,17 +24,32 @@ import { useTranslate } from "@/utils/i18n";
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
memo: Memo;
|
memo: Memo;
|
||||||
|
readonly?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
hiddenActions?: ("edit" | "archive" | "delete" | "share" | "pin" | "remove_completed_task_list")[];
|
|
||||||
onEdit?: () => void;
|
onEdit?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkHasCompletedTaskList = (memo: Memo) => {
|
||||||
|
for (const node of memo.nodes) {
|
||||||
|
if (node.type === NodeType.LIST && node.listNode?.children && node.listNode?.children?.length > 0) {
|
||||||
|
for (let j = 0; j < node.listNode.children.length; j++) {
|
||||||
|
if (node.listNode.children[j].type === NodeType.TASK_LIST_ITEM && node.listNode.children[j].taskListItemNode?.complete) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
const MemoActionMenu = (props: Props) => {
|
const MemoActionMenu = (props: Props) => {
|
||||||
const { memo, hiddenActions } = props;
|
const { memo, readonly } = props;
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigateTo = useNavigateTo();
|
const navigateTo = useNavigateTo();
|
||||||
const memoStore = useMemoStore();
|
const memoStore = useMemoStore();
|
||||||
|
const isArchived = memo.rowStatus === RowStatus.ARCHIVED;
|
||||||
|
const hasCompletedTaskList = checkHasCompletedTaskList(memo);
|
||||||
const isInMemoDetailPage = location.pathname.startsWith(`/m/${memo.uid}`);
|
const isInMemoDetailPage = location.pathname.startsWith(`/m/${memo.uid}`);
|
||||||
|
|
||||||
const handleTogglePinMemoBtnClick = async () => {
|
const handleTogglePinMemoBtnClick = async () => {
|
||||||
@ -69,26 +84,17 @@ const MemoActionMenu = (props: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleMemoStatusClick = async () => {
|
const handleToggleMemoStatusClick = async () => {
|
||||||
|
const status = memo.rowStatus === RowStatus.ARCHIVED ? RowStatus.ACTIVE : RowStatus.ARCHIVED;
|
||||||
|
const message = memo.rowStatus === RowStatus.ARCHIVED ? t("message.restored-successfully") : t("message.archived-successfully");
|
||||||
try {
|
try {
|
||||||
if (memo.rowStatus === RowStatus.ARCHIVED) {
|
await memoStore.updateMemo(
|
||||||
await memoStore.updateMemo(
|
{
|
||||||
{
|
name: memo.name,
|
||||||
name: memo.name,
|
rowStatus: status,
|
||||||
rowStatus: RowStatus.ACTIVE,
|
},
|
||||||
},
|
["row_status"],
|
||||||
["row_status"],
|
);
|
||||||
);
|
toast(message);
|
||||||
toast(t("message.restored-successfully"));
|
|
||||||
} else {
|
|
||||||
await memoStore.updateMemo(
|
|
||||||
{
|
|
||||||
name: memo.name,
|
|
||||||
rowStatus: RowStatus.ARCHIVED,
|
|
||||||
},
|
|
||||||
["row_status"],
|
|
||||||
);
|
|
||||||
toast.success(t("message.archived-successfully"));
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.error(error.details);
|
toast.error(error.details);
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -155,38 +161,44 @@ const MemoActionMenu = (props: Props) => {
|
|||||||
</span>
|
</span>
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
<Menu className="text-sm" size="sm" placement="bottom-end">
|
<Menu className="text-sm" size="sm" placement="bottom-end">
|
||||||
{!hiddenActions?.includes("pin") && (
|
{!readonly && !isArchived && (
|
||||||
<MenuItem onClick={handleTogglePinMemoBtnClick}>
|
<>
|
||||||
{memo.pinned ? <BookmarkMinusIcon className="w-4 h-auto" /> : <BookmarkPlusIcon className="w-4 h-auto" />}
|
<MenuItem onClick={handleTogglePinMemoBtnClick}>
|
||||||
{memo.pinned ? t("common.unpin") : t("common.pin")}
|
{memo.pinned ? <BookmarkMinusIcon className="w-4 h-auto" /> : <BookmarkPlusIcon className="w-4 h-auto" />}
|
||||||
</MenuItem>
|
{memo.pinned ? t("common.unpin") : t("common.pin")}
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={handleEditMemoClick}>
|
||||||
|
<Edit3Icon className="w-4 h-auto" />
|
||||||
|
{t("common.edit")}
|
||||||
|
</MenuItem>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
{!hiddenActions?.includes("edit") && props.onEdit && (
|
<MenuItem onClick={handleCopyLink}>
|
||||||
<MenuItem onClick={handleEditMemoClick}>
|
<CopyIcon className="w-4 h-auto" />
|
||||||
<Edit3Icon className="w-4 h-auto" />
|
{t("memo.copy-link")}
|
||||||
{t("common.edit")}
|
|
||||||
</MenuItem>
|
|
||||||
)}
|
|
||||||
{!hiddenActions?.includes("share") && (
|
|
||||||
<MenuItem onClick={handleCopyLink}>
|
|
||||||
<CopyIcon className="w-4 h-auto" />
|
|
||||||
{t("memo.copy-link")}
|
|
||||||
</MenuItem>
|
|
||||||
)}
|
|
||||||
<MenuItem color="warning" onClick={handleToggleMemoStatusClick}>
|
|
||||||
{memo.rowStatus === RowStatus.ARCHIVED ? <ArchiveRestoreIcon className="w-4 h-auto" /> : <ArchiveIcon className="w-4 h-auto" />}
|
|
||||||
{memo.rowStatus === RowStatus.ARCHIVED ? t("common.restore") : t("common.archive")}
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{!hiddenActions?.includes("remove_completed_task_list") && (
|
{!readonly && (
|
||||||
<MenuItem color="danger" onClick={handleRemoveCompletedTaskListItemsClick}>
|
<>
|
||||||
<SquareCheckIcon className="w-4 h-auto" />
|
{!isArchived && hasCompletedTaskList && (
|
||||||
{t("memo.remove-completed-task-list-items")}
|
<MenuItem color="danger" onClick={handleRemoveCompletedTaskListItemsClick}>
|
||||||
</MenuItem>
|
<SquareCheckIcon className="w-4 h-auto" />
|
||||||
|
{t("memo.remove-completed-task-list-items")}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
<MenuItem color="warning" onClick={handleToggleMemoStatusClick}>
|
||||||
|
{memo.rowStatus === RowStatus.ARCHIVED ? (
|
||||||
|
<ArchiveRestoreIcon className="w-4 h-auto" />
|
||||||
|
) : (
|
||||||
|
<ArchiveIcon className="w-4 h-auto" />
|
||||||
|
)}
|
||||||
|
{memo.rowStatus === RowStatus.ARCHIVED ? t("common.restore") : t("common.archive")}
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem color="danger" onClick={handleDeleteMemoClick}>
|
||||||
|
<TrashIcon className="w-4 h-auto" />
|
||||||
|
{t("common.delete")}
|
||||||
|
</MenuItem>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
<MenuItem color="danger" onClick={handleDeleteMemoClick}>
|
|
||||||
<TrashIcon className="w-4 h-auto" />
|
|
||||||
{t("common.delete")}
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
</Menu>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
|
@ -2,6 +2,7 @@ import { uniq } from "lodash-es";
|
|||||||
import { memo, useEffect, useState } from "react";
|
import { memo, useEffect, useState } from "react";
|
||||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||||
import { useUserStore } from "@/store/v1";
|
import { useUserStore } from "@/store/v1";
|
||||||
|
import { RowStatus } from "@/types/proto/api/v1/common";
|
||||||
import { Memo } from "@/types/proto/api/v1/memo_service";
|
import { Memo } from "@/types/proto/api/v1/memo_service";
|
||||||
import { Reaction } from "@/types/proto/api/v1/reaction_service";
|
import { Reaction } from "@/types/proto/api/v1/reaction_service";
|
||||||
import { User } from "@/types/proto/api/v1/user_service";
|
import { User } from "@/types/proto/api/v1/user_service";
|
||||||
@ -18,6 +19,7 @@ const MemoReactionListView = (props: Props) => {
|
|||||||
const currentUser = useCurrentUser();
|
const currentUser = useCurrentUser();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const [reactionGroup, setReactionGroup] = useState<Map<string, User[]>>(new Map());
|
const [reactionGroup, setReactionGroup] = useState<Map<string, User[]>>(new Map());
|
||||||
|
const readonly = memo.rowStatus === RowStatus.ARCHIVED;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
@ -38,7 +40,7 @@ const MemoReactionListView = (props: Props) => {
|
|||||||
{Array.from(reactionGroup).map(([reactionType, users]) => {
|
{Array.from(reactionGroup).map(([reactionType, users]) => {
|
||||||
return <ReactionView key={`${reactionType.toString()} ${users.length}`} memo={memo} reactionType={reactionType} users={users} />;
|
return <ReactionView key={`${reactionType.toString()} ${users.length}`} memo={memo} reactionType={reactionType} users={users} />;
|
||||||
})}
|
})}
|
||||||
{currentUser && <ReactionSelector memo={memo} />}
|
{!readonly && currentUser && <ReactionSelector memo={memo} />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -7,7 +7,7 @@ import useAsyncEffect from "@/hooks/useAsyncEffect";
|
|||||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||||
import useNavigateTo from "@/hooks/useNavigateTo";
|
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||||
import { useUserStore, useWorkspaceSettingStore, useMemoStore } from "@/store/v1";
|
import { useUserStore, useWorkspaceSettingStore, useMemoStore } from "@/store/v1";
|
||||||
import { NodeType } from "@/types/proto/api/v1/markdown_service";
|
import { RowStatus } from "@/types/proto/api/v1/common";
|
||||||
import { MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service";
|
import { MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service";
|
||||||
import { Memo, Visibility } from "@/types/proto/api/v1/memo_service";
|
import { Memo, Visibility } from "@/types/proto/api/v1/memo_service";
|
||||||
import { WorkspaceMemoRelatedSetting } from "@/types/proto/api/v1/workspace_setting_service";
|
import { WorkspaceMemoRelatedSetting } from "@/types/proto/api/v1/workspace_setting_service";
|
||||||
@ -29,7 +29,6 @@ import VisibilityIcon from "./VisibilityIcon";
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
memo: Memo;
|
memo: Memo;
|
||||||
displayTimeFormat?: "auto" | "time";
|
|
||||||
compact?: boolean;
|
compact?: boolean;
|
||||||
showCreator?: boolean;
|
showCreator?: boolean;
|
||||||
showVisibility?: boolean;
|
showVisibility?: boolean;
|
||||||
@ -59,6 +58,7 @@ const MemoView: React.FC<Props> = (props: Props) => {
|
|||||||
(relation) => relation.type === MemoRelation_Type.COMMENT && relation.relatedMemo?.name === memo.name,
|
(relation) => relation.type === MemoRelation_Type.COMMENT && relation.relatedMemo?.name === memo.name,
|
||||||
).length;
|
).length;
|
||||||
const relativeTimeFormat = Date.now() - memo.displayTime!.getTime() > 1000 * 60 * 60 * 24 ? "datetime" : "auto";
|
const relativeTimeFormat = Date.now() - memo.displayTime!.getTime() > 1000 * 60 * 60 * 24 ? "datetime" : "auto";
|
||||||
|
const isArchived = memo.rowStatus === RowStatus.ARCHIVED;
|
||||||
const readonly = memo.creator !== user?.name && !isSuperUser(user);
|
const readonly = memo.creator !== user?.name && !isSuperUser(user);
|
||||||
const isInMemoDetailPage = location.pathname.startsWith(`/m/${memo.uid}`);
|
const isInMemoDetailPage = location.pathname.startsWith(`/m/${memo.uid}`);
|
||||||
const parentPage = props.parentPage || location.pathname;
|
const parentPage = props.parentPage || location.pathname;
|
||||||
@ -115,42 +115,11 @@ const MemoView: React.FC<Props> = (props: Props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const displayTime =
|
const displayTime = isArchived ? (
|
||||||
props.displayTimeFormat === "time" ? (
|
memo.displayTime?.toLocaleString()
|
||||||
memo.displayTime?.toLocaleTimeString()
|
) : (
|
||||||
) : (
|
<relative-time datetime={memo.displayTime?.toISOString()} format={relativeTimeFormat}></relative-time>
|
||||||
<relative-time datetime={memo.displayTime?.toISOString()} format={relativeTimeFormat}></relative-time>
|
);
|
||||||
);
|
|
||||||
|
|
||||||
const handleHiddenActions = () => {
|
|
||||||
const hiddenActions: ("edit" | "archive" | "delete" | "share" | "pin" | "remove_completed_task_list")[] = [];
|
|
||||||
if (!props.showPinned) {
|
|
||||||
hiddenActions.push("pin");
|
|
||||||
}
|
|
||||||
// check if the content has done tasks
|
|
||||||
let hasCompletedTaskList = false;
|
|
||||||
const newNodes = JSON.parse(JSON.stringify(memo.nodes));
|
|
||||||
for (let i = 0; i < newNodes.length; i++) {
|
|
||||||
if (hasCompletedTaskList) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (newNodes[i].type === NodeType.LIST && newNodes[i].listNode?.children?.length > 0) {
|
|
||||||
for (let j = 0; j < newNodes[i].listNode.children.length; j++) {
|
|
||||||
if (
|
|
||||||
newNodes[i].listNode.children[j].type === NodeType.TASK_LIST_ITEM &&
|
|
||||||
newNodes[i].listNode.children[j].taskListItemNode?.complete
|
|
||||||
) {
|
|
||||||
hasCompletedTaskList = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasCompletedTaskList) {
|
|
||||||
hiddenActions.push("remove_completed_task_list");
|
|
||||||
}
|
|
||||||
return hiddenActions;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -213,7 +182,7 @@ const MemoView: React.FC<Props> = (props: Props) => {
|
|||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
{currentUser && <ReactionSelector className="border-none w-auto h-auto" memo={memo} />}
|
{currentUser && !isArchived && <ReactionSelector className="border-none w-auto h-auto" memo={memo} />}
|
||||||
</div>
|
</div>
|
||||||
{!isInMemoDetailPage && (workspaceMemoRelatedSetting.enableComment || commentAmount > 0) && (
|
{!isInMemoDetailPage && (workspaceMemoRelatedSetting.enableComment || commentAmount > 0) && (
|
||||||
<Link
|
<Link
|
||||||
@ -238,9 +207,7 @@ const MemoView: React.FC<Props> = (props: Props) => {
|
|||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
{!readonly && (
|
<MemoActionMenu className="-ml-1" memo={memo} readonly={readonly} onEdit={() => setShowEditor(true)} />
|
||||||
<MemoActionMenu className="-ml-1" memo={memo} hiddenActions={handleHiddenActions()} onEdit={() => setShowEditor(true)} />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MemoContent
|
<MemoContent
|
||||||
|
@ -3,6 +3,7 @@ import clsx from "clsx";
|
|||||||
import { memoServiceClient } from "@/grpcweb";
|
import { memoServiceClient } from "@/grpcweb";
|
||||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||||
import { useMemoStore } from "@/store/v1";
|
import { useMemoStore } from "@/store/v1";
|
||||||
|
import { RowStatus } from "@/types/proto/api/v1/common";
|
||||||
import { Memo } from "@/types/proto/api/v1/memo_service";
|
import { Memo } from "@/types/proto/api/v1/memo_service";
|
||||||
import { User } from "@/types/proto/api/v1/user_service";
|
import { User } from "@/types/proto/api/v1/user_service";
|
||||||
|
|
||||||
@ -32,9 +33,10 @@ const ReactionView = (props: Props) => {
|
|||||||
const currentUser = useCurrentUser();
|
const currentUser = useCurrentUser();
|
||||||
const memoStore = useMemoStore();
|
const memoStore = useMemoStore();
|
||||||
const hasReaction = users.some((user) => currentUser && user.username === currentUser.username);
|
const hasReaction = users.some((user) => currentUser && user.username === currentUser.username);
|
||||||
|
const readonly = memo.rowStatus === RowStatus.ARCHIVED;
|
||||||
|
|
||||||
const handleReactionClick = async () => {
|
const handleReactionClick = async () => {
|
||||||
if (!currentUser) {
|
if (!currentUser || readonly) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ const ReactionView = (props: Props) => {
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
"h-7 border px-2 py-0.5 rounded-full flex flex-row justify-center items-center gap-1 dark:border-zinc-700",
|
"h-7 border px-2 py-0.5 rounded-full flex flex-row justify-center items-center gap-1 dark:border-zinc-700",
|
||||||
"text-sm text-gray-600 dark:text-gray-400",
|
"text-sm text-gray-600 dark:text-gray-400",
|
||||||
currentUser && "cursor-pointer",
|
currentUser && !readonly && "cursor-pointer",
|
||||||
hasReaction && "bg-blue-100 border-blue-200 dark:bg-zinc-900",
|
hasReaction && "bg-blue-100 border-blue-200 dark:bg-zinc-900",
|
||||||
)}
|
)}
|
||||||
onClick={handleReactionClick}
|
onClick={handleReactionClick}
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
import { Tooltip } from "@mui/joy";
|
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { ArchiveIcon, ArchiveRestoreIcon, TrashIcon } from "lucide-react";
|
import { ArchiveIcon } from "lucide-react";
|
||||||
import { ClientError } from "nice-grpc-web";
|
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import toast from "react-hot-toast";
|
|
||||||
import MemoContent from "@/components/MemoContent";
|
|
||||||
import MemoFilters from "@/components/MemoFilters";
|
import MemoFilters from "@/components/MemoFilters";
|
||||||
|
import MemoView from "@/components/MemoView";
|
||||||
import MobileHeader from "@/components/MobileHeader";
|
import MobileHeader from "@/components/MobileHeader";
|
||||||
import PagedMemoList from "@/components/PagedMemoList";
|
import PagedMemoList from "@/components/PagedMemoList";
|
||||||
import SearchBar from "@/components/SearchBar";
|
import SearchBar from "@/components/SearchBar";
|
||||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||||
import { useMemoFilterStore, useMemoStore } from "@/store/v1";
|
import { useMemoFilterStore } from "@/store/v1";
|
||||||
import { RowStatus } from "@/types/proto/api/v1/common";
|
import { RowStatus } from "@/types/proto/api/v1/common";
|
||||||
import { Memo } from "@/types/proto/api/v1/memo_service";
|
import { Memo } from "@/types/proto/api/v1/memo_service";
|
||||||
import { useTranslate } from "@/utils/i18n";
|
import { useTranslate } from "@/utils/i18n";
|
||||||
@ -18,7 +15,6 @@ import { useTranslate } from "@/utils/i18n";
|
|||||||
const Archived = () => {
|
const Archived = () => {
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
const user = useCurrentUser();
|
const user = useCurrentUser();
|
||||||
const memoStore = useMemoStore();
|
|
||||||
const memoFilterStore = useMemoFilterStore();
|
const memoFilterStore = useMemoFilterStore();
|
||||||
|
|
||||||
const memoListFilter = useMemo(() => {
|
const memoListFilter = useMemo(() => {
|
||||||
@ -44,29 +40,6 @@ const Archived = () => {
|
|||||||
return filters.join(" && ");
|
return filters.join(" && ");
|
||||||
}, [user, memoFilterStore.filters]);
|
}, [user, memoFilterStore.filters]);
|
||||||
|
|
||||||
const handleDeleteMemoClick = async (memo: Memo) => {
|
|
||||||
const confirmed = window.confirm(t("memo.delete-confirm"));
|
|
||||||
if (confirmed) {
|
|
||||||
await memoStore.deleteMemo(memo.name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleRestoreMemoClick = async (memo: Memo) => {
|
|
||||||
try {
|
|
||||||
await memoStore.updateMemo(
|
|
||||||
{
|
|
||||||
name: memo.name,
|
|
||||||
rowStatus: RowStatus.ACTIVE,
|
|
||||||
},
|
|
||||||
["row_status"],
|
|
||||||
);
|
|
||||||
toast(t("message.restored-successfully"));
|
|
||||||
} catch (error: unknown) {
|
|
||||||
console.error(error);
|
|
||||||
toast.error((error as ClientError).details);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8">
|
<section className="@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8">
|
||||||
<MobileHeader />
|
<MobileHeader />
|
||||||
@ -83,33 +56,7 @@ const Archived = () => {
|
|||||||
</div>
|
</div>
|
||||||
<MemoFilters />
|
<MemoFilters />
|
||||||
<PagedMemoList
|
<PagedMemoList
|
||||||
renderer={(memo: Memo) => (
|
renderer={(memo: Memo) => <MemoView key={`${memo.name}-${memo.updateTime}`} memo={memo} showVisibility compact />}
|
||||||
<div
|
|
||||||
key={memo.name}
|
|
||||||
className="relative flex flex-col justify-start items-start w-full p-4 pt-3 mb-2 bg-white dark:bg-zinc-800 rounded-lg"
|
|
||||||
>
|
|
||||||
<div className="w-full mb-1 flex flex-row justify-between items-center">
|
|
||||||
<div className="w-full max-w-[calc(100%-20px)] flex flex-row justify-start items-center mr-1">
|
|
||||||
<div className="text-sm leading-6 text-gray-400 select-none">
|
|
||||||
<relative-time datetime={memo.displayTime?.toISOString()}></relative-time>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-row justify-end items-center gap-x-2">
|
|
||||||
<Tooltip title={t("common.restore")} placement="top">
|
|
||||||
<button onClick={() => handleRestoreMemoClick(memo)}>
|
|
||||||
<ArchiveRestoreIcon className="w-4 h-auto cursor-pointer text-gray-500 dark:text-gray-400" />
|
|
||||||
</button>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip title={t("common.delete")} placement="top">
|
|
||||||
<button onClick={() => handleDeleteMemoClick(memo)} className="text-gray-500 dark:text-gray-400">
|
|
||||||
<TrashIcon className="w-4 h-auto cursor-pointer" />
|
|
||||||
</button>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<MemoContent key={`${memo.name}-${memo.displayTime}`} memoName={memo.name} nodes={memo.nodes} readonly={true} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
listSort={(memos: Memo[]) =>
|
listSort={(memos: Memo[]) =>
|
||||||
memos
|
memos
|
||||||
.filter((memo) => memo.rowStatus === RowStatus.ARCHIVED)
|
.filter((memo) => memo.rowStatus === RowStatus.ARCHIVED)
|
||||||
|
Reference in New Issue
Block a user