chore(core): edit property meta events (#9253)

fix AF-1986
This commit is contained in:
pengx17
2024-12-23 11:36:24 +00:00
parent b246a2d45f
commit 8b076cb2a7
8 changed files with 131 additions and 14 deletions
@@ -278,6 +278,16 @@ export const BlocksuiteDocEditor = forwardRef<
[] []
); );
const onPropertyInfoChange = useCallback(
(property: DocCustomPropertyInfo, field: string) => {
track.doc.inlineDocInfo.property.editPropertyMeta({
type: property.type,
field,
});
},
[]
);
return ( return (
<> <>
<div className={styles.affineDocViewport}> <div className={styles.affineDocViewport}>
@@ -293,6 +303,7 @@ export const BlocksuiteDocEditor = forwardRef<
onDatabasePropertyChange={onDatabasePropertyChange} onDatabasePropertyChange={onDatabasePropertyChange}
onPropertyChange={onPropertyChange} onPropertyChange={onPropertyChange}
onPropertyAdded={onPropertyAdded} onPropertyAdded={onPropertyAdded}
onPropertyInfoChange={onPropertyInfoChange}
defaultOpenProperty={defaultOpenProperty} defaultOpenProperty={defaultOpenProperty}
/> />
</div> </div>
@@ -27,9 +27,14 @@ import * as styles from './styles.css';
const PropertyItem = ({ const PropertyItem = ({
propertyInfo, propertyInfo,
defaultOpenEditMenu, defaultOpenEditMenu,
onPropertyInfoChange,
}: { }: {
propertyInfo: DocCustomPropertyInfo; propertyInfo: DocCustomPropertyInfo;
defaultOpenEditMenu?: boolean; defaultOpenEditMenu?: boolean;
onPropertyInfoChange?: (
field: keyof DocCustomPropertyInfo,
value: string
) => void;
}) => { }) => {
const t = useI18n(); const t = useI18n();
const workspaceService = useService(WorkspaceService); const workspaceService = useService(WorkspaceService);
@@ -130,7 +135,12 @@ const PropertyItem = ({
onOpenChange: setMoreMenuOpen, onOpenChange: setMoreMenuOpen,
modal: true, modal: true,
}} }}
items={<EditDocPropertyMenuItems propertyId={propertyInfo.id} />} items={
<EditDocPropertyMenuItems
propertyId={propertyInfo.id}
onPropertyInfoChange={onPropertyInfoChange}
/>
}
> >
<IconButton size={20} iconClassName={styles.itemMore}> <IconButton size={20} iconClassName={styles.itemMore}>
<MoreHorizontalIcon /> <MoreHorizontalIcon />
@@ -145,8 +155,16 @@ const PropertyItem = ({
export const DocPropertyManager = ({ export const DocPropertyManager = ({
className, className,
defaultOpenEditMenuPropertyId, defaultOpenEditMenuPropertyId,
onPropertyInfoChange,
...props ...props
}: HTMLProps<HTMLDivElement> & { defaultOpenEditMenuPropertyId?: string }) => { }: HTMLProps<HTMLDivElement> & {
defaultOpenEditMenuPropertyId?: string;
onPropertyInfoChange?: (
property: DocCustomPropertyInfo,
field: keyof DocCustomPropertyInfo,
value: string
) => void;
}) => {
const docsService = useService(DocsService); const docsService = useService(DocsService);
const properties = useLiveData(docsService.propertyList.sortedProperties$); const properties = useLiveData(docsService.propertyList.sortedProperties$);
@@ -160,6 +178,9 @@ export const DocPropertyManager = ({
defaultOpenEditMenuPropertyId === propertyInfo.id defaultOpenEditMenuPropertyId === propertyInfo.id
} }
key={propertyInfo.id} key={propertyInfo.id}
onPropertyInfoChange={(...args) =>
onPropertyInfoChange?.(propertyInfo, ...args)
}
/> />
))} ))}
</div> </div>
@@ -4,6 +4,7 @@ import {
MenuSeparator, MenuSeparator,
useConfirmModal, useConfirmModal,
} from '@affine/component'; } from '@affine/component';
import type { DocCustomPropertyInfo } from '@affine/core/modules/db';
import { DocsService } from '@affine/core/modules/doc'; import { DocsService } from '@affine/core/modules/doc';
import { Trans, useI18n } from '@affine/i18n'; import { Trans, useI18n } from '@affine/i18n';
import { DeleteIcon, InvisibleIcon, ViewIcon } from '@blocksuite/icons/rc'; import { DeleteIcon, InvisibleIcon, ViewIcon } from '@blocksuite/icons/rc';
@@ -26,8 +27,13 @@ import * as styles from './edit-doc-property.css';
export const EditDocPropertyMenuItems = ({ export const EditDocPropertyMenuItems = ({
propertyId, propertyId,
onPropertyInfoChange,
}: { }: {
propertyId: string; propertyId: string;
onPropertyInfoChange?: (
field: keyof DocCustomPropertyInfo,
value: string
) => void;
}) => { }) => {
const t = useI18n(); const t = useI18n();
const docsService = useService(DocsService); const docsService = useService(DocsService);
@@ -68,8 +74,9 @@ export const EditDocPropertyMenuItems = ({
docsService.propertyList.updatePropertyInfo(propertyId, { docsService.propertyList.updatePropertyInfo(propertyId, {
name: e.currentTarget.value, name: e.currentTarget.value,
}); });
onPropertyInfoChange?.('name', e.currentTarget.value);
}, },
[docsService.propertyList, propertyId] [docsService.propertyList, propertyId, onPropertyInfoChange]
); );
const handleIconChange = useCallback( const handleIconChange = useCallback(
@@ -77,8 +84,9 @@ export const EditDocPropertyMenuItems = ({
docsService.propertyList.updatePropertyInfo(propertyId, { docsService.propertyList.updatePropertyInfo(propertyId, {
icon: iconName, icon: iconName,
}); });
onPropertyInfoChange?.('icon', iconName);
}, },
[docsService.propertyList, propertyId] [docsService.propertyList, propertyId, onPropertyInfoChange]
); );
const handleNameChange = useCallback((e: string) => { const handleNameChange = useCallback((e: string) => {
@@ -91,8 +99,9 @@ export const EditDocPropertyMenuItems = ({
docsService.propertyList.updatePropertyInfo(propertyId, { docsService.propertyList.updatePropertyInfo(propertyId, {
show: 'always-show', show: 'always-show',
}); });
onPropertyInfoChange?.('show', 'always-show');
}, },
[docsService.propertyList, propertyId] [docsService.propertyList, propertyId, onPropertyInfoChange]
); );
const handleClickHideWhenEmpty = useCallback( const handleClickHideWhenEmpty = useCallback(
@@ -101,8 +110,9 @@ export const EditDocPropertyMenuItems = ({
docsService.propertyList.updatePropertyInfo(propertyId, { docsService.propertyList.updatePropertyInfo(propertyId, {
show: 'hide-when-empty', show: 'hide-when-empty',
}); });
onPropertyInfoChange?.('show', 'hide-when-empty');
}, },
[docsService.propertyList, propertyId] [docsService.propertyList, propertyId, onPropertyInfoChange]
); );
const handleClickAlwaysHide = useCallback( const handleClickAlwaysHide = useCallback(
@@ -111,8 +121,9 @@ export const EditDocPropertyMenuItems = ({
docsService.propertyList.updatePropertyInfo(propertyId, { docsService.propertyList.updatePropertyInfo(propertyId, {
show: 'always-hide', show: 'always-hide',
}); });
onPropertyInfoChange?.('show', 'always-hide');
}, },
[docsService.propertyList, propertyId] [docsService.propertyList, propertyId, onPropertyInfoChange]
); );
if (!propertyInfo || !isSupportedDocPropertyType(propertyType)) { if (!propertyInfo || !isSupportedDocPropertyType(propertyType)) {
@@ -1,4 +1,5 @@
import { Divider, IconButton, Tooltip } from '@affine/component'; import { Divider, IconButton, Tooltip } from '@affine/component';
import type { DocCustomPropertyInfo } from '@affine/core/modules/db';
import { DocsService } from '@affine/core/modules/doc'; import { DocsService } from '@affine/core/modules/doc';
import { generateUniqueNameInSequence } from '@affine/core/utils/unique-name'; import { generateUniqueNameInSequence } from '@affine/core/utils/unique-name';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
@@ -59,6 +60,16 @@ export const DocPropertySidebar = () => {
[propertyList, properties] [propertyList, properties]
); );
const onPropertyInfoChange = useCallback(
(property: DocCustomPropertyInfo, field: string) => {
track.doc.sidepanel.property.editPropertyMeta({
type: property.type,
field,
});
},
[]
);
return ( return (
<div className={styles.container}> <div className={styles.container}>
<CollapsibleRoot defaultOpen> <CollapsibleRoot defaultOpen>
@@ -67,6 +78,7 @@ export const DocPropertySidebar = () => {
<DocPropertyManager <DocPropertyManager
className={styles.manager} className={styles.manager}
defaultOpenEditMenuPropertyId={newPropertyId} defaultOpenEditMenuPropertyId={newPropertyId}
onPropertyInfoChange={onPropertyInfoChange}
/> />
</CollapsibleContent> </CollapsibleContent>
</CollapsibleRoot> </CollapsibleRoot>
@@ -52,6 +52,11 @@ export interface DocPropertiesTableProps {
defaultOpenProperty?: DefaultOpenProperty; defaultOpenProperty?: DefaultOpenProperty;
onPropertyAdded?: (property: DocCustomPropertyInfo) => void; onPropertyAdded?: (property: DocCustomPropertyInfo) => void;
onPropertyChange?: (property: DocCustomPropertyInfo, value: unknown) => void; onPropertyChange?: (property: DocCustomPropertyInfo, value: unknown) => void;
onPropertyInfoChange?: (
property: DocCustomPropertyInfo,
field: keyof DocCustomPropertyInfo,
value: string
) => void;
onDatabasePropertyChange?: ( onDatabasePropertyChange?: (
row: DatabaseRow, row: DatabaseRow,
cell: DatabaseValueCell, cell: DatabaseValueCell,
@@ -106,12 +111,17 @@ interface DocPropertyRowProps {
showAll?: boolean; showAll?: boolean;
defaultOpenEditMenu?: boolean; defaultOpenEditMenu?: boolean;
onChange?: (value: unknown) => void; onChange?: (value: unknown) => void;
onPropertyInfoChange?: (
field: keyof DocCustomPropertyInfo,
value: string
) => void;
} }
export const DocPropertyRow = ({ export const DocPropertyRow = ({
propertyInfo, propertyInfo,
defaultOpenEditMenu, defaultOpenEditMenu,
onChange, onChange,
onPropertyInfoChange,
}: DocPropertyRowProps) => { }: DocPropertyRowProps) => {
const t = useI18n(); const t = useI18n();
const docService = useService(DocService); const docService = useService(DocService);
@@ -213,7 +223,12 @@ export const DocPropertyRow = ({
propertyInfo.name || propertyInfo.name ||
(typeInfo?.name ? t.t(typeInfo.name) : t['unnamed']()) (typeInfo?.name ? t.t(typeInfo.name) : t['unnamed']())
} }
menuItems={<EditDocPropertyMenuItems propertyId={propertyInfo.id} />} menuItems={
<EditDocPropertyMenuItems
propertyId={propertyInfo.id}
onPropertyInfoChange={onPropertyInfoChange}
/>
}
data-testid="doc-property-name" data-testid="doc-property-name"
/> />
<ValueRenderer <ValueRenderer
@@ -231,6 +246,11 @@ interface DocWorkspacePropertiesTableBodyProps {
defaultOpen?: boolean; defaultOpen?: boolean;
onChange?: (property: DocCustomPropertyInfo, value: unknown) => void; onChange?: (property: DocCustomPropertyInfo, value: unknown) => void;
onPropertyAdded?: (property: DocCustomPropertyInfo) => void; onPropertyAdded?: (property: DocCustomPropertyInfo) => void;
onPropertyInfoChange?: (
property: DocCustomPropertyInfo,
field: keyof DocCustomPropertyInfo,
value: string
) => void;
} }
// 🏷️ Tags (⋅ xxx) (⋅ yyy) // 🏷️ Tags (⋅ xxx) (⋅ yyy)
@@ -241,7 +261,15 @@ const DocWorkspacePropertiesTableBody = forwardRef<
DocWorkspacePropertiesTableBodyProps DocWorkspacePropertiesTableBodyProps
>( >(
( (
{ className, style, defaultOpen, onChange, onPropertyAdded, ...props }, {
className,
style,
defaultOpen,
onChange,
onPropertyAdded,
onPropertyInfoChange,
...props
},
ref ref
) => { ) => {
const t = useI18n(); const t = useI18n();
@@ -304,6 +332,9 @@ const DocWorkspacePropertiesTableBody = forwardRef<
propertyInfo={property} propertyInfo={property}
defaultOpenEditMenu={newPropertyId === property.id} defaultOpenEditMenu={newPropertyId === property.id}
onChange={value => onChange?.(property, value)} onChange={value => onChange?.(property, value)}
onPropertyInfoChange={(...args) =>
onPropertyInfoChange?.(property, ...args)
}
/> />
))} ))}
<div className={styles.actionContainer}> <div className={styles.actionContainer}>
@@ -357,6 +388,7 @@ const DocPropertiesTableInner = ({
defaultOpenProperty, defaultOpenProperty,
onPropertyAdded, onPropertyAdded,
onPropertyChange, onPropertyChange,
onPropertyInfoChange,
onDatabasePropertyChange, onDatabasePropertyChange,
className, className,
}: DocPropertiesTableProps) => { }: DocPropertiesTableProps) => {
@@ -376,6 +408,7 @@ const DocPropertiesTableInner = ({
} }
onPropertyAdded={onPropertyAdded} onPropertyAdded={onPropertyAdded}
onChange={onPropertyChange} onChange={onPropertyChange}
onPropertyInfoChange={onPropertyInfoChange}
/> />
<div className={styles.tableHeaderDivider} /> <div className={styles.tableHeaderDivider} />
<DocDatabaseBacklinkInfo <DocDatabaseBacklinkInfo
@@ -89,6 +89,20 @@ export const InfoTable = ({
[] []
); );
const onPropertyInfoChange = useCallback(
(
property: DocCustomPropertyInfo,
field: keyof DocCustomPropertyInfo,
_value: string
) => {
track.$.docInfoPanel.property.editPropertyMeta({
type: property.type,
field,
});
},
[]
);
return ( return (
<> <>
<PropertyCollapsibleSection <PropertyCollapsibleSection
@@ -120,6 +134,9 @@ export const InfoTable = ({
propertyInfo={property} propertyInfo={property}
defaultOpenEditMenu={newPropertyId === property.id} defaultOpenEditMenu={newPropertyId === property.id}
onChange={value => onPropertyChange(property, value)} onChange={value => onPropertyChange(property, value)}
onPropertyInfoChange={(...args) =>
onPropertyInfoChange(property, ...args)
}
/> />
))} ))}
<Menu <Menu
@@ -23,6 +23,16 @@ const WorkspaceSettingPropertiesMain = () => {
}); });
}, []); }, []);
const onPropertyInfoChange = useCallback(
(property: DocCustomPropertyInfo, field: string) => {
track.$.settingsPanel.workspace.editPropertyMeta({
type: property.type,
field,
});
},
[]
);
return ( return (
<div className={styles.main}> <div className={styles.main}>
<div className={styles.listHeader}> <div className={styles.listHeader}>
@@ -32,7 +42,7 @@ const WorkspaceSettingPropertiesMain = () => {
</Button> </Button>
</Menu> </Menu>
</div> </div>
<DocPropertyManager /> <DocPropertyManager onPropertyInfoChange={onPropertyInfoChange} />
</div> </div>
); );
}; };
+6 -4
View File
@@ -48,6 +48,7 @@ type DocEvents =
| 'copyBlockToLink' | 'copyBlockToLink'
| 'bookmark' | 'bookmark'
| 'editProperty' | 'editProperty'
| 'editPropertyMeta'
| 'addProperty'; | 'addProperty';
type EditorEvents = 'bold' | 'italic' | 'underline' | 'strikeThrough'; type EditorEvents = 'bold' | 'italic' | 'underline' | 'strikeThrough';
// END SECTION // END SECTION
@@ -168,12 +169,12 @@ const PageEvents = {
}, },
docInfoPanel: { docInfoPanel: {
$: ['open'], $: ['open'],
property: ['editProperty', 'addProperty'], property: ['editProperty', 'addProperty', 'editPropertyMeta'],
databaseProperty: ['editProperty'], databaseProperty: ['editProperty'],
}, },
settingsPanel: { settingsPanel: {
menu: ['openSettings'], menu: ['openSettings'],
workspace: ['viewPlans', 'export', 'addProperty'], workspace: ['viewPlans', 'export', 'addProperty', 'editPropertyMeta'],
profileAndBadge: ['viewPlans'], profileAndBadge: ['viewPlans'],
accountUsage: ['viewPlans'], accountUsage: ['viewPlans'],
accountSettings: ['uploadAvatar', 'removeAvatar', 'updateUserName'], accountSettings: ['uploadAvatar', 'removeAvatar', 'updateUserName'],
@@ -316,11 +317,11 @@ const PageEvents = {
}, },
inlineDocInfo: { inlineDocInfo: {
$: ['toggle'], $: ['toggle'],
property: ['editProperty', 'addProperty'], property: ['editProperty', 'editPropertyMeta', 'addProperty'],
databaseProperty: ['editProperty'], databaseProperty: ['editProperty'],
}, },
sidepanel: { sidepanel: {
property: ['addProperty'], property: ['addProperty', 'editPropertyMeta'],
}, },
biDirectionalLinksPanel: { biDirectionalLinksPanel: {
$: ['toggle'], $: ['toggle'],
@@ -459,6 +460,7 @@ export type EventArgs = {
type: string; type: string;
}; };
editProperty: { type: string }; editProperty: { type: string };
editPropertyMeta: { type: string; field: string };
addProperty: { type: string; control: 'at menu' | 'property list' }; addProperty: { type: string; control: 'at menu' | 'property list' };
linkDoc: { type: string; journal: boolean }; linkDoc: { type: string; journal: boolean };
drop: { type: string }; drop: { type: string };