diff --git a/packages/common/src/extensions/__tests__/gridMenuExtension.spec.ts b/packages/common/src/extensions/__tests__/gridMenuExtension.spec.ts
index 02467604d..3106c35df 100644
--- a/packages/common/src/extensions/__tests__/gridMenuExtension.spec.ts
+++ b/packages/common/src/extensions/__tests__/gridMenuExtension.spec.ts
@@ -3,7 +3,7 @@ import { Column, GridOption } from '../../interfaces/index';
import { GridMenuExtension } from '../gridMenuExtension';
import { ExtensionUtility } from '../extensionUtility';
import { SharedService } from '../../services/shared.service';
-import { /*ExcelExportService, ExportService,*/ FilterService, SortService } from '../../services';
+import { ExcelExportService, ExportService, FilterService, SortService } from '../../services';
import { TranslateServiceStub } from '../../../../../test/translateServiceStub';
declare const Slick: any;
@@ -13,13 +13,13 @@ const gridId = 'grid1';
const gridUid = 'slickgrid_124343';
const containerId = 'demo-container';
-// const excelExportServiceStub = {
-// exportToExcel: jest.fn(),
-// } as unknown as ExcelExportService;
+const excelExportServiceStub = {
+ exportToExcel: jest.fn(),
+} as unknown as ExcelExportService;
-// const exportServiceStub = {
-// exportToFile: jest.fn(),
-// } as unknown as ExportService;
+const exportServiceStub = {
+ exportToFile: jest.fn(),
+} as unknown as ExportService;
const filterServiceStub = {
clearFilters: jest.fn(),
@@ -120,7 +120,7 @@ describe('gridMenuExtension', () => {
sharedService = new SharedService();
translateService = new TranslateServiceStub();
extensionUtility = new ExtensionUtility(sharedService, translateService);
- extension = new GridMenuExtension(extensionUtility, filterServiceStub, sharedService, sortServiceStub, translateService);
+ extension = new GridMenuExtension(excelExportServiceStub, exportServiceStub, extensionUtility, filterServiceStub, sharedService, sortServiceStub, translateService);
translateService.setLocale('fr');
});
@@ -574,51 +574,51 @@ describe('gridMenuExtension', () => {
expect(refreshSpy).toHaveBeenCalled();
});
- // it('should call "exportToExcel" set when the command triggered is "export-excel"', () => {
- // const excelExportSpy = jest.spyOn(excelExportServiceStub, 'exportToExcel');
- // const onCommandSpy = jest.spyOn(SharedService.prototype.gridOptions.gridMenu, 'onCommand');
-
- // const instance = extension.register();
- // instance.onCommand.notify({ grid: gridStub, command: 'export-excel' }, new Slick.EventData(), gridStub);
-
- // expect(onCommandSpy).toHaveBeenCalled();
- // expect(excelExportSpy).toHaveBeenCalledWith({
- // filename: 'export',
- // format: FileType.xlsx,
- // });
- // });
-
- // it('should call "exportToFile" with CSV set when the command triggered is "export-csv"', () => {
- // const exportSpy = jest.spyOn(exportServiceStub, 'exportToFile');
- // const onCommandSpy = jest.spyOn(SharedService.prototype.gridOptions.gridMenu, 'onCommand');
-
- // const instance = extension.register();
- // instance.onCommand.notify({ grid: gridStub, command: 'export-csv' }, new Slick.EventData(), gridStub);
-
- // expect(onCommandSpy).toHaveBeenCalled();
- // expect(exportSpy).toHaveBeenCalledWith({
- // delimiter: DelimiterType.comma,
- // filename: 'export',
- // format: FileType.csv,
- // useUtf8WithBom: true
- // });
- // });
-
- // it('should call "exportToFile" with CSV set when the command triggered is "export-text-delimited"', () => {
- // const exportSpy = jest.spyOn(exportServiceStub, 'exportToFile');
- // const onCommandSpy = jest.spyOn(SharedService.prototype.gridOptions.gridMenu, 'onCommand');
-
- // const instance = extension.register();
- // instance.onCommand.notify({ grid: gridStub, command: 'export-text-delimited' }, new Slick.EventData(), gridStub);
-
- // expect(onCommandSpy).toHaveBeenCalled();
- // expect(exportSpy).toHaveBeenCalledWith({
- // delimiter: DelimiterType.tab,
- // filename: 'export',
- // format: FileType.txt,
- // useUtf8WithBom: true
- // });
- // });
+ it('should call "exportToExcel" set when the command triggered is "export-excel"', () => {
+ const excelExportSpy = jest.spyOn(excelExportServiceStub, 'exportToExcel');
+ const onCommandSpy = jest.spyOn(SharedService.prototype.gridOptions.gridMenu, 'onCommand');
+
+ const instance = extension.register();
+ instance.onCommand.notify({ grid: gridStub, command: 'export-excel' }, new Slick.EventData(), gridStub);
+
+ expect(onCommandSpy).toHaveBeenCalled();
+ expect(excelExportSpy).toHaveBeenCalledWith({
+ filename: 'export',
+ format: FileType.xlsx,
+ });
+ });
+
+ it('should call "exportToFile" with CSV set when the command triggered is "export-csv"', () => {
+ const exportSpy = jest.spyOn(exportServiceStub, 'exportToFile');
+ const onCommandSpy = jest.spyOn(SharedService.prototype.gridOptions.gridMenu, 'onCommand');
+
+ const instance = extension.register();
+ instance.onCommand.notify({ grid: gridStub, command: 'export-csv' }, new Slick.EventData(), gridStub);
+
+ expect(onCommandSpy).toHaveBeenCalled();
+ expect(exportSpy).toHaveBeenCalledWith({
+ delimiter: DelimiterType.comma,
+ filename: 'export',
+ format: FileType.csv,
+ useUtf8WithBom: true
+ });
+ });
+
+ it('should call "exportToFile" with CSV set when the command triggered is "export-text-delimited"', () => {
+ const exportSpy = jest.spyOn(exportServiceStub, 'exportToFile');
+ const onCommandSpy = jest.spyOn(SharedService.prototype.gridOptions.gridMenu, 'onCommand');
+
+ const instance = extension.register();
+ instance.onCommand.notify({ grid: gridStub, command: 'export-text-delimited' }, new Slick.EventData(), gridStub);
+
+ expect(onCommandSpy).toHaveBeenCalled();
+ expect(exportSpy).toHaveBeenCalledWith({
+ delimiter: DelimiterType.tab,
+ filename: 'export',
+ format: FileType.txt,
+ useUtf8WithBom: true
+ });
+ });
it('should call the grid "setHeaderRowVisibility" method when the command triggered is "toggle-filter"', () => {
gridOptionsMock.showHeaderRow = false;
@@ -723,7 +723,7 @@ describe('gridMenuExtension', () => {
describe('without Translate Service', () => {
beforeEach(() => {
translateService = null;
- extension = new GridMenuExtension({} as ExtensionUtility, filterServiceStub, { gridOptions: { enableTranslate: true } } as SharedService, {} as SortService, translateService);
+ extension = new GridMenuExtension(excelExportServiceStub, exportServiceStub, {} as ExtensionUtility, filterServiceStub, { gridOptions: { enableTranslate: true } } as SharedService, {} as SortService, translateService);
});
it('should throw an error if "enableTranslate" is set but the I18N Service is null', () => {
diff --git a/packages/common/src/extensions/gridMenuExtension.ts b/packages/common/src/extensions/gridMenuExtension.ts
index 3e333429a..355d63795 100644
--- a/packages/common/src/extensions/gridMenuExtension.ts
+++ b/packages/common/src/extensions/gridMenuExtension.ts
@@ -14,8 +14,8 @@ import {
ExtensionName,
FileType,
} from '../enums/index';
-// import { ExcelExportService } from '../services/excelExport.service';
-// import { ExportService } from '../services/export.service';
+import { ExcelExportService } from '../services/excelExport.service';
+import { ExportService } from '../services/export.service';
import { ExtensionUtility } from './extensionUtility';
import { FilterService } from '../services/filter.service';
import { SortService } from '../services/sort.service';
@@ -35,8 +35,8 @@ export class GridMenuExtension implements Extension {
private _userOriginalGridMenu: GridMenu;
constructor(
- // private excelExportService: ExcelExportService,
- // private exportService: ExportService,
+ private excelExportService: ExcelExportService,
+ private exportService: ExportService,
private extensionUtility: ExtensionUtility,
private filterService: FilterService,
private sharedService: SharedService,
@@ -360,26 +360,26 @@ export class GridMenuExtension implements Extension {
this.sharedService.dataView.refresh();
break;
case 'export-csv':
- // this.exportService.exportToFile({
- // delimiter: DelimiterType.comma,
- // filename: 'export',
- // format: FileType.csv,
- // useUtf8WithBom: true,
- // });
+ this.exportService.exportToFile({
+ delimiter: DelimiterType.comma,
+ filename: 'export',
+ format: FileType.csv,
+ useUtf8WithBom: true,
+ });
break;
case 'export-excel':
- // this.excelExportService.exportToExcel({
- // filename: 'export',
- // format: FileType.xlsx,
- // });
+ this.excelExportService.exportToExcel({
+ filename: 'export',
+ format: FileType.xlsx,
+ });
break;
case 'export-text-delimited':
- // this.exportService.exportToFile({
- // delimiter: DelimiterType.tab,
- // filename: 'export',
- // format: FileType.txt,
- // useUtf8WithBom: true,
- // });
+ this.exportService.exportToFile({
+ delimiter: DelimiterType.tab,
+ filename: 'export',
+ format: FileType.txt,
+ useUtf8WithBom: true,
+ });
break;
case 'toggle-filter':
const showHeaderRow = this.sharedService && this.sharedService.gridOptions && this.sharedService.gridOptions.showHeaderRow || false;
diff --git a/packages/common/src/formatters/__tests__/treeFormatter.spec.ts b/packages/common/src/formatters/__tests__/treeFormatter.spec.ts
new file mode 100644
index 000000000..fa028badd
--- /dev/null
+++ b/packages/common/src/formatters/__tests__/treeFormatter.spec.ts
@@ -0,0 +1,95 @@
+import { Column } from '../../interfaces/index';
+import { treeFormatter } from '../treeFormatter';
+
+const dataViewStub = {
+ getIdxById: jest.fn(),
+ getItemByIdx: jest.fn(),
+ getIdPropertyName: jest.fn(),
+};
+
+const gridStub = {
+ getData: jest.fn(),
+};
+
+describe('the Uppercase Formatter', () => {
+ let dataset;
+
+ beforeEach(() => {
+ dataset = [
+ { id: 0, firstName: 'John', lastName: 'Smith', email: 'john.smith@movie.com', parentId: null, indent: 0 },
+ { id: 1, firstName: 'Jane', lastName: 'Doe', email: 'jane.doe@movie.com', parentId: 0, indent: 1 },
+ { id: 2, firstName: 'Bob', lastName: 'Cane', email: 'bob.cane@movie.com', parentId: 1, indent: 2, __collapsed: true },
+ { id: 2, firstName: 'Barbara', lastName: 'Cane', email: 'barbara.cane@movie.com', parentId: null, indent: 0, __collapsed: true },
+ ];
+ });
+
+ it('should throw an error when oarams are mmissing', () => {
+ expect(() => treeFormatter(1, 1, 'blah', {} as Column, {}))
+ .toThrowError('You must provide a valid Tree Data column, it seems that there are no tree level found in this row');
+ });
+
+ it('should return empty string when DataView is not correctly formed', () => {
+ const output = treeFormatter(1, 1, '', { treeData: { levelPropName: 'indent' } } as Column, dataset[1]);
+ expect(output).toBe('');
+ });
+
+ it('should return empty string when value is null', () => {
+ const output = treeFormatter(1, 1, null, { treeData: { levelPropName: 'indent' } } as Column, dataset[1]);
+ expect(output).toBe('');
+ });
+
+ it('should return empty string when value is undefined', () => {
+ const output = treeFormatter(1, 1, undefined, { treeData: { levelPropName: 'indent' } } as Column, dataset[1]);
+ expect(output).toBe('');
+ });
+
+ it('should return empty string when item is undefined', () => {
+ const output = treeFormatter(1, 1, 'blah', { treeData: { levelPropName: 'indent' } } as Column, undefined);
+ expect(output).toBe('');
+ });
+
+ it('should return a span without any icon and ', () => {
+ jest.spyOn(gridStub, 'getData').mockReturnValue(dataViewStub);
+ jest.spyOn(dataViewStub, 'getIdxById').mockReturnValue(1);
+ jest.spyOn(dataViewStub, 'getItemByIdx').mockReturnValue(dataset[0]);
+
+ const output = treeFormatter(1, 1, dataset[0]['firstName'], { treeData: { levelPropName: 'indent' } } as Column, dataset[0], gridStub);
+ expect(output).toBe(` John`);
+ });
+
+ it('should return a span without any icon and 15px indentation of a tree level 1', () => {
+ jest.spyOn(gridStub, 'getData').mockReturnValue(dataViewStub);
+ jest.spyOn(dataViewStub, 'getIdxById').mockReturnValue(1);
+ jest.spyOn(dataViewStub, 'getItemByIdx').mockReturnValue(dataset[1]);
+
+ const output = treeFormatter(1, 1, dataset[1]['firstName'], { treeData: { levelPropName: 'indent' } } as Column, dataset[1], gridStub);
+ expect(output).toBe(` Jane`);
+ });
+
+ it('should return a span without any icon and 30px indentation of a tree level 2', () => {
+ jest.spyOn(gridStub, 'getData').mockReturnValue(dataViewStub);
+ jest.spyOn(dataViewStub, 'getIdxById').mockReturnValue(1);
+ jest.spyOn(dataViewStub, 'getItemByIdx').mockReturnValue(dataset[1]);
+
+ const output = treeFormatter(1, 1, dataset[2]['firstName'], { treeData: { levelPropName: 'indent' } } as Column, dataset[2], gridStub);
+ expect(output).toBe(` Bob`);
+ });
+
+ it('should return a span with expanded icon and 15px indentation of a tree level 1 when current item is greater than next item', () => {
+ jest.spyOn(gridStub, 'getData').mockReturnValue(dataViewStub);
+ jest.spyOn(dataViewStub, 'getIdxById').mockReturnValue(1);
+ jest.spyOn(dataViewStub, 'getItemByIdx').mockReturnValue(dataset[2]);
+
+ const output = treeFormatter(1, 1, dataset[1]['firstName'], { treeData: { levelPropName: 'indent' } } as Column, dataset[1], gridStub);
+ expect(output).toBe(` Jane`);
+ });
+
+ it('should return a span with collapsed icon and 0px indentation of a tree level 0 when current item is lower than next item', () => {
+ jest.spyOn(gridStub, 'getData').mockReturnValue(dataViewStub);
+ jest.spyOn(dataViewStub, 'getIdxById').mockReturnValue(1);
+ jest.spyOn(dataViewStub, 'getItemByIdx').mockReturnValue(dataset[1]);
+
+ const output = treeFormatter(1, 1, dataset[3]['firstName'], { treeData: { levelPropName: 'indent' } } as Column, dataset[3], gridStub);
+ expect(output).toBe(` Barbara`);
+ });
+});
diff --git a/packages/common/src/formatters/treeFormatter.ts b/packages/common/src/formatters/treeFormatter.ts
index c39e45a14..d51015764 100644
--- a/packages/common/src/formatters/treeFormatter.ts
+++ b/packages/common/src/formatters/treeFormatter.ts
@@ -5,12 +5,15 @@ export const treeFormatter: Formatter = (row: number, cell: number, value: any,
const indentMarginLeft = columnDef.treeData?.indentMarginLeft || 15;
const dataView = grid && grid.getData();
+ if (value === null || value === undefined || dataContext === undefined) {
+ return '';
+ }
+
if (!dataContext.hasOwnProperty(treeLevelPropName)) {
throw new Error('You must provide a valid Tree Data column, it seems that there are no tree level found in this row');
}
if (dataView && dataView.getIdxById && dataView.getItemByIdx) {
- if (value === null || value === undefined || dataContext === undefined) { return ''; }
value = value.replace(/&/g, '&').replace(//g, '>');
const identifierPropName = dataView.getIdPropertyName() || 'id';
const spacer = ``;
diff --git a/packages/common/src/services/excelExport.service.ts b/packages/common/src/services/excelExport.service.ts
new file mode 100644
index 000000000..b6149dbcb
--- /dev/null
+++ b/packages/common/src/services/excelExport.service.ts
@@ -0,0 +1,21 @@
+import { ExcelExportOption } from '../interfaces/index';
+
+export abstract class ExcelExportService {
+ /**
+ * Initialize the Export Service
+ * @param grid
+ * @param dataView
+ */
+ init(grid: any, dataView: any): void {
+ console.log('ExcelExportService the "init" method must be implemented');
+ }
+
+ /**
+ * Method to return the current locale used by the App
+ * @return {string} current locale
+ */
+ exportToExcel(options: ExcelExportOption): Promise {
+ console.log('ExcelExportService the "exportToExcel" method must be implemented');
+ return new Promise((resolve) => resolve(true));
+ }
+}
diff --git a/packages/common/src/services/export.service.ts b/packages/common/src/services/export.service.ts
new file mode 100644
index 000000000..53ca03fd3
--- /dev/null
+++ b/packages/common/src/services/export.service.ts
@@ -0,0 +1,21 @@
+import { ExportOption } from '../interfaces/index';
+
+export abstract class ExportService {
+ /**
+ * Initialize the Export Service
+ * @param grid
+ * @param dataView
+ */
+ init(grid: any, dataView: any): void {
+ console.log('ExportService the "init" method must be implemented');
+ }
+
+ /**
+ * Method to return the current locale used by the App
+ * @return {string} current locale
+ */
+ exportToFile(options: ExportOption): Promise {
+ console.log('ExportService the "exportToFile" method must be implemented');
+ return new Promise((resolve) => resolve(true));
+ }
+}
diff --git a/packages/common/src/services/index.ts b/packages/common/src/services/index.ts
index 1cab5a3a5..f6256707a 100644
--- a/packages/common/src/services/index.ts
+++ b/packages/common/src/services/index.ts
@@ -1,5 +1,7 @@
export * from './collection.service';
+export * from './excelExport.service';
export * from './export-utilities';
+export * from './export.service';
export * from './extension.service';
export * from './filter.service';
export * from './grid.service';
@@ -8,5 +10,5 @@ export * from './groupingAndColspan.service';
export * from './pubSub.service';
export * from './shared.service';
export * from './sort.service';
-export * from './utilities';
export * from './translater.service';
+export * from './utilities';
diff --git a/packages/vanilla-bundle/src/services/excelExport.service.ts b/packages/vanilla-bundle/src/services/excelExport.service.ts
new file mode 100644
index 000000000..0646cb848
--- /dev/null
+++ b/packages/vanilla-bundle/src/services/excelExport.service.ts
@@ -0,0 +1,11 @@
+import { ExcelExportService, ExcelExportOption } from '@slickgrid-universal/common';
+
+
+export class ExcelExportServicer implements ExcelExportService {
+ init(grid: any, dataView: any): void {
+ }
+
+ exportToExcel(options: ExcelExportOption): Promise {
+ return new Promise((resolve) => resolve(true));
+ }
+}
diff --git a/packages/vanilla-bundle/src/services/export.service.ts b/packages/vanilla-bundle/src/services/export.service.ts
new file mode 100644
index 000000000..162a18aab
--- /dev/null
+++ b/packages/vanilla-bundle/src/services/export.service.ts
@@ -0,0 +1,10 @@
+import { ExportService, ExportOption } from '@slickgrid-universal/common';
+
+export class ExportServicer implements ExportService {
+ init(grid: any, dataView: any): void {
+ }
+
+ exportToFile(options: ExportOption): Promise {
+ return new Promise((resolve) => resolve(true));
+ }
+}
diff --git a/packages/vanilla-bundle/src/services/index.ts b/packages/vanilla-bundle/src/services/index.ts
index 38769fbaf..1af0e36c8 100644
--- a/packages/vanilla-bundle/src/services/index.ts
+++ b/packages/vanilla-bundle/src/services/index.ts
@@ -1,2 +1,4 @@
export * from './eventPubSub.service';
+export * from './excelExport.service';
+export * from './export.service';
export * from './translate.service';
diff --git a/packages/vanilla-bundle/src/vanilla-grid-bundle.ts b/packages/vanilla-bundle/src/vanilla-grid-bundle.ts
index 789b0227e..14ad07870 100644
--- a/packages/vanilla-bundle/src/vanilla-grid-bundle.ts
+++ b/packages/vanilla-bundle/src/vanilla-grid-bundle.ts
@@ -43,6 +43,8 @@ import {
SlickgridConfig,
} from '@slickgrid-universal/common';
+import { ExportServicer } from './services/export.service';
+import { ExcelExportServicer } from './services/excelExport.service';
import { TranslateService } from './services/translate.service';
import { EventPubSubService } from './services/eventPubSub.service';
@@ -79,6 +81,8 @@ export class VanillaGridBundle {
columnPickerExtension: ColumnPickerExtension;
checkboxExtension: CheckboxSelectorExtension;
draggableGroupingExtension: DraggableGroupingExtension;
+ excelExportServicer: ExcelExportServicer;
+ exportServicer: ExportServicer;
gridMenuExtension: GridMenuExtension;
groupItemMetaProviderExtension: GroupItemMetaProviderExtension;
headerButtonExtension: HeaderButtonExtension;
@@ -119,6 +123,14 @@ export class VanillaGridBundle {
this.refreshGridData(dataset);
}
+ get datasetHierarchical(): any[] {
+ return this.sharedService.hierarchicalDataset;
+ }
+
+ set datasetHierarchical(hierarchicalDataset: any[]) {
+ this.sharedService.hierarchicalDataset = hierarchicalDataset;
+ }
+
constructor(gridContainerElm: Element, columnDefs?: Column[], options?: GridOption, dataset?: any[]) {
// make sure that the grid container has the "slickgrid-container" css class exist since we use it for slickgrid styling
gridContainerElm.classList.add('slickgrid-container');
@@ -128,6 +140,8 @@ export class VanillaGridBundle {
this.dataset = dataset || [];
this._eventPubSubService = new EventPubSubService(gridContainerElm);
+ this.exportServicer = new ExportServicer();
+ this.excelExportServicer = new ExcelExportServicer();
this.gridEventService = new GridEventService();
const slickgridConfig = new SlickgridConfig();
this.sharedService = new SharedService();
@@ -145,7 +159,7 @@ export class VanillaGridBundle {
this.columnPickerExtension = new ColumnPickerExtension(this.extensionUtility, this.sharedService);
this.checkboxExtension = new CheckboxSelectorExtension(this.extensionUtility, this.sharedService);
this.draggableGroupingExtension = new DraggableGroupingExtension(this.extensionUtility, this.sharedService);
- this.gridMenuExtension = new GridMenuExtension(this.extensionUtility, this.filterService, this.sharedService, this.sortService, this.translateService);
+ this.gridMenuExtension = new GridMenuExtension(this.excelExportServicer, this.exportServicer, this.extensionUtility, this.filterService, this.sharedService, this.sortService, this.translateService);
this.groupItemMetaProviderExtension = new GroupItemMetaProviderExtension(this.sharedService);
this.headerButtonExtension = new HeaderButtonExtension(this.extensionUtility, this.sharedService);
this.headerMenuExtension = new HeaderMenuExtension(this.extensionUtility, this.filterService, this._eventPubSubService, this.sharedService, this.sortService, this.translateService);