Skip to content

Commit

Permalink
feat(base-sheets): add clear all,clear formats (#265)
Browse files Browse the repository at this point in the history
* feat(base-sheets): 1. add clear all,clear formats buttons in context menu 2. clear with merged cells

* test(base-sheets): clear formats/all undo redo

* test(base-sheets): clear test restore the original data

* fix(base-sheets): 1. re-render after set range values mutation 2. fix color picker onclick event
  • Loading branch information
Dushusir committed Oct 12, 2023
1 parent fa3a3d4 commit fb03668
Show file tree
Hide file tree
Showing 13 changed files with 347 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import {
AddWorksheetMergeHorizontalCommand,
AddWorksheetMergeVerticalCommand,
} from '../commands/commands/add-worksheet-merge.command';
import { ClearSelectionAllCommand } from '../commands/commands/clear-selection-all.command';
import { ClearSelectionContentCommand } from '../commands/commands/clear-selection-content.command';
import { ClearSelectionFormatCommand } from '../commands/commands/clear-selection-format.command';
import { CopySheetCommand } from '../commands/commands/copy-worksheet.command';
import { DeleteRangeMoveLeftCommand } from '../commands/commands/delete-range-move-left.command';
import { DeleteRangeMoveUpCommand } from '../commands/commands/delete-range-move-up.command';
Expand Down Expand Up @@ -105,6 +107,8 @@ export class BasicWorksheetController extends Disposable implements IDisposable
RemoveWorksheetMergeCommand,
RemoveWorksheetMergeMutation,
ClearSelectionContentCommand,
ClearSelectionFormatCommand,
ClearSelectionAllCommand,
SetRangeValuesMutation,
SetWorksheetNameCommand,
SetWorksheetNameMutation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { InsertColMutation, InsertRowMutation } from '../commands/mutations/inse
import { MoveRowsMutation } from '../commands/mutations/move-rows-cols.mutation';
import { RemoveColMutation, RemoveRowMutation } from '../commands/mutations/remove-row-col.mutation';
import { RemoveWorksheetMergeMutation } from '../commands/mutations/remove-worksheet-merge.mutation';
import { SetBorderStylesMutation } from '../commands/mutations/set-border-styles.mutation';
import { SetRangeValuesMutation } from '../commands/mutations/set-range-values.mutation';
import { SetWorksheetActivateMutation } from '../commands/mutations/set-worksheet-activate.mutation';
import { SetWorksheetColWidthMutation } from '../commands/mutations/set-worksheet-col-width.mutation';
import { SetWorksheetRowHeightMutation } from '../commands/mutations/set-worksheet-row-height.mutation';
Expand Down Expand Up @@ -108,6 +110,8 @@ export class SheetRenderController extends Disposable {
AddWorksheetMergeMutation.id,
RemoveWorksheetMergeMutation.id,
MoveRowsMutation.id,
SetRangeValuesMutation.id,
SetBorderStylesMutation.id,
];

this.disposeWithMe(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
ICellData,
ICommandService,
ICurrentUniverService,
IRange,
IStyleData,
Nullable,
RANGE_TYPE,
Expand All @@ -13,7 +14,10 @@ import { Injector } from '@wendellhu/redi';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';

import { NORMAL_SELECTION_PLUGIN_NAME, SelectionManagerService } from '../../../services/selection-manager.service';
import { AddWorksheetMergeMutation } from '../../mutations/add-worksheet-merge.mutation';
import { RemoveWorksheetMergeMutation } from '../../mutations/remove-worksheet-merge.mutation';
import { SetRangeValuesMutation } from '../../mutations/set-range-values.mutation';
import { AddWorksheetMergeCommand } from '../add-worksheet-merge.command';
import { ClearSelectionAllCommand } from '../clear-selection-all.command';
import { ClearSelectionContentCommand } from '../clear-selection-content.command';
import { ClearSelectionFormatCommand } from '../clear-selection-format.command';
Expand All @@ -33,6 +37,9 @@ describe('Test clear selection content commands', () => {
commandService = get(ICommandService);
commandService.registerCommand(ClearSelectionContentCommand);
commandService.registerCommand(ClearSelectionFormatCommand);
commandService.registerCommand(AddWorksheetMergeCommand);
commandService.registerCommand(AddWorksheetMergeMutation);
commandService.registerCommand(RemoveWorksheetMergeMutation);
commandService.registerCommand(ClearSelectionAllCommand);
commandService.registerCommand(SetRangeValuesCommand);
commandService.registerCommand(SetRangeValuesMutation);
Expand All @@ -42,7 +49,7 @@ describe('Test clear selection content commands', () => {
univer.dispose();
});

describe('clear selection content', () => {
describe('clear selection contents', () => {
describe('correct situations', () => {
it('will clear selection content when there is a selected range', async () => {
const selectionManager = get(SelectionManagerService);
Expand Down Expand Up @@ -77,6 +84,9 @@ describe('Test clear selection content commands', () => {
// redo
expect(await commandService.executeCommand(RedoCommand.id)).toBeTruthy();
expect(getValue()).toStrictEqual({});

// Restore the original data
expect(await commandService.executeCommand(UndoCommand.id)).toBeTruthy();
});
});

Expand All @@ -87,7 +97,7 @@ describe('Test clear selection content commands', () => {
});
});
});
describe('clear selection format', () => {
describe('clear selection formats', () => {
describe('correct situations', () => {
it('will clear selection format when there is a selected range', async () => {
const selectionManager = get(SelectionManagerService);
Expand Down Expand Up @@ -136,7 +146,9 @@ describe('Test clear selection content commands', () => {

// clear formats
expect(await commandService.executeCommand(ClearSelectionFormatCommand.id)).toBeTruthy();
expect(getValue()).toStrictEqual({});
expect(getValue()).toStrictEqual({
v: 'A1',
});

// undo
expect(await commandService.executeCommand(UndoCommand.id)).toBeTruthy();
Expand All @@ -145,7 +157,88 @@ describe('Test clear selection content commands', () => {
});
// redo
expect(await commandService.executeCommand(RedoCommand.id)).toBeTruthy();
expect(getValue()).toStrictEqual({});
expect(getValue()).toStrictEqual({
v: 'A1',
});
});
it('clear formats with merged cells', async () => {
const selectionManager = get(SelectionManagerService);
selectionManager.setCurrentSelection({
pluginName: NORMAL_SELECTION_PLUGIN_NAME,
unitId: 'test',
sheetId: 'sheet1',
});
selectionManager.add([
{
range: { startRow: 0, startColumn: 0, endColumn: 1, endRow: 1, rangeType: RANGE_TYPE.NORMAL },
primary: null,
style: null,
},
]);

function getValue(): Nullable<ICellData> {
return get(ICurrentUniverService)
.getUniverSheetInstance('test')
?.getSheetBySheetId('sheet1')
?.getRange(0, 0, 0, 0)
.getValue();
}

function getStyle(): Nullable<IStyleData> {
const value = getValue();
const styles = get(ICurrentUniverService).getUniverSheetInstance('test')?.getStyles();
if (value && styles) {
return styles.getStyleByCell(value);
}
}

function getMerge(): IRange[] | undefined {
return get(ICurrentUniverService)
.getUniverSheetInstance('test')
?.getSheetBySheetId('sheet1')
?.getConfig().mergeData;
}

// set formats
const paramsStyle: ISetRangeValuesCommandParams = {
value: {
s: {
ff: 'Arial',
},
},
};

// set style
expect(await commandService.executeCommand(SetRangeValuesCommand.id, paramsStyle)).toBeTruthy();
expect(getStyle()).toStrictEqual({
ff: 'Arial',
});

// set merge cell
expect(await commandService.executeCommand(AddWorksheetMergeCommand.id)).toBeTruthy();
expect(getMerge()).toStrictEqual([{ startRow: 0, startColumn: 0, endRow: 1, endColumn: 1 }]);

// clear formats with merged cells
expect(await commandService.executeCommand(ClearSelectionFormatCommand.id)).toBeTruthy();
// clear formats
expect(getValue()).toStrictEqual({
v: 'A1',
});
// remove merge
expect(getMerge()).toStrictEqual([]);

// undo
expect(await commandService.executeCommand(UndoCommand.id)).toBeTruthy();
expect(getStyle()).toStrictEqual({
ff: 'Arial',
});
expect(getMerge()).toStrictEqual([{ startRow: 0, startColumn: 0, endRow: 1, endColumn: 1 }]);
// redo
expect(await commandService.executeCommand(RedoCommand.id)).toBeTruthy();
expect(getValue()).toStrictEqual({
v: 'A1',
});
expect(getMerge()).toStrictEqual([]);
});
});

Expand Down Expand Up @@ -214,6 +307,81 @@ describe('Test clear selection content commands', () => {
expect(await commandService.executeCommand(RedoCommand.id)).toBeTruthy();
expect(getValue()).toStrictEqual({});
});
it('clear all with merged cells', async () => {
const selectionManager = get(SelectionManagerService);
selectionManager.setCurrentSelection({
pluginName: NORMAL_SELECTION_PLUGIN_NAME,
unitId: 'test',
sheetId: 'sheet1',
});
selectionManager.add([
{
range: { startRow: 0, startColumn: 0, endColumn: 1, endRow: 1, rangeType: RANGE_TYPE.NORMAL },
primary: null,
style: null,
},
]);

function getValue(): Nullable<ICellData> {
return get(ICurrentUniverService)
.getUniverSheetInstance('test')
?.getSheetBySheetId('sheet1')
?.getRange(0, 0, 0, 0)
.getValue();
}

function getStyle(): Nullable<IStyleData> {
const value = getValue();
const styles = get(ICurrentUniverService).getUniverSheetInstance('test')?.getStyles();
if (value && styles) {
return styles.getStyleByCell(value);
}
}

function getMerge(): IRange[] | undefined {
return get(ICurrentUniverService)
.getUniverSheetInstance('test')
?.getSheetBySheetId('sheet1')
?.getConfig().mergeData;
}

// set formats
const paramsStyle: ISetRangeValuesCommandParams = {
value: {
s: {
ff: 'Arial',
},
},
};

// set style
expect(await commandService.executeCommand(SetRangeValuesCommand.id, paramsStyle)).toBeTruthy();
expect(getStyle()).toStrictEqual({
ff: 'Arial',
});

// set merge cell
expect(await commandService.executeCommand(AddWorksheetMergeCommand.id)).toBeTruthy();
expect(getMerge()).toStrictEqual([{ startRow: 0, startColumn: 0, endRow: 1, endColumn: 1 }]);

// clear all with merged cells
expect(await commandService.executeCommand(ClearSelectionAllCommand.id)).toBeTruthy();
// clear formats
expect(getValue()).toStrictEqual({});
// remove merge
expect(getMerge()).toStrictEqual([]);

// undo
expect(await commandService.executeCommand(UndoCommand.id)).toBeTruthy();
expect(getStyle()).toStrictEqual({
ff: 'Arial',
});
expect(getMerge()).toStrictEqual([{ startRow: 0, startColumn: 0, endRow: 1, endColumn: 1 }]);
// redo
expect(await commandService.executeCommand(RedoCommand.id)).toBeTruthy();
expect(getValue()).toStrictEqual({});
expect(getMerge()).toStrictEqual([]);
});
});

describe('fault situations', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ import {
RemoveWorksheetMergeMutation,
} from '../mutations/remove-worksheet-merge.mutation';

interface addMergeCommandParams {
interface IAddMergeCommandParams {
value: Dimension.ROWS | Dimension.COLUMNS;
}

export const AddWorksheetMergeCommand: ICommand = {
type: CommandType.COMMAND,
id: 'sheet.command.add-worksheet-merge',
// eslint-disable-next-line max-lines-per-function
handler: async (accessor: IAccessor, params?: addMergeCommandParams) => {
handler: async (accessor: IAccessor, params?: IAddMergeCommandParams) => {
const selectionManagerService = accessor.get(SelectionManagerService);
const commandService = accessor.get(ICommandService);
const undoRedoService = accessor.get(IUndoRedoService);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,28 @@ import {
CommandType,
ICellData,
ICommand,
ICommandInfo,
ICommandService,
ICurrentUniverService,
IRange,
IUndoRedoService,
ObjectMatrix,
ObjectMatrixPrimitiveType,
Rectangle,
sequenceExecute,
} from '@univerjs/core';
import { IAccessor } from '@wendellhu/redi';

import {
IAddWorksheetMergeMutationParams,
IRemoveWorksheetMergeMutationParams,
} from '../../Basics/Interfaces/MutationInterface';
import { SelectionManagerService } from '../../services/selection-manager.service';
import { AddWorksheetMergeMutation } from '../mutations/add-worksheet-merge.mutation';
import {
RemoveMergeUndoMutationFactory,
RemoveWorksheetMergeMutation,
} from '../mutations/remove-worksheet-merge.mutation';
import {
ISetRangeValuesMutationParams,
SetRangeValuesMutation,
Expand Down Expand Up @@ -39,6 +51,10 @@ export const ClearSelectionAllCommand: ICommand = {
return false;
}

const sequenceExecuteList: Array<ICommandInfo<object>> = [];
const sequenceExecuteUndoList: Array<ICommandInfo<object>> = [];

// clear style and content
const clearMutationParams: ISetRangeValuesMutationParams = {
range: selections,
worksheetId,
Expand All @@ -50,18 +66,56 @@ export const ClearSelectionAllCommand: ICommand = {
clearMutationParams
);

const result = commandService.executeCommand(SetRangeValuesMutation.id, clearMutationParams);
sequenceExecuteList.push({
id: SetRangeValuesMutation.id,
params: clearMutationParams,
});
sequenceExecuteUndoList.push({
id: SetRangeValuesMutation.id,
params: undoClearMutationParams,
});

// remove merged cells
let hasMerge = false;
const mergeData = worksheet.getConfig().mergeData;
selections.forEach((selection) => {
mergeData.forEach((merge) => {
if (Rectangle.intersects(selection, merge)) {
hasMerge = true;
}
});
});

if (hasMerge) {
const removeMergeParams: IRemoveWorksheetMergeMutationParams = {
workbookId,
worksheetId,
ranges: selections,
};
const undoRemoveMergeParams: IAddWorksheetMergeMutationParams = RemoveMergeUndoMutationFactory(
accessor,
removeMergeParams
);

sequenceExecuteList.push({
id: RemoveWorksheetMergeMutation.id,
params: removeMergeParams,
});
sequenceExecuteUndoList.push({
id: AddWorksheetMergeMutation.id,
params: undoRemoveMergeParams,
});
}

const result = await sequenceExecute(sequenceExecuteList, commandService);

if (result) {
undoRedoService.pushUndoRedo({
// If there are multiple mutations that form an encapsulated project, they must be encapsulated in the same undo redo element.
// Hooks can be used to hook the code of external controllers to add new actions.
URI: workbookId,
undo() {
return commandService.executeCommand(SetRangeValuesMutation.id, undoClearMutationParams);
},
redo() {
return commandService.executeCommand(SetRangeValuesMutation.id, clearMutationParams);
},
undo: async () => (await sequenceExecute(sequenceExecuteUndoList, commandService)).result,
redo: async () => (await sequenceExecute(sequenceExecuteList, commandService)).result,
});

return true;
Expand Down
Loading

0 comments on commit fb03668

Please sign in to comment.