diff --git a/packages/common/infra/src/modules/doc/stores/doc-properties.ts b/packages/common/infra/src/modules/doc/stores/doc-properties.ts index d668bfbc67..197b5fb301 100644 --- a/packages/common/infra/src/modules/doc/stores/doc-properties.ts +++ b/packages/common/infra/src/modules/doc/stores/doc-properties.ts @@ -64,7 +64,7 @@ export class DocPropertiesStore extends Store { createDocPropertyInfo( config: Omit & { id?: string } ) { - return this.dbService.db.docCustomPropertyInfo.create(config).id; + return this.dbService.db.docCustomPropertyInfo.create(config); } removeDocPropertyInfo(id: string) { diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-editor/lit-adaper.tsx b/packages/frontend/core/src/components/blocksuite/block-suite-editor/lit-adaper.tsx index 180ac7064d..52c903b3a6 100644 --- a/packages/frontend/core/src/components/blocksuite/block-suite-editor/lit-adaper.tsx +++ b/packages/frontend/core/src/components/blocksuite/block-suite-editor/lit-adaper.tsx @@ -3,11 +3,16 @@ import { useConfirmModal, useLitPortalFactory, } from '@affine/component'; +import type { + DatabaseRow, + DatabaseValueCell, +} from '@affine/core/modules/doc-info/types'; import { EditorService } from '@affine/core/modules/editor'; import { EditorSettingService } from '@affine/core/modules/editor-setting'; import { JournalService } from '@affine/core/modules/journal'; import { toURLSearchParams } from '@affine/core/modules/navigation'; import { PeekViewService } from '@affine/core/modules/peek-view/services/peek-view'; +import track from '@affine/track'; import type { DocMode } from '@blocksuite/affine/blocks'; import { DocTitle, @@ -16,6 +21,7 @@ import { } from '@blocksuite/affine/presets'; import type { Doc } from '@blocksuite/affine/store'; import { + type DocCustomPropertyInfo, DocService, DocsService, FeatureFlagService, @@ -239,6 +245,28 @@ export const BlocksuiteDocEditor = forwardRef< editorSettingService.editorSetting.settings$.selector(s => s.displayDocInfo) ); + const onPropertyChange = useCallback((property: DocCustomPropertyInfo) => { + track.doc.inlineDocInfo.property.editProperty({ + type: property.type, + }); + }, []); + + const onPropertyAdded = useCallback((property: DocCustomPropertyInfo) => { + track.doc.inlineDocInfo.property.addProperty({ + type: property.type, + control: 'at menu', + }); + }, []); + + const onDatabasePropertyChange = useCallback( + (_row: DatabaseRow, cell: DatabaseValueCell) => { + track.doc.inlineDocInfo.databaseProperty.editProperty({ + type: cell.property.type$.value, + }); + }, + [] + ); + return ( <>
@@ -248,7 +276,12 @@ export const BlocksuiteDocEditor = forwardRef< )} {!shared && displayDocInfo ? ( - + ) : null} void; + onCreated?: (property: DocCustomPropertyInfo) => void; }) => { const t = useI18n(); const docsService = useService(DocsService); @@ -36,13 +41,13 @@ export const CreatePropertyMenuItems = ({ ? generateUniqueNameInSequence(option.name, allNames) : option.name; const uniqueId = typeDefined.uniqueId; - const newPropertyId = propertyList.createProperty({ + const newProperty = propertyList.createProperty({ id: uniqueId, name, type: option.type, index: propertyList.indexAt(at), }); - onCreated?.(newPropertyId); + onCreated?.(newProperty); }, [at, onCreated, propertyList, properties] ); diff --git a/packages/frontend/core/src/components/doc-properties/sidebar/index.tsx b/packages/frontend/core/src/components/doc-properties/sidebar/index.tsx index 816d6cf6f8..b14c497add 100644 --- a/packages/frontend/core/src/components/doc-properties/sidebar/index.tsx +++ b/packages/frontend/core/src/components/doc-properties/sidebar/index.tsx @@ -1,6 +1,7 @@ import { Divider, IconButton, Tooltip } from '@affine/component'; import { generateUniqueNameInSequence } from '@affine/core/utils/unique-name'; import { useI18n } from '@affine/i18n'; +import track from '@affine/track'; import { PlusIcon } from '@blocksuite/icons/rc'; import { Content as CollapsibleContent, @@ -41,13 +42,17 @@ export const DocPropertySidebar = () => { const name = nameExists ? generateUniqueNameInSequence(option.name, allNames) : option.name; - const newPropertyId = propertyList.createProperty({ + const newProperty = propertyList.createProperty({ id: typeDefined.uniqueId, name, type: option.type, index: propertyList.indexAt('after'), }); - setNewPropertyId(newPropertyId); + setNewPropertyId(newProperty.id); + track.doc.sidepanel.property.addProperty({ + control: 'property list', + type: option.type, + }); }, [propertyList, properties] ); diff --git a/packages/frontend/core/src/components/doc-properties/table.tsx b/packages/frontend/core/src/components/doc-properties/table.tsx index 73d80965e0..ba602d3e4c 100644 --- a/packages/frontend/core/src/components/doc-properties/table.tsx +++ b/packages/frontend/core/src/components/doc-properties/table.tsx @@ -9,6 +9,10 @@ import { useDropTarget, } from '@affine/component'; import { DocDatabaseBacklinkInfo } from '@affine/core/modules/doc-info'; +import type { + DatabaseRow, + DatabaseValueCell, +} from '@affine/core/modules/doc-info/types'; import { WorkbenchService } from '@affine/core/modules/workbench'; import { ViewService } from '@affine/core/modules/workbench/services/view'; import type { AffineDNDData } from '@affine/core/types/dnd'; @@ -26,7 +30,6 @@ import { } from '@toeverything/infra'; import clsx from 'clsx'; import type React from 'react'; -import type { HTMLProps } from 'react'; import { forwardRef, useCallback, useState } from 'react'; import { DocPropertyIcon } from './icons/doc-property-icon'; @@ -47,6 +50,13 @@ export type DefaultOpenProperty = export interface DocPropertiesTableProps { defaultOpenProperty?: DefaultOpenProperty; + onPropertyAdded?: (property: DocCustomPropertyInfo) => void; + onPropertyChange?: (property: DocCustomPropertyInfo, value: unknown) => void; + onDatabasePropertyChange?: ( + row: DatabaseRow, + cell: DatabaseValueCell, + value: unknown + ) => void; } interface DocPropertiesTableHeaderProps { @@ -95,11 +105,13 @@ interface DocPropertyRowProps { propertyInfo: DocCustomPropertyInfo; showAll?: boolean; defaultOpenEditMenu?: boolean; + onChange?: (value: unknown) => void; } export const DocPropertyRow = ({ propertyInfo, defaultOpenEditMenu, + onChange, }: DocPropertyRowProps) => { const t = useI18n(); const docService = useService(DocService); @@ -123,8 +135,9 @@ export const DocPropertyRow = ({ throw new Error('only allow string value'); } docService.doc.record.setCustomProperty(propertyInfo.id, value); + onChange?.(value); }, - [docService, propertyInfo] + [docService, onChange, propertyInfo] ); const docId = docService.doc.id; @@ -214,6 +227,8 @@ interface DocWorkspacePropertiesTableBodyProps { className?: string; style?: React.CSSProperties; defaultOpen?: boolean; + onChange?: (property: DocCustomPropertyInfo, value: unknown) => void; + onPropertyAdded?: (property: DocCustomPropertyInfo) => void; } // 🏷️ Tags (⋅ xxx) (⋅ yyy) @@ -221,104 +236,121 @@ interface DocWorkspacePropertiesTableBodyProps { // + Add a property const DocWorkspacePropertiesTableBody = forwardRef< HTMLDivElement, - DocWorkspacePropertiesTableBodyProps & HTMLProps ->(({ className, style, defaultOpen, ...props }, ref) => { - const t = useI18n(); - const docsService = useService(DocsService); - const workbenchService = useService(WorkbenchService); - const viewService = useServiceOptional(ViewService); - const properties = useLiveData(docsService.propertyList.sortedProperties$); - const [propertyCollapsed, setPropertyCollapsed] = useState(true); + DocWorkspacePropertiesTableBodyProps +>( + ( + { className, style, defaultOpen, onChange, onPropertyAdded, ...props }, + ref + ) => { + const t = useI18n(); + const docsService = useService(DocsService); + const workbenchService = useService(WorkbenchService); + const viewService = useServiceOptional(ViewService); + const properties = useLiveData(docsService.propertyList.sortedProperties$); + const [propertyCollapsed, setPropertyCollapsed] = useState(true); - const [newPropertyId, setNewPropertyId] = useState(null); + const [newPropertyId, setNewPropertyId] = useState(null); - return ( - - - isCollapsed - ? hide === 1 - ? t['com.affine.page-properties.more-property.one']({ - count: hide.toString(), - }) - : t['com.affine.page-properties.more-property.more']({ - count: hide.toString(), - }) - : hide === 1 - ? t['com.affine.page-properties.hide-property.one']({ - count: hide.toString(), - }) - : t['com.affine.page-properties.hide-property.more']({ - count: hide.toString(), - }) - } + const handlePropertyAdded = useCallback( + (property: DocCustomPropertyInfo) => { + setNewPropertyId(property.id); + onPropertyAdded?.(property); + }, + [onPropertyAdded] + ); + + return ( + - {properties.map(property => ( - - ))} -
- - } - contentOptions={{ - onClick(e) { - e.stopPropagation(); - }, - }} - > - - - {viewService ? ( - - ) : null} -
-
-
- ); -}); + + + {viewService ? ( + + ) : null} +
+ + + ); + } +); DocWorkspacePropertiesTableBody.displayName = 'PagePropertiesTableBody'; const DocPropertiesTableInner = ({ defaultOpenProperty, + onPropertyAdded, + onPropertyChange, + onDatabasePropertyChange, }: DocPropertiesTableProps) => { const [expanded, setExpanded] = useState(!!defaultOpenProperty); return ( @@ -334,9 +366,12 @@ const DocPropertiesTableInner = ({ defaultOpen={ !defaultOpenProperty || defaultOpenProperty.type === 'workspace' } + onPropertyAdded={onPropertyAdded} + onChange={onPropertyChange} />
{ - return ; +export const DocPropertiesTable = (props: DocPropertiesTableProps) => { + return ; }; diff --git a/packages/frontend/core/src/components/doc-properties/tags-inline-editor.tsx b/packages/frontend/core/src/components/doc-properties/tags-inline-editor.tsx index 2517748d59..82e901c529 100644 --- a/packages/frontend/core/src/components/doc-properties/tags-inline-editor.tsx +++ b/packages/frontend/core/src/components/doc-properties/tags-inline-editor.tsx @@ -1,6 +1,7 @@ import type { TagLike } from '@affine/component/ui/tags'; import { TagsInlineEditor as TagsInlineEditorComponent } from '@affine/component/ui/tags'; import { TagService, useDeleteTagConfirmModal } from '@affine/core/modules/tag'; +import track from '@affine/track'; import { LiveData, useLiveData, @@ -38,6 +39,9 @@ export const TagsInlineEditor = ({ const onCreateTag = useCallback( (name: string, color: string) => { const newTag = tagService.tagList.createTag(name, color); + track.doc.inlineDocInfo.property.editProperty({ + type: 'tags', + }); return { id: newTag.id, value: newTag.value$.value, @@ -50,6 +54,9 @@ export const TagsInlineEditor = ({ const onSelectTag = useCallback( (tagId: string) => { tagService.tagList.tagByTagId$(tagId).value?.tag(pageId); + track.doc.inlineDocInfo.property.editProperty({ + type: 'tags', + }); }, [pageId, tagService.tagList] ); @@ -57,6 +64,9 @@ export const TagsInlineEditor = ({ const onDeselectTag = useCallback( (tagId: string) => { tagService.tagList.tagByTagId$(tagId).value?.untag(pageId); + track.doc.inlineDocInfo.property.editProperty({ + type: 'tags', + }); }, [pageId, tagService.tagList] ); @@ -68,6 +78,9 @@ export const TagsInlineEditor = ({ } else if (property === 'color') { tagService.tagList.tagByTagId$(id).value?.changeColor(value); } + track.doc.inlineDocInfo.property.editProperty({ + type: 'tags', + }); }, [tagService.tagList] ); @@ -77,6 +90,9 @@ export const TagsInlineEditor = ({ const onTagDelete = useAsyncCallback( async (id: string) => { await deleteTags([id]); + track.doc.inlineDocInfo.property.editProperty({ + type: 'tags', + }); }, [deleteTags] ); diff --git a/packages/frontend/core/src/desktop/dialogs/doc-info/info-modal.tsx b/packages/frontend/core/src/desktop/dialogs/doc-info/info-modal.tsx index b7ab1719fa..4a191b6577 100644 --- a/packages/frontend/core/src/desktop/dialogs/doc-info/info-modal.tsx +++ b/packages/frontend/core/src/desktop/dialogs/doc-info/info-modal.tsx @@ -8,16 +8,22 @@ import { import { CreatePropertyMenuItems } from '@affine/core/components/doc-properties/menu/create-doc-property'; import { DocPropertyRow } from '@affine/core/components/doc-properties/table'; import { DocDatabaseBacklinkInfo } from '@affine/core/modules/doc-info'; +import type { + DatabaseRow, + DatabaseValueCell, +} from '@affine/core/modules/doc-info/types'; import { DocsSearchService } from '@affine/core/modules/docs-search'; import { useI18n } from '@affine/i18n'; +import track from '@affine/track'; import { PlusIcon } from '@blocksuite/icons/rc'; import { + type DocCustomPropertyInfo, DocsService, LiveData, useLiveData, useServices, } from '@toeverything/infra'; -import { useMemo, useState } from 'react'; +import { useCallback, useMemo, useState } from 'react'; import * as styles from './info-modal.css'; import { LinksRow } from './links-row'; @@ -49,6 +55,23 @@ export const InfoTable = ({ ) ); + const onBacklinkPropertyChange = useCallback( + (_row: DatabaseRow, cell: DatabaseValueCell, _value: unknown) => { + track.$.docInfoPanel.databaseProperty.editProperty({ + type: cell.property.type$.value, + }); + }, + [] + ); + + const onPropertyAdded = useCallback((property: DocCustomPropertyInfo) => { + setNewPropertyId(property.id); + track.$.docInfoPanel.property.addProperty({ + type: property.type, + control: 'at menu', + }); + }, []); + return ( <> {backlinks && backlinks.length > 0 ? ( @@ -102,7 +125,7 @@ export const InfoTable = ({ /> ))} } + items={} contentOptions={{ onClick(e) { e.stopPropagation(); @@ -120,7 +143,7 @@ export const InfoTable = ({ - + ); }; diff --git a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/properties/index.tsx b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/properties/index.tsx index d846361771..ae2123de61 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/properties/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/properties/index.tsx @@ -4,7 +4,13 @@ import { DocPropertyManager } from '@affine/core/components/doc-properties/manag import { CreatePropertyMenuItems } from '@affine/core/components/doc-properties/menu/create-doc-property'; import { useWorkspaceInfo } from '@affine/core/components/hooks/use-workspace-info'; import { Trans, useI18n } from '@affine/i18n'; -import { FrameworkScope, type WorkspaceMetadata } from '@toeverything/infra'; +import track from '@affine/track'; +import { + type DocCustomPropertyInfo, + FrameworkScope, + type WorkspaceMetadata, +} from '@toeverything/infra'; +import { useCallback } from 'react'; import { useWorkspace } from '../../../../../components/hooks/use-workspace'; import * as styles from './styles.css'; @@ -12,10 +18,17 @@ import * as styles from './styles.css'; const WorkspaceSettingPropertiesMain = () => { const t = useI18n(); + const onCreated = useCallback((property: DocCustomPropertyInfo) => { + track.$.settingsPanel.workspace.addProperty({ + type: property.type, + control: 'at menu', + }); + }, []); + return (
- }> + }> diff --git a/packages/frontend/core/src/modules/doc-info/types.ts b/packages/frontend/core/src/modules/doc-info/types.ts index 9fa8b9325a..48a62758a1 100644 --- a/packages/frontend/core/src/modules/doc-info/types.ts +++ b/packages/frontend/core/src/modules/doc-info/types.ts @@ -32,4 +32,5 @@ export interface DatabaseCellRendererProps { rowId: string; cell: DatabaseValueCell; dataSource: DatabaseBlockDataSource; + onChange: (value: unknown) => void; } diff --git a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/checkbox.tsx b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/checkbox.tsx index 2892f4d86e..c3473e3762 100644 --- a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/checkbox.tsx +++ b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/checkbox.tsx @@ -8,6 +8,7 @@ export const CheckboxCell = ({ cell, rowId, dataSource, + onChange, }: DatabaseCellRendererProps) => { const value = useLiveData(cell.value$ as LiveData); return ( @@ -16,6 +17,7 @@ export const CheckboxCell = ({ value={value ? 'true' : 'false'} onChange={v => { dataSource.cellValueChange(rowId, cell.property.id, v === 'true'); + onChange?.(v === 'true'); }} /> ); diff --git a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/date.tsx b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/date.tsx index 02b5f65eb1..5a79cb9f39 100644 --- a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/date.tsx +++ b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/date.tsx @@ -20,6 +20,7 @@ export const DateCell = ({ cell, rowId, dataSource, + onChange, }: DatabaseCellRendererProps) => { const value = useLiveData( cell.value$ as LiveData @@ -34,6 +35,7 @@ export const DateCell = ({ cell.property.id, fromInternalDateString(v) ); + onChange?.(fromInternalDateString(v)); }} /> ); diff --git a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/link.tsx b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/link.tsx index 46cedacb7a..9db1365c11 100644 --- a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/link.tsx +++ b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/link.tsx @@ -21,6 +21,7 @@ export const LinkCell = ({ cell, dataSource, rowId, + onChange, }: DatabaseCellRendererProps) => { const isEmpty = useLiveData( cell.value$.map(value => typeof value !== 'string' || !value) @@ -35,7 +36,8 @@ export const LinkCell = ({ dataSource.cellValueChange(rowId, cell.id, tempValue.trim()); setEditing(false); setTempValue(tempValue.trim()); - }, [dataSource, rowId, cell.id, tempValue]); + onChange?.(tempValue.trim()); + }, [dataSource, rowId, cell.id, onChange, tempValue]); const handleOnChange: ChangeEventHandler = useCallback( e => { diff --git a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/number.tsx b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/number.tsx index 7415274bce..c183e87f44 100644 --- a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/number.tsx +++ b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/number.tsx @@ -7,6 +7,7 @@ export const NumberCell = ({ cell, rowId, dataSource, + onChange, }: DatabaseCellRendererProps) => { const value = useLiveData(cell.value$); return ( @@ -14,6 +15,7 @@ export const NumberCell = ({ value={value} onChange={v => { dataSource.cellValueChange(rowId, cell.property.id, v); + onChange?.(v); }} /> ); diff --git a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/progress.tsx b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/progress.tsx index a0c5a1db12..e705f65fbd 100644 --- a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/progress.tsx +++ b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/progress.tsx @@ -9,6 +9,7 @@ export const ProgressCell = ({ cell, dataSource, rowId, + onChange, }: DatabaseCellRendererProps) => { const value = useLiveData(cell.value$ as LiveData); const isEmpty = value === undefined; @@ -27,6 +28,7 @@ export const ProgressCell = ({ }} onBlur={() => { dataSource.cellValueChange(rowId, cell.id, localValue); + onChange?.(localValue); }} /> diff --git a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/rich-text.tsx b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/rich-text.tsx index a1a9da13be..63920ebe8b 100644 --- a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/rich-text.tsx +++ b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/rich-text.tsx @@ -40,6 +40,7 @@ const renderRichText = ({ export const RichTextCell = ({ cell, dataSource, + onChange, }: DatabaseCellRendererProps) => { const std = useBlockStdScope(dataSource.doc); const text = useLiveData(cell.value$ as LiveData); @@ -49,14 +50,19 @@ export const RichTextCell = ({ if (ref.current) { ref.current.innerHTML = ''; const richText = renderRichText({ doc: dataSource.doc, std, text }); + const listener = () => { + onChange(text); + }; if (richText) { + richText.addEventListener('change', listener); ref.current.append(richText); return () => { + richText.removeEventListener('change', listener); richText.remove(); }; } } return () => {}; - }, [dataSource.doc, std, text]); + }, [dataSource.doc, onChange, std, text]); return ; }; diff --git a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/select.tsx b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/select.tsx index d317dcaadd..b8c00fb608 100644 --- a/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/select.tsx +++ b/packages/frontend/core/src/modules/doc-info/views/database-properties/cells/select.tsx @@ -147,6 +147,7 @@ const BlocksuiteDatabaseSelector = ({ dataSource, rowId, multiple, + onChange, }: DatabaseCellRendererProps & { multiple: boolean }) => { const tagService = useService(TagService); const selectCell = cell as any as SingleSelectCell | MultiSelectCell; @@ -177,21 +178,24 @@ const BlocksuiteDatabaseSelector = ({ const onDeleteTag = useCallback( (tagId: string) => { adapter.deleteTag(selectCell, dataSource, tagId); + onChange?.(selectCell.value$.value); }, - [dataSource, selectCell] + [dataSource, selectCell, onChange] ); const onDeselectTag = useCallback( (tagId: string) => { adapter.deselectTag(rowId, selectCell, dataSource, tagId, multiple); + onChange?.(selectCell.value$.value); }, - [selectCell, dataSource, rowId, multiple] + [rowId, selectCell, dataSource, multiple, onChange] ); const onSelectTag = useCallback( (tagId: string) => { adapter.selectTag(rowId, selectCell, dataSource, tagId, multiple); + onChange?.(selectCell.value$.value); }, - [rowId, selectCell, dataSource, multiple] + [rowId, selectCell, dataSource, multiple, onChange] ); const tagColors = useMemo(() => { @@ -237,6 +241,7 @@ export const SelectCell = ({ cell, dataSource, rowId, + onChange, }: DatabaseCellRendererProps) => { const isEmpty = useLiveData( cell.value$.map(value => Array.isArray(value) && value.length === 0) @@ -248,6 +253,7 @@ export const SelectCell = ({ dataSource={dataSource} rowId={rowId} multiple={false} + onChange={onChange} /> ); @@ -257,6 +263,7 @@ export const MultiSelectCell = ({ cell, dataSource, rowId, + onChange, }: DatabaseCellRendererProps) => { const isEmpty = useLiveData( cell.value$.map(value => Array.isArray(value) && value.length === 0) @@ -268,6 +275,7 @@ export const MultiSelectCell = ({ dataSource={dataSource} rowId={rowId} multiple={true} + onChange={onChange} /> ); diff --git a/packages/frontend/core/src/modules/doc-info/views/database-properties/doc-database-backlink-info.tsx b/packages/frontend/core/src/modules/doc-info/views/database-properties/doc-database-backlink-info.tsx index b34e74da30..de4c3a45e4 100644 --- a/packages/frontend/core/src/modules/doc-info/views/database-properties/doc-database-backlink-info.tsx +++ b/packages/frontend/core/src/modules/doc-info/views/database-properties/doc-database-backlink-info.tsx @@ -46,10 +46,12 @@ const DatabaseBacklinkCell = ({ cell, dataSource, rowId, + onChange, }: { cell: DatabaseValueCell; dataSource: DatabaseBlockDataSource; rowId: string; + onChange: (value: unknown) => void; }) => { const cellType = useLiveData(cell.property.type$); @@ -67,7 +69,12 @@ const DatabaseBacklinkCell = ({ data-testid="database-backlink-cell" > - + ); }; @@ -79,9 +86,15 @@ const DatabaseBacklinkCell = ({ const DatabaseBacklinkRow = ({ defaultOpen = false, row$, + onChange, }: { defaultOpen: boolean; row$: Observable; + onChange?: ( + row: DatabaseRow, + cell: DatabaseValueCell, + value: unknown + ) => void; }) => { const row = useLiveData( useMemo(() => LiveData.from(row$, undefined), [row$]) @@ -132,6 +145,7 @@ const DatabaseBacklinkRow = ({ cell={cell} dataSource={row.dataSource} rowId={row.id} + onChange={value => onChange?.(row, cell, value)} /> ); })} @@ -142,11 +156,17 @@ const DatabaseBacklinkRow = ({ export const DocDatabaseBacklinkInfo = ({ defaultOpen = [], + onChange, }: { defaultOpen?: { databaseId: string; rowId: string; }[]; + onChange?: ( + row: DatabaseRow, + cell: DatabaseValueCell, + value: unknown + ) => void; }) => { const doc = useService(DocService).doc; const docDatabaseBacklinks = useService(DocDatabaseBacklinksService); @@ -173,6 +193,7 @@ export const DocDatabaseBacklinkInfo = ({ backlink.rowId === rowId )} row$={row$} + onChange={onChange} /> diff --git a/packages/frontend/track/src/events.ts b/packages/frontend/track/src/events.ts index 8dd7201fe0..a08a676145 100644 --- a/packages/frontend/track/src/events.ts +++ b/packages/frontend/track/src/events.ts @@ -46,7 +46,9 @@ type DocEvents = | 'openDocOptionsMenu' | 'openDocInfo' | 'copyBlockToLink' - | 'bookmark'; + | 'bookmark' + | 'editProperty' + | 'addProperty'; type EditorEvents = 'bold' | 'italic' | 'underline' | 'strikeThrough'; // END SECTION @@ -148,10 +150,12 @@ const PageEvents = { }, docInfoPanel: { $: ['open'], + property: ['editProperty', 'addProperty'], + databaseProperty: ['editProperty'], }, settingsPanel: { menu: ['openSettings'], - workspace: ['viewPlans', 'export'], + workspace: ['viewPlans', 'export', 'addProperty'], profileAndBadge: ['viewPlans'], accountUsage: ['viewPlans'], accountSettings: ['uploadAvatar', 'removeAvatar', 'updateUserName'], @@ -277,6 +281,11 @@ const PageEvents = { }, inlineDocInfo: { $: ['toggle'], + property: ['editProperty', 'addProperty'], + databaseProperty: ['editProperty'], + }, + sidepanel: { + property: ['addProperty'], }, }, // remove when type added @@ -413,6 +422,8 @@ export type EventArgs = { copyBlockToLink: { type: string; }; + editProperty: { type: string }; + addProperty: { type: string; control: 'at menu' | 'property list' }; }; // for type checking