diff --git a/packages/sheets-filter-ui/src/commands/commands/sheets-filter.command.ts b/packages/sheets-filter-ui/src/commands/commands/sheets-filter.command.ts index 6d573a1ed4d..68c9ef3b90d 100644 --- a/packages/sheets-filter-ui/src/commands/commands/sheets-filter.command.ts +++ b/packages/sheets-filter-ui/src/commands/commands/sheets-filter.command.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import type { IAccessor, ICommand, IMutationInfo, IRange, Nullable, Workbook } from '@univerjs/core'; import { CommandType, ICommandService, IUndoRedoService, IUniverInstanceService, LocaleService, Quantity, sequenceExecute, UniverInstanceType } from '@univerjs/core'; import { MessageType } from '@univerjs/design'; -import type { ISheetCommandSharedParams } from '@univerjs/sheets'; import { expandToContinuousRange, getSheetCommandTarget, isSingleCellSelection, SheetsSelectionsService } from '@univerjs/sheets'; -import type { FilterColumn, IAutoFilter, IFilterColumn, ISetSheetsFilterCriteriaMutationParams, ISetSheetsFilterRangeMutationParams } from '@univerjs/sheets-filter'; import { ReCalcSheetsFilterMutation, RemoveSheetsFilterMutation, SetSheetsFilterCriteriaMutation, SetSheetsFilterRangeMutation, SheetsFilterService } from '@univerjs/sheets-filter'; import { IMessageService } from '@univerjs/ui'; +import type { IAccessor, ICommand, IMutationInfo, IRange, Nullable, Workbook } from '@univerjs/core'; +import type { ISheetCommandSharedParams } from '@univerjs/sheets'; +import type { FilterColumn, IAutoFilter, IFilterColumn, ISetSheetsFilterCriteriaMutationParams, ISetSheetsFilterRangeMutationParams } from '@univerjs/sheets-filter'; /** * Parameters of command {@link SetSheetFilterRangeCommand}. @@ -85,6 +85,7 @@ export const RemoveSheetFilterCommand: ICommand = { const univerInstanceService = accessor.get(IUniverInstanceService); const sheetsFilterService = accessor.get(SheetsFilterService); const commandService = accessor.get(ICommandService); + const undoRedoService = accessor.get(IUndoRedoService); const commandTarget = getSheetCommandTarget(univerInstanceService, params); diff --git a/packages/sheets-filter-ui/src/views/components/SheetsFilterByValuesPanel.tsx b/packages/sheets-filter-ui/src/views/components/SheetsFilterByValuesPanel.tsx index 6c33635b99a..9860172d7b6 100644 --- a/packages/sheets-filter-ui/src/views/components/SheetsFilterByValuesPanel.tsx +++ b/packages/sheets-filter-ui/src/views/components/SheetsFilterByValuesPanel.tsx @@ -14,14 +14,14 @@ * limitations under the License. */ -import React, { useCallback } from 'react'; import { LocaleService, useDependency } from '@univerjs/core'; +import { Button, Checkbox, Input, Tooltip } from '@univerjs/design'; import { useObservable } from '@univerjs/ui'; import List from 'rc-virtual-list'; -import { Button, Checkbox, Input, Tooltip } from '@univerjs/design'; -import type { ByValuesModel, IFilterByValueItem } from '../../services/sheets-filter-panel.service'; +import React, { useCallback } from 'react'; import { statisticFilterByValueItems } from '../../models/utils'; import styles from './index.module.less'; +import type { ByValuesModel, IFilterByValueItem } from '../../services/sheets-filter-panel.service'; /** * Filter by values. @@ -54,7 +54,7 @@ export function FilterByValue(props: { model: ByValuesModel }) { return (
- +
{/* The on-top select all button */}
diff --git a/packages/sheets-filter-ui/src/views/components/SheetsFilterPanel.tsx b/packages/sheets-filter-ui/src/views/components/SheetsFilterPanel.tsx index cf20390f3b8..ac8d4de5361 100644 --- a/packages/sheets-filter-ui/src/views/components/SheetsFilterPanel.tsx +++ b/packages/sheets-filter-ui/src/views/components/SheetsFilterPanel.tsx @@ -14,20 +14,20 @@ * limitations under the License. */ -import React, { useCallback, useMemo } from 'react'; -import { Button, type ISegmentedProps, Segmented } from '@univerjs/design'; import { ICommandService, LocaleService, useDependency } from '@univerjs/core'; -import { ComponentContainer, useComponentsOfPart, useObservable } from '@univerjs/ui'; - -import { of } from 'rxjs'; +import { Button, type ISegmentedProps, Segmented } from '@univerjs/design'; import { SheetsFilterService } from '@univerjs/sheets-filter'; import { SheetsUIPart } from '@univerjs/sheets-ui'; -import type { ByConditionsModel, ByValuesModel } from '../../services/sheets-filter-panel.service'; -import { FilterBy, SheetsFilterPanelService } from '../../services/sheets-filter-panel.service'; + +import { ComponentContainer, useComponentsOfPart, useObservable } from '@univerjs/ui'; +import React, { useCallback, useMemo } from 'react'; +import { of } from 'rxjs'; import { ChangeFilterByOperation, CloseFilterPanelOperation } from '../../commands/operations/sheets-filter.operation'; +import { FilterBy, SheetsFilterPanelService } from '../../services/sheets-filter-panel.service'; import styles from './index.module.less'; import { FilterByCondition } from './SheetsFilterByConditionsPanel'; import { FilterByValue } from './SheetsFilterByValuesPanel'; +import type { ByConditionsModel, ByValuesModel } from '../../services/sheets-filter-panel.service'; /** * This Filter Panel component is used to filter the data in the sheet. @@ -79,7 +79,7 @@ export function FilterPanel() {
onFilterByTypeChange(value as FilterBy)}>
- { filterByModel + {filterByModel ? (
{filterBy === FilterBy.VALUES @@ -87,7 +87,9 @@ export function FilterPanel() { : }
) - : null } + : ( +
+ )}
@@ -105,7 +107,7 @@ function useFilterByOptions(localeService: LocaleService): ISegmentedProps['opti { label: localeService.t('sheets-filter.panel.by-values'), value: FilterBy.VALUES }, { label: localeService.t('sheets-filter.panel.by-conditions'), value: FilterBy.CONDITIONS }, ] - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line react-hooks/exhaustive-deps , [locale, localeService]); } diff --git a/packages/sheets-filter/src/controllers/__tests__/sheets-filter.controller.spec.ts b/packages/sheets-filter/src/controllers/__tests__/sheets-filter.controller.spec.ts index c1f974483eb..8be56f2b1bf 100644 --- a/packages/sheets-filter/src/controllers/__tests__/sheets-filter.controller.spec.ts +++ b/packages/sheets-filter/src/controllers/__tests__/sheets-filter.controller.spec.ts @@ -14,11 +14,13 @@ * limitations under the License. */ +/* eslint-disable perfectionist/sort-imports */ + import type { IWorkbookData, Workbook } from '@univerjs/core'; -import { ICommandService, Inject, Injector, IUniverInstanceService, LocaleType, Plugin, RANGE_TYPE, UndoCommand, Univer, UniverInstanceType } from '@univerjs/core'; +import { ICommandService, Inject, Injector, IUniverInstanceService, LocaleService, LocaleType, Plugin, RANGE_TYPE, UndoCommand, Univer, UniverInstanceType } from '@univerjs/core'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import type { ISetRangeValuesMutationParams } from '@univerjs/sheets'; -import { InsertColMutation, MoveColsCommand, MoveColsMutation, MoveRowsCommand, MoveRowsMutation, RefRangeService, RemoveColCommand, RemoveColMutation, RemoveRowCommand, RemoveRowMutation, SetRangeValuesMutation, SetSelectionsOperation, SheetInterceptorService, SheetsSelectionsService } from '@univerjs/sheets'; +import { CopySheetCommand, InsertColMutation, InsertSheetMutation, MoveColsCommand, MoveColsMutation, MoveRowsCommand, MoveRowsMutation, RefRangeService, RemoveColCommand, RemoveColMutation, RemoveRowCommand, RemoveRowMutation, SetRangeValuesMutation, SetSelectionsOperation, SheetInterceptorService, SheetsSelectionsService } from '@univerjs/sheets'; import { SHEET_FILTER_SNAPSHOT_ID, SheetsFilterService } from '../../services/sheet-filter.service'; import { SheetsFilterController } from '../sheets-filter.controller'; import { SetSheetsFilterCriteriaMutation } from '../../commands/mutations/sheets-filter.mutation'; @@ -87,6 +89,11 @@ function testWorkbookDataWithFilterFactory(): IWorkbookData { v: 'D', }, }, + 4: { + 0: { + v: 'H', + }, + }, }, name: 'Sheet-001', }, @@ -97,6 +104,8 @@ function testWorkbookDataWithFilterFactory(): IWorkbookData { data: JSON.stringify({ sheet1: { ref: { startRow: 3, startColumn: 0, endRow: 5, endColumn: 5 }, + filterColumns: [{ colId: 0, filters: { blank: true } }], + cachedFilteredOut: [4], }, }), }, @@ -153,6 +162,8 @@ function createFilterControllerTestBed(workbookData?: IWorkbookData) { RemoveColMutation, SetSelectionsOperation, SetRangeValuesMutation, + CopySheetCommand, + InsertSheetMutation, ] ).forEach((command) => commandService.registerCommand(command)); @@ -177,6 +188,8 @@ describe('test controller of sheets filter', () => { univer = testBed.univer; get = testBed.get; + get(LocaleService).load({ zhCN: {} }); + commandService = get(ICommandService); sheetsFilterService = get(SheetsFilterService); instanceService = get(IUniverInstanceService); @@ -358,4 +371,19 @@ describe('test controller of sheets filter', () => { expect((sheetsFilterService as SheetsFilterService).getFilterModel('test', 'sheet1')!.getAllFilterColumns()?.[0][0]).toBe(1); }); }); + + describe('test copy sheet', () => { + it('should copy filter', async () => { + const res = await commandService.executeCommand(CopySheetCommand.id, { + unitId: 'test', + subUnitId: 'sheet1', + }); + expect(res).toBeTruthy(); + const workbook = instanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_SHEET)!; + const sheet2 = workbook.getSheets()[1]; + const filterModel = (sheetsFilterService as SheetsFilterService).getFilterModel('test', sheet2.getSheetId()); + expect(filterModel).toBeTruthy(); + expect(filterModel?.getFilterColumn(0)?.getColumnData()).toStrictEqual({ colId: 0, filters: { blank: true } }); + }); + }); }); diff --git a/packages/sheets-filter/src/controllers/sheets-filter.controller.ts b/packages/sheets-filter/src/controllers/sheets-filter.controller.ts index 5f2b32c2edf..b83949a0e1e 100644 --- a/packages/sheets-filter/src/controllers/sheets-filter.controller.ts +++ b/packages/sheets-filter/src/controllers/sheets-filter.controller.ts @@ -15,9 +15,9 @@ */ import { Disposable, DisposableCollection, ICommandService, Inject, IUniverInstanceService, moveMatrixArray, Rectangle } from '@univerjs/core'; -import { EffectRefRangId, expandToContinuousRange, getSheetCommandTarget, InsertColCommand, InsertRowCommand, InsertRowMutation, INTERCEPTOR_POINT, MoveRangeCommand, MoveRowsCommand, RefRangeService, RemoveColCommand, RemoveRowCommand, RemoveRowMutation, RemoveSheetCommand, SetRangeValuesMutation, SetWorksheetActivateCommand, SheetInterceptorService } from '@univerjs/sheets'; +import { CopySheetCommand, EffectRefRangId, expandToContinuousRange, getSheetCommandTarget, InsertColCommand, InsertRowCommand, InsertRowMutation, INTERCEPTOR_POINT, MoveRangeCommand, MoveRowsCommand, RefRangeService, RemoveColCommand, RemoveRowCommand, RemoveRowMutation, RemoveSheetCommand, SetRangeValuesMutation, SetWorksheetActiveOperation, SheetInterceptorService } from '@univerjs/sheets'; import type { ICellData, ICommandInfo, IMutationInfo, IObjectArrayPrimitiveType, IRange, Nullable, Workbook } from '@univerjs/core'; -import type { EffectRefRangeParams, IAddWorksheetMergeMutationParams, IInsertColCommandParams, IInsertRowCommandParams, IInsertRowMutationParams, IMoveColsCommandParams, IMoveRangeCommandParams, IMoveRowsCommandParams, IRemoveColMutationParams, IRemoveRowsMutationParams, IRemoveSheetCommandParams, ISetRangeValuesMutationParams, ISetWorksheetActivateCommandParams, ISheetCommandSharedParams } from '@univerjs/sheets'; +import type { EffectRefRangeParams, IAddWorksheetMergeMutationParams, ICopySheetCommandParams, IInsertColCommandParams, IInsertRowCommandParams, IInsertRowMutationParams, IMoveColsCommandParams, IMoveRangeCommandParams, IMoveRowsCommandParams, IRemoveColMutationParams, IRemoveRowsMutationParams, IRemoveSheetCommandParams, ISetRangeValuesMutationParams, ISetWorksheetActiveOperationParams, ISheetCommandSharedParams } from '@univerjs/sheets'; import { ReCalcSheetsFilterMutation, RemoveSheetsFilterMutation, SetSheetsFilterCriteriaMutation, SetSheetsFilterRangeMutation } from '../commands/mutations/sheets-filter.mutation'; import { SheetsFilterService } from '../services/sheet-filter.service'; @@ -57,8 +57,8 @@ export class SheetsFilterController extends Disposable { getMutations: (command) => this._getUpdateFilter(command), })); this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo) => { - if (commandInfo.id === SetWorksheetActivateCommand.id) { - const params = commandInfo.params as ISetWorksheetActivateCommandParams; + if (commandInfo.id === SetWorksheetActiveOperation.id) { + const params = commandInfo.params as ISetWorksheetActiveOperationParams; const sheetId = params.subUnitId; const unitId = params.unitId; if (!sheetId || !unitId) { @@ -144,6 +144,14 @@ export class SheetsFilterController extends Disposable { const params = command.params as ISheetCommandSharedParams; return this._handleRemoveSheetCommand(params, params.unitId, params.subUnitId); } + case CopySheetCommand.id: { + const params = command.params as ICopySheetCommandParams & { targetSubUnitId: string }; + const { targetSubUnitId, unitId, subUnitId } = params; + if (!unitId || !subUnitId || !targetSubUnitId) { + return this._handleNull(); + } + return this._handleCopySheetCommand(unitId, subUnitId, targetSubUnitId); + } } return { redos: [], @@ -251,9 +259,9 @@ export class SheetsFilterController extends Disposable { const undos: IMutationInfo[] = []; const rangeRemoveCount = - removeEndColumn < startColumn - ? 0 : - Math.min(removeEndColumn, endColumn) - Math.max(removeStartColumn, startColumn) + 1; + removeEndColumn < startColumn + ? 0 : + Math.min(removeEndColumn, endColumn) - Math.max(removeStartColumn, startColumn) + 1; const removeCount = removeEndColumn - removeStartColumn + 1; @@ -285,7 +293,7 @@ export class SheetsFilterController extends Disposable { subUnitId, }; redos.push({ id: RemoveSheetsFilterMutation.id, params: removeFilterRangeMutationParams }); - undos.push({ id: SetSheetsFilterRangeMutation.id, params: { range: filterRange, unitId, subUnitId } }); + undos.unshift({ id: SetSheetsFilterRangeMutation.id, params: { range: filterRange, unitId, subUnitId } }); } else { const newStartColumn = startColumn <= removeStartColumn ? startColumn : @@ -324,13 +332,16 @@ export class SheetsFilterController extends Disposable { if (removeEndRow < startRow) { return { undos: [{ id: SetSheetsFilterRangeMutation.id, params: { range: filterRange, unitId, subUnitId } }], - redos: [{ id: SetSheetsFilterRangeMutation.id, params: { - range: { - ...filterRange, - startRow: startRow - (removeEndRow - removeStartRow + 1), - endRow: endRow - (removeEndRow - removeStartRow + 1), + redos: [{ + id: SetSheetsFilterRangeMutation.id, params: { + range: { + ...filterRange, + startRow: startRow - (removeEndRow - removeStartRow + 1), + endRow: endRow - (removeEndRow - removeStartRow + 1), + }, + unitId, subUnitId, }, - unitId, subUnitId } }], + }], }; } const redos: IMutationInfo[] = []; @@ -620,8 +631,7 @@ export class SheetsFilterController extends Disposable { const redos: IMutationInfo[] = []; const undos: IMutationInfo[] = []; const filterCols = filterModel.getAllFilterColumns(); - filterCols.forEach((col) => { - const [_, filter] = col; + filterCols.forEach(([col, filter]) => { undos.push({ id: SetSheetsFilterCriteriaMutation.id, params: { unitId, subUnitId, col, criteria: { ...filter.serialize(), colId: col } } }); }); redos.push({ id: RemoveSheetsFilterMutation.id, params: { unitId, subUnitId, range: filterRange } }); @@ -632,6 +642,34 @@ export class SheetsFilterController extends Disposable { }; } + private _handleCopySheetCommand(unitId: string, subUnitId: string, targetSubUnitId: string) { + const filterModel = this._sheetsFilterService.getFilterModel(unitId, subUnitId); + if (!filterModel) { + return this._handleNull(); + } + const filterRange = filterModel.getRange(); + if (!filterRange) { + return this._handleNull(); + } + const redos: IMutationInfo[] = []; + const undos: IMutationInfo[] = []; + const preUndos: IMutationInfo[] = []; + const preRedos: IMutationInfo[] = []; + const filterCols = filterModel.getAllFilterColumns(); + filterCols.forEach(([col, filter]) => { + redos.push({ id: SetSheetsFilterCriteriaMutation.id, params: { unitId, subUnitId: targetSubUnitId, col, criteria: { ...filter.serialize(), colId: col } } }); + preUndos.push({ id: SetSheetsFilterCriteriaMutation.id, params: { unitId, subUnitId: targetSubUnitId, col, criteria: null } }); + }); + preUndos.push({ id: RemoveSheetsFilterMutation.id, params: { unitId, subUnitId: targetSubUnitId, range: filterRange } }); + redos.unshift({ id: SetSheetsFilterRangeMutation.id, params: { range: filterRange, unitId, subUnitId: targetSubUnitId } }); + return { + undos, + redos, + preUndos, + preRedos, + }; + } + private _handleNull() { return { redos: [], undos: [] }; } @@ -756,7 +794,7 @@ export class SheetsFilterController extends Disposable { } // extend filter range when set range values - if (command.id === SetRangeValuesMutation.id && !options?.fromCollab && !options?.onlyLocal) { + if (command.id === SetRangeValuesMutation.id && !options?.onlyLocal) { const extendRegion = this._getExtendRegion(unitId, subUnitId); if (extendRegion) { const cellValue = (command.params as ISetRangeValuesMutationParams).cellValue; diff --git a/packages/sheets/src/commands/commands/copy-worksheet.command.ts b/packages/sheets/src/commands/commands/copy-worksheet.command.ts index 77002f70c29..3c81a573bd3 100644 --- a/packages/sheets/src/commands/commands/copy-worksheet.command.ts +++ b/packages/sheets/src/commands/commands/copy-worksheet.command.ts @@ -14,23 +14,25 @@ * limitations under the License. */ -import type { IAccessor, ICommand, Workbook } from '@univerjs/core'; import { CommandType, ICommandService, IUndoRedoService, IUniverInstanceService, LocaleService, + sequenceExecute, Tools, } from '@univerjs/core'; +import type { IAccessor, ICommand, IMutationInfo, Workbook } from '@univerjs/core'; +import { SheetInterceptorService } from '../../services/sheet-interceptor/sheet-interceptor.service'; +import { InsertSheetMutation, InsertSheetUndoMutationFactory } from '../mutations/insert-sheet.mutation'; +import { RemoveSheetMutation } from '../mutations/remove-sheet.mutation'; +import { getSheetCommandTarget } from './utils/target-util'; import type { IInsertSheetMutationParams, IRemoveSheetMutationParams, } from '../../basics/interfaces/mutation-interface'; -import { InsertSheetMutation, InsertSheetUndoMutationFactory } from '../mutations/insert-sheet.mutation'; -import { RemoveSheetMutation } from '../mutations/remove-sheet.mutation'; -import { getSheetCommandTarget } from './utils/target-util'; export interface ICopySheetCommandParams { unitId?: string; @@ -44,6 +46,7 @@ export const CopySheetCommand: ICommand = { const commandService = accessor.get(ICommandService); const undoRedoService = accessor.get(IUndoRedoService); const univerInstanceService = accessor.get(IUniverInstanceService); + const sheetInterceptorService = accessor.get(SheetInterceptorService); const localeService = accessor.get(LocaleService); const target = getSheetCommandTarget(univerInstanceService, params); @@ -51,7 +54,7 @@ export const CopySheetCommand: ICommand = { return false; } - const { workbook, worksheet, unitId } = target; + const { workbook, worksheet, unitId, subUnitId } = target; const config = Tools.deepClone(worksheet.getConfig()); config.name = getCopyUniqueSheetName(workbook, localeService, config.name); config.id = Tools.generateRandomId(); @@ -67,13 +70,31 @@ export const CopySheetCommand: ICommand = { accessor, insertSheetMutationParams ); - const insertResult = commandService.syncExecuteCommand(InsertSheetMutation.id, insertSheetMutationParams); + + const intercepted = sheetInterceptorService.onCommandExecute({ + id: CopySheetCommand.id, + params: { unitId, subUnitId, targetSubUnitId: config.id }, + }); + + const redos: IMutationInfo[] = [ + ...(intercepted.preRedos ?? []), + { id: InsertSheetMutation.id, params: insertSheetMutationParams }, + ...intercepted.redos, + ]; + + const undos: IMutationInfo[] = [ + ...(intercepted.preUndos ?? []), + { id: RemoveSheetMutation.id, params: removeSheetMutationParams }, + ...intercepted.undos, + ]; + + const insertResult = sequenceExecute(redos, commandService).result; if (insertResult) { undoRedoService.pushUndoRedo({ unitID: unitId, - undoMutations: [{ id: RemoveSheetMutation.id, params: removeSheetMutationParams }], - redoMutations: [{ id: InsertSheetMutation.id, params: insertSheetMutationParams }], + undoMutations: undos, + redoMutations: redos, }); return true; } diff --git a/packages/sheets/src/index.ts b/packages/sheets/src/index.ts index 1cc872c8236..87ac0a52344 100644 --- a/packages/sheets/src/index.ts +++ b/packages/sheets/src/index.ts @@ -186,6 +186,7 @@ export { ClearSelectionAllCommand } from './commands/commands/clear-selection-al export { ClearSelectionContentCommand } from './commands/commands/clear-selection-content.command'; export { ClearSelectionFormatCommand } from './commands/commands/clear-selection-format.command'; export { CopySheetCommand } from './commands/commands/copy-worksheet.command'; +export type { ICopySheetCommandParams } from './commands/commands/copy-worksheet.command'; export { DeleteRangeMoveLeftCommand, type IDeleteRangeMoveLeftCommandParams } from './commands/commands/delete-range-move-left.command'; export { DeleteRangeMoveUpCommand, type IDeleteRangeMoveUpCommandParams } from './commands/commands/delete-range-move-up.command'; export { DeleteRangeProtectionCommand, type IDeleteRangeProtectionCommandParams } from './commands/commands/delete-range-protection.command';