import type { Column } from '@blocksuite/affine-model'; import { arrayMove, insertPositionToIndex, type InsertToPosition, } from '@blocksuite/affine-shared/utils'; import type { DataViewDataType } from '@blocksuite/data-view'; import { BlockModel, BlockSchemaExtension, defineBlockSchema, } from '@blocksuite/store'; type Props = { title: string; views: DataViewDataType[]; columns: Column[]; cells: Record>; }; export class DataViewBlockModel extends BlockModel { constructor() { super(); } applyViewsUpdate() { this.doc.updateBlock(this, { views: this.views, }); } deleteView(id: string) { this.doc.captureSync(); this.doc.transact(() => { this.views = this.views.filter(v => v.id !== id); }); } duplicateView(id: string): string { const newId = this.doc.workspace.idGenerator(); this.doc.transact(() => { const index = this.views.findIndex(v => v.id === id); const view = this.views[index]; if (view) { this.views.splice( index + 1, 0, JSON.parse(JSON.stringify({ ...view, id: newId })) ); } }); return newId; } moveViewTo(id: string, position: InsertToPosition) { this.doc.transact(() => { this.views = arrayMove( this.views, v => v.id === id, arr => insertPositionToIndex(position, arr) ); }); this.applyViewsUpdate(); } updateView( id: string, update: (data: DataViewDataType) => Partial ) { this.doc.transact(() => { this.views = this.views.map(v => { if (v.id !== id) { return v; } return { ...v, ...(update(v) as DataViewDataType) }; }); }); this.applyViewsUpdate(); } } export const DataViewBlockSchema = defineBlockSchema({ flavour: 'affine:data-view', props: (): Props => ({ views: [], title: '', columns: [], cells: {}, }), metadata: { role: 'hub', version: 1, parent: ['affine:note'], children: ['affine:paragraph', 'affine:list'], }, toModel: () => { return new DataViewBlockModel(); }, }); export const DataViewBlockSchemaExtension = BlockSchemaExtension(DataViewBlockSchema);