UNPKG

ngx-gem-spaas

Version:

This library contains services, components, images and styles to provide a unified look and way-of-working throughout GEM SPaaS.

349 lines (340 loc) 18.4 kB
import * as i0 from '@angular/core'; import { Injectable, Component, Input, EventEmitter, Output, NgModule } from '@angular/core'; import * as i4 from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip'; import { CommonModule } from '@angular/common'; import * as i1 from 'ngx-gem-spaas'; import { UtilsService, BaseComponent } from 'ngx-gem-spaas'; import { takeUntil } from 'rxjs/operators'; import * as ExcelJS from 'exceljs'; import { saveAs } from 'file-saver'; import * as i3 from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon'; class ExcelService { constructor(settingsService, snackbarService) { this.settingsService = settingsService; this.snackbarService = snackbarService; this.settings = this.settingsService.getSettings(); } exportFile(sheetsToExport, fileName, colsToInclude = [], colsToExclude = [], isToStringify = false) { const workbook = new ExcelJS.Workbook(); const sheetsCreated = []; for (const sheet of sheetsToExport) { // check that a sheet with the same name has not been created yet (throws an error in ExcelJS) if (!sheetsCreated.includes(sheet.sheetName)) { // IF NOT AN ARRAY THEN WRAP IN ARRAY let arrData = Array.isArray(sheet.sheetData) ? UtilsService.copy(sheet.sheetData) : UtilsService.copy([sheet.sheetData]); // SOME COLUMNS CONTAIN OBJECTS: STRINGIFY if (isToStringify) { for (const curData of arrData) { for (const curCol in curData) { if (curData.hasOwnProperty(curCol) && UtilsService.checkJSON(JSON.stringify(curData[curCol]))) { curData[curCol] = JSON.stringify(curData[curCol]); } } } } // add sheet const worksheet = workbook.addWorksheet(sheet.sheetName); // add headers let headers = colsToInclude?.length ? colsToInclude : Object.keys(sheet.sheetData[0]); if (colsToExclude?.length) { headers = headers.filter((h) => !colsToExclude.includes(h)); } worksheet.addRow(headers); // add data for (const row of sheet.sheetData) { let r = []; for (const header of headers) { if (this.settings.exportExtension === 'csv' && this.settings.decimalSeparator === 'comma') { row[header] = typeof row[header] === 'number' ? ('' + row[header]).replace('.', ',') : row[header]; } r.push(row[header]); } worksheet.addRow(r); } sheetsCreated.push(sheet.sheetName); } else { this.snackbarService.error(`Duplicate sheet names: a sheet with name "${sheet.sheetName}" has already been created!`); } } // CLEAN FILENAME const fName = fileName.replace(/ /g, '_'); if (this.settings?.exportExtension === 'xlsx') { workbook.xlsx.writeBuffer() .then((buffer) => { saveAs(new Blob([buffer]), fName + '.' + this.settings.exportExtension); }); } else { workbook.csv.writeBuffer({ formatterOptions: { delimiter: this.settings.getCsvDelimiter() } }).then((buffer) => { saveAs(new Blob([buffer]), fName + '.' + this.settings.exportExtension); }); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ExcelService, deps: [{ token: i1.SettingsService }, { token: i1.SnackbarService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ExcelService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ExcelService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.SettingsService }, { type: i1.SnackbarService }] }); class ExcelExportComponent extends BaseComponent { constructor(excelExportService, settingsService) { super(); this.excelExportService = excelExportService; this.settingsService = settingsService; // TOOLTIP MESSAGE this.tooltipMsg = ''; // FILENAME FOR THE EXCEL FILE this.fileName = ''; // DATE TO EXPORT this.sheets = []; this.settings = null; this.getSettings(); } // ******************************************************************************************************** // LOAD DATA // ******************************************************************************************************** getSettings() { this.settingsService.onNewSettings() .pipe(takeUntil(this.onDestroy$)) .subscribe((settings) => { this.settings = settings; if (!this.tooltipMsg) { // set default label this.tooltipMsg = 'export to ' + settings.exportExtension; } }); } // ******************************************************************************************************** // DOM // ******************************************************************************************************** // EVENT LISTENERS onExport() { if (!this.settings) { throw new Error('something is wrong with your library implementation: no settings received from settings.service'); } this.excelExportService.exportFile(this.sheets, this.fileName); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ExcelExportComponent, deps: [{ token: ExcelService }, { token: i1.SettingsService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ExcelExportComponent, selector: "spaas-excel-export", inputs: { tooltipMsg: "tooltipMsg", fileName: "fileName", sheets: "sheets" }, usesInheritance: true, ngImport: i0, template: "<mat-icon (click)=\"onExport()\"\r\n fontIcon=\"download\"\r\n matTooltipPosition=\"below\"\r\n [matTooltip]=\"tooltipMsg\">\r\n</mat-icon>\r\n", styles: [""], dependencies: [{ kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ExcelExportComponent, decorators: [{ type: Component, args: [{ selector: 'spaas-excel-export', template: "<mat-icon (click)=\"onExport()\"\r\n fontIcon=\"download\"\r\n matTooltipPosition=\"below\"\r\n [matTooltip]=\"tooltipMsg\">\r\n</mat-icon>\r\n" }] }], ctorParameters: () => [{ type: ExcelService }, { type: i1.SettingsService }], propDecorators: { tooltipMsg: [{ type: Input }], fileName: [{ type: Input, args: [{ required: true }] }], sheets: [{ type: Input, args: [{ required: true }] }] } }); class ExcelImportComponent extends BaseComponent { static parseWorksheet(worksheet) { const newSheet = { sheetData: [], sheetName: worksheet.name }; const sheetColumns = []; worksheet.eachRow({ includeEmpty: false }, (row, rowNumber) => { // set columns if not set yet // do not rely on rowNumber to define the first row (being zero or one), it's the actual row number in excel if (!sheetColumns.length) { // take column header values from first row as attributes for the rows row.eachCell({ includeEmpty: true }, (cell, colNumber) => { sheetColumns.push('' + cell.value); }); } else { // parse all other rows (so except the first one, which is considered to contain headers) let rowData = {}; row.eachCell({ includeEmpty: true }, (cell, colNumber) => { // colNumber is 1-based !! if (sheetColumns[colNumber - 1] !== 'null') { rowData[sheetColumns[colNumber - 1]] = cell.formula ? cell.result : cell.value; } }); newSheet.sheetData.push(rowData); } }); return newSheet; } constructor(settingsService, snackbarService) { super(); this.settingsService = settingsService; this.snackbarService = snackbarService; // TOOLTIP MESSAGE this.tooltipMsg = ''; // EMIT THE IMPORTED SHEETS this.sheetsImported = new EventEmitter(); this.rawFileContent = null; this.settings = null; this.getSettings(); } // ******************************************************************************************************** // LOAD DATA // ******************************************************************************************************** getSettings() { this.settingsService.onNewSettings() .pipe(takeUntil(this.onDestroy$)) .subscribe((settings) => { this.settings = settings; if (!this.tooltipMsg) { // set default label this.tooltipMsg = 'import from ' + settings.exportExtension; } }); } // ******************************************************************************************************** // PROCESS DATA // ******************************************************************************************************** readFile(e) { this.rawFileContent = null; if (e?.target?.files && e.target.files.length === 1) { const file = e.target.files[0]; // READ FILE IF EXCEL const reader = new FileReader(); const isExcel = this.settings?.exportExtension === 'xlsx' && file.type.match('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); const isCsv = this.settings?.exportExtension === 'csv' && file.type.match('text/csv'); if (isExcel) { reader.onloadend = () => { // RESET UPLOADER e.target.value = null; // THEN PROCESS RESULT this.rawFileContent = reader.result; if (this.rawFileContent) { this.parseExcel(); } else { this.snackbarService.message('File does not contain valid data'); } }; reader.readAsArrayBuffer(file); } else if (isCsv) { reader.onloadend = () => { // RESET UPLOADER e.target.value = null; // THEN PROCESS RESULT this.rawFileContent = reader.result; if (this.rawFileContent) { this.parseCsv(); } else { this.snackbarService.message('File does not contain valid data'); } }; reader.readAsText(file); } else { // neither a valid xlsx, nor a valid csv this.snackbarService.message(`File type not supported (should be .${this.settings?.exportExtension})`); } } } parseExcel() { const sheets = []; const workBook = new ExcelJS.Workbook(); let hasAnyData = false; workBook.xlsx.load(this.rawFileContent) .then((wb) => { if (wb.worksheets.length) { wb.eachSheet((worksheet, sheetId) => { const newSheet = ExcelImportComponent.parseWorksheet(worksheet); hasAnyData = hasAnyData || newSheet.sheetData.length > 0; sheets.push(newSheet); }); this.emitSheets(hasAnyData, sheets); } else { this.snackbarService.error('Your file does not contain any sheets'); } }) .catch((reason) => { this.snackbarService.error('There was an error importing your file: ' + reason); return; }); } parseCsv() { const sheet = { sheetName: 'csv import', sheetData: [] }; let dataHeaders = []; const rows = ('' + this.rawFileContent).split('\n') || []; for (const row of rows) { const cells = row.split(this.settings?.getCsvDelimiter() || ','); if (!dataHeaders.length) { // take first row with data as headers dataHeaders = cells; continue; } const newRow = {}; for (let cellIdx = 0; cellIdx < cells.length; cellIdx++) { newRow[dataHeaders[cellIdx]] = cells[cellIdx]; } sheet.sheetData.push(newRow); } this.emitSheets(sheet.sheetData.length > 0, [sheet]); } emitSheets(hasAnyData, sheets) { if (!hasAnyData) { this.snackbarService.error('Your file does not contain any data, are you sure you uploaded the correct one?'); } else { this.sheetsImported.emit(sheets.sort((a, b) => a.sheetName < b.sheetName ? -1 : 1)); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ExcelImportComponent, deps: [{ token: i1.SettingsService }, { token: i1.SnackbarService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ExcelImportComponent, selector: "spaas-excel-import", inputs: { tooltipMsg: "tooltipMsg" }, outputs: { sheetsImported: "sheetsImported" }, usesInheritance: true, ngImport: i0, template: "<label>\r\n <mat-icon [matTooltip]=\"tooltipMsg\"\r\n matTooltipPosition=\"below\"\r\n fontIcon=\"file_upload\">\r\n </mat-icon>\r\n <input type=\"file\"\r\n (change)=\"readFile($event);\">\r\n</label>\r\n", styles: ["input[type=file]{display:none}\n"], dependencies: [{ kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ExcelImportComponent, decorators: [{ type: Component, args: [{ selector: 'spaas-excel-import', template: "<label>\r\n <mat-icon [matTooltip]=\"tooltipMsg\"\r\n matTooltipPosition=\"below\"\r\n fontIcon=\"file_upload\">\r\n </mat-icon>\r\n <input type=\"file\"\r\n (change)=\"readFile($event);\">\r\n</label>\r\n", styles: ["input[type=file]{display:none}\n"] }] }], ctorParameters: () => [{ type: i1.SettingsService }, { type: i1.SnackbarService }], propDecorators: { tooltipMsg: [{ type: Input }], sheetsImported: [{ type: Output }] } }); class SpaasExcelModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasExcelModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: SpaasExcelModule, declarations: [ExcelExportComponent, ExcelImportComponent], imports: [CommonModule, MatIconModule, MatTooltipModule], exports: [ExcelExportComponent, ExcelImportComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasExcelModule, imports: [CommonModule, MatIconModule, MatTooltipModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasExcelModule, decorators: [{ type: NgModule, args: [{ declarations: [ ExcelExportComponent, ExcelImportComponent, ], exports: [ ExcelExportComponent, ExcelImportComponent, ], imports: [ CommonModule, MatIconModule, MatTooltipModule, ], providers: [] }] }] }); class ExcelSheetModel { constructor() { this.sheetName = ''; this.sheetData = []; } } // MODULE /** * Generated bundle index. Do not edit. */ export { ExcelExportComponent, ExcelImportComponent, ExcelService, ExcelSheetModel, SpaasExcelModule }; //# sourceMappingURL=ngx-gem-spaas-excel.mjs.map