- {inlineProperties.map(({ property, config }) => {
- if (!displayProperties?.includes(property.id)) {
- return null;
- }
- return (
-
-
+ <>
+ {/* stack properties */}
+
+
+ {stackProperties.map(({ systemProperty, workspaceProperty }) => {
+ const displayKeys = [
+ systemProperty ? `system:${systemProperty.type}` : null,
+ workspaceProperty ? `property:${workspaceProperty.id}` : null,
+ ];
+ if (
+ !displayKeys.some(key => key && displayProperties?.includes(key))
+ ) {
+ return null;
+ }
+ if (systemProperty) {
+ return (
+
+ );
+ } else if (workspaceProperty) {
+ return (
+
+ );
+ }
+ return null;
+ })}
+
+ {displayProperties?.includes('system:tags') ? (
+
+
- );
- })}
- {tagsProperty && displayProperties?.includes(tagsProperty.property.id) ? (
-
- ) : null}
- {stackProperties.map(({ property, config }) => {
- if (!displayProperties?.includes(property.id)) {
+ ) : null}
+
+ {/* inline properties */}
+ {inlineProperties.map(({ systemProperty, workspaceProperty }) => {
+ const displayKeys = [
+ systemProperty ? `system:${systemProperty.type}` : null,
+ workspaceProperty ? `property:${workspaceProperty.id}` : null,
+ ];
+ if (!displayKeys.some(key => key && displayProperties?.includes(key))) {
return null;
}
- return (
-
- );
+ if (systemProperty) {
+ return (
+
+ );
+ } else if (workspaceProperty) {
+ return (
+
+
+
+ );
+ }
+ return null;
})}
-
+ >
);
};
-const PropertyRenderer = ({
+const SystemPropertyRenderer = ({
+ doc,
+ config,
+}: {
+ doc: DocRecord;
+ config: (typeof SystemPropertyTypes)[string];
+}) => {
+ if (!config.docListProperty) {
+ return null;
+ }
+
+ return
;
+};
+
+const WorkspacePropertyRenderer = ({
property,
doc,
config,
diff --git a/packages/frontend/core/src/components/explorer/properties.ts b/packages/frontend/core/src/components/explorer/properties.ts
new file mode 100644
index 0000000000..de3800d2ad
--- /dev/null
+++ b/packages/frontend/core/src/components/explorer/properties.ts
@@ -0,0 +1,67 @@
+import type { DocCustomPropertyInfo } from '@affine/core/modules/db';
+
+import { SystemPropertyTypes } from '../system-property-types';
+
+const systemProperties = Object.entries(SystemPropertyTypes);
+
+/**
+ * In AFFiNE's property system, the property list can be fully customized by users.
+ * For example, system properties like `createdAt` and `updatedAt`.
+ * Users can completely remove them or create multiple instances. (This doesn't affect the underlying data, only the property display)
+ *
+ * To prevent user-defined properties from affecting the display of system properties, we've designed a dedicated property list for the Explorer.
+ * This list generates a final property list based on system properties and user-defined properties, arranged in a specific order.
+ *
+ * For example, we have a workspace property list:
+ *
+ * - `{name: 'Birth', type: 'createdAt'}`
+ * - `{name: 'Labels', type: 'tags'}`
+ * - `{name: 'Name', type: 'Text'}`
+ *
+ * Assuming we have 3 system properties: `createdAt`, `updatedAt`, and `tags`
+ *
+ * The final property list should be:
+ *
+ * - `{systemProperty: {type: 'createdAt'}, workspaceProperty: {name: 'Birth'}}`
+ * - `{systemProperty: {type: 'updatedAt'}, workspaceProperty: null}`
+ * - `{systemProperty: {type: 'tags'}, workspaceProperty: {name: 'Labels'}}`
+ * - `{systemProperty: null, workspaceProperty: {name: 'Name'}}`
+ *
+ * When displaying the list to users, we prioritize showing the workspace property if it exists, otherwise we show the system property.
+ *
+ * When users configure a property, we prioritize recording the system property's ID. This ensures that when users delete a property, it won't affect these settings.
+ */
+export function generateExplorerPropertyList(
+ workspaceProperties: DocCustomPropertyInfo[]
+): {
+ systemProperty?: (typeof SystemPropertyTypes)[number] & { type: string };
+ workspaceProperty?: DocCustomPropertyInfo;
+}[] {
+ const finalList = [];
+ workspaceProperties = [...workspaceProperties];
+
+ for (const [type, info] of systemProperties) {
+ const workspacePropertyIndex = workspaceProperties.findIndex(
+ p => p.type === type
+ );
+ if (workspacePropertyIndex === -1) {
+ finalList.push({
+ systemProperty: { ...info, type },
+ });
+ } else {
+ finalList.push({
+ systemProperty: { ...info, type },
+ workspaceProperty: workspaceProperties[workspacePropertyIndex],
+ });
+ workspaceProperties.splice(workspacePropertyIndex, 1);
+ }
+ }
+
+ for (const workspaceProperty of workspaceProperties) {
+ finalList.push({
+ workspaceProperty,
+ });
+ }
+
+ return finalList;
+}
diff --git a/packages/frontend/core/src/components/filter/add-filter.tsx b/packages/frontend/core/src/components/filter/add-filter.tsx
index 0ca6a47a49..021388d07b 100644
--- a/packages/frontend/core/src/components/filter/add-filter.tsx
+++ b/packages/frontend/core/src/components/filter/add-filter.tsx
@@ -4,7 +4,9 @@ import { WorkspacePropertyService } from '@affine/core/modules/workspace-propert
import { useI18n } from '@affine/i18n';
import { ArrowLeftBigIcon, FavoriteIcon, PlusIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
+import { useMemo } from 'react';
+import { generateExplorerPropertyList } from '../explorer/properties';
import { WorkspacePropertyIcon, WorkspacePropertyName } from '../properties';
import { WorkspacePropertyTypes } from '../workspace-property-types';
import * as styles from './styles.css';
@@ -18,7 +20,13 @@ export const AddFilterMenu = ({
}) => {
const t = useI18n();
const workspacePropertyService = useService(WorkspacePropertyService);
- const workspaceProperties = useLiveData(workspacePropertyService.properties$);
+ const workspaceProperties = useLiveData(
+ workspacePropertyService.sortedProperties$
+ );
+ const explorerPropertyList = useMemo(
+ () => generateExplorerPropertyList(workspaceProperties),
+ [workspaceProperties]
+ );
return (
<>
@@ -64,34 +72,62 @@ export const AddFilterMenu = ({
{t['com.affine.filter.is-public']()}
- {workspaceProperties.map(property => {
- const type = WorkspacePropertyTypes[property.type];
- const defaultFilter = type?.defaultFilter;
- if (!defaultFilter) {
- return null;
+ {explorerPropertyList.map(({ systemProperty, workspaceProperty }) => {
+ if (systemProperty) {
+ const defaultFilter =
+ 'defaultFilter' in systemProperty && systemProperty.defaultFilter;
+ if (!defaultFilter) {
+ return null;
+ }
+ return (
+
+ }
+ key={systemProperty.type}
+ onClick={() => {
+ onAdd({
+ type: 'system',
+ key: systemProperty.type,
+ ...defaultFilter,
+ });
+ }}
+ >
+
+ {t.t(systemProperty.name)}
+
+
+ );
+ } else if (workspaceProperty) {
+ const type = WorkspacePropertyTypes[workspaceProperty.type];
+ const defaultFilter = type?.defaultFilter;
+ if (!defaultFilter) {
+ return null;
+ }
+ return (
+
+ }
+ key={workspaceProperty.id}
+ onClick={() => {
+ onAdd({
+ type: 'property',
+ key: workspaceProperty.id,
+ ...defaultFilter,
+ });
+ }}
+ >
+
+
+
+
+ );
}
- return (
-
- }
- key={property.id}
- onClick={() => {
- onAdd({
- type: 'property',
- key: property.id,
- ...defaultFilter,
- });
- }}
- >
-
-
-
-
- );
+ return null;
})}
>
);
diff --git a/packages/frontend/core/src/components/system-property-types/created-updated-at.tsx b/packages/frontend/core/src/components/system-property-types/created-updated-at.tsx
new file mode 100644
index 0000000000..4bab0154f1
--- /dev/null
+++ b/packages/frontend/core/src/components/system-property-types/created-updated-at.tsx
@@ -0,0 +1,8 @@
+export {
+ CreateAtDocListProperty,
+ CreatedAtFilterValue,
+ CreatedAtGroupHeader,
+ UpdatedAtDocListProperty,
+ UpdatedAtFilterValue,
+ UpdatedAtGroupHeader,
+} from '../workspace-property-types/created-updated-at';
diff --git a/packages/frontend/core/src/components/system-property-types/created-updated-by.tsx b/packages/frontend/core/src/components/system-property-types/created-updated-by.tsx
new file mode 100644
index 0000000000..f9f7c923a7
--- /dev/null
+++ b/packages/frontend/core/src/components/system-property-types/created-updated-by.tsx
@@ -0,0 +1,6 @@
+export {
+ CreatedByDocListInlineProperty,
+ CreatedByUpdatedByFilterValue,
+ ModifiedByGroupHeader,
+ UpdatedByDocListInlineProperty,
+} from '../workspace-property-types/created-updated-by';
diff --git a/packages/frontend/core/src/components/system-property-types/index.ts b/packages/frontend/core/src/components/system-property-types/index.ts
index bd707ad787..0a0067b958 100644
--- a/packages/frontend/core/src/components/system-property-types/index.ts
+++ b/packages/frontend/core/src/components/system-property-types/index.ts
@@ -1,10 +1,34 @@
import type { FilterParams } from '@affine/core/modules/collection-rules';
+import type { DocRecord } from '@affine/core/modules/doc';
import type { I18nString } from '@affine/i18n';
-import { FavoriteIcon, ShareIcon, TagIcon } from '@blocksuite/icons/rc';
+import {
+ DateTimeIcon,
+ FavoriteIcon,
+ HistoryIcon,
+ MemberIcon,
+ ShareIcon,
+ TagIcon,
+} from '@blocksuite/icons/rc';
+import type { GroupHeaderProps } from '../explorer/types';
+import { DateFilterMethod } from '../workspace-property-types';
+import {
+ CreateAtDocListProperty,
+ CreatedAtFilterValue,
+ CreatedAtGroupHeader,
+ UpdatedAtDocListProperty,
+ UpdatedAtFilterValue,
+ UpdatedAtGroupHeader,
+} from './created-updated-at';
+import {
+ CreatedByDocListInlineProperty,
+ CreatedByUpdatedByFilterValue,
+ ModifiedByGroupHeader,
+ UpdatedByDocListInlineProperty,
+} from './created-updated-by';
import { FavoriteFilterValue } from './favorite';
import { SharedFilterValue } from './shared';
-import { TagsFilterValue } from './tags';
+import { TagsDocListProperty, TagsFilterValue, TagsGroupHeader } from './tags';
export const SystemPropertyTypes = {
tags: {
@@ -16,6 +40,68 @@ export const SystemPropertyTypes = {
'is-empty': 'com.affine.filter.is empty',
},
filterValue: TagsFilterValue,
+ allowInGroupBy: true,
+ allowInOrderBy: true,
+ defaultFilter: { method: 'is-not-empty' },
+ showInDocList: 'stack',
+ docListProperty: TagsDocListProperty,
+ groupHeader: TagsGroupHeader,
+ },
+ createdBy: {
+ icon: MemberIcon,
+ name: 'com.affine.page-properties.property.createdBy',
+ allowInGroupBy: true,
+ allowInOrderBy: true,
+ filterMethod: {
+ include: 'com.affine.filter.contains all',
+ },
+ filterValue: CreatedByUpdatedByFilterValue,
+ defaultFilter: { method: 'include', value: '' },
+ showInDocList: 'inline',
+ docListProperty: CreatedByDocListInlineProperty,
+ groupHeader: ModifiedByGroupHeader,
+ },
+ updatedBy: {
+ icon: MemberIcon,
+ name: 'com.affine.page-properties.property.updatedBy',
+ allowInGroupBy: true,
+ allowInOrderBy: true,
+ filterMethod: {
+ include: 'com.affine.filter.contains all',
+ },
+ filterValue: CreatedByUpdatedByFilterValue,
+ defaultFilter: { method: 'include', value: '' },
+ showInDocList: 'inline',
+ docListProperty: UpdatedByDocListInlineProperty,
+ groupHeader: ModifiedByGroupHeader,
+ },
+ updatedAt: {
+ icon: DateTimeIcon,
+ name: 'com.affine.page-properties.property.updatedAt',
+ allowInGroupBy: true,
+ allowInOrderBy: true,
+ filterMethod: {
+ ...DateFilterMethod,
+ },
+ filterValue: UpdatedAtFilterValue,
+ defaultFilter: { method: 'this-week' },
+ showInDocList: 'inline',
+ docListProperty: UpdatedAtDocListProperty,
+ groupHeader: UpdatedAtGroupHeader,
+ },
+ createdAt: {
+ icon: HistoryIcon,
+ name: 'com.affine.page-properties.property.createdAt',
+ allowInGroupBy: true,
+ allowInOrderBy: true,
+ filterMethod: {
+ ...DateFilterMethod,
+ },
+ filterValue: CreatedAtFilterValue,
+ defaultFilter: { method: 'this-week' },
+ showInDocList: 'inline',
+ docListProperty: CreateAtDocListProperty,
+ groupHeader: CreatedAtGroupHeader,
},
favorite: {
icon: FavoriteIcon,
@@ -33,7 +119,7 @@ export const SystemPropertyTypes = {
},
filterValue: SharedFilterValue,
},
-} satisfies {
+} as {
[type: string]: {
icon: React.FC
>;
name: I18nString;
@@ -45,13 +131,20 @@ export const SystemPropertyTypes = {
filter: FilterParams;
onChange: (filter: FilterParams) => void;
}>;
+ defaultFilter?: Omit;
+ /**
+ * Whether to show the property in the doc list,
+ * - `inline`: show the property in the doc list inline
+ * - `stack`: show as tags
+ */
+ showInDocList?: 'inline' | 'stack';
+ docListProperty?: React.FC<{ doc: DocRecord }>;
+ groupHeader?: React.FC;
};
};
export type SystemPropertyType = keyof typeof SystemPropertyTypes;
-export const isSupportedSystemPropertyType = (
- type?: string
-): type is SystemPropertyType => {
+export const isSupportedSystemPropertyType = (type?: string) => {
return type ? type in SystemPropertyTypes : false;
};
diff --git a/packages/frontend/core/src/components/system-property-types/tags.tsx b/packages/frontend/core/src/components/system-property-types/tags.tsx
index 498836edff..b7d4f0d192 100644
--- a/packages/frontend/core/src/components/system-property-types/tags.tsx
+++ b/packages/frontend/core/src/components/system-property-types/tags.tsx
@@ -1,62 +1,5 @@
-import type { FilterParams } from '@affine/core/modules/collection-rules';
-import { TagService } from '@affine/core/modules/tag';
-import { useI18n } from '@affine/i18n';
-import { useLiveData, useService } from '@toeverything/infra';
-import { cssVarV2 } from '@toeverything/theme/v2';
-import { useCallback, useMemo } from 'react';
-
-import { WorkspaceTagsInlineEditor } from '../tags';
-
-export const TagsFilterValue = ({
- filter,
- onChange,
-}: {
- filter: FilterParams;
- onChange: (filter: FilterParams) => void;
-}) => {
- const t = useI18n();
- const tagService = useService(TagService);
- const allTagMetas = useLiveData(tagService.tagList.tagMetas$);
-
- const selectedTags = useMemo(
- () =>
- filter.value
- ?.split(',')
- .filter(id => allTagMetas.some(tag => tag.id === id)) ?? [],
- [filter, allTagMetas]
- );
-
- const handleSelectTag = useCallback(
- (tagId: string) => {
- onChange({
- ...filter,
- value: [...selectedTags, tagId].join(','),
- });
- },
- [filter, onChange, selectedTags]
- );
-
- const handleDeselectTag = useCallback(
- (tagId: string) => {
- onChange({
- ...filter,
- value: selectedTags.filter(id => id !== tagId).join(','),
- });
- },
- [filter, onChange, selectedTags]
- );
-
- return filter.method !== 'is-not-empty' && filter.method !== 'is-empty' ? (
-
- {t['com.affine.filter.empty']()}
-
- }
- selectedTags={selectedTags}
- onSelectTag={handleSelectTag}
- onDeselectTag={handleDeselectTag}
- tagMode="inline-tag"
- />
- ) : undefined;
-};
+export {
+ TagsDocListProperty,
+ TagsFilterValue,
+ TagsGroupHeader,
+} from '../workspace-property-types/tags';
diff --git a/packages/frontend/core/src/components/workspace-property-types/created-updated-at.css.ts b/packages/frontend/core/src/components/workspace-property-types/created-updated-at.css.ts
new file mode 100644
index 0000000000..86ba2faaca
--- /dev/null
+++ b/packages/frontend/core/src/components/workspace-property-types/created-updated-at.css.ts
@@ -0,0 +1,27 @@
+import { cssVarV2 } from '@toeverything/theme/v2';
+import { style } from '@vanilla-extract/css';
+
+export const empty = style({
+ color: cssVarV2.text.placeholder,
+});
+
+export const tooltip = style({
+ display: 'inline-block',
+ selectors: {
+ '&::first-letter': {
+ textTransform: 'uppercase',
+ },
+ },
+});
+
+export const dateDocListInlineProperty = style({
+ width: 60,
+ textAlign: 'center',
+ fontSize: 12,
+ lineHeight: '20px',
+ color: cssVarV2.text.secondary,
+ whiteSpace: 'nowrap',
+ overflow: 'hidden',
+ textOverflow: 'ellipsis',
+ flexShrink: 0,
+});
diff --git a/packages/frontend/core/src/components/workspace-property-types/created-updated-at.tsx b/packages/frontend/core/src/components/workspace-property-types/created-updated-at.tsx
new file mode 100644
index 0000000000..e1000b4cb4
--- /dev/null
+++ b/packages/frontend/core/src/components/workspace-property-types/created-updated-at.tsx
@@ -0,0 +1,110 @@
+import { PropertyValue, Tooltip } from '@affine/component';
+import { type DocRecord, DocService } from '@affine/core/modules/doc';
+import { i18nTime, useI18n } from '@affine/i18n';
+import { useLiveData, useServices } from '@toeverything/infra';
+
+import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
+import type { GroupHeaderProps } from '../explorer/types';
+import * as styles from './created-updated-at.css';
+
+const toRelativeDate = (time: string | number) => {
+ return i18nTime(time, {
+ relative: {
+ max: [1, 'day'],
+ },
+ absolute: {
+ accuracy: 'day',
+ },
+ });
+};
+
+const MetaDateValueFactory = ({
+ type,
+}: {
+ type: 'createDate' | 'updatedDate';
+}) =>
+ function ReadonlyDateValue() {
+ const { docService } = useServices({
+ DocService,
+ });
+
+ const docMeta = useLiveData(docService.doc.meta$);
+ const value = docMeta?.[type];
+
+ const relativeDate = value ? toRelativeDate(value) : null;
+ const date = value ? i18nTime(value) : null;
+
+ return (
+
+
+ {relativeDate}
+
+
+ );
+ };
+
+export const CreateAtValue = MetaDateValueFactory({
+ type: 'createDate',
+});
+
+export const UpdatedAtValue = MetaDateValueFactory({
+ type: 'updatedDate',
+});
+
+export const CreatedAtGroupHeader = (props: GroupHeaderProps) => {
+ return ;
+};
+
+export const UpdatedAtGroupHeader = (props: GroupHeaderProps) => {
+ return ;
+};
+
+export const CreateAtDocListProperty = ({ doc }: { doc: DocRecord }) => {
+ const t = useI18n();
+ const docMeta = useLiveData(doc.meta$);
+ const createDate = docMeta?.createDate;
+
+ if (!createDate) return null;
+
+ return (
+
+ {t.t('created at', { time: i18nTime(createDate) })}
+
+ }
+ >
+
+ {i18nTime(createDate, { relative: true })}
+
+
+ );
+};
+
+export const UpdatedAtDocListProperty = ({ doc }: { doc: DocRecord }) => {
+ const t = useI18n();
+ const docMeta = useLiveData(doc.meta$);
+ const updatedDate = docMeta?.updatedDate;
+
+ if (!updatedDate) return null;
+
+ return (
+
+ {t.t('updated at', { time: i18nTime(updatedDate) })}
+
+ }
+ >
+
+ {i18nTime(updatedDate, { relative: true })}
+
+
+ );
+};
+
+export { DateFilterValue as CreatedAtFilterValue } from './date';
+export { DateFilterValue as UpdatedAtFilterValue } from './date';
diff --git a/packages/frontend/core/src/components/workspace-property-types/created-updated-by.tsx b/packages/frontend/core/src/components/workspace-property-types/created-updated-by.tsx
index 8794796d6b..62a30f1b57 100644
--- a/packages/frontend/core/src/components/workspace-property-types/created-updated-by.tsx
+++ b/packages/frontend/core/src/components/workspace-property-types/created-updated-by.tsx
@@ -9,7 +9,7 @@ import { cssVarV2 } from '@toeverything/theme/v2';
import { type ReactNode, useCallback, useMemo } from 'react';
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
-import type { DocListPropertyProps, GroupHeaderProps } from '../explorer/types';
+import type { GroupHeaderProps } from '../explorer/types';
import { MemberSelectorInline } from '../member-selector';
import * as styles from './created-updated-by.css';
@@ -135,9 +135,7 @@ export const CreatedByUpdatedByFilterValue = ({
);
};
-export const CreatedByDocListInlineProperty = ({
- doc,
-}: DocListPropertyProps) => {
+export const CreatedByDocListInlineProperty = ({ doc }: { doc: DocRecord }) => {
return (
{
+export const UpdatedByDocListInlineProperty = ({ doc }: { doc: DocRecord }) => {
return (
{
- return i18nTime(time, {
- relative: {
- max: [1, 'day'],
- },
- absolute: {
- accuracy: 'day',
- },
- });
-};
-
-const MetaDateValueFactory = ({
- type,
-}: {
- type: 'createDate' | 'updatedDate';
-}) =>
- function ReadonlyDateValue() {
- const { docService } = useServices({
- DocService,
- });
-
- const docMeta = useLiveData(docService.doc.meta$);
- const value = docMeta?.[type];
-
- const relativeDate = value ? toRelativeDate(value) : null;
- const date = value ? i18nTime(value) : null;
-
- return (
-
-
- {relativeDate}
-
-
- );
- };
-
-export const CreateDateValue = MetaDateValueFactory({
- type: 'createDate',
-});
-
-export const UpdatedDateValue = MetaDateValueFactory({
- type: 'updatedDate',
-});
-
export const DateFilterValue = ({
filter,
onChange,
@@ -199,50 +150,6 @@ export const DateDocListProperty = ({ value }: DocListPropertyProps) => {
);
};
-export const CreateDateDocListProperty = ({ doc }: DocListPropertyProps) => {
- const t = useI18n();
- const docMeta = useLiveData(doc.meta$);
- const createDate = docMeta?.createDate;
-
- if (!createDate) return null;
-
- return (
-
- {t.t('created at', { time: i18nTime(createDate) })}
-
- }
- >
-
- {i18nTime(createDate, { relative: true })}
-
-
- );
-};
-
-export const UpdatedDateDocListProperty = ({ doc }: DocListPropertyProps) => {
- const t = useI18n();
- const docMeta = useLiveData(doc.meta$);
- const updatedDate = docMeta?.updatedDate;
-
- if (!updatedDate) return null;
-
- return (
-
- {t.t('updated at', { time: i18nTime(updatedDate) })}
-
- }
- >
-
- {i18nTime(updatedDate, { relative: true })}
-
-
- );
-};
-
export const DateGroupHeader = ({ groupId, docCount }: GroupHeaderProps) => {
const date = groupId || 'No Date';
@@ -252,7 +159,3 @@ export const DateGroupHeader = ({ groupId, docCount }: GroupHeaderProps) => {
);
};
-
-export const CreatedGroupHeader = (props: GroupHeaderProps) => {
- return ;
-};
diff --git a/packages/frontend/core/src/components/workspace-property-types/index.ts b/packages/frontend/core/src/components/workspace-property-types/index.ts
index 4958109ba9..9ac85630d3 100644
--- a/packages/frontend/core/src/components/workspace-property-types/index.ts
+++ b/packages/frontend/core/src/components/workspace-property-types/index.ts
@@ -28,6 +28,16 @@ import {
CheckboxGroupHeader,
CheckboxValue,
} from './checkbox';
+import {
+ CreateAtDocListProperty,
+ CreateAtValue,
+ CreatedAtFilterValue,
+ CreatedAtGroupHeader,
+ UpdatedAtDocListProperty,
+ UpdatedAtFilterValue,
+ UpdatedAtGroupHeader,
+ UpdatedAtValue,
+} from './created-updated-at';
import {
CreatedByDocListInlineProperty,
CreatedByUpdatedByFilterValue,
@@ -37,15 +47,10 @@ import {
UpdatedByValue,
} from './created-updated-by';
import {
- CreateDateDocListProperty,
- CreateDateValue,
- CreatedGroupHeader,
DateDocListProperty,
DateFilterValue,
DateGroupHeader,
DateValue,
- UpdatedDateDocListProperty,
- UpdatedDateValue,
} from './date';
import {
DocPrimaryModeDocListProperty,
@@ -79,7 +84,7 @@ import {
TextValue,
} from './text';
-const DateFilterMethod = {
+export const DateFilterMethod = {
after: 'com.affine.filter.after',
before: 'com.affine.filter.before',
between: 'com.affine.filter.between',
@@ -213,7 +218,7 @@ export const WorkspacePropertyTypes = {
},
updatedAt: {
icon: DateTimeIcon,
- value: UpdatedDateValue,
+ value: UpdatedAtValue,
name: 'com.affine.page-properties.property.updatedAt',
description: 'com.affine.page-properties.property.updatedAt.tooltips',
renameable: false,
@@ -222,15 +227,15 @@ export const WorkspacePropertyTypes = {
filterMethod: {
...DateFilterMethod,
},
- filterValue: DateFilterValue,
+ filterValue: UpdatedAtFilterValue,
defaultFilter: { method: 'this-week' },
showInDocList: 'inline',
- docListProperty: UpdatedDateDocListProperty,
- groupHeader: CreatedGroupHeader,
+ docListProperty: UpdatedAtDocListProperty,
+ groupHeader: UpdatedAtGroupHeader,
},
createdAt: {
icon: HistoryIcon,
- value: CreateDateValue,
+ value: CreateAtValue,
name: 'com.affine.page-properties.property.createdAt',
description: 'com.affine.page-properties.property.createdAt.tooltips',
renameable: false,
@@ -239,11 +244,11 @@ export const WorkspacePropertyTypes = {
filterMethod: {
...DateFilterMethod,
},
- filterValue: DateFilterValue,
+ filterValue: CreatedAtFilterValue,
defaultFilter: { method: 'this-week' },
showInDocList: 'inline',
- docListProperty: CreateDateDocListProperty,
- groupHeader: CreatedGroupHeader,
+ docListProperty: CreateAtDocListProperty,
+ groupHeader: CreatedAtGroupHeader,
},
docPrimaryMode: {
icon: FileIcon,
diff --git a/packages/frontend/core/src/components/workspace-property-types/tags.tsx b/packages/frontend/core/src/components/workspace-property-types/tags.tsx
index 4db7d6e101..d8fd43349b 100644
--- a/packages/frontend/core/src/components/workspace-property-types/tags.tsx
+++ b/packages/frontend/core/src/components/workspace-property-types/tags.tsx
@@ -1,6 +1,6 @@
import { PropertyValue } from '@affine/component';
import type { FilterParams } from '@affine/core/modules/collection-rules';
-import { DocService } from '@affine/core/modules/doc';
+import { type DocRecord, DocService } from '@affine/core/modules/doc';
import { type Tag, TagService } from '@affine/core/modules/tag';
import { WorkspaceService } from '@affine/core/modules/workspace';
import { useI18n } from '@affine/i18n';
@@ -11,7 +11,7 @@ import { useCallback, useMemo } from 'react';
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
import { StackProperty } from '../explorer/docs-view/stack-property';
-import type { DocListPropertyProps, GroupHeaderProps } from '../explorer/types';
+import type { GroupHeaderProps } from '../explorer/types';
import { useNavigateHelper } from '../hooks/use-navigate-helper';
import type { PropertyValueProps } from '../properties/types';
import {
@@ -185,7 +185,7 @@ const TagIcon = ({ tag, size = 8 }: { tag: Tag; size?: number }) => {
/>
);
};
-export const TagsDocListProperty = ({ doc }: DocListPropertyProps) => {
+export const TagsDocListProperty = ({ doc }: { doc: DocRecord }) => {
const tagList = useService(TagService).tagList;
const tags = useLiveData(tagList.tagsByPageId$(doc.id));