@universis/ngx-tables 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,16 +3,17 @@ import * as jQuery_ from 'jquery';
3
3
  import 'datatables.net';
4
4
  import 'datatables.net-scroller';
5
5
  import 'datatables.net-colreorder';
6
+ import 'datatables.net-buttons';
6
7
  import 'rxjs/add/observable/combineLatest';
7
8
  import { HttpClient } from '@angular/common/http';
8
- import { ClientDataQueryable, ResponseError, TextUtils } from '@themost/client';
9
+ import { ResponseError, ClientDataQueryable, TextUtils } from '@themost/client';
9
10
  import { BehaviorSubject } from 'rxjs';
10
11
  import { AngularDataContext } from '@themost/angular';
11
12
  import { __awaiter } from 'tslib';
12
13
  import { DatePipe, CommonModule } from '@angular/common';
13
14
  import { TranslateService, TranslatePipe, TranslateModule } from '@ngx-translate/core';
14
15
  import { FormControl, FormArray, FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
15
- import { TemplatePipe, ModalService, LoadingService, ErrorService, DIALOG_BUTTONS, UserActivityService, ToastService, AppEventService, UserStorageService, ConfigurationService, SharedModule } from '@universis/common';
16
+ import { TemplatePipe, ModalService, ConfigurationService, ErrorService, LoadingService, DIALOG_BUTTONS, ExportSpreadsheetService, UserActivityService, ToastService, AppEventService, UserStorageService, SharedModule } from '@universis/common';
16
17
  import { RouterModalOkCancel, RouterModalModule } from '@universis/common/routing';
17
18
  import { ServiceUrlPreProcessor, TranslatePreProcessor, AdvancedFormsModule } from '@universis/forms';
18
19
  import { FormioModule } from 'angular-formio';
@@ -20,7 +21,7 @@ import { BsModalRef, BsModalService, ModalModule } from 'ngx-bootstrap/modal';
20
21
  import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
21
22
  import { GroupByPipe, NgPipesModule } from 'ngx-pipes';
22
23
  import { template, at, cloneDeep } from 'lodash';
23
- import { Injectable, Directive, Optional, Input, Output, EventEmitter, Pipe, Component, ViewChild, ViewEncapsulation, ElementRef, ChangeDetectorRef, Inject, InjectionToken, Injector, NgModule, CUSTOM_ELEMENTS_SCHEMA, defineInjectable, inject, HostListener, ChangeDetectionStrategy } from '@angular/core';
24
+ import { Injectable, Directive, Optional, Input, Output, EventEmitter, Pipe, Component, ViewChild, ViewEncapsulation, ElementRef, ChangeDetectorRef, NgModule, CUSTOM_ELEMENTS_SCHEMA, defineInjectable, inject, HostListener, InjectionToken, Inject, Injector, ChangeDetectionStrategy } from '@angular/core';
24
25
  import { ActivatedRoute, Router, NavigationStart, NavigationEnd, RouterModule } from '@angular/router';
25
26
  import { createFeatureSelector, createSelector, select, Store } from '@ngrx/store';
26
27
  import { first, filter } from 'rxjs/operators';
@@ -704,6 +705,258 @@ ColumnSelectorService.ctorParameters = () => [
704
705
  { type: ModalService }
705
706
  ];
706
707
 
708
+ class ActivatedTableService {
709
+ constructor(_router, _activatedRoute) {
710
+ this._router = _router;
711
+ this._activatedRoute = _activatedRoute;
712
+ _router.events.forEach((event) => {
713
+ if (event instanceof NavigationStart) {
714
+ if (this._activeTable) {
715
+ this._activeTable = null;
716
+ }
717
+ }
718
+ });
719
+ }
720
+ get activeTable() {
721
+ return this._activeTable;
722
+ }
723
+ set activeTable(tableComponent) {
724
+ this._activeTable = tableComponent;
725
+ }
726
+ }
727
+ ActivatedTableService.decorators = [
728
+ { type: Injectable, args: [{
729
+ providedIn: 'root'
730
+ },] }
731
+ ];
732
+ /** @nocollapse */
733
+ ActivatedTableService.ctorParameters = () => [
734
+ { type: Router },
735
+ { type: ActivatedRoute }
736
+ ];
737
+ ActivatedTableService.ngInjectableDef = defineInjectable({ factory: function ActivatedTableService_Factory() { return new ActivatedTableService(inject(Router), inject(ActivatedRoute)); }, token: ActivatedTableService, providedIn: "root" });
738
+
739
+ const MAX_EXPORT_ITEMS = 500;
740
+ class BtnExpDirective {
741
+ constructor(_activatedTable, _context, _config, _translate, _loadingService, _errorService) {
742
+ this._activatedTable = _activatedTable;
743
+ this._context = _context;
744
+ this._config = _config;
745
+ this._translate = _translate;
746
+ this._loadingService = _loadingService;
747
+ this._errorService = _errorService;
748
+ }
749
+ clickEvent(event) {
750
+ return __awaiter(this, void 0, void 0, function* () {
751
+ event.preventDefault();
752
+ event.stopPropagation();
753
+ if (this._activatedTable.activeTable) {
754
+ return this._activatedTable.activeTable.exportView();
755
+ /*
756
+ const lastQuery = this._activatedTable.activeTable.lastQuery;
757
+ const tableConfig = this._activatedTable.activeTable.config;
758
+ const serviceHeaders = this._context.getService().getHeaders();
759
+ const queryModel = lastQuery.getModel();
760
+ let query = this._context.model(queryModel).asQueryable();
761
+ const queryParams = lastQuery.getParams();
762
+ query = this.constructQuery(query, queryParams, tableConfig, serviceHeaders);
763
+ // get export settings
764
+ const exportSettings = this._config.settings as ExportLimitConfiguration;
765
+ // get export limit
766
+ const maxExportItems = exportSettings && exportSettings.tables && exportSettings.tables.exportLimit;
767
+ if (maxExportItems && typeof maxExportItems === 'number' && maxExportItems > 0) {
768
+ query.skip(0).take(maxExportItems);
769
+ } else {
770
+ query.skip(0).take(MAX_EXPORT_ITEMS);
771
+ }
772
+ // This constructs the URI based on the way @themost does
773
+ const url = this.constructURL(query);
774
+ this.downloadFile(url, query.getService().getHeaders(), query.getModel()); */
775
+ }
776
+ });
777
+ }
778
+ /**
779
+ * Sets the parameters to the query based on
780
+ * the active filters of the activated table
781
+ * @param {ClientDataQueryable} query
782
+ * @param params: The filters of the last query of the activated table
783
+ * @return ClientDataQueryable
784
+ */
785
+ setParams(query, params) {
786
+ if (params && typeof params === 'object') {
787
+ Object.keys(params).forEach((key) => {
788
+ query.setParam(key, params[key]);
789
+ });
790
+ }
791
+ return query;
792
+ }
793
+ /**
794
+ * Sets the headers to the query based on
795
+ * the default headers of the DataContext
796
+ * and appending the accept header to get
797
+ * an xlsx file from the API
798
+ * @param {ClientDataQueryable} query
799
+ * @param {Headers} headers: The headers to append to the query
800
+ * @return ClientDataQueryable
801
+ */
802
+ setHeaders(query, headers) {
803
+ Object.keys(headers).forEach((key) => {
804
+ if (headers.hasOwnProperty(key)) {
805
+ query.getService().setHeader(key, headers[key]);
806
+ }
807
+ });
808
+ // sets a header to accept xlsx files
809
+ query.getService().setHeader('Accept', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
810
+ return query;
811
+ }
812
+ /**
813
+ * Constructs the select parameter of the
814
+ * ClientDataQuery by replacing the target name
815
+ * of the field based on the localized translation
816
+ * of that property on the advanced tabled
817
+ * @param {ClientDataQueryable} query
818
+ * @param tableConfig: The configuration of the activated table
819
+ * @return ClientDataQueryable
820
+ */
821
+ constructQueryParam(query, tableConfig) {
822
+ let selectQuery = query.getParams().$select;
823
+ let selectQueryArray = selectQuery.split(',');
824
+ selectQueryArray = selectQueryArray.map((select$$1) => {
825
+ const words = select$$1.split(' ');
826
+ if (words.length === 3) {
827
+ if (tableConfig && tableConfig.columns) {
828
+ for (const column of tableConfig.columns) {
829
+ if (column.property === words[2] && column.title) {
830
+ words[2] = `"${this._translate.instant(column.title)}"`;
831
+ }
832
+ else if (column.property === words[2]) {
833
+ words[2] = `"${this._translate.instant(words[2])}"`;
834
+ }
835
+ }
836
+ }
837
+ }
838
+ if (words.length === 1) {
839
+ if (tableConfig && tableConfig.columns) {
840
+ for (const column of tableConfig.columns) {
841
+ if (column.name === words[0] && column.title) {
842
+ words[0] = `${words[0]} as "${this._translate.instant(column.title)}"`;
843
+ break;
844
+ }
845
+ else if (column.name === words[0] && column.property) {
846
+ words[0] = `${words[0]} as "${this._translate.instant(column.property)}"`;
847
+ break;
848
+ }
849
+ else if (words[0] === column.name && words[0] === "id" && column.hidden) {
850
+ break;
851
+ }
852
+ else if (words[0] == column.name || words[0] === column.property) {
853
+ words[0] = `${words[0]} as "${this._translate.instant(words[0])}"`;
854
+ }
855
+ }
856
+ }
857
+ return words[0];
858
+ }
859
+ return words.join(' ');
860
+ });
861
+ selectQuery = selectQueryArray.join(',');
862
+ query.setParam('$select', selectQuery);
863
+ return query;
864
+ }
865
+ /**
866
+ * Constructs the fetch URL based the query parameters
867
+ * @param {ClientDataQueryable} query
868
+ * @return String
869
+ */
870
+ constructURL(query) {
871
+ const baseURL = query.getService().getBase();
872
+ let url = baseURL.endsWith('/') ? (baseURL + query.getModel() + '?') : (baseURL + '/' + query.getModel() + '?');
873
+ Object.keys(query.getParams()).forEach((key, index) => {
874
+ if (index === 0) {
875
+ url += key + '=' + query.getParams()[key];
876
+ }
877
+ else {
878
+ url += '&' + key + '=' + query.getParams()[key];
879
+ }
880
+ });
881
+ return url;
882
+ }
883
+ /**
884
+ * Constructs the query by setting the parameters of the
885
+ * advanced table's active filters, sets the necessary headers
886
+ * and build the select parameter of the query
887
+ * @param {ClientDataQueryable} query
888
+ * @param params: The filters of the last query of the activated table
889
+ * @param tableConfig: The configuration of the activated table
890
+ * @param {Headers} headers: The headers to append to the query
891
+ * @return ClientDataQueryable
892
+ */
893
+ constructQuery(query, params, tableConfig, headers) {
894
+ let _query = this.setParams(query, params);
895
+ _query = this.setHeaders(_query, headers);
896
+ _query = this.constructQueryParam(_query, tableConfig);
897
+ return _query;
898
+ }
899
+ /**
900
+ * Fetches and saves the xlsx file
901
+ * @param {String} url
902
+ * @param {Headers} serviceHeaders: The headers to append to the query
903
+ * @param modelName: The model name of the advanced table
904
+ */
905
+ downloadFile(url, serviceHeaders, modelName) {
906
+ this._loadingService.showLoading();
907
+ fetch(encodeURI(url), {
908
+ headers: serviceHeaders,
909
+ credentials: 'include'
910
+ }).then(response => {
911
+ if (response && !response.ok) {
912
+ throw new ResponseError(response.statusText, response.status);
913
+ }
914
+ return response.blob();
915
+ }).then(blob => {
916
+ const objectUrl = window.URL.createObjectURL(blob);
917
+ const a = document.createElement('a');
918
+ document.body.appendChild(a);
919
+ a.setAttribute('style', 'display: none');
920
+ a.href = objectUrl;
921
+ const downloadName = `${modelName}.xlsx`;
922
+ a.download = downloadName;
923
+ // this adds support for IE and MS Edge (up to version 44.19041)
924
+ if (window.navigator && window.navigator.msSaveOrOpenBlob) {
925
+ window.navigator.msSaveOrOpenBlob(blob, downloadName);
926
+ }
927
+ else {
928
+ // for all other browsers
929
+ a.click();
930
+ }
931
+ window.URL.revokeObjectURL(objectUrl);
932
+ a.remove();
933
+ this._loadingService.hideLoading();
934
+ }).catch(err => {
935
+ this._loadingService.hideLoading();
936
+ this._errorService.showError(err, {
937
+ continueLink: '.'
938
+ });
939
+ });
940
+ }
941
+ }
942
+ BtnExpDirective.decorators = [
943
+ { type: Directive, args: [{
944
+ selector: '.universis-btn-export'
945
+ },] }
946
+ ];
947
+ /** @nocollapse */
948
+ BtnExpDirective.ctorParameters = () => [
949
+ { type: ActivatedTableService },
950
+ { type: AngularDataContext },
951
+ { type: ConfigurationService },
952
+ { type: TranslateService },
953
+ { type: LoadingService },
954
+ { type: ErrorService }
955
+ ];
956
+ BtnExpDirective.propDecorators = {
957
+ clickEvent: [{ type: HostListener, args: ['click', ['$event'],] }]
958
+ };
959
+
707
960
  // restore jquery import to avoid Cannot call a namespace ('jquery') error
708
961
  const jQuery = jQuery_;
709
962
  const DataTablesApi = jQuery.fn.dataTable.Api;
@@ -731,6 +984,12 @@ class TableTranslationChangeDetector extends ChangeDetectorRef {
731
984
  }
732
985
  }
733
986
  let COLUMN_FORMATTERS = new InjectionToken('column.formatters');
987
+ class ExportLimitExceededError extends RangeError {
988
+ constructor(message) {
989
+ super(message);
990
+ this.name = 'ExportLimitExceededError';
991
+ }
992
+ }
734
993
  class ColumnFormatter extends AdvancedColumnFormatter {
735
994
  constructor(injector) {
736
995
  super();
@@ -755,7 +1014,7 @@ function getRandomIdentifier() {
755
1014
  return (Number(String(Math.random()).slice(2))).toString(36);
756
1015
  }
757
1016
  class AdvancedTableComponent {
758
- constructor(_context, _columnFormatters, _activatedRoute, _translateService, _injector, _advancedFilterValueProvider, _element, _template, _loading, _http, _columnSelector) {
1017
+ constructor(_context, _columnFormatters, _activatedRoute, _translateService, _injector, _advancedFilterValueProvider, _element, _template, _loading, _http, _columnSelector, _configuration, _exportSpreadsheet, _modalService, _errorService) {
759
1018
  this._context = _context;
760
1019
  this._columnFormatters = _columnFormatters;
761
1020
  this._activatedRoute = _activatedRoute;
@@ -767,6 +1026,10 @@ class AdvancedTableComponent {
767
1026
  this._loading = _loading;
768
1027
  this._http = _http;
769
1028
  this._columnSelector = _columnSelector;
1029
+ this._configuration = _configuration;
1030
+ this._exportSpreadsheet = _exportSpreadsheet;
1031
+ this._modalService = _modalService;
1032
+ this._errorService = _errorService;
770
1033
  this._firstLoad = true;
771
1034
  this._showFooter = false;
772
1035
  this._showHeader = true;
@@ -810,6 +1073,7 @@ class AdvancedTableComponent {
810
1073
  this.customSelect = false;
811
1074
  this.selected = [];
812
1075
  this.unselected = [];
1076
+ this._lastQueryTotalItems = 0;
813
1077
  // initialize translate pipe
814
1078
  this.translator = new TranslatePipe(this._translateService, new TableTranslationChangeDetector());
815
1079
  jQuery.fn.dataTable.ext.classes.sPageButton = 'btn';
@@ -829,6 +1093,9 @@ class AdvancedTableComponent {
829
1093
  get config() {
830
1094
  return this._config;
831
1095
  }
1096
+ get lastQueryTotalItems() {
1097
+ return this._lastQueryTotalItems;
1098
+ }
832
1099
  /**
833
1100
  * Indicates whether table footer will be visible or not
834
1101
  */
@@ -1437,6 +1704,7 @@ class AdvancedTableComponent {
1437
1704
  recordsFiltered: 0,
1438
1705
  data: [],
1439
1706
  };
1707
+ self._lastQueryTotalItems = 0;
1440
1708
  // emit empty data
1441
1709
  self.load.emit(emptyDataSet);
1442
1710
  // return empty data
@@ -1531,6 +1799,7 @@ class AdvancedTableComponent {
1531
1799
  recordsFiltered: items.total,
1532
1800
  data: items.value,
1533
1801
  };
1802
+ self._lastQueryTotalItems = items.total;
1534
1803
  if (items.total === 0) {
1535
1804
  self.resetEmptyTable();
1536
1805
  }
@@ -1544,6 +1813,7 @@ class AdvancedTableComponent {
1544
1813
  console.error('TABLES', err);
1545
1814
  // show error
1546
1815
  self.toggleError(err);
1816
+ self._lastQueryTotalItems = 0;
1547
1817
  // by returning empty dataset
1548
1818
  self.load.emit(EMPTY_DATASET);
1549
1819
  return fnCallback(EMPTY_DATASET);
@@ -1556,6 +1826,7 @@ class AdvancedTableComponent {
1556
1826
  recordsFiltered: items.total,
1557
1827
  data: items.value,
1558
1828
  };
1829
+ self._lastQueryTotalItems = items.total;
1559
1830
  if (items.total === 0) {
1560
1831
  self.resetEmptyTable();
1561
1832
  }
@@ -1931,6 +2202,125 @@ class AdvancedTableComponent {
1931
2202
  }
1932
2203
  });
1933
2204
  }
2205
+ /**
2206
+ *
2207
+ * @param options to pass an errorHandler callback, if desired
2208
+ * @returns void
2209
+ */
2210
+ exportView(options) {
2211
+ return __awaiter(this, void 0, void 0, function* () {
2212
+ try {
2213
+ this._loading.showLoading();
2214
+ // validate query items and config
2215
+ if (!(this._lastQueryTotalItems && this.config)) {
2216
+ // do nothing
2217
+ return;
2218
+ }
2219
+ // get export settings
2220
+ const exportSettings = this._configuration.settings;
2221
+ // and export limit
2222
+ const exportLimit = (exportSettings && exportSettings.tables && exportSettings.tables.exportLimit > 0)
2223
+ ? exportSettings.tables.exportLimit : MAX_EXPORT_ITEMS;
2224
+ // and validate it
2225
+ if (this._lastQueryTotalItems > exportLimit) {
2226
+ // call error handler
2227
+ // provide a recognizible error type
2228
+ if (options && options.errorHandler) {
2229
+ options.errorHandler(new ExportLimitExceededError('Export limit exceeded'));
2230
+ return;
2231
+ }
2232
+ // or show warning modal and exit
2233
+ this._modalService.showWarningDialog(this._translateService.instant('Tables.ExportList'), this._translateService.instant('Tables.ExportLimitExceeded', { dataLength: this._lastQueryTotalItems, exportLimit }), DIALOG_BUTTONS.Ok);
2234
+ return;
2235
+ }
2236
+ // get total displayed items
2237
+ const totalDisplayedItems = Array.from(this.dataTable.context[0].aiDisplay).length;
2238
+ // if they already satisfy the last query total
2239
+ if (totalDisplayedItems === this._lastQueryTotalItems) {
2240
+ // prepare excel data immediately
2241
+ const { body, header } = this.getExportableData();
2242
+ // and export them to excel
2243
+ this._exportSpreadsheet.export(body, `${this._translateService.instant(this.config.title || 'Tables.ExportResults')}.xlsx`, {
2244
+ header,
2245
+ skipHeader: false
2246
+ });
2247
+ }
2248
+ else {
2249
+ // at this point, more data need to be fetched
2250
+ // hold previous data state
2251
+ const previousDataState = this.dataTable.rows().data().toArray();
2252
+ // get target data state by executing the last query
2253
+ // note: taking the exportLimit amount of items will always satisfy the results,
2254
+ // because it has been validated
2255
+ const targetDataState = yield this.lastQuery.take(exportLimit).getItems();
2256
+ // change table data on the fly, but do not redraw
2257
+ this.dataTable.clear().rows.add(targetDataState);
2258
+ // prepare excel data
2259
+ const { body, header } = this.getExportableData();
2260
+ // reset table data
2261
+ this.dataTable.clear().rows.add(previousDataState);
2262
+ // and export target data to excel
2263
+ this._exportSpreadsheet.export(body, `${this._translateService.instant(this.config.title || 'Tables.ExportResults')}.xlsx`, {
2264
+ header,
2265
+ skipHeader: false
2266
+ });
2267
+ }
2268
+ // exit
2269
+ return;
2270
+ }
2271
+ catch (err) {
2272
+ // log error
2273
+ console.error(err);
2274
+ // call error handler, if defined
2275
+ if (options && options.errorHandler) {
2276
+ options.errorHandler(err);
2277
+ }
2278
+ else {
2279
+ // use default error service
2280
+ this._errorService.showError(err, {
2281
+ continueLink: '.'
2282
+ });
2283
+ }
2284
+ }
2285
+ finally {
2286
+ this._loading.hideLoading();
2287
+ }
2288
+ });
2289
+ }
2290
+ getExportableData() {
2291
+ if (!(this.dataTable && this.dataTable.buttons
2292
+ && typeof this.dataTable.buttons.exportData === 'function' && this.config)) {
2293
+ return { body: [], header: [] };
2294
+ }
2295
+ // fetch exportable excel data
2296
+ let { body, header } = this.dataTable.buttons.exportData();
2297
+ const cleanupIndexes = [];
2298
+ // clean up headers
2299
+ header = header.filter((headerItem, index) => {
2300
+ // exclude empty headers
2301
+ if (headerItem.trim().length === 0) {
2302
+ cleanupIndexes.push(index);
2303
+ return false;
2304
+ }
2305
+ // find item by title
2306
+ const findItem = this.config.columns.find((column) => {
2307
+ return column.title && column.title.length && this._translateService.instant(column.title) === headerItem;
2308
+ });
2309
+ // exclude hidden columns
2310
+ if (findItem && findItem.hidden === true) {
2311
+ cleanupIndexes.push(index);
2312
+ return false;
2313
+ }
2314
+ return true;
2315
+ });
2316
+ // clean up body
2317
+ body = body.map((row) => {
2318
+ return row.filter((_, rowIndex) => {
2319
+ return cleanupIndexes.indexOf(rowIndex) === -1;
2320
+ });
2321
+ });
2322
+ return { body, header };
2323
+ }
1934
2324
  }
1935
2325
  AdvancedTableComponent.decorators = [
1936
2326
  { type: Component, args: [{
@@ -1981,7 +2371,11 @@ AdvancedTableComponent.ctorParameters = () => [
1981
2371
  { type: TemplatePipe },
1982
2372
  { type: LoadingService },
1983
2373
  { type: HttpClient },
1984
- { type: ColumnSelectorService }
2374
+ { type: ColumnSelectorService },
2375
+ { type: ConfigurationService },
2376
+ { type: ExportSpreadsheetService },
2377
+ { type: ModalService },
2378
+ { type: ErrorService }
1985
2379
  ];
1986
2380
  AdvancedTableComponent.propDecorators = {
1987
2381
  table: [{ type: ViewChild, args: ['table',] }],
@@ -3035,37 +3429,6 @@ AdvancedSearchConfigurationResolver.ctorParameters = () => [
3035
3429
  { type: HttpClient }
3036
3430
  ];
3037
3431
 
3038
- class ActivatedTableService {
3039
- constructor(_router, _activatedRoute) {
3040
- this._router = _router;
3041
- this._activatedRoute = _activatedRoute;
3042
- _router.events.forEach((event) => {
3043
- if (event instanceof NavigationStart) {
3044
- if (this._activeTable) {
3045
- this._activeTable = null;
3046
- }
3047
- }
3048
- });
3049
- }
3050
- get activeTable() {
3051
- return this._activeTable;
3052
- }
3053
- set activeTable(tableComponent) {
3054
- this._activeTable = tableComponent;
3055
- }
3056
- }
3057
- ActivatedTableService.decorators = [
3058
- { type: Injectable, args: [{
3059
- providedIn: 'root'
3060
- },] }
3061
- ];
3062
- /** @nocollapse */
3063
- ActivatedTableService.ctorParameters = () => [
3064
- { type: Router },
3065
- { type: ActivatedRoute }
3066
- ];
3067
- ActivatedTableService.ngInjectableDef = defineInjectable({ factory: function ActivatedTableService_Factory() { return new ActivatedTableService(inject(Router), inject(ActivatedRoute)); }, token: ActivatedTableService, providedIn: "root" });
3068
-
3069
3432
  class AdvancedTableSettingsComponent {
3070
3433
  constructor(_context, _activatedRoute, elRef, modalService, userStorage, formBuilder, _activatedTable) {
3071
3434
  this._context = _context;
@@ -3895,226 +4258,6 @@ AdvancedTableEditorDirective.propDecorators = {
3895
4258
  dirtyChange: [{ type: Output }]
3896
4259
  };
3897
4260
 
3898
- const MAX_EXPORT_ITEMS = 500;
3899
- class BtnExpDirective {
3900
- constructor(_activatedTable, _context, _config, _translate, _loadingService, _errorService) {
3901
- this._activatedTable = _activatedTable;
3902
- this._context = _context;
3903
- this._config = _config;
3904
- this._translate = _translate;
3905
- this._loadingService = _loadingService;
3906
- this._errorService = _errorService;
3907
- }
3908
- clickEvent(event) {
3909
- return __awaiter(this, void 0, void 0, function* () {
3910
- event.preventDefault();
3911
- event.stopPropagation();
3912
- if (this._activatedTable.activeTable) {
3913
- const lastQuery = this._activatedTable.activeTable.lastQuery;
3914
- const tableConfig = this._activatedTable.activeTable.config;
3915
- const serviceHeaders = this._context.getService().getHeaders();
3916
- const queryModel = lastQuery.getModel();
3917
- let query = this._context.model(queryModel).asQueryable();
3918
- const queryParams = lastQuery.getParams();
3919
- query = this.constructQuery(query, queryParams, tableConfig, serviceHeaders);
3920
- // get export settings
3921
- const exportSettings = this._config.settings;
3922
- // get export limit
3923
- const maxExportItems = exportSettings && exportSettings.tables && exportSettings.tables.exportLimit;
3924
- if (maxExportItems && typeof maxExportItems === 'number' && maxExportItems > 0) {
3925
- query.skip(0).take(maxExportItems);
3926
- }
3927
- else {
3928
- query.skip(0).take(MAX_EXPORT_ITEMS);
3929
- }
3930
- // This constructs the URI based on the way @themost does
3931
- const url = this.constructURL(query);
3932
- this.downloadFile(url, query.getService().getHeaders(), query.getModel());
3933
- }
3934
- });
3935
- }
3936
- /**
3937
- * Sets the parameters to the query based on
3938
- * the active filters of the activated table
3939
- * @param {ClientDataQueryable} query
3940
- * @param params: The filters of the last query of the activated table
3941
- * @return ClientDataQueryable
3942
- */
3943
- setParams(query, params) {
3944
- if (params && typeof params === 'object') {
3945
- Object.keys(params).forEach((key) => {
3946
- query.setParam(key, params[key]);
3947
- });
3948
- }
3949
- return query;
3950
- }
3951
- /**
3952
- * Sets the headers to the query based on
3953
- * the default headers of the DataContext
3954
- * and appending the accept header to get
3955
- * an xlsx file from the API
3956
- * @param {ClientDataQueryable} query
3957
- * @param {Headers} headers: The headers to append to the query
3958
- * @return ClientDataQueryable
3959
- */
3960
- setHeaders(query, headers) {
3961
- Object.keys(headers).forEach((key) => {
3962
- if (headers.hasOwnProperty(key)) {
3963
- query.getService().setHeader(key, headers[key]);
3964
- }
3965
- });
3966
- // sets a header to accept xlsx files
3967
- query.getService().setHeader('Accept', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
3968
- return query;
3969
- }
3970
- /**
3971
- * Constructs the select parameter of the
3972
- * ClientDataQuery by replacing the target name
3973
- * of the field based on the localized translation
3974
- * of that property on the advanced tabled
3975
- * @param {ClientDataQueryable} query
3976
- * @param tableConfig: The configuration of the activated table
3977
- * @return ClientDataQueryable
3978
- */
3979
- constructQueryParam(query, tableConfig) {
3980
- let selectQuery = query.getParams().$select;
3981
- let selectQueryArray = selectQuery.split(',');
3982
- selectQueryArray = selectQueryArray.map((select$$1) => {
3983
- const words = select$$1.split(' ');
3984
- if (words.length === 3) {
3985
- if (tableConfig && tableConfig.columns) {
3986
- for (const column of tableConfig.columns) {
3987
- if (column.property === words[2] && column.title) {
3988
- words[2] = `"${this._translate.instant(column.title)}"`;
3989
- }
3990
- else if (column.property === words[2]) {
3991
- words[2] = `"${this._translate.instant(words[2])}"`;
3992
- }
3993
- }
3994
- }
3995
- }
3996
- if (words.length === 1) {
3997
- if (tableConfig && tableConfig.columns) {
3998
- for (const column of tableConfig.columns) {
3999
- if (column.name === words[0] && column.title) {
4000
- words[0] = `${words[0]} as "${this._translate.instant(column.title)}"`;
4001
- break;
4002
- }
4003
- else if (column.name === words[0] && column.property) {
4004
- words[0] = `${words[0]} as "${this._translate.instant(column.property)}"`;
4005
- break;
4006
- }
4007
- else if (words[0] === column.name && words[0] === "id" && column.hidden) {
4008
- break;
4009
- }
4010
- else if (words[0] == column.name || words[0] === column.property) {
4011
- words[0] = `${words[0]} as "${this._translate.instant(words[0])}"`;
4012
- }
4013
- }
4014
- }
4015
- return words[0];
4016
- }
4017
- return words.join(' ');
4018
- });
4019
- selectQuery = selectQueryArray.join(',');
4020
- query.setParam('$select', selectQuery);
4021
- return query;
4022
- }
4023
- /**
4024
- * Constructs the fetch URL based the query parameters
4025
- * @param {ClientDataQueryable} query
4026
- * @return String
4027
- */
4028
- constructURL(query) {
4029
- const baseURL = query.getService().getBase();
4030
- let url = baseURL.endsWith('/') ? (baseURL + query.getModel() + '?') : (baseURL + '/' + query.getModel() + '?');
4031
- Object.keys(query.getParams()).forEach((key, index) => {
4032
- if (index === 0) {
4033
- url += key + '=' + query.getParams()[key];
4034
- }
4035
- else {
4036
- url += '&' + key + '=' + query.getParams()[key];
4037
- }
4038
- });
4039
- return url;
4040
- }
4041
- /**
4042
- * Constructs the query by setting the parameters of the
4043
- * advanced table's active filters, sets the necessary headers
4044
- * and build the select parameter of the query
4045
- * @param {ClientDataQueryable} query
4046
- * @param params: The filters of the last query of the activated table
4047
- * @param tableConfig: The configuration of the activated table
4048
- * @param {Headers} headers: The headers to append to the query
4049
- * @return ClientDataQueryable
4050
- */
4051
- constructQuery(query, params, tableConfig, headers) {
4052
- let _query = this.setParams(query, params);
4053
- _query = this.setHeaders(_query, headers);
4054
- _query = this.constructQueryParam(_query, tableConfig);
4055
- return _query;
4056
- }
4057
- /**
4058
- * Fetches and saves the xlsx file
4059
- * @param {String} url
4060
- * @param {Headers} serviceHeaders: The headers to append to the query
4061
- * @param modelName: The model name of the advanced table
4062
- */
4063
- downloadFile(url, serviceHeaders, modelName) {
4064
- this._loadingService.showLoading();
4065
- fetch(encodeURI(url), {
4066
- headers: serviceHeaders,
4067
- credentials: 'include'
4068
- }).then(response => {
4069
- if (response && !response.ok) {
4070
- throw new ResponseError(response.statusText, response.status);
4071
- }
4072
- return response.blob();
4073
- }).then(blob => {
4074
- const objectUrl = window.URL.createObjectURL(blob);
4075
- const a = document.createElement('a');
4076
- document.body.appendChild(a);
4077
- a.setAttribute('style', 'display: none');
4078
- a.href = objectUrl;
4079
- const downloadName = `${modelName}.xlsx`;
4080
- a.download = downloadName;
4081
- // this adds support for IE and MS Edge (up to version 44.19041)
4082
- if (window.navigator && window.navigator.msSaveOrOpenBlob) {
4083
- window.navigator.msSaveOrOpenBlob(blob, downloadName);
4084
- }
4085
- else {
4086
- // for all other browsers
4087
- a.click();
4088
- }
4089
- window.URL.revokeObjectURL(objectUrl);
4090
- a.remove();
4091
- this._loadingService.hideLoading();
4092
- }).catch(err => {
4093
- this._loadingService.hideLoading();
4094
- this._errorService.showError(err, {
4095
- continueLink: '.'
4096
- });
4097
- });
4098
- }
4099
- }
4100
- BtnExpDirective.decorators = [
4101
- { type: Directive, args: [{
4102
- selector: '.universis-btn-export'
4103
- },] }
4104
- ];
4105
- /** @nocollapse */
4106
- BtnExpDirective.ctorParameters = () => [
4107
- { type: ActivatedTableService },
4108
- { type: AngularDataContext },
4109
- { type: ConfigurationService },
4110
- { type: TranslateService },
4111
- { type: LoadingService },
4112
- { type: ErrorService }
4113
- ];
4114
- BtnExpDirective.propDecorators = {
4115
- clickEvent: [{ type: HostListener, args: ['click', ['$event'],] }]
4116
- };
4117
-
4118
4261
  class AdvancedAggregatorService {
4119
4262
  constructor(_context, _template) {
4120
4263
  this._context = _context;
@@ -4600,6 +4743,8 @@ ParseTitlePipe.ctorParameters = () => [
4600
4743
  { type: TranslateService }
4601
4744
  ];
4602
4745
 
4746
+ // tslint:disable: quotemark
4747
+ // tslint:disable: max-line-length
4603
4748
  const TABLES_EL = {
4604
4749
  "Tables": {
4605
4750
  "Export": "Εξαγωγή",
@@ -4683,7 +4828,10 @@ const TABLES_EL = {
4683
4828
  "DataError": {
4684
4829
  "Title": "Σφάλμα κατά την παραλαβή των δεδομένων",
4685
4830
  "Message": "Συνέβη σφάλμα κατά την παραλαβή των δεδομένων. Προσπαθήστε ξανά ή τροποποιήστε τα στοιχεία αναζήτησης."
4686
- }
4831
+ },
4832
+ "ExportList": "Εξαγωγή λίστας",
4833
+ "ExportLimitExceeded": "Το πλήθος των στοιχείων προς εξαγωγή ({{dataLength}}) ξεπερνάει το μέγιστο επιτρεπτό ({{exportLimit}}). Παρακαλούμε προσαρμόστε τα φίλτρα της αναζήτησης και προσπαθήστε ξανά.",
4834
+ "ExportResults": "Δεδομένα λίστας"
4687
4835
  },
4688
4836
  "TrueFalse": {
4689
4837
  "long": {
@@ -4724,6 +4872,8 @@ const TABLES_EL = {
4724
4872
  }
4725
4873
  };
4726
4874
 
4875
+ // tslint:disable: quotemark
4876
+ // tslint:disable: max-line-length
4727
4877
  const TABLES_EN = {
4728
4878
  "Tables": {
4729
4879
  "Export": "Export",
@@ -4806,7 +4956,10 @@ const TABLES_EN = {
4806
4956
  "DataError": {
4807
4957
  "Title": "Error while getting data",
4808
4958
  "Message": "An error occurred while getting data. Please try again or change your criteria."
4809
- }
4959
+ },
4960
+ "ExportList": "Export list",
4961
+ "ExportLimitExceeded": "The number of items that are to be exported ({{dataLength}}) exceeds the export limit ({{exportLimit}}). Please apply more specific filters to the search.",
4962
+ "ExportResults": "Exported list"
4810
4963
  },
4811
4964
  "TrueFalse": {
4812
4965
  "long": {
@@ -5217,6 +5370,6 @@ TablesModule.ctorParameters = () => [
5217
5370
  * Generated bundle index. Do not edit.
5218
5371
  */
5219
5372
 
5220
- export { AdvancedSearchState as ɵa, AdvancedTableState as ɵc, AdvancedSearchRouterState as ɵd, AdvancedListComponent, AdvancedRowActionComponent, AdvancedSearchFormComponent, AdvancedSelectComponent, AdvancedSelectService, AdvancedTableConfigurationResolver, AdvancedSearchConfigurationResolver, AdvancedColumnFormatter, NestedPropertyFormatter, ButtonFormatter, LinkFormatter, ActionLinkFormatter, ActionButtonFormatter, ActionSplitButtonFormatter, SelectRowFormatter, TemplateFormatter, TrueFalseFormatter, TranslationFormatter, DateTimeFormatter, NgClassFormatter, LanguageFormatter, COLUMN_FORMATTERS, AdvancedTableConfiguration, AdvancedTableComponent, ɵ0, AdvancedTableSettingsComponent, AdvancedTableSearchBaseComponent, AdvancedTableSearchComponent, FORMATTERS, AdvancedFilterValueProvider, AdvancedTableModalBaseTemplate, AdvancedTableModalBaseComponent, SimpleHeaderToolsComponent, TableSimpleHeaderComponent, AdvancedTableNotNullError, AdvancedTableEditorDirective, BtnExpDirective, AdvancedAggregatorComponent, AdvancedAggregatorListComponent, AddItemsComponent, AdvancedAggregatorPipe, ParseTitlePipe, AdvancedAggregatorService, TablesModule, ActivatedTableService, ColumnSelectorService, ColumnSelectorComponent, initialState, tableInitialState, tableReducer, tableReducers, featureName, getTablesState, selectTable };
5373
+ export { AdvancedSearchState as ɵa, AdvancedTableState as ɵc, AdvancedSearchRouterState as ɵd, AdvancedListComponent, AdvancedRowActionComponent, AdvancedSearchFormComponent, AdvancedSelectComponent, AdvancedSelectService, AdvancedTableConfigurationResolver, AdvancedSearchConfigurationResolver, AdvancedColumnFormatter, NestedPropertyFormatter, ButtonFormatter, LinkFormatter, ActionLinkFormatter, ActionButtonFormatter, ActionSplitButtonFormatter, SelectRowFormatter, TemplateFormatter, TrueFalseFormatter, TranslationFormatter, DateTimeFormatter, NgClassFormatter, LanguageFormatter, COLUMN_FORMATTERS, ExportLimitExceededError, AdvancedTableConfiguration, AdvancedTableComponent, ɵ0, AdvancedTableSettingsComponent, AdvancedTableSearchBaseComponent, AdvancedTableSearchComponent, FORMATTERS, AdvancedFilterValueProvider, AdvancedTableModalBaseTemplate, AdvancedTableModalBaseComponent, SimpleHeaderToolsComponent, TableSimpleHeaderComponent, AdvancedTableNotNullError, AdvancedTableEditorDirective, MAX_EXPORT_ITEMS, BtnExpDirective, AdvancedAggregatorComponent, AdvancedAggregatorListComponent, AddItemsComponent, AdvancedAggregatorPipe, ParseTitlePipe, AdvancedAggregatorService, TablesModule, ActivatedTableService, ColumnSelectorService, ColumnSelectorComponent, initialState, tableInitialState, tableReducer, tableReducers, featureName, getTablesState, selectTable };
5221
5374
 
5222
5375
  //# sourceMappingURL=universis-ngx-tables.js.map