ms-data-grid 0.0.17 → 0.0.19

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 (58) hide show
  1. package/esm2022/lib/data-grid/data-grid.component.mjs +3646 -0
  2. package/esm2022/lib/data-grid/statuses.mjs +44 -0
  3. package/esm2022/lib/data-grid.module.mjs +25 -0
  4. package/esm2022/lib/data-grid.service.mjs +14 -0
  5. package/esm2022/lib/directives/draggable-header.directive.mjs +145 -0
  6. package/esm2022/lib/pipes/filter.pipe.mjs +22 -0
  7. package/esm2022/lib/services/common.service.mjs +206 -0
  8. package/esm2022/lib/services/copy-service.service.mjs +221 -0
  9. package/esm2022/lib/services/split-columns.service.mjs +143 -0
  10. package/esm2022/lib/services/swap-columns.service.mjs +118 -0
  11. package/esm2022/ms-data-grid.mjs +5 -0
  12. package/esm2022/public-api.mjs +8 -0
  13. package/fesm2022/ms-data-grid.mjs +4569 -0
  14. package/fesm2022/ms-data-grid.mjs.map +1 -0
  15. package/index.d.ts +5 -0
  16. package/lib/data-grid/data-grid.component.d.ts +469 -0
  17. package/lib/data-grid/statuses.d.ts +3 -0
  18. package/lib/data-grid.module.d.ts +14 -0
  19. package/lib/data-grid.service.d.ts +6 -0
  20. package/lib/directives/draggable-header.directive.d.ts +31 -0
  21. package/lib/pipes/filter.pipe.d.ts +7 -0
  22. package/lib/services/common.service.d.ts +17 -0
  23. package/lib/services/copy-service.service.d.ts +14 -0
  24. package/lib/services/split-columns.service.d.ts +9 -0
  25. package/lib/services/swap-columns.service.d.ts +19 -0
  26. package/package.json +45 -33
  27. package/{src/public-api.ts → public-api.d.ts} +4 -8
  28. package/CHANGELOG.md +0 -57
  29. package/DOCUMENTATION.md +0 -243
  30. package/ng-package.json +0 -10
  31. package/src/lib/css/bootstrap.css +0 -12043
  32. package/src/lib/data-grid/data-grid.component.html +0 -4806
  33. package/src/lib/data-grid/data-grid.component.scss +0 -1502
  34. package/src/lib/data-grid/data-grid.component.spec.ts +0 -28
  35. package/src/lib/data-grid/data-grid.component.ts +0 -4216
  36. package/src/lib/data-grid/statuses.ts +0 -47
  37. package/src/lib/data-grid.module.ts +0 -20
  38. package/src/lib/data-grid.service.spec.ts +0 -16
  39. package/src/lib/data-grid.service.ts +0 -9
  40. package/src/lib/directives/draggable-header.directive.spec.ts +0 -11
  41. package/src/lib/directives/draggable-header.directive.ts +0 -172
  42. package/src/lib/pipes/filter.pipe.spec.ts +0 -11
  43. package/src/lib/pipes/filter.pipe.ts +0 -16
  44. package/src/lib/services/cell-selection.service.spec.ts +0 -16
  45. package/src/lib/services/cell-selection.service.ts +0 -234
  46. package/src/lib/services/common.service.spec.ts +0 -16
  47. package/src/lib/services/common.service.ts +0 -239
  48. package/src/lib/services/copy-service.service.spec.ts +0 -16
  49. package/src/lib/services/copy-service.service.ts +0 -251
  50. package/src/lib/services/drag-drp.service.spec.ts +0 -16
  51. package/src/lib/services/drag-drp.service.ts +0 -58
  52. package/src/lib/services/split-columns.service.spec.ts +0 -16
  53. package/src/lib/services/split-columns.service.ts +0 -148
  54. package/src/lib/services/swap-columns.service.spec.ts +0 -16
  55. package/src/lib/services/swap-columns.service.ts +0 -162
  56. package/tsconfig.lib.json +0 -16
  57. package/tsconfig.lib.prod.json +0 -10
  58. package/tsconfig.spec.json +0 -14
@@ -1,4806 +0,0 @@
1
- <div class="position-relative h-100">
2
- <div
3
- class="d-flex justify-content-between mb-3 align-items-center position-relative"
4
- >
5
- <div class="col-4 global-search">
6
- <span
7
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/search.svg'"
8
- class="data-grid-svg-icon mx-2 position-absolute icon"
9
- ></span>
10
- <input
11
- style="height: 36px"
12
- class="form-control"
13
- placeholder="Type to search, then press Enter"
14
- [(ngModel)]="tableSearch"
15
- (keydown.enter)="onGlobalSearch()"
16
- type="search"
17
- />
18
- </div>
19
- <div class="d-flex gap-2 align-items-center table-right-top-actions">
20
- <div
21
- *ngIf="!showFilterRow"
22
- class="cursor-pointer position-relative"
23
- (click)="toggleOpenFilter()"
24
- [class.active]="showFilters"
25
- >
26
- <span
27
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'"
28
- class="data-grid-svg-icon top-icon me-2"
29
- ></span>
30
- <span
31
- *ngIf="activeFilteredColumns?.length"
32
- style="
33
- width: 7px;
34
- height: 7px;
35
- box-shadow: 0px 0px 3px #0022ff;
36
- background-color: rgb(0, 60, 255);
37
- position: absolute;
38
- right: 2px;
39
- top: 2px;
40
- "
41
- class="rounded-circle d-block"
42
- ></span>
43
- </div>
44
- <div
45
- class="cursor-pointer d-none"
46
- (click)="toggleActions('advance-filter')"
47
- [class.active]="activeTopButton === 'advance-filter'"
48
- >
49
- <span
50
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/zoom-charge.svg'"
51
- class="data-grid-svg-icon top-icon me-2"
52
- ></span>
53
- </div>
54
- <div
55
- class="cursor-pointer"
56
- (click)="toggleActions('setting')"
57
- [class.active]="
58
- activeTopButton === 'setting' ||
59
- activeTopButton === 'table-layout' ||
60
- activeTopButton === 'table-presets' ||
61
- activeTopButton === 'show-hide-columns'
62
- "
63
- >
64
- <span
65
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/settings-2.svg'"
66
- class="data-grid-svg-icon top-icon me-2"
67
- ></span>
68
-
69
- <div
70
- *ngIf="activeTopButton === 'setting'"
71
- class="actions-dropdown mt-1 actions-dropdown-setting"
72
- >
73
- <div class="dropdown-menu show shadow custom-menu">
74
- <!-- Table Layout -->
75
- <a
76
- class="dropdown-item d-flex justify-content-between align-items-center cursor-pointer"
77
- (click)="$event.stopPropagation(); toggleActions('table-layout')"
78
- >
79
- <span
80
- ><span
81
- [inlineSVG]="
82
- singleSpaAssetsPath + 'data-grid/icons/table-2.svg'
83
- "
84
- class="data-grid-svg-icon me-2"
85
- ></span>
86
- Table Layout</span
87
- >
88
- <span
89
- [inlineSVG]="
90
- singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
91
- "
92
- class="data-grid-svg-icon me-2"
93
- ></span>
94
- </a>
95
- <!-- Table Presets -->
96
- <a
97
- (click)="$event.stopPropagation(); toggleActions('table-presets')"
98
- class="dropdown-item d-flex justify-content-between align-items-center cursor-pointer"
99
- >
100
- <span
101
- ><span
102
- [inlineSVG]="
103
- singleSpaAssetsPath + 'data-grid/icons/list-details.svg'
104
- "
105
- class="data-grid-svg-icon me-2"
106
- ></span>
107
- Table Presets</span
108
- >
109
- <span
110
- [inlineSVG]="
111
- singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
112
- "
113
- class="data-grid-svg-icon me-2"
114
- ></span>
115
- </a>
116
-
117
- <!-- Columns -->
118
- <a
119
- *ngIf="!showSideMenu"
120
- (click)="
121
- $event.stopPropagation(); toggleActions('show-hide-columns')
122
- "
123
- class="dropdown-item d-flex justify-content-between align-items-center cursor-pointer"
124
- >
125
- <span
126
- ><span
127
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/eye.svg'"
128
- class="data-grid-svg-icon me-2"
129
- ></span>
130
- Columns</span
131
- >
132
- <div class="d-flex gap-2">
133
- <span class="muted-text">{{ columnsCount }}</span>
134
- <span
135
- [inlineSVG]="
136
- singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
137
- "
138
- class="data-grid-svg-icon me-2"
139
- ></span>
140
- </div>
141
- </a>
142
-
143
- <div class="dropdown-divider"></div>
144
-
145
- <!-- Filter -->
146
- <a class="dropdown-item cursor-pointer" (click)="toggleOpenFilter(); activeTopButton = ''" *ngIf="!showFilterRow">
147
- <span
148
- [inlineSVG]="
149
- singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'
150
- "
151
- class="data-grid-svg-icon me-2 mt-1 cursor-pointer"
152
- ></span>
153
- Filter
154
- </a>
155
-
156
- <!-- Download -->
157
- <a class="dropdown-item cursor-pointer" (click)="downloadCsv()">
158
- <span
159
- [inlineSVG]="
160
- singleSpaAssetsPath + 'data-grid/icons/download.svg'
161
- "
162
- class="data-grid-svg-icon me-2 cursor-pointer"
163
- ></span>
164
- Download as CSV
165
- </a>
166
- <!-- Font Family & Font Size -->
167
- <div class="px-2 pb-2 pt-2">
168
- <div class="d-flex gap-2">
169
- <!-- Font Family -->
170
- <select
171
- class="form-select form-select-sm"
172
- [(ngModel)]="fontFaimly"
173
- (change)="onFontChange()"
174
- >
175
- <option *ngFor="let font of fontFamilies" [value]="font">
176
- {{ font }}
177
- </option>
178
- </select>
179
-
180
- <!-- Font Size -->
181
- <select
182
- class="form-select form-select-sm"
183
- (change)="onFontChange()"
184
- [(ngModel)]="bodyTextFontsSize"
185
- >
186
- <option *ngFor="let size of fontSizes" [value]="size">
187
- {{ size }}
188
- </option>
189
- </select>
190
- </div>
191
- </div>
192
- </div>
193
- </div>
194
-
195
- <!-- Table Layout -->
196
-
197
- <ng-container *ngIf="activeTopButton === 'table-layout'">
198
- <div
199
- *ngTemplateOutlet="tableLayout"
200
- class="actions-dropdown mt-1"
201
- ></div>
202
- </ng-container>
203
-
204
- <!-- Table Presets -->
205
- <ng-container *ngIf="activeTopButton === 'table-presets'">
206
- <div
207
- *ngTemplateOutlet="tablePreset"
208
- class="actions-dropdown mt-1"
209
- ></div>
210
- </ng-container>
211
-
212
- <!-- Table Presets -->
213
- <ng-container *ngIf="activeTopButton === 'show-hide-columns'">
214
- <div
215
- *ngTemplateOutlet="showHideColumns"
216
- class="actions-dropdown mt-1"
217
- ></div>
218
- </ng-container>
219
- </div>
220
- <div>
221
- <!-- Example single danger button -->
222
-
223
- <!-- <button
224
- type="button"
225
- class="btn btn-primary btn-sm d-flex gap-2 action-button"
226
- (click)="toggleActions('actions')"
227
- >
228
- Action
229
- <span
230
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/Vector.svg'"
231
- class="data-grid-svg-icon"
232
- ></span>
233
- </button>
234
- <div
235
- *ngIf="activeTopButton === 'actions'"
236
- class="actions-dropdown mt-1"
237
- >
238
- <div class="dropdown-menu show">
239
- <a class="dropdown-item" href="#">Action</a>
240
- <a class="dropdown-item" href="#">Another action</a>
241
- <a class="dropdown-item" href="#">Something else here</a>
242
- <div class="dropdown-divider"></div>
243
- <a class="dropdown-item" href="#">Separated link</a>
244
- </div>
245
- </div> -->
246
- </div>
247
- </div>
248
- </div>
249
-
250
- <div
251
- *ngIf="showFilters && !showFilterRow"
252
- class="top-filter-row border-top py-2 d-flex justify-content-between align-items-center"
253
- [style.height.px]="topFilterRowHeight"
254
- >
255
- <!-- LEFT SIDE (Filter tags + Filter button) -->
256
- <div class="d-flex gap-2 align-items-center">
257
- <ng-container *ngIf="activeFilteredColumns?.length">
258
- <div
259
- *ngFor="let col of activeFilteredColumns; trackBy: trackByField"
260
- class="filter-tags"
261
- >
262
- <div
263
- (click)="
264
- isActiveFilterOpen = true;
265
- activeTopButton = 'filter-columns';
266
- openFilter(col)
267
- "
268
- class="d-flex justify-content-center align-items-center muted-text add-filter-button active-filters"
269
- style="white-space: nowrap"
270
- [class.active]="
271
- col?.field == selectedColumnForFilter?.field &&
272
- isActiveFilterOpen &&
273
- activeTopButton == 'filter-columns'
274
- "
275
- >
276
- <span class="header-tag mt-0 d-flex align-items-center">
277
- <span
278
- *ngIf="col?.pinned"
279
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/pin.svg'"
280
- class="data-grid-svg-icon me-2"
281
- ></span>
282
- {{ col.header }}
283
- <span
284
- (click)="
285
- $event.stopPropagation(); removeColumnFilterFromColumn(col)
286
- "
287
- [inlineSVG]="
288
- singleSpaAssetsPath + 'data-grid/icons/cross-primary.svg'
289
- "
290
- class="data-grid-svg-icon cross-secondary ms-2 mb-1"
291
- ></span>
292
- </span>
293
- </div>
294
-
295
- <ng-container
296
- *ngIf="
297
- activeTopButton === 'filter-columns' &&
298
- col?.field == selectedColumnForFilter?.field &&
299
- isActiveFilterOpen
300
- "
301
- >
302
- <div
303
- *ngTemplateOutlet="filterColumns; context: { column: col }"
304
- class="actions-dropdown mt-1"
305
- ></div>
306
- </ng-container>
307
- </div>
308
- </ng-container>
309
-
310
- <!-- Filter Button -->
311
- <div class="add-filter-button-menu">
312
- <div
313
- (click)="toggleActions('filter-columns'); isActiveFilterOpen = false"
314
- class="d-flex justify-content-center align-items-center muted-text add-filter-button button-filter"
315
- style="width: 70px"
316
- >
317
- <span
318
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/plus.svg'"
319
- class="me-2 data-grid-svg-icon"
320
- ></span>
321
- Filter
322
- </div>
323
-
324
- <ng-container
325
- *ngIf="activeTopButton === 'filter-columns' && !isActiveFilterOpen"
326
- >
327
- <div
328
- *ngTemplateOutlet="filterColumns"
329
- class="actions-dropdown mt-1"
330
- ></div>
331
- </ng-container>
332
- </div>
333
- </div>
334
-
335
- <!-- RIGHT SIDE (Update + Reset) -->
336
- <div class="d-flex gap-3 align-items-center">
337
- <div
338
- (click)="savePreset()"
339
- class="text-primary cursor-pointer all-filters-reset-button"
340
- *ngIf="!checkFilterChangesEffect()"
341
- >
342
- Update View
343
- </div>
344
-
345
- <div
346
- class="text-primary cursor-pointer all-filters-reset-button"
347
- *ngIf="!tableFilterViewId && activeFilteredColumns?.length"
348
- (click)="clearAllFilters()"
349
- >
350
- Reset
351
- </div>
352
- </div>
353
- </div>
354
-
355
- <div
356
- [style.height]="
357
- showFilters ? 'calc(100% - ' + topFilterRowHeight + 'px)' : '100%'
358
- "
359
- cdkDropListGroup
360
- class="data-grid-table-wrapper overflow-hidden"
361
- #dataGridContainer
362
- [style.fontFamily]="fontFaimly"
363
- >
364
- <div
365
- *ngIf="showRowsGrouping"
366
- [style.height.px]="headerRowHeight"
367
- [cdkDropListData]="columns"
368
- [style.backgroundColor]="
369
- topGroupedBadgesBackgroundColor || headerBackgroundColor
370
- "
371
- cdkDropList
372
- (cdkDropListEntered)="enterToTopRowGrouping($event)"
373
- (cdkDropListExited)="exitedFromTheTopRow($event)"
374
- (cdkDropListDropped)="onDropTopGroup($event)"
375
- [cdkDropListEnterPredicate]="canEnterToRowsGrouping"
376
- id="rows-grouping-top-container"
377
- class="border-below d-flex px-4 align-items-center"
378
- >
379
- <div class="d-flex gap-2 align-items-center">
380
- <span
381
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/justify.svg'"
382
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
383
- ></span>
384
- <div *ngIf="!draggingInGroupArea && !groupedColumns?.length">
385
- Drag here to set row groups
386
- </div>
387
- <ng-container
388
- *ngFor="
389
- let child of groupedColumns;
390
- let i = index;
391
- trackBy: trackByField
392
- "
393
- >
394
- <ng-container
395
- *ngTemplateOutlet="
396
- topGroupingRowPlaceholder;
397
- context: {
398
- $implicit: child,
399
- showChevron:
400
- groupedColumns.length > 1 && i != groupedColumns.length - 1
401
- }
402
- "
403
- ></ng-container>
404
- </ng-container>
405
- </div>
406
- </div>
407
- <div
408
- class="d-flex overflow-hidden"
409
- [style.height]="
410
- 'calc(100% - ' +
411
- (showRowsGrouping
412
- ? headerRowHeight + footerRowHeight
413
- : footerRowHeight) +
414
- 'px)'
415
- "
416
- >
417
- <div
418
- class="h-100"
419
- [style.width]="
420
- !showSideMenu
421
- ? '100%'
422
- : sideMenuVisible
423
- ? 'calc(100% - 280px)'
424
- : 'calc(100% - 30px)'
425
- "
426
- >
427
- <div class="h-100 transition position-relative w-100">
428
- <!-- ##################################################################################################################################################################################### -->
429
- <!-- ##################################################################################################################################################################################### -->
430
- <!-- Data Grid Header starts here -->
431
- <!-- ##################################################################################################################################################################################### -->
432
- <!-- ##################################################################################################################################################################################### -->
433
-
434
- <div
435
- class="data-grid-header-wrapper w-100"
436
- [style.color]="headerTextColor"
437
- [style.fontSize.px]="headerTextFontsSize"
438
- [style.backgroundColor]="headerBackgroundColor"
439
- [class.border-below]="!hasAnyVisibleColumn"
440
- [style.height.px]="
441
- showColumnsGrouping && showFilterRow
442
- ? headerRowHeight * 3
443
- : showColumnsGrouping || showFilterRow
444
- ? headerRowHeight * 2
445
- : headerRowHeight
446
- "
447
- >
448
- <!-- ********************************************************************************* -->
449
- <!-- ********************************************************************************* -->
450
- <!-- Data Grid Left Pinned Header starts here -->
451
- <!-- ********************************************************************************* -->
452
- <!-- ********************************************************************************* -->
453
- <div class="data-grid-header left-pinned" #leftPinnedHeader>
454
- <div
455
- *ngIf="showSerialNumber"
456
- [style.backgroundColor]="checkboxesBackgroundColor"
457
- class="select-all-checkbox-cell border-below"
458
- [style.width.px]="65"
459
- [style.height.px]="
460
- showColumnsGrouping && showFilterRow
461
- ? headerRowHeight * 3
462
- : showColumnsGrouping || showFilterRow
463
- ? headerRowHeight * 2
464
- : headerRowHeight
465
- "
466
- ></div>
467
- <div
468
- [style.backgroundColor]="checkboxesBackgroundColor"
469
- class="select-all-checkbox-cell border-below"
470
- [style.height.px]="
471
- showColumnsGrouping && showFilterRow
472
- ? headerRowHeight * 3
473
- : showColumnsGrouping || showFilterRow
474
- ? headerRowHeight * 2
475
- : headerRowHeight
476
- "
477
- >
478
- <input
479
- *ngIf="hasAnyVisibleColumn"
480
- type="checkbox"
481
- [indeterminate]="isIndeterminateState(dataSet)"
482
- [checked]="isAllSelected(dataSet)"
483
- (change)="toggleSelectAll(dataSet)"
484
- />
485
- </div>
486
- <div
487
- class="d-flex"
488
- cdkDropList
489
- id="left-pinned-header"
490
- cdkDropListOrientation="horizontal"
491
- [cdkDropListData]="leftPinnedColumns"
492
- (cdkDropListEntered)="onDropListEnter($event, 'left')"
493
- (cdkDropListSorted)="
494
- onSortGroup($event, 'previewLeftPinnedColumns')
495
- "
496
- (cdkDropListDropped)="onDropGroup()"
497
- style="min-width: 0.2px"
498
- [style.background-color]="headerBackgroundColor"
499
- >
500
- <div
501
- class="dragable-header"
502
- cdkDrag
503
- [cdkDragData]="col"
504
- *ngFor="
505
- let col of leftPinnedColumns;
506
- let i = index;
507
- trackBy: trackByField
508
- "
509
- >
510
- <ng-container
511
- *ngTemplateOutlet="
512
- headerCell;
513
- context: {
514
- $implicit: col,
515
- index: i,
516
- section: 'previewLeftPinnedColumns'
517
- }
518
- "
519
- ></ng-container>
520
- <ng-template cdkDragPreview
521
- ><div class="p-2 border d-flex gap-2">
522
- <div>
523
- <span
524
- [inlineSVG]="
525
- singleSpaAssetsPath +
526
- 'data-grid/icons/arrows-move.svg'
527
- "
528
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
529
- ></span>
530
- </div>
531
- <div>{{ col.header }}</div>
532
- </div>
533
- </ng-template>
534
- <ng-template cdkDragPlaceholder>
535
- <div *ngIf="!draggingInGroupArea">
536
- <div
537
- *ngTemplateOutlet="
538
- headerCell;
539
- context: {
540
- $implicit: col,
541
- index: i,
542
- section: ''
543
- }
544
- "
545
- ></div>
546
- </div>
547
- <div
548
- *ngIf="draggingInGroupArea"
549
- class="d-flex gap-2 ms-2"
550
- style="opacity: 0.6"
551
- >
552
- <ng-container
553
- *ngIf="col?.children?.length; else singleCol"
554
- >
555
- <ng-container
556
- *ngFor="
557
- let child of col.children;
558
- let i = index;
559
- trackBy: trackByField
560
- "
561
- >
562
- <ng-container
563
- *ngTemplateOutlet="
564
- topGroupingRowPlaceholder;
565
- context: {
566
- $implicit: child,
567
- showChevron:
568
- col.children.length > 1 &&
569
- i != col.children.length - 1
570
- }
571
- "
572
- ></ng-container>
573
- </ng-container>
574
- </ng-container>
575
-
576
- <ng-template #singleCol>
577
- <ng-container
578
- *ngTemplateOutlet="
579
- topGroupingRowPlaceholder;
580
- context: {
581
- $implicit: col,
582
- showChevron: col?.children?.length > 1
583
- }
584
- "
585
- ></ng-container>
586
- </ng-template>
587
- </div>
588
- </ng-template>
589
- </div>
590
- </div>
591
- </div>
592
-
593
- <!-- ********************************************************************************* -->
594
- <!-- ********************************************************************************* -->
595
- <!-- Data Grid Center Pinned Header starts here -->
596
- <!-- ********************************************************************************* -->
597
- <!-- ********************************************************************************* -->
598
- <div
599
- class="data-grid-header center-scrollable"
600
- #centerPinnedHeader
601
- (scroll)="onCenterHeaderScroll($event)"
602
- id="center-pinned-header"
603
- cdkDropList
604
- [cdkDropListConnectedTo]="
605
- showRowsGrouping ? ['rows-grouping-top-container'] : []
606
- "
607
- [cdkDropListData]="centerColumns"
608
- cdkDropListOrientation="horizontal"
609
- [cdkDropListSortingDisabled]="
610
- isDisableColumnGrouping && draggingInGroupArea
611
- "
612
- (cdkDropListEntered)="onDropListEnter($event, 'center')"
613
- (cdkDropListSorted)="onSortGroup($event, 'previewCenterColumns')"
614
- (cdkDropListDropped)="onDropGroup()"
615
- [style.maxWidth]="
616
- 'calc(100% - ' +
617
- (rightPinnedHeader.offsetWidth + leftPinnedHeader.offsetWidth) +
618
- 'px)'
619
- "
620
- >
621
- <div
622
- *ngIf="groupedColumns?.length"
623
- style="min-width: 200px"
624
- class="h-100 align-items-center"
625
- #columnsGroupedBox
626
- id="groupBoxHeaderDiv"
627
- >
628
- <div
629
- class="d-flex w-100 justify-content-between align-items-center border-below"
630
- [style.height.px]="
631
- showFilterRow ? headerRowHeight * 2 : headerRowHeight
632
- "
633
- >
634
- <div class="ps-3">Group</div>
635
- <div class="d-flex">
636
- <div
637
- class="three-dots cursor-pointer"
638
- (click)="openThreeDotsMenu($event, 'group')"
639
- >
640
- <span
641
- [inlineSVG]="
642
- singleSpaAssetsPath +
643
- 'data-grid/icons/three-dots-vertical.svg'
644
- "
645
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
646
- ></span>
647
- </div>
648
- <div
649
- (mousedown)="onResizeGroupBox($event)"
650
- class="resize-handle"
651
- style="margin-right: -2px"
652
- >
653
- <span
654
- [inlineSVG]="
655
- singleSpaAssetsPath +
656
- 'data-grid/icons/resize-handle.svg'
657
- "
658
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
659
- ></span>
660
- </div>
661
- </div>
662
- </div>
663
-
664
- <div
665
- [style.height.px]="headerRowHeight"
666
- class="border-below"
667
- ></div>
668
- </div>
669
- <span
670
- class="d-flex align-items-center justify-content-center cursor-pointer border-below"
671
- style="min-width: 30px; height: 100%"
672
- *ngIf="gridType === 'Assets'"
673
- >
674
- </span>
675
- <div
676
- class="dragable-header"
677
- (cdkDragStarted)="
678
- checkColumnGroupingStatus(col); dragStartOnGroup(col)
679
- "
680
- cdkDrag
681
- [cdkDragData]="col"
682
- *ngFor="
683
- let col of centerColumns;
684
- let i = index;
685
- trackBy: trackById
686
- "
687
- >
688
- <ng-container
689
- *ngTemplateOutlet="
690
- headerCell;
691
- context: {
692
- $implicit: col,
693
- index: i,
694
- section: 'previewCenterColumns'
695
- }
696
- "
697
- >
698
- </ng-container>
699
- <ng-template cdkDragPreview
700
- ><div class="p-2 border d-flex gap-2">
701
- <div>
702
- <span
703
- [inlineSVG]="
704
- singleSpaAssetsPath +
705
- 'data-grid/icons/arrows-move.svg'
706
- "
707
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
708
- ></span>
709
- </div>
710
- <div>{{ col.header }}</div>
711
- </div>
712
- </ng-template>
713
- <ng-template cdkDragPlaceholder>
714
- <div *ngIf="!draggingInGroupArea">
715
- <div
716
- *ngTemplateOutlet="
717
- headerCell;
718
- context: {
719
- $implicit: col,
720
- index: i,
721
- section: 'centerColumns'
722
- }
723
- "
724
- ></div>
725
- </div>
726
- <div
727
- *ngIf="draggingInGroupArea"
728
- class="d-flex gap-2 ms-2"
729
- style="opacity: 0.6"
730
- >
731
- <ng-container *ngIf="col?.children?.length; else singleCol">
732
- <ng-container
733
- *ngFor="
734
- let child of col.children;
735
- let i = index;
736
- trackBy: trackById
737
- "
738
- >
739
- <ng-container *ngIf="child?.isGroupable">
740
- <ng-container
741
- *ngTemplateOutlet="
742
- topGroupingRowPlaceholder;
743
- context: {
744
- $implicit: child,
745
- showChevron:
746
- col.children.length > 1 &&
747
- i != col.children.length - 1
748
- }
749
- "
750
- ></ng-container>
751
- </ng-container>
752
- </ng-container>
753
- </ng-container>
754
-
755
- <ng-template #singleCol>
756
- <ng-container *ngIf="col?.isGroupable">
757
- <ng-container
758
- *ngTemplateOutlet="
759
- topGroupingRowPlaceholder;
760
- context: {
761
- $implicit: col,
762
- showChevron: col?.children?.length > 1
763
- }
764
- "
765
- ></ng-container>
766
- </ng-container>
767
- </ng-template>
768
- </div>
769
- </ng-template>
770
- </div>
771
- </div>
772
-
773
- <!-- ********************************************************************************* -->
774
- <!-- ********************************************************************************* -->
775
- <!-- Data Grid Right Pinned Header starts here -->
776
- <!-- ********************************************************************************* -->
777
- <!-- ********************************************************************************* -->
778
- <div
779
- cdkDropList
780
- id="right-pinned-header"
781
- [cdkDropListConnectedTo]="
782
- showRowsGrouping ? ['rows-grouping-top-container'] : []
783
- "
784
- cdkDropListOrientation="horizontal"
785
- class="data-grid-header right-pinned"
786
- (cdkDropListSorted)="
787
- onSortGroup($event, 'previewRightPinnedColumns')
788
- "
789
- (cdkDropListEntered)="onDropListEnter($event, 'right')"
790
- (cdkDropListDropped)="onDropGroup()"
791
- #rightPinnedHeader
792
- class="right-pinned-header d-flex"
793
- style="min-width: 0.2px"
794
- >
795
- <div
796
- class="dragable-header"
797
- cdkDrag
798
- [cdkDragData]="col"
799
- *ngFor="
800
- let col of rightPinnedColumns;
801
- let i = index;
802
- trackBy: trackById
803
- "
804
- >
805
- <ng-container
806
- *ngTemplateOutlet="
807
- headerCell;
808
- context: {
809
- $implicit: col,
810
- pinnedRight: true,
811
- index: i,
812
- section: 'previewRightPinnedColumns'
813
- }
814
- "
815
- ></ng-container>
816
- <ng-template cdkDragPreview
817
- ><div class="p-2 border d-flex gap-2">
818
- <div>
819
- <span
820
- [inlineSVG]="
821
- singleSpaAssetsPath +
822
- 'data-grid/icons/arrows-move.svg'
823
- "
824
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
825
- ></span>
826
- </div>
827
- <div>{{ col.header }}</div>
828
- </div>
829
- </ng-template>
830
- <ng-template cdkDragPlaceholder>
831
- <div *ngIf="!draggingInGroupArea">
832
- <div
833
- *ngTemplateOutlet="
834
- headerCell;
835
- context: {
836
- $implicit: col,
837
- index: i,
838
- section: 'centerColumns'
839
- }
840
- "
841
- ></div>
842
- </div>
843
- <div
844
- *ngIf="draggingInGroupArea"
845
- class="d-flex gap-2 ms-2"
846
- style="opacity: 0.6"
847
- >
848
- <ng-container *ngIf="col?.children?.length; else singleCol">
849
- <ng-container
850
- *ngFor="
851
- let child of col.children;
852
- let i = index;
853
- trackBy: trackById
854
- "
855
- >
856
- <ng-container
857
- *ngTemplateOutlet="
858
- topGroupingRowPlaceholder;
859
- context: {
860
- $implicit: child,
861
- showChevron:
862
- col.children.length > 1 &&
863
- i != col.children.length - 1
864
- }
865
- "
866
- ></ng-container>
867
- </ng-container>
868
- </ng-container>
869
-
870
- <ng-template #singleCol>
871
- <ng-container
872
- *ngTemplateOutlet="
873
- topGroupingRowPlaceholder;
874
- context: {
875
- $implicit: col,
876
- showChevron: col?.children?.length > 1
877
- }
878
- "
879
- ></ng-container>
880
- </ng-template>
881
- </div>
882
- </ng-template>
883
- </div>
884
- </div>
885
- </div>
886
-
887
- <!--########################################################################################################################################################################################################################### -->
888
- <!--########################################################################################################################################################################################################################### -->
889
- <!-- Data Grid Body starts here -->
890
- <!--########################################################################################################################################################################################################################### -->
891
- <!--########################################################################################################################################################################################################################### -->
892
- <div
893
- class="h-100 d-flex justify-content-center align-items-center"
894
- *ngIf="!dataSet.length && !loading"
895
- >
896
- No Record Found
897
- </div>
898
-
899
- <div
900
- class="position-absolute w-100 h-100 d-flex justify-content-center align-items-center loading-overlay"
901
- *ngIf="loading"
902
- style="
903
- z-index: 999;
904
- background: rgba(255, 255, 255, 0.8);
905
- backdrop-filter: blur(1px);
906
- "
907
- >
908
- <div class="spinner-border text-primary" role="status">
909
- <!-- <span class="visually-hidden">Loading...</span> -->
910
- </div>
911
- </div>
912
-
913
- <div
914
- class="data-grid-body-wrapper position-relative d-flex"
915
- [style.height]="bodyWrapperHeight"
916
- style="overflow-y: auto; overflow-x: hidden"
917
- #mainScroll
918
- (scroll)="onMainScroll($event)"
919
- *ngIf="dataSet.length"
920
- [style.scrollbarWidth]="verticalScrollbarWidth"
921
- >
922
- <!-- LEFT PINNED -->
923
- <div
924
- [style.height.px]="
925
- !groupedColumns.length ? originalDataSet.length * rowHeight : 0
926
- "
927
- ></div>
928
- <div [class.h-100]="originalDataSet.length < 8">
929
- <div
930
- class="data-grid-body left-pinned-body w-100"
931
- style="overflow-y: hidden"
932
- [class.border-right]="hasLeftPinnedColumns"
933
- [class.transparent-border-right]="!hasLeftPinnedColumns"
934
- [style.transform]="
935
- 'translateY(' + startIndex * rowHeight + 'px)'
936
- "
937
- >
938
- <ng-container
939
- *ngFor="
940
- let row of visibleRows;
941
- let i = index;
942
- trackBy: trackById
943
- "
944
- >
945
- <ng-container
946
- *ngTemplateOutlet="
947
- rowCell;
948
- context: {
949
- $implicit: row,
950
- columns: previewLeftPinnedColumns,
951
- isEven: (startIndex + i) % 2 === 0,
952
- isOdd: (startIndex + i) % 2 !== 0,
953
- isLeft: true,
954
- section: 'left',
955
- isTotalRow: false
956
- }
957
- "
958
- ></ng-container>
959
- </ng-container>
960
- <ng-container *ngIf="showTotalAmountRow">
961
- <ng-container
962
- *ngTemplateOutlet="
963
- rowCell;
964
- context: {
965
- $implicit: { __virtualIndex: 0 },
966
- columns: previewLeftPinnedColumns,
967
- isEven: false,
968
- isOdd: false,
969
- section: 'left',
970
- isTotalRow: true
971
- }
972
- "
973
- ></ng-container>
974
- </ng-container>
975
- </div>
976
- </div>
977
-
978
- <!-- CENTER -->
979
- <div
980
- class="h-100"
981
- [style.width.px]="centerPinnedHeader.clientWidth"
982
- >
983
- <div
984
- class="data-grid-body center-scrollable"
985
- [class.h-100]="
986
- originalDataSet.length < 8 && gridType !== 'Assets'
987
- "
988
- style="overflow-y: hidden; overflow-x: auto"
989
- [style.transform]="
990
- 'translateY(' + startIndex * rowHeight + 'px)'
991
- "
992
- [style.backgroundColor]="bodyBackgroundColor"
993
- #centerScrollableBody
994
- (scroll)="onCenterBodyScroll($event)"
995
- [style.boxShadow]="leftPinnedBoxshadow"
996
- >
997
- <ng-container
998
- *ngFor="
999
- let row of visibleRows;
1000
- let i = index;
1001
- trackBy: trackById
1002
- "
1003
- >
1004
- <ng-container
1005
- *ngTemplateOutlet="
1006
- rowCell;
1007
- context: {
1008
- $implicit: row,
1009
- columns: previewCenterColumns,
1010
- isEven: (startIndex + i) % 2 === 0,
1011
- isOdd: (startIndex + i) % 2 !== 0,
1012
- section: 'center',
1013
- isTotalRow: false
1014
- }
1015
- "
1016
- ></ng-container>
1017
- </ng-container>
1018
- <ng-container *ngIf="showTotalAmountRow">
1019
- <ng-container
1020
- *ngTemplateOutlet="
1021
- rowCell;
1022
- context: {
1023
- $implicit: { __virtualIndex: 0 },
1024
- columns: previewCenterColumns,
1025
- isEven: false,
1026
- isOdd: false,
1027
- section: 'center',
1028
- isTotalRow: true
1029
- }
1030
- "
1031
- ></ng-container>
1032
- </ng-container>
1033
- </div>
1034
- </div>
1035
-
1036
- <!-- RIGHT PINNED -->
1037
- <div
1038
- class="right-pinned-body-wrapper"
1039
- *ngIf="hasRightPinnedColumns"
1040
- [class.h-100]="
1041
- originalDataSet.length < 8 && gridType !== 'Assets'
1042
- "
1043
- [style.max-width.px]="
1044
- isScrollbarVisible
1045
- ? rightPinnedHeader.offsetWidth - 15
1046
- : rightPinnedHeader.offsetWidth
1047
- "
1048
- >
1049
- <div
1050
- class="data-grid-body right-pinned-body w-100 h-100"
1051
- style="overflow-y: hidden"
1052
- [style.transform]="
1053
- 'translateY(' + startIndex * rowHeight + 'px)'
1054
- "
1055
- [style.boxShadow]="rightPinnedBoxshadow"
1056
- >
1057
- <ng-container
1058
- *ngFor="
1059
- let row of visibleRows;
1060
- let i = index;
1061
- trackBy: trackById
1062
- "
1063
- >
1064
- <ng-container
1065
- *ngTemplateOutlet="
1066
- rowCell;
1067
- context: {
1068
- $implicit: row,
1069
- columns: previewRightPinnedColumns,
1070
- isEven: (startIndex + i) % 2 === 0,
1071
- isOdd: (startIndex + i) % 2 !== 0,
1072
- section: 'right',
1073
- isTotalRow: false
1074
- }
1075
- "
1076
- ></ng-container>
1077
- </ng-container>
1078
- <ng-container *ngIf="showTotalAmountRow">
1079
- <ng-container
1080
- *ngTemplateOutlet="
1081
- rowCell;
1082
- context: {
1083
- $implicit: { __virtualIndex: 0 },
1084
- columns: previewRightPinnedColumns,
1085
- isEven: false,
1086
- isOdd: false,
1087
- section: 'right',
1088
- isTotalRow: true
1089
- }
1090
- "
1091
- ></ng-container>
1092
- </ng-container>
1093
- </div>
1094
- </div>
1095
- </div>
1096
- <!-- Vertical Fake scroll Bar -->
1097
- <div
1098
- (scroll)="onMainFakeScroll($event)"
1099
- class="fake-scrollbar fake-scrollbar-vertical d-none"
1100
- [style.scrollbarWidth]="verticalScrollbarWidth"
1101
- [style.top.px]="
1102
- showColumnsGrouping && showFilterRow
1103
- ? headerRowHeight * 3
1104
- : showColumnsGrouping || showFilterRow
1105
- ? headerRowHeight * 2
1106
- : headerRowHeight
1107
- "
1108
- #fakeScroll
1109
- [style.height]="bodyWrapperHeight"
1110
- style="
1111
- overflow-y: auto;
1112
- overflow-x: hidden;
1113
- width: 17px;
1114
- position: absolute;
1115
- right: 0;
1116
- background-color: f1f2f3;
1117
- z-index: 10;
1118
- "
1119
- >
1120
- <div [style.height.px]="rowHeight * dataSetLength"></div>
1121
- </div>
1122
- </div>
1123
-
1124
- <!-- Horizintal Fake Scrollbars -->
1125
- <div class="d-flex justify-content-between" *ngIf="dataSet.length">
1126
- <div
1127
- [style.scrollbarWidth]="horizintalScrollbarWidth"
1128
- class="fake-horizintal-scrollbar"
1129
- #fakeScroll
1130
- [style.width.px]="leftPinnedHeader.offsetWidth"
1131
- style="overflow-x: scroll"
1132
- ></div>
1133
- <div
1134
- [style.scrollbarWidth]="horizintalScrollbarWidth"
1135
- (scroll)="onHorizintalFakeScroll($event)"
1136
- class="fake-horizintal-scrollbar"
1137
- #horizintalFakeScroll
1138
- [style.width.px]="centerPinnedHeader.offsetWidth"
1139
- >
1140
- <div [style.width.px]="centerPinnedHeader.scrollWidth"></div>
1141
- </div>
1142
- <div
1143
- [style.scrollbarWidth]="horizintalScrollbarWidth"
1144
- class="fake-horizintal-scrollbar"
1145
- #fakeScroll
1146
- [style.width.px]="rightPinnedHeader.offsetWidth"
1147
- style="overflow-x: scroll"
1148
- ></div>
1149
- </div>
1150
- </div>
1151
-
1152
- <!-- Side Menu Implemented Here -->
1153
- <div
1154
- *ngIf="showSideMenu"
1155
- [style.width.px]="sideMenuVisible ? 280 : 30"
1156
- class="right-menu h-100"
1157
- [style.backgroundColor]="sidemenuBackgroundColor"
1158
- >
1159
- <div class="h-100 d-flex flex-row-reverse">
1160
- <div
1161
- style="width: 30px"
1162
- class="d-flex flex-column align-items-center cursor-pointer"
1163
- [class.border-start]="sideMenuVisible"
1164
- >
1165
- <div
1166
- (click)="toggleSideMenu('cols')"
1167
- [class.bg-fff]="
1168
- currentOpenedSideMenue == 'cols' && sideMenuVisible
1169
- "
1170
- [class.border-below]="sideMenuVisible"
1171
- class="columns-button d-flex flex-column align-items-center"
1172
- >
1173
- <div>
1174
- <span
1175
- [inlineSVG]="
1176
- singleSpaAssetsPath + 'data-grid/icons/ui-checks-grid.svg'
1177
- "
1178
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1179
- ></span>
1180
- </div>
1181
- <div class="side-menue-text">Columns</div>
1182
- </div>
1183
-
1184
- <div
1185
- (click)="toggleSideMenu('filtrs')"
1186
- [class.bg-fff]="
1187
- currentOpenedSideMenue == 'filtrs' && sideMenuVisible
1188
- "
1189
- [class.border-below]="
1190
- sideMenuVisible && currentOpenedSideMenue == 'filtrs'
1191
- "
1192
- class="columns-button d-flex flex-column align-items-center"
1193
- >
1194
- <div>
1195
- <span
1196
- [inlineSVG]="
1197
- singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'
1198
- "
1199
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1200
- ></span>
1201
- </div>
1202
- <div class="side-menue-text">Filter</div>
1203
- </div>
1204
- </div>
1205
- <div
1206
- class="h-100"
1207
- *ngIf="sideMenuVisible"
1208
- [ngStyle]="{ width: sideMenuVisible ? '250px' : '' }"
1209
- >
1210
- <div class="h-100">
1211
- <ng-container
1212
- *ngIf="currentOpenedSideMenue == 'cols' && sideMenuVisible"
1213
- >
1214
- <ng-container *ngTemplateOutlet="columnPannel"></ng-container>
1215
- <!-- Column Items -->
1216
- <div class="column-panel-body px-3">
1217
- <ng-container
1218
- *ngFor="let col of columns; trackBy: trackByField"
1219
- >
1220
- <ng-container
1221
- *ngTemplateOutlet="columnPanelItem; context: { col: col }"
1222
- ></ng-container>
1223
- </ng-container>
1224
- </div>
1225
- <hr />
1226
-
1227
- <div class="side-menu-row-groups" style="height: 30%">
1228
- <ng-container
1229
- *ngTemplateOutlet="sideMenuRowGroups"
1230
- ></ng-container>
1231
- </div>
1232
- </ng-container>
1233
- <ng-container
1234
- *ngIf="currentOpenedSideMenue == 'filtrs' && sideMenuVisible"
1235
- >
1236
- <ng-container *ngTemplateOutlet="sideFilters"></ng-container>
1237
- </ng-container>
1238
- </div>
1239
- </div>
1240
- </div>
1241
- </div>
1242
- </div>
1243
- <div [style.height.px]="footerRowHeight" class="border-top">
1244
- <!-- Rows: <span class="fw-500 ms-1">{{ dataSet.length }}</span> -->
1245
-
1246
- <div
1247
- class="pagination-container"
1248
- [style.height.px]="footerRowHeight"
1249
- [style.padding.px]="footerPadding"
1250
- >
1251
- <div class="page-size">
1252
- <select
1253
- [(ngModel)]="paginationConfig.limit"
1254
- (change)="onPageSizeChange()"
1255
- >
1256
- <option *ngFor="let size of pageSizeOptions" [value]="size">
1257
- {{ size }}
1258
- </option>
1259
- </select>
1260
- <span class="separator"> per page </span>
1261
- </div>
1262
-
1263
- <div class="page-info">
1264
- Results: {{( (paginationConfig.page -1 )* paginationConfig.limit)+1}}-{{
1265
- paginationConfig.page * paginationConfig.limit
1266
- }}
1267
- of
1268
- {{ paginationConfig.totalResults }}
1269
- </div>
1270
-
1271
- <div class="page-buttons">
1272
- <button
1273
- (click)="goToPage(paginationConfig.page - 1)"
1274
- [disabled]="paginationConfig.page === 1"
1275
- >
1276
-
1277
- </button>
1278
-
1279
- <ng-container *ngFor="let page of visiblePages">
1280
- <button
1281
- *ngIf="page !== '...'"
1282
- (click)="goToPage(page)"
1283
- [class.active]="page === paginationConfig.page"
1284
- >
1285
- {{ page }}
1286
- </button>
1287
- <span *ngIf="page === '...'">...</span>
1288
- </ng-container>
1289
-
1290
- <button
1291
- (click)="goToPage(paginationConfig.page + 1)"
1292
- [disabled]="paginationConfig.page === paginationConfig.totalResults"
1293
- >
1294
-
1295
- </button>
1296
- </div>
1297
- </div>
1298
- </div>
1299
- </div>
1300
- </div>
1301
-
1302
- <!-- ------------------------------------------------------------------------------------------------------------------------ -->
1303
- <!-- ------------------------------------------------------------------------------------------------------------------------ -->
1304
- <!-- Header Cell Template -->
1305
- <!-- ------------------------------------------------------------------------------------------------------------------------ -->
1306
- <!-- ------------------------------------------------------------------------------------------------------------------------ -->
1307
-
1308
- <ng-template
1309
- #headerCell
1310
- let-col
1311
- let-pinnedRight="pinnedRight"
1312
- let-i="index"
1313
- let-sections="section"
1314
- let-calledFromNestedPlaceholder="calledFromNestedPlaceholder"
1315
- >
1316
- <div>
1317
- <!-- Group Header -->
1318
- <ng-container *ngIf="col.children?.length > 0; else flatHeader">
1319
- <div cdkDroplistGroup class="group-column-wrapper">
1320
- <!-- Parent Header -->
1321
- <div
1322
- *ngIf="shouldTheGroupHeaderShow(col)"
1323
- class="header-cell group-header"
1324
- [style.height.px]="headerRowHeight"
1325
- [style.min-height.px]="headerRowHeight"
1326
- [style.max-height.px]="headerRowHeight"
1327
- [class.border-right]="showVerticalBorder"
1328
- [style.gridColumn]="'span ' + col.children.length"
1329
- [style.fontWeight]="headerFontWeight"
1330
- [class.flex-row-reverse]="pinnedRight"
1331
- [class.justify-content-end]="pinnedRight"
1332
- style="grid-row: 1"
1333
- >
1334
- <div
1335
- class="group-header-content"
1336
- [title]="col.header"
1337
- [class.ms-2]="pinnedRight"
1338
- >
1339
- {{ col.header }}
1340
- </div>
1341
- <div
1342
- class="resize-handle"
1343
- (dblclick)="autosizeColumn(col.children)"
1344
- (mousedown)="onResizeGroup($event, col, pinnedRight)"
1345
- >
1346
- <span
1347
- [inlineSVG]="
1348
- singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'
1349
- "
1350
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1351
- ></span>
1352
- </div>
1353
- </div>
1354
-
1355
- <!-- Child Headers and Filters -->
1356
-
1357
- <div
1358
- class="d-flex"
1359
- cdkDropList
1360
- cdkDropListOrientation="horizontal"
1361
- [cdkDropListData]="col.children"
1362
- (cdkDropListSorted)="onChildDroplistSorted($event, sections)"
1363
- (cdkDropListDropped)="onChildDroplistDroped($event)"
1364
- [cdkDropListSortingDisabled]="false"
1365
- [cdkDropListConnectedTo]="
1366
- showRowsGrouping ? ['rows-grouping-top-container'] : []
1367
- "
1368
- >
1369
- <div
1370
- cdkDrag
1371
- [cdkDragData]="child"
1372
- *ngFor="let child of col.children; let i = index"
1373
- >
1374
- <!-- Child Header -->
1375
- <ng-container *ngIf="child.is_visible && !child['isRowGrouped']">
1376
- <div
1377
- cdkDragHandle
1378
- class="header-cell one-row-header-cells cursor-pointer"
1379
- [class.border-right]="showVerticalBorder"
1380
- [attr.field]="child.field"
1381
- [style.width.px]="child.width"
1382
- [style.min-width.px]="child.width"
1383
- [style.min-height.px]="headerRowHeight"
1384
- [style.max-height.px]="headerRowHeight"
1385
- [style.fontWeight]="headerFontWeight"
1386
- style="grid-row: 2"
1387
- [class.filter-applied-on-text]="isFilterAppliedOnColumn(child)"
1388
- >
1389
- <div
1390
- class="d-flex justify-content-between h-100 align-items-center w-100"
1391
- >
1392
- <div
1393
- class="d-flex justify-content-between align-items-center w-100"
1394
- [class.flex-row-reverse]="pinnedRight"
1395
- >
1396
- <div
1397
- class="text-ellipsis h-100 d-flex align-items-center w-100"
1398
- [title]="col.header"
1399
- [class.w-100]="pinnedRight"
1400
- >
1401
- <div
1402
- class="text-ellipsis h-100 "
1403
- [class.editable-header]="child?.is_editable"
1404
- (click)="
1405
- openThreeDotsMenu($event, child);
1406
- openFilteronThreeDotsClick(child)
1407
- "
1408
- >
1409
- {{ child.header }}
1410
- </div>
1411
- </div>
1412
-
1413
- <div
1414
- class="position-relative d-flex"
1415
- [class.flex-row-reverse]="pinnedRight"
1416
- >
1417
- <div
1418
- [class.me-2]="pinnedRight"
1419
- class="d-flex align-items-center"
1420
- *ngIf="child.pinned"
1421
- >
1422
- <span
1423
- [inlineSVG]="
1424
- singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'
1425
- "
1426
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1427
- ></span>
1428
- </div>
1429
- <div
1430
- class="three-dots p-1"
1431
- (click)="openThreeDotsMenu($event, child)"
1432
- style="cursor: pointer"
1433
- >
1434
- <span
1435
- [inlineSVG]="
1436
- singleSpaAssetsPath +
1437
- 'data-grid/icons/three-dots-vertical.svg'
1438
- "
1439
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1440
- ></span>
1441
- </div>
1442
-
1443
- <!-- Only show menu if this column is active -->
1444
- <div
1445
- class="position-absolute"
1446
- *ngIf="activeCol === child"
1447
- style="top: -50%; z-index: 21"
1448
- [style.left.px]="
1449
- -(!child?.pinned ? centerPinnedHeader.scrollLeft : 0)
1450
- "
1451
- >
1452
- <ng-container
1453
- *ngTemplateOutlet="
1454
- columnMenu;
1455
- context: { col: child }
1456
- "
1457
- ></ng-container>
1458
- </div>
1459
-
1460
- <div
1461
- class="resize-handle"
1462
- (dblclick)="autosizeColumn(child)"
1463
- (mousedown)="onResizeColumn($event, child)"
1464
- >
1465
- <span
1466
- [inlineSVG]="
1467
- singleSpaAssetsPath +
1468
- 'data-grid/icons/resize-handle.svg'
1469
- "
1470
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1471
- ></span>
1472
- </div>
1473
- </div>
1474
- </div>
1475
- </div>
1476
- </div>
1477
-
1478
- <!-- Filter Cell -->
1479
- <div
1480
- *ngIf="showFilterRow"
1481
- [style.backgroundColor]="headerBackgroundColor"
1482
- class="header-cell filter-cell"
1483
- [class.border-right]="showVerticalBorder"
1484
- [attr.field]="child.field"
1485
- [style.width.px]="child.width"
1486
- [style.min-width.px]="child.width"
1487
- [style.height.px]="headerRowHeight"
1488
- [style.min-height.px]="headerRowHeight"
1489
- [style.max-height.px]="headerRowHeight"
1490
- [class.border-right]="showVerticalBorder"
1491
- style="grid-row: 3"
1492
- >
1493
- <div
1494
- class="header-cell filter-cell"
1495
- [attr.field]="col.field"
1496
- [style.width.px]="col.width"
1497
- [style.min-width.px]="col.width"
1498
- [style.height.px]="headerRowHeight"
1499
- [style.min-height.px]="headerRowHeight"
1500
- [style.max-height.px]="headerRowHeight"
1501
- >
1502
- <input
1503
- type="text"
1504
- class="form-control form-control-sm"
1505
- placeholder="Filter"
1506
- [(ngModel)]="col.filterValue"
1507
- (ngModelChange)="onFilterChange(col)"
1508
- />
1509
- <span
1510
- class="filter-icon-wrapper"
1511
- (click)="$event.stopPropagation(); openFilter(child)"
1512
- [class.filter-applied]="isFilterAppliedOnColumn(child)"
1513
- ><span
1514
- [inlineSVG]="
1515
- singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'
1516
- "
1517
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1518
- ></span>
1519
- <span
1520
- *ngIf="isFilterAppliedOnColumn(child)"
1521
- style="
1522
- width: 7px;
1523
- height: 7px;
1524
- box-shadow: 0px 0px 3px #7486ff;
1525
- background-color: rgb(0 163 233);
1526
- position: absolute;
1527
- right: 4px;
1528
- top: 12px;
1529
- "
1530
- class="rounded-circle d-block"
1531
- ></span
1532
- ></span>
1533
-
1534
- <div
1535
- class="position-absolute filter-row-filter-wrapper"
1536
- *ngIf="activeFilterCell?.field == child?.field"
1537
- style="top: 100%; right: 0; z-index: 99"
1538
- [style.left.px]="
1539
- child?.pinned ? 0 : -centerPinnedHeader.scrollLeft
1540
- "
1541
- >
1542
- <ng-container
1543
- *ngTemplateOutlet="filterMenu; context: { col: child }"
1544
- ></ng-container>
1545
- </div>
1546
- </div>
1547
- </div>
1548
- </ng-container>
1549
- <ng-template cdkDragPreview
1550
- ><div class="p-2 border d-flex gap-2">
1551
- <div
1552
- *ngIf="
1553
- !draggingInGroupArea ||
1554
- (child.isGroupable && draggingInGroupArea)
1555
- "
1556
- >
1557
- <span
1558
- [inlineSVG]="
1559
- singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'
1560
- "
1561
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1562
- ></span>
1563
- </div>
1564
- <div *ngIf="draggingInGroupArea && !child.isGroupable">
1565
- <span
1566
- [inlineSVG]="
1567
- singleSpaAssetsPath + 'data-grid/icons/ban.svg'
1568
- "
1569
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1570
- ></span>
1571
- </div>
1572
- <div>{{ child.header }}</div>
1573
- </div>
1574
- </ng-template>
1575
- <ng-template cdkDragPlaceholder>
1576
- <div *ngIf="!draggingInGroupArea" class="position-relative">
1577
- <div
1578
- *ngTemplateOutlet="
1579
- childHeaderPlaceholder;
1580
- context: {
1581
- $implicit: child,
1582
- index: i,
1583
- sections: sections,
1584
- calledFromNestedPlaceholder: true,
1585
- }
1586
- "
1587
- ></div>
1588
- </div>
1589
- <div
1590
- *ngIf="draggingInGroupArea && child?.isGroupable"
1591
- class="d-flex gap-2 ms-2"
1592
- style="opacity: 0.6"
1593
- >
1594
- <ng-container
1595
- *ngTemplateOutlet="
1596
- topGroupingRowPlaceholder;
1597
- context: {
1598
- $implicit: child,
1599
- showChevron: false,
1600
- pinnedRight: pinnedRight,
1601
- sections: sections,
1602
- index: i
1603
- }
1604
- "
1605
- ></ng-container>
1606
- </div>
1607
- </ng-template>
1608
- </div>
1609
- </div>
1610
- </div>
1611
- </ng-container>
1612
-
1613
- <!-- Flat Header || Single Header Cell-->
1614
- <ng-template #flatHeader>
1615
- <div class="group-column-wrapper">
1616
- <!-- Full-height Header Cell (spans 2 rows visually) -->
1617
- <div
1618
- class="header-cell one-row-header-cells"
1619
- [attr.field]="col.field"
1620
- [style.width.px]="col.width"
1621
- [style.min-width.px]="col.width"
1622
- [class.border-right]="showVerticalBorder"
1623
- [style.min-height.px]="
1624
- showColumnsGrouping ? headerRowHeight * 2 : headerRowHeight
1625
- "
1626
- [style.height.px]="
1627
- showColumnsGrouping ? headerRowHeight * 2 : headerRowHeight
1628
- "
1629
- [style.fontWeight]="headerFontWeight"
1630
- style="grid-row: 1 / span 2"
1631
- >
1632
- <div
1633
- class="d-flex justify-content-between h-100 align-items-center w-100"
1634
- >
1635
- <div
1636
- class="d-flex justify-content-between w-100 align-items-center"
1637
- [class.flex-row-reverse]="pinnedRight"
1638
- >
1639
- <div
1640
- class="text-ellipsis h-100 d-flex align-items-center w-100"
1641
- [title]="col.header"
1642
- >
1643
- <div
1644
- class="text-ellipsis h-100 cursor-pointer"
1645
- [class.editable-header]="col?.is_editable"
1646
- [class.filter-applied-on-text]="isFilterAppliedOnColumn(col)"
1647
- (click)="
1648
- openThreeDotsMenu($event, col);
1649
- openFilteronThreeDotsClick(col)
1650
- "
1651
- >
1652
- {{ col.header }}
1653
- </div>
1654
- </div>
1655
-
1656
- <div
1657
- class="position-relative d-flex"
1658
- [class.flex-row-reverse]="pinnedRight"
1659
- >
1660
- <div
1661
- [class.me-2]="pinnedRight"
1662
- class="d-flex align-items-center"
1663
- *ngIf="col?.pinned"
1664
- >
1665
- <span
1666
- [inlineSVG]="
1667
- singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'
1668
- "
1669
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1670
- ></span>
1671
- </div>
1672
- <div
1673
- [class.me-2]="col.order_by"
1674
- class="d-flex align-items-center"
1675
- *ngIf="sortingConfig?.field == col.field"
1676
- >
1677
- <!-- Ascending Sort Icon -->
1678
- <span
1679
- *ngIf="sortingConfig?.order_by == 'asc'"
1680
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/sort-asc.svg'"
1681
- class="data-grid-svg-icon d-flex justify-content-center align-items-center mt-1 cursor-pointer"
1682
- (click)="sortDesc(col)"
1683
- [class.active]="sortingConfig?.order_by === 'asc'"
1684
- ></span>
1685
-
1686
- <!-- Descending Sort Icon -->
1687
- <span
1688
- *ngIf="sortingConfig?.order_by == 'desc'"
1689
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/sort-desc.svg'"
1690
- class="data-grid-svg-icon d-flex justify-content-center align-items-center mt-1 cursor-pointer"
1691
- (click)="sortAsc(col)"
1692
- [class.active]="sortingConfig?.order_by === 'desc'"
1693
- ></span>
1694
-
1695
- </div>
1696
- <div
1697
- class="three-dots p-1"
1698
- (click)="openThreeDotsMenu($event, col)"
1699
- style="cursor: pointer"
1700
- >
1701
- <span
1702
- [inlineSVG]="
1703
- singleSpaAssetsPath +
1704
- 'data-grid/icons/three-dots-vertical.svg'
1705
- "
1706
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1707
- ></span>
1708
- </div>
1709
-
1710
- <!-- Only show menu if this column is active -->
1711
- <div
1712
- class="position-absolute"
1713
- *ngIf="activeCol === col"
1714
- style="top: -50%; z-index: 21"
1715
- [style.left.px]="
1716
- -(!col?.pinned ? centerPinnedHeader.scrollLeft : 0)
1717
- "
1718
- >
1719
- <ng-container
1720
- *ngTemplateOutlet="columnMenu; context: { col: col }"
1721
- ></ng-container>
1722
- </div>
1723
-
1724
- <div
1725
- class="resize-handle"
1726
- [class.w-100]="col.pinned == 'right'"
1727
- (dblclick)="autosizeColumn(col)"
1728
- (mousedown)="onResizeColumn($event, col)"
1729
- >
1730
- <span
1731
- [inlineSVG]="
1732
- singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'
1733
- "
1734
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1735
- ></span>
1736
- </div>
1737
- </div>
1738
- </div>
1739
- </div>
1740
- </div>
1741
-
1742
- <!-- Filter Cell -->
1743
- <div
1744
- *ngIf="showFilterRow"
1745
- [style.backgroundColor]="headerBackgroundColor"
1746
- class="header-cell filter-cell"
1747
- [class.border-right]="showVerticalBorder"
1748
- [attr.field]="col.field"
1749
- [style.width.px]="col.width"
1750
- [style.min-width.px]="col.width"
1751
- [style.height.px]="headerRowHeight"
1752
- [style.min-height.px]="headerRowHeight"
1753
- [style.max-height.px]="headerRowHeight"
1754
- >
1755
- <input
1756
- type="text"
1757
- class="form-control form-control-sm"
1758
- placeholder="Filter"
1759
- [(ngModel)]="col.filterValue"
1760
- (ngModelChange)="onFilterChange(col)"
1761
- />
1762
- <span
1763
- class="filter-icon-wrapper"
1764
- (click)="$event.stopPropagation(); openFilter(col)"
1765
- [class.filter-applied]="isFilterAppliedOnColumn(col)"
1766
- ><span
1767
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'"
1768
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
1769
- ></span>
1770
- <span
1771
- *ngIf="isFilterAppliedOnColumn(col)"
1772
- style="
1773
- width: 7px;
1774
- height: 7px;
1775
- box-shadow: 0px 0px 3px #7486ff;
1776
- background-color: rgb(0 163 233);
1777
- position: absolute;
1778
- right: 4px;
1779
- top: 12px;
1780
- "
1781
- class="rounded-circle d-block"
1782
- ></span
1783
- ></span>
1784
-
1785
- <div
1786
- class="position-absolute filter-row-filter-wrapper"
1787
- *ngIf="activeFilterCell === col"
1788
- style="top: 100%; right: 0; z-index: 99"
1789
- [style.left.px]="col?.pinned ? 0 : -centerPinnedHeader.scrollLeft"
1790
- >
1791
- <ng-container
1792
- *ngTemplateOutlet="filterMenu; context: { col: col }"
1793
- ></ng-container>
1794
- </div>
1795
- </div>
1796
- </div>
1797
- </ng-template>
1798
- </div>
1799
- </ng-template>
1800
-
1801
- <!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->
1802
- <!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->
1803
- <!-- Body Cell Template -->
1804
- <!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->
1805
- <!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->
1806
-
1807
- <ng-template
1808
- #rowCell
1809
- let-row
1810
- let-columns="columns"
1811
- let-isEven="isEven"
1812
- let-isOdd="isOdd"
1813
- let-isLeftSection="isLeft"
1814
- let-section="section"
1815
- let-rowIndex="rowIndex"
1816
- let-isTotalRow="isTotalRow"
1817
- >
1818
- <!-- Check if row is a group -->
1819
- <ng-container
1820
- *ngTemplateOutlet="groupRowTemplate; context: { $implicit: row, depth: 0 }"
1821
- ></ng-container>
1822
- <ng-template #groupRowTemplate let-row let-depth="depth">
1823
- <ng-container *ngIf="row.isGroup; else regularRow">
1824
- <!-- Group Header -->
1825
- <div
1826
- class="group-header-row border-below d-flex align-items-center"
1827
- [style.height.px]="rowHeight"
1828
- [style.width]="
1829
- section == 'center'
1830
- ? centerScrollableBody?.nativeElement?.scrollWidth + 'px'
1831
- : '100%'
1832
- "
1833
- >
1834
- <div
1835
- *ngIf="section == 'left'"
1836
- class="h-100 d-flex"
1837
- [style.width.px]="leftPinnedHeader.offsetWidth - 1"
1838
- [class.row-selected]="rowSelectedIndexes.has(row.__virtualIndex)"
1839
- >
1840
- <div
1841
- *ngIf="showSerialNumber"
1842
- style="width: 50px"
1843
- class="d-flex align-items-center h-100 border-right justify-content-end pe-2 s-no"
1844
- [style.backgroundColor]="checkboxesBackgroundColor"
1845
- [style.width.px]="65"
1846
- [style.cursor]="
1847
- 'url(' +
1848
- singleSpaAssetsPath +
1849
- 'data-grid/icons/arrow-right.svg), auto'
1850
- "
1851
- (mousedown)="onRowMouseDown(row.__virtualIndex, $event)"
1852
- (mouseover)="onRowMouseOver(row.__virtualIndex, $event)"
1853
- >
1854
- {{ row.__virtualIndex }}
1855
- </div>
1856
- <div
1857
- style="width: 50px"
1858
- class="d-flex align-items-center justify-content-center h-100 border-right"
1859
- [style.backgroundColor]="checkboxesBackgroundColor"
1860
- [class.row-selected]="rowSelectedIndexes.has(row.__virtualIndex)"
1861
- [class.left-selection-border]="
1862
- rowSelectedIndexes.has(row.__virtualIndex)
1863
- "
1864
- [class.first-row-selected]="firstSelectedRow == row.__virtualIndex"
1865
- [class.last-row-selected]="lastSelectedRow == row.__virtualIndex"
1866
- >
1867
- <input style="width: 16px; height: 16px" type="checkbox" />
1868
- </div>
1869
- </div>
1870
-
1871
- <div
1872
- *ngIf="section == 'center'"
1873
- [style.width.px]="centerPinnedHeader.scrollWidth"
1874
- class="d-flex align-items-center ps-2 h-100"
1875
- [class.row-selected]="rowSelectedIndexes.has(row.__virtualIndex)"
1876
- [class.first-row-selected]="firstSelectedRow == row.__virtualIndex"
1877
- [class.last-row-selected]="lastSelectedRow == row.__virtualIndex"
1878
- >
1879
- <div
1880
- class="d-flex align-items-center justify-content-between"
1881
- [style.paddingLeft.px]="depth > 0 ? depth * 16 : 0"
1882
- >
1883
- <span class="me-2 filter-icon-wrapper" (click)="toggleExpand(row)">
1884
- <span
1885
- class="data-grid-svg-icon"
1886
- [inlineSVG]="
1887
- row.isExpand
1888
- ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'
1889
- : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
1890
- "
1891
- ></span>
1892
- </span>
1893
- <strong (click)="toggleExpand(row)" class="cursor-pointer">
1894
- {{ row.groupValue }} ({{ countLeafRows(row) }})
1895
- </strong>
1896
- </div>
1897
- </div>
1898
-
1899
- <div
1900
- *ngIf="section == 'right'"
1901
- [style.width.px]="rightPinnedHeader.offsetWidth"
1902
- [class.row-selected]="rowSelectedIndexes.has(row.__virtualIndex)"
1903
- [class.first-row-selected]="firstSelectedRow == row.__virtualIndex"
1904
- [class.last-row-selected]="lastSelectedRow == row.__virtualIndex"
1905
- ></div>
1906
- </div>
1907
-
1908
- <!-- Recursive Children -->
1909
- <div class="group-children" *ngIf="row.isExpand">
1910
- <ng-container
1911
- *ngFor="let child of row.children; let i = index; trackBy: trackById"
1912
- >
1913
- <ng-container *ngIf="child.isGroup; else dataRow">
1914
- <!-- Recursive call for nested group -->
1915
- <ng-container
1916
- *ngTemplateOutlet="
1917
- groupRowTemplate;
1918
- context: { $implicit: child, depth: depth + 1 }
1919
- "
1920
- ></ng-container>
1921
- </ng-container>
1922
-
1923
- <ng-template #dataRow>
1924
- <!-- Regular data row -->
1925
- <ng-container
1926
- *ngTemplateOutlet="
1927
- rowCell;
1928
- context: {
1929
- $implicit: child,
1930
- columns: columns,
1931
- isEven: i % 2 === 0,
1932
- isOdd: i % 2 !== 0,
1933
- isLeft: isLeftSection,
1934
- section: section,
1935
- isTotalRow: isTotalRow
1936
- }
1937
- "
1938
- ></ng-container>
1939
- </ng-template>
1940
- </ng-container>
1941
- </div>
1942
- </ng-container>
1943
- </ng-template>
1944
-
1945
- <!-- Regular row (not a group) -->
1946
- <ng-template #regularRow>
1947
- <div class="d-flex" [style.height.px]="rowHeight">
1948
- <span
1949
- class="d-flex align-items-center justify-content-center cursor-pointer border-below"
1950
- style="min-width: 30px; height: 100%"
1951
- *ngIf="section == 'center' && gridType === 'Assets'"
1952
- [ngStyle]="{
1953
- 'background-color':
1954
- hoveredRowId === (row._id || row.id)
1955
- ? rowHoverColor
1956
- : isRowSelected(row)
1957
- ? checkedRowBackgroundColor
1958
- : isEven
1959
- ? evenRowsBackgroundColor
1960
- : oddRowsBackgroundColor
1961
- }"
1962
- >
1963
- <span
1964
- (click)="toggleDetailRowExpand(row)"
1965
- *ngIf="row?.detail?.result?.length"
1966
- class="data-grid-svg-icon filter-icon-wrapper"
1967
- [inlineSVG]="
1968
- isDetailsExpanded(row)
1969
- ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'
1970
- : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
1971
- "
1972
- ></span>
1973
- </span>
1974
- <div
1975
- [style.min-width.px]="
1976
- section == 'center' && groupedColumns?.length ? groupBoxPadding : 0
1977
- "
1978
- [class.row-selected]="rowSelectedIndexes.has(row.__virtualIndex)"
1979
- [class.first-row-selected]="firstSelectedRow == row.__virtualIndex"
1980
- [class.last-row-selected]="lastSelectedRow == row.__virtualIndex"
1981
- (contextmenu)="onRightClick($event, row)"
1982
- [style.height.px]="rowHeight"
1983
- class="data-grid-row h-100"
1984
- [class.even-row]="isEven"
1985
- [class.odd-row]="isOdd"
1986
- [class.hovered-row]="hoveredRowId === (row._id || row.id)"
1987
- (mouseenter)="onRowHover(row)"
1988
- (mouseleave)="onRowLeave()"
1989
- [ngStyle]="{
1990
- 'background-color':
1991
- hoveredRowId === (row._id || row.id)
1992
- ? rowHoverColor
1993
- : isRowSelected(row)
1994
- ? checkedRowBackgroundColor
1995
- : isEven
1996
- ? evenRowsBackgroundColor
1997
- : oddRowsBackgroundColor
1998
- }"
1999
- ></div>
2000
- <div
2001
- (contextmenu)="onRightClick($event, row)"
2002
- [style.height.px]="rowHeight"
2003
- class="data-grid-row"
2004
- [class.even-row]="isEven"
2005
- [class.odd-row]="isOdd"
2006
- [class.hovered-row]="hoveredRowId === (row._id || row.id)"
2007
- (mouseenter)="onRowHover(row)"
2008
- (mouseleave)="onRowLeave()"
2009
- [ngStyle]="{
2010
- 'background-color':
2011
- hoveredRowId === (row._id || row.id)
2012
- ? rowHoverColor
2013
- : isRowSelected(row)
2014
- ? checkedRowBackgroundColor
2015
- : isEven
2016
- ? evenRowsBackgroundColor
2017
- : oddRowsBackgroundColor
2018
- }"
2019
- >
2020
- <div
2021
- [style.backgroundColor]="checkboxesBackgroundColor"
2022
- class="select-all-checkbox-cell justify-content-end pe-2 s-no"
2023
- [style.width.px]="65"
2024
- *ngIf="isLeftSection && showSerialNumber"
2025
- [style.cursor]="
2026
- 'url(' +
2027
- singleSpaAssetsPath +
2028
- 'data-grid/icons/arrow-right.svg), auto'
2029
- "
2030
- (mousedown)="onRowMouseDown(row.__virtualIndex, $event)"
2031
- (mouseover)="onRowMouseOver(row.__virtualIndex, $event)"
2032
- >
2033
- {{ row.__virtualIndex }}
2034
- </div>
2035
- <div
2036
- [style.backgroundColor]="
2037
- rowSelectedIndexes.has(row.__virtualIndex)
2038
- ? selectedRowsBackgroundColor
2039
- : checkboxesBackgroundColor
2040
- "
2041
- class="select-all-checkbox-cell"
2042
- *ngIf="isLeftSection"
2043
- [class.left-selection-border]="
2044
- rowSelectedIndexes.has(row.__virtualIndex)
2045
- "
2046
- [class.first-row-selected]="firstSelectedRow == row.__virtualIndex"
2047
- [class.last-row-selected]="lastSelectedRow == row.__virtualIndex"
2048
- >
2049
- <input
2050
- *ngIf="hasAnyVisibleColumn"
2051
- type="checkbox"
2052
- [checked]="isRowSelected(row)"
2053
- (change)="toggleRowSelection(row)"
2054
- />
2055
- </div>
2056
-
2057
- <!-- Render all columns -->
2058
- <ng-container
2059
- *ngFor="
2060
- let col of columns;
2061
- trackBy: trackByField;
2062
- let colIndex = index
2063
- "
2064
- >
2065
- <ng-container *ngIf="col.children?.length > 0; else flatColumn">
2066
- <ng-container
2067
- *ngFor="
2068
- let child of col.children;
2069
- trackBy: trackByField;
2070
- let subColIndex = index
2071
- "
2072
- >
2073
- <ng-container *ngIf="child?.is_visible && !child?.isRowGrouped">
2074
- <ng-container
2075
- *ngTemplateOutlet="
2076
- cellTemplate;
2077
- context: {
2078
- col: child,
2079
- row: row,
2080
- rowIndex: rowIndex,
2081
- colIndex: colIndex,
2082
- subColIndex: subColIndex,
2083
- section: section,
2084
- isTotalRow: isTotalRow
2085
- }
2086
- "
2087
- ></ng-container>
2088
- </ng-container>
2089
- </ng-container>
2090
- </ng-container>
2091
-
2092
- <ng-template #flatColumn>
2093
- <ng-container
2094
- *ngTemplateOutlet="
2095
- cellTemplate;
2096
- context: {
2097
- col: col,
2098
- row: row,
2099
- rowIndex: rowIndex,
2100
- colIndex: colIndex,
2101
- subColIndex: null,
2102
- section: section,
2103
- isTotalRow: isTotalRow
2104
- }
2105
- "
2106
- ></ng-container>
2107
- </ng-template>
2108
- </ng-container>
2109
- </div>
2110
- </div>
2111
-
2112
- <div
2113
- [@slideToggle]
2114
- *ngIf="section === 'left' && isDetailsExpanded(row)"
2115
- class="accordion-details"
2116
- style="max-height: 350px; overflow: hidden"
2117
- >
2118
- <ng-container
2119
- *ngTemplateOutlet="
2120
- leftRightNestedPlaceholder;
2121
- context: { $implicit: row }
2122
- "
2123
- >
2124
- </ng-container>
2125
- </div>
2126
-
2127
- <div
2128
- [@slideToggle]
2129
- *ngIf="section === 'center' && isDetailsExpanded(row)"
2130
- class="accordion-details center-section"
2131
- style="max-height: 350px; overflow: auto; scrollbar-width: thin"
2132
- #nestedTable
2133
- [style.width]="
2134
- hasRightPinnedColumns
2135
- ? '100%'
2136
- : hasVerticalScroll
2137
- ? 'calc(100% - 12px)'
2138
- : '100%'
2139
- "
2140
- >
2141
- <ng-container
2142
- *ngTemplateOutlet="nestedTableTemplate; context: { $implicit: row }"
2143
- ></ng-container>
2144
- </div>
2145
-
2146
- <div
2147
- [@slideToggle]
2148
- *ngIf="section === 'right' && isDetailsExpanded(row)"
2149
- class="accordion-details"
2150
- style="max-height: 350px; overflow: hidden"
2151
- >
2152
- <ng-container
2153
- *ngTemplateOutlet="
2154
- leftRightNestedPlaceholder;
2155
- context: { $implicit: row }
2156
- "
2157
- >
2158
- </ng-container>
2159
- </div>
2160
- </ng-template>
2161
- </ng-template>
2162
-
2163
- <!-- Actual Cell is Here -->
2164
- <ng-template
2165
- #cellTemplate
2166
- let-col="col"
2167
- let-row="row"
2168
- let-section="section"
2169
- let-subColIndex="subColIndex"
2170
- let-rowIndex="rowIndex"
2171
- let-colIndex="colIndex"
2172
- let-isTotalRow="isTotalRow"
2173
- >
2174
- <div
2175
- (click)="editingKey = ''; setActiveCell(row, col)"
2176
- [style.fontWeight]="bodyFontWeight"
2177
- [class.border-right]="showVerticalBorder"
2178
- class="cell overflow-visible position-relative"
2179
- [attr.field]="col.field"
2180
- [style.width.px]="col.width"
2181
- [style.min-width.px]="col.width"
2182
- [style.fontSize.px]="bodyTextFontsSize"
2183
- [class.active-cell]="
2184
- isActiveCell(row, col) && !isEditing(row, col) && selectedKeys.size == 1
2185
- "
2186
- (dblclick)="
2187
- $event.stopPropagation(); $event.preventDefault(); enableEdit(row, col)
2188
- "
2189
- [class.row-selected]="rowSelectedIndexes.has(row.__virtualIndex)"
2190
- [class.first-row-selected]="firstSelectedRow === row?.__virtualIndex"
2191
- [class.last-row-selected]="lastSelectedRow === row?.__virtualIndex"
2192
- tabindex="-1"
2193
- (keydown.enter)="$event.preventDefault(); enableEdit(row, col)"
2194
- (mousedown)="
2195
- startSelection(
2196
- row.__virtualIndex,
2197
- colIndex,
2198
- subColIndex ?? 0,
2199
- col.field,
2200
- $event,
2201
- section
2202
- )
2203
- "
2204
- (mouseenter)="
2205
- extendSelection(
2206
- row.__virtualIndex,
2207
- colIndex,
2208
- subColIndex ?? 0,
2209
- col.field,
2210
- $event,
2211
- section
2212
- )
2213
- "
2214
- (mouseup)="endSelection()"
2215
- [class.selected-cell]="
2216
- isSelected(
2217
- row.__virtualIndex,
2218
- colIndex,
2219
- subColIndex ?? 0,
2220
- col.field,
2221
- section
2222
- )
2223
- "
2224
- [class.top-border]="
2225
- isTopBorder(row.__virtualIndex, colIndex, subColIndex, section)
2226
- "
2227
- [class.bottom-border]="
2228
- isBottomBorder(row.__virtualIndex, colIndex, subColIndex, section)
2229
- "
2230
- [class.left-border]="
2231
- isLeftBorder(row.__virtualIndex, colIndex, subColIndex, section)
2232
- "
2233
- [class.right-border]="
2234
- isRightBorder(row.__virtualIndex, colIndex, subColIndex, section)
2235
- "
2236
- [class.top-left-corner]="
2237
- isTopLeftCorner(row.__virtualIndex, colIndex, subColIndex, section)
2238
- "
2239
- [class.top-right-corner]="
2240
- isTopRightCorner(row.__virtualIndex, colIndex, subColIndex, section)
2241
- "
2242
- [class.bottom-left-corner]="
2243
- isBottomLeftCorner(row.__virtualIndex, colIndex, subColIndex, section)
2244
- "
2245
- [class.bottom-right-corner]="
2246
- isBottomRightCorner(row.__virtualIndex, colIndex, subColIndex, section)
2247
- "
2248
- >
2249
- <!-- (mousedown)="startSelection(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field, $event)"
2250
- (mouseenter)="extendSelection(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field, $event)"
2251
- (mouseup)="endSelection()"
2252
- [class.selected-cell]="isSelected(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field)" -->
2253
- <div
2254
- class="table-cell"
2255
- [class.active-for-editing]="
2256
- isEditing(row, col) &&
2257
- (getNestedValue(row, col.field)?.length === undefined ||
2258
- getNestedValue(row, col.field)?.length <= 50)
2259
- "
2260
- >
2261
- <div
2262
- (click)="$event.stopPropagation()"
2263
- *ngIf="
2264
- isEditing(row, col) &&
2265
- (getNestedValue(row, col.field)?.length === undefined ||
2266
- getNestedValue(row, col.field)?.length <= 50);
2267
- else viewMode
2268
- "
2269
- >
2270
- <ng-container [ngSwitch]="col.type">
2271
- <!-- Text Input -->
2272
- <input
2273
- [style.height.px]="rowHeight - 10"
2274
- *ngSwitchCase="'input'"
2275
- type="text"
2276
- [(ngModel)]="row[col.field]"
2277
- (blur)="disableEdit(row, col)"
2278
- autofocus
2279
- class="form-control form-control-sm"
2280
- (mousedown)="$event.stopPropagation()"
2281
- />
2282
-
2283
- <!-- Number Input -->
2284
- <input
2285
- [style.height.px]="rowHeight - 8"
2286
- *ngSwitchCase="'number'"
2287
- #numberInput="ngModel"
2288
- #numberRef
2289
- (keypress)="allowOnlyNumbers($event)"
2290
- type="number"
2291
- required
2292
- [(ngModel)]="row[col.field]"
2293
- (blur)="disableEdit(row, col)"
2294
- autofocus
2295
- (keydown.enter)="numberRef.blur()"
2296
- class="form-control form-control-sm"
2297
- [ngClass]="{
2298
- 'is-invalid': numberInput.invalid
2299
- }"
2300
- (mousedown)="$event.stopPropagation()"
2301
- />
2302
-
2303
- <!-- Date Input -->
2304
- <input
2305
- [style.height.px]="rowHeight - 8"
2306
- *ngSwitchCase="'date'"
2307
- type="date"
2308
- [(ngModel)]="row[col.field]"
2309
- (blur)="disableEdit(row, col)"
2310
- autofocus
2311
- class="form-control form-control-sm"
2312
- #dateInput="ngModel"
2313
- [ngClass]="{
2314
- 'is-invalid': dateInput.invalid
2315
- }"
2316
- (mousedown)="$event.stopPropagation()"
2317
- />
2318
-
2319
- <!-- Dropdown -->
2320
- <!-- ng-select like dropdown -->
2321
- <div
2322
- *ngSwitchCase="'dropdown'"
2323
- class="dropdown w-100"
2324
- (blur)="disableEdit(row, col)"
2325
- >
2326
- <!-- Trigger -->
2327
- <button
2328
- class="form-select form-select-sm text-start w-100 text-ellipsis"
2329
- type="button"
2330
- data-bs-toggle="dropdown"
2331
- aria-expanded="false"
2332
- [style.minHeight.px]="rowHeight - 10"
2333
- data-bs-display="static"
2334
- (mousedown)="$event.stopPropagation()"
2335
- >
2336
- <ng-container>
2337
- {{
2338
- getNestedValue(row, col.field)?.value ||
2339
- getNestedValue(row, col.field)?.name ||
2340
- getNestedValue(row, col.field)
2341
- }}
2342
- </ng-container>
2343
- <ng-template #placeholder> Select options... </ng-template>
2344
- </button>
2345
-
2346
- <!-- Menu -->
2347
- <div
2348
- class="dropdown-menu w-100 p-0 cell-editing-dropdown-menu rounded-3"
2349
- [class.show]="isEditing(row, col)"
2350
- >
2351
- <!-- Search -->
2352
- <div class="px-2 py-1 editing-dropdown-search-input">
2353
- <input
2354
- type="text"
2355
- class="form-control form-control-sm"
2356
- placeholder="Search..."
2357
- [(ngModel)]="editinDropdownSearch"
2358
- (mousedown)="$event.stopPropagation()"
2359
- />
2360
- </div>
2361
-
2362
- <!-- Options -->
2363
- <div
2364
- class="cell-editin-dropdown"
2365
- style="max-height: 200px; overflow: auto"
2366
- >
2367
- <div
2368
- (click)="
2369
- setNestedValue(row, col, option, true); editingKey = null
2370
- "
2371
- class="px-2 py-1 d-flex align-items-center item"
2372
- *ngFor="
2373
- let option of col.column_dropdown_value
2374
- | filter : editinDropdownSearch
2375
- "
2376
- >
2377
- <label
2378
- class="form-check-label d-flex align-items-center mb-0"
2379
- [for]="col.field + '-' + option.value || option"
2380
- >
2381
- {{ option.value || option }}
2382
- </label>
2383
- </div>
2384
- </div>
2385
- </div>
2386
- </div>
2387
-
2388
- <input
2389
- *ngSwitchCase="'email'"
2390
- [style.height.px]="rowHeight - 10"
2391
- [style.maxHeight.px]="rowHeight - 10"
2392
- #emailModel="ngModel"
2393
- #emailInput
2394
- type="email"
2395
- [(ngModel)]="row[col.field]"
2396
- name="{{ col.field }}"
2397
- required
2398
- pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
2399
- (blur)="disableEdit(row, col, emailModel)"
2400
- (keydown.enter)="
2401
- emailModel.control.markAsTouched(); emailInput.blur()
2402
- "
2403
- autofocus
2404
- class="form-control form-control-sm"
2405
- [ngClass]="{
2406
- 'is-invalid': emailModel.invalid
2407
- }"
2408
- (mousedown)="$event.stopPropagation()"
2409
- />
2410
- <!-- Default fallback -->
2411
- <input
2412
- *ngSwitchDefault
2413
- [style.height.px]="rowHeight - 10"
2414
- [style.maxHeight.px]="rowHeight - 10"
2415
- #textModel="ngModel"
2416
- #textInput
2417
- type="text"
2418
- [(ngModel)]="row[col.field]"
2419
- name="{{ col.field }}"
2420
- required
2421
- (blur)="disableEdit(row, col, textModel)"
2422
- (keydown.enter)="
2423
- textModel.control.markAsTouched(); textInput.blur()
2424
- "
2425
- autofocus
2426
- class="form-control form-control-sm"
2427
- [ngClass]="{
2428
- 'is-invalid': textModel.invalid
2429
- }"
2430
- (mousedown)="$event.stopPropagation()"
2431
- />
2432
- </ng-container>
2433
- </div>
2434
-
2435
- <!-- Display mode -->
2436
- <ng-template #viewMode>
2437
- <div
2438
- class="d-flex justify-between items-center w-100"
2439
- [ngClass]="getCellClasses(col, getNestedValue(row, col.field))"
2440
- >
2441
- <!-- Text cell -->
2442
- <div
2443
- #cellText
2444
- class="text-ellipsis flex-grow-1"
2445
- [title]="
2446
- col.type === 'date'
2447
- ? (getNestedValue(row, col.field) | date : dateFormat)
2448
- : getNestedValue(row, col.field) || '-'
2449
- "
2450
- >
2451
- <ng-container *ngIf="col.type !== 'image' && !isTotalRow">
2452
- <ng-container *ngIf="col.is_amount">{{
2453
- currencySymbol
2454
- }}</ng-container>
2455
- {{
2456
- !isNestedValueArray(row, col.field)
2457
- ? col.type === 'date'
2458
- ? (isDate(getNestedValue(row, col.field))
2459
- ? (getNestedValue(row, col.field) | date: dateFormat)
2460
- : (getNestedValue(row, col.field)?.value ||
2461
- getNestedValue(row, col.field)?.name ||
2462
- getNestedValue(row, col.field) ||
2463
- '-'))
2464
- : (getNestedValue(row, col.field)?.value ||
2465
- getNestedValue(row, col.field)?.name ||
2466
- getNestedValue(row, col.field) ||
2467
- (col.is_amount ? 0: '-'))
2468
- : (getNestedValue(row, col.field)?.[0]?.department_name ||
2469
- getNestedValue(row, col.field)?.[0]?.roleName ||
2470
- '-')
2471
- }}
2472
- </ng-container>
2473
- <ng-container *ngIf="isTotalRow">
2474
- {{ getTotalAmount(col) }}
2475
- </ng-container>
2476
- <ng-container *ngIf="col.type == 'image' && !isTotalRow">
2477
- <ng-container
2478
- *ngTemplateOutlet="
2479
- defaultImagePlaceholder;
2480
- context: {
2481
- row: row,
2482
- col: col,
2483
- }
2484
- "
2485
- ></ng-container>
2486
- </ng-container>
2487
- </div>
2488
-
2489
- <!-- Expand / Collapse icon -->
2490
- <span
2491
- *ngIf="
2492
- (isOverflowing(cellText) &&
2493
- showCellDetailsBox &&
2494
- getNestedValue(row, col.field)?.length > 50) ||
2495
- (isNestedValueArray(row, col.field) &&
2496
- getNestedValue(row, col.field)?.length > 1)
2497
- "
2498
- class="toggle-icon data-grid-svg-icon ms-2 cursor-pointer"
2499
- [inlineSVG]="
2500
- isExpanded(row, col)
2501
- ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'
2502
- : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
2503
- "
2504
- (click)="
2505
- $event.stopPropagation();
2506
- toggleExpandOfLongCellText(row, col, columns, true)
2507
- "
2508
- (dblclick)="$event.preventDefault(); $event.stopPropagation()"
2509
- ></span>
2510
- </div>
2511
-
2512
- <!-- Expanded text -->
2513
- <div
2514
- class="position-absolute w-100"
2515
- *ngIf="isExpanded(row, col)"
2516
- [style.zIndex]="getZIndex(row, col)"
2517
- style="top: 100%; left: 0"
2518
- >
2519
- <ng-container
2520
- *ngTemplateOutlet="
2521
- fullTextTemplate;
2522
- context: {
2523
- row: row,
2524
- col: col,
2525
- isArray: isNestedValueArray(row, col.field)
2526
- }
2527
- "
2528
- ></ng-container>
2529
- </div>
2530
- </ng-template>
2531
- </div>
2532
- </div>
2533
- </ng-template>
2534
-
2535
- <!-- Headers Action List On clicking three dots -->
2536
-
2537
- <ng-template #columnMenu let-col="col">
2538
- <div
2539
- class="column-menu three-dots-col-menu"
2540
- [class.visually-hidden]="isMenueHidden"
2541
- *ngIf="activeCol && !isThreeDotsFilterOpen"
2542
- [style.backgroundColor]="dropdownsBackgroundColor"
2543
- >
2544
- <!-- Sort Ascending -->
2545
- <div class="border-below pb-2" [class.disable-sorting]="!col.is_sortable">
2546
- <span class="muted-text fs-7" style="margin-left: 12px">Sort</span>
2547
- <div
2548
- *ngIf="
2549
- columnThreedotsMunuConfig?.showAscending &&
2550
- (sortingConfig?.field != col.field ||
2551
- sortingConfig?.order_by == 'desc')
2552
- "
2553
- class="column-menu-item"
2554
- (click)="sortAsc(activeCol)"
2555
- >
2556
- <span
2557
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/arrow-up.svg'"
2558
- class="data-grid-svg-icon me-2"
2559
- ></span>
2560
- Sort Ascending
2561
- </div>
2562
-
2563
- <!-- Sort Descending -->
2564
- <div
2565
- *ngIf="
2566
- columnThreedotsMunuConfig?.showDescending &&
2567
- (sortingConfig?.field != col.field ||
2568
- sortingConfig?.order_by == 'asc')
2569
- "
2570
- class="column-menu-item"
2571
- (click)="sortDesc(activeCol)"
2572
- >
2573
- <span
2574
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/arrow-down.svg'"
2575
- class="data-grid-svg-icon me-2"
2576
- ></span>
2577
- Sort Descending
2578
- </div>
2579
-
2580
- <div
2581
- *ngIf="
2582
- sortingConfig?.field === col.field &&
2583
- (sortingConfig?.order_by === 'asc' ||
2584
- sortingConfig?.order_by === 'desc')
2585
- "
2586
- class="column-menu-item"
2587
- (click)="resetSort(activeCol)"
2588
- >
2589
- <span
2590
- [inlineSVG]="
2591
- singleSpaAssetsPath + 'data-grid/icons/arrow-counterclockwise.svg'
2592
- "
2593
- class="data-grid-svg-icon me-2"
2594
- ></span>
2595
- Reset Sort
2596
- </div>
2597
- </div>
2598
- <div class="py-2 border-below three-dots-filter">
2599
- <div
2600
- *ngIf="columnThreedotsMunuConfig?.showFilter"
2601
- class="column-menu-item three-dots-filter"
2602
- (click)="openFilteronThreeDotsClick(col)"
2603
- >
2604
- <span
2605
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'"
2606
- class="data-grid-svg-icon me-2"
2607
- ></span>
2608
- Filter
2609
- </div>
2610
- </div>
2611
-
2612
- <div class="py-2 border-below">
2613
- <span class="muted-text fs-7" style="margin-left: 12px">Pin</span>
2614
- <div
2615
- *ngIf="columnThreedotsMunuConfig?.showPinleft && col?.pinned !== 'left'"
2616
- class="column-menu-item"
2617
- (click)="updateColumnPinInSourceByField(activeCol, 'left')"
2618
- >
2619
- <span
2620
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/pin-left.svg'"
2621
- class="data-grid-svg-icon me-2"
2622
- ></span
2623
- >Pin Left
2624
- </div>
2625
-
2626
- <div
2627
- *ngIf="
2628
- columnThreedotsMunuConfig?.showPinright && col?.pinned !== 'right'
2629
- "
2630
- class="column-menu-item"
2631
- (click)="updateColumnPinInSourceByField(activeCol, 'right')"
2632
- >
2633
- <span
2634
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/pin-right.svg'"
2635
- class="data-grid-svg-icon data-grid-svg-icon me-2"
2636
- ></span
2637
- >Pin Right
2638
- </div>
2639
-
2640
- <div
2641
- *ngIf="col?.pinned"
2642
- class="column-menu-item"
2643
- (click)="updateColumnPinInSourceByField(activeCol, null)"
2644
- >
2645
- <span
2646
- [inlineSVG]="
2647
- singleSpaAssetsPath + 'data-grid/icons/layout-three-columns.svg'
2648
- "
2649
- class="data-grid-svg-icon me-2"
2650
- ></span
2651
- >Unpin
2652
- </div>
2653
- </div>
2654
-
2655
- <div
2656
- *ngIf="columnThreedotsMunuConfig?.showAutosizeThisColumn"
2657
- class="column-menu-item"
2658
- (click)="autosizeColumn(activeCol)"
2659
- >
2660
- <span
2661
- [inlineSVG]="
2662
- singleSpaAssetsPath + 'data-grid/icons/arrows-expand-vertical.svg'
2663
- "
2664
- class="me-2"
2665
- ></span>
2666
- Autosize This Column
2667
- </div>
2668
-
2669
- <!-- Autosize All Columns -->
2670
- <div
2671
- *ngIf="columnThreedotsMunuConfig?.showAutosizeAllColumns"
2672
- class="column-menu-item"
2673
- (click)="autosizeAllColumns()"
2674
- >
2675
- <span
2676
- [inlineSVG]="
2677
- singleSpaAssetsPath + 'data-grid/icons/arrows-angle-expand.svg'
2678
- "
2679
- class="data-grid-svg-icon me-2"
2680
- ></span
2681
- >Autosize All Columns
2682
- </div>
2683
-
2684
- <!-- Group By -->
2685
- <div
2686
- *ngIf="showRowsGrouping"
2687
- class="column-menu-item"
2688
- (click)="groupBy(activeCol)"
2689
- >
2690
- <span
2691
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/diagram-3.svg'"
2692
- class="data-grid-svg-icon me-2"
2693
- ></span>
2694
- Group by {{ col.header }}
2695
- </div>
2696
-
2697
- <!-- Choose Columns -->
2698
- <div
2699
- *ngIf="columnThreedotsMunuConfig?.showChoseColumns"
2700
- class="column-menu-item"
2701
- (click)="chooseColumns()"
2702
- >
2703
- <span
2704
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/ui-checks-grid.svg'"
2705
- class="data-grid-svg-icon me-2"
2706
- ></span>
2707
- Choose Columns
2708
- </div>
2709
-
2710
- <!-- Reset Columns -->
2711
- <div
2712
- *ngIf="columnThreedotsMunuConfig?.showResetColumns"
2713
- class="column-menu-item"
2714
- (click)="resetColumns()"
2715
- >
2716
- <span
2717
- [inlineSVG]="
2718
- singleSpaAssetsPath + 'data-grid/icons/arrow-counterclockwise.svg'
2719
- "
2720
- class="data-grid-svg-icon me-2"
2721
- ></span
2722
- >Reset Columns
2723
- </div>
2724
- </div>
2725
- <div
2726
- *ngIf="isThreeDotsFilterOpen"
2727
- class="three-dots-col-menu position-relative"
2728
- [style.left.px]="-140"
2729
- [class.visually-hidden]="isMenueHidden"
2730
- >
2731
- <ng-container
2732
- *ngTemplateOutlet="filterMenu; context: { col: col }"
2733
- ></ng-container>
2734
- </div>
2735
- </ng-template>
2736
-
2737
- <!-- Filter Menue -->
2738
- <ng-template #filterMenu let-col="col">
2739
- <div
2740
- class="filter-menu-container filter-menu"
2741
- [style.backgroundColor]="dropdownsBackgroundColor"
2742
- >
2743
- <!-- Dropdown Type -->
2744
- <ng-container *ngIf="col.type === 'dropdown'; else textFilter">
2745
- <div class="filter-dropdown-section p-1">
2746
- <input
2747
- class="form-control form-control-sm"
2748
- placeholder="Search..."
2749
- type="search"
2750
- [(ngModel)]="addFilterColumnInput"
2751
- />
2752
-
2753
- <div class="form-check mb-1 mt-2">
2754
- <input
2755
- class="form-check-input"
2756
- type="checkbox"
2757
- [checked]="isAllSideFilterOptionsSelected(col)"
2758
- (change)="toggleSelectAllSideFilters(col, $event)"
2759
- id="selectAll_{{ col.field }}"
2760
- />
2761
- <label class="form-check-label" for="selectAll_{{ col.field }}">
2762
- Select All
2763
- </label>
2764
- </div>
2765
-
2766
- <div class="dropdown-options">
2767
- <div
2768
- class="form-check mb-1"
2769
- *ngFor="
2770
- let option of selectedColumnForFilter?.column_dropdown_value
2771
- | filter : addFilterColumnInput: 'value';
2772
- trackBy: trackById; let i = index
2773
- "
2774
- >
2775
- <input
2776
- class="form-check-input"
2777
- type="checkbox"
2778
- [id]="i"
2779
- [checked]="currentFilterSelectedIds.has(option.id || option._id || option)"
2780
- (change)="toggleSelectionInFilter(option)"
2781
- />
2782
- <label class="form-check-label fw-semibold" [for]="i">
2783
- {{ option?.value || option?.name || option }}
2784
- </label>
2785
- </div>
2786
- </div>
2787
- </div>
2788
- </ng-container>
2789
-
2790
- <!-- Text Filter Section -->
2791
- <ng-template #textFilter>
2792
- <div class="filter-text-section">
2793
- <div class="form-group mb-2">
2794
- <select
2795
- class="form-select form-select-sm custom-select"
2796
- [(ngModel)]="firstCondition"
2797
- >
2798
- <ng-container *ngIf="selectedColumnForFilter.type !== 'date'">
2799
- <option value="contain">Contains</option>
2800
- <option value="equal">Equals</option>
2801
- <option value="before">Starts With</option>
2802
- <option value="after">Ends With</option>
2803
- </ng-container>
2804
-
2805
- <ng-container *ngIf="selectedColumnForFilter.type == 'date'">
2806
- <option value="equal">Equals To</option>
2807
- <option value="after">After</option>
2808
- <option value="before">Before</option>
2809
- </ng-container>
2810
- </select>
2811
- </div>
2812
-
2813
- <input
2814
- [type]="col.type == 'string' ? 'text' : col.type"
2815
- class="form-control form-control-sm mb-3"
2816
- placeholder="Value"
2817
- [(ngModel)]="firstValue"
2818
- #filterMenueTextchInput
2819
- (keydown.enter)="applyDropdownFilter()"
2820
- />
2821
-
2822
- <ng-container *ngIf="col.query?.first_value">
2823
- <div class="form-group mb-2">
2824
- <div class="form-check form-check-inline">
2825
- <input
2826
- class="form-check-input filter-radio-inputs"
2827
- type="radio"
2828
- name="condition"
2829
- [(ngModel)]="condition"
2830
- value="and"
2831
- id="and_{{ col.field }}"
2832
- />
2833
- <label class="form-check-label" for="and_{{ col.field }}"
2834
- >AND</label
2835
- >
2836
- </div>
2837
- <div class="form-check form-check-inline">
2838
- <input
2839
- class="form-check-input filter-radio-inputs"
2840
- type="radio"
2841
- name="condition"
2842
- [(ngModel)]="condition"
2843
- value="or"
2844
- id="or_{{ col.field }}"
2845
- />
2846
- <label class="form-check-label" for="or_{{ col.field }}"
2847
- >OR</label
2848
- >
2849
- </div>
2850
- <div class="form-check form-check-inline">
2851
- <input
2852
- class="form-check-input filter-radio-inputs"
2853
- type="radio"
2854
- name="condition"
2855
- [(ngModel)]="condition"
2856
- value="none"
2857
- id="none_{{ col.field }}"
2858
- />
2859
- <label class="form-check-label" for="none_{{ col.field }}"
2860
- >None</label
2861
- >
2862
- </div>
2863
- </div>
2864
-
2865
- <div class="form-group mb-2">
2866
- <select
2867
- class="form-select form-select-sm custom-select"
2868
- [(ngModel)]="firstCondition"
2869
- >
2870
- <ng-container *ngIf="selectedColumnForFilter.type !== 'date'">
2871
- <option value="contain">Contains</option>
2872
- <option value="equal">Equals</option>
2873
- <option value="before">Starts With</option>
2874
- <option value="after">Ends With</option>
2875
- </ng-container>
2876
-
2877
- <ng-container *ngIf="selectedColumnForFilter.type == 'date'">
2878
- <option value="equal">Equals To</option>
2879
- <option value="after">After</option>
2880
- <option value="before">Before</option>
2881
- </ng-container>
2882
- </select>
2883
- </div>
2884
-
2885
- <input
2886
- [type]="col.type == 'string' ? 'text' : col.type"
2887
- class="form-control form-control-sm mb-2"
2888
- placeholder="Second Value"
2889
- [(ngModel)]="secondValue"
2890
- />
2891
- </ng-container>
2892
- </div>
2893
- </ng-template>
2894
-
2895
- <!-- Actions -->
2896
- <div class="d-flex gap-2 mt-2">
2897
- <div
2898
- [class.disabled]="!currentFilterSelectedIds?.size && !firstValue"
2899
- class="btn btn-sm btn-primary d-flex justify-content-center align-items-center w-100"
2900
- style="height: 22px"
2901
- (click)="applyDropdownFilter()"
2902
- >
2903
- Apply
2904
- </div>
2905
- <div
2906
- [class.disabled]="!currentFilterSelectedIds?.size && !firstValue"
2907
- class="btn btn-sm btn-secondary d-flex justify-content-center align-items-center w-100"
2908
- style="height: 22px"
2909
- (click)="resetSideFilter(col)"
2910
- >
2911
- Reset
2912
- </div>
2913
- </div>
2914
- </div>
2915
- </ng-template>
2916
-
2917
- <!-- Side Menue -->
2918
-
2919
- <!-- Column Pannel / Pivot Mode / Searching -->
2920
-
2921
- <ng-template #columnPannel>
2922
- <div class="column-panel-header">
2923
- <!-- Pivot Toggle -->
2924
- <div
2925
- class="form-check form-switch d-flex align-items-center mb-2 pivot-mode px-5 ms-2 d-none"
2926
- >
2927
- <input
2928
- class="form-check-input me-2"
2929
- type="checkbox"
2930
- id="pivotToggle"
2931
- [(ngModel)]="pivotMode"
2932
- />
2933
- <label class="form-check-label" for="pivotToggle">Pivot Mode</label>
2934
- </div>
2935
-
2936
- <!-- Select All & Search -->
2937
- <div class="d-flex align-items-center mb-2 px-3 mt-3">
2938
- <span class="filter-icon-wrapper me-2" *ngIf="showColumnsGrouping">
2939
- <span
2940
- class="toggle-icon data-grid-svg-icon"
2941
- [inlineSVG]="
2942
- accordionState === 'all'
2943
- ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'
2944
- : accordionState === 'some'
2945
- ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'
2946
- : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
2947
- "
2948
- (click)="toggleAllAccordions()"
2949
- ></span>
2950
- </span>
2951
- <input
2952
- type="checkbox"
2953
- class="form-check-input me-2"
2954
- [checked]="allColumnsSelected()"
2955
- (change)="toggleAllColumnsVisibility()"
2956
- />
2957
- <input
2958
- type="text"
2959
- class="form-control form-control-sm"
2960
- placeholder="Search columns..."
2961
- [(ngModel)]="columnSearch"
2962
- />
2963
- </div>
2964
-
2965
- <!-- Separator -->
2966
- <hr class="my-2" />
2967
- </div>
2968
- </ng-template>
2969
-
2970
- <!-- Right Columns Menue -->
2971
-
2972
- <!-- Column Panel Item Template -->
2973
- <ng-template #columnPanelItem let-col="col">
2974
- <!-- Group Column -->
2975
- <ng-container *ngIf="col.children?.length">
2976
- <div class="column-group d-flex align-items-center mb-2">
2977
- <span class="filter-icon-wrapper me-2">
2978
- <span
2979
- class="toggle-icon data-grid-svg-icon"
2980
- [inlineSVG]="
2981
- singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
2982
- "
2983
- [class.rotate]="col.expanded"
2984
- (click)="col.expanded = !col.expanded"
2985
- ></span>
2986
- </span>
2987
- <input
2988
- type="checkbox"
2989
- class="form-check-input me-2"
2990
- [id]="'group_' + col.header"
2991
- [checked]="isColumnVisible(col)"
2992
- (change)="toggleGroupVisibility(col)"
2993
- />
2994
- <span
2995
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'"
2996
- class="data-grid-svg-icon d-flex justify-content-center align-items-center me-2"
2997
- ></span>
2998
- <label
2999
- class="d-flex align-items-center mb-0 w-100"
3000
- [for]="'group_' + col.header"
3001
- style="cursor: pointer"
3002
- >
3003
- <span class="text-truncate">{{ col.header }}</span>
3004
- </label>
3005
- </div>
3006
- <div *ngIf="col.expanded" class="ps-4">
3007
- <ng-container *ngFor="let child of col.children; trackBy: trackByField">
3008
- <ng-container
3009
- *ngTemplateOutlet="columnPanelItem; context: { col: child }"
3010
- ></ng-container>
3011
- </ng-container>
3012
- </div>
3013
- </ng-container>
3014
-
3015
- <!-- Leaf Column -->
3016
- <ng-container *ngIf="!col.children?.length">
3017
- <div class="d-flex align-items-center mb-2">
3018
- <span class="me-2" style="width: 1.5rem"></span>
3019
- <input
3020
- type="checkbox"
3021
- class="form-check-input me-2"
3022
- [(ngModel)]="col.is_visible"
3023
- [id]="'col_' + col.field"
3024
- (change)="onSideMenuColumnsVisibilityChange()"
3025
- />
3026
- <span
3027
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'"
3028
- class="data-grid-svg-icon d-flex justify-content-center align-items-center me-2"
3029
- ></span>
3030
- <label
3031
- class="d-flex align-items-center mb-0 w-100"
3032
- [for]="'col_' + col.field"
3033
- style="cursor: pointer"
3034
- >
3035
- <span class="text-truncate">{{ col.header }}</span>
3036
- </label>
3037
- </div>
3038
- </ng-container>
3039
- </ng-template>
3040
-
3041
- <!-- Columns Side Filter -->
3042
- <ng-template #sideFilters>
3043
- <div class="py-3 px-2 pe-3 h-100">
3044
- <div class="d-flex align-items-center mb-2">
3045
- <span class="filter-icon-wrapper me-2">
3046
- <span
3047
- class="toggle-icon data-grid-svg-icon"
3048
- [inlineSVG]="
3049
- filterAccordionState === 'all'
3050
- ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'
3051
- : filterAccordionState === 'some'
3052
- ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'
3053
- : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
3054
- "
3055
- (click)="toggleAllFilterAccordions()"
3056
- ></span>
3057
- </span>
3058
- <input
3059
- type="text"
3060
- class="form-control form-control-sm"
3061
- placeholder="Search..."
3062
- [(ngModel)]="columnSearch"
3063
- />
3064
- </div>
3065
- <div
3066
- class="overflow-auto side-filter-columns-wrapper"
3067
- style="height: calc(100% - 70px); scrollbar-width: thin"
3068
- >
3069
- <ng-container
3070
- *ngFor="
3071
- let col of columns | filter : columnSearch : 'header';
3072
- trackBy: trackByField
3073
- "
3074
- >
3075
- <ng-container
3076
- *ngTemplateOutlet="filterPannelItem; context: { col: col }"
3077
- ></ng-container>
3078
- </ng-container>
3079
- </div>
3080
- </div>
3081
- </ng-template>
3082
-
3083
- <ng-template #filterPannelItem let-col="col">
3084
- <!-- Group Column -->
3085
- <ng-container *ngIf="col.children?.length">
3086
- <div class="column-group d-flex align-items-center mb-2">
3087
- <!-- Chevron toggle -->
3088
- <span class="filter-icon-wrapper me-2">
3089
- <span
3090
- class="toggle-icon data-grid-svg-icon"
3091
- [inlineSVG]="
3092
- singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
3093
- "
3094
- [class.rotate]="col.expandedFilter"
3095
- (click)="col.expandedFilter = !col.expandedFilter"
3096
- ></span>
3097
- </span>
3098
-
3099
- <!-- Group label toggle -->
3100
- <label
3101
- class="d-flex align-items-center mb-0 w-100"
3102
- style="cursor: pointer"
3103
- (click)="col.expandedFilter = !col.expandedFilter"
3104
- >
3105
- <span class="fw-bold text-truncate"
3106
- >{{ col.header }}
3107
- <span
3108
- class="text-primary ms-1"
3109
- *ngIf="col?.query?._ids?.length || col?.query?._first_value"
3110
- >*</span
3111
- >
3112
- </span>
3113
- </label>
3114
- </div>
3115
-
3116
- <!-- Children columns -->
3117
- <div *ngIf="col.expandedFilter" class="ps-4">
3118
- <ng-container *ngFor="let child of col.children; trackBy: trackByField">
3119
- <ng-container
3120
- *ngTemplateOutlet="filterPannelItem; context: { col: child }"
3121
- ></ng-container>
3122
- </ng-container>
3123
- </div>
3124
- </ng-container>
3125
-
3126
- <!-- Leaf Column -->
3127
- <ng-container *ngIf="!col.children?.length">
3128
- <div class="d-flex align-items-center mb-2">
3129
- <span
3130
- class="me-2 filter-icon-wrapper me-2"
3131
- (click)="col.expandedFilter = !col.expandedFilter"
3132
- >
3133
- <span
3134
- class="toggle-icon data-grid-svg-icon"
3135
- [inlineSVG]="
3136
- singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
3137
- "
3138
- [class.rotate]="col.expandedFilter"
3139
- ></span>
3140
- </span>
3141
-
3142
- <label
3143
- class="d-flex align-items-center mb-0 w-100"
3144
- style="cursor: pointer"
3145
- (click)="col.expandedFilter = !col.expandedFilter"
3146
- >
3147
- <span class="text-truncate fw-bold">{{ col.header }}</span>
3148
- </label>
3149
- </div>
3150
-
3151
- <!-- Show filter when expanded -->
3152
- <div *ngIf="col.expandedFilter" class="ps-4 pe-3">
3153
- <ng-container
3154
- *ngTemplateOutlet="sideNestedFilter; context: { col: col }"
3155
- ></ng-container>
3156
- </div>
3157
- </ng-container>
3158
- </ng-template>
3159
-
3160
- <!-- Side Nested Filters -->
3161
- <ng-template #sideNestedFilter let-col="col">
3162
- <div class="">
3163
- <!-- Dropdown Type -->
3164
- <ng-container *ngIf="col.type === 'dropdown'; else textFilter">
3165
- <div class="p-1">
3166
- <!-- Search -->
3167
- <input
3168
- type="text"
3169
- class="form-control form-control-sm mb-2"
3170
- placeholder="Search..."
3171
- [(ngModel)]="col.searchValue"
3172
- />
3173
-
3174
- <!-- Select All -->
3175
- <div class="form-check mb-1 ms-1">
3176
- <input
3177
- class="form-check-input"
3178
- type="checkbox"
3179
- [checked]="
3180
- col.query?._ids?.length == col?.column_dropdown_value?.length
3181
- "
3182
- (change)="toggleSelectAllSideFilters(col, $event)"
3183
- id="selectAll_{{ col.field }}"
3184
- />
3185
- <label class="form-check-label" for="selectAll_{{ col.field }}">
3186
- Select All
3187
- </label>
3188
- </div>
3189
-
3190
- <!-- Options -->
3191
- <div class="dropdown-options">
3192
- <div
3193
- class="form-check mb-1 ms-1"
3194
- *ngFor="
3195
- let option of col?.column_dropdown_value
3196
- | filter : addFilterDropdownSearch : 'header'
3197
- "
3198
- >
3199
- <input
3200
- class="form-check-input"
3201
- type="checkbox"
3202
- [value]="option"
3203
- [checked]="
3204
- col.query?._ids?.includes(option?._id || option?.id || option)
3205
- "
3206
- (change)="onOptionToggle(col, option)"
3207
- id="option_{{ col.field }}_{{
3208
- option?.id || option?._id || option
3209
- }}"
3210
- />
3211
- <label
3212
- class="form-check-label"
3213
- [for]="
3214
- 'option_' +
3215
- col.field +
3216
- '_' +
3217
- (option?.id || option?._id || option)
3218
- "
3219
- >
3220
- {{ option.value || option }}
3221
- </label>
3222
- </div>
3223
- </div>
3224
-
3225
- <!-- Actions -->
3226
- <!-- <div class="d-flex gap-2 mt-2">
3227
- <div
3228
- class="btn btn-sm btn-primary d-flex justify-content-center align-items-center"
3229
- style="height: 22px;"
3230
- (click)="applySideFilter(col)"
3231
- >
3232
- Apply
3233
- </div>
3234
- <div
3235
- class="btn btn-sm btn-secondary d-flex justify-content-center align-items-center"
3236
- style="height: 22px;"
3237
- (click)="resetSideFilter(col)"
3238
- >
3239
- Reset
3240
- </div>
3241
- </div> -->
3242
- </div>
3243
- </ng-container>
3244
-
3245
- <!-- Text Filter Section -->
3246
- <ng-template #textFilter>
3247
- <div class="filter-text-section">
3248
- <div class="form-group mb-2">
3249
- <select
3250
- class="form-select form-select-sm"
3251
- [(ngModel)]="col!.query!.first_condition"
3252
- >
3253
- <ng-container *ngIf="col.type !== 'date'">
3254
- <option value="contain">Contains</option>
3255
- <option value="equal">Equals</option>
3256
- <option value="before">Starts With</option>
3257
- <option value="after">Ends With</option>
3258
- </ng-container>
3259
-
3260
- <ng-container *ngIf="col.type == 'date'">
3261
- <option value="equal">Equals To</option>
3262
- <option value="after">After</option>
3263
- <option value="before">Before</option>
3264
- </ng-container>
3265
- </select>
3266
- </div>
3267
-
3268
- <input
3269
- [type]="col.type == 'date' ? 'date' : 'text'"
3270
- class="form-control form-control-sm mb-3"
3271
- placeholder="Value"
3272
- [(ngModel)]="col!.query!.firt_value"
3273
- />
3274
-
3275
- <ng-container *ngIf="col?.query?.firt_value">
3276
- <div class="form-group mb-2">
3277
- <div class="form-check form-check-inline">
3278
- <input
3279
- class="form-check-input filter-radio-inputs"
3280
- type="radio"
3281
- name="condition"
3282
- [(ngModel)]="col!.query.condition"
3283
- value="and"
3284
- id="and_{{ col.field }}"
3285
- />
3286
- <label class="form-check-label" for="and_{{ col.field }}"
3287
- >AND</label
3288
- >
3289
- </div>
3290
- <div class="form-check form-check-inline">
3291
- <input
3292
- class="form-check-input filter-radio-inputs"
3293
- type="radio"
3294
- name="condition"
3295
- [(ngModel)]="col!.query.condition"
3296
- value="or"
3297
- id="or_{{ col.field }}"
3298
- />
3299
- <label class="form-check-label" for="or_{{ col.field }}"
3300
- >OR</label
3301
- >
3302
- </div>
3303
- </div>
3304
-
3305
- <div class="form-group mb-2">
3306
- <select
3307
- class="form-select form-select-sm"
3308
- [(ngModel)]="col!.query.second_condition"
3309
- >
3310
- <ng-container *ngIf="col.type !== 'date'">
3311
- <option value="contain">Contains</option>
3312
- <option value="equal">Equals</option>
3313
- <option value="before">Starts With</option>
3314
- <option value="after">Ends With</option>
3315
- </ng-container>
3316
-
3317
- <ng-container *ngIf="col.type == 'date'">
3318
- <option value="equal">Equals To</option>
3319
- <option value="after">After</option>
3320
- <option value="before">Before</option>
3321
- </ng-container>
3322
- </select>
3323
- </div>
3324
-
3325
- <input
3326
- [type]="col.type == 'date' ? 'date' : 'text'"
3327
- class="form-control form-control-sm mb-2"
3328
- placeholder="Second Value"
3329
- [(ngModel)]="col!.query.second_value"
3330
- />
3331
- </ng-container>
3332
- <!-- <div class="d-flex gap-2">
3333
- <div class="btn btn-sm btn-primary d-flex justify-content-center align-items-center" style="height: 22px;" (click)="applyDropdownFilter()">apply</div>
3334
- <div class="btn btn-sm btn-secondary d-flex justify-content-center align-items-center" style="height: 22px;" (click)="applyDropdownFilter()">reset</div>
3335
-
3336
- </div> -->
3337
- </div>
3338
- </ng-template>
3339
- </div>
3340
- </ng-template>
3341
-
3342
- <!-- Centr Overlay for showing the chose columns -->
3343
-
3344
- <div *ngIf="showColumnPanel" class="custom-modal-overlay">
3345
- <div
3346
- class="custom-modal-content"
3347
- [style.backgroundColor]="dropdownsBackgroundColor"
3348
- (click)="$event.stopPropagation()"
3349
- >
3350
- <ng-container *ngTemplateOutlet="modalColumnPannel"></ng-container>
3351
- </div>
3352
- </div>
3353
-
3354
- <!-- The existing ng-template you provided -->
3355
- <ng-template #modalColumnPannel>
3356
- <div class="column-panel-header">
3357
- <div
3358
- class="d-flex justify-content-between align-items-center px-2 ps-3 rounded-top-2 moda-header"
3359
- [style.height.px]="48"
3360
- >
3361
- Choose Columns
3362
- <span class="filter-icon-wrapper" (click)="closeModalColumnPanel()"
3363
- ><span
3364
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/x.svg'"
3365
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
3366
- ></span
3367
- ></span>
3368
- </div>
3369
- <hr class="my-0" />
3370
- <div>
3371
- <div class="d-flex align-items-center px-2 pe-3" [style.height.px]="48">
3372
- <span class="filter-icon-wrapper me-2" *ngIf="showColumnsGrouping">
3373
- <span
3374
- class="toggle-icon data-grid-svg-icon"
3375
- [inlineSVG]="
3376
- accordionState === 'all'
3377
- ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'
3378
- : accordionState === 'some'
3379
- ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'
3380
- : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'
3381
- "
3382
- (click)="toggleAllAccordions()"
3383
- ></span>
3384
- </span>
3385
- <input
3386
- type="checkbox"
3387
- class="form-check-input me-2"
3388
- [checked]="allColumnsSelected()"
3389
- (change)="toggleAllColumnsVisibility()"
3390
- />
3391
- <input
3392
- type="text"
3393
- class="form-control form-control-sm"
3394
- placeholder="Search columns..."
3395
- [(ngModel)]="choseColumnsSearch"
3396
- />
3397
- </div>
3398
-
3399
- <hr class="mt-0 mb-1" />
3400
- <div class="px-2 overlay-scrollable">
3401
- <ng-container
3402
- *ngFor="
3403
- let col of columns | filter : choseColumnsSearch : 'header';
3404
- trackBy: trackByField
3405
- "
3406
- >
3407
- <ng-container
3408
- *ngTemplateOutlet="columnPanelItem; context: { col: col }"
3409
- ></ng-container>
3410
- </ng-container>
3411
- </div>
3412
- </div>
3413
- </div>
3414
- </ng-template>
3415
-
3416
- <ng-template #sideMenuRowGroups>
3417
- <div class="d-flex flex-column h-100 d-none">
3418
- <div class="px-3 h-100">
3419
- <div class="d-flex gap-3 mb-4">
3420
- <span
3421
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/justify.svg'"
3422
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
3423
- ></span>
3424
- <span>Row Groups</span>
3425
- </div>
3426
- <div class="h-50">
3427
- <div
3428
- class="px-3 py-2 border-dashed h-100 d-flex justify-content-center align-items-center"
3429
- style="font-size: 14px"
3430
- >
3431
- Drag here to set row Groups
3432
- </div>
3433
- </div>
3434
- </div>
3435
-
3436
- <hr class="mt-4" />
3437
-
3438
- <div class="px-3 h-100">
3439
- <div class="d-flex gap-3 mb-4">
3440
- <span
3441
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/justify.svg'"
3442
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
3443
- ></span>
3444
- <span>Values</span>
3445
- </div>
3446
- <div class="h-50 d-flex">
3447
- <div
3448
- class="px-3 py-2 border-dashed h-100 d-flex justify-content-center align-items-center"
3449
- style="font-size: 14px"
3450
- >
3451
- Drag here aggregate
3452
- </div>
3453
- </div>
3454
- </div>
3455
- </div>
3456
- </ng-template>
3457
-
3458
- <!-- *************************************************** -->
3459
- <!-- *************************************************** -->
3460
- <!-- *************************************************** -->
3461
- <!-- Drag Preview Template -->
3462
- <!-- *************************************************** -->
3463
- <!-- *************************************************** -->
3464
- <ng-template #dragPreview let-col>
3465
- <div class="p-2 border d-flex gap-2">
3466
- <div>
3467
- <span
3468
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'"
3469
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
3470
- ></span>
3471
- </div>
3472
- <div>{{ col.header }}</div>
3473
- </div>
3474
- </ng-template>
3475
-
3476
- <!-- Drag Placeholder Template -->
3477
- <ng-template
3478
- #dragPlaceholder
3479
- let-col
3480
- let-i="index"
3481
- let-section="section"
3482
- let-draggingInGroupArea="draggingInGroupArea"
3483
- >
3484
- <div *ngIf="!draggingInGroupArea">
3485
- <div
3486
- *ngTemplateOutlet="
3487
- headerCell;
3488
- context: { $implicit: col, index: i, section: section }
3489
- "
3490
- ></div>
3491
- </div>
3492
- <div *ngIf="draggingInGroupArea">New Placeholder</div>
3493
- </ng-template>
3494
-
3495
- <!-- Top Group Row Placeholder -->
3496
- <ng-template #topGroupingRowPlaceholder let-col let-showChevron="showChevron">
3497
- <div class="d-flex gap-2">
3498
- <div
3499
- class="d-flex gap-2 top-row-grouping-placeholder"
3500
- [style.backgroundColor]="topGroupedBadgesBackgroundColor"
3501
- >
3502
- <span
3503
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'"
3504
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
3505
- ></span>
3506
- <span>{{ col.header }}</span>
3507
- <span
3508
- (click)="ungroupColumn(col)"
3509
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/x.svg'"
3510
- class="cursor-pointer data-grid-svg-icon d-flex justify-content-center align-items-center"
3511
- ></span>
3512
- </div>
3513
- </div>
3514
- <div *ngIf="showChevron" style="opacity: 0.6; font-size: 14px">
3515
- <span
3516
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'"
3517
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
3518
- ></span>
3519
- </div>
3520
- </ng-template>
3521
-
3522
- <ng-template
3523
- #childHeaderPlaceholder
3524
- let-col
3525
- let-pinnedRight="pinnedRight"
3526
- let-i="index"
3527
- let-sections="sections"
3528
- >
3529
- <div
3530
- class="header-cell one-row-header-cells"
3531
- [class.border-right]="showVerticalBorder"
3532
- [style.width.px]="col.width"
3533
- [style.min-width.px]="col.width"
3534
- [style.min-height.px]="headerRowHeight"
3535
- [style.max-height.px]="headerRowHeight"
3536
- [class.border-right]="showVerticalBorder"
3537
- [style.fontWeight]="headerFontWeight"
3538
- >
3539
- <div class="d-flex justify-content-between h-100 align-items-center w-100">
3540
- <div
3541
- class="d-flex justify-content-between align-items-center w-100"
3542
- [class.flex-row-reverse]="pinnedRight"
3543
- >
3544
- <div
3545
- class="text-ellipsis h-100 d-flex align-items-center"
3546
- [title]="col.header"
3547
- [class.w-100]="pinnedRight"
3548
- >
3549
- {{ col.header }}
3550
- </div>
3551
-
3552
- <div
3553
- class="position-relative d-flex"
3554
- [class.flex-row-reverse]="pinnedRight"
3555
- >
3556
- <div class="three-dots p-1" style="cursor: pointer">
3557
- <span
3558
- [inlineSVG]="
3559
- singleSpaAssetsPath + 'data-grid/icons/three-dots-vertical.svg'
3560
- "
3561
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
3562
- ></span>
3563
- </div>
3564
-
3565
- <div class="resize-handle">
3566
- <span
3567
- [inlineSVG]="
3568
- singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'
3569
- "
3570
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
3571
- ></span>
3572
- </div>
3573
- </div>
3574
- </div>
3575
- </div>
3576
- </div>
3577
- <div
3578
- *ngIf="showFilterRow"
3579
- [style.backgroundColor]="headerBackgroundColor"
3580
- class="header-cell filter-cell"
3581
- [class.border-right]="showVerticalBorder"
3582
- [style.width.px]="col.width"
3583
- [style.min-width.px]="col.width"
3584
- [style.height.px]="headerRowHeight"
3585
- [style.min-height.px]="headerRowHeight"
3586
- [style.max-height.px]="headerRowHeight"
3587
- [class.border-right]="showVerticalBorder"
3588
- style="grid-row: 3"
3589
- >
3590
- <div
3591
- class="header-cell filter-cell"
3592
- [style.backgroundColor]="headerBackgroundColor"
3593
- [style.width.px]="col.width"
3594
- [style.min-width.px]="col.width"
3595
- [style.height.px]="headerRowHeight"
3596
- [style.min-height.px]="headerRowHeight"
3597
- [style.max-height.px]="headerRowHeight"
3598
- >
3599
- <input
3600
- type="text"
3601
- class="form-control form-control-sm"
3602
- placeholder="Filter"
3603
- [(ngModel)]="col.filterValue"
3604
- />
3605
- <span
3606
- class="filter-icon-wrapper"
3607
- (click)="activeFilterCell = col; activeCol = null"
3608
- ><span
3609
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'"
3610
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
3611
- ></span
3612
- ></span>
3613
-
3614
- <div
3615
- class="position-absolute"
3616
- *ngIf="activeFilterCell === col"
3617
- style="top: 100%; right: 0; z-index: 10; left: 0"
3618
- ></div>
3619
- </div>
3620
- </div>
3621
- </ng-template>
3622
-
3623
- <ng-template #tableLayout>
3624
- <div
3625
- (click)="$event.stopPropagation()"
3626
- class="p-3 shadow actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout"
3627
- style="width: 320px"
3628
- >
3629
- <div class="d-flex align-items-center mb-3">
3630
- <button
3631
- class="btn btn-link p-0"
3632
- style="margin-left: -10px"
3633
- (click)="toggleActions('setting')"
3634
- >
3635
- <span
3636
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'"
3637
- class="data-grid-svg-icon me-2"
3638
- ></span>
3639
- </button>
3640
- <h6 class="mb-0 ms-2" style="font-weight: 500">Table Layout</h6>
3641
- </div>
3642
- <hr class="my-2" />
3643
- <div class="w-100 mb-3 d-flex" role="group">
3644
- <input
3645
- type="radio"
3646
- class="btn-check layout-button-check"
3647
- name="layoutSize"
3648
- id="small"
3649
- autocomplete="off"
3650
- (change)="changeTableLayout($event, 'small')"
3651
- [checked]="selectedTableLayout == 'small'"
3652
- />
3653
- <label
3654
- class="border d-flex flex-column align-items-center layout-button"
3655
- for="small"
3656
- [ngStyle]="{
3657
- color: selectedTableLayout == 'small' ? '#000' : '#727272'
3658
- }"
3659
- >
3660
- <div class="preview-box border mb-1" style="height: 8px"></div>
3661
- Small
3662
- </label>
3663
-
3664
- <input
3665
- type="radio"
3666
- class="btn-check layout-button-check"
3667
- name="layoutSize"
3668
- id="medium"
3669
- autocomplete="off"
3670
- [checked]="selectedTableLayout == 'medium'"
3671
- (change)="changeTableLayout($event, 'medium')"
3672
- />
3673
- <label
3674
- class="border mx-3 d-flex flex-column align-items-center layout-button"
3675
- for="medium"
3676
- [ngStyle]="{
3677
- color: selectedTableLayout == 'medium' ? '#000' : '#727272'
3678
- }"
3679
- >
3680
- <div class="preview-box border mb-1" style="height: 12px"></div>
3681
- Medium
3682
- </label>
3683
-
3684
- <input
3685
- type="radio"
3686
- class="btn-check layout-button-check"
3687
- name="layoutSize"
3688
- id="large"
3689
- autocomplete="off"
3690
- (change)="changeTableLayout($event, 'large')"
3691
- [checked]="selectedTableLayout == 'large'"
3692
- />
3693
- <label
3694
- class="border d-flex flex-column align-items-center layout-button"
3695
- for="large"
3696
- [ngStyle]="{
3697
- color: selectedTableLayout == 'large' ? '#000' : '#727272'
3698
- }"
3699
- >
3700
- <div class="preview-box border mb-1" style="height: 16px"></div>
3701
- Large
3702
- </label>
3703
- </div>
3704
-
3705
- <hr class="my-2" />
3706
- <div class="d-flex justify-content-between align-items-center mb-2">
3707
- <span>Show separators</span>
3708
- <div class="form-check form-switch m-0">
3709
- <input
3710
- class="form-check-input"
3711
- type="checkbox"
3712
- id="separators"
3713
- [(ngModel)]="showVerticalBorder"
3714
- (change)="onFontChange()"
3715
- />
3716
- </div>
3717
- </div>
3718
- <div class="d-flex justify-content-between align-items-center">
3719
- <span>Row shading</span>
3720
- <div class="form-check form-switch m-0">
3721
- <input
3722
- class="form-check-input"
3723
- [(ngModel)]="rowShadingEnabled"
3724
- (change)="toggleRowShading()"
3725
- type="checkbox"
3726
- id="rowShading"
3727
- />
3728
- </div>
3729
- </div>
3730
- </div>
3731
- </ng-template>
3732
-
3733
- <ng-template #tablePreset>
3734
- <div
3735
- *ngIf="activeSubButton !== 'save-preset'"
3736
- (click)="$event.stopPropagation()"
3737
- class="p-3 shadow actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout"
3738
- style="width: 280px"
3739
- >
3740
- <!-- Header -->
3741
- <div class="d-flex justify-content-between align-items-center mb-3">
3742
- <div class="d-flex align-items-center">
3743
- <button
3744
- class="btn btn-link p-0"
3745
- style="margin-left: -10px"
3746
- (click)="toggleActions('setting')"
3747
- >
3748
- <span
3749
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'"
3750
- class="data-grid-svg-icon"
3751
- ></span>
3752
- </button>
3753
- <h6 class="mb-0 ms-2" style="font-weight: 500">Table Presets</h6>
3754
- </div>
3755
- <!-- Save Preset Button with Dropdown -->
3756
- <div>
3757
- <a
3758
- class="text-decoration-none"
3759
- type="button"
3760
- id="savePresetDropdown"
3761
- (click)="$event.stopPropagation(); toggleSubActions('save-preset')"
3762
- >
3763
- Save Preset
3764
- </a>
3765
- </div>
3766
- </div>
3767
-
3768
- <!-- Search -->
3769
- <div class="mb-3">
3770
- <div class="col-12 global-search">
3771
- <span
3772
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/search.svg'"
3773
- class="data-grid-svg-icon mx-2 position-absolute icon"
3774
- ></span>
3775
- <input
3776
- class="form-control form-control-sm"
3777
- placeholder="Search..."
3778
- [(ngModel)]="searchTextPresetTable"
3779
- type="search"
3780
- />
3781
- </div>
3782
- </div>
3783
-
3784
- <!-- Preset List -->
3785
- <ng-container
3786
- *ngIf="
3787
- tableView | filter : searchTextPresetTable : 'name' as filteredList
3788
- "
3789
- >
3790
- <!-- If filteredList exists and none is default -> show fallback -->
3791
- <div class="cursor-pointer" (click)="clearAllFilters(); openIndex = null">
3792
- <div class="fw-semibold">Default View</div>
3793
- </div>
3794
- <div class="d-flex justify-content-between">
3795
- <small class="text-dark">Created by system</small>
3796
- <span
3797
- *ngIf="!tableFilterViewId"
3798
- class="badge bg-light text-primary ms-2"
3799
- >Default</span
3800
- >
3801
- <span
3802
- *ngIf="!tableFilterViewId"
3803
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'"
3804
- class="me-2"
3805
- ></span>
3806
- <div
3807
- class="dropdown d-flex justify-content-end"
3808
- *ngIf="tableFilterViewId"
3809
- ></div>
3810
- </div>
3811
-
3812
- <!-- The list: render each table from filteredList -->
3813
- <div
3814
- class="list-group list-group-flush"
3815
- *ngFor="let table of filteredList; let i = index; trackBy: trackByTable"
3816
- >
3817
- <!-- Item -->
3818
- <div
3819
- (click)="$event.stopPropagation(); openIndex = null"
3820
- class="list-group-item px-0 d-flex justify-content-between align-items-center"
3821
- >
3822
- <div (click)="selectFilter(table); openIndex = null">
3823
- <div class="fw-semibold" style="cursor: pointer">
3824
- {{ table?.name }}
3825
- <!-- {{table?.is_temp}} -->
3826
- <span
3827
- *ngIf="table?.is_temp"
3828
- [inlineSVG]="
3829
- singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'
3830
- "
3831
- class="me-2"
3832
- ></span>
3833
- <span
3834
- *ngIf="table?.is_deafult"
3835
- class="badge bg-light text-primary ms-2"
3836
- >Default</span
3837
- >
3838
- </div>
3839
- <small class="text-dark"
3840
- >Created {{ table?.createdAt | date : "MMM d, y" }}</small
3841
- >
3842
- </div>
3843
-
3844
- <div class="d-flex align-items-center">
3845
- <span
3846
- *ngIf="table?.is_deafult"
3847
- [inlineSVG]="
3848
- singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'
3849
- "
3850
- class="me-2"
3851
- ></span>
3852
-
3853
- <div class="dropdown" *ngIf="!table?.is_deafult">
3854
- <div class="dropdown-wrapper" (click)="$event.stopPropagation()">
3855
- <button
3856
- type="button"
3857
- class="btn-icon muted-text"
3858
- (click)="toggleMenu(i, $event)"
3859
- aria-haspopup="true"
3860
- [attr.aria-expanded]="openIndex === i"
3861
- >
3862
- <span
3863
- [inlineSVG]="
3864
- singleSpaAssetsPath +
3865
- 'data-grid/icons/horizontal-dots.svg'
3866
- "
3867
- class="me-2"
3868
- ></span>
3869
- </button>
3870
-
3871
- <!-- menu -->
3872
- <ul
3873
- *ngIf="openIndex === i"
3874
- class="custom-dropdown-menu"
3875
- role="menu"
3876
- >
3877
- <li role="none">
3878
- <button
3879
- role="menuitem"
3880
- class="dropdown-item"
3881
- (click)="actionPreset(table, 'setPreset')"
3882
- >
3883
- <span
3884
- [inlineSVG]="
3885
- singleSpaAssetsPath + 'data-grid/icons/star.svg'
3886
- "
3887
- class="me-2"
3888
- ></span>
3889
- Set as default
3890
- </button>
3891
- </li>
3892
-
3893
- <li role="none" *ngIf="!table.confirmDelete">
3894
- <button
3895
- role="menuitem"
3896
- class="dropdown-item text-danger"
3897
- (click)="table.confirmDelete = true"
3898
- >
3899
- <span
3900
- style="margin-top: -4px"
3901
- [inlineSVG]="
3902
- singleSpaAssetsPath + 'data-grid/icons/trash-red.svg'
3903
- "
3904
- class="me-2"
3905
- ></span>
3906
- Delete
3907
- </button>
3908
- </li>
3909
-
3910
- <li
3911
- role="none"
3912
- *ngIf="table.confirmDelete"
3913
- class="confirm-block"
3914
- >
3915
- <div class="px-3 py-2 text-center">
3916
- <div class="mb-2">
3917
- Are you sure you want to delete <br /><b
3918
- >“{{ table?.name }}”</b
3919
- >?
3920
- </div>
3921
- <button
3922
- class="btn btn-sm btn-light me-2"
3923
- (click)="table.confirmDelete = false"
3924
- >
3925
- Cancel
3926
- </button>
3927
- <button
3928
- class="btn btn-sm btn-danger"
3929
- (click)="actionPreset(table, 'deletePreset')"
3930
- >
3931
- Delete
3932
- </button>
3933
- </div>
3934
- </li>
3935
- </ul>
3936
- </div>
3937
- </div>
3938
- </div>
3939
- </div>
3940
- <!-- Item End Here -->
3941
- </div>
3942
- </ng-container>
3943
- </div>
3944
-
3945
- <div
3946
- (click)="$event.stopPropagation()"
3947
- *ngIf="activeSubButton == 'save-preset'"
3948
- class="dropdown-menu p-3 badge mt-4 save-preset-dropdown mt-1"
3949
- aria-labelledby="savePresetDropdown"
3950
- style="min-width: 250px"
3951
- >
3952
- <div class="fw-bold fs-14px mb-2">Save preset</div>
3953
- <div class="fs-14px mb-2" style="line-height: 20px">
3954
- This will save the current table adjustments as a preset.
3955
- </div>
3956
- <!-- Input -->
3957
- <div class="mb-2">
3958
- <label for="presetName" class="form-label fs-12px fw-bold"
3959
- >Preset Name</label
3960
- >
3961
- <div class="col-12 global-search">
3962
- <input
3963
- #presetNameCtrl="ngModel"
3964
- required
3965
- [(ngModel)]="presetName"
3966
- [ngClass]="{
3967
- 'is-invalid':
3968
- presetNameCtrl.invalid &&
3969
- (presetNameCtrl.dirty || presetNameCtrl.touched)
3970
- }"
3971
- class="form-control form-control-sm ps-2"
3972
- placeholder="Enter preset name"
3973
- type="text"
3974
- />
3975
- </div>
3976
- </div>
3977
-
3978
- <!-- Checkbox -->
3979
- <div class="form-check mb-2">
3980
- <input
3981
- class="form-check-input"
3982
- [(ngModel)]="presetFilter"
3983
- type="checkbox"
3984
- id="saveFilters"
3985
- />
3986
- <label class="form-check-label mt-1" for="saveFilters">
3987
- Save active filters
3988
- </label>
3989
- </div>
3990
-
3991
- <!-- Save Button -->
3992
- <div class="d-flex justify-content-center gap-2" style="height: 32px">
3993
- <button
3994
- type="button"
3995
- style="height: 32px"
3996
- class="btn border w-100 d-flex align-items-center justify-content-center btn-light"
3997
- (click)="$event.stopPropagation(); toggleActions('table-presets')"
3998
- style="margin-top: -2px"
3999
- >
4000
- <span>Cancel</span>
4001
- </button>
4002
- <button
4003
- [disabled]="closeDropdown.preset.loading"
4004
- (click)="savePreset(presetNameCtrl)"
4005
- type="button"
4006
- style="height: 32px"
4007
- class="btn btn-primary w-100 d-flex align-items-center justify-content-center"
4008
- >
4009
- <span style="margin-top: -2px">
4010
- <ng-container *ngIf="!closeDropdown.preset.loading"
4011
- >Save</ng-container
4012
- >
4013
- <ng-container *ngIf="closeDropdown.preset.loading"
4014
- ><span class="spinner-border spinner-border-sm"></span
4015
- ></ng-container>
4016
- </span>
4017
- </button>
4018
- </div>
4019
- </div>
4020
- </ng-template>
4021
-
4022
- <ng-template #showHideColumns>
4023
- <div
4024
- (click)="$event.stopPropagation()"
4025
- class="p-3 shadow actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout"
4026
- style="width: 280px"
4027
- >
4028
- <!-- Header -->
4029
- <div class="d-flex justify-content-between align-items-center mb-3">
4030
- <div class="d-flex align-items-center">
4031
- <button
4032
- class="btn btn-link p-0"
4033
- style="margin-left: -10px"
4034
- (click)="toggleActions('setting')"
4035
- >
4036
- <span
4037
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'"
4038
- class="data-grid-svg-icon"
4039
- ></span>
4040
- </button>
4041
- <h6 class="mb-0 ms-2" style="font-weight: 500">Columns</h6>
4042
- </div>
4043
- <a
4044
- (click)="resetColumns()"
4045
- href="javascript:void(0)"
4046
- class="text-primary text-decoration-none"
4047
- >Reset</a
4048
- >
4049
- </div>
4050
-
4051
- <!-- Search -->
4052
- <div class="mb-3">
4053
- <div class="col-12 global-search">
4054
- <span
4055
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/search.svg'"
4056
- class="mx-2 position-absolute icon data-grid-svg-icon"
4057
- ></span>
4058
- <input
4059
- class="form-control form-control-sm"
4060
- placeholder="Search column"
4061
- type="search"
4062
- [(ngModel)]="topShowHideColumns"
4063
- />
4064
- </div>
4065
- </div>
4066
- <!-- Preset List -->
4067
- <div
4068
- class="list-group list-group-flush"
4069
- style="
4070
- max-height: calc(100vh - 300px);
4071
- overflow: auto;
4072
- scrollbar-width: thin;
4073
- "
4074
- >
4075
- <div class="muted-text show-hide-table-label" *ngIf="hasAnyVisibleColumn">
4076
- Show in table
4077
- </div>
4078
- <!-- Item -->
4079
- <ng-container
4080
- *ngFor="
4081
- let col of columns | filter : topShowHideColumns : 'header';
4082
- trackBy: trackByField
4083
- "
4084
- >
4085
- <div
4086
- *ngIf="col.is_visible"
4087
- class="list-group-item border-0 px-0 d-flex justify-content-between align-items-center"
4088
- [class.disabled]="getVisibleColumnCount(columns) <= 2"
4089
- >
4090
- <div class="d-flex gap-1">
4091
- <div>
4092
- <span
4093
- *ngIf="!col?.pinned"
4094
- [inlineSVG]="
4095
- singleSpaAssetsPath + 'data-grid/icons/grip-vertical.svg'
4096
- "
4097
- class="cursor-grap data-grid-svg-icon"
4098
- (mousedown)="$event.preventDefault()"
4099
- ></span>
4100
- <span
4101
- *ngIf="col?.pinned"
4102
- [inlineSVG]="
4103
- singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'
4104
- "
4105
- class="cursor-grap data-grid-svg-icon"
4106
- (mousedown)="$event.preventDefault()"
4107
- ></span>
4108
- </div>
4109
- <div class="fw-semibold">
4110
- {{ col.header }}
4111
- </div>
4112
- </div>
4113
- <div
4114
- *ngIf="!col?.query?.first_value && !col?.query?._ids?.length"
4115
- class="d-flex align-items-center cursor-pointer"
4116
- (click)="toggleColumnVisibility(col, false)"
4117
- >
4118
- <span
4119
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/eye.svg'"
4120
- class="data-grid-svg-icon me-2"
4121
- ></span>
4122
- </div>
4123
- <div
4124
- *ngIf="col?.query?.first_value || col?.query?._ids?.length"
4125
- class="d-flex align-items-center"
4126
- style="opacity: 0.5"
4127
- >
4128
- <span
4129
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/eye.svg'"
4130
- class="data-grid-svg-icon me-2"
4131
- ></span>
4132
- </div>
4133
- </div>
4134
- </ng-container>
4135
-
4136
- <!-- Item End Here -->
4137
-
4138
- <div
4139
- class="dropdown-divider"
4140
- *ngIf="hasAnyVisibleColumn && hasAnyInVisibleColumn"
4141
- ></div>
4142
-
4143
- <div
4144
- class="muted-text show-hide-table-label"
4145
- *ngIf="hasAnyInVisibleColumn"
4146
- >
4147
- Hide in table
4148
- </div>
4149
- <div class="list-group list-group-flush">
4150
- <ng-container *ngFor="let col of columns; trackBy: trackByField">
4151
- <div
4152
- *ngIf="!col.is_visible"
4153
- class="list-group-item border-0 px-0 d-flex justify-content-between align-items-center"
4154
- >
4155
- <div class="d-flex gap-1">
4156
- <div>
4157
- <span
4158
- *ngIf="!col?.pinned"
4159
- [inlineSVG]="
4160
- singleSpaAssetsPath + 'data-grid/icons/grip-vertical.svg'
4161
- "
4162
- class="data-grid-svg-icon cursor-grap"
4163
- (mousedown)="$event.preventDefault()"
4164
- ></span>
4165
- <span
4166
- *ngIf="col?.pinned"
4167
- [inlineSVG]="
4168
- singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'
4169
- "
4170
- class="data-grid-svg-icon cursor-grap"
4171
- (mousedown)="$event.preventDefault()"
4172
- ></span>
4173
- </div>
4174
- <div class="fw-semibold">
4175
- {{ col.header }}
4176
- </div>
4177
- </div>
4178
- <div
4179
- class="d-flex align-items-center cursor-pointer"
4180
- (click)="toggleColumnVisibility(col, true)"
4181
- >
4182
- <span
4183
- [inlineSVG]="
4184
- singleSpaAssetsPath + 'data-grid/icons/eye-cross.svg'
4185
- "
4186
- class="data-grid-svg-icon me-2"
4187
- ></span>
4188
- </div>
4189
- </div>
4190
- </ng-container>
4191
- </div>
4192
-
4193
- <!-- Item End Here -->
4194
- </div>
4195
- </div>
4196
- </ng-template>
4197
-
4198
- <ng-template #filterColumns let-col="column">
4199
- <div
4200
- @slideToggle
4201
- *ngIf="!isFilterOpen && activeTopButton == 'filter-columns'"
4202
- (click)="$event.stopPropagation()"
4203
- class="shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns"
4204
- style="width: 280px; right: unset; max-width: 230px"
4205
- >
4206
- <div class="mb-2 px-3">
4207
- <div class="col-12 global-search">
4208
- <span
4209
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/search.svg'"
4210
- class="data-grid-svg-icon mx-2 position-absolute icon"
4211
- ></span>
4212
- <input
4213
- class="form-control form-control-sm"
4214
- placeholder="Filter by"
4215
- type="search"
4216
- [(ngModel)]="addFilterColumnInput"
4217
- />
4218
- </div>
4219
- </div>
4220
- <div
4221
- class="list-group list-group-flush"
4222
- style="max-height: calc(100vh - 500px); overflow: auto; scrollbar-width: thin"
4223
- >
4224
- <ng-container
4225
- *ngFor="
4226
- let col of columns | filter : addFilterColumnInput : 'header';
4227
- trackBy: trackByField
4228
- "
4229
- >
4230
- <div
4231
- (click)="openFilter(col)"
4232
- *ngIf="
4233
- col.is_visible &&
4234
- !col?.query?.first_value &&
4235
- !col?.query?._ids?.length
4236
- "
4237
- class="list-group-item border-0 px-0 d-flex justify-content-between align-items-center dropdown-item cursor-pointer"
4238
- >
4239
- <div class="d-flex gap-1">
4240
- <div style="margin-top: -3px"></div>
4241
- <div class="fw-semibold">
4242
- {{ col.header }}
4243
- </div>
4244
- </div>
4245
- </div>
4246
- </ng-container>
4247
- </div>
4248
- </div>
4249
-
4250
- <!-- Dropdown -->
4251
- <div
4252
- @slideToggle
4253
- *ngIf="isFilterOpen && selectedColumnForFilter.type == 'dropdown'"
4254
- (click)="$event.stopPropagation()"
4255
- class="shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns"
4256
- style="width: 280px; right: unset; max-width: 230px"
4257
- >
4258
- <div class="px-3 my-2 border-below py-1 pb-2 mb-3 d-flex ps-1">
4259
- <span
4260
- (click)="toggleActions('filter-columns'); isActiveFilterOpen = false"
4261
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'"
4262
- class="data-grid-svg-icon me-2 cursor-pointer"
4263
- ></span
4264
- ><b>{{ selectedColumnForFilter?.header }}</b>
4265
- </div>
4266
- <div class="mb-2 px-3">
4267
- <div
4268
- class="col-12 global-search position-relative border rounded d-flex align-items-center flex-wrap px-2 filter-serach-inpt"
4269
- >
4270
- <span
4271
- *ngFor="let selected of selectedFilterOptions"
4272
- class="badge d-flex align-items-center gap-1 me-1 mb-1"
4273
- >
4274
- {{ selected?.value ? selected.value : selected }}
4275
- <span
4276
- (click)="toggleSelectionInFilter(selected)"
4277
- [inlineSVG]="
4278
- singleSpaAssetsPath + 'data-grid/icons/cross-primary.svg'
4279
- "
4280
- class="me-2"
4281
- ></span>
4282
- </span>
4283
- <input
4284
- class="form-control form-control-sm border-0 flex-grow-1"
4285
- style="padding: 0"
4286
- [placeholder]="selectedFilterOptions?.length ? '' : 'Filter by'"
4287
- type="search"
4288
- [(ngModel)]="searchTextForFilterDropDown"
4289
- (keydown.backspace)="handleBackspace($event)"
4290
- />
4291
- </div>
4292
- </div>
4293
- <div
4294
- class="list-group list-group-flush"
4295
- style="max-height: calc(100vh - 600px); overflow: auto"
4296
- >
4297
- <ng-container
4298
- *ngFor="
4299
- let col of selectedColumnForFilter.column_dropdown_value
4300
- | filter : searchTextForFilterDropDown : 'value';
4301
- let i = index
4302
- "
4303
- >
4304
- <div
4305
- class="list-group-item border-0 px-2 d-flex justify-content-between align-items-center dropdown-item cursor-pointer"
4306
- >
4307
- <div class="form-check">
4308
- <input
4309
- class="form-check-input"
4310
- type="checkbox"
4311
- [id]="i"
4312
- [checked]="currentFilterSelectedIds.has(col.id || col._id || col)"
4313
- (change)="toggleSelectionInFilter(col)"
4314
- />
4315
- <label class="form-check-label fw-semibold" [for]="i">
4316
- {{ col?.value || col?.name || col }}
4317
- </label>
4318
- </div>
4319
- </div>
4320
- </ng-container>
4321
- </div>
4322
- <div
4323
- class="d-flex justify-content-center gap-2 px-2 border-top"
4324
- style="height: 38px"
4325
- >
4326
- <button
4327
- [disabled]="currentFilterSelectedIds?.size === 0 && !firstValue"
4328
- type="button"
4329
- style="height: 32px"
4330
- class="btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light"
4331
- (click)="$event.stopPropagation(); resetFilterChanges(); removeColumnFilterFromColumn(selectedColumnForFilter)"
4332
- >
4333
- <span>Reset</span>
4334
- </button>
4335
- <button
4336
- [disabled]="currentFilterSelectedIds?.size === 0 && !firstValue"
4337
- type="button"
4338
- style="height: 32px"
4339
- class="btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1"
4340
- (click)="applyDropdownFilter()"
4341
- >
4342
- <span style="margin-top: -2px">Save</span>
4343
- </button>
4344
- </div>
4345
- </div>
4346
-
4347
- <!-- For Text fields and number fields-->
4348
-
4349
- <div
4350
- @slideToggle
4351
- *ngIf="
4352
- isFilterOpen &&
4353
- (selectedColumnForFilter.type == 'string' ||
4354
- selectedColumnForFilter.type == 'number' ||
4355
- selectedColumnForFilter.type == 'date')
4356
- "
4357
- (click)="$event.stopPropagation()"
4358
- class="shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns"
4359
- style="width: 280px; right: unset; max-width: 230px"
4360
- >
4361
- <div class="px-3 border-below py-1 pb-2 d-flex ps-1">
4362
- <span
4363
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'"
4364
- (click)="toggleActions('filter-columns'); isActiveFilterOpen = false"
4365
- class="data-grid-svg-icon me-2 cursor-pointer"
4366
- ></span
4367
- ><b>{{ selectedColumnForFilter?.header }}</b>
4368
- </div>
4369
- <div class="col-12 position-relative p-2 text-filter">
4370
- <div class="mb-2">
4371
- <select
4372
- class="form-select form-select-sm custom-select"
4373
- [(ngModel)]="firstCondition"
4374
- >
4375
- <ng-container *ngIf="selectedColumnForFilter.type !== 'date'">
4376
- <option value="contain">Contains</option>
4377
- <option value="equal">Equals</option>
4378
- <option value="before">Starts With</option>
4379
- <option value="after">Ends With</option>
4380
- </ng-container>
4381
-
4382
- <ng-container *ngIf="selectedColumnForFilter.type == 'date'">
4383
- <option value="equal">Equals To</option>
4384
- <option value="after">After</option>
4385
- <option value="before">Before</option>
4386
- </ng-container>
4387
- </select>
4388
- </div>
4389
- <div class="mb-2">
4390
- <input
4391
- class="form-control form-control-sm"
4392
- placeholder="Enter first value"
4393
- type="search"
4394
- [type]="
4395
- selectedColumnForFilter.type == 'string'
4396
- ? 'text'
4397
- : selectedColumnForFilter.type
4398
- "
4399
- [(ngModel)]="firstValue"
4400
- (keydown.enter)="applyDropdownFilter()"
4401
- />
4402
- </div>
4403
- <div *ngIf="firstValue">
4404
- <div class="d-flex my-3">
4405
- <div class="form-check form-check-inline">
4406
- <input
4407
- class="form-check-input"
4408
- type="radio"
4409
- id="logicalAnd"
4410
- name="logicalOperator"
4411
- value="and"
4412
- [(ngModel)]="condition"
4413
- />
4414
- <label class="form-check-label" for="logicalAnd">AND</label>
4415
- </div>
4416
-
4417
- <div class="form-check form-check-inline">
4418
- <input
4419
- class="form-check-input"
4420
- type="radio"
4421
- id="logicalOr"
4422
- name="logicalOperator"
4423
- value="or"
4424
- [(ngModel)]="condition"
4425
- />
4426
- <label class="form-check-label" for="logicalOr">OR</label>
4427
- </div>
4428
-
4429
- <div class="form-check form-check-inline">
4430
- <input
4431
- class="form-check-input"
4432
- type="radio"
4433
- id="logicalNone"
4434
- name="logicalOperator"
4435
- value="none"
4436
- [(ngModel)]="condition"
4437
- />
4438
- <label class="form-check-label" for="logicalNone">None</label>
4439
- </div>
4440
- </div>
4441
-
4442
- <div class="my-3">
4443
- <!-- Second condition select -->
4444
- <select
4445
- class="form-select form-select-sm"
4446
- [(ngModel)]="secondCondition"
4447
- >
4448
- <ng-container *ngIf="selectedColumnForFilter.type !== 'date'">
4449
- <option value="contain">Contains</option>
4450
- <option value="equal">Equals</option>
4451
- <option value="before">Starts With</option>
4452
- <option value="after">Ends With</option>
4453
- </ng-container>
4454
-
4455
- <ng-container *ngIf="selectedColumnForFilter.type == 'date'">
4456
- <option value="equal">Equals To</option>
4457
- <option value="after">After</option>
4458
- <option value="before">Before</option>
4459
- </ng-container>
4460
- </select>
4461
- </div>
4462
-
4463
- <div class="mb-2">
4464
- <!-- Second value input -->
4465
- <input
4466
- [type]="
4467
- selectedColumnForFilter.type == 'string'
4468
- ? 'text'
4469
- : selectedColumnForFilter.type
4470
- "
4471
- class="form-control form-control-sm"
4472
- placeholder="Enter second value"
4473
- type="search"
4474
- [(ngModel)]="secondValue"
4475
- (keydown.enter)="applyDropdownFilter()"
4476
- />
4477
- </div>
4478
- </div>
4479
- </div>
4480
-
4481
- <div
4482
- class="d-flex justify-content-center gap-2 px-2 border-top"
4483
- style="height: 38px"
4484
- >
4485
- <button
4486
- [disabled]="!currentFilterSelectedIds?.size && !firstValue"
4487
- type="button"
4488
- style="height: 32px"
4489
- class="btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light"
4490
- (click)="$event.stopPropagation(); resetTextFilterChanges(); removeColumnFilterFromColumn(selectedColumnForFilter)"
4491
- >
4492
- <span>Reset</span>
4493
- </button>
4494
- <button
4495
- [disabled]="currentFilterSelectedIds?.size === 0 && !firstValue"
4496
- type="button"
4497
- style="height: 32px"
4498
- class="btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1"
4499
- (click)="applyDropdownFilter()"
4500
- >
4501
- <span style="margin-top: -2px">Save</span>
4502
- </button>
4503
- </div>
4504
- </div>
4505
- </ng-template>
4506
-
4507
- <!-- Edit dropdown here -->
4508
- <ng-template let-col>
4509
- <div class="drop-down-edit"></div>
4510
- </ng-template>
4511
-
4512
- <ng-template
4513
- #fullTextTemplate
4514
- let-row="row"
4515
- let-col="col"
4516
- let-isArray="isArray"
4517
- >
4518
- <div
4519
- class="full-text-box"
4520
- (dblclick)="$event.stopPropagation(); $event.preventDefault()"
4521
- (click)="$event.stopPropagation(); $event.preventDefault()"
4522
- >
4523
- <ng-container *ngIf="!isEditing(row, col)">
4524
- <div
4525
- *ngIf="!isArray"
4526
- class="full-text-content"
4527
- (dblclick)="
4528
- $event.stopPropagation();
4529
- $event.preventDefault();
4530
- enableEdit(row, col)
4531
- "
4532
- (click)="$event.stopPropagation(); $event.preventDefault()"
4533
- >
4534
- {{
4535
- getNestedValue(row, col.field)?.value ||
4536
- getNestedValue(row, col.field)?.name ||
4537
- getNestedValue(row, col.field)
4538
- }}
4539
- </div>
4540
- <div *ngIf="isArray">
4541
- <ul>
4542
- <ng-container
4543
- *ngFor="let item of getNestedValue(row, col.field); let i = index"
4544
- >
4545
- <li *ngIf="i !== 0">
4546
- <ng-container>
4547
- {{ item?.department_name || item?.roleName || "-" }}
4548
- </ng-container>
4549
- </li>
4550
- </ng-container>
4551
- </ul>
4552
- </div>
4553
- </ng-container>
4554
- <ng-container *ngIf="isEditing(row, col)">
4555
- <textarea
4556
- #textModel="ngModel"
4557
- rows="4"
4558
- #textAreadInput
4559
- [(ngModel)]="row[col.field]"
4560
- name="{{ col.field }}"
4561
- required
4562
- (blur)="disableEdit(row, col, textModel)"
4563
- (keydown.enter)="textAreadInput.blur()"
4564
- autofocus
4565
- class="form-control"
4566
- [ngClass]="{
4567
- 'is-invalid': textModel.invalid
4568
- }"
4569
- (mousedown)="$event.stopPropagation()"
4570
- ></textarea>
4571
- </ng-container>
4572
- </div>
4573
- </ng-template>
4574
-
4575
- <ng-template #defaultImagePlaceholder let-row="row" let-col="col">
4576
- <span
4577
- class="px-2 d-flex w-100 cell-content image-placeholder"
4578
- [title]="row?.full_name || row?.name || 'N/A'"
4579
- >
4580
- <ng-container
4581
- *ngIf="
4582
- row?.logo ||
4583
- row?.assetImage ||
4584
- row?.invoice?.invoice_image ||
4585
- row?.invoice_image;
4586
- else placeholder
4587
- "
4588
- >
4589
- <span class="pic" [class.assets-pic]="gridType == 'Assets'">
4590
- <img
4591
- [width]="rowHeight - 12"
4592
- [height]="rowHeight - 12"
4593
- [src]="row?.profile_pictures?.[4]?.path || row?.logo || row?.assetImage || row?.invoice_image || row?.invoice_image"
4594
- alt="icon"
4595
- class="option-icon"
4596
- (click)="openFullScreenImage(
4597
- row?.profile_pictures?.[4]?.path ||
4598
- row?.logo ||
4599
- row?.assetImage ||
4600
- row?.invoice_image ||
4601
- row?.invoice_image
4602
- )"
4603
- />
4604
- </span>
4605
- </ng-container>
4606
- <div
4607
- class="fullscreen-overlay"
4608
- *ngIf="fullscreenImage"
4609
- (click)="fullscreenImage = null"
4610
- >
4611
- <img [src]="fullscreenImage" class="fullscreen-img" />
4612
- </div>
4613
-
4614
- <ng-template #placeholder>
4615
- <span
4616
- [ngClass]="getDynamicClass(row?.full_name || row?.name)"
4617
- class="pic d-flex align-items-center rounded-circle"
4618
- [style.width.px]="rowHeight - 12"
4619
- [style.height.px]="rowHeight - 12"
4620
- [style.fontSize.px]="rowHeight / 3"
4621
- [class.assets-pic]="gridType == 'Assets'"
4622
- >
4623
- {{ getInitials(row?.full_name) }}
4624
- </span>
4625
- </ng-template>
4626
- </span>
4627
- </ng-template>
4628
-
4629
- <!-- Right Click Menue -->
4630
- <div
4631
- [class.invisible]="!positionedYet"
4632
- class="context-menu p-2"
4633
- *ngIf="actionHide && actions?.length"
4634
- [ngStyle]="{ 'top.px': yPos, 'left.px': xPos }"
4635
- [class.show]="isVisible"
4636
- appendTo="body"
4637
- >
4638
- <ul>
4639
- <li
4640
- *ngFor="let action of actions"
4641
- class="rounded d-flex align-items-center"
4642
- (click)="onActionClick(action)"
4643
- >
4644
- <span
4645
- [inlineSVG]="singleSpaAssetsPath + 'data-grid/icons/' + action + '.svg'"
4646
- class="data-grid-svg-icon me-2"
4647
- ></span>
4648
- <span class="text-capitalize fw-500">{{ action }}</span>
4649
- </li>
4650
- </ul>
4651
- </div>
4652
-
4653
- <!-- Details Toggle from bottom -->
4654
- <div
4655
- [style.bottom.px]="footerRowHeight + 50"
4656
- *ngIf="selectedRows.size > 0 && showTaskbar"
4657
- class="taskbar"
4658
- >
4659
- <div class="selected-rows-action-bar" [@slideUp]>
4660
- <span class="selected-count">
4661
- {{ selectedRows.size }} selected of
4662
- {{ config?.paginationParams?.totalItems }} Total
4663
- </span>
4664
- <div class="action-buttons">
4665
- <ng-container *ngFor="let action of taskbarActions; let i = index">
4666
- <span
4667
- class="action-btn verified btn {{ action }}"
4668
- (click)="onVerifyClick(action)"
4669
- >{{ action }}</span
4670
- >
4671
- <span
4672
- *ngIf="taskbarActions.length > 1 && i !== taskbarActions.length - 1"
4673
- class="separator"
4674
- >|</span
4675
- >
4676
- </ng-container>
4677
- </div>
4678
- </div>
4679
- </div>
4680
-
4681
-
4682
-
4683
- <ng-template #nestedTableTemplate let-row>
4684
- <table
4685
- class="nested-table table table-sm w-100 mb-0 center-nested-table w-100"
4686
- style="table-layout: fixed !important"
4687
- >
4688
- <thead>
4689
- <tr
4690
- cdkDropList
4691
- [cdkDropListData]="row?.detail.columns"
4692
- cdkDropListOrientation="horizontal"
4693
- (cdkDropListDropped)="dropColumn($event, row)"
4694
- [style.height.px]="nestedTableHeaderRowHeight"
4695
- >
4696
- <th
4697
- [style.width]="getColumnWidthPx(row, col)"
4698
- (click)="sortNestedCol(col, row.detail.result)"
4699
- *ngFor="let col of row?.detail.columns; let i = index"
4700
- cdkDrag
4701
- class="px-4"
4702
- [style.backgroundColor]="nestedTableHeaderBAckgroundColor"
4703
- [attr.field]="col.field"
4704
- >
4705
- <div class="d-flex h-100 justify-content-between position-relative">
4706
- <div class="text-ellipsis">{{ col.header }}</div>
4707
- <div class="d-flex gap-2">
4708
- <span
4709
- *ngIf="currentSubSortColumn == col.field"
4710
- [inlineSVG]="
4711
- singleSpaAssetsPath +
4712
- (col?.order_by == 'desc'
4713
- ? 'data-grid/icons/sort-desc.svg'
4714
- : 'data-grid/icons/sort-asc.svg')
4715
- "
4716
- class="data-grid-svg-icon d-flex justify-content-center align-items-center ms-2 start-50"
4717
- >
4718
- </span>
4719
- <div
4720
- class="resize-handle"
4721
- (click)="$event.stopPropagation()"
4722
- (mousedown)="
4723
- $event.preventDefault();
4724
- onResizeColumn($event, col);
4725
- $event.stopPropagation()
4726
- "
4727
- >
4728
- <span
4729
- [inlineSVG]="
4730
- singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'
4731
- "
4732
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
4733
- ></span>
4734
- </div>
4735
- </div>
4736
- </div>
4737
- <ng-template cdkDragPreview>
4738
- <div class="p-2 border d-flex gap-2">
4739
- <div>
4740
- <span
4741
- [inlineSVG]="
4742
- singleSpaAssetsPath +
4743
- 'data-grid/icons/arrows-move.svg'
4744
- "
4745
- class="data-grid-svg-icon d-flex justify-content-center align-items-center"
4746
- ></span>
4747
- </div>
4748
- <div>{{ col.header }}</div>
4749
- </div>
4750
- </ng-template>
4751
- </th>
4752
- </tr>
4753
- </thead>
4754
- <tbody>
4755
- <tr
4756
- class="cursor-pointer"
4757
- [style.height.px]="nestedTablerowHeight"
4758
- *ngFor="let d of row?.detail?.result; trackBy: trackById"
4759
- >
4760
- <td
4761
- class="px-4 py-0"
4762
- [attr.field]="col.field"
4763
- *ngFor="let col of row.detail.columns; let j = index"
4764
- [style.fontSize.px]="nestedTablerowFontsize"
4765
- >
4766
- <div
4767
- [style.height.px]="nestedTablerowHeight - 1"
4768
- [style.max-width.px]="col?.width"
4769
- class="d-flex align-items-center"
4770
- >
4771
- <div class="w-100 text-ellipsis">
4772
- {{ d[col.field] || (col.is_amount ? 0 : "-") }}
4773
- </div>
4774
- </div>
4775
- </td>
4776
- </tr>
4777
- </tbody>
4778
- </table>
4779
- </ng-template>
4780
-
4781
- <ng-template #leftRightNestedPlaceholder let-row>
4782
- <table class="nested-table table table-sm w-100 mb-0">
4783
- <thead>
4784
- <tr
4785
- [style.height.px]="nestedTableHeaderRowHeight"
4786
- [style.backgroundColor]="headerBackgroundColor"
4787
- >
4788
- <th *ngFor="let _ of [1, 2, 3, 4, 5]"></th>
4789
- </tr>
4790
- </thead>
4791
- <tbody>
4792
- <tr
4793
- [style.height.px]="nestedTablerowHeight"
4794
- *ngFor="let _ of row?.detail?.result"
4795
- [style.backgroundColor]="headerBackgroundColor"
4796
- >
4797
- <td *ngFor="let __ of [1, 2, 3, 4, 5]" class="py-0">
4798
- <span
4799
- [style.height.px]="nestedTablerowHeight"
4800
- [style.max-width.px]="nestedTablerowHeight"
4801
- ></span>
4802
- </td>
4803
- </tr>
4804
- </tbody>
4805
- </table>
4806
- </ng-template>