mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-15 05:37:32 +00:00
feat(editor): add grouping support for member property of the database block (#12243)
close: BS-3433 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced advanced group-by configurations for database blocks with user membership support. - Added a React hook for fetching and displaying user information in member-related components. - Enabled dynamic user and membership data types in database properties. - **Improvements** - Replaced context-based service access with a dependency injection system for shared services and state. - Enhanced type safety and consistency across group-by UI components and data handling. - Centralized group data management with a new Group class and refined group trait logic. - **Bug Fixes** - Improved reliability and consistency in retrieving and rendering user and group information. - **Style** - Removed obsolete member selection styles for cleaner UI code. - **Chores** - Registered external group-by configurations via dependency injection. - Refactored internal APIs for data sources, views, and group-by matchers to use service-based patterns. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -1,7 +1,4 @@
|
||||
import { createContextKey } from '@blocksuite/data-view';
|
||||
import { createIdentifier } from '@blocksuite/global/di';
|
||||
import type { EditorHost } from '@blocksuite/std';
|
||||
|
||||
export const HostContextKey = createContextKey<EditorHost | undefined>(
|
||||
'editor-host',
|
||||
undefined
|
||||
);
|
||||
export const EditorHostKey = createIdentifier<EditorHost>('editor-host');
|
||||
|
||||
@@ -57,6 +57,9 @@ type SpacialProperty = {
|
||||
valueGet: (rowId: string, propertyId: string) => unknown;
|
||||
};
|
||||
export class DatabaseBlockDataSource extends DataSourceBase {
|
||||
override get parentProvider() {
|
||||
return this._model.store.provider;
|
||||
}
|
||||
spacialProperties: Record<string, SpacialProperty> = {
|
||||
'created-time': {
|
||||
valueSet: () => {},
|
||||
@@ -186,9 +189,13 @@ export class DatabaseBlockDataSource extends DataSourceBase {
|
||||
);
|
||||
});
|
||||
|
||||
constructor(model: DatabaseBlockModel) {
|
||||
constructor(
|
||||
model: DatabaseBlockModel,
|
||||
init?: (dataSource: DatabaseBlockDataSource) => void
|
||||
) {
|
||||
super();
|
||||
this._model = model;
|
||||
this._model = model; // ensure invariants first
|
||||
init?.(this); // then allow external initialisation
|
||||
}
|
||||
|
||||
private _runCapture() {
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
type DataViewWidget,
|
||||
type DataViewWidgetProps,
|
||||
defineUniComponent,
|
||||
ExternalGroupByConfigProvider,
|
||||
renderUniLit,
|
||||
type SingleView,
|
||||
uniMap,
|
||||
@@ -47,7 +48,7 @@ import { css, html, nothing, unsafeCSS } from 'lit';
|
||||
|
||||
import { popSideDetail } from './components/layout.js';
|
||||
import { DatabaseConfigExtension } from './config.js';
|
||||
import { HostContextKey } from './context/host-context.js';
|
||||
import { EditorHostKey } from './context/host-context.js';
|
||||
import { DatabaseBlockDataSource } from './data-source.js';
|
||||
import { BlockRenderer } from './detail-panel/block-renderer.js';
|
||||
import { NoteRenderer } from './detail-panel/note-renderer.js';
|
||||
@@ -333,8 +334,17 @@ export class DatabaseBlockComponent extends CaptionedBlockComponent<DatabaseBloc
|
||||
|
||||
get dataSource(): DatabaseBlockDataSource {
|
||||
if (!this._dataSource) {
|
||||
this._dataSource = new DatabaseBlockDataSource(this.model);
|
||||
this._dataSource.contextSet(HostContextKey, this.host);
|
||||
this._dataSource = new DatabaseBlockDataSource(this.model, dataSource => {
|
||||
dataSource.serviceSet(EditorHostKey, this.host);
|
||||
this.std.provider
|
||||
.getAll(ExternalGroupByConfigProvider)
|
||||
.forEach(config => {
|
||||
dataSource.serviceSet(
|
||||
ExternalGroupByConfigProvider(config.name),
|
||||
config
|
||||
);
|
||||
});
|
||||
});
|
||||
const id = currentViewStorage.getCurrentView(this.model.id);
|
||||
if (id && this.dataSource.viewManager.viewGet(id)) {
|
||||
this.dataSource.viewManager.setCurrentView(id);
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { SlashMenuConfigExtension } from '@blocksuite/affine-widget-slash-menu';
|
||||
import { BlockViewExtension, FlavourExtension } from '@blocksuite/std';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
import { literal } from 'lit/static-html.js';
|
||||
|
||||
import { DatabaseBlockAdapterExtensions } from './adapters/extension.js';
|
||||
import { databaseSlashMenuConfig } from './configs/slash-menu.js';
|
||||
|
||||
export const DatabaseBlockSpec: ExtensionType[] = [
|
||||
FlavourExtension('affine:database'),
|
||||
BlockViewExtension('affine:database', literal`affine-database`),
|
||||
DatabaseBlockAdapterExtensions,
|
||||
SlashMenuConfigExtension('affine:database', databaseSlashMenuConfig),
|
||||
].flat();
|
||||
@@ -4,7 +4,6 @@ export * from './config';
|
||||
export * from './context';
|
||||
export * from './data-source';
|
||||
export * from './database-block';
|
||||
export * from './database-spec';
|
||||
export * from './detail-panel/block-renderer';
|
||||
export * from './detail-panel/note-renderer';
|
||||
export * from './properties';
|
||||
|
||||
@@ -15,7 +15,7 @@ import { computed } from '@preact/signals-core';
|
||||
import { html, nothing, type PropertyValues } from 'lit';
|
||||
import { createRef, ref } from 'lit/directives/ref.js';
|
||||
|
||||
import { HostContextKey } from '../../context/host-context.js';
|
||||
import { EditorHostKey } from '../../context/host-context.js';
|
||||
import {
|
||||
inlineLinkNodeStyle,
|
||||
linkCellStyle,
|
||||
@@ -88,7 +88,7 @@ export class LinkCell extends BaseCellRenderer<string, string> {
|
||||
};
|
||||
|
||||
get std() {
|
||||
const host = this.view.contextGet(HostContextKey);
|
||||
const host = this.view.serviceGet(EditorHostKey);
|
||||
return host?.std;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import { computed, effect, signal } from '@preact/signals-core';
|
||||
import { ref } from 'lit/directives/ref.js';
|
||||
import { html } from 'lit/static-html.js';
|
||||
|
||||
import { HostContextKey } from '../../context/host-context.js';
|
||||
import { EditorHostKey } from '../../context/host-context.js';
|
||||
import type { DatabaseBlockComponent } from '../../database-block.js';
|
||||
import {
|
||||
richTextCellStyle,
|
||||
@@ -87,7 +87,7 @@ export class RichTextCell extends BaseCellRenderer<Text, string> {
|
||||
|
||||
get inlineManager() {
|
||||
return this.view
|
||||
.contextGet(HostContextKey)
|
||||
.serviceGet(EditorHostKey)
|
||||
?.std.get(DefaultInlineManagerExtension.identifier);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ export class RichTextCell extends BaseCellRenderer<Text, string> {
|
||||
}
|
||||
|
||||
get host() {
|
||||
return this.view.contextGet(HostContextKey);
|
||||
return this.view.serviceGet(EditorHostKey);
|
||||
}
|
||||
|
||||
private readonly richText$ = signal<RichText>();
|
||||
@@ -398,7 +398,7 @@ export class RichTextCell extends BaseCellRenderer<Text, string> {
|
||||
}
|
||||
|
||||
private get std() {
|
||||
return this.view.contextGet(HostContextKey)?.std;
|
||||
return this.view.serviceGet(EditorHostKey)?.std;
|
||||
}
|
||||
|
||||
insertDelta = (delta: DeltaInsert<AffineTextAttributes>) => {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Text } from '@blocksuite/store';
|
||||
import * as Y from 'yjs';
|
||||
import zod from 'zod';
|
||||
|
||||
import { HostContextKey } from '../../context/host-context.js';
|
||||
import { EditorHostKey } from '../../context/host-context.js';
|
||||
import { isLinkedDoc } from '../../utils/title-doc.js';
|
||||
|
||||
export const richTextColumnType = propertyType('rich-text');
|
||||
@@ -43,7 +43,7 @@ export const richTextPropertyModelConfig = richTextColumnType.modelConfig({
|
||||
},
|
||||
toJson: ({ value, dataSource }) => {
|
||||
if (!value) return null;
|
||||
const host = dataSource.contextGet(HostContextKey);
|
||||
const host = dataSource.serviceGet(EditorHostKey);
|
||||
if (host) {
|
||||
const collection = host.std.workspace;
|
||||
const yText = toYText(value);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Text } from '@blocksuite/store';
|
||||
import { Doc } from 'yjs';
|
||||
import zod from 'zod';
|
||||
|
||||
import { HostContextKey } from '../../context/host-context.js';
|
||||
import { EditorHostKey } from '../../context/host-context.js';
|
||||
import { isLinkedDoc } from '../../utils/title-doc.js';
|
||||
|
||||
export const titleColumnType = propertyType('title');
|
||||
@@ -28,7 +28,7 @@ export const titlePropertyModelConfig = titleColumnType.modelConfig({
|
||||
},
|
||||
toJson: ({ value, dataSource }) => {
|
||||
if (!value) return '';
|
||||
const host = dataSource.contextGet(HostContextKey);
|
||||
const host = dataSource.serviceGet(EditorHostKey);
|
||||
if (host) {
|
||||
const collection = host.std.workspace;
|
||||
const deltas = value.deltas$.value;
|
||||
|
||||
@@ -17,7 +17,7 @@ import { property } from 'lit/decorators.js';
|
||||
import { createRef, ref } from 'lit/directives/ref.js';
|
||||
import { html } from 'lit/static-html.js';
|
||||
|
||||
import { HostContextKey } from '../../context/host-context.js';
|
||||
import { EditorHostKey } from '../../context/host-context.js';
|
||||
import type { DatabaseBlockComponent } from '../../database-block.js';
|
||||
import { getSingleDocIdFromText } from '../../utils/title-doc.js';
|
||||
import {
|
||||
@@ -32,7 +32,7 @@ export class HeaderAreaTextCell extends BaseCellRenderer<Text, string> {
|
||||
docId$ = signal<string>();
|
||||
|
||||
get host() {
|
||||
return this.view.contextGet(HostContextKey);
|
||||
return this.view.serviceGet(EditorHostKey);
|
||||
}
|
||||
|
||||
get inlineEditor() {
|
||||
@@ -50,7 +50,7 @@ export class HeaderAreaTextCell extends BaseCellRenderer<Text, string> {
|
||||
}
|
||||
|
||||
get std() {
|
||||
return this.view.contextGet(HostContextKey)?.std;
|
||||
return this.view.serviceGet(EditorHostKey)?.std;
|
||||
}
|
||||
|
||||
private readonly _onCopy = (e: ClipboardEvent) => {
|
||||
|
||||
Reference in New Issue
Block a user