inviton-powerduck 0.0.154 → 0.0.156

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.
Files changed (60) hide show
  1. package/app/powerduck-initializer.ts +3 -3
  2. package/common/api-http.ts +20 -14
  3. package/common/css/ladda-themeless-zoomin.min.css +89 -89
  4. package/common/enum-translation/day-translator.ts +3 -2
  5. package/common/excel/excel-reader.ts +2 -9
  6. package/common/extensions/array-extensions.ts +116 -0
  7. package/common/extensions/string-extensions.ts +92 -0
  8. package/common/extensions/temporal-extensions.ts +115 -0
  9. package/common/scroll-utils.ts +2 -1
  10. package/common/temporal-helpers.ts +551 -0
  11. package/common/timezone-helper.ts +39 -29
  12. package/common/utils/cookie.ts +11 -8
  13. package/common/utils/date-localization-utils.ts +25 -19
  14. package/common/utils/date-utils.ts +37 -47
  15. package/common/utils/form-utils.ts +3 -1
  16. package/common/utils/language-utils.ts +21 -27
  17. package/common/utils/temporal-utils.ts +43 -0
  18. package/common/utils/upload-image-helper.ts +1 -1
  19. package/common/utils/utils.ts +14 -14
  20. package/common/validation.ts +17 -5
  21. package/components/chart-js/line-chart-flot.tsx +9 -9
  22. package/components/chart-js/thirdparty/flot/jquery.flot.categories.min.js +93 -93
  23. package/components/chart-js/thirdparty/flot/jquery.flot.crosshair.min.js +83 -83
  24. package/components/chart-js/thirdparty/flot/jquery.flot.navigate.min.js +270 -270
  25. package/components/chart-js/thirdparty/flot/jquery.flot.pie.min.js +507 -507
  26. package/components/chart-js/thirdparty/flot/jquery.flot.resize.js +7 -9
  27. package/components/chart-js/thirdparty/flot/jquery.flot.resize.min.js +9 -11
  28. package/components/chart-js/thirdparty/flot/jquery.flot.stack.min.js +104 -104
  29. package/components/chart-js/ts/line-chart-contracts.ts +2 -2
  30. package/components/container-with-breakpoints/ts/breakpoint-handler.ts +2 -2
  31. package/components/counter/testall.tsx +89 -75
  32. package/components/datatable/datatable.tsx +2379 -2375
  33. package/components/datatable/export-excel-modal.tsx +12 -14
  34. package/components/datatable/ts/reorder.ts +4 -2
  35. package/components/dropdown/index.tsx +48 -22
  36. package/components/dropdown/mobile/legacy_fdd.ts +10 -11
  37. package/components/dropzone/gallery-dropzone.tsx +394 -382
  38. package/components/fullcalendar/fullcalendar-draggable-event.tsx +8 -7
  39. package/components/fullcalendar/timegrid-calendar.tsx +60 -67
  40. package/components/image-crop/image-cropping-modal.tsx +9 -8
  41. package/components/image-crop/upload-and-crop.tsx +162 -162
  42. package/components/image-crop/vendor/jquery.Jcrop.min.css +344 -344
  43. package/components/import/import-mapper.tsx +2 -2
  44. package/components/input/daterange-picker.tsx +40 -59
  45. package/components/input/datetime-picker.tsx +45 -50
  46. package/components/input/plugins/daterangepicker/daterangepicker.min.css +400 -400
  47. package/components/input/plugins/daterangepicker/jquery.daterangepicker.min.js +346 -339
  48. package/components/input/plugins/daterangepicker/jquery.daterangepicker.ts +580 -402
  49. package/components/input/radio-button-group.tsx +2 -2
  50. package/components/input/ts/dateInputHelper.ts +1 -0
  51. package/components/input/wysiwig.tsx +12 -7
  52. package/components/svg/skilift-svg.tsx +6 -6
  53. package/package.json +2 -1
  54. package/common/date-wrapper.ts +0 -422
  55. package/common/utils/array-extend.ts +0 -215
  56. package/common/utils/array-remove.ts +0 -10
  57. package/common/utils/array-sort.ts +0 -56
  58. package/common/utils/capitalize-string.ts +0 -11
  59. package/common/utils/format-string.ts +0 -14
  60. package/common/utils/latinize-string.ts +0 -7
@@ -1,4 +1,4 @@
1
- import type { DateWrapper } from '../../common/date-wrapper';
1
+ import type { Temporal } from '@js-temporal/polyfill';
2
2
  import type { IWebApiClient, WebClientApiMethod } from '../../common/IWebClient';
3
3
  import type { DaterangeChangedArgs } from '../input/daterange-picker';
4
4
  import type { ColFilterModalShowResponse } from './filter-modal';
@@ -10,12 +10,10 @@ import TsxComponent, { Component } from '../../app/vuetsx';
10
10
  import { DialogResult, DialogUtils } from '../../common/dialog-utils';
11
11
  import { DialogIcons } from '../../common/enums/dialog-icons';
12
12
  import { QueryStringUtils } from '../../common/query-string-utils';
13
- import { arraySort } from '../../common/utils/array-sort';
14
- import { capitalize } from '../../common/utils/capitalize-string';
15
13
  import CheckboxUtils from '../../common/utils/checkbox-utils';
16
14
  import DropdownUtils from '../../common/utils/dropdown-utils';
17
15
  import { isNullOrEmpty } from '../../common/utils/is-null-or-empty';
18
- import { latinize } from '../../common/utils/latinize-string';
16
+ import TemporalUtils from '../../common/utils/temporal-utils';
19
17
  import { PortalUtils } from '../../common/utils/utils';
20
18
  import Button from '../button/button';
21
19
  import { ButtonLayout } from '../button/button-layout';
@@ -34,2462 +32,2468 @@ import ColFilterModal from './filter-modal';
34
32
  import loadingGif from './img/loading_16_16.gif';
35
33
  import ReorderProvider from './ts/reorder';
36
34
  import './css/datatable.css';
35
+ import { sortBy } from '../../common/extensions/array-extensions';
36
+ import { capitalize, latinize } from '../../common/extensions/string-extensions';
37
37
 
38
38
  interface DataTableArgs {
39
- id: string;
40
- apiClient: IWebApiClient;
41
- apiMethod: WebClientApiMethod;
42
- allowMassOperations?: boolean;
43
- allowExport?: boolean;
44
- autoFetch?: boolean;
45
- apiArgs?: any;
46
- exportConfig?: DataTableExportConfig;
47
- paginations?: number[];
48
- paginationLength?: number;
49
- autoFilter?: boolean;
50
- fullSizeTable?: boolean;
51
- insetTop?: boolean;
52
- fullSizeHasButtonBelow?: boolean;
53
- filterMode?: DataTableFilterMode;
54
- checkboxesVisible?: boolean;
55
- checkboxButtonsVisible?: boolean;
56
- topVisible?: boolean;
57
- bottomVisible?: boolean;
58
- cssClass?: string;
59
- columns: TableColumn[];
60
- buttons?: TableButton[];
61
- rowIndexMode?: RowIndexMode;
62
- fulltextPlaceholder?: string;
63
- skin?: DataTableSkin;
64
- preserveOrderBy?: boolean;
65
- preserveFilter?: boolean;
66
- sortableRows?: boolean;
67
- customAjaxCall?: (args: DataTablePostBackData) => Promise<DataTableLoadedRowset>;
68
- parseLoadedRowset?: (serverResp: any) => DataTableLoadedRowset;
69
- rowClicked?: (row: any) => void;
70
- rowCssClass?: (row: any) => string;
71
- rowCheckstateChanged?: (row: any, checked: boolean, selectedRows: any[]) => void;
72
- mobileBehavior?: DataTableMobileBehavior;
73
- mobileModeCustomRender?: (h, columns: TableColumn[], rows: any) => void;
74
- sortComplete?: (args: DataTableOnSortedArgs) => void;
75
- mobileModeRowIcon?: string;
76
- mobileModeShouldAutoCollapse?: boolean;
77
- massOperationOptions?: typeof DropdownButtonItem.prototype[];
78
- handleInitialFilter?: boolean;
79
- timezoneGmtOffset?: number;
80
- timezoneDstOffset?: number;
81
- timeFilterShiftTimezone?: boolean;
82
- hidePagination?: boolean;
39
+ id: string;
40
+ apiClient: IWebApiClient;
41
+ apiMethod: WebClientApiMethod;
42
+ allowMassOperations?: boolean;
43
+ allowExport?: boolean;
44
+ autoFetch?: boolean;
45
+ apiArgs?: any;
46
+ exportConfig?: DataTableExportConfig;
47
+ paginations?: number[];
48
+ paginationLength?: number;
49
+ autoFilter?: boolean;
50
+ fullSizeTable?: boolean;
51
+ insetTop?: boolean;
52
+ fullSizeHasButtonBelow?: boolean;
53
+ filterMode?: DataTableFilterMode;
54
+ checkboxesVisible?: boolean;
55
+ checkboxButtonsVisible?: boolean;
56
+ topVisible?: boolean;
57
+ bottomVisible?: boolean;
58
+ cssClass?: string;
59
+ columns: TableColumn[];
60
+ buttons?: TableButton[];
61
+ rowIndexMode?: RowIndexMode;
62
+ fulltextPlaceholder?: string;
63
+ skin?: DataTableSkin;
64
+ preserveOrderBy?: boolean;
65
+ preserveFilter?: boolean;
66
+ sortableRows?: boolean;
67
+ customAjaxCall?: (args: DataTablePostBackData) => Promise<DataTableLoadedRowset>;
68
+ parseLoadedRowset?: (serverResp: any) => DataTableLoadedRowset;
69
+ rowClicked?: (row: any) => void;
70
+ rowCssClass?: (row: any) => string;
71
+ rowCheckstateChanged?: (row: any, checked: boolean, selectedRows: any[]) => void;
72
+ mobileBehavior?: DataTableMobileBehavior;
73
+ mobileModeCustomRender?: (h, columns: TableColumn[], rows: any) => void;
74
+ sortComplete?: (args: DataTableOnSortedArgs) => void;
75
+ mobileModeRowIcon?: string;
76
+ mobileModeShouldAutoCollapse?: boolean;
77
+ massOperationOptions?: typeof DropdownButtonItem.prototype[];
78
+ handleInitialFilter?: boolean;
79
+ timezoneGmtOffset?: number;
80
+ timezoneDstOffset?: number;
81
+ timeFilterShiftTimezone?: boolean;
82
+ hidePagination?: boolean;
83
83
  }
84
84
 
85
85
  export interface DataTableExportConfig {
86
- attrName: string;
87
- limitName?: string;
88
- pageName?: string;
86
+ attrName: string;
87
+ limitName?: string;
88
+ pageName?: string;
89
89
  }
90
90
 
91
91
  export interface DataTablePostBackData {
92
- ShowHidden: boolean;
93
- PaginationPosition: number;
94
- PaginationLength: number;
95
- SessionId: number;
96
- Filter: DataTableFilterDefinition;
97
- Sort: DataTableSortDefinition;
92
+ ShowHidden: boolean;
93
+ PaginationPosition: number;
94
+ PaginationLength: number;
95
+ SessionId: number;
96
+ Filter: DataTableFilterDefinition;
97
+ Sort: DataTableSortDefinition;
98
98
  }
99
99
 
100
100
  interface DataTableFilterDefinition {
101
- FullText: string;
102
- FilterItems: DataTablePostBackFilterItem[];
101
+ FullText: string;
102
+ FilterItems: DataTablePostBackFilterItem[];
103
103
  }
104
104
 
105
105
  export interface DataTableOnSortedArgs {
106
- oldIndex: number;
107
- newIndex: number;
106
+ oldIndex: number;
107
+ newIndex: number;
108
108
  }
109
109
 
110
110
  export interface DataTablePostBackFilterItem {
111
- PropertyName: string;
112
- ContainsValue?: string;
113
- EqualsValue?: string;
114
- FilterType: DataTableFilterItemType;
115
- NumFrom?: number;
116
- NumTo?: number;
117
- DateFrom?: DateWrapper;
118
- DateTo?: DateWrapper;
119
- ValueArr?: string[];
120
- ValueArrStrategy?: MultiSelectExclusivity;
111
+ PropertyName: string;
112
+ ContainsValue?: string;
113
+ EqualsValue?: string;
114
+ FilterType: DataTableFilterItemType;
115
+ NumFrom?: number;
116
+ NumTo?: number;
117
+ DateFrom?: Temporal.PlainDateTime;
118
+ DateTo?: Temporal.PlainDateTime;
119
+ ValueArr?: string[];
120
+ ValueArrStrategy?: MultiSelectExclusivity;
121
121
  }
122
122
 
123
123
  interface DataTableSortDefinition {
124
- PropertyName: string;
125
- Direction: DataTableSortDirection;
124
+ PropertyName: string;
125
+ Direction: DataTableSortDirection;
126
126
  }
127
127
 
128
128
  export enum DataTableFilterMode {
129
- Serverside = 0,
130
- Clientside = 1,
129
+ Serverside = 0,
130
+ Clientside = 1,
131
131
  }
132
132
 
133
133
  export enum DataTableFilterItemType {
134
- None = 0,
135
- Text = 1,
136
- Dropdown = 2,
137
- DateRange = 3,
138
- NumericRange = 4,
134
+ None = 0,
135
+ Text = 1,
136
+ Dropdown = 2,
137
+ DateRange = 3,
138
+ NumericRange = 4,
139
139
  }
140
140
 
141
141
  export enum DataTableSkin {
142
- Default = 'default',
143
- Compact = 'compact',
142
+ Default = 'default',
143
+ Compact = 'compact',
144
144
  }
145
145
 
146
146
  export enum DataTableMobileBehavior {
147
- MobileLayout = 'mobile',
148
- Compact = 'compact',
149
- VerticalTransform = 'vertical', // Do not use, shitty
147
+ MobileLayout = 'mobile',
148
+ Compact = 'compact',
149
+ VerticalTransform = 'vertical', // Do not use, shitty
150
150
  }
151
151
 
152
152
  export enum RowIndexMode {
153
- Identifier = 0,
154
- Index = 1,
153
+ Identifier = 0,
154
+ Index = 1,
155
155
  }
156
156
 
157
157
  export interface DataTableLoadedRowset {
158
- totalCount: number;
159
- totalFilteredCount: number;
160
- rows: any[];
158
+ totalCount: number;
159
+ totalFilteredCount: number;
160
+ rows: any[];
161
161
  }
162
162
 
163
163
  interface StoredState {
164
- sortOrder: string[];
165
- filter: DataTablePostBackFilterItem[];
166
- hiddenColumns: string[];
167
- visibleColumns: string[];
168
- paginationLength: number;
169
- orderBy: SortDefinition;
170
- skin: DataTableSkin;
171
- mobileBehavior: DataTableMobileBehavior;
164
+ sortOrder: string[];
165
+ filter: DataTablePostBackFilterItem[];
166
+ hiddenColumns: string[];
167
+ visibleColumns: string[];
168
+ paginationLength: number;
169
+ orderBy: SortDefinition;
170
+ skin: DataTableSkin;
171
+ mobileBehavior: DataTableMobileBehavior;
172
172
  }
173
173
 
174
174
  class RowIdentifier {
175
- name: string = null;
176
- surname: string = null;
177
- dtColumns: TableColumn[] = null;
178
-
179
- constructor(name: string, surname: string) {
180
- this.name = name;
181
- this.surname = surname;
182
- }
183
-
184
- get fullName(): string {
185
- return (`${this.name || ''} ${this.surname || ''}`).trim();
186
- }
175
+ name: string = null;
176
+ surname: string = null;
177
+ dtColumns: TableColumn[] = null;
178
+
179
+ constructor(name: string, surname: string) {
180
+ this.name = name;
181
+ this.surname = surname;
182
+ }
183
+
184
+ get fullName(): string {
185
+ return (`${this.name || ''} ${this.surname || ''}`).trim();
186
+ }
187
187
  }
188
188
 
189
189
  export enum DataTableSortDirection {
190
- Ascending = 0,
191
- Descending = 1,
190
+ Ascending = 0,
191
+ Descending = 1,
192
192
  }
193
193
 
194
194
  interface SortDefinition {
195
- columnId: string;
196
- direction: DataTableSortDirection;
195
+ columnId: string;
196
+ direction: DataTableSortDirection;
197
197
  }
198
198
 
199
199
  const enum DataTableBreakpoint {
200
- Desktop = 'desktop',
201
- Mobile = 'mobile',
200
+ Desktop = 'desktop',
201
+ Mobile = 'mobile',
202
202
  }
203
203
 
204
204
  class StorageHelper {
205
- private static getStorageKey(id: string) {
206
- return `bldt-${window.location.pathname.split('/').join('_')}${id}`;
207
- }
208
-
209
- static getStoredState(id: string): StoredState {
210
- const retVal = localStorage.getItem(StorageHelper.getStorageKey(id));
211
- if (retVal != null) {
212
- try {
213
- return JSON.parse(retVal);
214
- } catch (e) { }
215
- }
216
-
217
- return {} as any;
218
- }
219
-
220
- static saveStoredState(id: string, state: StoredState): void {
221
- localStorage.setItem(StorageHelper.getStorageKey(id), JSON.stringify(state));
222
- }
223
-
224
- static storeSortOrder(id: string, sortOrder: string[]) {
225
- const state = StorageHelper.getStoredState(id);
226
- if (sortOrder != null) {
227
- state.sortOrder = sortOrder;
228
- } else if (state.sortOrder != null) {
229
- delete state.sortOrder;
230
- }
231
-
232
- StorageHelper.saveStoredState(id, state);
233
- }
234
-
235
- static storeOrderBy(id: string, orderBy: SortDefinition) {
236
- const state = StorageHelper.getStoredState(id);
237
- if (orderBy != null) {
238
- state.orderBy = orderBy;
239
- } else if (state.orderBy != null) {
240
- delete state.orderBy;
241
- }
242
-
243
- StorageHelper.saveStoredState(id, state);
244
- }
245
-
246
- static storeColVis(id: string, columns: TableColumn[]) {
247
- const state = StorageHelper.getStoredState(id);
248
- state.hiddenColumns = columns.filter(p => p.visible == false).map(p => p.id);
249
- state.visibleColumns = columns.filter(p => (p as any)._enforceVisible == true).map(p => p.id);
250
- StorageHelper.saveStoredState(id, state);
251
- }
252
-
253
- static storePaginationLength(id: string, paginationLength: number) {
254
- const state = StorageHelper.getStoredState(id);
255
- state.paginationLength = paginationLength;
256
- StorageHelper.saveStoredState(id, state);
257
- }
258
-
259
- static storeSkin(id: string, skin: DataTableSkin) {
260
- const state = StorageHelper.getStoredState(id);
261
- state.skin = skin;
262
- StorageHelper.saveStoredState(id, state);
263
- }
264
-
265
- static storeMobileBehavior(id: string, mobileBehavior: DataTableMobileBehavior) {
266
- const state = StorageHelper.getStoredState(id);
267
- state.mobileBehavior = mobileBehavior;
268
- StorageHelper.saveStoredState(id, state);
269
- }
270
-
271
- static storeFilter(id: string, filter: DataTablePostBackFilterItem) {
272
- const state = StorageHelper.getStoredState(id);
273
- if (filter != null) {
274
- if (state.filter == null || state.filter.length == 0) {
275
- state.filter = [filter];
276
- } else {
277
- if (state.filter.some(p => p.PropertyName.includes(filter.PropertyName))) {
278
- state.filter = state.filter.filter(p => p.PropertyName != filter.PropertyName);
279
- }
280
-
281
- state.filter.push(filter);
282
- }
283
- } else if (state.filter != null) {
284
- delete state.filter;
285
- }
286
-
287
- StorageHelper.saveStoredState(id, state);
288
- }
205
+ private static getStorageKey(id: string) {
206
+ return `bldt-${window.location.pathname.split('/').join('_')}${id}`;
207
+ }
208
+
209
+ static getStoredState(id: string): StoredState {
210
+ const retVal = localStorage.getItem(StorageHelper.getStorageKey(id));
211
+ if (retVal != null) {
212
+ try {
213
+ return JSON.parse(retVal);
214
+ } catch (e) { }
215
+ }
216
+
217
+ return {} as any;
218
+ }
219
+
220
+ static saveStoredState(id: string, state: StoredState): void {
221
+ localStorage.setItem(StorageHelper.getStorageKey(id), JSON.stringify(state));
222
+ }
223
+
224
+ static storeSortOrder(id: string, sortOrder: string[]) {
225
+ const state = StorageHelper.getStoredState(id);
226
+ if (sortOrder != null) {
227
+ state.sortOrder = sortOrder;
228
+ } else if (state.sortOrder != null) {
229
+ delete state.sortOrder;
230
+ }
231
+
232
+ StorageHelper.saveStoredState(id, state);
233
+ }
234
+
235
+ static storeOrderBy(id: string, orderBy: SortDefinition) {
236
+ const state = StorageHelper.getStoredState(id);
237
+ if (orderBy != null) {
238
+ state.orderBy = orderBy;
239
+ } else if (state.orderBy != null) {
240
+ delete state.orderBy;
241
+ }
242
+
243
+ StorageHelper.saveStoredState(id, state);
244
+ }
245
+
246
+ static storeColVis(id: string, columns: TableColumn[]) {
247
+ const state = StorageHelper.getStoredState(id);
248
+ state.hiddenColumns = columns.filter(p => p.visible == false).map(p => p.id);
249
+ state.visibleColumns = columns.filter(p => (p as any)._enforceVisible == true).map(p => p.id);
250
+ StorageHelper.saveStoredState(id, state);
251
+ }
252
+
253
+ static storePaginationLength(id: string, paginationLength: number) {
254
+ const state = StorageHelper.getStoredState(id);
255
+ state.paginationLength = paginationLength;
256
+ StorageHelper.saveStoredState(id, state);
257
+ }
258
+
259
+ static storeSkin(id: string, skin: DataTableSkin) {
260
+ const state = StorageHelper.getStoredState(id);
261
+ state.skin = skin;
262
+ StorageHelper.saveStoredState(id, state);
263
+ }
264
+
265
+ static storeMobileBehavior(id: string, mobileBehavior: DataTableMobileBehavior) {
266
+ const state = StorageHelper.getStoredState(id);
267
+ state.mobileBehavior = mobileBehavior;
268
+ StorageHelper.saveStoredState(id, state);
269
+ }
270
+
271
+ static storeFilter(id: string, filter: DataTablePostBackFilterItem) {
272
+ const state = StorageHelper.getStoredState(id);
273
+ if (filter != null) {
274
+ if (state.filter == null || state.filter.length == 0) {
275
+ state.filter = [filter];
276
+ } else {
277
+ if (state.filter.some(p => p.PropertyName.includes(filter.PropertyName))) {
278
+ state.filter = state.filter.filter(p => p.PropertyName != filter.PropertyName);
279
+ }
280
+
281
+ state.filter.push(filter);
282
+ }
283
+ } else if (state.filter != null) {
284
+ delete state.filter;
285
+ }
286
+
287
+ StorageHelper.saveStoredState(id, state);
288
+ }
289
289
  }
290
290
 
291
291
  export interface TableColumn {
292
- id: string;
293
- caption: string;
294
- cssClass?: string;
295
- visible?: boolean;
296
- sortable?: boolean;
297
- searchable?: boolean;
298
- filterType?: DataTableFilterItemType;
299
- filterItems?: DataTableFilterItemCollection;
300
- filterAllowExclusivity?: boolean;
301
- customFilterValue?: (row) => string;
302
- mobileOrder?: number;
303
- mobileRender?: (h, row) => void;
304
- mobileCaption?: boolean;
305
- mobileVisible?: boolean;
306
- mobileShouldRenderRow?: (row) => boolean;
307
- exportInclude?: boolean;
308
- exportValue?: (row) => any;
309
- customValue?: (row) => string;
310
- customRender?: (h, row) => void;
311
- clientsideFilter?: (row: any, filterDefinition: DataTablePostBackFilterItem) => boolean;
292
+ id: string;
293
+ caption: string;
294
+ cssClass?: string;
295
+ visible?: boolean;
296
+ sortable?: boolean;
297
+ searchable?: boolean;
298
+ filterType?: DataTableFilterItemType;
299
+ filterItems?: DataTableFilterItemCollection;
300
+ filterAllowExclusivity?: boolean;
301
+ customFilterValue?: (row) => string;
302
+ mobileOrder?: number;
303
+ mobileRender?: (h, row) => void;
304
+ mobileCaption?: boolean;
305
+ mobileVisible?: boolean;
306
+ mobileShouldRenderRow?: (row) => boolean;
307
+ exportInclude?: boolean;
308
+ exportValue?: (row) => any;
309
+ customValue?: (row) => string;
310
+ customRender?: (h, row) => void;
311
+ clientsideFilter?: (row: any, filterDefinition: DataTablePostBackFilterItem) => boolean;
312
312
  }
313
313
 
314
314
  export interface TableButton {
315
- title: string;
316
- icon: string;
317
- clicked: () => void;
318
- childItems?: TableButtonChildItem[];
319
- customRender?: (h, row) => void;
315
+ title: string;
316
+ icon: string;
317
+ clicked: () => void;
318
+ childItems?: TableButtonChildItem[];
319
+ customRender?: (h, row) => void;
320
320
  }
321
321
 
322
322
  export interface TableButtonChildItem extends TableButton {
323
- isSelectable?: boolean;
324
- isSelected?: boolean;
323
+ isSelectable?: boolean;
324
+ isSelected?: boolean;
325
325
  }
326
326
 
327
327
  export interface DataTableFilterItem {
328
- id: string;
329
- text: string;
328
+ id: string;
329
+ text: string;
330
330
  }
331
331
 
332
332
  export class DataTableFilterItemCollection extends Array<DataTableFilterItem> {
333
- allowExclusiveSearch: boolean = false;
334
-
335
- constructor(allowExclusive: boolean, items: DataTableFilterItem[]) {
336
- super();
337
- this.allowExclusiveSearch = allowExclusive;
338
- (items || []).forEach((item) => {
339
- this.push(item);
340
- });
341
- }
333
+ allowExclusiveSearch: boolean = false;
334
+
335
+ constructor(allowExclusive: boolean, items: DataTableFilterItem[]) {
336
+ super();
337
+ this.allowExclusiveSearch = allowExclusive;
338
+ (items || []).forEach((item) => {
339
+ this.push(item);
340
+ });
341
+ }
342
342
  }
343
343
 
344
344
  export class DataTableConfig {
345
- static filterMarking = true;
345
+ static filterMarking = true;
346
346
  }
347
347
 
348
348
  @Component
349
349
  class TableButtonComponent extends TsxComponent<TableButton> implements TableButton {
350
- @Prop() title!: string;
351
- @Prop() icon!: string;
352
- @Prop() cssClass!: string;
353
- @Prop() clicked: () => void;
354
- @Prop() customRender: (h, row) => void;
355
- @Prop() childItems!: TableButtonChildItem[];
356
- randomUUID: string = `ddl-${PortalUtils.randomString(10)}`;
357
-
358
- render(h) {
359
- if (isNullOrEmpty(this.childItems)) {
360
- return (
361
- <button class={`dt-button${this.cssClass != null ? ` ${this.cssClass}` : ''}`} title={this.title} onClick={this.clicked}>
362
- <span>
363
- <i class={this.icon}></i>
364
- </span>
365
- </button>
366
- );
367
- } else {
368
- return (
369
- <span class="nav-item dt-button dropdown">
370
- <span class="dropdown-toggle" id={this.randomUUID} data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
371
- <i class={this.icon}></i>
372
- </span>
373
- <div class="dropdown-menu dropdown-menu-right" aria-labelledby={this.randomUUID}>
374
- {this.childItems.map(childItem => (
375
- <a class={`dropdown-item${childItem.isSelectable == true ? ' dropdown-selectable-section' : ''}`} href="javascript:" onClick={() => childItem.clicked()}>
376
- <span>{childItem.title}</span>
377
- {childItem.isSelected && <i class="fas fa-check"></i>}
378
- </a>
379
- ))}
380
- </div>
381
- </span>
382
- );
383
- }
384
- }
350
+ @Prop() title!: string;
351
+ @Prop() icon!: string;
352
+ @Prop() cssClass!: string;
353
+ @Prop() clicked: () => void;
354
+ @Prop() customRender: (h, row) => void;
355
+ @Prop() childItems!: TableButtonChildItem[];
356
+ randomUUID: string = `ddl-${PortalUtils.randomString(10)}`;
357
+
358
+ render(h) {
359
+ if (isNullOrEmpty(this.childItems)) {
360
+ return (
361
+ <button class={`dt-button${this.cssClass != null ? ` ${this.cssClass}` : ''}`} title={this.title} onClick={this.clicked}>
362
+ <span>
363
+ <i class={this.icon}></i>
364
+ </span>
365
+ </button>
366
+ );
367
+ } else {
368
+ return (
369
+ <span class="nav-item dt-button dropdown">
370
+ <span class="dropdown-toggle" id={this.randomUUID} data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
371
+ <i class={this.icon}></i>
372
+ </span>
373
+ <div class="dropdown-menu dropdown-menu-right" aria-labelledby={this.randomUUID}>
374
+ {this.childItems.map(childItem => (
375
+ <a class={`dropdown-item${childItem.isSelectable == true ? ' dropdown-selectable-section' : ''}`} href="javascript:" onClick={() => childItem.clicked()}>
376
+ <span>{childItem.title}</span>
377
+ {childItem.isSelected && <i class="fas fa-check"></i>}
378
+ </a>
379
+ ))}
380
+ </div>
381
+ </span>
382
+ );
383
+ }
384
+ }
385
385
  }
386
386
 
387
387
  @Component
388
388
  class DataTableComponent extends TsxComponent<DataTableArgs> implements DataTableArgs {
389
- @Prop() id!: string;
390
- @Prop() apiClient!: IWebApiClient;
391
- @Prop() apiMethod!: WebClientApiMethod;
392
- @Prop() allowMassOperations!: boolean;
393
- @Prop() allowExport!: boolean;
394
- @Prop() apiArgs!: any;
395
- @Prop() exportConfig?: DataTableExportConfig;
396
- @Prop() paginations?: number[];
397
- @Prop() paginationLengthProp!: number;
398
- @Prop() cssClass!: string;
399
- @Prop() autoFilter!: boolean;
400
- @Prop() insetTop!: boolean;
401
- @Prop() topVisible!: boolean;
402
- @Prop() bottomVisible!: boolean;
403
- @Prop() skin!: DataTableSkin;
404
- @Prop() preserveOrderBy!: boolean;
405
- @Prop() preserveFilter!: boolean;
406
- @Prop() sortableRows!: boolean;
407
- @Prop() filterMode!: DataTableFilterMode;
408
- @Prop() fullSizeTable!: boolean;
409
- @Prop() fullSizeHasButtonBelow!: boolean;
410
- @Prop() mobileBehavior!: DataTableMobileBehavior;
411
- @Prop() mobileModeCustomRender!: (h, columns: TableColumn[], rows: any) => void;
412
- @Prop() mobileModeRowIcon!: string;
413
- @Prop() mobileModeShouldAutoCollapse!: boolean;
414
- @Prop() handleInitialFilter!: boolean;
415
- @Prop() massOperationOptions!: typeof DropdownButtonItem.prototype[];
416
- @Prop() checkboxesVisible!: boolean;
417
- @Prop() checkboxesTitle!: string;
418
- @Prop() checkboxButtonsVisible!: boolean;
419
- @Prop() rowIndexMode!: RowIndexMode;
420
- @Prop() fulltextPlaceholder!: string;
421
- @Prop() timezoneGmtOffset!: number;
422
- @Prop() timezoneDstOffset!: number;
423
- @Prop() timeFilterShiftTimezone!: boolean;
424
- @Prop() columns!: TableColumn[];
425
- @Prop() buttons!: TableButton[];
426
- @Prop() rowClicked: (row: any) => void;
427
- @Prop() rowCssClass: (row: any) => string;
428
- @Prop() rowCheckstateChanged: (row: any, checked: boolean, selectedRows: any[]) => void;
429
- @Prop() parseLoadedRowset?: (serverResp: any) => DataTableLoadedRowset;
430
- @Prop() customAjaxCall?: (args: DataTablePostBackData) => Promise<DataTableLoadedRowset>;
431
- @Prop() sortComplete?: (args: DataTableOnSortedArgs) => void;
432
- @Prop() autoFetch!: boolean;
433
- @Prop() hidePagination!: boolean;
434
- paginationLength: number = this.paginationLengthProp ?? 50;
435
- paginationPosition: number = 1;
436
- isLoading: boolean = false;
437
- initialized: boolean = false;
438
- initDataLoaded: boolean = false;
439
- currentMobileBehavior: DataTableMobileBehavior = null;
440
- currentSkin: DataTableSkin = null;
441
- currentAdvancedFilterState: any = {};
442
- fullTextQuery: string;
443
-
444
- rows: any[] = [];
445
- loadedRows: any[];
446
- tableFilterTimeout: any = null;
447
- filterArr: DataTablePostBackFilterItem[] = [];
448
- sessionId: number = null;
449
- totalCount: number = 0;
450
- totalFilteredCount: number = 0;
451
- colSortOrder: string[] = null;
452
- enforceHeaderRedraw: boolean = false;
453
- enforceBodyRedraw: boolean = false;
454
- checkboxesShown: boolean = false;
455
- sortDefinition: SortDefinition = null;
456
- activeBreakPoint: DataTableBreakpoint = null;
457
- markInstance: any = null;
458
-
459
- mounted(): void {
460
- this.checkboxesShown = this.checkboxesVisible == true;
461
- this.currentSkin = this.skin;
462
- this.currentMobileBehavior = this.mobileBehavior;
463
- this.performColumnRefresh();
464
- this.handleWindowResized();
465
- window.addEventListener(
466
- 'resize',
467
- this.handleWindowResized,
468
- true,
469
- );
470
-
471
- if (DataTableConfig.filterMarking) {
472
- this.markInstance = new Mark(this.$el);
473
- }
474
-
475
- if (this.handleInitialFilter) {
476
- this.parseInitialFilter();
477
- }
478
-
479
- if (this.fullSizeTable) {
480
- const htmlElem = $('html');
481
- htmlElem.addClass('has-dt-fullsize');
482
-
483
- if (PortalUtils.treatAsMobileDevice()) {
484
- htmlElem.addClass('has-dt-fullsize-mobile');
485
- }
486
-
487
- if (PortalUtils.isIOS()) {
488
- htmlElem.addClass('has-dt-fullsize-ios');
489
- }
490
- }
491
-
492
- if (this.sortableRows == true) {
493
- this.initRowSortable();
494
- }
495
-
496
- if (this.preserveFilter == true) {
497
- this.initRowFilters();
498
- }
499
-
500
- if (this.autoFetch != false) {
501
- setTimeout(async () => {
502
- this.loadInitialData();
503
- }, 300);
504
- } else {
505
- this.initialized = true;
506
- }
507
- }
508
-
509
- updated(): void {
510
- if (this.autoFetch != false) {
511
- this.loadInitialData();
512
- } else {
513
- this.initialized = true;
514
- }
515
- }
516
-
517
- beforeUnmount(): void {
518
- if (this.fullSizeTable) {
519
- this.removeFullsizeModeLayoutCssClass();
520
-
521
- $('html').removeClass('has-dt-fullsize').removeClass('has-dt-fullsize-mobile').removeClass('has-dt-fullsize-ios');
522
- }
523
-
524
- window.removeEventListener(
525
- 'resize',
526
- this.handleWindowResized,
527
- true,
528
- );
529
- }
530
-
531
- loadInitialData(): void {
532
- if (this.apiArgs == null) {
533
- return;
534
- }
535
-
536
- if (!this.initialized && !this.initDataLoaded) {
537
- this.initDataLoaded = true;
538
- const self = this;
539
- this.reloadDataPromise().then(() => {
540
- setTimeout(() => {
541
- this.initialized = true;
542
- }, 1);
543
- });
544
- }
545
- }
546
-
547
- parseInitialFilter(): void {
548
- const self = this;
549
- const filterBy = QueryStringUtils.getString('filterBy');
550
- const orderBy = QueryStringUtils.getString('orderBy');
551
- const getColumn = function (id: string) {
552
- let column = self.columns.filter(p => p.id == id)[0];
553
- if (column == null && id.toLowerCase() == 'name') {
554
- column = self.columns.filter(p => (p as any).customField != null && (p as any).customField.MappingType == 1)[0];
555
- }
556
-
557
- if (column == null && id.toLowerCase() == 'surname') {
558
- column = self.columns.filter(p => (p as any).customField != null && (p as any).customField.MappingType == 2)[0];
559
- }
560
-
561
- return column;
562
- };
563
-
564
- const getParamArr = function (val: string): Array<Array<string>> {
565
- let arrOfArr: Array<Array<string>>;
566
- try {
567
- arrOfArr = JSON.parse(val);
568
- } catch (e) { }
569
-
570
- if (arrOfArr == null) {
571
- return null;
572
- }
573
-
574
- if (arrOfArr.length && arrOfArr.splice) {
575
- if (PortalUtils.isString(arrOfArr[0])) {
576
- arrOfArr = [arrOfArr as any];
577
- }
578
-
579
- return arrOfArr;
580
- }
581
-
582
- return null;
583
- };
584
-
585
- if (!isNullOrEmpty(filterBy)) {
586
- const arrOfArr = getParamArr(filterBy);
587
-
588
- if (!isNullOrEmpty(arrOfArr)) {
589
- arrOfArr.forEach((pair) => {
590
- const column = getColumn(pair[0]);
591
- if (column != null) {
592
- if (column.filterType == null || column.filterType == DataTableFilterItemType.Text) {
593
- this.addFilterItem(column, {
594
- PropertyName: column.id,
595
- ContainsValue: pair[1],
596
- FilterType: DataTableFilterItemType.Text,
597
- });
598
- } else if (column.filterType == DataTableFilterItemType.Dropdown) {
599
- this.addFilterItem(column, {
600
- PropertyName: column.id,
601
- ValueArr: [pair[1]],
602
- ValueArrStrategy: MultiSelectExclusivity.Exclusive,
603
- FilterType: DataTableFilterItemType.Dropdown,
604
- });
605
- }
606
- }
607
- });
608
- }
609
- }
610
-
611
- if (!isNullOrEmpty(orderBy)) {
612
- const arrOfArr = getParamArr(orderBy);
613
-
614
- if (!isNullOrEmpty(arrOfArr)) {
615
- arrOfArr.forEach((pair) => {
616
- const column = getColumn(pair[0]);
617
- if (column != null) {
618
- this.sortDefinition = {
619
- columnId: column.id,
620
- direction: pair[1] == 'desc' ? DataTableSortDirection.Descending : DataTableSortDirection.Ascending,
621
- };
622
- }
623
- });
624
- }
625
- }
626
- }
627
-
628
- async ensureMassPaginationConsent(): Promise<DialogResult> {
629
- const selectedCount = this.getSelectedRows().length;
630
- const paginationLength = this.getPaginationLength();
631
- if (paginationLength < 0) {
632
- return DialogResult.Confirm;
633
- }
634
-
635
- if (this.totalCount < paginationLength) {
636
- return DialogResult.Confirm;
637
- }
638
-
639
- if (selectedCount < paginationLength - 7) {
640
- return DialogResult.Confirm;
641
- }
642
-
643
- const continueLabel = `${PowerduckState.getResourceValue('continue')}&nbsp;&nbsp;<i class="icon icon-arrow-right-circle"></i>`;
644
- const messageHtml = PowerduckState.getResourceValue('dtMassOperationWarningText').replace('{0}', selectedCount.toString()).replace('{1}', this.totalCount.toString());
645
- const dialogResult = await DialogUtils.showConfirmDialog(
646
- PowerduckState.getResourceValue('warning'),
647
- messageHtml,
648
- continueLabel,
649
- PowerduckState.getResourceValue('cancel'),
650
- DialogIcons.Warning,
651
- );
652
- return dialogResult;
653
- }
654
-
655
- performColumnRefresh(): void {
656
- const savedState = StorageHelper.getStoredState(this.id);
657
- this.colSortOrder = savedState.sortOrder;
658
- this.handleColumnsVisibility(savedState, this.columns);
659
- this.paginationLength = savedState.paginationLength;
660
-
661
- if (savedState.skin != null) {
662
- this.currentSkin = savedState.skin;
663
- }
664
-
665
- if (savedState.mobileBehavior != null) {
666
- this.currentMobileBehavior = savedState.mobileBehavior;
667
- }
668
-
669
- if (savedState.orderBy != null) {
670
- this.sortDefinition = savedState.orderBy;
671
- }
672
-
673
- if (savedState.filter != null) {
674
- this.filterArr = savedState.filter;
675
- }
676
- }
677
-
678
- initRowSortable(): void {
679
- const args = {
680
- animation: 150,
681
- handle: '.dt-col-index',
682
- onEnd: (evt) => {
683
- this.sortComplete(evt);
684
- },
685
- } as any;
686
-
687
- this.$nextTick(() => {
688
- this.$nextTick(() => {
689
- new Sortable(this.$el.querySelector('tbody'), args);
690
- });
691
- });
692
- }
693
-
694
- reorderColumns(sortOrder: string[], columns: TableColumn[]): void {
695
- if (sortOrder != null && sortOrder.length >= columns.length) {
696
- const sorted = [];
697
- let allFound = true;
698
-
699
- if (sortOrder.length == columns.length) {
700
- sortOrder.forEach((propName) => {
701
- const ci = columns.filter(p => p.id == propName)[0];
702
- if (ci != null) {
703
- sorted.push(ci);
704
- } else {
705
- allFound = false;
706
- }
707
- });
708
- }
709
-
710
- if (!allFound) {
711
- StorageHelper.storeSortOrder(this.id, null);
712
- sortOrder = null;
713
- } else {
714
- columns.splice(0, columns.length);
715
- sorted.forEach((sortedCol) => {
716
- columns.push(sortedCol);
717
- });
718
- }
719
- }
720
- }
721
-
722
- initRowFilters(): void {
723
- const savedState = StorageHelper.getStoredState(this.id);
724
-
725
- if (savedState.filter == null) {
726
- return;
727
- }
728
-
729
- for (const filterItem of savedState.filter) {
730
- if (filterItem.FilterType == DataTableFilterItemType.None) {
731
- continue;
732
- } else if (filterItem.FilterType == DataTableFilterItemType.Dropdown) {
733
- this.currentAdvancedFilterState[filterItem.PropertyName] = filterItem.ValueArr;
734
- } else if (filterItem.FilterType == DataTableFilterItemType.DateRange) {
735
- this.currentAdvancedFilterState[filterItem.PropertyName] = {
736
- startTime: filterItem.DateFrom,
737
- endTime: filterItem.DateTo,
738
- };
739
- } else if (filterItem.FilterType == DataTableFilterItemType.NumericRange) {
740
-
741
- } else if (filterItem.FilterType == DataTableFilterItemType.Text) {
742
- this.currentAdvancedFilterState[filterItem.PropertyName] = filterItem.ContainsValue;
743
- }
744
- }
745
- }
746
-
747
- handleWindowResized(): void {
748
- const width = window.innerWidth;
749
- const breakpointMode = width > 767 ? DataTableBreakpoint.Desktop : DataTableBreakpoint.Mobile;
750
-
751
- if (breakpointMode != this.activeBreakPoint) {
752
- this.activeBreakPoint = breakpointMode;
753
- this.handleMobileBreakpointChanged();
754
- }
755
- }
756
-
757
- handleMobileBreakpointChanged() {
758
- if (this.fullSizeTable && PortalUtils.treatAsMobileDevice()) {
759
- this.removeFullsizeModeLayoutCssClass();
760
- $('html').addClass(`dt-fullsize-beh-${this.getMobileBehavior()}`);
761
- $('html').addClass(`dt-fullsize-skin-${this.getSkin()}`);
762
- }
763
- }
764
-
765
- removeFullsizeModeLayoutCssClass() {
766
- if (this.fullSizeTable && PortalUtils.treatAsMobileDevice()) {
767
- $('html')
768
- .removeClass(`dt-fullsize-beh-${DataTableMobileBehavior.Compact}`)
769
- .removeClass(`dt-fullsize-beh-${DataTableMobileBehavior.MobileLayout}`)
770
- .removeClass(`dt-fullsize-beh-${DataTableMobileBehavior.VerticalTransform}`)
771
- .removeClass(`dt-fullsize-skin-${DataTableSkin.Default}`)
772
- .removeClass(`dt-fullsize-skin-${DataTableSkin.Compact}`);
773
- }
774
- }
775
-
776
- handleColumnsVisibility(savedState: StoredState, columns: TableColumn[]): void {
777
- if (savedState.hiddenColumns != null) {
778
- savedState.hiddenColumns.forEach((hc) => {
779
- const colItem = columns.filter(p => p.id == hc)[0];
780
- if (colItem != null) {
781
- colItem.visible = false;
782
-
783
- if ((colItem as any)._enforceVisible != null) {
784
- delete (colItem as any)._enforceVisible;
785
- }
786
- }
787
- });
788
- }
789
-
790
- if (savedState.visibleColumns != null) {
791
- savedState.visibleColumns.forEach((vc) => {
792
- const colItem = columns.filter(p => p.id == vc)[0];
793
- if (colItem != null) {
794
- colItem.visible = true;
795
- (colItem as any)._enforceVisible = true;
796
- }
797
- });
798
- }
799
- }
800
-
801
- getPaginationLength(): number {
802
- return this.paginationLength || 50;
803
- }
804
-
805
- getTableColumnHeaderCssClass(column: TableColumn, index: number): string {
806
- return `dt-header-${column.id.split(':').join('_').toLowerCase()} dt-header-i${index} ${column.cssClass || ''}${column.sortable == false ? ' dt-header-notsortable' : ''}`;
807
- }
808
-
809
- getTableColumnHeaderFilterCssClass(column: TableColumn, index: number): string {
810
- return `header-filter-cell dt-filter-${column.id.split(':').join('_').toLowerCase()} dt-filter-i${index} dt-filtertype-${this.getFilterTypeName(column.filterType)}`;
811
- }
812
-
813
- getTableItemCssClass(column: TableColumn, index: number): string {
814
- return `dt-col-${column.id.split(':').join('_').toLowerCase()} dt-col-i${index} ${column.cssClass || ''}`;
815
- }
816
-
817
- getFilterTypeName(filterType: DataTableFilterItemType): string {
818
- switch (filterType) {
819
- case DataTableFilterItemType.None:
820
- return 'none';
821
-
822
- case null:
823
- case undefined:
824
- case DataTableFilterItemType.Text:
825
- return 'text';
826
-
827
- case DataTableFilterItemType.Dropdown:
828
- return 'dropdown';
829
-
830
- case DataTableFilterItemType.DateRange:
831
- return 'daterange';
832
-
833
- case DataTableFilterItemType.NumericRange:
834
- return 'numericrange';
835
-
836
- default:
837
- }
838
- }
839
-
840
- getRowIdProp(row: any): string {
841
- if (row?.Id != null) {
842
- return 'Id';
843
- }
844
-
845
- return 'id';
846
- }
847
-
848
- getRowId(row: any): number {
849
- return row[this.getRowIdProp(row)];
850
- }
851
-
852
- getSelectedRows(): any[] {
853
- const self = this;
854
- const selectedRows = [];
855
-
856
- if (isNullOrEmpty(self.rows)) {
857
- return [];
858
- }
859
-
860
- const rowIdProp = this.getRowIdProp(self.rows[0]);
861
-
862
- $('.dt-selection-checkbox input:checked').each(function (this: any) {
863
- const rowId = Number($(this).closest('.dt-selection-checkbox').attr('data-id'));
864
- const existingRow = selectedRows.filter(p => p[rowIdProp] == rowId)[0];
865
-
866
- if (existingRow == null) {
867
- const selectedRow = self.rows.filter(p => p[rowIdProp] == rowId)[0];
868
- if (selectedRow != null) {
869
- selectedRows.push(selectedRow);
870
- }
871
- }
872
- });
873
-
874
- return selectedRows;
875
- }
876
-
877
- unmarkSelection(cb: () => void): void {
878
- if (DataTableConfig.filterMarking) {
879
- this.markInstance.unmark({
880
- done: () => {
881
- this.enforceBodyRedraw = true;
882
- this.$nextTick(() => {
883
- this.enforceBodyRedraw = false;
884
- this.$nextTick(() => {
885
- cb();
886
- });
887
- });
888
- },
889
- });
890
- } else {
891
- cb();
892
- }
893
- }
894
-
895
- markSelection (): void {
896
- const mySelf = this;
897
- const escapeRegExp = function (string) {
898
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
899
- };
900
-
901
- const getValueArr = function (filterItem: DataTablePostBackFilterItem): string[] {
902
- if (!isNullOrEmpty(filterItem.EqualsValue)) {
903
- return [filterItem.EqualsValue];
904
- } else if (!isNullOrEmpty(filterItem.ContainsValue)) {
905
- return [filterItem.ContainsValue];
906
- } else if (!isNullOrEmpty(filterItem.ValueArr)) {
907
- return [];
908
- // return filterItem.ValueArr;
909
- }
910
- };
911
-
912
- let regexBuilder = '';
913
- const markArr = [];
914
- if (this.filterArr != null) {
915
- this.filterArr.forEach((filterItem) => {
916
- if (regexBuilder.length > 0) {
917
- regexBuilder += '|';
918
- }
919
-
920
- const columnId = filterItem.PropertyName?.toLowerCase();
921
- const tds = Array.from($(mySelf.$el).find(`td.dt-col-${columnId}`));
922
- if (tds == null || tds.length == 0) {
923
- return;
924
- }
925
-
926
- (getValueArr(filterItem) || []).forEach((filterValue) => {
927
- markArr.push({
928
- value: escapeRegExp(filterValue),
929
- elements: tds,
930
- });
931
- });
932
- });
933
- }
934
-
935
- if (!isNullOrEmpty(this.fullTextQuery)) {
936
- const value = escapeRegExp(this.fullTextQuery);
937
- const tds = Array.from($(mySelf.$el).find(`td`));
938
- regexBuilder += value;
939
-
940
- markArr.push({
941
- value,
942
- elements: tds,
943
- });
944
- }
945
-
946
- if (DataTableConfig.filterMarking) {
947
- this.unmarkSelection(() => {
948
- for (const item of markArr) {
949
- this.markInstance.mark(item.value, {
950
- filter: (node) => {
951
- const parentTd = $(node).closest('td')[0];
952
- if (!parentTd) {
953
- return false;
954
- }
955
-
956
- const matchesColumn = item.elements?.some(el => parentTd?.isEqualNode(el));
957
- const matchesText = parentTd?.textContent?.toLowerCase().includes(item.value.toLowerCase());
958
- return matchesColumn && matchesText;
959
- }
960
- });
961
- }
962
- });
963
- }
964
- }
965
-
966
- addFilterItem(dtColumn: TableColumn, newFilter: DataTablePostBackFilterItem): void {
967
- const existingItem = this.filterArr.filter(p => p.PropertyName == dtColumn.id)[0];
968
- const hasValue
969
- = !isNullOrEmpty(newFilter.ContainsValue)
970
- || !isNullOrEmpty(newFilter.EqualsValue)
971
- || !isNullOrEmpty(newFilter.ValueArr)
972
- || newFilter.DateFrom != null
973
- || newFilter.DateTo != null
974
- || newFilter.NumFrom != null
975
- || newFilter.NumTo != null;
976
-
977
- if (existingItem == null && hasValue) {
978
- this.filterArr.push(newFilter);
979
- return;
980
- }
981
-
982
- this.filterArr.splice(this.filterArr.indexOf(existingItem), 1);
983
- if (existingItem != null && hasValue) {
984
- this.filterArr.push(newFilter);
985
- }
986
- }
987
-
988
- filterDataHaveChanged(dtColumn: TableColumn, filterItem: DataTablePostBackFilterItem): boolean {
989
- const currentData: DataTablePostBackFilterItem = this.filterArr.filter(p => p.PropertyName == dtColumn.id)[0] || ({} as any);
990
- return JSON.stringify(currentData) != JSON.stringify(filterItem);
991
- }
992
-
993
- handleClientsideFilter(markResults?: boolean): boolean {
994
- if (this.filterMode == DataTableFilterMode.Clientside) {
995
- this.unmarkSelection(() => {
996
- this.performClientsideFilter();
997
-
998
- if (markResults) {
999
- this.markSelection();
1000
- }
1001
- });
1002
-
1003
- return true;
1004
- }
1005
-
1006
- return false;
1007
- }
1008
-
1009
- performFullTextSearch(e): void {
1010
- if (this.tableFilterTimeout != null) {
1011
- clearTimeout(this.tableFilterTimeout);
1012
- }
1013
-
1014
- this.fullTextQuery = e.target.value;
1015
-
1016
- e = e || window.event;
1017
- let charCode: number = -1;
1018
- if (e.which) {
1019
- charCode = e.which;
1020
- } else if (e.keyCode) {
1021
- charCode = e.keyCode;
1022
- }
1023
-
1024
- if (charCode == 13) {
1025
- if (this.handleClientsideFilter(true)) {
1026
- return;
1027
- }
1028
-
1029
- this.reloadData();
1030
- } else {
1031
- this.tableFilterTimeout = setTimeout(() => {
1032
- if (this.handleClientsideFilter(true)) {
1033
- return;
1034
- }
1035
-
1036
- this.reloadData();
1037
- }, 750);
1038
- }
1039
- }
1040
-
1041
- performInputFilter(dtColumn: TableColumn, e): void {
1042
- if (this.tableFilterTimeout != null) {
1043
- clearTimeout(this.tableFilterTimeout);
1044
- }
1045
-
1046
- this.currentAdvancedFilterState[dtColumn.id] = e;
1047
-
1048
- const filterItem = {
1049
- PropertyName: dtColumn.id,
1050
- ContainsValue: (e || ''),
1051
- FilterType: DataTableFilterItemType.Text,
1052
- };
1053
-
1054
- this.addFilterItem(dtColumn, filterItem);
1055
-
1056
- if (this.preserveFilter == true) {
1057
- if (isNullOrEmpty(filterItem.ContainsValue)) {
1058
- StorageHelper.storeFilter(this.id, null);
1059
- } else {
1060
- StorageHelper.storeFilter(this.id, filterItem);
1061
- }
1062
- }
1063
-
1064
- if (this.handleClientsideFilter(true)) {
1065
- return;
1066
- }
1067
-
1068
- e = (e) || window.event;
1069
- let charCode: number = -1;
1070
- if (e.which) {
1071
- charCode = e.which;
1072
- } else if (e.keyCode) {
1073
- charCode = e.keyCode;
1074
- }
1075
-
1076
- if (charCode == 13) {
1077
- this.reloadData();
1078
- } else {
1079
- this.tableFilterTimeout = setTimeout(() => {
1080
- this.reloadData();
1081
- }, 750);
1082
- }
1083
- }
1084
-
1085
- performSelectionFilter(
1086
- dtColumn: TableColumn,
1087
- data: DataTableFilterItem[],
1088
- exclusivity: MultiSelectExclusivity,
1089
- ): void {
1090
- this.currentAdvancedFilterState[dtColumn.id] = data;
1091
-
1092
- const filterValue: DataTablePostBackFilterItem = {
1093
- PropertyName: dtColumn.id,
1094
- ValueArr: (data || []).map(p => p.id),
1095
- ValueArrStrategy: exclusivity == MultiSelectExclusivity.Exclusive ? MultiSelectExclusivity.Exclusive : MultiSelectExclusivity.Inclusive,
1096
- FilterType: DataTableFilterItemType.Dropdown,
1097
- };
1098
-
1099
- if (!this.filterDataHaveChanged(dtColumn, filterValue)) {
1100
- return;
1101
- }
1102
-
1103
- if (data == null || data.length == 0) {
1104
- this.addFilterItem(dtColumn, {} as any);
1105
- } else {
1106
- this.addFilterItem(dtColumn, filterValue);
1107
- }
1108
-
1109
- if (this.preserveFilter == true) {
1110
- if (data == null || data.length == 0) {
1111
- StorageHelper.storeFilter(this.id, null);
1112
- } else {
1113
- StorageHelper.storeFilter(this.id, filterValue);
1114
- }
1115
- }
1116
-
1117
- if (this.handleClientsideFilter(false)) {
1118
- return;
1119
- }
1120
-
1121
- // Immediate reload if changed, delay handled by the Dropdown component
1122
- this.reloadData();
1123
- }
1124
-
1125
- performDateRangeFilter(dtColumn: TableColumn, data: DaterangeChangedArgs): void {
1126
- this.currentAdvancedFilterState[dtColumn.id] = data;
1127
-
1128
- let startDate = data?.startTime;
1129
- let endDate = data?.endTime;
1130
- if (data == null || data.startTime == null || data.endTime == null) {
1131
- this.addFilterItem(dtColumn, {} as any);
1132
- }
1133
-
1134
- if (data != null && this.timeFilterShiftTimezone) {
1135
- let dstOffset = this.timezoneDstOffset;
1136
- let gmtOffset = this.timezoneGmtOffset;
1137
-
1138
- if (dstOffset == null && this.rows != null) {
1139
- dstOffset = (this.rows.filter(p => p.TimezoneDstOffset != null && p.TimezoneDstOffset != 0)[0] || {}).TimezoneDstOffset;
1140
- if (dstOffset == null) {
1141
- dstOffset = 0;
1142
- }
1143
- }
1144
-
1145
- if (gmtOffset == null && this.rows != null) {
1146
- gmtOffset = (this.rows.filter(p => p.TimezoneGmtOffset != null && p.TimezoneGmtOffset != 0)[0] || {}).TimezoneGmtOffset;
1147
- if (gmtOffset == null) {
1148
- gmtOffset = 0;
1149
- }
1150
- }
1151
-
1152
- startDate = TimezoneHelper.getUTCFromLocalDate(
1153
- startDate,
1154
- dstOffset,
1155
- gmtOffset,
1156
- );
1157
- endDate = TimezoneHelper.getUTCFromLocalDate(
1158
- endDate,
1159
- dstOffset,
1160
- gmtOffset,
1161
- );
1162
- }
1163
-
1164
- const filterValue: DataTablePostBackFilterItem = {
1165
- PropertyName: dtColumn.id,
1166
- DateFrom: startDate,
1167
- DateTo: endDate,
1168
- FilterType: DataTableFilterItemType.DateRange,
1169
- };
1170
-
1171
- if (!this.filterDataHaveChanged(dtColumn, filterValue)) {
1172
- return;
1173
- }
1174
-
1175
- if (data == null || data.startTime == null || data.endTime == null) {
1176
- this.addFilterItem(dtColumn, {} as any);
1177
- } else {
1178
- this.addFilterItem(dtColumn, filterValue);
1179
- }
1180
-
1181
- if (this.preserveFilter == true) {
1182
- if (data == null || data.startTime == null || data.endTime == null) {
1183
- StorageHelper.storeFilter(this.id, null);
1184
- } else {
1185
- StorageHelper.storeFilter(this.id, filterValue);
1186
- }
1187
- }
1188
-
1189
- if (this.handleClientsideFilter(false)) {
1190
- return;
1191
- }
1192
-
1193
- // Immediate reload if changed, delay handled by the Dropdown component
1194
- this.reloadData();
1195
- }
1196
-
1197
- performClientsideFilter(): void {
1198
- this.rows = this.getClientsideFilteredAndSortedRows(this.loadedRows);
1199
- }
1200
-
1201
- getClientsideFilteredAndSortedRows(rowArr: any[]): any[] {
1202
- let newRowArr = [...rowArr];
1203
- for (const filterData of this.filterArr) {
1204
- const column = this.columns.find(p => p.id == filterData.PropertyName);
1205
- const filterDef = column?.clientsideFilter;
1206
-
1207
- if (filterDef != null) {
1208
- if (!isNullOrEmpty(filterData.ContainsValue)) {
1209
- filterData.ContainsValue = this.normalizeStringForSearch(filterData.ContainsValue);
1210
- }
1211
-
1212
- newRowArr = newRowArr.filter((p) => {
1213
- return filterDef(p, filterData);
1214
- });
1215
-
1216
- continue;
1217
- }
1218
-
1219
- if (filterData.FilterType == DataTableFilterItemType.Text && !isNullOrEmpty(filterData.ContainsValue)) {
1220
- const containsVal = this.normalizeStringForSearch(filterData.ContainsValue);
1221
- newRowArr = newRowArr.filter((p) => {
1222
- let val: any;
1223
- if (column?.customFilterValue != null) {
1224
- val = column.customFilterValue(p);
1225
- } else if (column?.customValue != null) {
1226
- val = column.customValue(p);
1227
- } else {
1228
- val = p[filterData.PropertyName];
1229
- }
1230
-
1231
- if (val == null) {
1232
- return false;
1233
- }
1234
-
1235
- if (typeof val === 'string' || val instanceof String) {
1236
- return this.normalizeStringForSearch(val as any).includes(containsVal);
1237
- }
1238
-
1239
- return this.normalizeStringForSearch((p[filterData.PropertyName] || '').toString()).includes(containsVal);
1240
- });
1241
- } else if (filterData.FilterType == DataTableFilterItemType.Dropdown && !isNullOrEmpty(filterData.ValueArr)) {
1242
- newRowArr = newRowArr.filter((p) => {
1243
- let propVal: any;
1244
- if (column?.customFilterValue != null) {
1245
- propVal = column.customFilterValue(p);
1246
- } else if (column?.customValue != null) {
1247
- propVal = column.customValue(p);
1248
- } else {
1249
- propVal = p[filterData.PropertyName];
1250
- }
1251
-
1252
- if (propVal == null) {
1253
- return false;
1254
- }
1255
-
1256
- if (filterData.ValueArr.length == 1) {
1257
- return propVal == filterData.ValueArr[0];
1258
- } else if (filterData.ValueArrStrategy == MultiSelectExclusivity.Inclusive) {
1259
- return filterData.ValueArr.includes(propVal);
1260
- }
1261
-
1262
- return true;
1263
- });
1264
- } else if (filterData.FilterType == DataTableFilterItemType.DateRange) {
1265
- const fromMs = filterData.DateFrom.getTime();
1266
- const toMs = filterData.DateTo.getTime();
1267
-
1268
- newRowArr = newRowArr.filter((p) => {
1269
- let propVal: any;
1270
- if (column?.customFilterValue != null) {
1271
- propVal = column.customFilterValue(p);
1272
- } else if (column?.customValue != null) {
1273
- propVal = column.customValue(p);
1274
- } else {
1275
- propVal = p[filterData.PropertyName];
1276
- }
1277
-
1278
- if (propVal == null) {
1279
- return false;
1280
- }
1281
-
1282
- try {
1283
- const timeMs = propVal.getTime();
1284
- return fromMs <= timeMs && toMs >= timeMs;
1285
- } catch (error) {
1286
- return false;
1287
- }
1288
- });
1289
- } else if (filterData.FilterType == DataTableFilterItemType.NumericRange) {
1290
- newRowArr = newRowArr.filter((p) => {
1291
- let propVal: any;
1292
- if (column?.customFilterValue != null) {
1293
- propVal = column.customFilterValue(p);
1294
- } else if (column?.customValue != null) {
1295
- propVal = column.customValue(p);
1296
- } else {
1297
- propVal = p[filterData.PropertyName];
1298
- }
1299
-
1300
- if (propVal == null) {
1301
- return false;
1302
- }
1303
-
1304
- return filterData.NumFrom <= propVal && filterData.NumTo >= propVal;
1305
- });
1306
- }
1307
- }
1308
-
1309
- if (!isNullOrEmpty(this.fullTextQuery)) {
1310
- const fulltextArr: any[] = [];
1311
- const normalizedQuery = this.normalizeStringForSearch(this.fullTextQuery);
1312
-
1313
- for (const row of newRowArr) {
1314
- for (const propName in row) {
1315
- const column = this.columns.find(p => p.id == propName);
1316
- let propVal: any;
1317
-
1318
- if (column?.customFilterValue != null) {
1319
- propVal = column.customFilterValue(row);
1320
- } else if (column?.customValue != null) {
1321
- propVal = column.customValue(row);
1322
- } else {
1323
- propVal = row[propName];
1324
- }
1325
-
1326
- if (propVal != null) {
1327
- if (this.normalizeStringForSearch(propVal.toString()).includes(normalizedQuery)) {
1328
- fulltextArr.push(row);
1329
- break;
1330
- }
1331
- }
1332
- }
1333
- }
1334
-
1335
- newRowArr = fulltextArr;
1336
- }
1337
-
1338
- if (this.sortDefinition != null) {
1339
- const colId = this.sortDefinition.columnId;
1340
- type SORT_TYPE_OPTS = 'string' | 'date' | 'unknown';
1341
- let sortType: SORT_TYPE_OPTS = 'unknown';
1342
-
1343
- for (const row of newRowArr) {
1344
- const item = row[colId];
1345
- if (item == null) {
1346
- continue;
1347
- }
1348
-
1349
- if (typeof item === 'string' || item instanceof String) {
1350
- sortType = 'string';
1351
- } else if (item.getTime != null && item.getSeconds != null) {
1352
- sortType = 'date';
1353
- } else {
1354
- sortType = 'unknown';
1355
- }
1356
-
1357
- break;
1358
- }
1359
-
1360
- if (sortType == 'string') {
1361
- const collator = new Intl.Collator(PowerduckState.getCurrentLanguage(), {
1362
- numeric: true,
1363
- sensitivity: 'base',
1364
- });
1365
- newRowArr = newRowArr.sort((a, b) => collator.compare(a[colId], b[colId]));
1366
- } else if (sortType == 'date') {
1367
- newRowArr = newRowArr.sort((a, b) => {
1368
- return (b[colId]?.getTime() || 0) - (a[colId]?.getTime() || 0);
1369
- });
1370
- } else {
1371
- try {
1372
- newRowArr = arraySort(newRowArr, this.sortDefinition.columnId);
1373
- } catch (error) { }
1374
- }
1375
-
1376
- if (this.sortDefinition.direction == DataTableSortDirection.Descending) {
1377
- newRowArr = newRowArr.reverse();
1378
- }
1379
- }
1380
-
1381
- return newRowArr;
1382
- }
1383
-
1384
- normalizeStringForSearch(str: string): string {
1385
- return latinize(str.toLowerCase()).trim();
1386
- }
1387
-
1388
- reloadData(): void {
1389
- this.reloadDataPromise().then((data) => {
1390
- this.handleClientsideFilter(false);
1391
- }).catch((err) => {
1392
-
1393
- });
1394
- }
1395
-
1396
- reloadDataPromise(paginationPosition?: number, paginationLength?: number): Promise<any> {
1397
- const mySelf = this;
1398
- this.isLoading = true;
1399
-
1400
- return new Promise((resolve, reject) => {
1401
- let loadPromise: Promise<any>;
1402
- if (mySelf.customAjaxCall == null) {
1403
- loadPromise = mySelf.apiClient[mySelf.apiMethod](mySelf.getAjaxArgs(paginationPosition, paginationLength));
1404
- } else {
1405
- loadPromise = mySelf.customAjaxCall(mySelf.getAjaxArgs(paginationPosition, paginationLength));
1406
- }
1407
-
1408
- loadPromise.then((data: any) => {
1409
- mySelf.unmarkSelection(() => {
1410
- mySelf.enforceBodyRedraw = true;
1411
- mySelf.$nextTick(() => {
1412
- mySelf.enforceBodyRedraw = false;
1413
- mySelf.isLoading = false;
1414
-
1415
- if (mySelf.parseLoadedRowset != null) {
1416
- const rowset = mySelf.parseLoadedRowset(data);
1417
- mySelf.totalCount = rowset.totalCount;
1418
- mySelf.totalFilteredCount = rowset.totalFilteredCount;
1419
- mySelf.rows = rowset.rows;
1420
- } else {
1421
- mySelf.totalCount = data.totalCount ?? data.TotalCount;
1422
- mySelf.totalFilteredCount = data.totalFilteredCount ?? data.TotalFilteredCount;
1423
- mySelf.rows = data.rows ?? data.Rows ?? data.data;
1424
- }
1425
-
1426
- mySelf.loadedRows = mySelf.rows;
1427
- mySelf.$forceUpdate();
1428
- mySelf.$nextTick(() => mySelf.markSelection());
1429
- resolve(data);
1430
- });
1431
- });
1432
- })
1433
- .catch((err) => {
1434
- mySelf.isLoading = false;
1435
- NotificationProvider.showErrorMessage(PowerduckState.getResourceValue('errorFetchingData'));
1436
- reject(err);
1437
- });
1438
- });
1439
- }
1440
-
1441
- getAjaxArgs(paginationPosition?: number, paginationLength?: number): DataTablePostBackData {
1442
- if (this.sessionId == null) {
1443
- this.sessionId = Math.floor(Math.random() * 2147483647) + 2147483647 * -1;
1444
- }
1445
-
1446
- const dataArgs = {} as any as DataTablePostBackData;
1447
- if (this.apiArgs != null) {
1448
- for (const key in this.apiArgs) {
1449
- const kv = this.apiArgs[key];
1450
- if (kv && {}.toString.call(kv) === '[object Function]') {
1451
- dataArgs[key] = kv.call(this);
1452
- } else {
1453
- dataArgs[key] = kv;
1454
- }
1455
- }
1456
- }
1457
-
1458
- dataArgs.SessionId = this.sessionId;
1459
- dataArgs.PaginationPosition = paginationPosition || this.paginationPosition;
1460
- dataArgs.PaginationLength = paginationLength || this.getPaginationLength();
1461
- dataArgs.Filter = {
1462
- FullText: this.fullTextQuery,
1463
- FilterItems: this.filterArr,
1464
- };
1465
-
1466
- if (this.sortDefinition != null) {
1467
- dataArgs.Sort = {
1468
- PropertyName: this.sortDefinition.columnId,
1469
- Direction: this.sortDefinition.direction,
1470
- };
1471
- }
1472
-
1473
- if (dataArgs.PaginationLength == -1) {
1474
- dataArgs.PaginationPosition = 1;
1475
- }
1476
-
1477
- return dataArgs;
1478
- }
1479
-
1480
- isMobileModeRenderType(): boolean {
1481
- return this.activeBreakPoint == 'mobile' && this.getMobileBehavior() == DataTableMobileBehavior.MobileLayout;
1482
- }
1483
-
1484
- forceHeaderRedraw(): void {
1485
- this.enforceHeaderRedraw = true;
1486
- this.$nextTick(() => (this.enforceHeaderRedraw = false));
1487
- }
1488
-
1489
- forceBodyRedraw(): void {
1490
- this.enforceBodyRedraw = true;
1491
- this.$nextTick(() => (this.enforceBodyRedraw = false));
1492
- }
1493
-
1494
- updateRows(rowArr: any[]): void {
1495
- this.rows = rowArr;
1496
- this.loadedRows = rowArr;
1497
- this.forceBodyRedraw();
1498
- }
1499
-
1500
- getTotalCount(): number {
1501
- return this.totalCount;
1502
- }
1503
-
1504
- setSkin(skin: DataTableSkin): void {
1505
- StorageHelper.storeSkin(this.id, skin);
1506
- this.currentSkin = skin;
1507
- this.handleMobileBreakpointChanged();
1508
- }
1509
-
1510
- setMobileBehavior(mobileBehavior: DataTableMobileBehavior): void {
1511
- StorageHelper.storeMobileBehavior(this.id, mobileBehavior);
1512
- this.currentMobileBehavior = mobileBehavior;
1513
- this.handleMobileBreakpointChanged();
1514
- }
1515
-
1516
- handleColumnsReordered(sortOrder: string[]): void {
1517
- sortOrder = sortOrder.filter(p => p != '_sysIndexCol');
1518
- StorageHelper.storeSortOrder(this.id, sortOrder);
1519
- this.colSortOrder = sortOrder;
1520
- this.reorderColumns(sortOrder, this.getVisibleColumns());
1521
- this.forceHeaderRedraw();
1522
- }
1523
-
1524
- async handleColumnHeaderClicked(dtColumn: TableColumn) {
1525
- if (dtColumn.sortable == false) {
1526
- return;
1527
- }
1528
-
1529
- const oldDef = this.sortDefinition;
1530
- let newDirection = DataTableSortDirection.Ascending;
1531
- if (this.sortDefinition != null && this.sortDefinition.columnId == dtColumn.id && this.sortDefinition.direction == DataTableSortDirection.Ascending) {
1532
- newDirection = DataTableSortDirection.Descending;
1533
- }
1534
-
1535
- this.sortDefinition = {
1536
- columnId: dtColumn.id,
1537
- direction: newDirection,
1538
- };
1539
-
1540
- if (this.preserveOrderBy == true) {
1541
- StorageHelper.storeOrderBy(this.id, this.sortDefinition);
1542
- }
1543
-
1544
- if (this.handleClientsideFilter(false)) {
1545
- return;
1546
- }
1547
-
1548
- try {
1549
- await this.reloadDataPromise();
1550
- } catch (e) {
1551
- this.sortDefinition = oldDef;
1552
- }
1553
- }
1554
-
1555
- handleColumnVisibilityChanged(columns: TableColumn[]): void {
1556
- StorageHelper.storeColVis(this.id, columns);
1557
- this.forceHeaderRedraw();
1558
- }
1559
-
1560
- handleColumnModalFilterChanged(e: ColFilterModalShowResponse): void {
1561
- if (e.changed) {
1562
- this.filterArr = e.filterArr;
1563
- this.reloadData();
1564
- }
1565
- }
1566
-
1567
- handleMobileRowClicked(e: any, row: any) {
1568
- if (this.checkboxesShown) {
1569
- let target = $(e.target);
1570
- if (!target.hasClass('dt-mobile-row-inner')) {
1571
- target = target.closest('.dt-mobile-row-inner');
1572
- }
1573
-
1574
- const input = target.find('.dt-selection-checkbox input')[0] as HTMLInputElement;
1575
- input.checked = !input.checked;
1576
- }
1577
-
1578
- if (this.rowClicked) {
1579
- this.rowClicked(row);
1580
- }
1581
- }
1582
-
1583
- handleRowCheckboxChanged(row: any, checked: boolean) {
1584
- if (this.rowCheckstateChanged != null) {
1585
- this.rowCheckstateChanged(
1586
- row,
1587
- checked,
1588
- this.getSelectedRows(),
1589
- );
1590
- }
1591
- }
1592
-
1593
- getLastPaginationIndex(): number {
1594
- let retVal = this.totalFilteredCount / this.getPaginationLength();
1595
- if (retVal % this.getPaginationLength() != 0) {
1596
- retVal = Math.floor(retVal) + 1;
1597
- }
1598
-
1599
- if (retVal == 0) {
1600
- retVal = 1;
1601
- }
1602
-
1603
- return retVal;
1604
- }
1605
-
1606
- async handlePaginationPositionChanged(newValue: number): Promise<any> {
1607
- if (this.paginationPosition == newValue || newValue < 1 || newValue > this.getLastPaginationIndex()) {
1608
- return;
1609
- }
1610
-
1611
- await this.reloadDataPromise(newValue);
1612
- this.paginationPosition = newValue;
1613
- }
1614
-
1615
- async handlePaginationLengthChanged(newValue: number) {
1616
- if (this.getPaginationLength() == newValue) {
1617
- return;
1618
- }
1619
-
1620
- await this.reloadDataPromise(null, newValue);
1621
- StorageHelper.storePaginationLength(this.id, newValue);
1622
- this.paginationLength = newValue;
1623
- }
1624
-
1625
- handleCheckAllChanged(checked: boolean): void {
1626
- $('.dt-col-indexcheckbox').each(function (this: HTMLElement) {
1627
- $(this).find('input').prop('checked', checked);
1628
- });
1629
-
1630
- this.handleRowCheckboxChanged(null, null);
1631
- }
1632
-
1633
- getNameAndSurnameIndex(name: string, surname: string): string {
1634
- let retVal: string;
1635
- if ((name != null && name.length > 0) || (surname != null && surname.length > 0)) {
1636
- name = name || '';
1637
- surname = surname || '';
1638
-
1639
- if (name.length > 0) {
1640
- if (surname.length > 0) {
1641
- retVal = name.substring(0, 1).toUpperCase() + surname.substring(0, 1).toUpperCase();
1642
- } else {
1643
- retVal = name;
1644
- }
1645
- } else {
1646
- retVal = surname;
1647
- }
1648
- }
1649
-
1650
- return retVal;
1651
- }
1652
-
1653
- getRowIdentifier(
1654
- columns: TableColumn[],
1655
- row: any,
1656
- includeColumns: boolean,
1657
- ): RowIdentifier {
1658
- let namingData: RowIdentifier;
1659
- if (row.CustomFields != null) {
1660
- const nameCf = (row.CustomFields.filter(p => p.MappingType == 1)[0] || {}) as any;
1661
- const surnameCf = (row.CustomFields.filter(p => p.MappingType == 2)[0] || {}) as any;
1662
- namingData = new RowIdentifier(nameCf.Value, surnameCf.Value);
1663
-
1664
- if (includeColumns && namingData.fullName.length > 1) {
1665
- namingData.dtColumns = [];
1666
-
1667
- const nameCol = columns.filter(p => p.id.includes(`cf:map:${1}`) || p.id.includes(`cf:id:${nameCf.Id}`))[0];
1668
- if (nameCol != null) {
1669
- namingData.dtColumns.push(nameCol);
1670
- }
1671
-
1672
- const surnameCol = columns.filter(p => p.id.includes(`cf:map:${2}`) || p.id.includes(`cf:id:${surnameCf.Id}`))[0];
1673
- if (surnameCol != null) {
1674
- namingData.dtColumns.push(surnameCol);
1675
- }
1676
- }
1677
- }
1678
-
1679
- if (namingData == null || (namingData.fullName.length < 2 && row.Name != null)) {
1680
- namingData = new RowIdentifier(row.Name, row.Surname);
1681
-
1682
- if (includeColumns) {
1683
- namingData.dtColumns = [];
1684
-
1685
- const nameCol = columns.filter(p => p.id == 'Name')[0];
1686
- if (nameCol != null) {
1687
- namingData.dtColumns.push(nameCol);
1688
- }
1689
-
1690
- const surnameCol = columns.filter(p => p.id == 'Surname')[0];
1691
- if (surnameCol != null) {
1692
- namingData;
1693
- }
1694
- }
1695
- }
1696
-
1697
- if (namingData == null || (namingData.fullName.length < 2 && row.Email != null)) {
1698
- if (row.Email != null) {
1699
- namingData = new RowIdentifier(row.Email, '');
1700
-
1701
- if (includeColumns) {
1702
- const emailCol = columns.filter(p => p.id == 'Email')[0];
1703
- if (emailCol != null) {
1704
- namingData.dtColumns = [emailCol];
1705
- }
1706
- }
1707
- }
1708
- }
1709
-
1710
- if (namingData == null || (namingData.fullName.length < 2 && row.TicketName != null)) {
1711
- if (row.TicketName != null) {
1712
- namingData = new RowIdentifier(row.TicketName, '');
1713
-
1714
- if (includeColumns) {
1715
- const emailCol = columns.filter(p => p.id == 'TicketName')[0];
1716
- if (emailCol != null) {
1717
- namingData.dtColumns = [emailCol];
1718
- }
1719
- }
1720
- }
1721
- }
1722
-
1723
- return namingData;
1724
- }
1725
-
1726
- getHeaderColumnIndex(
1727
- columns: TableColumn[],
1728
- row,
1729
- i,
1730
- ): string {
1731
- if (this.rowIndexMode == RowIndexMode.Index) {
1732
- return i + 1;
1733
- } else {
1734
- var indexText: string;
1735
- const rowIdentifier = this.getRowIdentifier(
1736
- columns,
1737
- row,
1738
- false,
1739
- );
1740
- if (rowIdentifier != null) {
1741
- indexText = this.getNameAndSurnameIndex(rowIdentifier.name, rowIdentifier.surname);
1742
- }
1743
-
1744
- var indexText: string;
1745
- if (row.CustomFields != null) {
1746
- const nameCf = row.CustomFields.filter(p => p.MappingType == 1)[0];
1747
- const surnameCf = row.CustomFields.filter(p => p.MappingType == 2)[0];
1748
- indexText = this.getNameAndSurnameIndex(nameCf != null ? nameCf.Value : '', surnameCf != null ? surnameCf.Value : '');
1749
- }
1750
-
1751
- if (indexText != null && indexText.length > 1) {
1752
- if (indexText.length > 2) {
1753
- const splitArr = indexText.split(' ');
1754
- if (splitArr.length > 1) {
1755
- indexText = (splitArr[0].substring(0, 1) + splitArr[1].substring(0, 1)).toUpperCase();
1756
- } else {
1757
- indexText = indexText.substring(0, 2).toUpperCase();
1758
- }
1759
- }
1760
- } else {
1761
- indexText = (i + 1).toString();
1762
- }
1763
-
1764
- return indexText;
1765
- }
1766
- }
1767
-
1768
- showColVis(): void {
1769
- (this.$refs.colVisModal as typeof ColVisModal.prototype).show();
1770
- }
1771
-
1772
- showFilterModal(): void {
1773
- (this.$refs.colFilterModal as typeof ColFilterModal.prototype).show({
1774
- filterArr: this.filterArr,
1775
- });
1776
- }
1777
-
1778
- exportExcel(): void {
1779
- (this.$refs.tableExportModal as typeof TableExportModal.prototype).show({
1780
- apiClient: this.apiClient,
1781
- apiMethod: this.apiMethod,
1782
- apiArgs: this.getAjaxArgs(),
1783
- columns: this.columns,
1784
- rows: this.rows,
1785
- exportConfig: this.exportConfig,
1786
- paginationOffset: this.paginationPosition - 1,
1787
- paginationLength: this.getPaginationLength(),
1788
- totalFilteredCount: this.totalFilteredCount,
1789
- });
1790
- }
1791
-
1792
- toggleCheckboxes(visible?: boolean): void {
1793
- if (visible == null) {
1794
- visible = !this.checkboxesShown;
1795
- }
1796
-
1797
- this.checkboxesShown = visible;
1798
- }
1799
-
1800
- getSkin(): DataTableSkin {
1801
- return this.currentSkin || DataTableSkin.Default;
1802
- }
1803
-
1804
- getMobileBehavior(): DataTableMobileBehavior {
1805
- return this.currentMobileBehavior || DataTableMobileBehavior.MobileLayout;
1806
- }
1807
-
1808
- getVisibleColumns(): TableColumn[] {
1809
- const state = StorageHelper.getStoredState(this.id);
1810
- const colArr = this.columns.filter(p => p.visible != false);
1811
- this.reorderColumns(this.colSortOrder, colArr);
1812
- this.handleColumnsVisibility(state, colArr);
1813
- return colArr;
1814
-
1815
- // return this.columns.filter(p => p.visible != false);
1816
- }
1817
-
1818
- isDesiredCustomFieldColumn(
1819
- dtCol: TableColumn,
1820
- row: any,
1821
- mappingType: any,
1822
- ): boolean {
1823
- const nameCf = row.CustomFields.filter(p => p.MappingType == mappingType)[0];
1824
- if (nameCf != null && ((dtCol.id.includes(`id:${nameCf.Id}`)) || (dtCol.id.includes(`map:${nameCf.MappingType}`)))) {
1825
- return true;
1826
- }
1827
-
1828
- return false;
1829
- }
1830
-
1831
- getChangeEventDelay() {
1832
- if (this.filterMode == DataTableFilterMode.Clientside) {
1833
- return 0;
1834
- } else {
1835
- return 650;
1836
- }
1837
- }
1838
-
1839
- getTableColumnOrder(dtCol: TableColumn, row: any): number {
1840
- if (dtCol.mobileOrder != null) {
1841
- return dtCol.mobileOrder;
1842
- }
1843
-
1844
- if (dtCol.id.includes('cf:') && row.CustomFields != null) {
1845
- if (this.isDesiredCustomFieldColumn(
1846
- dtCol,
1847
- row,
1848
- 1,
1849
- )) {
1850
- return -10100;
1851
- }
1852
-
1853
- if (this.isDesiredCustomFieldColumn(
1854
- dtCol,
1855
- row,
1856
- 1,
1857
- )) {
1858
- return -10000;
1859
- }
1860
- }
1861
-
1862
- if (dtCol.id == 'Name') {
1863
- return -9000;
1864
- }
1865
-
1866
- if (dtCol.id == 'TicketName') {
1867
- return -8900;
1868
- }
1869
-
1870
- return null;
1871
- }
1872
-
1873
- getTableColumnOrderStyle(dtCol: TableColumn, row: any): string {
1874
- const retVal = this.getTableColumnOrder(dtCol, row);
1875
- if (retVal != null) {
1876
- return `order:${retVal}`;
1877
- }
1878
-
1879
- return null;
1880
- }
1881
-
1882
- getMassOperationItems(): typeof DropdownButtonItem.prototype[] {
1883
- return this.massOperationOptions || [];
1884
- }
1885
-
1886
- shouldRenderMobileRowColumn(row, dtColumn: TableColumn): boolean {
1887
- if (dtColumn.customRender == null) {
1888
- if (dtColumn.customValue != null) {
1889
- return dtColumn.customValue(row) != null;
1890
- }
1891
-
1892
- return row[dtColumn.id] != null;
1893
- }
1894
-
1895
- if (dtColumn.mobileShouldRenderRow) {
1896
- return dtColumn.mobileShouldRenderRow(row);
1897
- }
1898
-
1899
- return true;
1900
- }
1901
-
1902
- clearSelection() {
1903
- $(this.$el).find('.dt-col-index').find('input').prop('checked', false);
1904
- }
1905
-
1906
- getFilterValue(dtColumn: TableColumn): any {
1907
- if (this.filterArr == null) {
1908
- return null;
1909
- }
1910
-
1911
- const filterItem = this.filterArr.filter(p => p.PropertyName == dtColumn.id)[0];
1912
- if (filterItem == null) {
1913
- return null;
1914
- }
1915
-
1916
- if (filterItem.FilterType == DataTableFilterItemType.Text) {
1917
- return filterItem.ContainsValue;
1918
- } else if (filterItem.FilterType == DataTableFilterItemType.Dropdown) {
1919
- return filterItem.ValueArr;
1920
- } else if (filterItem.FilterType == DataTableFilterItemType.DateRange) {
1921
- return {
1922
- startTime: filterItem.DateFrom,
1923
- endTime: filterItem.DateTo,
1924
- };
1925
- } else if (filterItem.FilterType == DataTableFilterItemType.NumericRange) {
1926
-
1927
- } else {
1928
- return null;
1929
- }
1930
- }
1931
-
1932
- render(h) {
1933
- const columns = this.getVisibleColumns();
1934
- let paginationStart = (this.paginationPosition - 1) * this.getPaginationLength() + 1;
1935
- let paginationEnd = Math.min(paginationStart + this.getPaginationLength(), this.totalFilteredCount) - 1;
1936
- const settingsUUID = `ddl-${PortalUtils.randomString(10)}`;
1937
- const isMobile = PortalUtils.treatAsMobileDevice();
1938
- const hasMobLayout = this.getMobileBehavior() == DataTableMobileBehavior.MobileLayout;
1939
- const hasTableSkin = this.getSkin() == DataTableSkin.Default;
1940
-
1941
- if (this.paginationPosition == this.getLastPaginationIndex()) {
1942
- paginationEnd += 1;
1943
- }
1944
-
1945
- if (this.totalFilteredCount == 0) {
1946
- paginationStart = 0;
1947
- paginationEnd = 0;
1948
- }
1949
-
1950
- if (this.getPaginationLength() == -1) {
1951
- paginationEnd = this.totalFilteredCount;
1952
- }
1953
-
1954
- return (
1955
- <div
1956
- class={
1957
- `dt-root dt-mobile-mobile dt-device-${PortalUtils.treatAsMobileDevice() ? 'mobile' : 'desktop'
1958
- }${PortalUtils.isIOS() ? ' dt-ios' : ''
1959
- } dt-skin-${this.getSkin()
1960
- } dt-mobbehavior-${this.getMobileBehavior()
1961
- }${this.checkboxesShown ? ' dt-checkboxes-visible' : ''
1962
- } dt-breakpoint-${this.activeBreakPoint
1963
- }${this.fullSizeHasButtonBelow ? ' dt-fs-buttonsbelow' : ''
1964
- }${this.insetTop ? ' dt-inset-top' : ''
1965
- }${this.fullSizeTable == true ? ' dt-fullsize-table' : ''
1966
- } ${this.cssClass || ''}`
1967
- }
1968
- >
1969
- {this.topVisible != false && (
1970
- <div class="dt-top">
1971
- <div class="dt-top-buttonsrow">
1972
- <div class="dt-buttons">
1973
- <TableButtonComponent title={PowerduckState.getResourceValue('colVisLabel')} icon="fa fa-eye-slash" clicked={() => this.showColVis()} />
1974
-
1975
- {this.buttons
1976
- && this.buttons.map(btn => (
1977
- <TableButtonComponent title={btn.title} icon={btn.icon} childItems={btn.childItems} customRender={btn.customRender} clicked={() => btn.clicked()} />
1978
- ))}
1979
-
1980
- {this.allowExport != false && <TableButtonComponent title="Excel export" icon="far fa-file-excel" clicked={() => this.exportExcel()} />}
1981
-
1982
- {this.allowMassOperations != false && <TableButtonComponent title={this.checkboxesTitle || ''} icon="far fa-check-square" clicked={() => this.toggleCheckboxes()} />}
1983
-
1984
- {this.activeBreakPoint == DataTableBreakpoint.Mobile && this.getMobileBehavior() == DataTableMobileBehavior.MobileLayout && (
1985
- <TableButtonComponent title="Filter" icon="fas fa-filter" clicked={() => this.showFilterModal()} />
1986
- )}
1987
-
1988
- <span class="nav-item dt-button dropdown">
1989
- <span class="dropdown-toggle" id={settingsUUID} data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
1990
- <i class="fas fa-desktop"></i>
1991
- </span>
1992
- <div class="dropdown-menu dropdown-menu-right" aria-labelledby={settingsUUID}>
1993
- {isMobile && (
1994
- <a class="dropdown-item dropdown-selectable-section" href="javascript:" onClick={() => this.setMobileBehavior(DataTableMobileBehavior.MobileLayout)}>
1995
- <span>{PowerduckState.getResourceValue('dtLayoutMobile')}</span>
1996
- {hasMobLayout && <i class="fas fa-check"></i>}
1997
- </a>
1998
- )}
1999
-
2000
- {!isMobile && (
2001
- <a class="dropdown-item dropdown-selectable-section" href="javascript:" onClick={() => this.setSkin(DataTableSkin.Default)}>
2002
- <span>{PowerduckState.getResourceValue('dtLayoutTable')}</span>
2003
- {hasTableSkin && <i class="fas fa-check"></i>}
2004
- </a>
2005
- )}
2006
-
2007
- <a
2008
- class="dropdown-item dropdown-selectable-section"
2009
- href="javascript:"
2010
- onClick={() => (isMobile ? this.setMobileBehavior(DataTableMobileBehavior.Compact) : this.setSkin(DataTableSkin.Compact))}
2011
- >
2012
- <span>{isMobile ? PowerduckState.getResourceValue('dtLayoutTable') : PowerduckState.getResourceValue('dtLayoutCompact')}</span>
2013
- {((isMobile && !hasMobLayout) || (!isMobile && !hasTableSkin)) && <i class="fas fa-check"></i>}
2014
- </a>
2015
- </div>
2016
- </span>
2017
- </div>
2018
- </div>
2019
- {this.hidePagination != true
2020
- && (
2021
- <div class="dt-top-paginationrow">
2022
- {(!this.checkboxesShown || this.checkboxButtonsVisible == false) && (
2023
- <div class="dt-pagination-length">
2024
- <select onChange={e => this.handlePaginationLengthChanged(Number(e.target.value))}>
2025
- {(this.paginations || [
2026
- 10,
2027
- 25,
2028
- 50,
2029
- 100,
2030
- 250,
2031
- 500,
2032
- 1000,
2033
- -1,
2034
- ]).map(item => (
2035
- <option value={item} selected={this.getPaginationLength() == item}>
2036
- {item != -1 ? item.toString() : PowerduckState.getResourceValue('all')}
2037
- </option>
2038
- ))}
2039
- </select>
2040
-
2041
- <span>{PowerduckState.getResourceValue('recordsDtLabel')}</span>
2042
- </div>
2043
- )}
2044
-
2045
- {this.checkboxesShown && this.checkboxButtonsVisible != false && (
2046
- <div class="dt-pagination-length dt-massop-btn-wrap">
2047
- <DropdownButton text="Hromadne operacie" layout={ButtonLayout.Secondary}>
2048
- {this.getMassOperationItems().map(mi =>
2049
- (mi as any).isSeparator != true ? <DropdownButtonItem icon={mi.icon} text={mi.text} clicked={mi.clicked} /> : <div class="dropdown-divider" />)}
2050
-
2051
- <DropdownButtonItem icon="icon icon-close" text={PowerduckState.getResourceValue('cancel')} clicked={() => this.toggleCheckboxes(false)} />
2052
- </DropdownButton>
2053
- <Button text={PowerduckState.getResourceValue('cancel')} layout={ButtonLayout.Default} clicked={() => this.toggleCheckboxes(false)} cssClass="dt-massop-cancelbtn" />
2054
- </div>
2055
- )}
2056
-
2057
- <div class="dt-fulltext-search">
2058
- <input type="search" placeholder={`${capitalize(PowerduckState.getResourceValue('search'))}...`} onKeyup={e => this.performFullTextSearch(e)} />
2059
- </div>
2060
- </div>
2061
- )}
2062
- </div>
2063
- )}
2064
-
2065
- {this.renderTableByMode(h, columns)}
2066
-
2067
- {this.bottomVisible != false && (
2068
- <div class="dt-bottom">
2069
- <div class="dt-summary-wrap">
2070
- {PowerduckState.getResourceValue('dtCountText').replace('{0}', paginationStart.toString()).replace('{1}', paginationEnd.toString()).replace('{2}', this.totalFilteredCount.toString())}
2071
- {this.totalFilteredCount != this.totalCount && (
2072
- <span class="dt-summary-totalcount">
2073
- &nbsp;
2074
- {PowerduckState.getResourceValue('dtCountFilteredOutOf').replace('{0}', this.totalCount.toString())}
2075
- </span>
2076
- )}
2077
- </div>
2078
-
2079
- <div class="dt-pagination">{this.renderPagination(h)}</div>
2080
- </div>
2081
- )}
2082
-
2083
- <ColVisModal ref="colVisModal" columns={this.columns} changed={e => this.handleColumnVisibilityChanged(e)} />
2084
- <ColFilterModal ref="colFilterModal" columns={this.columns} changed={e => this.handleColumnModalFilterChanged(e)} />
2085
- <TableExportModal ref="tableExportModal" />
2086
- </div>
2087
- );
2088
- }
2089
-
2090
- protected renderTableByMode(h, columns: TableColumn[]) {
2091
- if (this.activeBreakPoint == DataTableBreakpoint.Mobile) {
2092
- if (this.getMobileBehavior() == DataTableMobileBehavior.MobileLayout) {
2093
- return this.renderMobileMode(h, columns);
2094
- } else if (this.getMobileBehavior() == DataTableMobileBehavior.VerticalTransform) {
2095
- return this.renderVerticallyTransformedTable(h, columns);
2096
- }
2097
- }
2098
-
2099
- return this.renderStandardTable(h, columns);
2100
- }
2101
-
2102
- protected renderStandardTable(h, columns: TableColumn[]) {
2103
- return (
2104
- <div class="dt-table dt-table-mode">
2105
- <table>
2106
- <LoadingIndicator visible={!this.initialized} />
2107
-
2108
- {this.enforceHeaderRedraw == false && (
2109
- <thead>
2110
- <tr class="dt-header">
2111
- <th data-col-id="_sysIndexCol" class="dt-header-index">
2112
- {!this.isLoading && (
2113
- <span>
2114
- <span class="dt-header-indexlabel" style={this.checkboxesShown ? 'display:none' : ''}>
2115
- #
2116
- </span>
2117
- <span class="dt-header-indexcheckbox" style={this.checkboxesShown ? '' : 'display:none'}>
2118
- <CheckBox
2119
- skin={CheckBoxSkin.Material}
2120
- label={null}
2121
- wrap={false}
2122
- value={false}
2123
- changed={(e) => {
2124
- this.handleCheckAllChanged(e);
2125
- }}
2126
- />
2127
- </span>
2128
- </span>
2129
- )}
2130
-
2131
- {this.isLoading && <img src={loadingGif} />}
2132
- </th>
2133
-
2134
- {this.renderHeaderRow(h, columns)}
2135
- </tr>
2136
-
2137
- {this.autoFilter != false && (
2138
- <tr class="dt-header-filter">
2139
- <th class="dt-filter-index"></th>
2140
-
2141
- {columns.map((dtColumn, i) => (
2142
- <th class={this.getTableColumnHeaderFilterCssClass(dtColumn, i)}>{this.renderHeaderFilter(h, dtColumn)}</th>
2143
- ))}
2144
- </tr>
2145
- )}
2146
- </thead>
2147
- )}
2148
- <tbody>
2149
- {this.rowClicked == null
2150
- && this.enforceBodyRedraw == false
2151
- && (this.rows || []).map((row, i) => (
2152
- <tr class={`dt-item${this.rowCssClass == null ? '' : ` ${this.rowCssClass(row)}`}`}>
2153
- <td class={`dt-col-index${this.sortableRows == true ? ' dt-has-sortable-rows' : ''}`}>
2154
- <span class="dt-col-indexlabel" style={this.checkboxesShown ? 'display:none' : ''}>
2155
- {this.getHeaderColumnIndex(
2156
- columns,
2157
- row,
2158
- i,
2159
- )}
2160
- </span>
2161
- <span class="dt-col-indexcheckbox dt-selection-checkbox" data-id={this.getRowId(row)} style={this.checkboxesShown ? '' : 'display:none'}>
2162
- <CheckBox skin={CheckBoxSkin.Material} label={null} value={false} wrap={false} changed={e => this.handleRowCheckboxChanged(row, e)} />
2163
- </span>
2164
-
2165
- {this.sortableRows == true && <i class="fas fa-sort dt-sort-handle" />}
2166
- </td>
2167
-
2168
- {columns.map((dtColumn, j) => (
2169
- <td class={this.getTableItemCssClass(dtColumn, j)}>{dtColumn.customRender == null ? (dtColumn.customValue == null ? row[dtColumn.id] : dtColumn.customValue(row)) : dtColumn.customRender(h, row)}</td>
2170
- ))}
2171
- </tr>
2172
- ))}
2173
-
2174
- {this.rowClicked != null
2175
- && this.enforceBodyRedraw == false
2176
- && (this.rows || []).map((row, i) => (
2177
- <tr
2178
- class={`dt-item${this.rowCssClass == null ? '' : ` ${this.rowCssClass(row)}`}`}
2179
- onClick={() => {
2180
- this.rowClicked(row);
2181
- }}
2182
- >
2183
- <td class={`dt-col-index${this.sortableRows == true ? ' dt-has-sortable-rows' : ''}`}>
2184
- <span class="dt-col-indexlabel" style={this.checkboxesShown ? 'display:none' : ''}>
2185
- {this.getHeaderColumnIndex(
2186
- columns,
2187
- row,
2188
- i,
2189
- )}
2190
- </span>
2191
- <span class="dt-col-indexcheckbox dt-selection-checkbox" data-id={this.getRowId(row)} style={this.checkboxesShown ? '' : 'display:none'}>
2192
- <CheckBox skin={CheckBoxSkin.Material} label={null} value={false} wrap={false} changed={e => this.handleRowCheckboxChanged(row, e)} />
2193
- </span>
2194
-
2195
- {this.sortableRows == true && <i class="fas fa-sort dt-sort-handle" />}
2196
- </td>
2197
-
2198
- {columns.map((dtColumn, j) => (
2199
- <td class={this.getTableItemCssClass(dtColumn, j)}>{dtColumn.customRender == null ? (dtColumn.customValue == null ? row[dtColumn.id] : dtColumn.customValue(row)) : dtColumn.customRender(h, row)}</td>
2200
- ))}
2201
- </tr>
2202
- ))}
2203
-
2204
- {this.totalFilteredCount == 0 && (
2205
- <tr>
2206
- <td class="dt-no-results" colspan="99999">
2207
- <div class="dt-no-results-inner">
2208
- <div>{PowerduckState.getResourceValue('noResultsFound')}</div>
2209
- </div>
2210
- </td>
2211
- </tr>
2212
- )}
2213
- </tbody>
2214
- </table>
2215
- </div>
2216
- );
2217
- }
2218
-
2219
- protected renderHeaderRow(h, columns: TableColumn[]) {
2220
- return columns.map((dtColumn, i) => (
2221
- <th
2222
- data-col-id={dtColumn.id}
2223
- onMousedown={e =>
2224
- ReorderProvider.handleMouseDown(
2225
- e,
2226
- (sortOrder) => {
2227
- this.handleColumnsReordered(sortOrder);
2228
- },
2229
- () => {
2230
- this.handleColumnHeaderClicked(dtColumn);
2231
- },
2232
- )}
2233
- onTouchstart={e =>
2234
- ReorderProvider.handleMouseDown(
2235
- e,
2236
- (sortOrder) => {
2237
- this.handleColumnsReordered(sortOrder);
2238
- },
2239
- () => {
2240
- this.handleColumnHeaderClicked(dtColumn);
2241
- },
2242
- )}
2243
- class={this.getTableColumnHeaderCssClass(dtColumn, i)}
2244
- >
2245
- {dtColumn.caption}
2246
- {this.sortDefinition && this.sortDefinition.columnId == dtColumn.id && (
2247
- <span class="dt-sort">
2248
- <i class={`fas ${this.sortDefinition.direction == DataTableSortDirection.Ascending ? 'fa-sort-up' : 'fa-sort-down'} float-right`} aria-hidden="true"></i>
2249
- </span>
2250
- )}
2251
- </th>
2252
- ));
2253
- }
2254
-
2255
- protected renderHeaderFilter(h, dtColumn: TableColumn) {
2256
- const filterType = dtColumn.filterType;
2257
- const filterValue = this.getFilterValue(dtColumn);
2258
- const closeIcon = !isNullOrEmpty(filterValue) ? 'icon icon-close' : null;
2259
- const appendIconClicked = () => {
2260
- if (this.currentAdvancedFilterState[dtColumn.id] != null) {
2261
- this.currentAdvancedFilterState[dtColumn.id] = null;
2262
- }
2263
-
2264
- if (this.filterArr != null) {
2265
- this.filterArr = this.filterArr.filter(p => p.PropertyName != dtColumn.id);
2266
- }
2267
-
2268
- if (filterType == DataTableFilterItemType.Text || filterType == null) {
2269
- this.performInputFilter(dtColumn, null);
2270
- } else if (filterType == DataTableFilterItemType.DateRange) {
2271
- this.performDateRangeFilter(dtColumn, null);
2272
- } else if (filterType == DataTableFilterItemType.Dropdown) {
2273
- this.performSelectionFilter(
2274
- dtColumn,
2275
- [],
2276
- null,
2277
- );
2278
- } else if (filterType == DataTableFilterItemType.NumericRange) {
2279
-
2280
- }
2281
- };
2282
-
2283
- if (filterType == DataTableFilterItemType.None) {
2284
- return '';
2285
- } else if (filterType == DataTableFilterItemType.Text || filterType == null) {
2286
- return (<TextBox updateMode="input" cssClass="dt-filter-input" wrap={false} label={null} placeholder={`${capitalize(PowerduckState.getResourceValue('search'))}...`} value={this.currentAdvancedFilterState[dtColumn.id]} changed={(e) => { this.performInputFilter(dtColumn, e); }} appendIcon={closeIcon} appendIconClicked={appendIconClicked} />);
2287
- } else if (filterType == DataTableFilterItemType.Dropdown) {
2288
- return (
2289
- <div class="dt-filter-dropdown">
2290
- <DropdownList
2291
- label={null}
2292
- containerCssClass="dt-filter-dropdown-container"
2293
- options={dtColumn.filterItems}
2294
- wrap={false}
2295
- disableSearch={!dtColumn.searchable}
2296
- dropdownAutoWidth={true}
2297
- multiselect={true}
2298
- multiselectMode={MultiselectMode.Checkboxes}
2299
- mobileShortMode={true}
2300
- allowExclusiveSearch={dtColumn.filterAllowExclusivity}
2301
- changedEventDelay={this.getChangeEventDelay()}
2302
- selected={this.currentAdvancedFilterState[dtColumn.id]}
2303
- changed={(changeArr, exclusivity) => {
2304
- this.performSelectionFilter(
2305
- dtColumn,
2306
- changeArr,
2307
- exclusivity,
2308
- );
2309
- }}
2310
- appendIcon={closeIcon}
2311
- appendIconClicked={appendIconClicked}
2312
- />
2313
- </div>
2314
- );
2315
- } else if (filterType == DataTableFilterItemType.DateRange) {
2316
- return (<DaterangePicker label={null} cssClass="dt-filter-input" wrap={false} placeholder={`${capitalize(PowerduckState.getResourceValue('search'))}...`} value={this.currentAdvancedFilterState[dtColumn.id]} changed={(e) => { this.performDateRangeFilter(dtColumn, e); }} appendIcon={closeIcon} appendIconClicked={appendIconClicked} />);
2317
- }
2318
- }
2319
-
2320
- protected renderVerticallyTransformedTable(h, columns: TableColumn[]) {
2321
- return (this.rows || []).map((row, i) => (
2322
- <div class="dt-vert-row">
2323
- {columns.map((dtColumn, j) => (
2324
- <div class="dt-vert-item" style={this.getTableColumnOrderStyle(dtColumn, row)}>
2325
- <div class="dt-vert-caption">{dtColumn.caption}</div>
2326
- <div class="dt-vert-value">{dtColumn.customRender == null ? (dtColumn.customValue == null ? row[dtColumn.id] : dtColumn.customValue(row)) : dtColumn.customRender(h, row)}</div>
2327
- </div>
2328
- ))}
2329
- </div>
2330
- ));
2331
- }
2332
-
2333
- protected renderMobileMode(h, columns: TableColumn[]) {
2334
- if (this.mobileModeCustomRender != null) {
2335
- return this.mobileModeCustomRender(
2336
- h,
2337
- columns,
2338
- this.rows,
2339
- );
2340
- }
2341
-
2342
- return (
2343
- <div class="dt-mobile-rows">
2344
- {(this.isLoading || this.enforceBodyRedraw || this.enforceHeaderRedraw) && (
2345
- <div style="min-height:150px;">
2346
- <LoadingIndicator visible={true} />
2347
- </div>
2348
- )}
2349
-
2350
- {this.enforceHeaderRedraw == false
2351
- && this.enforceBodyRedraw == false
2352
- && (this.rows || []).map((row, i) => (
2353
- <div class={`dt-mobile-row${this.rowCssClass == null ? '' : ` ${this.rowCssClass(row)}`}`}>
2354
- {this.renderMobileModeRow(
2355
- h,
2356
- columns,
2357
- row,
2358
- i,
2359
- )}
2360
- </div>
2361
- ))}
2362
- </div>
2363
- );
2364
- }
2365
-
2366
- protected renderMobileModeRow(
2367
- h,
2368
- columns: TableColumn[],
2369
- row: any,
2370
- i: number,
2371
- ) {
2372
- const identifier = this.getRowIdentifier(
2373
- columns,
2374
- row,
2375
- true,
2376
- );
2377
- let colArr = this.getVisibleColumns().filter(p => p.mobileVisible != false);
2378
- const cssClass = `dt-mobile-row-inner${this.checkboxesShown ? ' dt-mobile-chbvisible' : ''}`;
2379
-
2380
- // Exclude identifier columns if they are already picked by the engine
2381
- if (identifier != null && identifier.dtColumns != null && identifier.dtColumns.length > 0) {
2382
- colArr = colArr.filter(p => !identifier.dtColumns.map(c => c.id).includes(p.id));
2383
- }
2384
-
2385
- return (
2386
- <div
2387
- class={cssClass}
2388
- onClick={(e) => {
2389
- this.handleMobileRowClicked(e, row);
2390
- }}
2391
- >
2392
- {this.checkboxesShown && (
2393
- <div class="dt-mobile-checkbox dt-selection-checkbox" data-id={this.getRowId(row)}>
2394
- <CheckBox skin={CheckBoxSkin.Material} label={null} wrap={false} value={null} changed={e => this.handleRowCheckboxChanged(row, e)} />
2395
- </div>
2396
- )}
2397
-
2398
- {identifier && <div class="dt-mobile-identifier">{identifier.fullName}</div>}
2399
-
2400
- {colArr.map((dtColumn, j) => (
2401
- <div class={`dt-mobile-item dt-mobile-${dtColumn.id.replaceAll(':', '_').toLowerCase()}`} style={this.getTableColumnOrderStyle(dtColumn, row)}>
2402
- {dtColumn.mobileRender == null && this.shouldRenderMobileRowColumn(row, dtColumn) && (
2403
- <div class="dt-mobile-item-inner">
2404
- {dtColumn.mobileCaption != false && <div class="dt-mobile-caption">{dtColumn.caption}</div>}
2405
-
2406
- <div class="dt-mobile-value">{dtColumn.customRender == null ? (dtColumn.customValue == null ? row[dtColumn.id] : dtColumn.customValue(row)) : dtColumn.customRender(h, row)}</div>
2407
- </div>
2408
- )}
2409
- {dtColumn.mobileRender && dtColumn.mobileRender(h, row)}
2410
- </div>
2411
- ))}
2412
-
2413
- <i class={`${this.mobileModeRowIcon || 'icon icon-arrow-right'} dt-mobile-row-icon`}></i>
2414
- </div>
2415
- );
2416
- }
2417
-
2418
- protected renderPagination(h) {
2419
- let paginationLength = 5;
2420
- let firstIndex = Math.max(this.paginationPosition - 2, 1);
2421
- let paginationEnd = firstIndex + paginationLength - 1;
2422
- let indexArr = [];
2423
-
2424
- if (this.getPaginationLength() > -1) {
2425
- if (paginationEnd > this.getLastPaginationIndex()) {
2426
- paginationEnd = this.getLastPaginationIndex();
2427
- firstIndex = paginationEnd - paginationLength + 1;
2428
- }
2429
-
2430
- if (firstIndex < 1) {
2431
- firstIndex = 1;
2432
- paginationLength = paginationEnd - firstIndex + 1;
2433
- }
2434
-
2435
- for (let i = firstIndex, len = paginationLength; i <= paginationEnd; i++) {
2436
- indexArr.push(i);
2437
- }
2438
- } else {
2439
- indexArr = [1];
2440
- this.paginationPosition = 1;
2441
- }
2442
-
2443
- return (
2444
- <ul class="pagination">
2445
- <li class="page-item">
2446
- <a class="page-link" href="javascript:" aria-label="Previous" onClick={e => this.handlePaginationPositionChanged(this.paginationPosition - 1)}>
2447
- <span aria-hidden="true">
2448
- <i class="fa fa-angle-double-left" aria-hidden="true"></i>
2449
- </span>
2450
- </a>
2451
- </li>
2452
-
2453
- {indexArr.map(pagIndex => (
2454
- <li class={`page-item${pagIndex == this.paginationPosition ? ' active' : ''}`} onClick={e => this.handlePaginationPositionChanged(pagIndex)}>
2455
- <a class="page-link" href="javascript:">
2456
- {pagIndex}
2457
- </a>
2458
- </li>
2459
- ))}
2460
-
2461
- <li class="page-item">
2462
- <a class="page-link" href="javascript:" aria-label="Next" onClick={e => this.handlePaginationPositionChanged(this.paginationPosition + 1)}>
2463
- <span aria-hidden="true">
2464
- <i class="fa fa-angle-double-right" aria-hidden="true"></i>
2465
- </span>
2466
- </a>
2467
- </li>
2468
- </ul>
2469
- );
2470
- }
2471
-
2472
- protected renderColumnValue(
2473
- h,
2474
- dtColumn: TableColumn,
2475
- row,
2476
- ) {
2477
- if (dtColumn.customRender == null) {
2478
- return (dtColumn.customValue == null ? row[dtColumn.id] : dtColumn.customValue(row));
2479
- } else {
2480
- return dtColumn.customRender(h, row);
2481
- }
2482
- }
389
+ @Prop() id!: string;
390
+ @Prop() apiClient!: IWebApiClient;
391
+ @Prop() apiMethod!: WebClientApiMethod;
392
+ @Prop() allowMassOperations!: boolean;
393
+ @Prop() allowExport!: boolean;
394
+ @Prop() apiArgs!: any;
395
+ @Prop() exportConfig?: DataTableExportConfig;
396
+ @Prop() paginations?: number[];
397
+ @Prop() paginationLengthProp!: number;
398
+ @Prop() cssClass!: string;
399
+ @Prop() autoFilter!: boolean;
400
+ @Prop() insetTop!: boolean;
401
+ @Prop() topVisible!: boolean;
402
+ @Prop() bottomVisible!: boolean;
403
+ @Prop() skin!: DataTableSkin;
404
+ @Prop() preserveOrderBy!: boolean;
405
+ @Prop() preserveFilter!: boolean;
406
+ @Prop() sortableRows!: boolean;
407
+ @Prop() filterMode!: DataTableFilterMode;
408
+ @Prop() fullSizeTable!: boolean;
409
+ @Prop() fullSizeHasButtonBelow!: boolean;
410
+ @Prop() mobileBehavior!: DataTableMobileBehavior;
411
+ @Prop() mobileModeCustomRender!: (h, columns: TableColumn[], rows: any) => void;
412
+ @Prop() mobileModeRowIcon!: string;
413
+ @Prop() mobileModeShouldAutoCollapse!: boolean;
414
+ @Prop() handleInitialFilter!: boolean;
415
+ @Prop() massOperationOptions!: typeof DropdownButtonItem.prototype[];
416
+ @Prop() checkboxesVisible!: boolean;
417
+ @Prop() checkboxesTitle!: string;
418
+ @Prop() checkboxButtonsVisible!: boolean;
419
+ @Prop() rowIndexMode!: RowIndexMode;
420
+ @Prop() fulltextPlaceholder!: string;
421
+ @Prop() timezoneGmtOffset!: number;
422
+ @Prop() timezoneDstOffset!: number;
423
+ @Prop() timeFilterShiftTimezone!: boolean;
424
+ @Prop() columns!: TableColumn[];
425
+ @Prop() buttons!: TableButton[];
426
+ @Prop() rowClicked: (row: any) => void;
427
+ @Prop() rowCssClass: (row: any) => string;
428
+ @Prop() rowCheckstateChanged: (row: any, checked: boolean, selectedRows: any[]) => void;
429
+ @Prop() parseLoadedRowset?: (serverResp: any) => DataTableLoadedRowset;
430
+ @Prop() customAjaxCall?: (args: DataTablePostBackData) => Promise<DataTableLoadedRowset>;
431
+ @Prop() sortComplete?: (args: DataTableOnSortedArgs) => void;
432
+ @Prop() autoFetch!: boolean;
433
+ @Prop() hidePagination!: boolean;
434
+ paginationLength: number = this.paginationLengthProp ?? 50;
435
+ paginationPosition: number = 1;
436
+ isLoading: boolean = false;
437
+ initialized: boolean = false;
438
+ initDataLoaded: boolean = false;
439
+ currentMobileBehavior: DataTableMobileBehavior = null;
440
+ currentSkin: DataTableSkin = null;
441
+ currentAdvancedFilterState: any = {};
442
+ fullTextQuery: string;
443
+
444
+ rows: any[] = [];
445
+ loadedRows: any[];
446
+ tableFilterTimeout: any = null;
447
+ filterArr: DataTablePostBackFilterItem[] = [];
448
+ sessionId: number = null;
449
+ totalCount: number = 0;
450
+ totalFilteredCount: number = 0;
451
+ colSortOrder: string[] = null;
452
+ enforceHeaderRedraw: boolean = false;
453
+ enforceBodyRedraw: boolean = false;
454
+ checkboxesShown: boolean = false;
455
+ sortDefinition: SortDefinition = null;
456
+ activeBreakPoint: DataTableBreakpoint = null;
457
+ markInstance: any = null;
458
+
459
+ mounted(): void {
460
+ this.checkboxesShown = this.checkboxesVisible == true;
461
+ this.currentSkin = this.skin;
462
+ this.currentMobileBehavior = this.mobileBehavior;
463
+ this.performColumnRefresh();
464
+ this.handleWindowResized();
465
+ window.addEventListener(
466
+ 'resize',
467
+ this.handleWindowResized,
468
+ true,
469
+ );
470
+
471
+ if (DataTableConfig.filterMarking) {
472
+ this.markInstance = new Mark(this.$el);
473
+ }
474
+
475
+ if (this.handleInitialFilter) {
476
+ this.parseInitialFilter();
477
+ }
478
+
479
+ if (this.fullSizeTable) {
480
+ const htmlElem = $('html');
481
+ htmlElem.addClass('has-dt-fullsize');
482
+
483
+ if (PortalUtils.treatAsMobileDevice()) {
484
+ htmlElem.addClass('has-dt-fullsize-mobile');
485
+ }
486
+
487
+ if (PortalUtils.isIOS()) {
488
+ htmlElem.addClass('has-dt-fullsize-ios');
489
+ }
490
+ }
491
+
492
+ if (this.sortableRows == true) {
493
+ this.initRowSortable();
494
+ }
495
+
496
+ if (this.preserveFilter == true) {
497
+ this.initRowFilters();
498
+ }
499
+
500
+ if (this.autoFetch != false) {
501
+ setTimeout(async () => {
502
+ this.loadInitialData();
503
+ }, 300);
504
+ } else {
505
+ this.initialized = true;
506
+ }
507
+ }
508
+
509
+ updated(): void {
510
+ if (this.autoFetch != false) {
511
+ this.loadInitialData();
512
+ } else {
513
+ this.initialized = true;
514
+ }
515
+ }
516
+
517
+ beforeUnmount(): void {
518
+ if (this.fullSizeTable) {
519
+ this.removeFullsizeModeLayoutCssClass();
520
+
521
+ $('html').removeClass('has-dt-fullsize').removeClass('has-dt-fullsize-mobile').removeClass('has-dt-fullsize-ios');
522
+ }
523
+
524
+ window.removeEventListener(
525
+ 'resize',
526
+ this.handleWindowResized,
527
+ true,
528
+ );
529
+ }
530
+
531
+ loadInitialData(): void {
532
+ if (this.apiArgs == null) {
533
+ return;
534
+ }
535
+
536
+ if (!this.initialized && !this.initDataLoaded) {
537
+ this.initDataLoaded = true;
538
+ const self = this;
539
+ this.reloadDataPromise().then(() => {
540
+ setTimeout(() => {
541
+ this.initialized = true;
542
+ }, 1);
543
+ });
544
+ }
545
+ }
546
+
547
+ parseInitialFilter(): void {
548
+ const self = this;
549
+ const filterBy = QueryStringUtils.getString('filterBy');
550
+ const orderBy = QueryStringUtils.getString('orderBy');
551
+ const getColumn = function (id: string) {
552
+ let column = self.columns.filter(p => p.id == id)[0];
553
+ if (column == null && id.toLowerCase() == 'name') {
554
+ column = self.columns.filter(p => (p as any).customField != null && (p as any).customField.MappingType == 1)[0];
555
+ }
556
+
557
+ if (column == null && id.toLowerCase() == 'surname') {
558
+ column = self.columns.filter(p => (p as any).customField != null && (p as any).customField.MappingType == 2)[0];
559
+ }
560
+
561
+ return column;
562
+ };
563
+
564
+ const getParamArr = function (val: string): Array<Array<string>> {
565
+ let arrOfArr: Array<Array<string>>;
566
+ try {
567
+ arrOfArr = JSON.parse(val);
568
+ } catch (e) { }
569
+
570
+ if (arrOfArr == null) {
571
+ return null;
572
+ }
573
+
574
+ if (arrOfArr.length && arrOfArr.splice) {
575
+ if (PortalUtils.isString(arrOfArr[0])) {
576
+ arrOfArr = [arrOfArr as any];
577
+ }
578
+
579
+ return arrOfArr;
580
+ }
581
+
582
+ return null;
583
+ };
584
+
585
+ if (!isNullOrEmpty(filterBy)) {
586
+ const arrOfArr = getParamArr(filterBy);
587
+
588
+ if (!isNullOrEmpty(arrOfArr)) {
589
+ arrOfArr.forEach((pair) => {
590
+ const column = getColumn(pair[0]);
591
+ if (column != null) {
592
+ if (column.filterType == null || column.filterType == DataTableFilterItemType.Text) {
593
+ this.addFilterItem(column, {
594
+ PropertyName: column.id,
595
+ ContainsValue: pair[1],
596
+ FilterType: DataTableFilterItemType.Text,
597
+ });
598
+ } else if (column.filterType == DataTableFilterItemType.Dropdown) {
599
+ this.addFilterItem(column, {
600
+ PropertyName: column.id,
601
+ ValueArr: [pair[1]],
602
+ ValueArrStrategy: MultiSelectExclusivity.Exclusive,
603
+ FilterType: DataTableFilterItemType.Dropdown,
604
+ });
605
+ }
606
+ }
607
+ });
608
+ }
609
+ }
610
+
611
+ if (!isNullOrEmpty(orderBy)) {
612
+ const arrOfArr = getParamArr(orderBy);
613
+
614
+ if (!isNullOrEmpty(arrOfArr)) {
615
+ arrOfArr.forEach((pair) => {
616
+ const column = getColumn(pair[0]);
617
+ if (column != null) {
618
+ this.sortDefinition = {
619
+ columnId: column.id,
620
+ direction: pair[1] == 'desc' ? DataTableSortDirection.Descending : DataTableSortDirection.Ascending,
621
+ };
622
+ }
623
+ });
624
+ }
625
+ }
626
+ }
627
+
628
+ async ensureMassPaginationConsent(): Promise<DialogResult> {
629
+ const selectedCount = this.getSelectedRows().length;
630
+ const paginationLength = this.getPaginationLength();
631
+ if (paginationLength < 0) {
632
+ return DialogResult.Confirm;
633
+ }
634
+
635
+ if (this.totalCount < paginationLength) {
636
+ return DialogResult.Confirm;
637
+ }
638
+
639
+ if (selectedCount < paginationLength - 7) {
640
+ return DialogResult.Confirm;
641
+ }
642
+
643
+ const continueLabel = `${PowerduckState.getResourceValue('continue')}&nbsp;&nbsp;<i class="icon icon-arrow-right-circle"></i>`;
644
+ const messageHtml = PowerduckState.getResourceValue('dtMassOperationWarningText').replace('{0}', selectedCount.toString()).replace('{1}', this.totalCount.toString());
645
+ const dialogResult = await DialogUtils.showConfirmDialog(
646
+ PowerduckState.getResourceValue('warning'),
647
+ messageHtml,
648
+ continueLabel,
649
+ PowerduckState.getResourceValue('cancel'),
650
+ DialogIcons.Warning,
651
+ );
652
+ return dialogResult;
653
+ }
654
+
655
+ performColumnRefresh(): void {
656
+ const savedState = StorageHelper.getStoredState(this.id);
657
+ this.colSortOrder = savedState.sortOrder;
658
+ this.handleColumnsVisibility(savedState, this.columns);
659
+ this.paginationLength = savedState.paginationLength;
660
+
661
+ if (savedState.skin != null) {
662
+ this.currentSkin = savedState.skin;
663
+ }
664
+
665
+ if (savedState.mobileBehavior != null) {
666
+ this.currentMobileBehavior = savedState.mobileBehavior;
667
+ }
668
+
669
+ if (savedState.orderBy != null) {
670
+ this.sortDefinition = savedState.orderBy;
671
+ }
672
+
673
+ if (savedState.filter != null) {
674
+ this.filterArr = savedState.filter;
675
+ }
676
+ }
677
+
678
+ initRowSortable(): void {
679
+ const args = {
680
+ animation: 150,
681
+ handle: '.dt-col-index',
682
+ onEnd: (evt) => {
683
+ this.sortComplete(evt);
684
+ },
685
+ } as any;
686
+
687
+ this.$nextTick(() => {
688
+ this.$nextTick(() => {
689
+ new Sortable(this.$el.querySelector('tbody'), args);
690
+ });
691
+ });
692
+ }
693
+
694
+ reorderColumns(sortOrder: string[], columns: TableColumn[]): void {
695
+ if (sortOrder != null && sortOrder.length >= columns.length) {
696
+ const sorted = [];
697
+ let allFound = true;
698
+
699
+ if (sortOrder.length == columns.length) {
700
+ sortOrder.forEach((propName) => {
701
+ const ci = columns.filter(p => p.id == propName)[0];
702
+ if (ci != null) {
703
+ sorted.push(ci);
704
+ } else {
705
+ allFound = false;
706
+ }
707
+ });
708
+ }
709
+
710
+ if (!allFound) {
711
+ StorageHelper.storeSortOrder(this.id, null);
712
+ sortOrder = null;
713
+ } else {
714
+ columns.splice(0, columns.length);
715
+ sorted.forEach((sortedCol) => {
716
+ columns.push(sortedCol);
717
+ });
718
+ }
719
+ }
720
+ }
721
+
722
+ initRowFilters(): void {
723
+ const savedState = StorageHelper.getStoredState(this.id);
724
+
725
+ if (savedState.filter == null) {
726
+ return;
727
+ }
728
+
729
+ for (const filterItem of savedState.filter) {
730
+ if (filterItem.FilterType == DataTableFilterItemType.None) {
731
+ continue;
732
+ } else if (filterItem.FilterType == DataTableFilterItemType.Dropdown) {
733
+ this.currentAdvancedFilterState[filterItem.PropertyName] = filterItem.ValueArr;
734
+ } else if (filterItem.FilterType == DataTableFilterItemType.DateRange) {
735
+ this.currentAdvancedFilterState[filterItem.PropertyName] = {
736
+ startTime: filterItem.DateFrom,
737
+ endTime: filterItem.DateTo,
738
+ };
739
+ } else if (filterItem.FilterType == DataTableFilterItemType.NumericRange) {
740
+
741
+ } else if (filterItem.FilterType == DataTableFilterItemType.Text) {
742
+ this.currentAdvancedFilterState[filterItem.PropertyName] = filterItem.ContainsValue;
743
+ }
744
+ }
745
+ }
746
+
747
+ handleWindowResized(): void {
748
+ const width = window.innerWidth;
749
+ const breakpointMode = width > 767 ? DataTableBreakpoint.Desktop : DataTableBreakpoint.Mobile;
750
+
751
+ if (breakpointMode != this.activeBreakPoint) {
752
+ this.activeBreakPoint = breakpointMode;
753
+ this.handleMobileBreakpointChanged();
754
+ }
755
+ }
756
+
757
+ handleMobileBreakpointChanged() {
758
+ if (this.fullSizeTable && PortalUtils.treatAsMobileDevice()) {
759
+ this.removeFullsizeModeLayoutCssClass();
760
+ $('html').addClass(`dt-fullsize-beh-${this.getMobileBehavior()}`);
761
+ $('html').addClass(`dt-fullsize-skin-${this.getSkin()}`);
762
+ }
763
+ }
764
+
765
+ removeFullsizeModeLayoutCssClass() {
766
+ if (this.fullSizeTable && PortalUtils.treatAsMobileDevice()) {
767
+ $('html')
768
+ .removeClass(`dt-fullsize-beh-${DataTableMobileBehavior.Compact}`)
769
+ .removeClass(`dt-fullsize-beh-${DataTableMobileBehavior.MobileLayout}`)
770
+ .removeClass(`dt-fullsize-beh-${DataTableMobileBehavior.VerticalTransform}`)
771
+ .removeClass(`dt-fullsize-skin-${DataTableSkin.Default}`)
772
+ .removeClass(`dt-fullsize-skin-${DataTableSkin.Compact}`);
773
+ }
774
+ }
775
+
776
+ handleColumnsVisibility(savedState: StoredState, columns: TableColumn[]): void {
777
+ if (savedState.hiddenColumns != null) {
778
+ savedState.hiddenColumns.forEach((hc) => {
779
+ const colItem = columns.filter(p => p.id == hc)[0];
780
+ if (colItem != null) {
781
+ colItem.visible = false;
782
+
783
+ if ((colItem as any)._enforceVisible != null) {
784
+ delete (colItem as any)._enforceVisible;
785
+ }
786
+ }
787
+ });
788
+ }
789
+
790
+ if (savedState.visibleColumns != null) {
791
+ savedState.visibleColumns.forEach((vc) => {
792
+ const colItem = columns.filter(p => p.id == vc)[0];
793
+ if (colItem != null) {
794
+ colItem.visible = true;
795
+ (colItem as any)._enforceVisible = true;
796
+ }
797
+ });
798
+ }
799
+ }
800
+
801
+ getPaginationLength(): number {
802
+ return this.paginationLength || 50;
803
+ }
804
+
805
+ getTableColumnHeaderCssClass(column: TableColumn, index: number): string {
806
+ return `dt-header-${column.id.split(':').join('_').toLowerCase()} dt-header-i${index} ${column.cssClass || ''}${column.sortable == false ? ' dt-header-notsortable' : ''}`;
807
+ }
808
+
809
+ getTableColumnHeaderFilterCssClass(column: TableColumn, index: number): string {
810
+ return `header-filter-cell dt-filter-${column.id.split(':').join('_').toLowerCase()} dt-filter-i${index} dt-filtertype-${this.getFilterTypeName(column.filterType)}`;
811
+ }
812
+
813
+ getTableItemCssClass(column: TableColumn, index: number): string {
814
+ return `dt-col-${column.id.split(':').join('_').toLowerCase()} dt-col-i${index} ${column.cssClass || ''}`;
815
+ }
816
+
817
+ getFilterTypeName(filterType: DataTableFilterItemType): string {
818
+ switch (filterType) {
819
+ case DataTableFilterItemType.None:
820
+ return 'none';
821
+
822
+ case null:
823
+ case undefined:
824
+ case DataTableFilterItemType.Text:
825
+ return 'text';
826
+
827
+ case DataTableFilterItemType.Dropdown:
828
+ return 'dropdown';
829
+
830
+ case DataTableFilterItemType.DateRange:
831
+ return 'daterange';
832
+
833
+ case DataTableFilterItemType.NumericRange:
834
+ return 'numericrange';
835
+
836
+ default:
837
+ }
838
+ }
839
+
840
+ getRowIdProp(row: any): string {
841
+ if (row?.Id != null) {
842
+ return 'Id';
843
+ }
844
+
845
+ return 'id';
846
+ }
847
+
848
+ getRowId(row: any): number {
849
+ return row[this.getRowIdProp(row)];
850
+ }
851
+
852
+ getSelectedRows(): any[] {
853
+ const self = this;
854
+ const selectedRows = [];
855
+
856
+ if (isNullOrEmpty(self.rows)) {
857
+ return [];
858
+ }
859
+
860
+ const rowIdProp = this.getRowIdProp(self.rows[0]);
861
+
862
+ $('.dt-selection-checkbox input:checked').each(function (this: any) {
863
+ const rowId = Number($(this).closest('.dt-selection-checkbox').attr('data-id'));
864
+ const existingRow = selectedRows.filter(p => p[rowIdProp] == rowId)[0];
865
+
866
+ if (existingRow == null) {
867
+ const selectedRow = self.rows.filter(p => p[rowIdProp] == rowId)[0];
868
+ if (selectedRow != null) {
869
+ selectedRows.push(selectedRow);
870
+ }
871
+ }
872
+ });
873
+
874
+ return selectedRows;
875
+ }
876
+
877
+ unmarkSelection(cb: () => void): void {
878
+ if (DataTableConfig.filterMarking) {
879
+ this.markInstance.unmark({
880
+ done: () => {
881
+ this.enforceBodyRedraw = true;
882
+ this.$nextTick(() => {
883
+ this.enforceBodyRedraw = false;
884
+ this.$nextTick(() => {
885
+ cb();
886
+ });
887
+ });
888
+ },
889
+ });
890
+ } else {
891
+ cb();
892
+ }
893
+ }
894
+
895
+ markSelection(): void {
896
+ const mySelf = this;
897
+ const escapeRegExp = function (string) {
898
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
899
+ };
900
+
901
+ const getValueArr = function (filterItem: DataTablePostBackFilterItem): string[] {
902
+ if (!isNullOrEmpty(filterItem.EqualsValue)) {
903
+ return [filterItem.EqualsValue];
904
+ } else if (!isNullOrEmpty(filterItem.ContainsValue)) {
905
+ return [filterItem.ContainsValue];
906
+ } else if (!isNullOrEmpty(filterItem.ValueArr)) {
907
+ return [];
908
+ // return filterItem.ValueArr;
909
+ }
910
+ };
911
+
912
+ let regexBuilder = '';
913
+ const markArr = [];
914
+ if (this.filterArr != null) {
915
+ this.filterArr.forEach((filterItem) => {
916
+ if (regexBuilder.length > 0) {
917
+ regexBuilder += '|';
918
+ }
919
+
920
+ const columnId = filterItem.PropertyName?.toLowerCase();
921
+ const tds = Array.from($(mySelf.$el).find(`td.dt-col-${columnId}`));
922
+ if (tds == null || tds.length == 0) {
923
+ return;
924
+ }
925
+
926
+ (getValueArr(filterItem) || []).forEach((filterValue) => {
927
+ markArr.push({
928
+ value: escapeRegExp(filterValue),
929
+ elements: tds,
930
+ });
931
+ });
932
+ });
933
+ }
934
+
935
+ if (!isNullOrEmpty(this.fullTextQuery)) {
936
+ const value = escapeRegExp(this.fullTextQuery);
937
+ const tds = Array.from($(mySelf.$el).find(`td`));
938
+ regexBuilder += value;
939
+
940
+ markArr.push({
941
+ value,
942
+ elements: tds,
943
+ });
944
+ }
945
+
946
+ if (DataTableConfig.filterMarking) {
947
+ this.unmarkSelection(() => {
948
+ for (const item of markArr) {
949
+ this.markInstance.mark(item.value, {
950
+ filter: (node) => {
951
+ const parentTd = $(node).closest('td')[0];
952
+ if (!parentTd) {
953
+ return false;
954
+ }
955
+
956
+ const matchesColumn = item.elements?.some(el => parentTd?.isEqualNode(el));
957
+ const matchesText = parentTd?.textContent?.toLowerCase().includes(item.value.toLowerCase());
958
+ return matchesColumn && matchesText;
959
+ },
960
+ });
961
+ }
962
+ });
963
+ }
964
+ }
965
+
966
+ addFilterItem(dtColumn: TableColumn, newFilter: DataTablePostBackFilterItem): void {
967
+ const existingItem = this.filterArr.filter(p => p.PropertyName == dtColumn.id)[0];
968
+ const hasValue
969
+ = !isNullOrEmpty(newFilter.ContainsValue)
970
+ || !isNullOrEmpty(newFilter.EqualsValue)
971
+ || !isNullOrEmpty(newFilter.ValueArr)
972
+ || newFilter.DateFrom != null
973
+ || newFilter.DateTo != null
974
+ || newFilter.NumFrom != null
975
+ || newFilter.NumTo != null;
976
+
977
+ if (existingItem == null && hasValue) {
978
+ this.filterArr.push(newFilter);
979
+ return;
980
+ }
981
+
982
+ this.filterArr.splice(this.filterArr.indexOf(existingItem), 1);
983
+ if (existingItem != null && hasValue) {
984
+ this.filterArr.push(newFilter);
985
+ }
986
+ }
987
+
988
+ filterDataHaveChanged(dtColumn: TableColumn, filterItem: DataTablePostBackFilterItem): boolean {
989
+ const currentData: DataTablePostBackFilterItem = this.filterArr.filter(p => p.PropertyName == dtColumn.id)[0] || ({} as any);
990
+ return JSON.stringify(currentData) != JSON.stringify(filterItem);
991
+ }
992
+
993
+ handleClientsideFilter(markResults?: boolean): boolean {
994
+ if (this.filterMode == DataTableFilterMode.Clientside) {
995
+ this.unmarkSelection(() => {
996
+ this.performClientsideFilter();
997
+
998
+ if (markResults) {
999
+ this.markSelection();
1000
+ }
1001
+ });
1002
+
1003
+ return true;
1004
+ }
1005
+
1006
+ return false;
1007
+ }
1008
+
1009
+ performFullTextSearch(e): void {
1010
+ if (this.tableFilterTimeout != null) {
1011
+ clearTimeout(this.tableFilterTimeout);
1012
+ }
1013
+
1014
+ this.fullTextQuery = e.target.value;
1015
+
1016
+ e = e || window.event;
1017
+ let charCode: number = -1;
1018
+ if (e.which) {
1019
+ charCode = e.which;
1020
+ } else if (e.keyCode) {
1021
+ charCode = e.keyCode;
1022
+ }
1023
+
1024
+ if (charCode == 13) {
1025
+ if (this.handleClientsideFilter(true)) {
1026
+ return;
1027
+ }
1028
+
1029
+ this.reloadData();
1030
+ } else {
1031
+ this.tableFilterTimeout = setTimeout(() => {
1032
+ if (this.handleClientsideFilter(true)) {
1033
+ return;
1034
+ }
1035
+
1036
+ this.reloadData();
1037
+ }, 750);
1038
+ }
1039
+ }
1040
+
1041
+ performInputFilter(dtColumn: TableColumn, e): void {
1042
+ if (this.tableFilterTimeout != null) {
1043
+ clearTimeout(this.tableFilterTimeout);
1044
+ }
1045
+
1046
+ this.currentAdvancedFilterState[dtColumn.id] = e;
1047
+
1048
+ const filterItem = {
1049
+ PropertyName: dtColumn.id,
1050
+ ContainsValue: (e || ''),
1051
+ FilterType: DataTableFilterItemType.Text,
1052
+ };
1053
+
1054
+ this.addFilterItem(dtColumn, filterItem);
1055
+
1056
+ if (this.preserveFilter == true) {
1057
+ if (isNullOrEmpty(filterItem.ContainsValue)) {
1058
+ StorageHelper.storeFilter(this.id, null);
1059
+ } else {
1060
+ StorageHelper.storeFilter(this.id, filterItem);
1061
+ }
1062
+ }
1063
+
1064
+ if (this.handleClientsideFilter(true)) {
1065
+ return;
1066
+ }
1067
+
1068
+ e = (e) || window.event;
1069
+ let charCode: number = -1;
1070
+ if (e.which) {
1071
+ charCode = e.which;
1072
+ } else if (e.keyCode) {
1073
+ charCode = e.keyCode;
1074
+ }
1075
+
1076
+ if (charCode == 13) {
1077
+ this.reloadData();
1078
+ } else {
1079
+ this.tableFilterTimeout = setTimeout(() => {
1080
+ this.reloadData();
1081
+ }, 750);
1082
+ }
1083
+ }
1084
+
1085
+ performSelectionFilter(
1086
+ dtColumn: TableColumn,
1087
+ data: DataTableFilterItem[],
1088
+ exclusivity: MultiSelectExclusivity,
1089
+ ): void {
1090
+ this.currentAdvancedFilterState[dtColumn.id] = data;
1091
+
1092
+ const filterValue: DataTablePostBackFilterItem = {
1093
+ PropertyName: dtColumn.id,
1094
+ ValueArr: (data || []).map(p => p.id),
1095
+ ValueArrStrategy: exclusivity == MultiSelectExclusivity.Exclusive ? MultiSelectExclusivity.Exclusive : MultiSelectExclusivity.Inclusive,
1096
+ FilterType: DataTableFilterItemType.Dropdown,
1097
+ };
1098
+
1099
+ if (!this.filterDataHaveChanged(dtColumn, filterValue)) {
1100
+ return;
1101
+ }
1102
+
1103
+ if (data == null || data.length == 0) {
1104
+ this.addFilterItem(dtColumn, {} as any);
1105
+ } else {
1106
+ this.addFilterItem(dtColumn, filterValue);
1107
+ }
1108
+
1109
+ if (this.preserveFilter == true) {
1110
+ if (data == null || data.length == 0) {
1111
+ StorageHelper.storeFilter(this.id, null);
1112
+ } else {
1113
+ StorageHelper.storeFilter(this.id, filterValue);
1114
+ }
1115
+ }
1116
+
1117
+ if (this.handleClientsideFilter(false)) {
1118
+ return;
1119
+ }
1120
+
1121
+ // Immediate reload if changed, delay handled by the Dropdown component
1122
+ this.reloadData();
1123
+ }
1124
+
1125
+ performDateRangeFilter(dtColumn: TableColumn, data: DaterangeChangedArgs): void {
1126
+ this.currentAdvancedFilterState[dtColumn.id] = data;
1127
+
1128
+ let startDate = data?.startTime;
1129
+ let endDate = data?.endTime;
1130
+ if (data == null || data.startTime == null || data.endTime == null) {
1131
+ this.addFilterItem(dtColumn, {} as any);
1132
+ }
1133
+
1134
+ if (data != null && this.timeFilterShiftTimezone) {
1135
+ let dstOffset = this.timezoneDstOffset;
1136
+ let gmtOffset = this.timezoneGmtOffset;
1137
+
1138
+ if (dstOffset == null && this.rows != null) {
1139
+ dstOffset = (this.rows.filter(p => p.TimezoneDstOffset != null && p.TimezoneDstOffset != 0)[0] || {}).TimezoneDstOffset;
1140
+ if (dstOffset == null) {
1141
+ dstOffset = 0;
1142
+ }
1143
+ }
1144
+
1145
+ if (gmtOffset == null && this.rows != null) {
1146
+ gmtOffset = (this.rows.filter(p => p.TimezoneGmtOffset != null && p.TimezoneGmtOffset != 0)[0] || {}).TimezoneGmtOffset;
1147
+ if (gmtOffset == null) {
1148
+ gmtOffset = 0;
1149
+ }
1150
+ }
1151
+
1152
+ startDate = TimezoneHelper.getUTCFromLocalDate(
1153
+ startDate,
1154
+ dstOffset,
1155
+ gmtOffset,
1156
+ );
1157
+ endDate = TimezoneHelper.getUTCFromLocalDate(
1158
+ endDate,
1159
+ dstOffset,
1160
+ gmtOffset,
1161
+ );
1162
+ }
1163
+
1164
+ const filterValue: DataTablePostBackFilterItem = {
1165
+ PropertyName: dtColumn.id,
1166
+ DateFrom: startDate,
1167
+ DateTo: endDate,
1168
+ FilterType: DataTableFilterItemType.DateRange,
1169
+ };
1170
+
1171
+ if (!this.filterDataHaveChanged(dtColumn, filterValue)) {
1172
+ return;
1173
+ }
1174
+
1175
+ if (data == null || data.startTime == null || data.endTime == null) {
1176
+ this.addFilterItem(dtColumn, {} as any);
1177
+ } else {
1178
+ this.addFilterItem(dtColumn, filterValue);
1179
+ }
1180
+
1181
+ if (this.preserveFilter == true) {
1182
+ if (data == null || data.startTime == null || data.endTime == null) {
1183
+ StorageHelper.storeFilter(this.id, null);
1184
+ } else {
1185
+ StorageHelper.storeFilter(this.id, filterValue);
1186
+ }
1187
+ }
1188
+
1189
+ if (this.handleClientsideFilter(false)) {
1190
+ return;
1191
+ }
1192
+
1193
+ // Immediate reload if changed, delay handled by the Dropdown component
1194
+ this.reloadData();
1195
+ }
1196
+
1197
+ performClientsideFilter(): void {
1198
+ this.rows = this.getClientsideFilteredAndSortedRows(this.loadedRows);
1199
+ }
1200
+
1201
+ getClientsideFilteredAndSortedRows(rowArr: any[]): any[] {
1202
+ let newRowArr = [...rowArr];
1203
+ for (const filterData of this.filterArr) {
1204
+ const column = this.columns.find(p => p.id == filterData.PropertyName);
1205
+ const filterDef = column?.clientsideFilter;
1206
+
1207
+ if (filterDef != null) {
1208
+ if (!isNullOrEmpty(filterData.ContainsValue)) {
1209
+ filterData.ContainsValue = this.normalizeStringForSearch(filterData.ContainsValue);
1210
+ }
1211
+
1212
+ newRowArr = newRowArr.filter((p) => {
1213
+ return filterDef(p, filterData);
1214
+ });
1215
+
1216
+ continue;
1217
+ }
1218
+
1219
+ if (filterData.FilterType == DataTableFilterItemType.Text && !isNullOrEmpty(filterData.ContainsValue)) {
1220
+ const containsVal = this.normalizeStringForSearch(filterData.ContainsValue);
1221
+ newRowArr = newRowArr.filter((p) => {
1222
+ let val: any;
1223
+ if (column?.customFilterValue != null) {
1224
+ val = column.customFilterValue(p);
1225
+ } else if (column?.customValue != null) {
1226
+ val = column.customValue(p);
1227
+ } else {
1228
+ val = p[filterData.PropertyName];
1229
+ }
1230
+
1231
+ if (val == null) {
1232
+ return false;
1233
+ }
1234
+
1235
+ if (typeof val === 'string' || val instanceof String) {
1236
+ return this.normalizeStringForSearch(val as any).includes(containsVal);
1237
+ }
1238
+
1239
+ return this.normalizeStringForSearch((p[filterData.PropertyName] || '').toString()).includes(containsVal);
1240
+ });
1241
+ } else if (filterData.FilterType == DataTableFilterItemType.Dropdown && !isNullOrEmpty(filterData.ValueArr)) {
1242
+ newRowArr = newRowArr.filter((p) => {
1243
+ let propVal: any;
1244
+ if (column?.customFilterValue != null) {
1245
+ propVal = column.customFilterValue(p);
1246
+ } else if (column?.customValue != null) {
1247
+ propVal = column.customValue(p);
1248
+ } else {
1249
+ propVal = p[filterData.PropertyName];
1250
+ }
1251
+
1252
+ if (propVal == null) {
1253
+ return false;
1254
+ }
1255
+
1256
+ if (filterData.ValueArr.length == 1) {
1257
+ return propVal == filterData.ValueArr[0];
1258
+ } else if (filterData.ValueArrStrategy == MultiSelectExclusivity.Inclusive) {
1259
+ return filterData.ValueArr.includes(propVal);
1260
+ }
1261
+
1262
+ return true;
1263
+ });
1264
+ } else if (filterData.FilterType == DataTableFilterItemType.DateRange) {
1265
+ const fromMs = filterData.DateFrom?.toZonedDateTime('UTC')?.epochMilliseconds;
1266
+ const toMs = filterData.DateTo?.toZonedDateTime('UTC')?.epochMilliseconds;
1267
+
1268
+ newRowArr = newRowArr.filter((p) => {
1269
+ let propVal: any;
1270
+ if (column?.customFilterValue != null) {
1271
+ propVal = column.customFilterValue(p);
1272
+ } else if (column?.customValue != null) {
1273
+ propVal = column.customValue(p);
1274
+ } else {
1275
+ propVal = p[filterData.PropertyName];
1276
+ }
1277
+
1278
+ if (propVal == null) {
1279
+ return false;
1280
+ }
1281
+
1282
+ try {
1283
+ if (typeof propVal == 'string') {
1284
+ propVal = TemporalUtils.fromString(propVal);
1285
+ }
1286
+
1287
+ const timeMs = (propVal as Temporal.PlainDateTime)?.toZonedDateTime('UTC')?.epochMilliseconds;
1288
+ return fromMs <= timeMs && toMs >= timeMs;
1289
+ } catch (error) {
1290
+ return false;
1291
+ }
1292
+ });
1293
+ } else if (filterData.FilterType == DataTableFilterItemType.NumericRange) {
1294
+ newRowArr = newRowArr.filter((p) => {
1295
+ let propVal: any;
1296
+ if (column?.customFilterValue != null) {
1297
+ propVal = column.customFilterValue(p);
1298
+ } else if (column?.customValue != null) {
1299
+ propVal = column.customValue(p);
1300
+ } else {
1301
+ propVal = p[filterData.PropertyName];
1302
+ }
1303
+
1304
+ if (propVal == null) {
1305
+ return false;
1306
+ }
1307
+
1308
+ return filterData.NumFrom <= propVal && filterData.NumTo >= propVal;
1309
+ });
1310
+ }
1311
+ }
1312
+
1313
+ if (!isNullOrEmpty(this.fullTextQuery)) {
1314
+ const fulltextArr: any[] = [];
1315
+ const normalizedQuery = this.normalizeStringForSearch(this.fullTextQuery);
1316
+
1317
+ for (const row of newRowArr) {
1318
+ for (const propName in row) {
1319
+ const column = this.columns.find(p => p.id == propName);
1320
+ let propVal: any;
1321
+
1322
+ if (column?.customFilterValue != null) {
1323
+ propVal = column.customFilterValue(row);
1324
+ } else if (column?.customValue != null) {
1325
+ propVal = column.customValue(row);
1326
+ } else {
1327
+ propVal = row[propName];
1328
+ }
1329
+
1330
+ if (propVal != null) {
1331
+ if (this.normalizeStringForSearch(propVal.toString()).includes(normalizedQuery)) {
1332
+ fulltextArr.push(row);
1333
+ break;
1334
+ }
1335
+ }
1336
+ }
1337
+ }
1338
+
1339
+ newRowArr = fulltextArr;
1340
+ }
1341
+
1342
+ if (this.sortDefinition != null) {
1343
+ const colId = this.sortDefinition.columnId;
1344
+ type SORT_TYPE_OPTS = 'string' | 'date' | 'unknown';
1345
+ let sortType: SORT_TYPE_OPTS = 'unknown';
1346
+
1347
+ for (const row of newRowArr) {
1348
+ const item = row[colId];
1349
+ if (item == null) {
1350
+ continue;
1351
+ }
1352
+
1353
+ if (typeof item === 'string' || item instanceof String) {
1354
+ sortType = 'string';
1355
+ } else if (item.getTime != null && item.getSeconds != null) {
1356
+ sortType = 'date';
1357
+ } else {
1358
+ sortType = 'unknown';
1359
+ }
1360
+
1361
+ break;
1362
+ }
1363
+
1364
+ if (sortType == 'string') {
1365
+ const collator = new Intl.Collator(PowerduckState.getCurrentLanguage(), {
1366
+ numeric: true,
1367
+ sensitivity: 'base',
1368
+ });
1369
+ newRowArr = newRowArr.sort((a, b) => collator.compare(a[colId], b[colId]));
1370
+ } else if (sortType == 'date') {
1371
+ newRowArr = newRowArr.sort((a, b) => {
1372
+ return (b[colId]?.getTime() || 0) - (a[colId]?.getTime() || 0);
1373
+ });
1374
+ } else {
1375
+ try {
1376
+ newRowArr = newRowArr[sortBy](this.sortDefinition.columnId);
1377
+ } catch (error) { }
1378
+ }
1379
+
1380
+ if (this.sortDefinition.direction == DataTableSortDirection.Descending) {
1381
+ newRowArr = newRowArr.reverse();
1382
+ }
1383
+ }
1384
+
1385
+ return newRowArr;
1386
+ }
1387
+
1388
+ normalizeStringForSearch(str: string): string {
1389
+ return str.toLowerCase()[latinize]().trim();
1390
+ }
1391
+
1392
+ reloadData(): void {
1393
+ this.reloadDataPromise().then((data) => {
1394
+ this.handleClientsideFilter(false);
1395
+ }).catch((err) => {
1396
+
1397
+ });
1398
+ }
1399
+
1400
+ reloadDataPromise(paginationPosition?: number, paginationLength?: number): Promise<any> {
1401
+ const mySelf = this;
1402
+ this.isLoading = true;
1403
+
1404
+ return new Promise((resolve, reject) => {
1405
+ let loadPromise: Promise<any>;
1406
+ if (mySelf.customAjaxCall == null) {
1407
+ loadPromise = mySelf.apiClient[mySelf.apiMethod](mySelf.getAjaxArgs(paginationPosition, paginationLength));
1408
+ } else {
1409
+ loadPromise = mySelf.customAjaxCall(mySelf.getAjaxArgs(paginationPosition, paginationLength));
1410
+ }
1411
+
1412
+ loadPromise.then((data: any) => {
1413
+ mySelf.unmarkSelection(() => {
1414
+ mySelf.enforceBodyRedraw = true;
1415
+ mySelf.$nextTick(() => {
1416
+ mySelf.enforceBodyRedraw = false;
1417
+ mySelf.isLoading = false;
1418
+
1419
+ if (mySelf.parseLoadedRowset != null) {
1420
+ const rowset = mySelf.parseLoadedRowset(data);
1421
+ mySelf.totalCount = rowset.totalCount;
1422
+ mySelf.totalFilteredCount = rowset.totalFilteredCount;
1423
+ mySelf.rows = rowset.rows;
1424
+ } else {
1425
+ mySelf.totalCount = data.totalCount ?? data.TotalCount;
1426
+ mySelf.totalFilteredCount = data.totalFilteredCount ?? data.TotalFilteredCount;
1427
+ mySelf.rows = data.rows ?? data.Rows ?? data.data;
1428
+ }
1429
+
1430
+ mySelf.loadedRows = mySelf.rows;
1431
+ mySelf.$forceUpdate();
1432
+ mySelf.$nextTick(() => mySelf.markSelection());
1433
+ resolve(data);
1434
+ });
1435
+ });
1436
+ })
1437
+ .catch((err) => {
1438
+ mySelf.isLoading = false;
1439
+ NotificationProvider.showErrorMessage(PowerduckState.getResourceValue('errorFetchingData'));
1440
+ reject(err);
1441
+ });
1442
+ });
1443
+ }
1444
+
1445
+ getAjaxArgs(paginationPosition?: number, paginationLength?: number): DataTablePostBackData {
1446
+ if (this.sessionId == null) {
1447
+ this.sessionId = Math.floor(Math.random() * 2147483647) + 2147483647 * -1;
1448
+ }
1449
+
1450
+ const dataArgs = {} as any as DataTablePostBackData;
1451
+ if (this.apiArgs != null) {
1452
+ for (const key in this.apiArgs) {
1453
+ const kv = this.apiArgs[key];
1454
+ if (kv && {}.toString.call(kv) === '[object Function]') {
1455
+ dataArgs[key] = kv.call(this);
1456
+ } else {
1457
+ dataArgs[key] = kv;
1458
+ }
1459
+ }
1460
+ }
1461
+
1462
+ dataArgs.SessionId = this.sessionId;
1463
+ dataArgs.PaginationPosition = paginationPosition || this.paginationPosition;
1464
+ dataArgs.PaginationLength = paginationLength || this.getPaginationLength();
1465
+ dataArgs.Filter = {
1466
+ FullText: this.fullTextQuery,
1467
+ FilterItems: this.filterArr,
1468
+ };
1469
+
1470
+ if (this.sortDefinition != null) {
1471
+ dataArgs.Sort = {
1472
+ PropertyName: this.sortDefinition.columnId,
1473
+ Direction: this.sortDefinition.direction,
1474
+ };
1475
+ }
1476
+
1477
+ if (dataArgs.PaginationLength == -1) {
1478
+ dataArgs.PaginationPosition = 1;
1479
+ }
1480
+
1481
+ return dataArgs;
1482
+ }
1483
+
1484
+ isMobileModeRenderType(): boolean {
1485
+ return this.activeBreakPoint == 'mobile' && this.getMobileBehavior() == DataTableMobileBehavior.MobileLayout;
1486
+ }
1487
+
1488
+ forceHeaderRedraw(): void {
1489
+ this.enforceHeaderRedraw = true;
1490
+ this.$nextTick(() => (this.enforceHeaderRedraw = false));
1491
+ }
1492
+
1493
+ forceBodyRedraw(): void {
1494
+ this.enforceBodyRedraw = true;
1495
+ this.$nextTick(() => (this.enforceBodyRedraw = false));
1496
+ }
1497
+
1498
+ updateRows(rowArr: any[]): void {
1499
+ this.rows = rowArr;
1500
+ this.loadedRows = rowArr;
1501
+ this.forceBodyRedraw();
1502
+ }
1503
+
1504
+ getTotalCount(): number {
1505
+ return this.totalCount;
1506
+ }
1507
+
1508
+ setSkin(skin: DataTableSkin): void {
1509
+ StorageHelper.storeSkin(this.id, skin);
1510
+ this.currentSkin = skin;
1511
+ this.handleMobileBreakpointChanged();
1512
+ }
1513
+
1514
+ setMobileBehavior(mobileBehavior: DataTableMobileBehavior): void {
1515
+ StorageHelper.storeMobileBehavior(this.id, mobileBehavior);
1516
+ this.currentMobileBehavior = mobileBehavior;
1517
+ this.handleMobileBreakpointChanged();
1518
+ }
1519
+
1520
+ handleColumnsReordered(sortOrder: string[]): void {
1521
+ sortOrder = sortOrder.filter(p => p != '_sysIndexCol');
1522
+ StorageHelper.storeSortOrder(this.id, sortOrder);
1523
+ this.colSortOrder = sortOrder;
1524
+ this.reorderColumns(sortOrder, this.getVisibleColumns());
1525
+ this.forceHeaderRedraw();
1526
+ }
1527
+
1528
+ async handleColumnHeaderClicked(dtColumn: TableColumn) {
1529
+ if (dtColumn.sortable == false) {
1530
+ return;
1531
+ }
1532
+
1533
+ const oldDef = this.sortDefinition;
1534
+ let newDirection = DataTableSortDirection.Ascending;
1535
+ if (this.sortDefinition != null && this.sortDefinition.columnId == dtColumn.id && this.sortDefinition.direction == DataTableSortDirection.Ascending) {
1536
+ newDirection = DataTableSortDirection.Descending;
1537
+ }
1538
+
1539
+ this.sortDefinition = {
1540
+ columnId: dtColumn.id,
1541
+ direction: newDirection,
1542
+ };
1543
+
1544
+ if (this.preserveOrderBy == true) {
1545
+ StorageHelper.storeOrderBy(this.id, this.sortDefinition);
1546
+ }
1547
+
1548
+ if (this.handleClientsideFilter(false)) {
1549
+ return;
1550
+ }
1551
+
1552
+ try {
1553
+ await this.reloadDataPromise();
1554
+ } catch (e) {
1555
+ this.sortDefinition = oldDef;
1556
+ }
1557
+ }
1558
+
1559
+ handleColumnVisibilityChanged(columns: TableColumn[]): void {
1560
+ StorageHelper.storeColVis(this.id, columns);
1561
+ this.forceHeaderRedraw();
1562
+ }
1563
+
1564
+ handleColumnModalFilterChanged(e: ColFilterModalShowResponse): void {
1565
+ if (e.changed) {
1566
+ this.filterArr = e.filterArr;
1567
+ this.reloadData();
1568
+ }
1569
+ }
1570
+
1571
+ handleMobileRowClicked(e: any, row: any) {
1572
+ if (this.checkboxesShown) {
1573
+ let target = $(e.target);
1574
+ if (!target.hasClass('dt-mobile-row-inner')) {
1575
+ target = target.closest('.dt-mobile-row-inner');
1576
+ }
1577
+
1578
+ const input = target.find('.dt-selection-checkbox input')[0] as HTMLInputElement;
1579
+ input.checked = !input.checked;
1580
+ }
1581
+
1582
+ if (this.rowClicked) {
1583
+ this.rowClicked(row);
1584
+ }
1585
+ }
1586
+
1587
+ handleRowCheckboxChanged(row: any, checked: boolean) {
1588
+ if (this.rowCheckstateChanged != null) {
1589
+ this.rowCheckstateChanged(
1590
+ row,
1591
+ checked,
1592
+ this.getSelectedRows(),
1593
+ );
1594
+ }
1595
+ }
1596
+
1597
+ getLastPaginationIndex(): number {
1598
+ let retVal = this.totalFilteredCount / this.getPaginationLength();
1599
+ if (retVal % this.getPaginationLength() != 0) {
1600
+ retVal = Math.floor(retVal) + 1;
1601
+ }
1602
+
1603
+ if (retVal == 0) {
1604
+ retVal = 1;
1605
+ }
1606
+
1607
+ return retVal;
1608
+ }
1609
+
1610
+ async handlePaginationPositionChanged(newValue: number): Promise<any> {
1611
+ if (this.paginationPosition == newValue || newValue < 1 || newValue > this.getLastPaginationIndex()) {
1612
+ return;
1613
+ }
1614
+
1615
+ await this.reloadDataPromise(newValue);
1616
+ this.paginationPosition = newValue;
1617
+ }
1618
+
1619
+ async handlePaginationLengthChanged(newValue: number) {
1620
+ if (this.getPaginationLength() == newValue) {
1621
+ return;
1622
+ }
1623
+
1624
+ await this.reloadDataPromise(null, newValue);
1625
+ StorageHelper.storePaginationLength(this.id, newValue);
1626
+ this.paginationLength = newValue;
1627
+ }
1628
+
1629
+ handleCheckAllChanged(checked: boolean): void {
1630
+ $('.dt-col-indexcheckbox').each(function (this: HTMLElement) {
1631
+ $(this).find('input').prop('checked', checked);
1632
+ });
1633
+
1634
+ this.handleRowCheckboxChanged(null, null);
1635
+ }
1636
+
1637
+ getNameAndSurnameIndex(name: string, surname: string): string {
1638
+ let retVal: string;
1639
+ if ((name != null && name.length > 0) || (surname != null && surname.length > 0)) {
1640
+ name = name || '';
1641
+ surname = surname || '';
1642
+
1643
+ if (name.length > 0) {
1644
+ if (surname.length > 0) {
1645
+ retVal = name.substring(0, 1).toUpperCase() + surname.substring(0, 1).toUpperCase();
1646
+ } else {
1647
+ retVal = name;
1648
+ }
1649
+ } else {
1650
+ retVal = surname;
1651
+ }
1652
+ }
1653
+
1654
+ return retVal;
1655
+ }
1656
+
1657
+ getRowIdentifier(
1658
+ columns: TableColumn[],
1659
+ row: any,
1660
+ includeColumns: boolean,
1661
+ ): RowIdentifier {
1662
+ let namingData: RowIdentifier;
1663
+ if (row.CustomFields != null) {
1664
+ const nameCf = (row.CustomFields.filter(p => p.MappingType == 1)[0] || {}) as any;
1665
+ const surnameCf = (row.CustomFields.filter(p => p.MappingType == 2)[0] || {}) as any;
1666
+ namingData = new RowIdentifier(nameCf.Value, surnameCf.Value);
1667
+
1668
+ if (includeColumns && namingData.fullName.length > 1) {
1669
+ namingData.dtColumns = [];
1670
+
1671
+ const nameCol = columns.filter(p => p.id.includes(`cf:map:${1}`) || p.id.includes(`cf:id:${nameCf.Id}`))[0];
1672
+ if (nameCol != null) {
1673
+ namingData.dtColumns.push(nameCol);
1674
+ }
1675
+
1676
+ const surnameCol = columns.filter(p => p.id.includes(`cf:map:${2}`) || p.id.includes(`cf:id:${surnameCf.Id}`))[0];
1677
+ if (surnameCol != null) {
1678
+ namingData.dtColumns.push(surnameCol);
1679
+ }
1680
+ }
1681
+ }
1682
+
1683
+ if (namingData == null || (namingData.fullName.length < 2 && row.Name != null)) {
1684
+ namingData = new RowIdentifier(row.Name, row.Surname);
1685
+
1686
+ if (includeColumns) {
1687
+ namingData.dtColumns = [];
1688
+
1689
+ const nameCol = columns.filter(p => p.id == 'Name')[0];
1690
+ if (nameCol != null) {
1691
+ namingData.dtColumns.push(nameCol);
1692
+ }
1693
+
1694
+ const surnameCol = columns.filter(p => p.id == 'Surname')[0];
1695
+ if (surnameCol != null) {
1696
+ namingData;
1697
+ }
1698
+ }
1699
+ }
1700
+
1701
+ if (namingData == null || (namingData.fullName.length < 2 && row.Email != null)) {
1702
+ if (row.Email != null) {
1703
+ namingData = new RowIdentifier(row.Email, '');
1704
+
1705
+ if (includeColumns) {
1706
+ const emailCol = columns.filter(p => p.id == 'Email')[0];
1707
+ if (emailCol != null) {
1708
+ namingData.dtColumns = [emailCol];
1709
+ }
1710
+ }
1711
+ }
1712
+ }
1713
+
1714
+ if (namingData == null || (namingData.fullName.length < 2 && row.TicketName != null)) {
1715
+ if (row.TicketName != null) {
1716
+ namingData = new RowIdentifier(row.TicketName, '');
1717
+
1718
+ if (includeColumns) {
1719
+ const emailCol = columns.filter(p => p.id == 'TicketName')[0];
1720
+ if (emailCol != null) {
1721
+ namingData.dtColumns = [emailCol];
1722
+ }
1723
+ }
1724
+ }
1725
+ }
1726
+
1727
+ return namingData;
1728
+ }
1729
+
1730
+ getHeaderColumnIndex(
1731
+ columns: TableColumn[],
1732
+ row,
1733
+ i,
1734
+ ): string {
1735
+ if (this.rowIndexMode == RowIndexMode.Index) {
1736
+ return i + 1;
1737
+ } else {
1738
+ var indexText: string;
1739
+ const rowIdentifier = this.getRowIdentifier(
1740
+ columns,
1741
+ row,
1742
+ false,
1743
+ );
1744
+ if (rowIdentifier != null) {
1745
+ indexText = this.getNameAndSurnameIndex(rowIdentifier.name, rowIdentifier.surname);
1746
+ }
1747
+
1748
+ var indexText: string;
1749
+ if (row.CustomFields != null) {
1750
+ const nameCf = row.CustomFields.filter(p => p.MappingType == 1)[0];
1751
+ const surnameCf = row.CustomFields.filter(p => p.MappingType == 2)[0];
1752
+ indexText = this.getNameAndSurnameIndex(nameCf != null ? nameCf.Value : '', surnameCf != null ? surnameCf.Value : '');
1753
+ }
1754
+
1755
+ if (indexText != null && indexText.length > 1) {
1756
+ if (indexText.length > 2) {
1757
+ const splitArr = indexText.split(' ');
1758
+ if (splitArr.length > 1) {
1759
+ indexText = (splitArr[0].substring(0, 1) + splitArr[1].substring(0, 1)).toUpperCase();
1760
+ } else {
1761
+ indexText = indexText.substring(0, 2).toUpperCase();
1762
+ }
1763
+ }
1764
+ } else {
1765
+ indexText = (i + 1).toString();
1766
+ }
1767
+
1768
+ return indexText;
1769
+ }
1770
+ }
1771
+
1772
+ showColVis(): void {
1773
+ (this.$refs.colVisModal as typeof ColVisModal.prototype).show();
1774
+ }
1775
+
1776
+ showFilterModal(): void {
1777
+ (this.$refs.colFilterModal as typeof ColFilterModal.prototype).show({
1778
+ filterArr: this.filterArr,
1779
+ });
1780
+ }
1781
+
1782
+ exportExcel(): void {
1783
+ (this.$refs.tableExportModal as typeof TableExportModal.prototype).show({
1784
+ apiClient: this.apiClient,
1785
+ apiMethod: this.apiMethod,
1786
+ apiArgs: this.getAjaxArgs(),
1787
+ columns: this.columns,
1788
+ rows: this.rows,
1789
+ exportConfig: this.exportConfig,
1790
+ paginationOffset: this.paginationPosition - 1,
1791
+ paginationLength: this.getPaginationLength(),
1792
+ totalFilteredCount: this.totalFilteredCount,
1793
+ });
1794
+ }
1795
+
1796
+ toggleCheckboxes(visible?: boolean): void {
1797
+ if (visible == null) {
1798
+ visible = !this.checkboxesShown;
1799
+ }
1800
+
1801
+ this.checkboxesShown = visible;
1802
+ }
1803
+
1804
+ getSkin(): DataTableSkin {
1805
+ return this.currentSkin || DataTableSkin.Default;
1806
+ }
1807
+
1808
+ getMobileBehavior(): DataTableMobileBehavior {
1809
+ return this.currentMobileBehavior || DataTableMobileBehavior.MobileLayout;
1810
+ }
1811
+
1812
+ getVisibleColumns(): TableColumn[] {
1813
+ const state = StorageHelper.getStoredState(this.id);
1814
+ const colArr = this.columns.filter(p => p.visible != false);
1815
+ this.reorderColumns(this.colSortOrder, colArr);
1816
+ this.handleColumnsVisibility(state, colArr);
1817
+ return colArr;
1818
+
1819
+ // return this.columns.filter(p => p.visible != false);
1820
+ }
1821
+
1822
+ isDesiredCustomFieldColumn(
1823
+ dtCol: TableColumn,
1824
+ row: any,
1825
+ mappingType: any,
1826
+ ): boolean {
1827
+ const nameCf = row.CustomFields.filter(p => p.MappingType == mappingType)[0];
1828
+ if (nameCf != null && ((dtCol.id.includes(`id:${nameCf.Id}`)) || (dtCol.id.includes(`map:${nameCf.MappingType}`)))) {
1829
+ return true;
1830
+ }
1831
+
1832
+ return false;
1833
+ }
1834
+
1835
+ getChangeEventDelay() {
1836
+ if (this.filterMode == DataTableFilterMode.Clientside) {
1837
+ return 0;
1838
+ } else {
1839
+ return 650;
1840
+ }
1841
+ }
1842
+
1843
+ getTableColumnOrder(dtCol: TableColumn, row: any): number {
1844
+ if (dtCol.mobileOrder != null) {
1845
+ return dtCol.mobileOrder;
1846
+ }
1847
+
1848
+ if (dtCol.id.includes('cf:') && row.CustomFields != null) {
1849
+ if (this.isDesiredCustomFieldColumn(
1850
+ dtCol,
1851
+ row,
1852
+ 1,
1853
+ )) {
1854
+ return -10100;
1855
+ }
1856
+
1857
+ if (this.isDesiredCustomFieldColumn(
1858
+ dtCol,
1859
+ row,
1860
+ 1,
1861
+ )) {
1862
+ return -10000;
1863
+ }
1864
+ }
1865
+
1866
+ if (dtCol.id == 'Name') {
1867
+ return -9000;
1868
+ }
1869
+
1870
+ if (dtCol.id == 'TicketName') {
1871
+ return -8900;
1872
+ }
1873
+
1874
+ return null;
1875
+ }
1876
+
1877
+ getTableColumnOrderStyle(dtCol: TableColumn, row: any): string {
1878
+ const retVal = this.getTableColumnOrder(dtCol, row);
1879
+ if (retVal != null) {
1880
+ return `order:${retVal}`;
1881
+ }
1882
+
1883
+ return null;
1884
+ }
1885
+
1886
+ getMassOperationItems(): typeof DropdownButtonItem.prototype[] {
1887
+ return this.massOperationOptions || [];
1888
+ }
1889
+
1890
+ shouldRenderMobileRowColumn(row, dtColumn: TableColumn): boolean {
1891
+ if (dtColumn.customRender == null) {
1892
+ if (dtColumn.customValue != null) {
1893
+ return dtColumn.customValue(row) != null;
1894
+ }
1895
+
1896
+ return row[dtColumn.id] != null;
1897
+ }
1898
+
1899
+ if (dtColumn.mobileShouldRenderRow) {
1900
+ return dtColumn.mobileShouldRenderRow(row);
1901
+ }
1902
+
1903
+ return true;
1904
+ }
1905
+
1906
+ clearSelection() {
1907
+ $(this.$el).find('.dt-col-index').find('input').prop('checked', false);
1908
+ }
1909
+
1910
+ getFilterValue(dtColumn: TableColumn): any {
1911
+ if (this.filterArr == null) {
1912
+ return null;
1913
+ }
1914
+
1915
+ const filterItem = this.filterArr.filter(p => p.PropertyName == dtColumn.id)[0];
1916
+ if (filterItem == null) {
1917
+ return null;
1918
+ }
1919
+
1920
+ if (filterItem.FilterType == DataTableFilterItemType.Text) {
1921
+ return filterItem.ContainsValue;
1922
+ } else if (filterItem.FilterType == DataTableFilterItemType.Dropdown) {
1923
+ return filterItem.ValueArr;
1924
+ } else if (filterItem.FilterType == DataTableFilterItemType.DateRange) {
1925
+ return {
1926
+ startTime: filterItem.DateFrom,
1927
+ endTime: filterItem.DateTo,
1928
+ };
1929
+ } else if (filterItem.FilterType == DataTableFilterItemType.NumericRange) {
1930
+
1931
+ } else {
1932
+ return null;
1933
+ }
1934
+ }
1935
+
1936
+ render(h) {
1937
+ const columns = this.getVisibleColumns();
1938
+ let paginationStart = (this.paginationPosition - 1) * this.getPaginationLength() + 1;
1939
+ let paginationEnd = Math.min(paginationStart + this.getPaginationLength(), this.totalFilteredCount) - 1;
1940
+ const settingsUUID = `ddl-${PortalUtils.randomString(10)}`;
1941
+ const isMobile = PortalUtils.treatAsMobileDevice();
1942
+ const hasMobLayout = this.getMobileBehavior() == DataTableMobileBehavior.MobileLayout;
1943
+ const hasTableSkin = this.getSkin() == DataTableSkin.Default;
1944
+
1945
+ if (this.paginationPosition == this.getLastPaginationIndex()) {
1946
+ paginationEnd += 1;
1947
+ }
1948
+
1949
+ if (this.totalFilteredCount == 0) {
1950
+ paginationStart = 0;
1951
+ paginationEnd = 0;
1952
+ }
1953
+
1954
+ if (this.getPaginationLength() == -1) {
1955
+ paginationEnd = this.totalFilteredCount;
1956
+ }
1957
+
1958
+ return (
1959
+ <div
1960
+ class={
1961
+ `dt-root dt-mobile-mobile dt-device-${PortalUtils.treatAsMobileDevice() ? 'mobile' : 'desktop'
1962
+ }${PortalUtils.isIOS() ? ' dt-ios' : ''
1963
+ } dt-skin-${this.getSkin()
1964
+ } dt-mobbehavior-${this.getMobileBehavior()
1965
+ }${this.checkboxesShown ? ' dt-checkboxes-visible' : ''
1966
+ } dt-breakpoint-${this.activeBreakPoint
1967
+ }${this.fullSizeHasButtonBelow ? ' dt-fs-buttonsbelow' : ''
1968
+ }${this.insetTop ? ' dt-inset-top' : ''
1969
+ }${this.fullSizeTable == true ? ' dt-fullsize-table' : ''
1970
+ } ${this.cssClass || ''}`
1971
+ }
1972
+ >
1973
+ {this.topVisible != false && (
1974
+ <div class="dt-top">
1975
+ <div class="dt-top-buttonsrow">
1976
+ <div class="dt-buttons">
1977
+ <TableButtonComponent title={PowerduckState.getResourceValue('colVisLabel')} icon="fa fa-eye-slash" clicked={() => this.showColVis()} />
1978
+
1979
+ {this.buttons
1980
+ && this.buttons.map(btn => (
1981
+ <TableButtonComponent title={btn.title} icon={btn.icon} childItems={btn.childItems} customRender={btn.customRender} clicked={() => btn.clicked()} />
1982
+ ))}
1983
+
1984
+ {this.allowExport != false && <TableButtonComponent title="Excel export" icon="far fa-file-excel" clicked={() => this.exportExcel()} />}
1985
+
1986
+ {this.allowMassOperations != false && <TableButtonComponent title={this.checkboxesTitle || ''} icon="far fa-check-square" clicked={() => this.toggleCheckboxes()} />}
1987
+
1988
+ {this.activeBreakPoint == DataTableBreakpoint.Mobile && this.getMobileBehavior() == DataTableMobileBehavior.MobileLayout && (
1989
+ <TableButtonComponent title="Filter" icon="fas fa-filter" clicked={() => this.showFilterModal()} />
1990
+ )}
1991
+
1992
+ <span class="nav-item dt-button dropdown">
1993
+ <span class="dropdown-toggle" id={settingsUUID} data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
1994
+ <i class="fas fa-desktop"></i>
1995
+ </span>
1996
+ <div class="dropdown-menu dropdown-menu-right" aria-labelledby={settingsUUID}>
1997
+ {isMobile && (
1998
+ <a class="dropdown-item dropdown-selectable-section" href="javascript:" onClick={() => this.setMobileBehavior(DataTableMobileBehavior.MobileLayout)}>
1999
+ <span>{PowerduckState.getResourceValue('dtLayoutMobile')}</span>
2000
+ {hasMobLayout && <i class="fas fa-check"></i>}
2001
+ </a>
2002
+ )}
2003
+
2004
+ {!isMobile && (
2005
+ <a class="dropdown-item dropdown-selectable-section" href="javascript:" onClick={() => this.setSkin(DataTableSkin.Default)}>
2006
+ <span>{PowerduckState.getResourceValue('dtLayoutTable')}</span>
2007
+ {hasTableSkin && <i class="fas fa-check"></i>}
2008
+ </a>
2009
+ )}
2010
+
2011
+ <a
2012
+ class="dropdown-item dropdown-selectable-section"
2013
+ href="javascript:"
2014
+ onClick={() => (isMobile ? this.setMobileBehavior(DataTableMobileBehavior.Compact) : this.setSkin(DataTableSkin.Compact))}
2015
+ >
2016
+ <span>{isMobile ? PowerduckState.getResourceValue('dtLayoutTable') : PowerduckState.getResourceValue('dtLayoutCompact')}</span>
2017
+ {((isMobile && !hasMobLayout) || (!isMobile && !hasTableSkin)) && <i class="fas fa-check"></i>}
2018
+ </a>
2019
+ </div>
2020
+ </span>
2021
+ </div>
2022
+ </div>
2023
+ {this.hidePagination != true
2024
+ && (
2025
+ <div class="dt-top-paginationrow">
2026
+ {(!this.checkboxesShown || this.checkboxButtonsVisible == false) && (
2027
+ <div class="dt-pagination-length">
2028
+ <select onChange={e => this.handlePaginationLengthChanged(Number(e.target.value))}>
2029
+ {(this.paginations || [
2030
+ 10,
2031
+ 25,
2032
+ 50,
2033
+ 100,
2034
+ 250,
2035
+ 500,
2036
+ 1000,
2037
+ -1,
2038
+ ]).map(item => (
2039
+ <option value={item} selected={this.getPaginationLength() == item}>
2040
+ {item != -1 ? item.toString() : PowerduckState.getResourceValue('all')}
2041
+ </option>
2042
+ ))}
2043
+ </select>
2044
+
2045
+ <span>{PowerduckState.getResourceValue('recordsDtLabel')}</span>
2046
+ </div>
2047
+ )}
2048
+
2049
+ {this.checkboxesShown && this.checkboxButtonsVisible != false && (
2050
+ <div class="dt-pagination-length dt-massop-btn-wrap">
2051
+ <DropdownButton text="Hromadne operacie" layout={ButtonLayout.Secondary}>
2052
+ {this.getMassOperationItems().map(mi =>
2053
+ (mi as any).isSeparator != true ? <DropdownButtonItem icon={mi.icon} text={mi.text} clicked={mi.clicked} /> : <div class="dropdown-divider" />)}
2054
+
2055
+ <DropdownButtonItem icon="icon icon-close" text={PowerduckState.getResourceValue('cancel')} clicked={() => this.toggleCheckboxes(false)} />
2056
+ </DropdownButton>
2057
+ <Button text={PowerduckState.getResourceValue('cancel')} layout={ButtonLayout.Default} clicked={() => this.toggleCheckboxes(false)} cssClass="dt-massop-cancelbtn" />
2058
+ </div>
2059
+ )}
2060
+
2061
+ <div class="dt-fulltext-search">
2062
+ <input type="search" placeholder={`${PowerduckState.getResourceValue('search')[capitalize]()}...`} onKeyup={e => this.performFullTextSearch(e)} />
2063
+ </div>
2064
+ </div>
2065
+ )}
2066
+ </div>
2067
+ )}
2068
+
2069
+ {this.renderTableByMode(h, columns)}
2070
+
2071
+ {this.bottomVisible != false && (
2072
+ <div class="dt-bottom">
2073
+ <div class="dt-summary-wrap">
2074
+ {PowerduckState.getResourceValue('dtCountText').replace('{0}', paginationStart.toString()).replace('{1}', paginationEnd.toString()).replace('{2}', this.totalFilteredCount.toString())}
2075
+ {this.totalFilteredCount != this.totalCount && (
2076
+ <span class="dt-summary-totalcount">
2077
+ &nbsp;
2078
+ {PowerduckState.getResourceValue('dtCountFilteredOutOf').replace('{0}', this.totalCount.toString())}
2079
+ </span>
2080
+ )}
2081
+ </div>
2082
+
2083
+ <div class="dt-pagination">{this.renderPagination(h)}</div>
2084
+ </div>
2085
+ )}
2086
+
2087
+ <ColVisModal ref="colVisModal" columns={this.columns} changed={e => this.handleColumnVisibilityChanged(e)} />
2088
+ <ColFilterModal ref="colFilterModal" columns={this.columns} changed={e => this.handleColumnModalFilterChanged(e)} />
2089
+ <TableExportModal ref="tableExportModal" />
2090
+ </div>
2091
+ );
2092
+ }
2093
+
2094
+ protected renderTableByMode(h, columns: TableColumn[]) {
2095
+ if (this.activeBreakPoint == DataTableBreakpoint.Mobile) {
2096
+ if (this.getMobileBehavior() == DataTableMobileBehavior.MobileLayout) {
2097
+ return this.renderMobileMode(h, columns);
2098
+ } else if (this.getMobileBehavior() == DataTableMobileBehavior.VerticalTransform) {
2099
+ return this.renderVerticallyTransformedTable(h, columns);
2100
+ }
2101
+ }
2102
+
2103
+ return this.renderStandardTable(h, columns);
2104
+ }
2105
+
2106
+ protected renderStandardTable(h, columns: TableColumn[]) {
2107
+ return (
2108
+ <div class="dt-table dt-table-mode">
2109
+ <table>
2110
+ <LoadingIndicator visible={!this.initialized} />
2111
+
2112
+ {this.enforceHeaderRedraw == false && (
2113
+ <thead>
2114
+ <tr class="dt-header">
2115
+ <th data-col-id="_sysIndexCol" class="dt-header-index">
2116
+ {!this.isLoading && (
2117
+ <span>
2118
+ <span class="dt-header-indexlabel" style={this.checkboxesShown ? 'display:none' : ''}>
2119
+ #
2120
+ </span>
2121
+ <span class="dt-header-indexcheckbox" style={this.checkboxesShown ? '' : 'display:none'}>
2122
+ <CheckBox
2123
+ skin={CheckBoxSkin.Material}
2124
+ label={null}
2125
+ wrap={false}
2126
+ value={false}
2127
+ changed={(e) => {
2128
+ this.handleCheckAllChanged(e);
2129
+ }}
2130
+ />
2131
+ </span>
2132
+ </span>
2133
+ )}
2134
+
2135
+ {this.isLoading && <img src={loadingGif} />}
2136
+ </th>
2137
+
2138
+ {this.renderHeaderRow(h, columns)}
2139
+ </tr>
2140
+
2141
+ {this.autoFilter != false && (
2142
+ <tr class="dt-header-filter">
2143
+ <th class="dt-filter-index"></th>
2144
+
2145
+ {columns.map((dtColumn, i) => (
2146
+ <th class={this.getTableColumnHeaderFilterCssClass(dtColumn, i)}>{this.renderHeaderFilter(h, dtColumn)}</th>
2147
+ ))}
2148
+ </tr>
2149
+ )}
2150
+ </thead>
2151
+ )}
2152
+ <tbody>
2153
+ {this.rowClicked == null
2154
+ && this.enforceBodyRedraw == false
2155
+ && (this.rows || []).map((row, i) => (
2156
+ <tr class={`dt-item${this.rowCssClass == null ? '' : ` ${this.rowCssClass(row)}`}`}>
2157
+ <td class={`dt-col-index${this.sortableRows == true ? ' dt-has-sortable-rows' : ''}`}>
2158
+ <span class="dt-col-indexlabel" style={this.checkboxesShown ? 'display:none' : ''}>
2159
+ {this.getHeaderColumnIndex(
2160
+ columns,
2161
+ row,
2162
+ i,
2163
+ )}
2164
+ </span>
2165
+ <span class="dt-col-indexcheckbox dt-selection-checkbox" data-id={this.getRowId(row)} style={this.checkboxesShown ? '' : 'display:none'}>
2166
+ <CheckBox skin={CheckBoxSkin.Material} label={null} value={false} wrap={false} changed={e => this.handleRowCheckboxChanged(row, e)} />
2167
+ </span>
2168
+
2169
+ {this.sortableRows == true && <i class="fas fa-sort dt-sort-handle" />}
2170
+ </td>
2171
+
2172
+ {columns.map((dtColumn, j) => (
2173
+ <td class={this.getTableItemCssClass(dtColumn, j)}>{dtColumn.customRender == null ? (dtColumn.customValue == null ? row[dtColumn.id] : dtColumn.customValue(row)) : dtColumn.customRender(h, row)}</td>
2174
+ ))}
2175
+ </tr>
2176
+ ))}
2177
+
2178
+ {this.rowClicked != null
2179
+ && this.enforceBodyRedraw == false
2180
+ && (this.rows || []).map((row, i) => (
2181
+ <tr
2182
+ class={`dt-item${this.rowCssClass == null ? '' : ` ${this.rowCssClass(row)}`}`}
2183
+ onClick={() => {
2184
+ this.rowClicked(row);
2185
+ }}
2186
+ >
2187
+ <td class={`dt-col-index${this.sortableRows == true ? ' dt-has-sortable-rows' : ''}`}>
2188
+ <span class="dt-col-indexlabel" style={this.checkboxesShown ? 'display:none' : ''}>
2189
+ {this.getHeaderColumnIndex(
2190
+ columns,
2191
+ row,
2192
+ i,
2193
+ )}
2194
+ </span>
2195
+ <span class="dt-col-indexcheckbox dt-selection-checkbox" data-id={this.getRowId(row)} style={this.checkboxesShown ? '' : 'display:none'}>
2196
+ <CheckBox skin={CheckBoxSkin.Material} label={null} value={false} wrap={false} changed={e => this.handleRowCheckboxChanged(row, e)} />
2197
+ </span>
2198
+
2199
+ {this.sortableRows == true && <i class="fas fa-sort dt-sort-handle" />}
2200
+ </td>
2201
+
2202
+ {columns.map((dtColumn, j) => (
2203
+ <td class={this.getTableItemCssClass(dtColumn, j)}>{dtColumn.customRender == null ? (dtColumn.customValue == null ? row[dtColumn.id] : dtColumn.customValue(row)) : dtColumn.customRender(h, row)}</td>
2204
+ ))}
2205
+ </tr>
2206
+ ))}
2207
+
2208
+ {this.totalFilteredCount == 0 && (
2209
+ <tr>
2210
+ <td class="dt-no-results" colspan="99999">
2211
+ <div class="dt-no-results-inner">
2212
+ <div>{PowerduckState.getResourceValue('noResultsFound')}</div>
2213
+ </div>
2214
+ </td>
2215
+ </tr>
2216
+ )}
2217
+ </tbody>
2218
+ </table>
2219
+ </div>
2220
+ );
2221
+ }
2222
+
2223
+ protected renderHeaderRow(h, columns: TableColumn[]) {
2224
+ return columns.map((dtColumn, i) => (
2225
+ <th
2226
+ data-col-id={dtColumn.id}
2227
+ onMousedown={e =>
2228
+ ReorderProvider.handleMouseDown(
2229
+ e,
2230
+ (sortOrder) => {
2231
+ this.handleColumnsReordered(sortOrder);
2232
+ },
2233
+ () => {
2234
+ this.handleColumnHeaderClicked(dtColumn);
2235
+ },
2236
+ )}
2237
+ onTouchstart={e =>
2238
+ ReorderProvider.handleMouseDown(
2239
+ e,
2240
+ (sortOrder) => {
2241
+ this.handleColumnsReordered(sortOrder);
2242
+ },
2243
+ () => {
2244
+ this.handleColumnHeaderClicked(dtColumn);
2245
+ },
2246
+ )}
2247
+ class={this.getTableColumnHeaderCssClass(dtColumn, i)}
2248
+ >
2249
+ {dtColumn.caption}
2250
+ {this.sortDefinition && this.sortDefinition.columnId == dtColumn.id && (
2251
+ <span class="dt-sort">
2252
+ <i class={`fas ${this.sortDefinition.direction == DataTableSortDirection.Ascending ? 'fa-sort-up' : 'fa-sort-down'} float-right`} aria-hidden="true"></i>
2253
+ </span>
2254
+ )}
2255
+ </th>
2256
+ ));
2257
+ }
2258
+
2259
+ protected renderHeaderFilter(h, dtColumn: TableColumn) {
2260
+ const filterType = dtColumn.filterType;
2261
+ const filterValue = this.getFilterValue(dtColumn);
2262
+ const closeIcon = !isNullOrEmpty(filterValue) ? 'icon icon-close' : null;
2263
+ const appendIconClicked = () => {
2264
+ if (this.currentAdvancedFilterState[dtColumn.id] != null) {
2265
+ this.currentAdvancedFilterState[dtColumn.id] = null;
2266
+ }
2267
+
2268
+ if (this.filterArr != null) {
2269
+ this.filterArr = this.filterArr.filter(p => p.PropertyName != dtColumn.id);
2270
+ }
2271
+
2272
+ if (filterType == DataTableFilterItemType.Text || filterType == null) {
2273
+ this.performInputFilter(dtColumn, null);
2274
+ } else if (filterType == DataTableFilterItemType.DateRange) {
2275
+ this.performDateRangeFilter(dtColumn, null);
2276
+ } else if (filterType == DataTableFilterItemType.Dropdown) {
2277
+ this.performSelectionFilter(
2278
+ dtColumn,
2279
+ [],
2280
+ null,
2281
+ );
2282
+ } else if (filterType == DataTableFilterItemType.NumericRange) {
2283
+
2284
+ }
2285
+ };
2286
+
2287
+ if (filterType == DataTableFilterItemType.None) {
2288
+ return '';
2289
+ } else if (filterType == DataTableFilterItemType.Text || filterType == null) {
2290
+ return (<TextBox updateMode="input" cssClass="dt-filter-input" wrap={false} label={null} placeholder={`${PowerduckState.getResourceValue('search')[capitalize]()}...`} value={this.currentAdvancedFilterState[dtColumn.id]} changed={(e) => { this.performInputFilter(dtColumn, e); }} appendIcon={closeIcon} appendIconClicked={appendIconClicked} />);
2291
+ } else if (filterType == DataTableFilterItemType.Dropdown) {
2292
+ return (
2293
+ <div class="dt-filter-dropdown">
2294
+ <DropdownList
2295
+ label={null}
2296
+ containerCssClass="dt-filter-dropdown-container"
2297
+ options={dtColumn.filterItems}
2298
+ wrap={false}
2299
+ disableSearch={!dtColumn.searchable}
2300
+ dropdownAutoWidth={true}
2301
+ multiselect={true}
2302
+ multiselectMode={MultiselectMode.Checkboxes}
2303
+ mobileShortMode={true}
2304
+ allowExclusiveSearch={dtColumn.filterAllowExclusivity}
2305
+ changedEventDelay={this.getChangeEventDelay()}
2306
+ selected={this.currentAdvancedFilterState[dtColumn.id]}
2307
+ changed={(changeArr, exclusivity) => {
2308
+ this.performSelectionFilter(
2309
+ dtColumn,
2310
+ changeArr,
2311
+ exclusivity,
2312
+ );
2313
+ }}
2314
+ appendIcon={closeIcon}
2315
+ appendIconClicked={appendIconClicked}
2316
+ />
2317
+ </div>
2318
+ );
2319
+ } else if (filterType == DataTableFilterItemType.DateRange) {
2320
+ return (<DaterangePicker label={null} cssClass="dt-filter-input" wrap={false} placeholder={`${PowerduckState.getResourceValue('search')[capitalize]()}...`} value={this.currentAdvancedFilterState[dtColumn.id]} changed={(e) => { this.performDateRangeFilter(dtColumn, e); }} appendIcon={closeIcon} appendIconClicked={appendIconClicked} />);
2321
+ }
2322
+ }
2323
+
2324
+ protected renderVerticallyTransformedTable(h, columns: TableColumn[]) {
2325
+ return (this.rows || []).map((row, i) => (
2326
+ <div class="dt-vert-row">
2327
+ {columns.map((dtColumn, j) => (
2328
+ <div class="dt-vert-item" style={this.getTableColumnOrderStyle(dtColumn, row)}>
2329
+ <div class="dt-vert-caption">{dtColumn.caption}</div>
2330
+ <div class="dt-vert-value">{dtColumn.customRender == null ? (dtColumn.customValue == null ? row[dtColumn.id] : dtColumn.customValue(row)) : dtColumn.customRender(h, row)}</div>
2331
+ </div>
2332
+ ))}
2333
+ </div>
2334
+ ));
2335
+ }
2336
+
2337
+ protected renderMobileMode(h, columns: TableColumn[]) {
2338
+ if (this.mobileModeCustomRender != null) {
2339
+ return this.mobileModeCustomRender(
2340
+ h,
2341
+ columns,
2342
+ this.rows,
2343
+ );
2344
+ }
2345
+
2346
+ return (
2347
+ <div class="dt-mobile-rows">
2348
+ {(this.isLoading || this.enforceBodyRedraw || this.enforceHeaderRedraw) && (
2349
+ <div style="min-height:150px;">
2350
+ <LoadingIndicator visible={true} />
2351
+ </div>
2352
+ )}
2353
+
2354
+ {this.enforceHeaderRedraw == false
2355
+ && this.enforceBodyRedraw == false
2356
+ && (this.rows || []).map((row, i) => (
2357
+ <div class={`dt-mobile-row${this.rowCssClass == null ? '' : ` ${this.rowCssClass(row)}`}`}>
2358
+ {this.renderMobileModeRow(
2359
+ h,
2360
+ columns,
2361
+ row,
2362
+ i,
2363
+ )}
2364
+ </div>
2365
+ ))}
2366
+ </div>
2367
+ );
2368
+ }
2369
+
2370
+ protected renderMobileModeRow(
2371
+ h,
2372
+ columns: TableColumn[],
2373
+ row: any,
2374
+ i: number,
2375
+ ) {
2376
+ const identifier = this.getRowIdentifier(
2377
+ columns,
2378
+ row,
2379
+ true,
2380
+ );
2381
+ let colArr = this.getVisibleColumns().filter(p => p.mobileVisible != false);
2382
+ const cssClass = `dt-mobile-row-inner${this.checkboxesShown ? ' dt-mobile-chbvisible' : ''}`;
2383
+
2384
+ // Exclude identifier columns if they are already picked by the engine
2385
+ if (identifier != null && identifier.dtColumns != null && identifier.dtColumns.length > 0) {
2386
+ colArr = colArr.filter(p => !identifier.dtColumns.map(c => c.id).includes(p.id));
2387
+ }
2388
+
2389
+ return (
2390
+ <div
2391
+ class={cssClass}
2392
+ onClick={(e) => {
2393
+ this.handleMobileRowClicked(e, row);
2394
+ }}
2395
+ >
2396
+ {this.checkboxesShown && (
2397
+ <div class="dt-mobile-checkbox dt-selection-checkbox" data-id={this.getRowId(row)}>
2398
+ <CheckBox skin={CheckBoxSkin.Material} label={null} wrap={false} value={null} changed={e => this.handleRowCheckboxChanged(row, e)} />
2399
+ </div>
2400
+ )}
2401
+
2402
+ {identifier && <div class="dt-mobile-identifier">{identifier.fullName}</div>}
2403
+
2404
+ {colArr.map((dtColumn, j) => (
2405
+ <div class={`dt-mobile-item dt-mobile-${dtColumn.id.replaceAll(':', '_').toLowerCase()}`} style={this.getTableColumnOrderStyle(dtColumn, row)}>
2406
+ {dtColumn.mobileRender == null && this.shouldRenderMobileRowColumn(row, dtColumn) && (
2407
+ <div class="dt-mobile-item-inner">
2408
+ {dtColumn.mobileCaption != false && <div class="dt-mobile-caption">{dtColumn.caption}</div>}
2409
+
2410
+ <div class="dt-mobile-value">{dtColumn.customRender == null ? (dtColumn.customValue == null ? row[dtColumn.id] : dtColumn.customValue(row)) : dtColumn.customRender(h, row)}</div>
2411
+ </div>
2412
+ )}
2413
+ {dtColumn.mobileRender && dtColumn.mobileRender(h, row)}
2414
+ </div>
2415
+ ))}
2416
+
2417
+ <i class={`${this.mobileModeRowIcon || 'icon icon-arrow-right'} dt-mobile-row-icon`}></i>
2418
+ </div>
2419
+ );
2420
+ }
2421
+
2422
+ protected renderPagination(h) {
2423
+ let paginationLength = 5;
2424
+ let firstIndex = Math.max(this.paginationPosition - 2, 1);
2425
+ let paginationEnd = firstIndex + paginationLength - 1;
2426
+ let indexArr = [];
2427
+
2428
+ if (this.getPaginationLength() > -1) {
2429
+ if (paginationEnd > this.getLastPaginationIndex()) {
2430
+ paginationEnd = this.getLastPaginationIndex();
2431
+ firstIndex = paginationEnd - paginationLength + 1;
2432
+ }
2433
+
2434
+ if (firstIndex < 1) {
2435
+ firstIndex = 1;
2436
+ paginationLength = paginationEnd - firstIndex + 1;
2437
+ }
2438
+
2439
+ for (let i = firstIndex, len = paginationLength; i <= paginationEnd; i++) {
2440
+ indexArr.push(i);
2441
+ }
2442
+ } else {
2443
+ indexArr = [1];
2444
+ this.paginationPosition = 1;
2445
+ }
2446
+
2447
+ return (
2448
+ <ul class="pagination">
2449
+ <li class="page-item">
2450
+ <a class="page-link" href="javascript:" aria-label="Previous" onClick={e => this.handlePaginationPositionChanged(this.paginationPosition - 1)}>
2451
+ <span aria-hidden="true">
2452
+ <i class="fa fa-angle-double-left" aria-hidden="true"></i>
2453
+ </span>
2454
+ </a>
2455
+ </li>
2456
+
2457
+ {indexArr.map(pagIndex => (
2458
+ <li class={`page-item${pagIndex == this.paginationPosition ? ' active' : ''}`} onClick={e => this.handlePaginationPositionChanged(pagIndex)}>
2459
+ <a class="page-link" href="javascript:">
2460
+ {pagIndex}
2461
+ </a>
2462
+ </li>
2463
+ ))}
2464
+
2465
+ <li class="page-item">
2466
+ <a class="page-link" href="javascript:" aria-label="Next" onClick={e => this.handlePaginationPositionChanged(this.paginationPosition + 1)}>
2467
+ <span aria-hidden="true">
2468
+ <i class="fa fa-angle-double-right" aria-hidden="true"></i>
2469
+ </span>
2470
+ </a>
2471
+ </li>
2472
+ </ul>
2473
+ );
2474
+ }
2475
+
2476
+ protected renderColumnValue(
2477
+ h,
2478
+ dtColumn: TableColumn,
2479
+ row,
2480
+ ) {
2481
+ if (dtColumn.customRender == null) {
2482
+ return (dtColumn.customValue == null ? row[dtColumn.id] : dtColumn.customValue(row));
2483
+ } else {
2484
+ return dtColumn.customRender(h, row);
2485
+ }
2486
+ }
2483
2487
  }
2484
2488
 
2485
2489
  (function () {
2486
- CheckboxUtils.bindTableShiftClick();
2487
- DropdownUtils.bindDropdownOverflowHack(
2488
- '.dt-root.dt-breakpoint-desktop tbody .dropdown',
2489
- 'dataTableDropdown',
2490
- 'dt-dropdown-button-cloned',
2491
- false,
2492
- );
2490
+ CheckboxUtils.bindTableShiftClick();
2491
+ DropdownUtils.bindDropdownOverflowHack(
2492
+ '.dt-root.dt-breakpoint-desktop tbody .dropdown',
2493
+ 'dataTableDropdown',
2494
+ 'dt-dropdown-button-cloned',
2495
+ false,
2496
+ );
2493
2497
  })();
2494
2498
 
2495
2499
  const DataTable = toNative(DataTableComponent);