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

This commit is contained in:
Whitewater
2023-05-25 03:22:57 -07:00
committed by GitHub
parent be065e2de3
commit 3b8f2c1ac3
10 changed files with 107 additions and 80 deletions
-1
View File
@@ -36,7 +36,6 @@
"@toeverything/hooks": "workspace:*",
"cmdk": "^0.2.0",
"css-spring": "^4.1.0",
"dayjs": "^1.11.7",
"graphql": "^16.6.0",
"jotai": "^2.1.0",
"jotai-devtools": "^0.5.3",
@@ -12,7 +12,7 @@ import { useBlockSuiteMetaHelper } from '../../../hooks/affine/use-block-suite-m
import type { BlockSuiteWorkspace } from '../../../shared';
import { toast } from '../../../utils';
import { pageListEmptyStyle } from './index.css';
import { formatDate, usePageHelper } from './utils';
import { usePageHelper } from './utils';
export type BlockSuitePageListProps = {
blockSuiteWorkspace: BlockSuiteWorkspace;
@@ -91,8 +91,10 @@ export const BlockSuitePageList: React.FC<BlockSuitePageListProps> = ({
),
pageId: pageMeta.id,
title: pageMeta.title,
createDate: formatDate(pageMeta.createDate),
updatedDate: formatDate(pageMeta.updatedDate ?? pageMeta.createDate),
createDate: new Date(pageMeta.createDate),
trashDate: pageMeta.trashDate
? new Date(pageMeta.trashDate)
: undefined,
onClickPage: () => onOpenPage(pageMeta.id),
onClickRestore: () => {
restoreFromTrash(pageMeta.id);
@@ -117,8 +119,8 @@ export const BlockSuitePageList: React.FC<BlockSuitePageListProps> = ({
title: pageMeta.title,
favorite: !!pageMeta.favorite,
isPublicPage: !!pageMeta.isPublic,
createDate: formatDate(pageMeta.createDate),
updatedDate: formatDate(pageMeta.updatedDate ?? pageMeta.createDate),
createDate: new Date(pageMeta.createDate),
updatedDate: new Date(pageMeta.updatedDate ?? pageMeta.createDate),
onClickPage: () => onOpenPage(pageMeta.id),
onOpenPageInNewTab: () => onOpenPage(pageMeta.id, true),
onClickRestore: () => {
@@ -1,19 +1,10 @@
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 { useWorkspacePreferredMode } from '../../../hooks/use-recent-views';
import { useRouterHelper } from '../../../hooks/use-router-helper';
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) => {
const router = useRouter();
const { openPage } = useRouterHelper(router);
@@ -16,15 +16,9 @@ import { TitleCell } from './components/title-cell';
import { AllPageListMobileView, TrashListMobileView } from './mobile';
import { TrashOperationCell } from './operation-cell';
import { StyledTableContainer, StyledTableRow } from './styles';
import type { ListData } from './type';
import type { ListData, PageListProps, TrashListData } from './type';
import { useSorter } from './use-sorter';
export type PageListProps = {
isPublicWorkspace?: boolean;
list: ListData[];
onCreateNewPage: () => void;
onCreateNewEdgeless: () => void;
};
import { formatDate } from './utils';
const AllPagesHead = ({
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<{
list: TrashListData[];
}> = ({ list }) => {
@@ -220,10 +201,10 @@ export const PageListTrashView: React.FC<{
onClick={onClickPage}
/>
<TableCell ellipsis={true} onClick={onClickPage}>
{createDate}
{formatDate(createDate)}
</TableCell>
<TableCell ellipsis={true} onClick={onClickPage}>
{trashDate}
{trashDate ? formatDate(trashDate) : '--'}
</TableCell>
<TableCell
style={{ padding: 0 }}
@@ -7,6 +7,7 @@ import { TitleCell } from './components/title-cell';
import { OperationCell } from './operation-cell';
import { StyledTableRow } from './styles';
import type { ListData } from './type';
import { formatDate } from './utils';
export const AllPagesBody = ({
isPublicWorkspace,
@@ -55,7 +56,7 @@ export const AllPagesBody = ({
hidden={isSmallDevices}
onClick={onClickPage}
>
{createDate}
{formatDate(createDate)}
</TableCell>
<TableCell
data-testid="updated-date"
@@ -63,7 +64,7 @@ export const AllPagesBody = ({
hidden={isSmallDevices}
onClick={onClickPage}
>
{updatedDate ?? createDate}
{formatDate(updatedDate ?? createDate)}
</TableCell>
{!isPublicWorkspace && (
<TableCell
@@ -3,9 +3,8 @@ export type ListData = {
icon: JSX.Element;
title: string;
favorite: boolean;
createDate: string;
updatedDate?: string;
trashDate?: string;
createDate: Date;
updatedDate: Date;
isPublicPage: boolean;
onClickPage: () => void;
onOpenPageInNewTab: () => void;
@@ -13,3 +12,22 @@ export type ListData = {
removeToTrash: () => 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 valB = b[ctx.key];
const revert = ctx.order === 'desc';
if (typeof valA !== typeof valB) {
return 0;
const revertSymbol = revert ? -1 : 1;
if (typeof valA === 'string' && typeof valB === 'string') {
return valA.localeCompare(valB) * revertSymbol;
}
if (typeof valA === 'string') {
return valA.localeCompare(valB as string) * (revert ? -1 : 1);
if (typeof valA === 'number' && typeof valB === 'number') {
return valA - valB * revertSymbol;
}
if (typeof valA === 'number') {
return valA - (valB as number) * (revert ? -1 : 1);
if (valA instanceof Date && valB instanceof Date) {
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;
};
@@ -48,6 +60,7 @@ export const useSorter = <T extends Record<keyof any, unknown>>({
key: sorter.key,
order: sorter.order,
};
// TODO supports custom sorting function
const sortingFn = (a: T, b: T) => defaultSortingFn(sortCtx, a, b);
const sortedData = data.sort(sortingFn);
@@ -72,7 +85,7 @@ export const useSorter = <T extends Record<keyof any, unknown>>({
order: sorter.order,
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>>) =>
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 { AffineLoading } from '../components/affine-loading';
import type {
PageListProps,
TrashListData,
} from '../components/page-list/all-page';
import { PageListTrashView } from '../components/page-list/all-page';
import { PageList } from '../components/page-list/all-page';
import { NewPageButton } from '../components/page-list/components/new-page-buttton';
@@ -59,7 +55,7 @@ AffineNewPageButton.play = async ({ canvasElement }) => {
userEvent.click(dropdown);
};
export const AffineAllPageList: StoryFn<PageListProps> = ({ ...props }) => (
export const AffineAllPageList: StoryFn<typeof PageList> = ({ ...props }) => (
<PageList {...props} />
);
@@ -68,14 +64,28 @@ AffineAllPageList.args = {
onCreateNewPage: () => toast('Create new page'),
onCreateNewEdgeless: () => toast('Create new edgeless'),
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',
favorite: false,
icon: <PageIcon />,
isPublicPage: true,
title: '1 Example Public Page with long title that will be truncated',
createDate: '2021-01-01',
updatedDate: '2021-01-02',
createDate: new Date('2021-01-01'),
updatedDate: new Date('2021-01-02'),
bookmarkPage: () => toast('Bookmark page'),
onClickPage: () => toast('Click page'),
onDisablePublicSharing: () => toast('Disable public sharing'),
@@ -88,8 +98,8 @@ AffineAllPageList.args = {
isPublicPage: false,
icon: <PageIcon />,
title: '2 Favorited Page',
createDate: '2021-01-02',
updatedDate: '2021-01-01',
createDate: new Date('2021-01-02'),
updatedDate: new Date('2021-01-01'),
bookmarkPage: () => toast('Bookmark page'),
onClickPage: () => toast('Click page'),
onDisablePublicSharing: () => toast('Disable public sharing'),
@@ -99,15 +109,15 @@ AffineAllPageList.args = {
],
};
export const AffinePublicPageList: StoryFn<PageListProps> = ({ ...props }) => (
<PageList {...props} />
);
export const AffinePublicPageList: StoryFn<typeof PageList> = ({
...props
}) => <PageList {...props} />;
AffinePublicPageList.args = {
...AffineAllPageList.args,
isPublicWorkspace: true,
};
export const AffineAllPageMobileList: StoryFn<PageListProps> = ({
export const AffineAllPageMobileList: StoryFn<typeof PageList> = ({
...props
}) => <PageList {...props} />;
@@ -118,9 +128,9 @@ AffineAllPageMobileList.parameters = {
},
};
export const AffineTrashPageList: StoryFn<{
list: TrashListData[];
}> = ({ ...props }) => <PageListTrashView {...props} />;
export const AffineTrashPageList: StoryFn<typeof PageListTrashView> = ({
...props
}) => <PageListTrashView {...props} />;
AffineTrashPageList.args = {
list: [
@@ -128,9 +138,8 @@ AffineTrashPageList.args = {
pageId: '1',
icon: <PageIcon />,
title: 'Example Page',
updatedDate: '2021-02-01',
createDate: '2021-01-01',
trashDate: '2021-01-01',
createDate: new Date('2021-01-01'),
trashDate: new Date('2021-01-01'),
onClickPage: () => toast('Click page'),
onPermanentlyDeletePage: () => toast('Permanently delete page'),
onRestorePage: () => toast('Restore page'),
@@ -139,9 +148,7 @@ AffineTrashPageList.args = {
pageId: '2',
icon: <PageIcon />,
title: 'Example Page with long title that will be truncated',
updatedDate: '2021-01-01',
createDate: '2021-01-01',
trashDate: '2021-01-01',
createDate: new Date('2021-01-01'),
onClickPage: () => toast('Click page'),
onPermanentlyDeletePage: () => toast('Permanently delete page'),
onRestorePage: () => toast('Restore page'),
-8
View File
@@ -338,7 +338,6 @@ __metadata:
"@vanilla-extract/next-plugin": ^2.1.2
cmdk: ^0.2.0
css-spring: ^4.1.0
dayjs: ^1.11.7
dotenv: ^16.0.3
eslint: ^8.40.0
eslint-config-next: ^13.4.2
@@ -12785,13 +12784,6 @@ __metadata:
languageName: node
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":
version: 1.2.1
resolution: "debounce@npm:1.2.1"