diff --git a/packages/common/src/extensions/__tests__/contextMenuExtension.spec.ts b/packages/common/src/extensions/__tests__/contextMenuExtension.spec.ts index 06205c348..513415ed9 100644 --- a/packages/common/src/extensions/__tests__/contextMenuExtension.spec.ts +++ b/packages/common/src/extensions/__tests__/contextMenuExtension.spec.ts @@ -7,7 +7,7 @@ import { SharedService } from '../../services/shared.service'; import { DelimiterType, FileType } from '../../enums/index'; import { Column, SlickDataView, GridOption, MenuCommandItem, SlickGrid, SlickNamespace, ContextMenu, SlickContextMenu } from '../../interfaces/index'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; -import { ExcelExportService, TextExportService, TreeDataService } from '../../services'; +import { ExcelExportService, PubSubService, TextExportService, TreeDataService } from '../../services'; declare const Slick: SlickNamespace; @@ -46,6 +46,13 @@ const gridStub = { setPreHeaderPanelVisibility: jest.fn(), } as unknown as SlickGrid; +const pubSubServiceStub = { + publish: jest.fn(), + subscribe: jest.fn(), + unsubscribe: jest.fn(), + unsubscribeAll: jest.fn(), +} as PubSubService; + const treeDataServiceStub = { init: jest.fn(), dispose: jest.fn(), @@ -126,7 +133,7 @@ describe('contextMenuExtension', () => { sharedService = new SharedService(); translateService = new TranslateServiceStub(); extensionUtility = new ExtensionUtility(sharedService, translateService); - extension = new ContextMenuExtension(extensionUtility, sharedService, treeDataServiceStub, translateService); + extension = new ContextMenuExtension(extensionUtility, pubSubServiceStub, sharedService, treeDataServiceStub, translateService); translateService.use('fr'); }); @@ -876,6 +883,7 @@ describe('contextMenuExtension', () => { }); it('should call "setGrouping" from the DataView when Grouping is enabled and the command triggered is "clear-grouping"', () => { + const pubSpy = jest.spyOn(pubSubServiceStub, 'publish'); const dataviewSpy = jest.spyOn(SharedService.prototype.dataView, 'setGrouping'); const copyGridOptionsMock = { ...gridOptionsMock, enableGrouping: true, contextMenu: { hideClearAllGrouping: false } } as GridOption; jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(copyGridOptionsMock); @@ -885,6 +893,7 @@ describe('contextMenuExtension', () => { menuItemCommand.action!(new CustomEvent('change'), { command: 'clear-grouping', cell: 0, row: 0 } as any); expect(dataviewSpy).toHaveBeenCalledWith([]); + expect(pubSpy).toHaveBeenCalledWith('contextMenu:clearGrouping', true); }); it('should call "collapseAllGroups" from the DataView when Grouping is enabled and the command triggered is "collapse-all-groups"', () => { @@ -1099,7 +1108,7 @@ describe('contextMenuExtension', () => { describe('without Translate Service', () => { beforeEach(() => { translateService = undefined as any; - extension = new ContextMenuExtension({} as ExtensionUtility, { gridOptions: { enableTranslate: true } } as SharedService, treeDataServiceStub, translateService); + extension = new ContextMenuExtension({} as ExtensionUtility, pubSubServiceStub, { gridOptions: { enableTranslate: true } } as SharedService, treeDataServiceStub, translateService); }); it('should throw an error if "enableTranslate" is set but the I18N Service is null', () => { diff --git a/packages/common/src/extensions/__tests__/draggableGroupingExtension.spec.ts b/packages/common/src/extensions/__tests__/draggableGroupingExtension.spec.ts index 7030995ef..5d9e0078e 100644 --- a/packages/common/src/extensions/__tests__/draggableGroupingExtension.spec.ts +++ b/packages/common/src/extensions/__tests__/draggableGroupingExtension.spec.ts @@ -3,6 +3,7 @@ import { DraggableGroupingExtension } from '../draggableGroupingExtension'; import { ExtensionUtility } from '../extensionUtility'; import { SharedService } from '../../services/shared.service'; import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; +import { PubSubService } from '../../services/pubSub.service'; declare const Slick: SlickNamespace; @@ -11,9 +12,21 @@ const gridStub = { registerPlugin: jest.fn(), } as unknown as SlickGrid; +const fnCallbacks = {}; +const pubSubServiceStub = { + publish: jest.fn(), + subscribe: (eventName, fn) => fnCallbacks[eventName as string] = fn, + unsubscribe: jest.fn(), + unsubscribeAll: jest.fn(), +} as PubSubService; +jest.mock('../../services/pubSub.service', () => ({ + PubSubService: () => pubSubServiceStub +})); + const mockAddon = jest.fn().mockImplementation(() => ({ init: jest.fn(), destroy: jest.fn(), + clearDroppedGroups: jest.fn(), onGroupChanged: new Slick.Event(), })); @@ -40,7 +53,7 @@ describe('draggableGroupingExtension', () => { sharedService = new SharedService(); translateService = new TranslateServiceStub(); extensionUtility = new ExtensionUtility(sharedService, translateService); - extension = new DraggableGroupingExtension(extensionUtility, sharedService); + extension = new DraggableGroupingExtension(extensionUtility, pubSubServiceStub, sharedService); }); it('should return null after calling "create" method when the grid options is missing', () => { @@ -120,5 +133,15 @@ describe('draggableGroupingExtension', () => { ); expect(onColumnSpy).toHaveBeenCalledWith(expect.anything(), { caller: 'clear-all', groupColumns: [] }); }); + + it('should expect that it call the Draggable Grouping "clearDroppedGroups" when Context Menu subscribed event triggers a clear grouping', () => { + extension.create(gridOptionsMock) as SlickDraggableGrouping; + const addon = extension.register(); + const clearSpy = jest.spyOn(addon, 'clearDroppedGroups'); + + fnCallbacks['contextMenu:clearGrouping'](true); + + expect(clearSpy).toHaveBeenCalled(); + }); }); }); diff --git a/packages/common/src/extensions/contextMenuExtension.ts b/packages/common/src/extensions/contextMenuExtension.ts index 7d94f9f13..70b246556 100644 --- a/packages/common/src/extensions/contextMenuExtension.ts +++ b/packages/common/src/extensions/contextMenuExtension.ts @@ -17,6 +17,7 @@ import { ExtensionUtility } from './extensionUtility'; import { exportWithFormatterWhenDefined } from '../formatters/formatterUtilities'; import { SharedService } from '../services/shared.service'; import { getDescendantProperty, getTranslationPrefix } from '../services/utilities'; +import { PubSubService } from '../services/pubSub.service'; import { ExcelExportService, TextExportService, TranslaterService, TreeDataService } from '../services/index'; // using external non-typed js libraries @@ -30,6 +31,7 @@ export class ContextMenuExtension implements Extension { constructor( private readonly extensionUtility: ExtensionUtility, + private readonly pubSubService: PubSubService, private readonly sharedService: SharedService, private readonly treeDataService: TreeDataService, private readonly translaterService?: TranslaterService, @@ -319,7 +321,10 @@ export class ContextMenuExtension implements Extension { disabled: false, command: commandName, positionOrder: 55, - action: () => dataView.setGrouping([]), + action: () => { + dataView.setGrouping([]); + this.pubSubService.publish('contextMenu:clearGrouping', true); + }, itemUsabilityOverride: () => { // only enable the command when there's an actually grouping in play const groupingArray = dataView && dataView.getGrouping && dataView.getGrouping(); diff --git a/packages/common/src/extensions/draggableGroupingExtension.ts b/packages/common/src/extensions/draggableGroupingExtension.ts index 482de387e..ce9fad14b 100644 --- a/packages/common/src/extensions/draggableGroupingExtension.ts +++ b/packages/common/src/extensions/draggableGroupingExtension.ts @@ -2,6 +2,7 @@ import 'slickgrid/plugins/slick.draggablegrouping'; import { DraggableGrouping, Extension, GetSlickEventType, GridOption, SlickDraggableGrouping, SlickEventHandler, SlickNamespace } from '../interfaces/index'; import { ExtensionUtility } from './extensionUtility'; +import { PubSubService } from '../services/pubSub.service'; import { SharedService } from '../services/shared.service'; // using external non-typed js libraries @@ -12,7 +13,7 @@ export class DraggableGroupingExtension implements Extension { private _draggableGroupingOptions: DraggableGrouping | null = null; private _eventHandler: SlickEventHandler; - constructor(private readonly extensionUtility: ExtensionUtility, private readonly sharedService: SharedService) { + constructor(private readonly extensionUtility: ExtensionUtility, private readonly pubSubService: PubSubService, private readonly sharedService: SharedService) { this._eventHandler = new Slick.EventHandler(); } @@ -71,6 +72,9 @@ export class DraggableGroupingExtension implements Extension { } }); } + + // we also need to subscribe to a possible user clearing the grouping via the Context Menu, we need to clear the pre-header bar as well + this.pubSubService.subscribe('contextMenu:clearGrouping', () => this._addon?.clearDroppedGroups?.()); } return this._addon; diff --git a/packages/common/src/services/__tests__/gridState.service.spec.ts b/packages/common/src/services/__tests__/gridState.service.spec.ts index 8bc00cc0e..a51a843f2 100644 --- a/packages/common/src/services/__tests__/gridState.service.spec.ts +++ b/packages/common/src/services/__tests__/gridState.service.spec.ts @@ -31,16 +31,17 @@ import { } from '../../interfaces/index'; import { SharedService } from '../shared.service'; import { TreeDataService } from '../treeData.service'; +import { PubSubService } from '../pubSub.service'; declare const Slick: SlickNamespace; const fnCallbacks = {}; const mockPubSub = { publish: jest.fn(), - subscribe: (eventName, fn) => fnCallbacks[eventName] = fn, + subscribe: (eventName, fn) => fnCallbacks[eventName as string] = fn, unsubscribe: jest.fn(), unsubscribeAll: jest.fn(), -}; +} as PubSubService; jest.mock('../pubSub.service', () => ({ PubSubService: () => mockPubSub })); diff --git a/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts b/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts index 3d286daa1..b4c202a10 100644 --- a/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts +++ b/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts @@ -363,10 +363,10 @@ export class SlickVanillaGridBundle { const autoTooltipExtension = new AutoTooltipExtension(this.sharedService); const cellExternalCopyManagerExtension = new CellExternalCopyManagerExtension(this.extensionUtility, this.sharedService); const cellMenuExtension = new CellMenuExtension(this.extensionUtility, this.sharedService, this.translaterService); - const contextMenuExtension = new ContextMenuExtension(this.extensionUtility, this.sharedService, this.treeDataService, this.translaterService); + const contextMenuExtension = new ContextMenuExtension(this.extensionUtility, this._eventPubSubService, this.sharedService, this.treeDataService, this.translaterService); const columnPickerExtension = new ColumnPickerExtension(this.extensionUtility, this.sharedService); const checkboxExtension = new CheckboxSelectorExtension(this.sharedService); - const draggableGroupingExtension = new DraggableGroupingExtension(this.extensionUtility, this.sharedService); + const draggableGroupingExtension = new DraggableGroupingExtension(this.extensionUtility, this._eventPubSubService, this.sharedService); const gridMenuExtension = new GridMenuExtension(this.extensionUtility, this.filterService, this.sharedService, this.sortService, this.backendUtilityService, this.translaterService); const groupItemMetaProviderExtension = new GroupItemMetaProviderExtension(this.sharedService); const headerButtonExtension = new HeaderButtonExtension(this.extensionUtility, this.sharedService);