refactor(editor): remove database-service (#9769)

close: BS-2426
This commit is contained in:
zzj3720
2025-01-18 05:36:15 +00:00
parent ad814a0f4f
commit 95c0f59d96
30 changed files with 448 additions and 427 deletions
@@ -1,4 +1,8 @@
import type { DatabaseBlockModel } from '@blocksuite/affine-model';
import type {
Column,
ColumnUpdater,
DatabaseBlockModel,
} from '@blocksuite/affine-model';
import { FeatureFlagService } from '@blocksuite/affine-shared/services';
import {
insertPositionToIndex,
@@ -19,7 +23,6 @@ import {
import { propertyPresets } from '@blocksuite/data-view/property-presets';
import { IS_MOBILE } from '@blocksuite/global/env';
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
import { assertExists } from '@blocksuite/global/utils';
import { type BlockModel, nanoid, Text } from '@blocksuite/store';
import { computed, type ReadonlySignal } from '@preact/signals-core';
@@ -29,7 +32,6 @@ import {
databaseBlockPropertyList,
databasePropertyConverts,
} from './properties/index.js';
import { titlePropertyModelConfig } from './properties/title/define.js';
import {
addProperty,
applyCellsUpdate,
@@ -38,7 +40,6 @@ import {
deleteRows,
deleteView,
duplicateView,
findPropertyIndex,
getCell,
getProperty,
moveViewTo,
@@ -69,7 +70,17 @@ export class DatabaseBlockDataSource extends DataSourceBase {
});
properties$: ReadonlySignal<string[]> = computed(() => {
return this._model.columns$.value.map(column => column.id);
const fixedPropertiesSet = new Set(this.fixedProperties$.value);
const properties: string[] = [];
this._model.columns$.value.forEach(column => {
if (fixedPropertiesSet.has(column.type)) {
fixedPropertiesSet.delete(column.type);
}
properties.push(column.id);
});
const result = [...fixedPropertiesSet, ...properties];
return result;
});
readonly$: ReadonlySignal<boolean> = computed(() => {
@@ -98,9 +109,15 @@ export class DatabaseBlockDataSource extends DataSourceBase {
return this._model.doc;
}
get propertyMetas(): PropertyMetaConfig<any, any, any>[] {
allPropertyMetas$ = computed<PropertyMetaConfig<any, any, any>[]>(() => {
return databaseBlockPropertyList;
}
});
propertyMetas$ = computed<PropertyMetaConfig[]>(() => {
return this.allPropertyMetas$.value.filter(
v => !v.config.fixed && !v.config.hide
);
});
constructor(model: DatabaseBlockModel) {
super();
@@ -147,13 +164,6 @@ export class DatabaseBlockDataSource extends DataSourceBase {
newValue: value,
});
}
if (type === 'title' && newValue instanceof Text) {
this._model.doc.transact(() => {
this._model.text?.clear();
this._model.text?.join(newValue);
});
return;
}
if (this._model.columns$.value.some(v => v.id === propertyId)) {
updateCell(this._model, rowId, {
columnId: propertyId,
@@ -193,34 +203,108 @@ export class DatabaseBlockDataSource extends DataSourceBase {
return result;
}
propertyDataGet(propertyId: string): Record<string, unknown> {
return (
this._model.columns$.value.find(v => v.id === propertyId)?.data ?? {}
protected override getNormalPropertyAndIndex(propertyId: string):
| {
column: Column<Record<string, unknown>>;
index: number;
}
| undefined {
const index = this._model.columns$.value.findIndex(
v => v.id === propertyId
);
if (index >= 0) {
const column = this._model.columns$.value[index];
if (!column) {
return;
}
return {
column,
index,
};
}
return;
}
private getPropertyAndIndex(propertyId: string):
| {
column: Column<Record<string, unknown>>;
index: number;
}
| undefined {
const result = this.getNormalPropertyAndIndex(propertyId);
if (result) {
return result;
}
if (this.isFixedProperty(propertyId)) {
const meta = this.propertyMetaGet(propertyId);
const defaultData = meta.config.fixed?.defaultData ?? {};
return {
column: {
data: defaultData,
id: propertyId,
type: propertyId,
name: meta.config.name,
},
index: -1,
};
}
return undefined;
}
private updateProperty(id: string, updater: ColumnUpdater) {
const result = this.getPropertyAndIndex(id);
if (!result) {
return;
}
const { column: prevColumn, index } = result;
this._model.doc.transact(() => {
if (index >= 0) {
const result = updater(prevColumn);
this._model.columns[index] = { ...prevColumn, ...result };
} else {
const result = updater(prevColumn);
this._model.columns = [
...this._model.columns,
{ ...prevColumn, ...result },
];
}
});
return id;
}
propertyDataGet(propertyId: string): Record<string, unknown> {
const result = this.getPropertyAndIndex(propertyId);
if (!result) {
return {};
}
return result.column.data;
}
propertyDataSet(propertyId: string, data: Record<string, unknown>): void {
this._runCapture();
updateProperty(this._model, propertyId, () => ({ data }));
this.updateProperty(propertyId, () => ({ data }));
applyPropertyUpdate(this._model);
}
propertyDataTypeGet(propertyId: string): TypeInstance | undefined {
const data = this._model.columns$.value.find(v => v.id === propertyId);
if (!data) {
const result = this.getPropertyAndIndex(propertyId);
if (!result) {
return;
}
const meta = this.propertyMetaGet(data.type);
const { column } = result;
const meta = this.propertyMetaGet(column.type);
return meta.config.type({
data: data.data,
data: column.data,
dataSource: this,
});
}
propertyDelete(id: string): void {
if (this.isFixedProperty(id)) {
return;
}
this.doc.captureSync();
const index = findPropertyIndex(this._model, id);
const index = this._model.columns.findIndex(v => v.id === id);
if (index < 0) return;
this.doc.transact(() => {
@@ -228,10 +312,15 @@ export class DatabaseBlockDataSource extends DataSourceBase {
});
}
propertyDuplicate(propertyId: string): string {
propertyDuplicate(propertyId: string): string | undefined {
if (this.isFixedProperty(propertyId)) {
return;
}
this.doc.captureSync();
const currentSchema = getProperty(this._model, propertyId);
assertExists(currentSchema);
if (!currentSchema) {
return;
}
const { id: copyId, ...nonIdProps } = currentSchema;
const names = new Set(this._model.columns$.value.map(v => v.name));
let index = 1;
@@ -267,14 +356,16 @@ export class DatabaseBlockDataSource extends DataSourceBase {
if (propertyId === 'type') {
return 'Block Type';
}
return (
this._model.columns$.value.find(v => v.id === propertyId)?.name ?? ''
);
const result = this.getPropertyAndIndex(propertyId);
if (!result) {
return '';
}
return result.column.name;
}
propertyNameSet(propertyId: string, name: string): void {
this.doc.captureSync();
updateProperty(this._model, propertyId, () => ({ name }));
this.updateProperty(propertyId, () => ({ name }));
applyPropertyUpdate(this._model);
}
@@ -287,12 +378,17 @@ export class DatabaseBlockDataSource extends DataSourceBase {
if (propertyId === 'type') {
return 'image';
}
return (
this._model.columns$.value.find(v => v.id === propertyId)?.type ?? ''
);
const result = this.getPropertyAndIndex(propertyId);
if (!result) {
return '';
}
return result.column.type;
}
propertyTypeSet(propertyId: string, toType: string): void {
if (this.isFixedProperty(propertyId)) {
return;
}
const currentType = this.propertyTypeGet(propertyId);
const currentData = this.propertyDataGet(propertyId);
const rows = this.rows$.value;
@@ -409,77 +505,54 @@ export class DatabaseBlockDataSource extends DataSourceBase {
}
}
export const databaseViewAddView = (
model: DatabaseBlockModel,
viewType: string
) => {
const dataSource = new DatabaseBlockDataSource(model);
dataSource.viewManager.viewAdd(viewType);
};
export const databaseViewInitEmpty = (
model: DatabaseBlockModel,
viewType: string
) => {
addProperty(
model,
'start',
titlePropertyModelConfig.create(titlePropertyModelConfig.config.name)
);
databaseViewAddView(model, viewType);
};
export const databaseViewInitConvert = (
model: DatabaseBlockModel,
viewType: string
) => {
addProperty(
model,
'end',
propertyPresets.multiSelectPropertyConfig.create('Tag', { options: [] })
);
databaseViewInitEmpty(model, viewType);
};
export const databaseViewInitTemplate = (
model: DatabaseBlockModel,
datasource: DatabaseBlockDataSource,
viewType: string
) => {
const ids = [nanoid(), nanoid(), nanoid()] as const;
const statusId = addProperty(
model,
const titleId = datasource.properties$.value[0];
const statusId = datasource.propertyAdd(
'end',
propertyPresets.selectPropertyConfig.create('Status', {
options: [
{
id: ids[0],
color: getTagColor(),
value: 'TODO',
},
{
id: ids[1],
color: getTagColor(),
value: 'In Progress',
},
{
id: ids[2],
color: getTagColor(),
value: 'Done',
},
],
})
propertyPresets.selectPropertyConfig.type
);
for (let i = 0; i < 4; i++) {
const rowId = model.doc.addBlock(
'affine:paragraph',
datasource.propertyNameSet(statusId, 'Status');
datasource.propertyDataSet(statusId, {
options: [
{
text: new Text(`Task ${i + 1}`),
id: ids[0],
color: getTagColor(),
value: 'TODO',
},
model.id
);
updateCell(model, rowId, {
columnId: statusId,
value: ids[i],
});
{
id: ids[1],
color: getTagColor(),
value: 'In Progress',
},
{
id: ids[2],
color: getTagColor(),
value: 'Done',
},
],
});
for (let i = 0; i < 4; i++) {
const rowId = datasource.rowAdd('end');
if (titleId) {
const text = datasource.cellValueGet(rowId, titleId);
if (text instanceof Text) {
text.replace(0, text.length, `Task ${i + 1}`);
}
}
datasource.cellValueChange(rowId, statusId, ids[i]);
// const rowId = model.doc.addBlock(
// 'affine:paragraph',
// {
// text: new Text(`Task ${i + 1}`),
// },
// model.id
// );
}
databaseViewInitEmpty(model, viewType);
datasource.viewManager.viewAdd(viewType);
};
export const convertToDatabase = (host: EditorHost, viewType: string) => {
const [_, ctx] = host.std.command
@@ -511,8 +584,8 @@ export const convertToDatabase = (host: EditorHost, viewType: string) => {
if (!databaseModel) {
return;
}
databaseViewInitConvert(databaseModel, viewType);
applyPropertyUpdate(databaseModel);
const datasource = new DatabaseBlockDataSource(databaseModel);
datasource.viewManager.viewAdd(viewType);
host.doc.moveBlocks(selectedModels, databaseModel);
const selectionManager = host.selection;