refactor: use date obj in all pages (#2523)

This commit is contained in:
Whitewater
2023-05-25 03:22:57 -07:00
committed by himself65
parent 625fcec51c
commit 2a767af71d
10 changed files with 107 additions and 80 deletions
-1
View File
@@ -36,7 +36,6 @@
"@toeverything/hooks": "workspace:*", "@toeverything/hooks": "workspace:*",
"cmdk": "^0.2.0", "cmdk": "^0.2.0",
"css-spring": "^4.1.0", "css-spring": "^4.1.0",
"dayjs": "^1.11.7",
"graphql": "^16.6.0", "graphql": "^16.6.0",
"jotai": "^2.1.0", "jotai": "^2.1.0",
"jotai-devtools": "^0.5.3", "jotai-devtools": "^0.5.3",
@@ -12,7 +12,7 @@ import { useBlockSuiteMetaHelper } from '../../../hooks/affine/use-block-suite-m
import type { BlockSuiteWorkspace } from '../../../shared'; import type { BlockSuiteWorkspace } from '../../../shared';
import { toast } from '../../../utils'; import { toast } from '../../../utils';
import { pageListEmptyStyle } from './index.css'; import { pageListEmptyStyle } from './index.css';
import { formatDate, usePageHelper } from './utils'; import { usePageHelper } from './utils';
export type BlockSuitePageListProps = { export type BlockSuitePageListProps = {
blockSuiteWorkspace: BlockSuiteWorkspace; blockSuiteWorkspace: BlockSuiteWorkspace;
@@ -91,8 +91,10 @@ export const BlockSuitePageList: React.FC<BlockSuitePageListProps> = ({
), ),
pageId: pageMeta.id, pageId: pageMeta.id,
title: pageMeta.title, title: pageMeta.title,
createDate: formatDate(pageMeta.createDate), createDate: new Date(pageMeta.createDate),
updatedDate: formatDate(pageMeta.updatedDate ?? pageMeta.createDate), trashDate: pageMeta.trashDate
? new Date(pageMeta.trashDate)
: undefined,
onClickPage: () => onOpenPage(pageMeta.id), onClickPage: () => onOpenPage(pageMeta.id),
onClickRestore: () => { onClickRestore: () => {
restoreFromTrash(pageMeta.id); restoreFromTrash(pageMeta.id);
@@ -117,8 +119,8 @@ export const BlockSuitePageList: React.FC<BlockSuitePageListProps> = ({
title: pageMeta.title, title: pageMeta.title,
favorite: !!pageMeta.favorite, favorite: !!pageMeta.favorite,
isPublicPage: !!pageMeta.isPublic, isPublicPage: !!pageMeta.isPublic,
createDate: formatDate(pageMeta.createDate), createDate: new Date(pageMeta.createDate),
updatedDate: formatDate(pageMeta.updatedDate ?? pageMeta.createDate), updatedDate: new Date(pageMeta.updatedDate ?? pageMeta.createDate),
onClickPage: () => onOpenPage(pageMeta.id), onClickPage: () => onOpenPage(pageMeta.id),
onOpenPageInNewTab: () => onOpenPage(pageMeta.id, true), onOpenPageInNewTab: () => onOpenPage(pageMeta.id, true),
onClickRestore: () => { onClickRestore: () => {
@@ -1,19 +1,10 @@
import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suite-workspace-helper'; import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suite-workspace-helper';
import dayjs from 'dayjs';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useWorkspacePreferredMode } from '../../../hooks/use-recent-views'; import { useWorkspacePreferredMode } from '../../../hooks/use-recent-views';
import { useRouterHelper } from '../../../hooks/use-router-helper'; import { useRouterHelper } from '../../../hooks/use-router-helper';
import type { BlockSuiteWorkspace } from '../../../shared'; import type { BlockSuiteWorkspace } from '../../../shared';
dayjs.extend(localizedFormat);
export const formatDate = (date?: number | unknown) => {
const dateStr =
typeof date === 'number' ? dayjs(date).format('MM-DD HH:mm') : '--';
return dateStr;
};
export const usePageHelper = (blockSuiteWorkspace: BlockSuiteWorkspace) => { export const usePageHelper = (blockSuiteWorkspace: BlockSuiteWorkspace) => {
const router = useRouter(); const router = useRouter();
const { openPage } = useRouterHelper(router); const { openPage } = useRouterHelper(router);
@@ -16,15 +16,9 @@ import { TitleCell } from './components/title-cell';
import { AllPageListMobileView, TrashListMobileView } from './mobile'; import { AllPageListMobileView, TrashListMobileView } from './mobile';
import { TrashOperationCell } from './operation-cell'; import { TrashOperationCell } from './operation-cell';
import { StyledTableContainer, StyledTableRow } from './styles'; import { StyledTableContainer, StyledTableRow } from './styles';
import type { ListData } from './type'; import type { ListData, PageListProps, TrashListData } from './type';
import { useSorter } from './use-sorter'; import { useSorter } from './use-sorter';
import { formatDate } from './utils';
export type PageListProps = {
isPublicWorkspace?: boolean;
list: ListData[];
onCreateNewPage: () => void;
onCreateNewEdgeless: () => void;
};
const AllPagesHead = ({ const AllPagesHead = ({
isPublicWorkspace, isPublicWorkspace,
@@ -166,19 +160,6 @@ const TrashListHead = () => {
); );
}; };
export type TrashListData = {
pageId: string;
icon: JSX.Element;
title: string;
createDate: string;
updatedDate?: string;
trashDate?: string;
// isPublic: boolean;
onClickPage: () => void;
onRestorePage: () => void;
onPermanentlyDeletePage: () => void;
};
export const PageListTrashView: React.FC<{ export const PageListTrashView: React.FC<{
list: TrashListData[]; list: TrashListData[];
}> = ({ list }) => { }> = ({ list }) => {
@@ -220,10 +201,10 @@ export const PageListTrashView: React.FC<{
onClick={onClickPage} onClick={onClickPage}
/> />
<TableCell ellipsis={true} onClick={onClickPage}> <TableCell ellipsis={true} onClick={onClickPage}>
{createDate} {formatDate(createDate)}
</TableCell> </TableCell>
<TableCell ellipsis={true} onClick={onClickPage}> <TableCell ellipsis={true} onClick={onClickPage}>
{trashDate} {trashDate ? formatDate(trashDate) : '--'}
</TableCell> </TableCell>
<TableCell <TableCell
style={{ padding: 0 }} style={{ padding: 0 }}
@@ -7,6 +7,7 @@ import { TitleCell } from './components/title-cell';
import { OperationCell } from './operation-cell'; import { OperationCell } from './operation-cell';
import { StyledTableRow } from './styles'; import { StyledTableRow } from './styles';
import type { ListData } from './type'; import type { ListData } from './type';
import { formatDate } from './utils';
export const AllPagesBody = ({ export const AllPagesBody = ({
isPublicWorkspace, isPublicWorkspace,
@@ -55,7 +56,7 @@ export const AllPagesBody = ({
hidden={isSmallDevices} hidden={isSmallDevices}
onClick={onClickPage} onClick={onClickPage}
> >
{createDate} {formatDate(createDate)}
</TableCell> </TableCell>
<TableCell <TableCell
data-testid="updated-date" data-testid="updated-date"
@@ -63,7 +64,7 @@ export const AllPagesBody = ({
hidden={isSmallDevices} hidden={isSmallDevices}
onClick={onClickPage} onClick={onClickPage}
> >
{updatedDate ?? createDate} {formatDate(updatedDate ?? createDate)}
</TableCell> </TableCell>
{!isPublicWorkspace && ( {!isPublicWorkspace && (
<TableCell <TableCell
@@ -3,9 +3,8 @@ export type ListData = {
icon: JSX.Element; icon: JSX.Element;
title: string; title: string;
favorite: boolean; favorite: boolean;
createDate: string; createDate: Date;
updatedDate?: string; updatedDate: Date;
trashDate?: string;
isPublicPage: boolean; isPublicPage: boolean;
onClickPage: () => void; onClickPage: () => void;
onOpenPageInNewTab: () => void; onOpenPageInNewTab: () => void;
@@ -13,3 +12,22 @@ export type ListData = {
removeToTrash: () => void; removeToTrash: () => void;
onDisablePublicSharing: () => void; onDisablePublicSharing: () => void;
}; };
export type TrashListData = {
pageId: string;
icon: JSX.Element;
title: string;
createDate: Date;
// TODO remove optional after assert that trashDate is always set
trashDate?: Date;
onClickPage: () => void;
onRestorePage: () => void;
onPermanentlyDeletePage: () => void;
};
export type PageListProps = {
isPublicWorkspace?: boolean;
list: ListData[];
onCreateNewPage: () => void;
onCreateNewEdgeless: () => void;
};
@@ -17,15 +17,27 @@ const defaultSortingFn = <T extends Record<keyof any, unknown>>(
const valA = a[ctx.key]; const valA = a[ctx.key];
const valB = b[ctx.key]; const valB = b[ctx.key];
const revert = ctx.order === 'desc'; const revert = ctx.order === 'desc';
if (typeof valA !== typeof valB) { const revertSymbol = revert ? -1 : 1;
return 0; if (typeof valA === 'string' && typeof valB === 'string') {
return valA.localeCompare(valB) * revertSymbol;
} }
if (typeof valA === 'string') { if (typeof valA === 'number' && typeof valB === 'number') {
return valA.localeCompare(valB as string) * (revert ? -1 : 1); return valA - valB * revertSymbol;
} }
if (typeof valA === 'number') { if (valA instanceof Date && valB instanceof Date) {
return valA - (valB as number) * (revert ? -1 : 1); return (valA.getTime() - valB.getTime()) * revertSymbol;
} }
if (!valA) {
return -1 * revertSymbol;
}
if (!valB) {
return 1 * revertSymbol;
}
console.warn(
'Unsupported sorting type! Please use custom sorting function.',
valA,
valB
);
return 0; return 0;
}; };
@@ -48,6 +60,7 @@ export const useSorter = <T extends Record<keyof any, unknown>>({
key: sorter.key, key: sorter.key,
order: sorter.order, order: sorter.order,
}; };
// TODO supports custom sorting function
const sortingFn = (a: T, b: T) => defaultSortingFn(sortCtx, a, b); const sortingFn = (a: T, b: T) => defaultSortingFn(sortCtx, a, b);
const sortedData = data.sort(sortingFn); const sortedData = data.sort(sortingFn);
@@ -72,7 +85,7 @@ export const useSorter = <T extends Record<keyof any, unknown>>({
order: sorter.order, order: sorter.order,
key: sorter.order !== 'none' ? sorter.key : null, key: sorter.order !== 'none' ? sorter.key : null,
/** /**
* @deprecated In most cases, we no necessary use `setSorter` directly. * @deprecated In most cases, we no necessary use `updateSorter` directly.
*/ */
updateSorter: (newVal: Partial<SorterConfig<T>>) => updateSorter: (newVal: Partial<SorterConfig<T>>) =>
setSorter({ ...sorter, ...newVal }), setSorter({ ...sorter, ...newVal }),
@@ -0,0 +1,23 @@
const isToday = (date: Date) => {
const today = new Date();
return (
date.getDate() == today.getDate() &&
date.getMonth() == today.getMonth() &&
date.getFullYear() == today.getFullYear()
);
};
export const formatDate = (date: Date): string => {
// yyyy-mm-dd MM-DD HH:mm
// const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
if (isToday(date)) {
// HH:mm
return `${hours}:${minutes}`;
}
// MM-DD HH:mm
return `${month}-${day} ${hours}:${minutes}`;
};
@@ -4,10 +4,6 @@ import type { StoryFn } from '@storybook/react';
import { userEvent } from '@storybook/testing-library'; import { userEvent } from '@storybook/testing-library';
import { AffineLoading } from '../components/affine-loading'; import { AffineLoading } from '../components/affine-loading';
import type {
PageListProps,
TrashListData,
} from '../components/page-list/all-page';
import { PageListTrashView } from '../components/page-list/all-page'; import { PageListTrashView } from '../components/page-list/all-page';
import { PageList } from '../components/page-list/all-page'; import { PageList } from '../components/page-list/all-page';
import { NewPageButton } from '../components/page-list/components/new-page-buttton'; import { NewPageButton } from '../components/page-list/components/new-page-buttton';
@@ -59,7 +55,7 @@ AffineNewPageButton.play = async ({ canvasElement }) => {
userEvent.click(dropdown); userEvent.click(dropdown);
}; };
export const AffineAllPageList: StoryFn<PageListProps> = ({ ...props }) => ( export const AffineAllPageList: StoryFn<typeof PageList> = ({ ...props }) => (
<PageList {...props} /> <PageList {...props} />
); );
@@ -68,14 +64,28 @@ AffineAllPageList.args = {
onCreateNewPage: () => toast('Create new page'), onCreateNewPage: () => toast('Create new page'),
onCreateNewEdgeless: () => toast('Create new edgeless'), onCreateNewEdgeless: () => toast('Create new edgeless'),
list: [ list: [
{
pageId: '1',
favorite: false,
icon: <PageIcon />,
isPublicPage: true,
title: 'Today Page',
createDate: new Date(),
updatedDate: new Date(),
bookmarkPage: () => toast('Bookmark page'),
onClickPage: () => toast('Click page'),
onDisablePublicSharing: () => toast('Disable public sharing'),
onOpenPageInNewTab: () => toast('Open page in new tab'),
removeToTrash: () => toast('Remove to trash'),
},
{ {
pageId: '1', pageId: '1',
favorite: false, favorite: false,
icon: <PageIcon />, icon: <PageIcon />,
isPublicPage: true, isPublicPage: true,
title: '1 Example Public Page with long title that will be truncated', title: '1 Example Public Page with long title that will be truncated',
createDate: '2021-01-01', createDate: new Date('2021-01-01'),
updatedDate: '2021-01-02', updatedDate: new Date('2021-01-02'),
bookmarkPage: () => toast('Bookmark page'), bookmarkPage: () => toast('Bookmark page'),
onClickPage: () => toast('Click page'), onClickPage: () => toast('Click page'),
onDisablePublicSharing: () => toast('Disable public sharing'), onDisablePublicSharing: () => toast('Disable public sharing'),
@@ -88,8 +98,8 @@ AffineAllPageList.args = {
isPublicPage: false, isPublicPage: false,
icon: <PageIcon />, icon: <PageIcon />,
title: '2 Favorited Page', title: '2 Favorited Page',
createDate: '2021-01-02', createDate: new Date('2021-01-02'),
updatedDate: '2021-01-01', updatedDate: new Date('2021-01-01'),
bookmarkPage: () => toast('Bookmark page'), bookmarkPage: () => toast('Bookmark page'),
onClickPage: () => toast('Click page'), onClickPage: () => toast('Click page'),
onDisablePublicSharing: () => toast('Disable public sharing'), onDisablePublicSharing: () => toast('Disable public sharing'),
@@ -99,15 +109,15 @@ AffineAllPageList.args = {
], ],
}; };
export const AffinePublicPageList: StoryFn<PageListProps> = ({ ...props }) => ( export const AffinePublicPageList: StoryFn<typeof PageList> = ({
<PageList {...props} /> ...props
); }) => <PageList {...props} />;
AffinePublicPageList.args = { AffinePublicPageList.args = {
...AffineAllPageList.args, ...AffineAllPageList.args,
isPublicWorkspace: true, isPublicWorkspace: true,
}; };
export const AffineAllPageMobileList: StoryFn<PageListProps> = ({ export const AffineAllPageMobileList: StoryFn<typeof PageList> = ({
...props ...props
}) => <PageList {...props} />; }) => <PageList {...props} />;
@@ -118,9 +128,9 @@ AffineAllPageMobileList.parameters = {
}, },
}; };
export const AffineTrashPageList: StoryFn<{ export const AffineTrashPageList: StoryFn<typeof PageListTrashView> = ({
list: TrashListData[]; ...props
}> = ({ ...props }) => <PageListTrashView {...props} />; }) => <PageListTrashView {...props} />;
AffineTrashPageList.args = { AffineTrashPageList.args = {
list: [ list: [
@@ -128,9 +138,8 @@ AffineTrashPageList.args = {
pageId: '1', pageId: '1',
icon: <PageIcon />, icon: <PageIcon />,
title: 'Example Page', title: 'Example Page',
updatedDate: '2021-02-01', createDate: new Date('2021-01-01'),
createDate: '2021-01-01', trashDate: new Date('2021-01-01'),
trashDate: '2021-01-01',
onClickPage: () => toast('Click page'), onClickPage: () => toast('Click page'),
onPermanentlyDeletePage: () => toast('Permanently delete page'), onPermanentlyDeletePage: () => toast('Permanently delete page'),
onRestorePage: () => toast('Restore page'), onRestorePage: () => toast('Restore page'),
@@ -139,9 +148,7 @@ AffineTrashPageList.args = {
pageId: '2', pageId: '2',
icon: <PageIcon />, icon: <PageIcon />,
title: 'Example Page with long title that will be truncated', title: 'Example Page with long title that will be truncated',
updatedDate: '2021-01-01', createDate: new Date('2021-01-01'),
createDate: '2021-01-01',
trashDate: '2021-01-01',
onClickPage: () => toast('Click page'), onClickPage: () => toast('Click page'),
onPermanentlyDeletePage: () => toast('Permanently delete page'), onPermanentlyDeletePage: () => toast('Permanently delete page'),
onRestorePage: () => toast('Restore page'), onRestorePage: () => toast('Restore page'),
-8
View File
@@ -338,7 +338,6 @@ __metadata:
"@vanilla-extract/next-plugin": ^2.1.2 "@vanilla-extract/next-plugin": ^2.1.2
cmdk: ^0.2.0 cmdk: ^0.2.0
css-spring: ^4.1.0 css-spring: ^4.1.0
dayjs: ^1.11.7
dotenv: ^16.0.3 dotenv: ^16.0.3
eslint: ^8.40.0 eslint: ^8.40.0
eslint-config-next: ^13.4.2 eslint-config-next: ^13.4.2
@@ -12785,13 +12784,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"dayjs@npm:^1.11.7":
version: 1.11.7
resolution: "dayjs@npm:1.11.7"
checksum: 5003a7c1dd9ed51385beb658231c3548700b82d3548c0cfbe549d85f2d08e90e972510282b7506941452c58d32136d6362f009c77ca55381a09c704e9f177ebb
languageName: node
linkType: hard
"debounce@npm:^1.2.0": "debounce@npm:^1.2.0":
version: 1.2.1 version: 1.2.1
resolution: "debounce@npm:1.2.1" resolution: "debounce@npm:1.2.1"