Skip to content

Commit

Permalink
fix(components): refactor to use registerExternalResources grid option (
Browse files Browse the repository at this point in the history
#199)

* fix(components): refactor to use registerExternalResources grid option
- create new ExternalResource interface and make all external resources (components/services) implement it
  • Loading branch information
ghiscoding authored Dec 15, 2020
1 parent 6789e25 commit 7ca42f4
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 29 deletions.
10 changes: 10 additions & 0 deletions packages/common/src/interfaces/externalResource.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SlickGrid } from './slickGrid.interface';
import { ContainerService } from '../services';

export interface ExternalResource {
/** Initialize the External Resource (Component or Service) */
init: (grid: SlickGrid, container?: ContainerService) => void;

/** Dispose method */
dispose?: () => void;
}
3 changes: 2 additions & 1 deletion packages/common/src/interfaces/gridOption.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
EmptyWarning,
ExcelCopyBufferOption,
ExcelExportOption,
ExternalResource,
FormatterOption,
GridMenu,
GridState,
Expand Down Expand Up @@ -423,7 +424,7 @@ export interface GridOption {
preselectedRows?: number[];

/** Register any external Resources (Components, Services) like the ExcelExportService, TextExportService, SlickCompositeEditorComponent, ... */
registerExternalResources?: any[];
registerExternalResources?: ExternalResource[];

/** Row Detail View Plugin options & events (columnId, cssClass, toolTip, width) */
// rowDetailView?: RowDetailView;
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export * from './excelWorkbook.interface';
export * from './excelWorksheet.interface';
export * from './extension.interface';
export * from './extensionModel.interface';
export * from './externalResource.interface';
export * from './filter.interface';
export * from './filterArguments.interface';
export * from './filterCallback.interface';
Expand Down
4 changes: 2 additions & 2 deletions packages/common/src/services/excelExport.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { ExcelExportOption, SlickGrid } from '../interfaces/index';
import { ExcelExportOption, ExternalResource, SlickGrid } from '../interfaces/index';
import { ContainerService } from '../services/container.service';

export abstract class ExcelExportService {
export abstract class ExcelExportService implements ExternalResource {
/** ExcelExportService class name which is use to find service instance in the external registered services */
className: string;

Expand Down
4 changes: 2 additions & 2 deletions packages/common/src/services/textExport.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { TextExportOption, SlickGrid } from '../interfaces/index';
import { ExternalResource, SlickGrid, TextExportOption } from '../interfaces/index';
import { ContainerService } from '../services/container.service';

export abstract class TextExportService {
export abstract class TextExportService implements ExternalResource {
/** ExcelExportService class name which is use to find service instance in the external registered services */
className: string;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
CurrentRowSelection,
Editor,
EditorValidationResult,
ExternalResource,
getDescendantProperty,
GetSlickEventType,
GridOption,
Expand All @@ -32,7 +33,7 @@ declare const Slick: SlickNamespace;

const DEFAULT_ON_ERROR = (error: OnErrorOption) => console.log(error.message);

export class SlickCompositeEditorComponent {
export class SlickCompositeEditorComponent implements ExternalResource {
private _bindEventService: BindingEventService;
private _eventHandler: SlickEventHandler;
private _modalElm: HTMLDivElement;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
import {
ContainerService,
EmptyWarning,
ExternalResource,
GridOption,
sanitizeTextByAvailableSanitizer,
SlickGrid,
TranslaterService
} from '@slickgrid-universal/common';

export class SlickEmptyWarningComponent {
export class SlickEmptyWarningComponent implements ExternalResource {
private _warningLeftElement: HTMLDivElement | null;
private _warningRightElement: HTMLDivElement | null;
private grid: SlickGrid;
private translaterService?: TranslaterService | null;


/** Getter for the Grid Options pulled through the Grid Object */
get gridOptions(): GridOption {
return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {};
}

constructor(private grid: SlickGrid, private translaterService?: TranslaterService) { }
constructor() { }

init(grid: SlickGrid, containerService: ContainerService) {
this.grid = grid;
this.translaterService = containerService.get<TranslaterService>('TranslaterService');
}

dispose() {
this._warningLeftElement?.remove();
Expand Down
43 changes: 30 additions & 13 deletions packages/empty-warning-component/src/slick-empty-warning.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { EmptyWarning, GridOption, SlickGrid } from '@slickgrid-universal/common';
import { SlickEmptyWarningComponent } from './slick-empty-warning.component';
import { ContainerServiceStub } from '../../../test/containerServiceStub';
import { TranslateServiceStub } from '../../../test/translateServiceStub';

const GRID_UID = 'slickgrid_123456';
Expand All @@ -17,11 +18,13 @@ const gridStub = {
} as unknown as SlickGrid;

describe('Slick-Empty-Warning Component', () => {
let container: ContainerServiceStub;
let component: SlickEmptyWarningComponent;
let div: HTMLDivElement;
let translateService: TranslateServiceStub;

beforeEach(() => {
container = new ContainerServiceStub();
div = document.createElement('div');
const canvasLeft = document.createElement('div');
const canvasRight = document.createElement('div');
Expand All @@ -47,7 +50,8 @@ describe('Slick-Empty-Warning Component', () => {
});

it('should expect the Slick-Empty-Warning to return False when calling the "showEmptyDataMessage" method without a grid object defined', () => {
component = new SlickEmptyWarningComponent(null as any);
component = new SlickEmptyWarningComponent();
component.init(null as any, container);
const output = component.showEmptyDataMessage(false);

expect(component).toBeTruthy();
Expand All @@ -56,7 +60,8 @@ describe('Slick-Empty-Warning Component', () => {
});

it('should expect the Slick-Empty-Warning to be created and NOT be rendered when passing False as 2nd argument and component was never rendered', () => {
component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(false);

const componentLeftElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
Expand All @@ -69,7 +74,8 @@ describe('Slick-Empty-Warning Component', () => {
});

it('should expect the Slick-Empty-Warning to be created in both viewports and rendered and passing true as 2nd argument', () => {
component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true);

const componentLeftElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
Expand All @@ -85,7 +91,8 @@ describe('Slick-Empty-Warning Component', () => {
});

it('should expect the Slick-Empty-Warning to be created but not shown after calling the method twice with False on 2nd time', () => {
component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true);
component.showEmptyDataMessage(false);

Expand All @@ -105,7 +112,8 @@ describe('Slick-Empty-Warning Component', () => {
mockGridOptions.frozenColumn = 2;
(mockGridOptions.emptyDataWarning as EmptyWarning).hideFrozenLeftWarning = true;
(mockGridOptions.emptyDataWarning as EmptyWarning).hideFrozenRightWarning = false;
component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true);

const componentLeftElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
Expand All @@ -125,7 +133,8 @@ describe('Slick-Empty-Warning Component', () => {
it('should expect the Slick-Empty-Warning to be created and use different left margin when "leftViewportMarginLeft" is set', () => {
mockGridOptions.frozenColumn = -1;
(mockGridOptions.emptyDataWarning as EmptyWarning).leftViewportMarginLeft = '40%';
component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true);

const componentLeftElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
Expand All @@ -147,7 +156,8 @@ describe('Slick-Empty-Warning Component', () => {
(mockGridOptions.emptyDataWarning as EmptyWarning).rightViewportMarginLeft = '40%';
jest.spyOn(gridStub, 'getOptions').mockReturnValue(mockGridOptions);

component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true);

const componentLeftElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
Expand All @@ -168,7 +178,8 @@ describe('Slick-Empty-Warning Component', () => {
mockGridOptions.frozenColumn = 2;
(mockGridOptions.emptyDataWarning as EmptyWarning).leftViewportMarginLeft = '40%';
(mockGridOptions.emptyDataWarning as EmptyWarning).frozenLeftViewportMarginLeft = '15px';
component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true);

const componentLeftElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
Expand All @@ -189,7 +200,8 @@ describe('Slick-Empty-Warning Component', () => {
mockGridOptions.frozenColumn = 2;
(mockGridOptions.emptyDataWarning as EmptyWarning).leftViewportMarginLeft = '40%';
(mockGridOptions.emptyDataWarning as EmptyWarning).frozenRightViewportMarginLeft = '22px';
component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true);

const componentLeftElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
Expand All @@ -210,7 +222,8 @@ describe('Slick-Empty-Warning Component', () => {
mockGridOptions.frozenColumn = 2;
(mockGridOptions.emptyDataWarning as EmptyWarning).hideFrozenLeftWarning = false;
(mockGridOptions.emptyDataWarning as EmptyWarning).hideFrozenRightWarning = true;
component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true);

const componentLeftElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas.grid-canvas-left .slick-empty-data-warning') as HTMLSelectElement;
Expand All @@ -227,7 +240,8 @@ describe('Slick-Empty-Warning Component', () => {

it('should expect the Slick-Empty-Warning to change some options and display a different message when provided as an option', () => {
const mockOptions = { message: '<span class="fa fa-warning"></span> No Record found.', className: 'custom-class', marginTop: 22, marginLeft: 11 };
component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true, mockOptions);

const componentElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas .custom-class') as HTMLSelectElement;
Expand All @@ -242,7 +256,8 @@ describe('Slick-Empty-Warning Component', () => {

it('should expect the Slick-Empty-Warning provide html text and expect script to be sanitized out of the final html', () => {
const mockOptions = { message: `<script>alert('test')></script><span class="fa fa-warning"></span> No Record found.`, className: 'custom-class', marginTop: 22, marginLeft: 11 };
component = new SlickEmptyWarningComponent(gridStub);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true, mockOptions);

const componentElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas .custom-class') as HTMLSelectElement;
Expand All @@ -256,10 +271,12 @@ describe('Slick-Empty-Warning Component', () => {
});

it('should expect the Slick-Empty-Warning message to be translated to French when providing a Translater Service and "messageKey" property', () => {
container.registerInstance('TranslaterService', translateService);
mockGridOptions.enableTranslate = true;
translateService.use('fr');

component = new SlickEmptyWarningComponent(gridStub, translateService);
component = new SlickEmptyWarningComponent();
component.init(gridStub, container);
component.showEmptyDataMessage(true);
const componentElm = document.querySelector<HTMLSelectElement>('div.slickgrid_123456 .grid-canvas .slick-empty-data-warning') as HTMLSelectElement;

Expand Down
3 changes: 2 additions & 1 deletion packages/excel-export/src/excelExport.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
Constants,
ContainerService,
ExcelExportService as BaseExcelExportService,
ExternalResource,
FileType,
FieldType,
GridOption,
Expand All @@ -37,7 +38,7 @@ import {
ExcelWorksheet,
} from './interfaces/index';

export class ExcelExportService implements BaseExcelExportService {
export class ExcelExportService implements ExternalResource, BaseExcelExportService {
private _fileFormat = FileType.xlsx;
private _grid: SlickGrid;
private _locales: Locale;
Expand Down
5 changes: 3 additions & 2 deletions packages/text-export/src/textExport.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
Column,
Constants,
ContainerService,
TextExportService as BaseTextExportService,
ExternalResource,
FileType,
GridOption,
KeyTitlePair,
Expand All @@ -22,10 +22,11 @@ import {
SlickDataView,
SlickGrid,
TextExportOption,
TextExportService as BaseTextExportService,
TranslaterService,
} from '@slickgrid-universal/common';

export class TextExportService implements BaseTextExportService {
export class TextExportService implements ExternalResource, BaseTextExportService {
private _delimiter = ',';
private _exportQuoteWrapper = '';
private _exportOptions: TextExportOption;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
Editor,
ExtensionName,
ColumnFilter,
SlickEventHandler,
} from '@slickgrid-universal/common';
import { GraphqlService, GraphqlPaginatedResult, GraphqlServiceApi, GraphqlServiceOption } from '@slickgrid-universal/graphql';
import { SlickCompositeEditorComponent } from '@slickgrid-universal/composite-editor-component';
Expand All @@ -57,7 +58,7 @@ const mockConvertParentChildArray = jest.fn();
(backendUtilities.onBackendError as any) = mockBackendError;

declare const Slick: any;
const slickEventHandler = new MockSlickEventHandler();
const slickEventHandler = new MockSlickEventHandler() as SlickEventHandler;

const extensionServiceStub = {
bindDifferentExtensions: jest.fn(),
Expand Down Expand Up @@ -886,7 +887,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', ()
component.initialization(divContainer, slickEventHandler);

expect(TextExportService).toHaveBeenCalled();
expect(component.registeredResources.length).toBe(3); // TextExportService, GridService, GridStateService
expect(component.registeredResources.length).toBe(4); // TextExportService, GridService, GridStateService, SlickEmptyCompositeEditorComponent
expect(component.registeredResources[0] instanceof TextExportService).toBeTrue();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
DataViewOption,
ExtensionList,
ExtensionName,
ExternalResource,
EventNamingStyle,
GlobalGridOptions,
GridOption,
Expand Down Expand Up @@ -99,7 +100,7 @@ export class SlickVanillaGridBundle {
private _eventHandler: SlickEventHandler;
private _extensions: ExtensionList<any, any> | undefined;
private _paginationOptions: Pagination | undefined;
private _registeredResources: any[] = [];
private _registeredResources: ExternalResource[] = [];
private _slickgridInitialized = false;
private _slickerGridInstances: SlickerGridInstance | undefined;
backendServiceApi: BackendServiceApi | undefined;
Expand Down Expand Up @@ -384,8 +385,6 @@ export class SlickVanillaGridBundle {
if (!hierarchicalDataset && !this.gridOptions.backendServiceApi) {
this.dataset = dataset || [];
}

this.slickEmptyWarning = new SlickEmptyWarningComponent(this.slickGrid, this.translaterService);
}

emptyGridContainerElm() {
Expand Down Expand Up @@ -628,6 +627,10 @@ export class SlickVanillaGridBundle {
this.extensionService.translateColumnHeaders();
}

// also initialize (render) the empty warning component
this.slickEmptyWarning = new SlickEmptyWarningComponent();
this._registeredResources.push(this.slickEmptyWarning);

// also initialize (render) the pagination component
if (this.gridOptions.enableCompositeEditor && this.gridOptions.useSalesforceDefaultGridOptions) {
this.slickCompositeEditor = new SlickCompositeEditorComponent();
Expand Down

0 comments on commit 7ca42f4

Please sign in to comment.