feat: add page stats to page menu (#876)

This commit is contained in:
Philip Okugbe
2025-03-13 14:54:18 +00:00
committed by GitHub
parent f7a14e23cd
commit f45d9dc5a0
8 changed files with 111 additions and 7 deletions

View File

@ -71,6 +71,7 @@ import MentionView from "@/features/editor/components/mention/mention-view.tsx";
import i18n from "@/i18n.ts";
import { MarkdownClipboard } from "@/features/editor/extensions/markdown-clipboard.ts";
import EmojiCommand from "./emoji-command";
import { CharacterCount } from "@tiptap/extension-character-count";
const lowlight = createLowlight(common);
lowlight.register("mermaid", plaintext);
@ -211,6 +212,7 @@ export const mainExtensions = [
MarkdownClipboard.configure({
transformPastedText: true,
}),
CharacterCount
] as any;
type CollabExtensions = (provider: HocuspocusProvider, user: IUser) => any[];

View File

@ -1,4 +1,4 @@
import { ActionIcon, Group, Menu, Tooltip } from "@mantine/core";
import { ActionIcon, Group, Menu, Text, Tooltip } from "@mantine/core";
import {
IconArrowsHorizontal,
IconDots,
@ -24,9 +24,13 @@ import { extractPageSlugId } from "@/lib";
import { treeApiAtom } from "@/features/page/tree/atoms/tree-api-atom.ts";
import { useDeletePageModal } from "@/features/page/hooks/use-delete-page-modal.tsx";
import { PageWidthToggle } from "@/features/user/components/page-width-pref.tsx";
import { useTranslation } from "react-i18next";
import { Trans, useTranslation } from "react-i18next";
import ExportModal from "@/components/common/export-modal";
import { yjsConnectionStatusAtom } from "@/features/editor/atoms/editor-atoms.ts";
import {
pageEditorAtom,
yjsConnectionStatusAtom,
} from "@/features/editor/atoms/editor-atoms.ts";
import { formattedDate, timeAgo } from "@/lib/time.ts";
interface PageHeaderMenuProps {
readOnly?: boolean;
@ -79,6 +83,7 @@ function PageActionMenu({ readOnly }: PageActionMenuProps) {
const [tree] = useAtom(treeApiAtom);
const [exportOpened, { open: openExportModal, close: closeExportModal }] =
useDisclosure(false);
const [pageEditor] = useAtom(pageEditorAtom);
const handleCopyLink = () => {
const pageUrl =
@ -108,7 +113,7 @@ function PageActionMenu({ readOnly }: PageActionMenuProps) {
shadow="xl"
position="bottom-end"
offset={20}
width={200}
width={230}
withArrow
arrowPosition="center"
>
@ -168,6 +173,41 @@ function PageActionMenu({ readOnly }: PageActionMenuProps) {
</Menu.Item>
</>
)}
<Menu.Divider />
<>
<Group px="sm" wrap="nowrap" style={{ cursor: "pointer" }}>
<Tooltip
label={t("Edited by {{name}} {{time}}", {
name: page.lastUpdatedBy.name,
time: timeAgo(page.updatedAt),
})}
position="left-start"
>
<div>
<Text size="xs" c="dimmed" truncate="end">
{t("Word count: {{wordCount}}", {
wordCount: pageEditor?.storage?.characterCount?.words(),
})}
</Text>
<Text size="xs" c="dimmed" lineClamp={1}>
<Trans
defaults="Created by: <b>{{creatorName}}</b>"
values={{ creatorName: page?.creator?.name }}
components={{ b: <Text span fw={500} /> }}
/>
</Text>
<Text size="xs" c="dimmed" truncate="end">
{t("Created at: {{time}}", {
time: formattedDate(page.createdAt),
})}
</Text>
</div>
</Tooltip>
</Group>
</>
</Menu.Dropdown>
</Menu>

View File

@ -12,16 +12,28 @@ export interface IPage {
spaceId: string;
workspaceId: string;
isLocked: boolean;
isPublic: boolean;
lastModifiedById: Date;
lastUpdatedById: Date;
createdAt: Date;
updatedAt: Date;
deletedAt: Date;
position: string;
hasChildren: boolean;
creator: ICreator;
lastUpdatedBy: ILastUpdatedBy;
space: Partial<ISpace>;
}
interface ICreator {
id: string;
name: string;
avatarUrl: string;
}
interface ILastUpdatedBy {
id: string;
name: string;
avatarUrl: string;
}
export interface IMovePage {
pageId: string;
position?: string;