Skip to content

Commit

Permalink
fix(sheet): support bind delete & date type source (#4487)
Browse files Browse the repository at this point in the history
  • Loading branch information
VicKun4937 authored Jan 16, 2025
1 parent 5e6cd64 commit 4aff7f7
Show file tree
Hide file tree
Showing 9 changed files with 273 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
* limitations under the License.
*/

import type { ICellBindingNode, ICellBindingNodeParam } from '../types';
import { Disposable, generateRandomId } from '@univerjs/core';
import type { IMutationInfo } from '@univerjs/core';
import type { ICellBindingJSON, ICellBindingNode, ICellBindingNodeParam } from '../types';
import { Disposable, generateRandomId, Inject, IUniverInstanceService, Range } from '@univerjs/core';

import { ClearSelectionAllCommand, ClearSelectionContentCommand, getSheetCommandTarget, SheetInterceptorService, SheetsSelectionsService } from '@univerjs/sheets';
import { Subject } from 'rxjs';
import { SheetBindingModel } from '../model/binding-model';
import { BindingSourceChangeTypeEnum } from '../types';
Expand All @@ -32,12 +35,47 @@ interface IBindingNodeInfo {
export class SheetsBindingManager extends Disposable {
modelMap: Map<string, Map<string, SheetBindingModel>> = new Map();

private _cellBindInfoUpdate$ = new Subject<IBindingNodeInfo & { changeType: BindingSourceChangeTypeEnum;oldSourceId?: string }>();
private _cellBindInfoUpdate$ = new Subject<IBindingNodeInfo & { changeType: BindingSourceChangeTypeEnum; oldSourceId?: string }>();
cellBindInfoUpdate$ = this._cellBindInfoUpdate$.asObservable();

constructor(
@IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService,
@Inject(SheetInterceptorService) private readonly _sheetInterceptorService: SheetInterceptorService,
@Inject(SheetsSelectionsService) private readonly _sheetsSelectionsService: SheetsSelectionsService
) {
super();
this._initRemoveCommand();
}

private _initRemoveCommand() {
this.disposeWithMe(
this._sheetInterceptorService.interceptCommand({
getMutations: (command) => {
const redos: IMutationInfo[] = [];
const undos: IMutationInfo[] = [];
const selections = this._sheetsSelectionsService.getCurrentSelections();
const target = getSheetCommandTarget(this._univerInstanceService);
if (!target || !selections || selections.length === 0) {
return {
redos: [],
undos: [],
};
}
const { unitId, subUnitId } = target;
if (command.id === ClearSelectionContentCommand.id || command.id === ClearSelectionAllCommand.id) {
selections.forEach(({ range }) => {
Range.foreach(range, (row, column) => {
const node = this.getBindingNode(unitId, subUnitId, row, column);
if (node) {
this.removeBindingNode(unitId, subUnitId, row, column);
}
});
});
}
return { redos, undos };
},
})
);
}

getBindingModelBySourceId(sourceId: string) {
Expand Down Expand Up @@ -127,13 +165,31 @@ export class SheetsBindingManager extends Disposable {
return undefined;
}

createModel(unitId: string, subunitId: string, json?: any): SheetBindingModel {
createModel(unitId: string, subunitId: string, json?: ICellBindingNode[]): SheetBindingModel {
const model = new SheetBindingModel(json);
this.addModel(unitId, subunitId, model);
return model;
}

toJSON(unitId: string) {
const rs: ICellBindingJSON = {};
const subMap = this.modelMap.get(unitId);
if (subMap) {
subMap.forEach((model, subunitId) => {
rs[subunitId] = model.toJSON();
});
}
return rs;
}

fromJSON(unitId: string, json: ICellBindingJSON) {
Object.entries(json).forEach(([subunitId, nodes]) => {
this.createModel(unitId, subunitId, nodes);
});
}

override dispose(): void {
this.modelMap.clear();
this._cellBindInfoUpdate$.complete();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type { ISourceEvent } from '../types';
import type { ISourceEvent, ISourceJSON } from '../types';
import { Disposable, generateRandomId } from '@univerjs/core';
import { Subject } from 'rxjs';
import { ListSourceModel, ObjectSourceModel, SourceModelBase } from '../model/source-model';
Expand Down Expand Up @@ -85,4 +85,39 @@ export class SheetsSourceManager extends Disposable {
this._sourceDataUpdate$.next({ ...source.getSourceInfo(), unitId, changeType: BindingSourceChangeTypeEnum.Remove });
}
}

toJSON(unitId: string): ISourceJSON[] {
const sourceList: ISourceJSON[] = [];
const unitMap = this._getUnitMap(unitId);
if (unitMap) {
for (const source of unitMap.values()) {
sourceList.push(source.toJSON());
}
}
return sourceList;
}

fromJSON(unitId: string, sources: ISourceJSON[]): void {
const unitMap = this._ensureUnitMap(unitId);
for (const source of sources) {
let model: SourceModelBase;
switch (source.type) {
case DataBindingNodeTypeEnum.List:
model = new ListSourceModel(source.id);
break;
case DataBindingNodeTypeEnum.Object:
model = new ObjectSourceModel(source.id);
break;
default:
throw new Error(`Invalid source type: ${source.type}`);
}
model.fromJSON(source);
unitMap.set(source.id, model);
}
}

override dispose(): void {
this._sourceDataUpdate$.complete();
this.sourceMap.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@
* limitations under the License.
*/

import type { DataBindingNodeTypeEnum, SourceModelBase } from '@univerjs/sheets-source-binding';
import { SheetsSourceBindService } from '@univerjs/sheets-source-binding';
import type { DataBindingNodeTypeEnum, ISourceBindingInfo, SourceModelBase } from '@univerjs/sheets-source-binding';
import { SheetsSourceBindService, SheetsSourceManager } from '@univerjs/sheets-source-binding';
import { FWorkbook } from '@univerjs/sheets/facade';

export interface IFWorkbookSourceBindingMixin {
/**
* Create a source model with the specified type.
* @param {DataBindingNodeTypeEnum} type The source type.
* @param {boolean} [isListObject] Whether the source is a list object.
* @param {string} [id] The source id.
* @returns {SourceModelBase} The source data of sheet.
*/
createSource(type: DataBindingNodeTypeEnum, isListObject?: boolean): SourceModelBase;
createSource(type: DataBindingNodeTypeEnum, isListObject?: boolean, id?: string | undefined): SourceModelBase;
/**
* Switch to path mode.In this mode, the path will show in cell.
*/
Expand All @@ -39,13 +40,37 @@ export interface IFWorkbookSourceBindingMixin {
* @param {string} sourceId The source id.
*/
getSource(sourceId: string): SourceModelBase | undefined;
/**
* Set the source data by the specified source id.
* @param {string} sourceId - The source id which you want to set data.
* @param data - The source data. If the source is a list object, the data should be an array of objects.
* If the isListObject is false, the data should look like below:
* ```typescript
* {
* fields: ['name', 'age'],
* records: [['Tom', 18], ['Jerry', 20]]
* }
* ```
* If the isListObject is true, the data should look like below:
* ```typescript
* {
* fields: ['name', 'age'],
* records: [{name: 'Tom', age: 18}, {name: 'Jerry', age: 20}]
* }
* ```
*/
setSourceData(sourceId: string, data: any): void;

loadSourceBindingPathInfo(obj: ISourceBindingInfo): void;

saveSourceBindingPathInfo(): ISourceBindingInfo;
}

export class FWorkbookSourceBinding extends FWorkbook implements IFWorkbookSourceBindingMixin {
override createSource(type: DataBindingNodeTypeEnum, isListObject?: boolean): SourceModelBase {
override createSource(type: DataBindingNodeTypeEnum, isListObject?: boolean, id?: string | undefined): SourceModelBase {
const injector = this._injector;
const sheetsSourceBindService = injector.get(SheetsSourceBindService);
return sheetsSourceBindService.createSource(this.getId(), type, isListObject);
return sheetsSourceBindService.createSource(this.getId(), type, isListObject, id);
}

override getSource(sourceId: string): SourceModelBase | undefined {
Expand All @@ -54,6 +79,12 @@ export class FWorkbookSourceBinding extends FWorkbook implements IFWorkbookSourc
return sheetsSourceBindService.getSource(this.getId(), sourceId);
}

override setSourceData(sourceId: string, data: any): void {
const injector = this._injector;
const sheetsSourceManager = injector.get(SheetsSourceManager);
sheetsSourceManager.updateSourceData(this.getId(), sourceId, data);
}

override usePathMode(): void {
const injector = this._injector;
const sheetsSourceBindService = injector.get(SheetsSourceBindService);
Expand All @@ -65,6 +96,18 @@ export class FWorkbookSourceBinding extends FWorkbook implements IFWorkbookSourc
const sheetsSourceBindService = injector.get(SheetsSourceBindService);
sheetsSourceBindService.useValueMode();
}

override loadSourceBindingPathInfo(obj: ISourceBindingInfo): void {
const injector = this._injector;
const sheetsSourceBindService = injector.get(SheetsSourceBindService);
sheetsSourceBindService.loadSourceBindingPathInfo(this.getId(), obj);
}

override saveSourceBindingPathInfo(): ISourceBindingInfo {
const injector = this._injector;
const sheetsSourceBindService = injector.get(SheetsSourceBindService);
return sheetsSourceBindService.getSourceBindingPathInfo(this.getId());
}
}

FWorkbook.extend(FWorkbookSourceBinding);
Expand Down
3 changes: 2 additions & 1 deletion packages-experimental/sheets-source-binding/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export { SourceModelBase } from './model/source-model';
export { UniverSheetsBindingSourcePlugin } from './plugin';
export { BindModeEnum, DataBindingNodeTypeEnum } from './types';
export { SheetsSourceBindService } from './services/source-binding-service';
export type { ICellBindingNode, ICellBindingNodeParam } from './types';
export { SheetsSourceManager } from './controllers/source-manager';
export type { ICellBindingNode, ICellBindingNodeParam, ISourceBindingInfo } from './types';
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ export class SheetBindingModel {

private _sourceIdMap: Map<string, string[]> = new Map();

constructor(json?: any) {
constructor(json?: ICellBindingNode[]) {
if (json) {
this._init(json);
}
}

_init(json: any): void {
this.fromJSON();
_init(json: ICellBindingNode[]): void {
this.fromJSON(json);
}

getBindingNodesBySourceId(sourceId: string): ICellBindingNode[] | undefined {
Expand Down Expand Up @@ -86,12 +86,14 @@ export class SheetBindingModel {
return this._nodeMap.get(nodeId);
}

fromJSON(): void {

fromJSON(nodes: ICellBindingNode[]): void {
nodes.forEach((node) => {
this.setBindingNode(node.row, node.column, node);
});
}

toJSON() {

toJSON(): ICellBindingNode[] {
return Array.from(this._nodeMap.values());
}
}

Loading

0 comments on commit 4aff7f7

Please sign in to comment.