mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-18 14:56:59 +08:00
feat(core): adjust the display settings to be independent for each workspace (#6502)
close TOV-793
This commit is contained in:
@@ -7,12 +7,10 @@ import {
|
||||
} from '@affine/component';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { ArrowDownSmallIcon, DoneIcon } from '@blocksuite/icons';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { pageGroupByTypeAtom } from '../group-definitions';
|
||||
import type { PageDisplayProperties, PageGroupByType } from '../types';
|
||||
import { usePageDisplayProperties } from '../use-page-display-properties';
|
||||
import { useAllDocDisplayProperties } from '../use-all-doc-display-properties';
|
||||
import * as styles from './page-display-menu.css';
|
||||
|
||||
type GroupOption = {
|
||||
@@ -22,13 +20,21 @@ type GroupOption = {
|
||||
|
||||
export const PageDisplayMenu = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const [group, setGroup] = useAtom(pageGroupByTypeAtom);
|
||||
const [properties, setProperties] = usePageDisplayProperties();
|
||||
const [workspaceProperties, setProperties] = useAllDocDisplayProperties();
|
||||
const handleSelect = useCallback(
|
||||
(value: PageGroupByType) => {
|
||||
setGroup(value);
|
||||
setProperties('groupBy', value);
|
||||
},
|
||||
[setGroup]
|
||||
[setProperties]
|
||||
);
|
||||
const handleSetDocDisplayProperties = useCallback(
|
||||
(key: keyof PageDisplayProperties) => {
|
||||
setProperties('displayProperties', {
|
||||
...workspaceProperties.displayProperties,
|
||||
[key]: !workspaceProperties.displayProperties[key],
|
||||
});
|
||||
},
|
||||
[setProperties, workspaceProperties.displayProperties]
|
||||
);
|
||||
const propertyOptions: Array<{
|
||||
key: keyof PageDisplayProperties;
|
||||
@@ -38,26 +44,26 @@ export const PageDisplayMenu = () => {
|
||||
return [
|
||||
{
|
||||
key: 'bodyNotes',
|
||||
onClick: () => setProperties('bodyNotes', !properties['bodyNotes']),
|
||||
onClick: () => handleSetDocDisplayProperties('bodyNotes'),
|
||||
label: t['com.affine.page.display.display-properties.body-notes'](),
|
||||
},
|
||||
{
|
||||
key: 'tags',
|
||||
onClick: () => setProperties('tags', !properties['tags']),
|
||||
onClick: () => handleSetDocDisplayProperties('tags'),
|
||||
label: t['Tags'](),
|
||||
},
|
||||
{
|
||||
key: 'createDate',
|
||||
onClick: () => setProperties('createDate', !properties['createDate']),
|
||||
onClick: () => handleSetDocDisplayProperties('createDate'),
|
||||
label: t['Created'](),
|
||||
},
|
||||
{
|
||||
key: 'updatedDate',
|
||||
onClick: () => setProperties('updatedDate', !properties['updatedDate']),
|
||||
onClick: () => handleSetDocDisplayProperties('updatedDate'),
|
||||
label: t['Updated'](),
|
||||
},
|
||||
];
|
||||
}, [properties, setProperties, t]);
|
||||
}, [handleSetDocDisplayProperties, t]);
|
||||
|
||||
const items = useMemo(() => {
|
||||
const groupOptions: GroupOption[] = [
|
||||
@@ -87,8 +93,12 @@ export const PageDisplayMenu = () => {
|
||||
<MenuItem
|
||||
key={option.value}
|
||||
onSelect={() => handleSelect(option.value)}
|
||||
data-active={group === option.value}
|
||||
endFix={group === option.value ? <DoneIcon fontSize={'20px'} /> : null}
|
||||
data-active={workspaceProperties.groupBy === option.value}
|
||||
endFix={
|
||||
workspaceProperties.groupBy === option.value ? (
|
||||
<DoneIcon fontSize={'20px'} />
|
||||
) : null
|
||||
}
|
||||
className={styles.subMenuItem}
|
||||
data-testid={`group-by-${option.value}`}
|
||||
>
|
||||
@@ -97,7 +107,7 @@ export const PageDisplayMenu = () => {
|
||||
));
|
||||
|
||||
const currentGroupType = groupOptions.find(
|
||||
option => option.value === group
|
||||
option => option.value === workspaceProperties.groupBy
|
||||
)?.label;
|
||||
|
||||
return (
|
||||
@@ -131,7 +141,7 @@ export const PageDisplayMenu = () => {
|
||||
key={option.label}
|
||||
className={styles.propertyButton}
|
||||
onClick={option.onClick}
|
||||
data-active={properties[option.key]}
|
||||
data-active={!!workspaceProperties.displayProperties[option.key]}
|
||||
data-testid={`property-${option.key}`}
|
||||
>
|
||||
{option.label}
|
||||
@@ -140,7 +150,13 @@ export const PageDisplayMenu = () => {
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}, [group, handleSelect, properties, propertyOptions, t]);
|
||||
}, [
|
||||
handleSelect,
|
||||
propertyOptions,
|
||||
t,
|
||||
workspaceProperties.displayProperties,
|
||||
workspaceProperties.groupBy,
|
||||
]);
|
||||
return (
|
||||
<Menu
|
||||
items={items}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useCallback, useMemo } from 'react';
|
||||
import { WorkbenchLink } from '../../../modules/workbench/view/workbench-link';
|
||||
import { selectionStateAtom, useAtom } from '../scoped-atoms';
|
||||
import type { DraggableTitleCellData, PageListItemProps } from '../types';
|
||||
import { usePageDisplayProperties } from '../use-page-display-properties';
|
||||
import { useAllDocDisplayProperties } from '../use-all-doc-display-properties';
|
||||
import { ColWrapper, formatDate, stopPropagation } from '../utils';
|
||||
import * as styles from './page-list-item.css';
|
||||
import { PageTags } from './page-tags';
|
||||
@@ -18,7 +18,7 @@ const ListTitleCell = ({
|
||||
title,
|
||||
preview,
|
||||
}: Pick<PageListItemProps, 'title' | 'preview'>) => {
|
||||
const [displayProperties] = usePageDisplayProperties();
|
||||
const [displayProperties] = useAllDocDisplayProperties();
|
||||
return (
|
||||
<div data-testid="page-list-item-title" className={styles.titleCell}>
|
||||
<div
|
||||
@@ -27,7 +27,7 @@ const ListTitleCell = ({
|
||||
>
|
||||
{title}
|
||||
</div>
|
||||
{preview && displayProperties['bodyNotes'] ? (
|
||||
{preview && displayProperties.displayProperties.bodyNotes ? (
|
||||
<div
|
||||
data-testid="page-list-item-preview-text"
|
||||
className={styles.titleCellPreview}
|
||||
@@ -127,7 +127,7 @@ const PageListOperationsCell = ({
|
||||
};
|
||||
|
||||
export const PageListItem = (props: PageListItemProps) => {
|
||||
const [displayProperties] = usePageDisplayProperties();
|
||||
const [displayProperties] = useAllDocDisplayProperties();
|
||||
const pageTitleElement = useMemo(() => {
|
||||
return (
|
||||
<div className={styles.dragPageItemOverlay}>
|
||||
@@ -190,7 +190,7 @@ export const PageListItem = (props: PageListItemProps) => {
|
||||
flex={4}
|
||||
alignment="end"
|
||||
style={{ overflow: 'visible' }}
|
||||
hidden={!displayProperties['tags']}
|
||||
hidden={!displayProperties.displayProperties.tags}
|
||||
>
|
||||
<PageTagsCell pageId={props.pageId} />
|
||||
</ColWrapper>
|
||||
@@ -199,7 +199,7 @@ export const PageListItem = (props: PageListItemProps) => {
|
||||
flex={1}
|
||||
alignment="end"
|
||||
hideInSmallContainer
|
||||
hidden={!displayProperties['createDate']}
|
||||
hidden={!displayProperties.displayProperties.createDate}
|
||||
>
|
||||
<PageCreateDateCell createDate={props.createDate} />
|
||||
</ColWrapper>
|
||||
@@ -207,7 +207,7 @@ export const PageListItem = (props: PageListItemProps) => {
|
||||
flex={1}
|
||||
alignment="end"
|
||||
hideInSmallContainer
|
||||
hidden={!displayProperties['updatedDate']}
|
||||
hidden={!displayProperties.displayProperties.updatedDate}
|
||||
>
|
||||
<PageUpdatedDateCell updatedDate={props.updatedDate} />
|
||||
</ColWrapper>
|
||||
|
||||
@@ -5,24 +5,13 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { FavoritedIcon, FavoriteIcon } from '@blocksuite/icons';
|
||||
import type { DocMeta } from '@blocksuite/store';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { atomWithStorage } from 'jotai/utils';
|
||||
import { type ReactNode, useMemo } from 'react';
|
||||
|
||||
import * as styles from './group-definitions.css';
|
||||
import type {
|
||||
DateKey,
|
||||
ItemGroupDefinition,
|
||||
ListItem,
|
||||
PageGroupByType,
|
||||
} from './types';
|
||||
import type { DateKey, ItemGroupDefinition, ListItem } from './types';
|
||||
import { useAllDocDisplayProperties } from './use-all-doc-display-properties';
|
||||
import { betweenDaysAgo, withinDaysAgo } from './utils';
|
||||
|
||||
export const pageGroupByTypeAtom = atomWithStorage<PageGroupByType>(
|
||||
'pageGroupByType',
|
||||
'updatedDate'
|
||||
);
|
||||
|
||||
const GroupLabel = ({
|
||||
label,
|
||||
count,
|
||||
@@ -189,7 +178,7 @@ export const useFavoriteGroupDefinitions = <
|
||||
};
|
||||
|
||||
export const usePageItemGroupDefinitions = () => {
|
||||
const key = useAtomValue(pageGroupByTypeAtom);
|
||||
const [workspaceProperties] = useAllDocDisplayProperties();
|
||||
const tagGroupDefinitions = useTagGroupDefinitions();
|
||||
const createDateGroupDefinitions = useDateGroupDefinitions('createDate');
|
||||
const updatedDateGroupDefinitions = useDateGroupDefinitions('updatedDate');
|
||||
@@ -206,12 +195,12 @@ export const usePageItemGroupDefinitions = () => {
|
||||
// add more here later
|
||||
// todo: some page group definitions maybe dynamic
|
||||
};
|
||||
return itemGroupDefinitions[key];
|
||||
return itemGroupDefinitions[workspaceProperties.groupBy];
|
||||
}, [
|
||||
createDateGroupDefinitions,
|
||||
favouriteGroupDefinitions,
|
||||
key,
|
||||
tagGroupDefinitions,
|
||||
updatedDateGroupDefinitions,
|
||||
workspaceProperties.groupBy,
|
||||
]);
|
||||
};
|
||||
|
||||
@@ -3,9 +3,10 @@ import { useMemo } from 'react';
|
||||
|
||||
import { ListHeaderTitleCell } from './page-header';
|
||||
import type { HeaderColDef } from './types';
|
||||
import { usePageDisplayProperties } from './use-page-display-properties';
|
||||
import { useAllDocDisplayProperties } from './use-all-doc-display-properties';
|
||||
export const usePageHeaderColsDef = (): HeaderColDef[] => {
|
||||
const [displayProperties] = usePageDisplayProperties();
|
||||
const [displayProperties] = useAllDocDisplayProperties();
|
||||
|
||||
return useMemo(
|
||||
() => [
|
||||
{
|
||||
@@ -20,7 +21,7 @@ export const usePageHeaderColsDef = (): HeaderColDef[] => {
|
||||
content: <Trans i18nKey="Tags" />,
|
||||
flex: 3,
|
||||
alignment: 'end',
|
||||
hidden: !displayProperties['tags'],
|
||||
hidden: !displayProperties.displayProperties.tags,
|
||||
},
|
||||
{
|
||||
key: 'createDate',
|
||||
@@ -29,7 +30,7 @@ export const usePageHeaderColsDef = (): HeaderColDef[] => {
|
||||
sortable: true,
|
||||
alignment: 'end',
|
||||
hideInSmallContainer: true,
|
||||
hidden: !displayProperties['createDate'],
|
||||
hidden: !displayProperties.displayProperties.createDate,
|
||||
},
|
||||
{
|
||||
key: 'updatedDate',
|
||||
@@ -38,7 +39,7 @@ export const usePageHeaderColsDef = (): HeaderColDef[] => {
|
||||
sortable: true,
|
||||
alignment: 'end',
|
||||
hideInSmallContainer: true,
|
||||
hidden: !displayProperties['updatedDate'],
|
||||
hidden: !displayProperties.displayProperties.updatedDate,
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
|
||||
@@ -16,9 +16,9 @@ export * from './page-group';
|
||||
export * from './page-header';
|
||||
export * from './tags';
|
||||
export * from './types';
|
||||
export * from './use-all-doc-display-properties';
|
||||
export * from './use-collection-manager';
|
||||
export * from './use-filtered-page-metas';
|
||||
export * from './use-page-display-properties';
|
||||
export * from './utils';
|
||||
export * from './view';
|
||||
export * from './virtualized-list';
|
||||
|
||||
@@ -168,3 +168,8 @@ export type PageDisplayProperties = {
|
||||
createDate: boolean;
|
||||
updatedDate: boolean;
|
||||
};
|
||||
|
||||
export type DisplayProperties = {
|
||||
groupBy: PageGroupByType;
|
||||
displayProperties: PageDisplayProperties;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { useService, Workspace } from '@toeverything/infra';
|
||||
import { useAtom } from 'jotai';
|
||||
import { atomWithStorage } from 'jotai/utils';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import type {
|
||||
DisplayProperties,
|
||||
PageDisplayProperties,
|
||||
PageGroupByType,
|
||||
} from './types';
|
||||
|
||||
export const displayPropertiesAtom = atomWithStorage<{
|
||||
[workspaceId: string]: DisplayProperties;
|
||||
}>('allDocDisplayProperties', {});
|
||||
|
||||
const defaultProps: DisplayProperties = {
|
||||
groupBy: 'updatedDate',
|
||||
displayProperties: {
|
||||
bodyNotes: true,
|
||||
tags: true,
|
||||
createDate: true,
|
||||
updatedDate: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const useAllDocDisplayProperties = (): [
|
||||
DisplayProperties,
|
||||
(
|
||||
key: keyof DisplayProperties,
|
||||
value: PageGroupByType | PageDisplayProperties
|
||||
) => void,
|
||||
] => {
|
||||
const workspace = useService(Workspace);
|
||||
const [properties, setProperties] = useAtom(displayPropertiesAtom);
|
||||
|
||||
const workspaceProperties = properties[workspace.id] || defaultProps;
|
||||
|
||||
const onChange = useCallback(
|
||||
(
|
||||
key: keyof DisplayProperties,
|
||||
value: PageGroupByType | PageDisplayProperties
|
||||
) => {
|
||||
setProperties(prev => ({
|
||||
...prev,
|
||||
[workspace.id]: {
|
||||
...(prev[workspace.id] || defaultProps),
|
||||
[key]: value,
|
||||
},
|
||||
}));
|
||||
},
|
||||
[setProperties, workspace.id]
|
||||
);
|
||||
|
||||
return [workspaceProperties, onChange];
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
import { useAtom } from 'jotai';
|
||||
import { atomWithStorage } from 'jotai/utils';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import type { PageDisplayProperties } from './types';
|
||||
|
||||
export const pageDisplayPropertiesAtom = atomWithStorage<PageDisplayProperties>(
|
||||
'pageDisplayProperties',
|
||||
{
|
||||
bodyNotes: true,
|
||||
tags: true,
|
||||
createDate: true,
|
||||
updatedDate: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const usePageDisplayProperties = (): [
|
||||
PageDisplayProperties,
|
||||
(key: keyof PageDisplayProperties, value: boolean) => void,
|
||||
] => {
|
||||
const [properties, setProperties] = useAtom(pageDisplayPropertiesAtom);
|
||||
const onChange = useCallback(
|
||||
(key: keyof PageDisplayProperties, value: boolean) => {
|
||||
setProperties(prev => ({ ...prev, [key]: value }));
|
||||
},
|
||||
[setProperties]
|
||||
);
|
||||
return [properties, onChange];
|
||||
};
|
||||
Reference in New Issue
Block a user