ms-data-grid 0.0.89 → 0.0.90
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.
- package/README.md +323 -323
- package/esm2022/lib/data-grid/data-grid.component.mjs +258 -206
- package/esm2022/lib/data-grid/statuses.mjs +1 -1
- package/esm2022/lib/data-grid.module.mjs +1 -1
- package/esm2022/lib/directives/cell-editor.directive.mjs +1 -1
- package/esm2022/lib/directives/cell-render-init.directive.mjs +1 -1
- package/esm2022/lib/directives/cellHost.directive.mjs +1 -1
- package/esm2022/lib/pipes/filter.pipe.mjs +1 -1
- package/esm2022/lib/pipes/format-currency.pipe.mjs +1 -1
- package/esm2022/lib/pipes/format-index.pipe.mjs +1 -1
- package/esm2022/lib/services/common.service.mjs +7 -7
- package/esm2022/lib/services/copy-service.service.mjs +1 -1
- package/esm2022/lib/services/export.service.mjs +1 -1
- package/esm2022/lib/services/split-columns.service.mjs +2 -2
- package/esm2022/public-api.mjs +3 -2
- package/fesm2022/ms-data-grid.mjs +337 -283
- package/fesm2022/ms-data-grid.mjs.map +1 -1
- package/lib/data-grid/data-grid.component.d.ts +32 -10
- package/lib/styles/font-style.css +34 -0
- package/package.json +1 -1
- package/public-api.d.ts +0 -1
- package/esm2022/lib/interfaces/data-grid-config.ts.mjs +0 -2
- package/lib/interfaces/data-grid-config.ts.d.ts +0 -97
|
@@ -3,7 +3,7 @@ import { Directive, Injectable, inject, Pipe, EventEmitter, Injector, Input, Out
|
|
|
3
3
|
import * as i9 from '@angular/cdk/drag-drop';
|
|
4
4
|
import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
|
|
5
5
|
import { trigger, transition, query, style, animate, stagger, state } from '@angular/animations';
|
|
6
|
-
import {
|
|
6
|
+
import { take } from 'rxjs';
|
|
7
7
|
import * as i6 from '@angular/common';
|
|
8
8
|
import { DatePipe, CommonModule, TitleCasePipe } from '@angular/common';
|
|
9
9
|
import * as i4 from '@angular/platform-browser';
|
|
@@ -168,7 +168,7 @@ class SplitColumnsService {
|
|
|
168
168
|
// ✅ Total width already consumed
|
|
169
169
|
const usedWidth = fixedCols.reduce((sum, col) => sum + col.width, 0);
|
|
170
170
|
// ✅ Remaining width after fixed columns
|
|
171
|
-
let remainingWidth = containerWidth -
|
|
171
|
+
let remainingWidth = containerWidth - usedWidth;
|
|
172
172
|
if (remainingWidth < 0)
|
|
173
173
|
remainingWidth = 0;
|
|
174
174
|
// ✅ Average width for columns without width
|
|
@@ -229,7 +229,7 @@ class CommonService {
|
|
|
229
229
|
}
|
|
230
230
|
gethasVisibleColumns(columns) {
|
|
231
231
|
const checkVisible = (columns) => {
|
|
232
|
-
return columns
|
|
232
|
+
return columns?.some((col) => {
|
|
233
233
|
if (col?.is_visible)
|
|
234
234
|
return true;
|
|
235
235
|
if (col?.children?.length) {
|
|
@@ -242,7 +242,7 @@ class CommonService {
|
|
|
242
242
|
}
|
|
243
243
|
gethasInVisibleColumns(columns) {
|
|
244
244
|
const checkVisible = (columns) => {
|
|
245
|
-
return columns
|
|
245
|
+
return columns?.some((col) => {
|
|
246
246
|
if (!col?.is_visible)
|
|
247
247
|
return true;
|
|
248
248
|
if (col?.children?.length) {
|
|
@@ -255,7 +255,7 @@ class CommonService {
|
|
|
255
255
|
}
|
|
256
256
|
getTotalColumnsLength(columns) {
|
|
257
257
|
let count = 0;
|
|
258
|
-
columns
|
|
258
|
+
columns?.forEach(col => {
|
|
259
259
|
if (col.children && Array.isArray(col.children) && col.children.length) {
|
|
260
260
|
count += col.children.length; // count children instead of parent
|
|
261
261
|
}
|
|
@@ -267,7 +267,7 @@ class CommonService {
|
|
|
267
267
|
}
|
|
268
268
|
gethasRightPinnedColumns(columns) {
|
|
269
269
|
const checkPinnedRight = (columns) => {
|
|
270
|
-
return columns
|
|
270
|
+
return columns?.some((col) => {
|
|
271
271
|
if (col?.pinned === 'right' && col?.is_visible)
|
|
272
272
|
return true;
|
|
273
273
|
if (col?.children?.length) {
|
|
@@ -280,7 +280,7 @@ class CommonService {
|
|
|
280
280
|
}
|
|
281
281
|
gethasLeftPinnedColumns(columns) {
|
|
282
282
|
const checkPinnedRight = (columns) => {
|
|
283
|
-
return columns
|
|
283
|
+
return columns?.some((col) => {
|
|
284
284
|
if (col?.pinned === 'left' && col?.is_visible)
|
|
285
285
|
return true;
|
|
286
286
|
if (col?.children?.length) {
|
|
@@ -294,7 +294,7 @@ class CommonService {
|
|
|
294
294
|
getExpandedRowCount(data) {
|
|
295
295
|
let groupCount = 0;
|
|
296
296
|
let rowCount = 0;
|
|
297
|
-
data
|
|
297
|
+
data?.forEach(group => {
|
|
298
298
|
if (group?.isGroup) {
|
|
299
299
|
groupCount++;
|
|
300
300
|
if (group?.isExpand && Array.isArray(group?.children)) {
|
|
@@ -1031,79 +1031,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1031
1031
|
type: Output
|
|
1032
1032
|
}] } });
|
|
1033
1033
|
|
|
1034
|
-
class CellEditorDirective {
|
|
1035
|
-
constructor(vcr, injector) {
|
|
1036
|
-
this.vcr = vcr;
|
|
1037
|
-
this.injector = injector;
|
|
1038
|
-
// Parent component listens using:
|
|
1039
|
-
// (editorEvent)="finishEdit($event)"
|
|
1040
|
-
this.editorEvent = new EventEmitter();
|
|
1041
|
-
}
|
|
1042
|
-
ngOnInit() {
|
|
1043
|
-
if (!this.componentType)
|
|
1044
|
-
return;
|
|
1045
|
-
// ✅ Dynamically create the editor component
|
|
1046
|
-
const componentRef = this.vcr.createComponent(this.componentType, {
|
|
1047
|
-
injector: Injector.create({
|
|
1048
|
-
providers: [
|
|
1049
|
-
{ provide: 'rowData', useValue: this.rowData },
|
|
1050
|
-
{ provide: 'colData', useValue: this.colData },
|
|
1051
|
-
{ provide: 'cellValue', useValue: this.cellValue }
|
|
1052
|
-
],
|
|
1053
|
-
parent: this.injector
|
|
1054
|
-
})
|
|
1055
|
-
});
|
|
1056
|
-
// -----------------------------------------------
|
|
1057
|
-
// 1️⃣ Call custom lifecycle hook if it exists
|
|
1058
|
-
// -----------------------------------------------
|
|
1059
|
-
if (typeof componentRef.instance.editorInit === 'function') {
|
|
1060
|
-
componentRef.instance.editorInit({
|
|
1061
|
-
row: this.rowData,
|
|
1062
|
-
col: this.colData,
|
|
1063
|
-
value: this.cellValue
|
|
1064
|
-
});
|
|
1065
|
-
}
|
|
1066
|
-
// -----------------------------------------------
|
|
1067
|
-
// 2️⃣ Auto-detect all @Output() EventEmitters
|
|
1068
|
-
// -----------------------------------------------
|
|
1069
|
-
for (const key of Object.keys(componentRef.instance)) {
|
|
1070
|
-
const property = componentRef.instance[key];
|
|
1071
|
-
// Check if any property is an EventEmitter
|
|
1072
|
-
if (property instanceof EventEmitter) {
|
|
1073
|
-
property.subscribe((value) => {
|
|
1074
|
-
this.editorEvent.emit({
|
|
1075
|
-
eventName: key,
|
|
1076
|
-
data: {
|
|
1077
|
-
row: this.rowData,
|
|
1078
|
-
col: this.colData,
|
|
1079
|
-
value
|
|
1080
|
-
}
|
|
1081
|
-
});
|
|
1082
|
-
});
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellEditorDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1087
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: CellEditorDirective, selector: "[cellEditor]", inputs: { componentType: ["cellEditor", "componentType"], rowData: "rowData", colData: "colData", cellValue: "cellValue" }, outputs: { editorEvent: "editorEvent" }, ngImport: i0 }); }
|
|
1088
|
-
}
|
|
1089
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellEditorDirective, decorators: [{
|
|
1090
|
-
type: Directive,
|
|
1091
|
-
args: [{
|
|
1092
|
-
selector: '[cellEditor]'
|
|
1093
|
-
}]
|
|
1094
|
-
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.Injector }]; }, propDecorators: { componentType: [{
|
|
1095
|
-
type: Input,
|
|
1096
|
-
args: ['cellEditor']
|
|
1097
|
-
}], rowData: [{
|
|
1098
|
-
type: Input
|
|
1099
|
-
}], colData: [{
|
|
1100
|
-
type: Input
|
|
1101
|
-
}], cellValue: [{
|
|
1102
|
-
type: Input
|
|
1103
|
-
}], editorEvent: [{
|
|
1104
|
-
type: Output
|
|
1105
|
-
}] } });
|
|
1106
|
-
|
|
1107
1034
|
class FilterPipe {
|
|
1108
1035
|
transform(items, searchText, key) {
|
|
1109
1036
|
if (!items || !searchText)
|
|
@@ -1183,50 +1110,50 @@ class DataGridComponent {
|
|
|
1183
1110
|
// The columns Store Here
|
|
1184
1111
|
this.columns = [];
|
|
1185
1112
|
// Row Height;
|
|
1186
|
-
this.rowHeight =
|
|
1113
|
+
this.rowHeight = 50;
|
|
1187
1114
|
// Header Row Height;
|
|
1188
|
-
this.headerRowHeight =
|
|
1115
|
+
this.headerRowHeight = 40;
|
|
1189
1116
|
// Show Vertical Borders;
|
|
1190
1117
|
this.showVerticalBorder = false;
|
|
1191
1118
|
// Even Rows Background Color;
|
|
1192
1119
|
this.evenRowsBackgroundColor = '';
|
|
1193
1120
|
// Even Rows Background Color;
|
|
1194
|
-
this.oddRowsBackgroundColor = '#
|
|
1121
|
+
this.oddRowsBackgroundColor = '#F5F5F5';
|
|
1195
1122
|
// Header Rows Background Color;
|
|
1196
|
-
this.headerBackgroundColor = '#
|
|
1123
|
+
this.headerBackgroundColor = '#F5F5F5';
|
|
1197
1124
|
// Header Rows Background Color;
|
|
1198
|
-
this.checkboxesBackgroundColor = '#
|
|
1125
|
+
this.checkboxesBackgroundColor = '#FFFFFF';
|
|
1199
1126
|
// Show Columns Grouping;
|
|
1200
1127
|
this.showColumnsGrouping = false;
|
|
1201
1128
|
// Row Hovered Background color;
|
|
1202
|
-
this.rowHoverColor = '
|
|
1129
|
+
this.rowHoverColor = '#F5F5F5';
|
|
1203
1130
|
// Left PinnedBackground color;
|
|
1204
|
-
this.leftPinnedBackgroundColor = '#
|
|
1131
|
+
this.leftPinnedBackgroundColor = '#FFFFFF';
|
|
1205
1132
|
// Body Background color;
|
|
1206
|
-
this.bodyBackgroundColor = '#
|
|
1133
|
+
this.bodyBackgroundColor = '#FFFFFF';
|
|
1207
1134
|
// Right Pinned Background color;
|
|
1208
|
-
this.rightPinnedBackgroundColor = '#
|
|
1135
|
+
this.rightPinnedBackgroundColor = '#FFFFFF';
|
|
1209
1136
|
// Side Menu Background color;
|
|
1210
|
-
this.sidemenuBackgroundColor = '#
|
|
1137
|
+
this.sidemenuBackgroundColor = '#FFFFFF';
|
|
1211
1138
|
// Body text color;
|
|
1212
|
-
this.bodyTextColor = '#
|
|
1139
|
+
this.bodyTextColor = '#1B1F22';
|
|
1213
1140
|
// Header text color;
|
|
1214
|
-
this.headerTextColor = '#
|
|
1141
|
+
this.headerTextColor = '#6A6B6D';
|
|
1215
1142
|
// Header text color;
|
|
1216
|
-
this.checkboxesColor = '#
|
|
1143
|
+
this.checkboxesColor = '#FFFFFF';
|
|
1217
1144
|
// Header text size;
|
|
1218
|
-
this.headerTextFontsSize =
|
|
1145
|
+
this.headerTextFontsSize = 13;
|
|
1219
1146
|
// Body text color;
|
|
1220
1147
|
this.bodyTextFontsSize = 14;
|
|
1221
1148
|
// Header font weight;
|
|
1222
|
-
this.headerFontWeight =
|
|
1149
|
+
this.headerFontWeight = 600; // basit said
|
|
1223
1150
|
// Body Font Weight;
|
|
1224
1151
|
this.bodyFontWeight = 400;
|
|
1225
1152
|
// Checked Row Background Color;
|
|
1226
|
-
this.checkedRowBackgroundColor = '
|
|
1153
|
+
this.checkedRowBackgroundColor = '#0084FF1A';
|
|
1227
1154
|
// dropdowns Background Color;
|
|
1228
|
-
this.dropdownsBackgroundColor = '#
|
|
1229
|
-
this.footerRowBackgroundColor = '';
|
|
1155
|
+
this.dropdownsBackgroundColor = '#FFFFFF';
|
|
1156
|
+
this.footerRowBackgroundColor = '#FFFFFF';
|
|
1230
1157
|
// Footer row Height;
|
|
1231
1158
|
this.footerRowHeight = 46;
|
|
1232
1159
|
// Footer row Height;
|
|
@@ -1278,7 +1205,7 @@ class DataGridComponent {
|
|
|
1278
1205
|
// Taskbar actions
|
|
1279
1206
|
this.taskbarActions = [];
|
|
1280
1207
|
// Sorting Config to show sort icons
|
|
1281
|
-
this.sortingConfig =
|
|
1208
|
+
this.sortingConfig = { field: '', order_by: '' };
|
|
1282
1209
|
this.tableFilterViewId = '';
|
|
1283
1210
|
this.selectedTableLayout = 'medium';
|
|
1284
1211
|
this.closeDropdown = { preset: { closed: false, loading: false } };
|
|
@@ -1294,7 +1221,7 @@ class DataGridComponent {
|
|
|
1294
1221
|
this.gridType = '';
|
|
1295
1222
|
this.currencySymbol = '';
|
|
1296
1223
|
this.currencyFormat = '';
|
|
1297
|
-
this.leftPinnedBoxshadow = '';
|
|
1224
|
+
this.leftPinnedBoxshadow = '1px 0 4px 0 rgba(18, 19, 20, 0.1';
|
|
1298
1225
|
this.rightPinnedBoxshadow = '';
|
|
1299
1226
|
// GlobalSearch
|
|
1300
1227
|
this.selectedRowsBackgroundColor = '#8ac5ff';
|
|
@@ -1312,7 +1239,8 @@ class DataGridComponent {
|
|
|
1312
1239
|
this.enableCut = false;
|
|
1313
1240
|
this.tabs = [];
|
|
1314
1241
|
this.showCheckboxes = true;
|
|
1315
|
-
this.
|
|
1242
|
+
this.consumerFont = null;
|
|
1243
|
+
this.defaultConfig = null;
|
|
1316
1244
|
this.resetAllFilters = { resetAll: false };
|
|
1317
1245
|
this.columnThreedotsMunuConfig = {
|
|
1318
1246
|
showPinleft: true,
|
|
@@ -1334,7 +1262,6 @@ class DataGridComponent {
|
|
|
1334
1262
|
this.tablePresetConfig = new EventEmitter();
|
|
1335
1263
|
this.sortingOrderOptions = new EventEmitter();
|
|
1336
1264
|
this.createUpdateConfigListing = new EventEmitter();
|
|
1337
|
-
this.storePresetName = '';
|
|
1338
1265
|
this.isFullScreen = false;
|
|
1339
1266
|
this.activeTab = null;
|
|
1340
1267
|
this.groupedColumns = [];
|
|
@@ -1352,6 +1279,7 @@ class DataGridComponent {
|
|
|
1352
1279
|
this.filterColumnsList = [];
|
|
1353
1280
|
this.groupBoxPadding = 200;
|
|
1354
1281
|
this.presetName = '';
|
|
1282
|
+
this.storePresetName = '';
|
|
1355
1283
|
this.presetFilter = false;
|
|
1356
1284
|
this.searchTextPresetTable = '';
|
|
1357
1285
|
this.addFilterColumnInput = '';
|
|
@@ -1433,7 +1361,6 @@ class DataGridComponent {
|
|
|
1433
1361
|
];
|
|
1434
1362
|
this.hasScroll = false;
|
|
1435
1363
|
this.injector = inject(Injector);
|
|
1436
|
-
this.shouldRestoreScroll = false;
|
|
1437
1364
|
// private getDecrypt(key:string){
|
|
1438
1365
|
// const value = localStorage.getItem(key)
|
|
1439
1366
|
// try {
|
|
@@ -1473,6 +1400,7 @@ class DataGridComponent {
|
|
|
1473
1400
|
// Row Hover Logic Here
|
|
1474
1401
|
this.hoveredRowId = null;
|
|
1475
1402
|
this.isMenueHidden = false;
|
|
1403
|
+
this.clickedOnSortIcon = false;
|
|
1476
1404
|
this.getVisibleLeafColumns = (columns) => {
|
|
1477
1405
|
const result = [];
|
|
1478
1406
|
for (const column of columns) {
|
|
@@ -1638,38 +1566,37 @@ class DataGridComponent {
|
|
|
1638
1566
|
moveItemInArray(this.columns, prevColIndexInColumns, currColIndexInColumns);
|
|
1639
1567
|
// await this.refreshPreviewColumns();
|
|
1640
1568
|
this.cdr.detectChanges();
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
}
|
|
1569
|
+
this.ngZone.runOutsideAngular(() => {
|
|
1570
|
+
// Wait a tick to make sure elements are rendered
|
|
1571
|
+
requestAnimationFrame(() => {
|
|
1572
|
+
allFields.forEach((field) => {
|
|
1573
|
+
const updatedCells = Array.from(document.querySelectorAll(`[field="${field}"]`));
|
|
1574
|
+
updatedCells.forEach((el) => {
|
|
1575
|
+
const oldLeft = firstPositions.get(el);
|
|
1576
|
+
if (oldLeft == null)
|
|
1577
|
+
return; // skip if old position not available
|
|
1578
|
+
const newLeft = el.getBoundingClientRect().left;
|
|
1579
|
+
const deltaX = oldLeft - newLeft;
|
|
1580
|
+
if (deltaX !== 0) {
|
|
1581
|
+
el.style.willChange = 'transform';
|
|
1582
|
+
el.style.transition = 'none';
|
|
1583
|
+
el.style.transform = `translateX(${deltaX}px)`;
|
|
1584
|
+
// Force reflow
|
|
1585
|
+
void el.offsetWidth;
|
|
1586
|
+
el.style.transition = 'transform 300ms cubic-bezier(0.4, 0, 0.2, 1)';
|
|
1587
|
+
el.style.transform = 'translateX(0)';
|
|
1588
|
+
const handle = () => {
|
|
1589
|
+
el.style.transition = '';
|
|
1590
|
+
el.style.transform = '';
|
|
1591
|
+
el.style.willChange = '';
|
|
1592
|
+
el.removeEventListener('transitionend', handle);
|
|
1593
|
+
};
|
|
1594
|
+
el.addEventListener('transitionend', handle);
|
|
1595
|
+
}
|
|
1596
|
+
});
|
|
1669
1597
|
});
|
|
1670
1598
|
});
|
|
1671
1599
|
});
|
|
1672
|
-
// });
|
|
1673
1600
|
};
|
|
1674
1601
|
// onChildDragStart() {
|
|
1675
1602
|
// debugger;
|
|
@@ -1734,7 +1661,6 @@ class DataGridComponent {
|
|
|
1734
1661
|
moveItemInArray(this[section]?.[groupInSectionIndex].children, event.previousIndex, event.currentIndex);
|
|
1735
1662
|
// await this.refreshPreviewColumns();
|
|
1736
1663
|
this.cdr.detectChanges();
|
|
1737
|
-
await firstValueFrom(this.ngZone.onStable);
|
|
1738
1664
|
// allFields.forEach((field) => {
|
|
1739
1665
|
// const updatedCells = Array.from(
|
|
1740
1666
|
// document.querySelectorAll(`[field="${field}"]`)
|
|
@@ -1775,7 +1701,7 @@ class DataGridComponent {
|
|
|
1775
1701
|
el.style.transform = `translateX(${deltaX}px)`;
|
|
1776
1702
|
// Force reflow
|
|
1777
1703
|
void el.offsetWidth;
|
|
1778
|
-
el.style.transition = 'transform
|
|
1704
|
+
el.style.transition = 'transform 400ms cubic-bezier(0.4, 0, 0.2, 1)';
|
|
1779
1705
|
el.style.transform = 'translateX(0)';
|
|
1780
1706
|
const handle = () => {
|
|
1781
1707
|
el.style.transition = '';
|
|
@@ -1792,6 +1718,7 @@ class DataGridComponent {
|
|
|
1792
1718
|
};
|
|
1793
1719
|
this.isActiveFilterOpen = false;
|
|
1794
1720
|
this.activeSubButton = '';
|
|
1721
|
+
this.pageSizeOptions = [10, 25, 50, 75, 100, 150, 200, 250, 300, 500];
|
|
1795
1722
|
this.searchTextForFilterDropDown = '';
|
|
1796
1723
|
this.isFilterOpen = false;
|
|
1797
1724
|
this.showFilters = this.showSideMenu ? false : false;
|
|
@@ -1903,6 +1830,7 @@ class DataGridComponent {
|
|
|
1903
1830
|
// }
|
|
1904
1831
|
this.undoStack = [];
|
|
1905
1832
|
this.redoStack = [];
|
|
1833
|
+
this.pageSizeKeyMap = {};
|
|
1906
1834
|
// Hold expanded IDs (array for multiple, single value for single)
|
|
1907
1835
|
this.expandededDetailRows = '';
|
|
1908
1836
|
this.openIndex = null;
|
|
@@ -1927,6 +1855,7 @@ class DataGridComponent {
|
|
|
1927
1855
|
'.svg');
|
|
1928
1856
|
},
|
|
1929
1857
|
};
|
|
1858
|
+
this.activeFilterType = '';
|
|
1930
1859
|
}
|
|
1931
1860
|
ngAfterViewInit() {
|
|
1932
1861
|
this.ngZone.onStable.pipe(take(1)).subscribe(async () => {
|
|
@@ -1945,6 +1874,7 @@ class DataGridComponent {
|
|
|
1945
1874
|
this.cdr.detectChanges();
|
|
1946
1875
|
});
|
|
1947
1876
|
this.renderCustomCells();
|
|
1877
|
+
this.buildPageSizeKeyMap();
|
|
1948
1878
|
}
|
|
1949
1879
|
createCellInjector(row, col) {
|
|
1950
1880
|
return Injector.create({
|
|
@@ -1982,23 +1912,20 @@ class DataGridComponent {
|
|
|
1982
1912
|
this.addStylesToImages();
|
|
1983
1913
|
this.hasScroll = this.hasHorizontalScrollbar();
|
|
1984
1914
|
this.cdr.detectChanges();
|
|
1985
|
-
if (this.shouldRestoreScroll &&
|
|
1986
|
-
this.centerScrollableBody?.nativeElement) {
|
|
1987
|
-
setTimeout(() => {
|
|
1988
|
-
const left = this.commonSevice.mainContainerLeft;
|
|
1989
|
-
this.centerScrollableBody.nativeElement.scrollLeft = left;
|
|
1990
|
-
this.centerPinnedHeader.nativeElement.scrollLeft = left;
|
|
1991
|
-
this.shouldRestoreScroll = false;
|
|
1992
|
-
}, 1000);
|
|
1993
|
-
}
|
|
1994
1915
|
}
|
|
1995
1916
|
ngOnInit() {
|
|
1996
1917
|
// if (this.tabs?.length) {
|
|
1997
1918
|
// this.activeTab = this.tabs[0];
|
|
1998
1919
|
// }
|
|
1999
1920
|
// this.autosizeAllColumns();
|
|
1921
|
+
if (this.consumerFont) {
|
|
1922
|
+
if (!this.fontFamilies.includes(this.consumerFont)) {
|
|
1923
|
+
this.fontFamilies.unshift(this.consumerFont);
|
|
1924
|
+
}
|
|
1925
|
+
this.fontFaimly = this.consumerFont;
|
|
1926
|
+
}
|
|
2000
1927
|
if (!this.curretaTablePresetForUpdate) {
|
|
2001
|
-
|
|
1928
|
+
this.autosizeAllColumns();
|
|
2002
1929
|
}
|
|
2003
1930
|
// const user = this.getDecrypt('user');
|
|
2004
1931
|
// this.currencyFormat = user?.currency_format;
|
|
@@ -2006,21 +1933,15 @@ class DataGridComponent {
|
|
|
2006
1933
|
// this.dateFormat = user?.date_format;
|
|
2007
1934
|
if (!this.dateFormat) {
|
|
2008
1935
|
const storedDateFormat = localStorage.getItem('dateformat');
|
|
2009
|
-
|
|
2010
|
-
this.dateFormat = storedDateFormat ? JSON.parse(storedDateFormat) : 'dd/MM/yyyy';
|
|
2011
|
-
}
|
|
1936
|
+
this.dateFormat = storedDateFormat ? JSON.parse(storedDateFormat) : 'dd/MM/yyyy';
|
|
2012
1937
|
}
|
|
2013
1938
|
if (!this.currencyFormat) {
|
|
2014
1939
|
const storedCurrencyFormat = localStorage.getItem('currencyFormat');
|
|
2015
|
-
|
|
2016
|
-
this.currencyFormat = storedCurrencyFormat ? JSON.parse(storedCurrencyFormat) : '1,234,567.89';
|
|
2017
|
-
}
|
|
1940
|
+
this.currencyFormat = storedCurrencyFormat ? JSON.parse(storedCurrencyFormat) : '1,234,567.89';
|
|
2018
1941
|
}
|
|
2019
1942
|
if (!this.currencySymbol) {
|
|
2020
1943
|
const storedCurrencySymbol = localStorage.getItem('currencySymbol');
|
|
2021
|
-
|
|
2022
|
-
this.currencySymbol = storedCurrencySymbol ? JSON.parse(storedCurrencySymbol) : '$';
|
|
2023
|
-
}
|
|
1944
|
+
this.currencySymbol = storedCurrencySymbol ? JSON.parse(storedCurrencySymbol) : '$';
|
|
2024
1945
|
}
|
|
2025
1946
|
}
|
|
2026
1947
|
async ngOnChanges(changes) {
|
|
@@ -2031,15 +1952,10 @@ class DataGridComponent {
|
|
|
2031
1952
|
if (changes['tabs']) {
|
|
2032
1953
|
const allTabs = JSON.parse(localStorage.getItem('activeTabs') || '{}');
|
|
2033
1954
|
const savedTab = allTabs[this.tableType];
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
else {
|
|
2038
|
-
this.activeTab = savedTab || this.tabs?.[0];
|
|
1955
|
+
this.activeTab = savedTab || this.tabs?.[0];
|
|
1956
|
+
if (this.tableType) {
|
|
1957
|
+
this.setActiveTab(this.activeTab);
|
|
2039
1958
|
}
|
|
2040
|
-
// if (this.tableType) {
|
|
2041
|
-
// this.setActiveTab(this.activeTab);
|
|
2042
|
-
// }
|
|
2043
1959
|
}
|
|
2044
1960
|
}
|
|
2045
1961
|
if (changes['filtersConfig']) {
|
|
@@ -2076,13 +1992,11 @@ class DataGridComponent {
|
|
|
2076
1992
|
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
|
|
2077
1993
|
this.computeViewportRows();
|
|
2078
1994
|
this.updateVisibleRows(0);
|
|
2079
|
-
if (this.commonSevice?.mainContainerLeft > 200)
|
|
2080
|
-
this.shouldRestoreScroll = true;
|
|
2081
1995
|
this.cdr.detectChanges();
|
|
2082
1996
|
});
|
|
2083
1997
|
if (this.centerPinnedHeader?.nativeElement) {
|
|
2084
1998
|
void this.centerPinnedHeader.nativeElement.offsetWidth;
|
|
2085
|
-
this.dataSetLoading = true;
|
|
1999
|
+
// this.dataSetLoading = true;
|
|
2086
2000
|
setTimeout(() => {
|
|
2087
2001
|
if (this.centerScrollableBody?.nativeElement) {
|
|
2088
2002
|
this.centerScrollableBody.nativeElement.scrollLeft =
|
|
@@ -2159,18 +2073,22 @@ class DataGridComponent {
|
|
|
2159
2073
|
this.globalSearchText = temprorySelected.config.globalSearch;
|
|
2160
2074
|
this.setTableLayout(this.selectedTableLayout);
|
|
2161
2075
|
this.oddRowsBackgroundColor = temprorySelected?.config?.oddRowsBackgroundColor || '#f1f1f1';
|
|
2162
|
-
const groupedColumns = temprorySelected?.config?.groupedColumns;
|
|
2163
|
-
if (groupedColumns?.length) {
|
|
2164
|
-
this.groupedColumns = structuredClone(groupedColumns);
|
|
2165
|
-
this.groupDataAsync(this.dataSet, this.groupedColumns);
|
|
2166
|
-
}
|
|
2167
2076
|
this.cdr.detectChanges();
|
|
2168
2077
|
}
|
|
2078
|
+
else if (this.defaultConfig) {
|
|
2079
|
+
this.rowShadingEnabled = this.defaultConfig.rowShadingEnabled;
|
|
2080
|
+
this.showVerticalBorder = this.defaultConfig.showVerticalBorder;
|
|
2081
|
+
this.fontFaimly = this.defaultConfig.fontFaimly;
|
|
2082
|
+
this.headerTextFontsSize = this.defaultConfig.headerTextFontsSize;
|
|
2083
|
+
this.selectedTableLayout = this.defaultConfig.selectedTableLayout;
|
|
2084
|
+
this.bodyTextFontsSize = this.defaultConfig.bodyTextFontsSize;
|
|
2085
|
+
this.globalSearchText = this.defaultConfig.globalSearch;
|
|
2086
|
+
}
|
|
2169
2087
|
else {
|
|
2170
2088
|
this.rowShadingEnabled = false;
|
|
2171
2089
|
this.showVerticalBorder = false;
|
|
2172
2090
|
this.fontFaimly = 'Inter';
|
|
2173
|
-
this.headerTextFontsSize =
|
|
2091
|
+
this.headerTextFontsSize = 13;
|
|
2174
2092
|
this.selectedTableLayout = 'medium';
|
|
2175
2093
|
this.bodyTextFontsSize = 14;
|
|
2176
2094
|
this.globalSearchText = '';
|
|
@@ -2178,13 +2096,15 @@ class DataGridComponent {
|
|
|
2178
2096
|
this.presetName = '';
|
|
2179
2097
|
}
|
|
2180
2098
|
this.cdr.detectChanges();
|
|
2181
|
-
},
|
|
2099
|
+
}, 500);
|
|
2100
|
+
}
|
|
2101
|
+
if (changes['pageSizeOptions'] && changes['pageSizeOptions']?.currentValue) {
|
|
2102
|
+
this.buildPageSizeKeyMap();
|
|
2182
2103
|
}
|
|
2183
2104
|
}
|
|
2184
2105
|
async setColumnsColumnDropdownValus() {
|
|
2185
2106
|
if (!this.columns)
|
|
2186
2107
|
return;
|
|
2187
|
-
// Just removed temporary for super admin will set it again
|
|
2188
2108
|
if (this.columns?.length) {
|
|
2189
2109
|
this.columns = this.columns?.filter(c => c?.field?.trim() !== 'is_deleted');
|
|
2190
2110
|
}
|
|
@@ -2390,6 +2310,7 @@ class DataGridComponent {
|
|
|
2390
2310
|
...rest,
|
|
2391
2311
|
column_dropdown_value: cleanedDropdown,
|
|
2392
2312
|
query: cleanedQuery,
|
|
2313
|
+
is_groupable: rest.type !== 'image',
|
|
2393
2314
|
};
|
|
2394
2315
|
});
|
|
2395
2316
|
}
|
|
@@ -2564,7 +2485,8 @@ class DataGridComponent {
|
|
|
2564
2485
|
}
|
|
2565
2486
|
return false;
|
|
2566
2487
|
}
|
|
2567
|
-
openThreeDotsMenu(event, child,
|
|
2488
|
+
openThreeDotsMenu(event, child, clickedOnSortIcon) {
|
|
2489
|
+
this.clickedOnSortIcon = clickedOnSortIcon || false;
|
|
2568
2490
|
event.preventDefault();
|
|
2569
2491
|
event.stopPropagation();
|
|
2570
2492
|
this.isMenueHidden = true;
|
|
@@ -2594,6 +2516,8 @@ class DataGridComponent {
|
|
|
2594
2516
|
sortAsc(col) {
|
|
2595
2517
|
if (!col.is_sortable)
|
|
2596
2518
|
return;
|
|
2519
|
+
this.sortingConfig['order_by'] = 'asc';
|
|
2520
|
+
this.sortingConfig['field'] = col.field;
|
|
2597
2521
|
col.order_by = 'asc';
|
|
2598
2522
|
const event = {
|
|
2599
2523
|
order: 'asc',
|
|
@@ -2605,6 +2529,8 @@ class DataGridComponent {
|
|
|
2605
2529
|
sortDesc(col) {
|
|
2606
2530
|
if (!col.is_sortable)
|
|
2607
2531
|
return;
|
|
2532
|
+
this.sortingConfig['order_by'] = 'desc';
|
|
2533
|
+
this.sortingConfig['field'] = col.field;
|
|
2608
2534
|
col.order_by = 'desc';
|
|
2609
2535
|
const event = {
|
|
2610
2536
|
order: 'desc',
|
|
@@ -2620,7 +2546,6 @@ class DataGridComponent {
|
|
|
2620
2546
|
this.sortingOrderOptions.emit(event);
|
|
2621
2547
|
}
|
|
2622
2548
|
async updateColumnPinInSourceByField(column, pinned, isNestedTable = false, columns) {
|
|
2623
|
-
debugger;
|
|
2624
2549
|
if (isNestedTable) {
|
|
2625
2550
|
this.pinUnpinColum(column, pinned, columns);
|
|
2626
2551
|
return;
|
|
@@ -2963,7 +2888,7 @@ class DataGridComponent {
|
|
|
2963
2888
|
}
|
|
2964
2889
|
async toggleColumnVisibility(column, isVisible) {
|
|
2965
2890
|
if (isVisible) {
|
|
2966
|
-
if (this.visibleColumns()?.length <= 2 && column.is_visible
|
|
2891
|
+
if (this.visibleColumns()?.length <= 2 && column.is_visible) {
|
|
2967
2892
|
return;
|
|
2968
2893
|
}
|
|
2969
2894
|
}
|
|
@@ -3725,6 +3650,10 @@ class DataGridComponent {
|
|
|
3725
3650
|
// const dateObj = new Date(keyValue);
|
|
3726
3651
|
// groupKey = this.commonSevice.formatDateValue(dateObj, this.dateFormat || 'dd/MM/yyyy');
|
|
3727
3652
|
// }
|
|
3653
|
+
if (typeof keyValue === 'string' && !isNaN(Date.parse(keyValue))) {
|
|
3654
|
+
const dateObj = new Date(keyValue);
|
|
3655
|
+
groupKey = this.commonSevice.formatDateValue(dateObj, this.dateFormat || 'dd/MM/yyyy');
|
|
3656
|
+
}
|
|
3728
3657
|
if (!groupedMap.has(groupKey))
|
|
3729
3658
|
groupedMap.set(groupKey, []);
|
|
3730
3659
|
groupedMap.get(groupKey).push(item);
|
|
@@ -3789,25 +3718,23 @@ class DataGridComponent {
|
|
|
3789
3718
|
this.onFontChange();
|
|
3790
3719
|
}
|
|
3791
3720
|
setTableLayout(layoutType) {
|
|
3792
|
-
if (!layoutType)
|
|
3793
|
-
return;
|
|
3794
3721
|
if (layoutType === 'small') {
|
|
3795
|
-
this.rowHeight =
|
|
3722
|
+
this.rowHeight = 50;
|
|
3796
3723
|
this.headerRowHeight = 40;
|
|
3797
|
-
this.bodyTextFontsSize =
|
|
3798
|
-
this.headerTextFontsSize =
|
|
3724
|
+
this.bodyTextFontsSize = 10;
|
|
3725
|
+
this.headerTextFontsSize = 10;
|
|
3799
3726
|
}
|
|
3800
3727
|
else if (layoutType === 'medium') {
|
|
3801
|
-
this.rowHeight =
|
|
3802
|
-
this.headerRowHeight =
|
|
3803
|
-
this.bodyTextFontsSize =
|
|
3804
|
-
this.headerTextFontsSize =
|
|
3728
|
+
this.rowHeight = 60;
|
|
3729
|
+
this.headerRowHeight = 40;
|
|
3730
|
+
this.bodyTextFontsSize = 14;
|
|
3731
|
+
this.headerTextFontsSize = 13;
|
|
3805
3732
|
}
|
|
3806
3733
|
else {
|
|
3807
|
-
this.rowHeight =
|
|
3808
|
-
this.headerRowHeight =
|
|
3809
|
-
this.bodyTextFontsSize =
|
|
3810
|
-
this.headerTextFontsSize =
|
|
3734
|
+
this.rowHeight = 72;
|
|
3735
|
+
this.headerRowHeight = 40;
|
|
3736
|
+
this.bodyTextFontsSize = 16;
|
|
3737
|
+
this.headerTextFontsSize = 16;
|
|
3811
3738
|
}
|
|
3812
3739
|
}
|
|
3813
3740
|
get startIndexData() {
|
|
@@ -3852,16 +3779,16 @@ class DataGridComponent {
|
|
|
3852
3779
|
}
|
|
3853
3780
|
}
|
|
3854
3781
|
openFilteronThreeDotsClick(col) {
|
|
3855
|
-
if (col.type == 'image' || !col?.type
|
|
3782
|
+
if (col.type == 'image' || !col?.type)
|
|
3856
3783
|
return;
|
|
3857
3784
|
this.selectedColumnForFilter = col;
|
|
3858
3785
|
this.isThreeDotsFilterOpen = true;
|
|
3859
3786
|
this.addFilterColumnInput = '';
|
|
3860
|
-
if (col.type === 'dropdown'
|
|
3787
|
+
if (col.type === 'dropdown') {
|
|
3861
3788
|
this.currentFilterSelectedIds.clear();
|
|
3862
3789
|
const savedIds = col?.query?._ids || [];
|
|
3863
3790
|
savedIds.forEach((id) => this.currentFilterSelectedIds.add(id));
|
|
3864
|
-
this.selectedFilterOptions = this.selectedColumnForFilter?.column_dropdown_value
|
|
3791
|
+
this.selectedFilterOptions = this.selectedColumnForFilter?.column_dropdown_value.filter((option) => this.currentFilterSelectedIds.has(option?.id || option?._id || option));
|
|
3865
3792
|
setTimeout(() => {
|
|
3866
3793
|
if (this.filterMenueSearchInput) {
|
|
3867
3794
|
this.filterMenueSearchInput.nativeElement.focus();
|
|
@@ -3869,10 +3796,10 @@ class DataGridComponent {
|
|
|
3869
3796
|
}, 100);
|
|
3870
3797
|
}
|
|
3871
3798
|
else if (['string', 'number', 'date'].includes(col.type)) {
|
|
3872
|
-
this.firstCondition = col.query.first_condition ? col.query.first_condition : (
|
|
3799
|
+
this.firstCondition = col.query.first_condition ? col.query.first_condition : (col.type == 'date' ? 'equal' : 'contain');
|
|
3873
3800
|
this.firstValue = col?.query?.first_value || '';
|
|
3874
3801
|
this.condition = col?.query?.condition || 'none';
|
|
3875
|
-
this.secondCondition = col.query.first_condition ? col.query.first_condition : (
|
|
3802
|
+
this.secondCondition = col.query.first_condition ? col.query.first_condition : (col.type == 'date' ? 'equal' : 'contain');
|
|
3876
3803
|
this.secondValue = col?.query?.second_value || '';
|
|
3877
3804
|
setTimeout(() => {
|
|
3878
3805
|
this.filterMenueTextchInput.nativeElement.focus();
|
|
@@ -3881,30 +3808,28 @@ class DataGridComponent {
|
|
|
3881
3808
|
this.cdr.detectChanges();
|
|
3882
3809
|
}
|
|
3883
3810
|
openFilterFromDisabledSearchedInput(col) {
|
|
3884
|
-
if (col.type !== 'dropdown'
|
|
3811
|
+
if (col.type !== 'dropdown')
|
|
3885
3812
|
return;
|
|
3886
3813
|
this.openFilter(col);
|
|
3887
3814
|
}
|
|
3888
3815
|
openFilter(col) {
|
|
3889
|
-
if (!col.is_search_able)
|
|
3890
|
-
return;
|
|
3891
3816
|
this.activeFilterCell = col;
|
|
3892
3817
|
this.activeCol = null;
|
|
3893
3818
|
this.isFilterOpen = true;
|
|
3894
3819
|
this.searchTextForFilterDropDown = '';
|
|
3895
3820
|
this.addFilterColumnInput = '';
|
|
3896
3821
|
this.selectedColumnForFilter = col;
|
|
3897
|
-
if (col.type === 'dropdown'
|
|
3822
|
+
if (col.type === 'dropdown') {
|
|
3898
3823
|
this.currentFilterSelectedIds.clear();
|
|
3899
3824
|
const savedIds = col?.query?._ids || [];
|
|
3900
3825
|
savedIds.forEach((id) => this.currentFilterSelectedIds.add(id));
|
|
3901
3826
|
this.selectedFilterOptions = this.selectedColumnForFilter?.column_dropdown_value?.filter((option) => this.currentFilterSelectedIds.has(option?.id || option?._id || option));
|
|
3902
3827
|
}
|
|
3903
3828
|
else if (['string', 'number', 'date'].includes(col.type)) {
|
|
3904
|
-
this.firstCondition = col?.query?.first_condition ||
|
|
3829
|
+
this.firstCondition = col?.query?.first_condition || 'contain';
|
|
3905
3830
|
this.firstValue = col?.query?.first_value || '';
|
|
3906
3831
|
this.condition = col?.query?.condition || 'none';
|
|
3907
|
-
this.secondCondition = col?.query?.second_condition ||
|
|
3832
|
+
this.secondCondition = col?.query?.second_condition || 'contain';
|
|
3908
3833
|
this.secondValue = col?.query?.second_value || '';
|
|
3909
3834
|
}
|
|
3910
3835
|
this.cdr.detectChanges();
|
|
@@ -3962,7 +3887,7 @@ class DataGridComponent {
|
|
|
3962
3887
|
};
|
|
3963
3888
|
const column = findColumn(this.columns, this.selectedColumnForFilter.field);
|
|
3964
3889
|
if (column) {
|
|
3965
|
-
if (column.type === 'dropdown'
|
|
3890
|
+
if (column.type === 'dropdown') {
|
|
3966
3891
|
column.query = column.query || {};
|
|
3967
3892
|
column.query._ids = column.query._ids || [];
|
|
3968
3893
|
// Remove stale IDs (not present in Set)
|
|
@@ -4014,7 +3939,6 @@ class DataGridComponent {
|
|
|
4014
3939
|
this.createUpdateConfigListing.emit(sendData);
|
|
4015
3940
|
const filters = this.cleanFilterdColumns();
|
|
4016
3941
|
setTimeout(() => {
|
|
4017
|
-
this.commonSevice.mainContainerLeft = this.centerScrollableBody.nativeElement.scrollLeft;
|
|
4018
3942
|
this.filterOptions.emit(filters);
|
|
4019
3943
|
}, 200);
|
|
4020
3944
|
}
|
|
@@ -4107,12 +4031,10 @@ class DataGridComponent {
|
|
|
4107
4031
|
this.createUpdateConfigListing.emit(sendData);
|
|
4108
4032
|
const filters = this.cleanFilterdColumns();
|
|
4109
4033
|
setTimeout(() => {
|
|
4110
|
-
this.commonSevice.mainContainerLeft = this.centerScrollableBody.nativeElement.scrollLeft;
|
|
4111
4034
|
this.filterOptions.emit(filters);
|
|
4112
4035
|
}, 200);
|
|
4113
4036
|
}
|
|
4114
4037
|
clearAllFilters() {
|
|
4115
|
-
this.groupedColumns = [];
|
|
4116
4038
|
this.tableView?.forEach((ele) => { ele.is_temp = false; });
|
|
4117
4039
|
const resetAllRecursively = (columns) => {
|
|
4118
4040
|
for (const column of columns) {
|
|
@@ -4151,8 +4073,6 @@ class DataGridComponent {
|
|
|
4151
4073
|
type: this.tableType,
|
|
4152
4074
|
};
|
|
4153
4075
|
this.createUpdateConfigListing.emit(sendData);
|
|
4154
|
-
this.commonSevice.mainContainerLeft = this.centerScrollableBody.nativeElement.scrollLeft;
|
|
4155
|
-
this.commonSevice.mainContainerLeft = this.centerScrollableBody.nativeElement.scrollLeft;
|
|
4156
4076
|
setTimeout(() => {
|
|
4157
4077
|
const filteredColumns = this.cleanFilterdColumns();
|
|
4158
4078
|
this.genericEvent.emit(event);
|
|
@@ -4194,7 +4114,6 @@ class DataGridComponent {
|
|
|
4194
4114
|
type: this.tableType,
|
|
4195
4115
|
};
|
|
4196
4116
|
this.createUpdateConfigListing.emit(sendData);
|
|
4197
|
-
this.commonSevice.mainContainerLeft = this.centerScrollableBody.nativeElement.scrollLeft;
|
|
4198
4117
|
setTimeout(() => {
|
|
4199
4118
|
const filteredColumns = this.cleanFilterdColumns();
|
|
4200
4119
|
this.filterOptions.emit(filteredColumns);
|
|
@@ -4222,7 +4141,6 @@ class DataGridComponent {
|
|
|
4222
4141
|
type: this.tableType,
|
|
4223
4142
|
};
|
|
4224
4143
|
this.createUpdateConfigListing.emit(sendData);
|
|
4225
|
-
this.commonSevice.mainContainerLeft = this.centerScrollableBody.nativeElement.scrollLeft;
|
|
4226
4144
|
setTimeout(() => {
|
|
4227
4145
|
const filteredColumns = this.cleanFilterdColumns();
|
|
4228
4146
|
this.filterOptions.emit(filteredColumns);
|
|
@@ -4271,7 +4189,7 @@ class DataGridComponent {
|
|
|
4271
4189
|
if (column.type == 'image' || !column?.is_editable)
|
|
4272
4190
|
return;
|
|
4273
4191
|
this.editingKey = ((row.id || row._id) + '-' + column.field);
|
|
4274
|
-
if (column.type === 'dropdown'
|
|
4192
|
+
if (column.type === 'dropdown') {
|
|
4275
4193
|
setTimeout(() => {
|
|
4276
4194
|
const dropdownMenu = document.querySelector('.cell-editing-dropdown-menu');
|
|
4277
4195
|
if (dropdownMenu) {
|
|
@@ -4307,10 +4225,6 @@ class DataGridComponent {
|
|
|
4307
4225
|
this.rowSelectedIndexes.clear();
|
|
4308
4226
|
if (!this.editingKey)
|
|
4309
4227
|
return;
|
|
4310
|
-
if (control && control.pristine) {
|
|
4311
|
-
this.editingKey = null;
|
|
4312
|
-
return;
|
|
4313
|
-
}
|
|
4314
4228
|
this.checkRowEditAndEmitValue(row, column, row[column.field]);
|
|
4315
4229
|
this.editingKey = null;
|
|
4316
4230
|
this.cdr.detectChanges();
|
|
@@ -4395,7 +4309,6 @@ class DataGridComponent {
|
|
|
4395
4309
|
},
|
|
4396
4310
|
eventType: 'pageChange',
|
|
4397
4311
|
};
|
|
4398
|
-
this.commonSevice.mainContainerLeft = this.centerScrollableBody.nativeElement.scrollLeft;
|
|
4399
4312
|
this.genericEvent.emit(event);
|
|
4400
4313
|
}
|
|
4401
4314
|
onPageSizeChange() {
|
|
@@ -4427,11 +4340,11 @@ class DataGridComponent {
|
|
|
4427
4340
|
}, 700);
|
|
4428
4341
|
}
|
|
4429
4342
|
actionPreset(data, type) {
|
|
4430
|
-
data.columns = data
|
|
4343
|
+
data.columns = data.columns.map(({ _id, filterValue, search, column_dropdown_value, query, __typename, ...rest }) => rest);
|
|
4431
4344
|
this.tableView?.forEach((ele) => { ele.is_temp = false; });
|
|
4432
4345
|
{
|
|
4433
|
-
this.bodyTextFontsSize = data
|
|
4434
|
-
this.fontFaimly = data
|
|
4346
|
+
this.bodyTextFontsSize = data?.config?.bodyTextFontsSize,
|
|
4347
|
+
this.fontFaimly = data?.config?.fontFaimly,
|
|
4435
4348
|
data?.filters?.forEach((element) => {
|
|
4436
4349
|
delete element.__typename;
|
|
4437
4350
|
if (element.query) {
|
|
@@ -4472,9 +4385,9 @@ class DataGridComponent {
|
|
|
4472
4385
|
}));
|
|
4473
4386
|
this.columns = data.columns;
|
|
4474
4387
|
{
|
|
4475
|
-
this.bodyTextFontsSize = data
|
|
4476
|
-
this.fontFaimly = data
|
|
4477
|
-
data
|
|
4388
|
+
this.bodyTextFontsSize = data?.config?.bodyTextFontsSize,
|
|
4389
|
+
this.fontFaimly = data?.config?.fontFaimly,
|
|
4390
|
+
data?.filters?.forEach((element) => {
|
|
4478
4391
|
delete element.__typename;
|
|
4479
4392
|
if (element.query) {
|
|
4480
4393
|
delete element.query.__typename;
|
|
@@ -4486,9 +4399,9 @@ class DataGridComponent {
|
|
|
4486
4399
|
}
|
|
4487
4400
|
});
|
|
4488
4401
|
// this.globalSearch = data.config.bodyTextFontsSize,
|
|
4489
|
-
this.headerTextFontsSize = data
|
|
4490
|
-
this.selectedTableLayout = data
|
|
4491
|
-
this.showVerticalBorder = data
|
|
4402
|
+
this.headerTextFontsSize = data?.config?.headerTextFontsSize,
|
|
4403
|
+
this.selectedTableLayout = data?.config?.selectedTableLayout,
|
|
4404
|
+
this.showVerticalBorder = data?.config?.showVerticalBorder,
|
|
4492
4405
|
this.currentIdForUpdatePreset = data.id;
|
|
4493
4406
|
this.curretaTablePresetForUpdate = structuredClone(data);
|
|
4494
4407
|
this.presetName = data?.name;
|
|
@@ -4737,13 +4650,13 @@ class DataGridComponent {
|
|
|
4737
4650
|
const menuWidth = menuElement.offsetWidth;
|
|
4738
4651
|
const menuHeight = menuElement.offsetHeight;
|
|
4739
4652
|
const viewportWidth = window.innerWidth;
|
|
4740
|
-
const viewportHeight =
|
|
4653
|
+
const viewportHeight = window.innerHeight;
|
|
4741
4654
|
let x = (event instanceof MouseEvent) ? event.clientX : event.touches[0].clientX; //event.clientX;
|
|
4742
4655
|
let y = (event instanceof MouseEvent) ? event.clientY : event.touches[0].clientY; //event.clientY;
|
|
4743
4656
|
if (x + menuWidth > viewportWidth) {
|
|
4744
4657
|
x = viewportWidth - menuWidth - 10;
|
|
4745
4658
|
}
|
|
4746
|
-
if (y + menuHeight >
|
|
4659
|
+
if (y + menuHeight > viewportHeight) {
|
|
4747
4660
|
y = viewportHeight - menuHeight - 10;
|
|
4748
4661
|
}
|
|
4749
4662
|
this.xPos = x;
|
|
@@ -4768,20 +4681,12 @@ class DataGridComponent {
|
|
|
4768
4681
|
this.genericEvent.emit(sendObj);
|
|
4769
4682
|
}
|
|
4770
4683
|
onVerifyClick(type) {
|
|
4684
|
+
const idsArray = Array.from(this.selectedRows);
|
|
4771
4685
|
const text = type?.toLowerCase();
|
|
4772
|
-
if (text == 'archive' || text == 'unarchive'
|
|
4773
|
-
// || text == 'delete' || text == 'restore' || text == 'remove' || text == 'deactivate' || text == 'activate' || text == 'block' || text == 'unblock'
|
|
4774
|
-
// || text == 'enable' || text == 'disable' || text == 'approve' || text == 'reject' || text == 'publish' || text == 'unpublish' || text == 'lock' || text == 'unlock' || text == 'complete' || text == 'incomplete'
|
|
4775
|
-
// || text == 'send to review' || text == 'mark as paid' || text == 'mark as unpaid' || text == 'fulfill' || text == 'unfulfill' || text == 'refund' || text == 'cancel' || text == 'resend' || text == 'chargeback'
|
|
4776
|
-
// || text == 'dispute' || text == 'escalate' || text == 'deescalate' || text == 'flag' || text == 'unflag' || text == 'verify' || text == 'unverify' || text == 'subscribe' || text == 'unsubscribe' || text == 'follow' || text == 'unfollow'
|
|
4777
|
-
// || text == 'like' || text == 'unlike' || text == 'share' || text == 'unshare' || text == 'comment' || text == 'uncomment' || text == 'tag' || text == 'untag' || text == 'assign' || text == 'unassign' || text == 'link' || text == 'unlink'
|
|
4778
|
-
// || text == 'sync' || text == 'unsync' || text == 'backup' || text == 'restore backup' || text == 'migrate' || text == 'import' || text == 'export' || text == 'generate report' || text == 'download report' || text == 'view details'
|
|
4779
|
-
// || text == 'edit details' || text == 'update details' || text == 'change status' || text == 'reset password' || text == 'send notification' || text == 'schedule' || text == 'reschedule' || text == 'cancel schedule' || text == 'start' || text == 'stop' || text == 'pause' || text == 'resume'
|
|
4780
|
-
) {
|
|
4686
|
+
if (text == 'archive' || text == 'unarchive') {
|
|
4781
4687
|
this.clearSelectionState(this.tableType);
|
|
4782
4688
|
this.selectedRows.clear();
|
|
4783
4689
|
}
|
|
4784
|
-
const idsArray = Array.from(this.selectedRows);
|
|
4785
4690
|
const arrayOfObjectsWithTableType = [];
|
|
4786
4691
|
this.selectedRows.forEach(id => {
|
|
4787
4692
|
arrayOfObjectsWithTableType.push({
|
|
@@ -4800,7 +4705,7 @@ class DataGridComponent {
|
|
|
4800
4705
|
this.genericEvent.emit(sendObj);
|
|
4801
4706
|
}
|
|
4802
4707
|
getCellClasses(column, value) {
|
|
4803
|
-
if (!value || !column?.field
|
|
4708
|
+
if (!value || !column?.field)
|
|
4804
4709
|
return '';
|
|
4805
4710
|
let val = typeof value === 'object' ? value?.value ?? value : value;
|
|
4806
4711
|
const field = column.field.toLowerCase();
|
|
@@ -4829,7 +4734,7 @@ class DataGridComponent {
|
|
|
4829
4734
|
removeColumnFilterFromColumn(column) {
|
|
4830
4735
|
if (!column)
|
|
4831
4736
|
return;
|
|
4832
|
-
if (column.type === 'dropdown'
|
|
4737
|
+
if (column.type === 'dropdown') {
|
|
4833
4738
|
column.query._ids = [];
|
|
4834
4739
|
}
|
|
4835
4740
|
else if (['string', 'number', 'date'].includes(column.type)) {
|
|
@@ -5358,13 +5263,67 @@ class DataGridComponent {
|
|
|
5358
5263
|
getSelectedDataForCopy() {
|
|
5359
5264
|
return this.copyService.getSelectedDataForCopy(this.dataSet, this.columns, this.rowSelectedIndexes, this.selectedCells, this.getNestedValue.bind(this));
|
|
5360
5265
|
}
|
|
5266
|
+
buildPageSizeKeyMap() {
|
|
5267
|
+
this.pageSizeKeyMap = {};
|
|
5268
|
+
this.pageSizeOptions.forEach((size, index) => {
|
|
5269
|
+
// Keys: 1–9, then 0 for 10th item
|
|
5270
|
+
const key = index < 9
|
|
5271
|
+
? String(index + 1)
|
|
5272
|
+
: index === 9
|
|
5273
|
+
? '0'
|
|
5274
|
+
: null;
|
|
5275
|
+
if (key) {
|
|
5276
|
+
this.pageSizeKeyMap[key] = size;
|
|
5277
|
+
}
|
|
5278
|
+
});
|
|
5279
|
+
}
|
|
5361
5280
|
onKeyDown(event) {
|
|
5362
5281
|
const target = event.target;
|
|
5363
5282
|
const isFormField = target.tagName === 'INPUT' ||
|
|
5364
5283
|
target.tagName === 'TEXTAREA' ||
|
|
5365
5284
|
target.isContentEditable;
|
|
5366
|
-
if (isFormField)
|
|
5285
|
+
if (isFormField || this.loading)
|
|
5286
|
+
return;
|
|
5287
|
+
if ((event.ctrlKey || event.metaKey) && !event.shiftKey && event.key === 'ArrowRight') {
|
|
5288
|
+
event.preventDefault();
|
|
5289
|
+
this.goToNextPage();
|
|
5290
|
+
return;
|
|
5291
|
+
}
|
|
5292
|
+
// Ctrl + Arrow Left → Previous Page
|
|
5293
|
+
if ((event.ctrlKey || event.metaKey) && !event.shiftKey && event.key === 'ArrowLeft') {
|
|
5294
|
+
event.preventDefault();
|
|
5295
|
+
this.goToPreviousPage();
|
|
5367
5296
|
return;
|
|
5297
|
+
}
|
|
5298
|
+
// Ctrl + Shift + Arrow Right → Last Page
|
|
5299
|
+
if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key === 'ArrowRight') {
|
|
5300
|
+
event.preventDefault();
|
|
5301
|
+
this.goToLastPage();
|
|
5302
|
+
return;
|
|
5303
|
+
}
|
|
5304
|
+
// Ctrl + Shift + Arrow Left → First Page
|
|
5305
|
+
if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key === 'ArrowLeft') {
|
|
5306
|
+
event.preventDefault();
|
|
5307
|
+
this.goToFirstPage();
|
|
5308
|
+
return;
|
|
5309
|
+
}
|
|
5310
|
+
if ((event.ctrlKey || event.metaKey) && event.key === '/') {
|
|
5311
|
+
event.preventDefault();
|
|
5312
|
+
if (this.globalSearchInput) {
|
|
5313
|
+
this.globalSearchInput?.nativeElement?.focus();
|
|
5314
|
+
}
|
|
5315
|
+
return;
|
|
5316
|
+
}
|
|
5317
|
+
if (event.altKey) {
|
|
5318
|
+
const newLimit = this.pageSizeKeyMap[event.key];
|
|
5319
|
+
if (newLimit) {
|
|
5320
|
+
event.preventDefault();
|
|
5321
|
+
if (this.paginationConfig.limit !== newLimit) {
|
|
5322
|
+
this.paginationConfig.limit = newLimit;
|
|
5323
|
+
this.onPageSizeChange();
|
|
5324
|
+
}
|
|
5325
|
+
}
|
|
5326
|
+
}
|
|
5368
5327
|
const tableContainer = document.querySelector('.data-grid-body-wrapper');
|
|
5369
5328
|
if (tableContainer && !tableContainer.contains(target))
|
|
5370
5329
|
return;
|
|
@@ -5400,6 +5359,30 @@ class DataGridComponent {
|
|
|
5400
5359
|
this.selectAllCells();
|
|
5401
5360
|
}
|
|
5402
5361
|
}
|
|
5362
|
+
goToNextPage() {
|
|
5363
|
+
const currentPage = this.paginationConfig.page;
|
|
5364
|
+
const totalPages = this.paginationConfig.totalPages;
|
|
5365
|
+
if (currentPage >= totalPages)
|
|
5366
|
+
return;
|
|
5367
|
+
this.goToPage(currentPage + 1);
|
|
5368
|
+
}
|
|
5369
|
+
goToPreviousPage() {
|
|
5370
|
+
const currentPage = this.paginationConfig.page;
|
|
5371
|
+
if (currentPage <= 1)
|
|
5372
|
+
return;
|
|
5373
|
+
this.goToPage(currentPage - 1);
|
|
5374
|
+
}
|
|
5375
|
+
goToFirstPage() {
|
|
5376
|
+
if (this.paginationConfig.page === 1)
|
|
5377
|
+
return;
|
|
5378
|
+
this.goToPage(1);
|
|
5379
|
+
}
|
|
5380
|
+
goToLastPage() {
|
|
5381
|
+
const lastPage = this.paginationConfig.totalPages;
|
|
5382
|
+
if (this.paginationConfig.page === lastPage)
|
|
5383
|
+
return;
|
|
5384
|
+
this.goToPage(lastPage);
|
|
5385
|
+
}
|
|
5403
5386
|
selectAllCells() {
|
|
5404
5387
|
this.selectedCells = [];
|
|
5405
5388
|
this.selectedKeys.clear();
|
|
@@ -5470,8 +5453,6 @@ class DataGridComponent {
|
|
|
5470
5453
|
}
|
|
5471
5454
|
}
|
|
5472
5455
|
async onPaste(event) {
|
|
5473
|
-
if (!this.enableCut)
|
|
5474
|
-
return;
|
|
5475
5456
|
const target = event.target;
|
|
5476
5457
|
const tag = target?.tagName?.toLowerCase();
|
|
5477
5458
|
if (tag === 'input' || tag === 'textarea' || target?.getAttribute('contenteditable') === 'true') {
|
|
@@ -5504,18 +5485,18 @@ class DataGridComponent {
|
|
|
5504
5485
|
return new Promise(resolve => {
|
|
5505
5486
|
const overlay = document.createElement('div');
|
|
5506
5487
|
overlay.classList.add('custom-overlay-wrapper');
|
|
5507
|
-
overlay.innerHTML = `
|
|
5508
|
-
<div class="custom-overlay">
|
|
5509
|
-
<div class="custom-modal">
|
|
5510
|
-
<div class="custom-modal-body">
|
|
5511
|
-
<p class="modal-message">${message}</p>
|
|
5512
|
-
<div class="modal-actions">
|
|
5513
|
-
<button class="btn-confirm">Confirm</button>
|
|
5514
|
-
<button class="btn-cancel">Cancel</button>
|
|
5515
|
-
</div>
|
|
5516
|
-
</div>
|
|
5517
|
-
</div>
|
|
5518
|
-
</div>
|
|
5488
|
+
overlay.innerHTML = `
|
|
5489
|
+
<div class="custom-overlay">
|
|
5490
|
+
<div class="custom-modal">
|
|
5491
|
+
<div class="custom-modal-body">
|
|
5492
|
+
<p class="modal-message">${message}</p>
|
|
5493
|
+
<div class="modal-actions">
|
|
5494
|
+
<button class="btn-confirm">Confirm</button>
|
|
5495
|
+
<button class="btn-cancel">Cancel</button>
|
|
5496
|
+
</div>
|
|
5497
|
+
</div>
|
|
5498
|
+
</div>
|
|
5499
|
+
</div>
|
|
5519
5500
|
`;
|
|
5520
5501
|
document.body.appendChild(overlay);
|
|
5521
5502
|
const confirmBtn = overlay.querySelector('.btn-confirm');
|
|
@@ -5755,8 +5736,8 @@ class DataGridComponent {
|
|
|
5755
5736
|
setTimeout(() => {
|
|
5756
5737
|
// if (this.isOutsideContainer && this.currentDraggingColumn) {
|
|
5757
5738
|
// this.currentDraggingColumn!.is_visible = false;
|
|
5758
|
-
this.currentDraggingColumn = null;
|
|
5759
|
-
this.isOutsideContainer = false;
|
|
5739
|
+
// this.currentDraggingColumn = null;
|
|
5740
|
+
// this.isOutsideContainer = false;
|
|
5760
5741
|
// this.cdr.detectChanges();
|
|
5761
5742
|
// }
|
|
5762
5743
|
}, 100);
|
|
@@ -5790,7 +5771,7 @@ class DataGridComponent {
|
|
|
5790
5771
|
});
|
|
5791
5772
|
const stringsCurrentPrestCols = JSON.stringify(currentPresetColumns);
|
|
5792
5773
|
const stringColumns = JSON.stringify(columns);
|
|
5793
|
-
const filters = this.filtersConfig
|
|
5774
|
+
const filters = this.filtersConfig?.map((filter) => {
|
|
5794
5775
|
return {
|
|
5795
5776
|
filed: filter.field,
|
|
5796
5777
|
query: {
|
|
@@ -5816,6 +5797,14 @@ class DataGridComponent {
|
|
|
5816
5797
|
// console.log('Current Temp Preset : ', currPreset)
|
|
5817
5798
|
// console.log('Current Temp Preset Cols columns: ', currentPresetColumns)
|
|
5818
5799
|
// console.log('Current columns: ', columns);
|
|
5800
|
+
// this.rowShadingEnabled = temprorySelected.config.rowShadingEnabled;
|
|
5801
|
+
// this.showVerticalBorder = temprorySelected.config.showVerticalBorder;
|
|
5802
|
+
// this.fontFaimly = temprorySelected.config.fontFaimly;
|
|
5803
|
+
// this.headerTextFontsSize = temprorySelected.config.headerTextFontsSize;
|
|
5804
|
+
// this.selectedTableLayout = temprorySelected.config.selectedTableLayout;
|
|
5805
|
+
// this.bodyTextFontsSize = temprorySelected.config.bodyTextFontsSize;
|
|
5806
|
+
// this.globalSearchText = temprorySelected.config.globalSearch;
|
|
5807
|
+
// this.setTableLayout(this.selectedTableLayout);
|
|
5819
5808
|
if (!currentPresetColumns)
|
|
5820
5809
|
return true;
|
|
5821
5810
|
return (currentPresetColumns && (stringsCurrentPrestCols == stringColumns) && (JSON.stringify(filters) == JSON.stringify(currentPresetFilters)) && (this.fontFaimly == currPreset.config.fontFaimly)
|
|
@@ -5841,6 +5830,15 @@ class DataGridComponent {
|
|
|
5841
5830
|
};
|
|
5842
5831
|
this.genericEvent.emit(event);
|
|
5843
5832
|
}
|
|
5833
|
+
createCustomColumn() {
|
|
5834
|
+
const event = {
|
|
5835
|
+
data: {
|
|
5836
|
+
listingType: this.listingType,
|
|
5837
|
+
},
|
|
5838
|
+
eventType: "createCustomColumn",
|
|
5839
|
+
};
|
|
5840
|
+
this.genericEvent.emit(event);
|
|
5841
|
+
}
|
|
5844
5842
|
setActiveTab(tab) {
|
|
5845
5843
|
this.activeTab = tab;
|
|
5846
5844
|
const allTabs = JSON.parse(localStorage.getItem('activeTabs') || '{}');
|
|
@@ -6097,34 +6095,11 @@ class DataGridComponent {
|
|
|
6097
6095
|
first?.full_name ??
|
|
6098
6096
|
'-');
|
|
6099
6097
|
}
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
}
|
|
6103
|
-
getDynamicRight(col, section, colIndex, subColIndex) {
|
|
6104
|
-
if (section == 'right' && this.previewRightPinnedColumns?.length == 1 && col.width < 200) {
|
|
6105
|
-
return 100;
|
|
6106
|
-
}
|
|
6107
|
-
else if (section == 'right') {
|
|
6108
|
-
return null;
|
|
6109
|
-
}
|
|
6110
|
-
else if (section == 'previewCenterColumns' && colIndex == (this.previewCenterColumns?.length - 1) && col.width < 200) {
|
|
6111
|
-
return 200;
|
|
6112
|
-
}
|
|
6113
|
-
else {
|
|
6114
|
-
return col.width - 45;
|
|
6115
|
-
}
|
|
6116
|
-
}
|
|
6117
|
-
blurInput(event, row, col) {
|
|
6118
|
-
const input = event?.target;
|
|
6119
|
-
input?.blur();
|
|
6120
|
-
this.setActiveCell(row, col);
|
|
6121
|
-
setTimeout(() => {
|
|
6122
|
-
this.editingKey = '';
|
|
6123
|
-
this.cdr.detectChanges();
|
|
6124
|
-
}, 0);
|
|
6098
|
+
activeFilter(type) {
|
|
6099
|
+
this.activeFilterType = type;
|
|
6125
6100
|
}
|
|
6126
6101
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataGridComponent, deps: [{ token: SplitColumnsService }, { token: i0.ChangeDetectorRef }, { token: CommonService }, { token: i0.ElementRef }, { token: i0.NgZone }, { token: CopyServiceService }, { token: i0.Renderer2 }, { token: i4.DomSanitizer }, { token: ExportService }, { token: i6.DatePipe }, { token: FormatCurrencyPipe }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6127
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DataGridComponent, selector: "data-grid", inputs: { rowAnimation: "rowAnimation", paginationConfig: "paginationConfig", dataSet: "dataSet", columns: "columns", rowHeight: "rowHeight", headerRowHeight: "headerRowHeight", showVerticalBorder: "showVerticalBorder", evenRowsBackgroundColor: "evenRowsBackgroundColor", oddRowsBackgroundColor: "oddRowsBackgroundColor", headerBackgroundColor: "headerBackgroundColor", checkboxesBackgroundColor: "checkboxesBackgroundColor", showColumnsGrouping: "showColumnsGrouping", rowHoverColor: "rowHoverColor", leftPinnedBackgroundColor: "leftPinnedBackgroundColor", bodyBackgroundColor: "bodyBackgroundColor", rightPinnedBackgroundColor: "rightPinnedBackgroundColor", sidemenuBackgroundColor: "sidemenuBackgroundColor", bodyTextColor: "bodyTextColor", headerTextColor: "headerTextColor", checkboxesColor: "checkboxesColor", headerTextFontsSize: "headerTextFontsSize", bodyTextFontsSize: "bodyTextFontsSize", headerFontWeight: "headerFontWeight", bodyFontWeight: "bodyFontWeight", checkedRowBackgroundColor: "checkedRowBackgroundColor", dropdownsBackgroundColor: "dropdownsBackgroundColor", footerRowBackgroundColor: "footerRowBackgroundColor", footerRowHeight: "footerRowHeight", topGroupedBadgesBackgroundColor: "topGroupedBadgesBackgroundColor", showRowsGrouping: "showRowsGrouping", showFilterRow: "showFilterRow", fontFaimly: "fontFaimly", showSideMenu: "showSideMenu", footerPadding: "footerPadding", topFilterRowHeight: "topFilterRowHeight", rowShadingEnabled: "rowShadingEnabled", showSerialNumber: "showSerialNumber", singleSpaAssetsPath: "singleSpaAssetsPath", filtersConfig: "filtersConfig", loading: "loading", verticalScrollbarWidth: "verticalScrollbarWidth", horizintalScrollbarWidth: "horizintalScrollbarWidth", showCellDetailsBox: "showCellDetailsBox", dateFormat: "dateFormat", tableSearch: "tableSearch", actions: "actions", config: "config", showTaskbar: "showTaskbar", tableName: "tableName", listingType: "listingType", checkboxState: "checkboxState", taskbarActions: "taskbarActions", sortingConfig: "sortingConfig", tableFilterViewId: "tableFilterViewId", selectedTableLayout: "selectedTableLayout", closeDropdown: "closeDropdown", globalSearchText: "globalSearchText", nestedTablerowFontsize: "nestedTablerowFontsize", nestedTableHeaderRowHeight: "nestedTableHeaderRowHeight", nestedTablerowHeight: "nestedTablerowHeight", gridType: "gridType", currencySymbol: "currencySymbol", currencyFormat: "currencyFormat", leftPinnedBoxshadow: "leftPinnedBoxshadow", rightPinnedBoxshadow: "rightPinnedBoxshadow", selectedRowsBackgroundColor: "selectedRowsBackgroundColor", nestedTableHeaderBackgroundColor: "nestedTableHeaderBackgroundColor", nestedTableRowBackgroundColor: "nestedTableRowBackgroundColor", tableView: "tableView", buttons: "buttons", keepMultipleExpandedDetails: "keepMultipleExpandedDetails", showTotalAmountRow: "showTotalAmountRow", enableGlobalSearch: "enableGlobalSearch", tableType: "tableType", enableExport: "enableExport", showFullScreenButton: "showFullScreenButton", enableCut: "enableCut", tabs: "tabs", showCheckboxes: "showCheckboxes", pageSizeOptions: "pageSizeOptions", resetAllFilters: "resetAllFilters", columnThreedotsMunuConfig: "columnThreedotsMunuConfig" }, outputs: { changeLayout: "changeLayout", customCellEvent: "customCellEvent", filterOptions: "filterOptions", genericEvent: "genericEvent", tablePresetConfig: "tablePresetConfig", sortingOrderOptions: "sortingOrderOptions", createUpdateConfigListing: "createUpdateConfigListing" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape($event)", "window:resize": "onResize($event)", "document:keydown": "onKeyDown($event)", "document:paste": "onPaste($event)" } }, viewQueries: [{ propertyName: "cellText", first: true, predicate: ["cellText"], descendants: true }, { propertyName: "nestedHeader", first: true, predicate: ["nestedHeader"], descendants: true }, { propertyName: "dataGridContainer", first: true, predicate: ["dataGridContainer"], descendants: true }, { propertyName: "taskManagementContainer", first: true, predicate: ["taskManagementContainer"], descendants: true }, { propertyName: "nestedTableContainer", first: true, predicate: ["nestedTableContainer"], descendants: true }, { propertyName: "leftPinnedBody", first: true, predicate: ["leftPinnedBody"], descendants: true }, { propertyName: "centerPinnedBody", first: true, predicate: ["centerPinnedBody"], descendants: true }, { propertyName: "rightPinnedBody", first: true, predicate: ["rightPinnedBody"], descendants: true }, { propertyName: "leftPinnedHeader", first: true, predicate: ["leftPinnedHeader"], descendants: true }, { propertyName: "centerPinnedHeader", first: true, predicate: ["centerPinnedHeader"], descendants: true }, { propertyName: "rightPinnedHeader", first: true, predicate: ["rightPinnedHeader"], descendants: true }, { propertyName: "columnsGroupedBox", first: true, predicate: ["columnsGroupedBox"], descendants: true }, { propertyName: "centerFakeScrollbar", first: true, predicate: ["centerFakeScrollbar"], descendants: true }, { propertyName: "centerScroll", first: true, predicate: ["centerScroll"], descendants: true }, { propertyName: "mainScroll", first: true, predicate: ["mainScroll"], descendants: true }, { propertyName: "fakeScroll", first: true, predicate: ["fakeScroll"], descendants: true }, { propertyName: "horizintalFakeScroll", first: true, predicate: ["horizintalFakeScroll"], descendants: true }, { propertyName: "centerScrollableBody", first: true, predicate: ["centerScrollableBody"], descendants: true }, { propertyName: "filterMenueSearchInput", first: true, predicate: ["filterMenueSearchInput"], descendants: true }, { propertyName: "filterMenueTextchInput", first: true, predicate: ["filterMenueTextchInput"], descendants: true }, { propertyName: "textAreadInput", first: true, predicate: ["textAreadInput"], descendants: true }, { propertyName: "nestedTable", first: true, predicate: ["nestedTable"], descendants: true }, { propertyName: "fullscreenImageTemplate", first: true, predicate: ["fullscreenImageTemplate"], descendants: true }, { propertyName: "cellHosts", predicate: CellHostDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"position-relative h-100\">\r\n <div\r\n class=\"d-flex justify-content-between mb-2 align-items-center position-relative\"\r\n >\r\n <div class=\"d-flex gap-2\">\r\n <div class=\"nav nav-tabs\" *ngIf=\"true\">\r\n <div class=\"nav nav-tabs\" id=\"nav-tab\" role=\"tablist\">\r\n <span\r\n *ngFor=\"let tab of tabs; let i = index\"\r\n (click)=\"setActiveTab(tab)\"\r\n class=\"nav-link cursor-pointer\"\r\n [class.active]=\"activeTab == tab\"\r\n >\r\n {{ tab }}\r\n </span>\r\n </div>\r\n </div>\r\n <div class=\"global-search\" [style.width.px]=\"350\">\r\n <span\r\n *ngIf=\"enableGlobalSearch\"\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\r\n class=\"data-grid-svg-icon mx-2 position-absolute icon\"\r\n ></span>\r\n <input\r\n *ngIf=\"enableGlobalSearch\"\r\n style=\"height: 36px\"\r\n class=\"form-control\"\r\n placeholder=\"Type to search, then press Enter\"\r\n [(ngModel)]=\"tableSearch\"\r\n (keydown.enter)=\"onGlobalSearch()\"\r\n (input)=\"onSearchInput($event)\"\r\n type=\"search\"\r\n />\r\n </div>\r\n </div>\r\n <div class=\"d-flex gap-2 align-items-center table-right-top-actions\">\r\n <ng-container *ngFor=\"let button of buttons\">\r\n <div\r\n class=\"d-flex align-items-center gap-2 action-buttons-row\"\r\n *ngIf=\"button?.has_permission\"\r\n >\r\n <a\r\n href=\"JavaScript:void(0)\"\r\n (click)=\"onActionButtonClick(button.name)\"\r\n class=\"button button-small btn border border-primary btn-active-primary me-2 p-0 d-flex align-items-center justify-content-center px-3\"\r\n >\r\n <span\r\n *ngIf=\"button.is_showIcon\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/' + button.icon + '.svg'\r\n \"\r\n class=\"svg-icon svg-icon-2\"\r\n ></span>\r\n <span\r\n class=\"label-hidden text-white\"\r\n [class.ms-0]=\"button.is_showIcon\"\r\n >{{ button?.name }}</span\r\n >\r\n </a>\r\n </div>\r\n </ng-container>\r\n <div\r\n *ngIf=\"!showFilterRow\"\r\n class=\"cursor-pointer position-relative action-buttons-row\"\r\n (click)=\"toggleOpenFilter()\"\r\n [class.active]=\"showFilters\"\r\n >\r\n <a\r\n href=\"JavaScript:void(0)\"\r\n class=\"button button-small btn btn-active-primary border border-primary me-2 p-0 d-flex align-items-center justify-content-center px-3\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\r\n class=\"svg-icon svg-icon-2\"\r\n ></span>\r\n <span class=\"label-hidden text-white\">Filters</span>\r\n </a>\r\n <span\r\n *ngIf=\"activeFilteredColumns?.length\"\r\n style=\"\r\n width: 7px;\r\n height: 7px;\r\n box-shadow: 0px 0px 3px #0022ff;\r\n background-color: rgb(0, 60, 255);\r\n position: absolute;\r\n right: 16px;\r\n top: 10px;\r\n \"\r\n class=\"rounded-circle d-block\"\r\n ></span>\r\n </div>\r\n <div\r\n class=\"cursor-pointer d-none\"\r\n (click)=\"toggleActions('advance-filter')\"\r\n [class.active]=\"activeTopButton === 'advance-filter'\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/zoom-charge.svg'\"\r\n class=\"data-grid-svg-icon top-icon me-2\"\r\n ></span>\r\n </div>\r\n <div\r\n class=\"cursor-pointer action-buttons-row\"\r\n (click)=\"toggleActions('setting')\"\r\n [class.active]=\"\r\n activeTopButton === 'setting' ||\r\n activeTopButton === 'table-layout' ||\r\n activeTopButton === 'table-presets' ||\r\n activeTopButton === 'show-hide-columns'\r\n \"\r\n >\r\n <!-- <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/settings-2.svg'\"\r\n class=\"data-grid-svg-icon top-icon me-2\"\r\n ></span> -->\r\n <a\r\n href=\"JavaScript:void(0)\"\r\n class=\"button button-small btn btn-active-primary border border-primary me-2 p-0 d-flex align-items-center justify-content-center px-3\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/settings-2.svg'\"\r\n class=\"svg-icon svg-icon-2\"\r\n ></span>\r\n <span class=\"label-hidden text-white\">Setting</span>\r\n </a>\r\n\r\n <div\r\n *ngIf=\"activeTopButton === 'setting'\"\r\n class=\"actions-dropdown mt-1 actions-dropdown-setting\"\r\n style=\"position: absolute\"\r\n >\r\n <div class=\"dropdown-menu show shadow custom-menu\">\r\n <!-- Table Layout -->\r\n <a\r\n class=\"dropdown-item d-flex justify-content-between align-items-center cursor-pointer\"\r\n (click)=\"$event.stopPropagation(); toggleActions('table-layout')\"\r\n >\r\n <span\r\n ><span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/table-2.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Table Layout</span\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </a>\r\n <!-- Table Presets -->\r\n <a\r\n (click)=\"$event.stopPropagation(); toggleActions('table-presets')\"\r\n class=\"dropdown-item d-flex justify-content-between align-items-center cursor-pointer\"\r\n >\r\n <span\r\n ><span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/list-details.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Table Presets</span\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </a>\r\n\r\n <!-- Columns -->\r\n <a\r\n *ngIf=\"!showSideMenu\"\r\n (click)=\"\r\n $event.stopPropagation(); toggleActions('show-hide-columns')\r\n \"\r\n class=\"dropdown-item d-flex justify-content-between align-items-center cursor-pointer\"\r\n >\r\n <span class=\"align-items-center d-flex\"\r\n ><span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/eye.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Columns</span\r\n >\r\n <div class=\"d-flex gap-2\">\r\n <span class=\"muted-text\">{{ columnsCount }}</span>\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </div>\r\n </a>\r\n\r\n <div class=\"dropdown-divider\"></div>\r\n\r\n <!-- Filter -->\r\n <a\r\n class=\"dropdown-item cursor-pointer\"\r\n (click)=\"toggleOpenFilter(); activeTopButton = '';\"\r\n *ngIf=\"!showFilterRow\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2 mt-1 cursor-pointer\"\r\n ></span>\r\n Filter\r\n </a>\r\n\r\n <!-- Download -->\r\n <a\r\n class=\"dropdown-item cursor-pointer\"\r\n (click)=\"downloadCsv('csv')\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/download.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\r\n ></span>\r\n CSV Export\r\n </a>\r\n <a\r\n *ngIf=\"enableExport\"\r\n class=\"dropdown-item cursor-pointer\"\r\n (click)=\"downloadCsv('xlsx')\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/download.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\r\n ></span>\r\n Excel Export\r\n </a>\r\n <!-- Font Family & Font Size -->\r\n <div class=\"px-2 pb-2 pt-2\">\r\n <div class=\"d-flex gap-2\">\r\n <!-- Font Family -->\r\n <select\r\n class=\"form-select form-select-sm\"\r\n [(ngModel)]=\"fontFaimly\"\r\n (change)=\"onFontChange()\"\r\n >\r\n <option *ngFor=\"let font of fontFamilies\" [value]=\"font\">\r\n {{ font }}\r\n </option>\r\n </select>\r\n\r\n <!-- Font Size -->\r\n <select\r\n class=\"form-select form-select-sm\"\r\n (change)=\"onFontChange()\"\r\n [(ngModel)]=\"bodyTextFontsSize\"\r\n >\r\n <option *ngFor=\"let size of fontSizes\" [value]=\"size\">\r\n {{ size }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Table Layout -->\r\n\r\n <ng-container *ngIf=\"activeTopButton === 'table-layout'\">\r\n <div\r\n *ngTemplateOutlet=\"tableLayout\"\r\n class=\"actions-dropdown mt-1\"\r\n style=\"position: absolute\"\r\n ></div>\r\n </ng-container>\r\n\r\n <!-- Table Presets -->\r\n <ng-container *ngIf=\"activeTopButton === 'table-presets'\">\r\n <div\r\n *ngTemplateOutlet=\"tablePreset\"\r\n class=\"actions-dropdown mt-1\"\r\n style=\"position: absolute\"\r\n ></div>\r\n </ng-container>\r\n\r\n <!-- Table Presets -->\r\n <ng-container *ngIf=\"activeTopButton === 'show-hide-columns'\">\r\n <div\r\n *ngTemplateOutlet=\"showHideColumns\"\r\n class=\"actions-dropdown mt-1\"\r\n style=\"position: absolute\"\r\n ></div>\r\n </ng-container>\r\n </div>\r\n\r\n <div class=\"action-buttons-row\" *ngIf=\"showFullScreenButton\">\r\n <a\r\n *ngIf=\"!isFullScreen\"\r\n class=\"button button-small btn btn-active-primary border border-primary expend d-flex justify-content-center align-items-center\"\r\n (click)=\"toggleFullscreen()\"\r\n data-bs-toggle=\"tooltip\"\r\n data-bs-placement=\"top\"\r\n title=\"Minimise\"\r\n [ngClass]=\"{ minArrow: !isFullScreen, maxArrow: isFullScreen }\"\r\n style=\"transition: color 0.2s\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/expend.svg'\"\r\n class=\"svg-icon svg-icon-2 mb-1\"\r\n ></span>\r\n </a>\r\n <a\r\n *ngIf=\"isFullScreen\"\r\n class=\"button button-small btn btn-active-primary border border-primary expend d-flex justify-content-center align-items-center\"\r\n (click)=\"toggleFullscreen()\"\r\n data-bs-toggle=\"tooltip\"\r\n data-bs-placement=\"top\"\r\n title=\"Maximise\"\r\n [ngClass]=\"{ minArrow: !isFullScreen, maxArrow: isFullScreen }\"\r\n style=\"transition: color 0.2s\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/minimize.svg'\"\r\n class=\"svg-icon svg-icon-2 mb-1\"\r\n ></span>\r\n </a>\r\n </div>\r\n <div>\r\n <!-- Example single danger button -->\r\n\r\n <!-- <button\r\n type=\"button\"\r\n class=\"btn btn-primary btn-sm d-flex gap-2 action-button\"\r\n (click)=\"toggleActions('actions')\"\r\n >\r\n Action\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/Vector.svg'\"\r\n class=\"data-grid-svg-icon\"\r\n ></span>\r\n </button>\r\n <div\r\n *ngIf=\"activeTopButton === 'actions'\"\r\n class=\"actions-dropdown mt-1\"\r\n >\r\n <div class=\"dropdown-menu show\">\r\n <a class=\"dropdown-item\" href=\"#\">Action</a>\r\n <a class=\"dropdown-item\" href=\"#\">Another action</a>\r\n <a class=\"dropdown-item\" href=\"#\">Something else here</a>\r\n <div class=\"dropdown-divider\"></div>\r\n <a class=\"dropdown-item\" href=\"#\">Separated link</a>\r\n </div>\r\n </div> -->\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"showFilters && !showFilterRow\"\r\n class=\"top-filter-row border-top py-2 d-flex justify-content-between align-items-center\"\r\n [style.height.px]=\"topFilterRowHeight\"\r\n >\r\n <!-- LEFT SIDE (Filter tags + Filter button) -->\r\n <div class=\"d-flex gap-2 align-items-center\">\r\n <ng-container>\r\n <div\r\n *ngFor=\"let col of activeFilteredColumns; trackBy: trackByField\"\r\n class=\"filter-tags\"\r\n >\r\n <div\r\n (click)=\"\r\n isActiveFilterOpen = true;\r\n activeTopButton = 'filter-columns';\r\n openFilter(col)\r\n \"\r\n class=\"d-flex justify-content-center align-items-center muted-text add-filter-button active-filters\"\r\n style=\"white-space: nowrap\"\r\n [class.active]=\"\r\n col?.field == selectedColumnForFilter?.field &&\r\n isActiveFilterOpen &&\r\n activeTopButton == 'filter-columns'\r\n \"\r\n >\r\n <span class=\"header-tag mt-0 d-flex align-items-center\">\r\n <span\r\n *ngIf=\"col?.pinned\"\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pin.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n {{ col.header }}\r\n <span\r\n (click)=\"\r\n $event.stopPropagation(); removeColumnFilterFromColumn(col)\r\n \"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/cross-primary.svg'\r\n \"\r\n class=\"data-grid-svg-icon cross-secondary ms-2 mb-1\"\r\n ></span>\r\n </span>\r\n </div>\r\n\r\n <ng-container\r\n *ngIf=\"\r\n activeTopButton === 'filter-columns' &&\r\n col?.field == selectedColumnForFilter?.field &&\r\n isActiveFilterOpen\r\n \"\r\n >\r\n <div\r\n *ngTemplateOutlet=\"filterColumns; context: { column: col }\"\r\n class=\"actions-dropdown mt-1\"\r\n ></div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Filter Button -->\r\n <div class=\"add-filter-button-menu\">\r\n <div\r\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\r\n class=\"d-flex justify-content-center align-items-center muted-text add-filter-button button-filter\"\r\n style=\"width: 70px\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/plus.svg'\"\r\n class=\"me-2 data-grid-svg-icon\"\r\n ></span>\r\n Filter\r\n </div>\r\n\r\n <ng-container\r\n *ngIf=\"activeTopButton === 'filter-columns' && !isActiveFilterOpen\"\r\n >\r\n <div\r\n *ngTemplateOutlet=\"filterColumns\"\r\n class=\"actions-dropdown mt-1\"\r\n ></div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- RIGHT SIDE (Update + Reset) -->\r\n <div class=\"d-flex gap-3 align-items-center\">\r\n <div\r\n (click)=\"savePreset()\"\r\n class=\"text-primary cursor-pointer all-filters-reset-button\"\r\n *ngIf=\"!checkFilterChangesEffect()\"\r\n >\r\n Update View\r\n </div>\r\n\r\n <div\r\n class=\"text-primary cursor-pointer all-filters-reset-button\"\r\n *ngIf=\"!tableFilterViewId && activeFilteredColumns?.length\"\r\n (click)=\"clearAllFilters()\"\r\n >\r\n Reset\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div\r\n [style.height]=\"\r\n showFilters ? 'calc(100% - ' + topFilterRowHeight + 'px)' : '100%'\r\n \"\r\n cdkDropListGroup\r\n class=\"data-grid-table-wrapper overflow-hidden\"\r\n #dataGridContainer\r\n [style.fontFamily]=\"fontFaimly\"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n id=\"data-grid-main-container\"\r\n >\r\n <div\r\n *ngIf=\"showRowsGrouping\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [cdkDropListData]=\"columns\"\r\n [style.backgroundColor]=\"\r\n topGroupedBadgesBackgroundColor || headerBackgroundColor\r\n \"\r\n cdkDropList\r\n (cdkDropListEntered)=\"enterToTopRowGrouping($event)\"\r\n (cdkDropListExited)=\"exitedFromTheTopRow($event)\"\r\n (cdkDropListDropped)=\"onDropTopGroup($event)\"\r\n [cdkDropListEnterPredicate]=\"canEnterToRowsGrouping\"\r\n id=\"rows-grouping-top-container\"\r\n class=\"border-below d-flex px-4 align-items-center\"\r\n >\r\n <div\r\n class=\"d-flex gap-2 align-items-center\"\r\n [style.color]=\"headerTextColor\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <div *ngIf=\"!draggingInGroupArea && !groupedColumns?.length\">\r\n Drag here to set row groups\r\n </div>\r\n <div\r\n cdkDropListOrientation=\"horizontal\"\r\n cdkDropList\r\n (cdkDropListDropped)=\"onGroupReorder($event)\"\r\n class=\"d-flex\"\r\n >\r\n <div\r\n cdkDrag\r\n [cdkDragLockAxis]=\"'x'\"\r\n *ngFor=\"\r\n let child of groupedColumns;\r\n let i = index;\r\n trackBy: trackByField\r\n \"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: child,\r\n showChevron:\r\n groupedColumns.length > 1 && i != groupedColumns.length - 1\r\n }\r\n \"\r\n ></ng-container>\r\n <ng-template cdkDragPreview\r\n ><div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n *ngIf=\"!draggingInGroupArea\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ child.header }}</div>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div\r\n class=\"d-flex overflow-hidden\"\r\n [style.height]=\"\r\n 'calc(100% - ' +\r\n (showRowsGrouping\r\n ? headerRowHeight + footerRowHeight\r\n : footerRowHeight) +\r\n 'px)'\r\n \"\r\n >\r\n <div\r\n class=\"h-100\"\r\n [style.width]=\"\r\n !showSideMenu\r\n ? '100%'\r\n : sideMenuVisible\r\n ? 'calc(100% - 280px)'\r\n : 'calc(100% - 30px)'\r\n \"\r\n >\r\n <div class=\"h-100 transition position-relative w-100\">\r\n <!-- ##################################################################################################################################################################################### -->\r\n <!-- ##################################################################################################################################################################################### -->\r\n <!-- Data Grid Header starts here -->\r\n <!-- ##################################################################################################################################################################################### -->\r\n <!-- ##################################################################################################################################################################################### -->\r\n\r\n <div\r\n class=\"data-grid-header-wrapper w-100\"\r\n [style.color]=\"headerTextColor\"\r\n [style.fontSize.px]=\"headerTextFontsSize\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n [class.border-below]=\"!hasAnyVisibleColumn\"\r\n [style.height.px]=\"\r\n showColumnsGrouping && showFilterRow\r\n ? headerRowHeight * 3\r\n : showColumnsGrouping || showFilterRow\r\n ? headerRowHeight * 2\r\n : headerRowHeight\r\n \"\r\n >\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <!-- Data Grid Left Pinned Header starts here -->\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <div\r\n class=\"data-grid-header left-pinned\"\r\n #leftPinnedHeader\r\n [class.border-right]=\"hasLeftPinnedColumns\"\r\n >\r\n <div\r\n *ngIf=\"showSerialNumber\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n class=\"select-all-checkbox-cell border-below\"\r\n [style.width.px]=\"55\"\r\n [style.height.px]=\"\r\n showColumnsGrouping && showFilterRow\r\n ? headerRowHeight * 3\r\n : showColumnsGrouping || showFilterRow\r\n ? headerRowHeight * 2\r\n : headerRowHeight\r\n \"\r\n >\r\n S.No\r\n </div>\r\n <div\r\n *ngIf=\"showCheckboxes\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n class=\"select-all-checkbox-cell border-below\"\r\n [style.height.px]=\"\r\n showColumnsGrouping && showFilterRow\r\n ? headerRowHeight * 3\r\n : showColumnsGrouping || showFilterRow\r\n ? headerRowHeight * 2\r\n : headerRowHeight\r\n \"\r\n >\r\n <input\r\n *ngIf=\"hasAnyVisibleColumn\"\r\n style=\"width: 16px; height: 16px\"\r\n type=\"checkbox\"\r\n [indeterminate]=\"isIndeterminateState(dataSet)\"\r\n [checked]=\"isAllSelected(dataSet)\"\r\n (change)=\"toggleSelectAll(dataSet)\"\r\n />\r\n </div>\r\n <div\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n class=\"d-flex\"\r\n cdkDropList\r\n id=\"left-pinned-header\"\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListData]=\"leftPinnedColumns\"\r\n (cdkDropListEntered)=\"onDropListEnter($event, 'left')\"\r\n (cdkDropListSorted)=\"\r\n onSortGroup($event, 'previewLeftPinnedColumns')\r\n \"\r\n (cdkDropListDropped)=\"onDropGroup()\"\r\n style=\"min-width: 1px\"\r\n >\r\n <div\r\n class=\"dragable-header\"\r\n cdkDrag\r\n [cdkDragData]=\"col\"\r\n *ngFor=\"\r\n let col of leftPinnedColumns;\r\n let i = index;\r\n trackBy: trackByField\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n index: i,\r\n section: 'previewLeftPinnedColumns'\r\n }\r\n \"\r\n ></ng-container>\r\n <ng-template cdkDragPreview\r\n ><div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n *ngIf=\"!draggingInGroupArea\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/arrows-move.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ col.header }}</div>\r\n </div>\r\n </ng-template>\r\n <ng-template cdkDragPlaceholder>\r\n <div *ngIf=\"!draggingInGroupArea\">\r\n <div\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n index: i,\r\n section: ''\r\n }\r\n \"\r\n ></div>\r\n </div>\r\n <div\r\n *ngIf=\"draggingInGroupArea\"\r\n class=\"d-flex gap-2 ms-2\"\r\n style=\"opacity: 0.6\"\r\n >\r\n <ng-container\r\n *ngIf=\"col?.children?.length; else singleCol\"\r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let child of col.children;\r\n let i = index;\r\n trackBy: trackByField\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: child,\r\n showChevron:\r\n col.children.length > 1 &&\r\n i != col.children.length - 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #singleCol>\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: col,\r\n showChevron: col?.children?.length > 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <!-- Data Grid Center Pinned Header starts here -->\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <div\r\n class=\"data-grid-header center-scrollable\"\r\n #centerPinnedHeader\r\n (scroll)=\"onCenterBodyScroll($event)\"\r\n id=\"center-pinned-header\"\r\n cdkDropList\r\n [cdkDropListConnectedTo]=\"\r\n showRowsGrouping ? ['rows-grouping-top-container'] : []\r\n \"\r\n [cdkDropListData]=\"centerColumns\"\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListSortingDisabled]=\"\r\n isDisableColumnGrouping && draggingInGroupArea\r\n \"\r\n (cdkDropListEntered)=\"onDropListEnter($event, 'center')\"\r\n (cdkDropListSorted)=\"onSortGroup($event, 'previewCenterColumns')\"\r\n (cdkDropListDropped)=\"onDropGroup()\"\r\n [style.maxWidth]=\"\r\n 'calc(100% - ' +\r\n (rightPinnedHeader.offsetWidth + leftPinnedHeader.offsetWidth) +\r\n 'px)'\r\n \"\r\n >\r\n <div\r\n *ngIf=\"groupedColumns?.length\"\r\n style=\"min-width: 200px\"\r\n class=\"h-100 align-items-center\"\r\n #columnsGroupedBox\r\n id=\"groupBoxHeaderDiv\"\r\n >\r\n <div\r\n class=\"d-flex w-100 justify-content-between align-items-center border-below\"\r\n [style.height.px]=\"\r\n showFilterRow ? headerRowHeight * 2 : headerRowHeight\r\n \"\r\n >\r\n <div class=\"ps-3\">Group</div>\r\n <div class=\"d-flex\">\r\n <div\r\n class=\"three-dots cursor-pointer\"\r\n (click)=\"\r\n openThreeDotsMenu($event, 'group');\r\n isThreeDotsFilterOpen = false\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/three-dots-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div\r\n (mousedown)=\"\r\n $event.stopPropagation(); onResizeGroupBox($event)\r\n \"\r\n class=\"resize-handle\"\r\n style=\"margin-right: -2px\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div\r\n [style.height.px]=\"headerRowHeight\"\r\n class=\"border-below\"\r\n ></div>\r\n </div>\r\n <span\r\n class=\"d-flex align-items-center justify-content-center cursor-pointer border-below\"\r\n style=\"min-width: 30px; height: 100%\"\r\n *ngIf=\"gridType === 'Assets' || gridType === 'Tasks'\"\r\n >\r\n </span>\r\n <div\r\n class=\"dragable-header\"\r\n (cdkDragStarted)=\"\r\n checkColumnGroupingStatus(col);\r\n dragStartOnGroup(col);\r\n onDragStarted(col)\r\n \"\r\n (cdkDragMoved)=\"onDragMoved($event)\"\r\n (cdkDragEnded)=\"onDragEnded()\"\r\n cdkDrag\r\n [cdkDragData]=\"col\"\r\n *ngFor=\"\r\n let col of centerColumns;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n index: i,\r\n section: 'previewCenterColumns'\r\n }\r\n \"\r\n >\r\n </ng-container>\r\n <ng-template cdkDragPreview\r\n ><div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n *ngIf=\"!isOutsideContainer\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n (draggingInGroupArea\r\n ? 'data-grid/icons/justify.svg'\r\n : 'data-grid/icons/arrows-move.svg')\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n >\r\n </span>\r\n <span\r\n *ngIf=\"isOutsideContainer\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/eye-cross.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n >\r\n </span>\r\n </div>\r\n <div>{{ col.header }}</div>\r\n </div>\r\n </ng-template>\r\n <ng-template cdkDragPlaceholder>\r\n <div *ngIf=\"!draggingInGroupArea\">\r\n <div\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n index: i,\r\n section: 'centerColumns'\r\n }\r\n \"\r\n ></div>\r\n </div>\r\n <div\r\n *ngIf=\"draggingInGroupArea && !isOutsideContainer\"\r\n class=\"d-flex gap-2 ms-2\"\r\n style=\"opacity: 0.6\"\r\n >\r\n <ng-container *ngIf=\"col?.children?.length; else singleCol\">\r\n <ng-container\r\n *ngFor=\"\r\n let child of col.children;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container *ngIf=\"child?.is_groupable\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: child,\r\n showChevron:\r\n col.children.length > 1 &&\r\n i != col.children.length - 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #singleCol>\r\n <ng-container *ngIf=\"col?.is_groupable\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: col,\r\n showChevron: col?.children?.length > 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <!-- Data Grid Right Pinned Header starts here -->\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <div\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n cdkDropList\r\n id=\"right-pinned-header\"\r\n [cdkDropListConnectedTo]=\"\r\n showRowsGrouping ? ['rows-grouping-top-container'] : []\r\n \"\r\n cdkDropListOrientation=\"horizontal\"\r\n class=\"data-grid-header right-pinned\"\r\n (cdkDropListSorted)=\"\r\n onSortGroup($event, 'previewRightPinnedColumns')\r\n \"\r\n (cdkDropListEntered)=\"onDropListEnter($event, 'right')\"\r\n (cdkDropListDropped)=\"onDropGroup()\"\r\n #rightPinnedHeader\r\n class=\"right-pinned-header d-flex\"\r\n style=\"min-width: 0.2px\"\r\n >\r\n <div\r\n class=\"dragable-header\"\r\n cdkDrag\r\n [cdkDragData]=\"col\"\r\n *ngFor=\"\r\n let col of rightPinnedColumns;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n pinnedRight: true,\r\n index: i,\r\n section: 'right'\r\n }\r\n \"\r\n ></ng-container>\r\n <ng-template cdkDragPreview\r\n ><div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n *ngIf=\"!draggingInGroupArea\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/arrows-move.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ col.header }}</div>\r\n </div>\r\n </ng-template>\r\n <ng-template cdkDragPlaceholder>\r\n <div *ngIf=\"!draggingInGroupArea\">\r\n <div\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n index: i,\r\n section: 'right'\r\n }\r\n \"\r\n ></div>\r\n </div>\r\n <div\r\n *ngIf=\"draggingInGroupArea\"\r\n class=\"d-flex gap-2 ms-2\"\r\n style=\"opacity: 0.6\"\r\n >\r\n <ng-container *ngIf=\"col?.children?.length; else singleCol\">\r\n <ng-container\r\n *ngFor=\"\r\n let child of col.children;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: child,\r\n showChevron:\r\n col.children.length > 1 &&\r\n i != col.children.length - 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #singleCol>\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: col,\r\n showChevron: col?.children?.length > 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!--########################################################################################################################################################################################################################### -->\r\n <!--########################################################################################################################################################################################################################### -->\r\n <!-- Data Grid Body starts here -->\r\n <!--########################################################################################################################################################################################################################### -->\r\n <!--########################################################################################################################################################################################################################### -->\r\n <div\r\n class=\"h-100 d-flex justify-content-center align-items-center\"\r\n *ngIf=\"!dataSet?.length && !loading && !dataSetLoading\"\r\n >\r\n <!-- <div\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/record-not-found.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></div> -->\r\n <div>No Record Found</div>\r\n </div>\r\n\r\n <div\r\n class=\"position-absolute w-100 h-100 d-flex justify-content-center align-items-center loading-overlay\"\r\n *ngIf=\"loading || dataSetLoading\"\r\n style=\"\r\n z-index: 999;\r\n backdrop-filter: blur(1px);\r\n \"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n >\r\n <div class=\"spinner-border text-primary\" role=\"status\">\r\n <!-- <span class=\"loader\"></span> -->\r\n <!-- <span class=\"visually-hidden\">Loading...</span> -->\r\n <!-- </div> -->\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"data-grid-body-wrapper position-relative d-flex\"\r\n [style.height]=\"bodyWrapperHeight\"\r\n style=\"overflow-y: auto; overflow-x: hidden\"\r\n #mainScroll\r\n (scroll)=\"onMainScroll($event)\"\r\n [style.scrollbarWidth]=\"verticalScrollbarWidth\"\r\n >\r\n <!-- LEFT PINNED -->\r\n <div\r\n [style.height.px]=\"\r\n !groupedColumns.length ? originalDataSet.length * rowHeight : 0\r\n \"\r\n ></div>\r\n <div [class.h-100]=\"originalDataSet.length < 8\">\r\n <div\r\n class=\"data-grid-body left-pinned-body w-100\"\r\n style=\"overflow-y: hidden\"\r\n [class.border-right]=\"hasLeftPinnedColumns\"\r\n [class.transparent-border-right]=\"!hasLeftPinnedColumns\"\r\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\r\n [style.backgroundColor]=\"leftPinnedBackgroundColor\"\r\n [class.h-100]=\"originalDataSet.length < 8\"\r\n *ngIf=\"!loading && !dataSetLoading\"\r\n [@rowDynamic]=\"rowAnimation\"\r\n\r\n \r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let row of visibleRows;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: row,\r\n columns: previewLeftPinnedColumns,\r\n isEven: (startIndex + i) % 2 === 0,\r\n isOdd: (startIndex + i) % 2 !== 0,\r\n isLeft: true,\r\n section: 'left',\r\n isTotalRow: false\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: { __virtualIndex: 0 },\r\n columns: previewLeftPinnedColumns,\r\n isEven: false,\r\n isOdd: false,\r\n section: 'left',\r\n isTotalRow: true\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- CENTER -->\r\n <div\r\n class=\"h-100\"\r\n [style.width.px]=\"centerPinnedHeader.clientWidth\"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n >\r\n <div\r\n class=\"data-grid-body center-scrollable\"\r\n [class.h-100]=\"originalDataSet.length < 8\"\r\n style=\"overflow-y: hidden; overflow-x: auto\"\r\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n #centerScrollableBody\r\n (scroll)=\"onCenterBodyScroll($event)\"\r\n [style.boxShadow]=\"leftPinnedBoxshadow\"\r\n >\r\n <div [@rowDynamic]=\"rowAnimation\" *ngIf=\"!loading && !dataSetLoading\">\r\n <ng-container\r\n *ngFor=\"\r\n let row of visibleRows;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: row,\r\n columns: previewCenterColumns,\r\n isEven: (startIndex + i) % 2 === 0,\r\n isOdd: (startIndex + i) % 2 !== 0,\r\n section: 'center',\r\n isTotalRow: false\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: { __virtualIndex: 0 },\r\n columns: previewCenterColumns,\r\n isEven: false,\r\n isOdd: false,\r\n section: 'center',\r\n isTotalRow: true\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- RIGHT PINNED -->\r\n <div\r\n class=\"right-pinned-body-wrapper\"\r\n *ngIf=\"hasRightPinnedColumns\"\r\n [class.h-100]=\"originalDataSet.length < 8\"\r\n [style.maxWidth.px]=\"\r\n isScrollbarVisible\r\n ? rightPinnedHeader.offsetWidth - 15\r\n : rightPinnedHeader.offsetWidth\r\n \"\r\n [style.backgroundColor]=\"rightPinnedBackgroundColor\"\r\n >\r\n <div\r\n class=\"data-grid-body right-pinned-body w-100 h-100\"\r\n style=\"overflow-y: hidden\"\r\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\r\n [style.boxShadow]=\"rightPinnedBoxshadow\"\r\n [style.backgroundColor]=\"rightPinnedBackgroundColor\"\r\n *ngIf=\"!loading && !dataSetLoading\"\r\n [@rowDynamic]=\"rowAnimation\"\r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let row of visibleRows;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: row,\r\n columns: previewRightPinnedColumns,\r\n isEven: (startIndex + i) % 2 === 0,\r\n isOdd: (startIndex + i) % 2 !== 0,\r\n section: 'right',\r\n isTotalRow: false\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: { __virtualIndex: 0 },\r\n columns: previewRightPinnedColumns,\r\n isEven: false,\r\n isOdd: false,\r\n section: 'right',\r\n isTotalRow: true\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div\r\n style=\"top: auto; left: auto\"\r\n (click)=\"\r\n $event.stopPropagation();\r\n fullscreenImage = null;\r\n cdr.detectChanges()\r\n \"\r\n [style.width.px]=\"dataGridContainer.offsetWidth\"\r\n [style.height.px]=\"\r\n dataGridContainer.offsetHeight - (footerRowHeight + 100)\r\n \"\r\n class=\"image-modal full-image-modal\"\r\n *ngIf=\"fullscreenImage\"\r\n >\r\n <img\r\n (click)=\"$event.stopPropagation()\"\r\n [src]=\"fullscreenImage\"\r\n alt=\"Fullscreen Image\"\r\n />\r\n </div>\r\n <div\r\n *ngIf=\"selectedRows.size > 0 && showTaskbar\"\r\n class=\"taskbar w-100\"\r\n [style.bottom.px]=\"85\"\r\n >\r\n <div class=\"selected-rows-action-bar\" [@slideUp]>\r\n <span class=\"selected-count\">\r\n {{ selectedRows.size }} selected of\r\n {{\r\n paginationConfig.totalResults ||\r\n config?.paginationParams?.totalItems\r\n }}\r\n Total\r\n </span>\r\n <div class=\"action-buttons d-flex align-items-center\">\r\n <ng-container\r\n *ngFor=\"let action of taskbarActions; let i = index\"\r\n >\r\n <ng-container *ngIf=\"action?.has_permission\">\r\n <span\r\n class=\"action-btn verified btn {{ action }}\"\r\n (click)=\"onVerifyClick(action?.actionName)\"\r\n >{{ action?.actionName }}</span\r\n >\r\n <span\r\n *ngIf=\"\r\n taskbarActions.length > 1 &&\r\n i !== taskbarActions.length - 1 &&\r\n taskbarActions[i + 1]?.has_permission\r\n \"\r\n class=\"\"\r\n >|</span\r\n >\r\n </ng-container>\r\n </ng-container>\r\n <button (click)=\"clearSelectionState(tableType);selectedRows.clear();\" class=\"clear-btn ms-2 mt-2\">\r\n <i class=\"bi bi-x-circle\"></i> Clear Selection\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Vertical Fake scroll Bar -->\r\n <!-- <div\r\n (scroll)=\"onMainFakeScroll($event)\"\r\n class=\"fake-scrollbar fake-scrollbar-vertical d-none\"\r\n [style.scrollbarWidth]=\"verticalScrollbarWidth\"\r\n [style.top.px]=\"\r\n showColumnsGrouping && showFilterRow\r\n ? headerRowHeight * 3\r\n : showColumnsGrouping || showFilterRow\r\n ? headerRowHeight * 2\r\n : headerRowHeight\r\n \"\r\n #fakeScroll\r\n [style.height]=\"bodyWrapperHeight\"\r\n style=\"\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n width: 17px;\r\n position: absolute;\r\n right: 0;\r\n background-color: f1f2f3;\r\n z-index: 10;\r\n \"\r\n >\r\n <div [style.height.px]=\"rowHeight * dataSetLength\"></div>\r\n </div> -->\r\n </div>\r\n\r\n <!-- Horizintal Fake Scrollbars -->\r\n <div\r\n class=\"d-flex justify-content-between\"\r\n *ngIf=\"hasScroll && !shouldRestoreScroll\"\r\n >\r\n <div\r\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\r\n class=\"fake-horizintal-scrollbar\"\r\n #fakeScroll\r\n [style.width.px]=\"leftPinnedHeader.offsetWidth\"\r\n style=\"overflow-x: scroll\"\r\n ></div>\r\n <div\r\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\r\n (scroll)=\"onCenterBodyScroll($event)\"\r\n class=\"fake-horizintal-scrollbar\"\r\n #horizintalFakeScroll\r\n [style.width.px]=\"centerPinnedHeader.offsetWidth\"\r\n >\r\n <div [style.width.px]=\"centerPinnedHeader.scrollWidth - 10\"></div>\r\n </div>\r\n <div\r\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\r\n class=\"fake-horizintal-scrollbar\"\r\n #fakeScroll\r\n [style.width.px]=\"rightPinnedHeader.offsetWidth\"\r\n style=\"overflow-x: scroll\"\r\n ></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Side Menu Implemented Here -->\r\n <div\r\n *ngIf=\"showSideMenu\"\r\n [style.width.px]=\"sideMenuVisible ? 280 : 30\"\r\n class=\"right-menu h-100\"\r\n [style.backgroundColor]=\"sidemenuBackgroundColor\"\r\n >\r\n <div class=\"h-100 d-flex flex-row-reverse\">\r\n <div\r\n style=\"width: 30px\"\r\n class=\"d-flex flex-column align-items-center cursor-pointer\"\r\n [class.border-start]=\"sideMenuVisible\"\r\n >\r\n <div\r\n (click)=\"toggleSideMenu('cols')\"\r\n [class.bg-fff]=\"\r\n currentOpenedSideMenue == 'cols' && sideMenuVisible\r\n \"\r\n [class.border-below]=\"sideMenuVisible\"\r\n class=\"columns-button d-flex flex-column align-items-center\"\r\n >\r\n <div>\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/ui-checks-grid.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div class=\"side-menue-text\">Columns</div>\r\n </div>\r\n\r\n <div\r\n (click)=\"toggleSideMenu('filtrs')\"\r\n [class.bg-fff]=\"\r\n currentOpenedSideMenue == 'filtrs' && sideMenuVisible\r\n \"\r\n [class.border-below]=\"\r\n sideMenuVisible && currentOpenedSideMenue == 'filtrs'\r\n \"\r\n class=\"columns-button d-flex flex-column align-items-center\"\r\n >\r\n <div>\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div class=\"side-menue-text\">Filter</div>\r\n </div>\r\n </div>\r\n <div\r\n class=\"h-100\"\r\n *ngIf=\"sideMenuVisible\"\r\n [ngStyle]=\"{ width: sideMenuVisible ? '250px' : '' }\"\r\n >\r\n <div class=\"h-100\">\r\n <ng-container\r\n *ngIf=\"currentOpenedSideMenue == 'cols' && sideMenuVisible\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"columnPannel\"></ng-container>\r\n <!-- Column Items -->\r\n <div class=\"column-panel-body px-3\">\r\n <ng-container\r\n *ngFor=\"let col of columns; trackBy: trackByField\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"columnPanelItem; context: { col: col }\"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n <hr />\r\n\r\n <div class=\"side-menu-row-groups\" style=\"height: 30%\">\r\n <ng-container\r\n *ngTemplateOutlet=\"sideMenuRowGroups\"\r\n ></ng-container>\r\n </div>\r\n </ng-container>\r\n <ng-container\r\n *ngIf=\"currentOpenedSideMenue == 'filtrs' && sideMenuVisible\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sideFilters\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div\r\n [style.height.px]=\"footerRowHeight\"\r\n class=\"border-top\"\r\n [style.backgroundColor]=\"footerRowBackgroundColor\"\r\n >\r\n <!-- Rows: <span class=\"fw-500 ms-1\">{{ dataSet.length }}</span> -->\r\n\r\n <div\r\n class=\"pagination-container\"\r\n [style.height.px]=\"footerRowHeight\"\r\n [style.padding.px]=\"footerPadding\"\r\n >\r\n <div class=\"page-size\">\r\n <select\r\n [(ngModel)]=\"paginationConfig.limit\"\r\n (change)=\"onPageSizeChange()\"\r\n >\r\n <option *ngFor=\"let size of pageSizeOptions\" [value]=\"size\">\r\n {{ size }}\r\n </option>\r\n </select>\r\n <span class=\"separator\"> per page </span>\r\n </div>\r\n\r\n <div class=\"page-info\">\r\n Results:\r\n {{ (paginationConfig.page - 1) * paginationConfig.limit + 1 }}-{{\r\n paginationConfig.page * paginationConfig.limit <\r\n paginationConfig.totalResults\r\n ? paginationConfig.page * paginationConfig.limit\r\n : paginationConfig.totalResults\r\n }}\r\n of\r\n {{ paginationConfig.totalResults }}\r\n </div>\r\n\r\n <div class=\"page-buttons\">\r\n <button\r\n (click)=\"goToPage(paginationConfig.page - 1)\"\r\n [disabled]=\"paginationConfig.page === 1\"\r\n >\r\n \u2039\r\n </button>\r\n\r\n <ng-container *ngFor=\"let page of visiblePages\">\r\n <button\r\n *ngIf=\"page !== '...'\"\r\n (click)=\"goToPage(page)\"\r\n [class.active]=\"page === paginationConfig.page\"\r\n >\r\n {{ page }}\r\n </button>\r\n <span *ngIf=\"page === '...'\">...</span>\r\n </ng-container>\r\n\r\n <button\r\n (click)=\"goToPage(paginationConfig.page + 1)\"\r\n [disabled]=\"paginationConfig.page === paginationConfig.totalResults\"\r\n >\r\n \u203A\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\r\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\r\n<!-- Header Cell Template -->\r\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\r\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\r\n\r\n<ng-template\r\n #headerCell\r\n let-col\r\n let-pinnedRight=\"pinnedRight\"\r\n let-i=\"index\"\r\n let-columnIndex=\"index\"\r\n let-sections=\"section\"\r\n let-calledFromNestedPlaceholder=\"calledFromNestedPlaceholder\"\r\n>\r\n <div>\r\n <!-- Group Header -->\r\n <ng-container *ngIf=\"col.children?.length > 0; else flatHeader\">\r\n <div cdkDroplistGroup class=\"group-column-wrapper\">\r\n <!-- Parent Header -->\r\n <div\r\n *ngIf=\"shouldTheGroupHeaderShow(col)\"\r\n class=\"header-cell group-header\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [style.gridColumn]=\"'span ' + col.children.length\"\r\n [style.fontWeight]=\"headerFontWeight\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n [class.justify-content-end]=\"pinnedRight\"\r\n style=\"grid-row: 1\"\r\n >\r\n <div\r\n class=\"group-header-content\"\r\n [title]=\"col.header\"\r\n [class.ms-2]=\"pinnedRight\"\r\n >\r\n {{ col.header }}\r\n </div>\r\n <div\r\n class=\"resize-handle\"\r\n (dblclick)=\"autosizeColumn(col.children)\"\r\n (mousedown)=\"\r\n $event.stopPropagation(); onResizeGroup($event, col, pinnedRight)\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Child Headers and Filters -->\r\n\r\n <div\r\n class=\"d-flex\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListData]=\"col.children\"\r\n (cdkDropListSorted)=\"onChildDroplistSorted($event, sections)\"\r\n (cdkDropListDropped)=\"onChildDroplistDroped($event)\"\r\n [cdkDropListSortingDisabled]=\"false\"\r\n [cdkDropListConnectedTo]=\"\r\n showRowsGrouping ? ['rows-grouping-top-container'] : []\r\n \"\r\n >\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"child\"\r\n *ngFor=\"let child of col.children; let i = index\"\r\n >\r\n <!-- Child Header -->\r\n <ng-container *ngIf=\"child.is_visible && !child['isRowGrouped']\">\r\n <div\r\n cdkDragHandle\r\n class=\"header-cell one-row-header-cells cursor-pointer\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [attr.field]=\"child.field\"\r\n [style.width.px]=\"child.width\"\r\n [style.min-width.px]=\"child.width\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n [style.fontWeight]=\"headerFontWeight\"\r\n style=\"grid-row: 2\"\r\n [class.filter-applied-on-text]=\"isFilterAppliedOnColumn(child)\"\r\n >\r\n <div\r\n class=\"d-flex justify-content-between h-100 align-items-center w-100\"\r\n >\r\n <div\r\n class=\"d-flex justify-content-between align-items-center w-100\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div\r\n class=\"text-ellipsis h-100 d-flex align-items-center w-100\"\r\n [title]=\"col.header\"\r\n [class.w-100]=\"pinnedRight\"\r\n >\r\n <div\r\n class=\"text-ellipsis h-100\"\r\n [class.editable-header]=\"child?.is_editable\"\r\n (click)=\"\r\n openThreeDotsMenu($event, child);\r\n openFilteronThreeDotsClick(child)\r\n \"\r\n >\r\n {{ child.header }}\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"position-relative d-flex\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div\r\n [class.me-2]=\"pinnedRight\"\r\n class=\"d-flex align-items-center\"\r\n *ngIf=\"child.pinned\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div\r\n class=\"three-dots p-1\"\r\n (click)=\"\r\n openThreeDotsMenu($event, child);\r\n isThreeDotsFilterOpen = false\r\n \"\r\n style=\"cursor: pointer\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/three-dots-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n\r\n <!-- Only show menu if this column is active -->\r\n <div\r\n class=\"position-absolute\"\r\n *ngIf=\"activeCol === child\"\r\n style=\"top: -50%; z-index: 21\"\r\n [style.left.px]=\"\r\n -(!child?.pinned ? centerPinnedHeader.scrollLeft : 0)\r\n \"\r\n [style.top.px]=\"\r\n isThreeDotsFilterOpen\r\n ? showFilterRow || showColumnsGrouping\r\n ? headerRowHeight * 2 - 10\r\n : headerRowHeight - 10\r\n : 0\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n columnMenu;\r\n context: {\r\n col: child,\r\n isNestedTable: false,\r\n section: sections,\r\n columnIndex: columnIndex,\r\n childColIndex: i\r\n }\r\n \"\r\n ></ng-container>\r\n </div>\r\n\r\n <div\r\n class=\"resize-handle\"\r\n (dblclick)=\"autosizeColumn(child)\"\r\n (mousedown)=\"\r\n $event.stopPropagation();\r\n onResizeColumn($event, child)\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filter Cell -->\r\n <div\r\n *ngIf=\"showFilterRow\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n class=\"header-cell filter-cell\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [attr.field]=\"child.field\"\r\n [style.width.px]=\"child.width\"\r\n [style.min-width.px]=\"child.width\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n style=\"grid-row: 3\"\r\n >\r\n <div\r\n class=\"header-cell filter-cell\"\r\n [attr.field]=\"col.field\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n >\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Filter\"\r\n [(ngModel)]=\"child.filterValue\"\r\n (ngModelChange)=\"onFilterChange(child)\"\r\n (paste)=\"onFilterChange(child); applyDropdownFilter()\"\r\n [readonly]=\"\r\n child?.type == 'dropdown' || child?.type == 'image' || child?.type == 'array'\r\n \"\r\n [class.disabled-search-input]=\"\r\n child?.type == 'dropdown' || child?.type == 'image' || child?.type == 'array'\r\n \"\r\n (click)=\"\r\n $event.stopPropagation();\r\n openFilterFromDisabledSearchedInput(child)\r\n \"\r\n (keydown.enter)=\"applyDropdownFilter()\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n <span\r\n class=\"filter-icon-wrapper\"\r\n (click)=\"$event.stopPropagation(); openFilter(child)\"\r\n [class.filter-applied]=\"isFilterAppliedOnColumn(child)\"\r\n [class.pe-none]=\"child?.type == 'image'\"\r\n ><span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <span\r\n *ngIf=\"isFilterAppliedOnColumn(child)\"\r\n style=\"\r\n width: 7px;\r\n height: 7px;\r\n box-shadow: 0px 0px 3px #7486ff;\r\n background-color: rgb(0 163 233);\r\n position: absolute;\r\n right: 4px;\r\n top: 12px;\r\n \"\r\n class=\"rounded-circle d-block\"\r\n ></span\r\n ></span>\r\n\r\n <div\r\n class=\"position-absolute filter-row-filter-wrapper\"\r\n *ngIf=\"activeFilterCell?.field == child?.field\"\r\n style=\"top: 100%; right: 0; z-index: 99\"\r\n [style.left.px]=\"\r\n child?.pinned ? 0 : -centerPinnedHeader.scrollLeft\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"filterMenu; context: { col: child }\"\r\n ></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n <ng-template cdkDragPreview\r\n ><div class=\"p-2 border d-flex gap-2\">\r\n <div\r\n *ngIf=\"\r\n !draggingInGroupArea ||\r\n (child.is_groupable && draggingInGroupArea)\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div *ngIf=\"draggingInGroupArea && !child.is_groupable\">\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/ban.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ child.header }}</div>\r\n </div>\r\n </ng-template>\r\n <ng-template cdkDragPlaceholder>\r\n <div *ngIf=\"!draggingInGroupArea\" class=\"position-relative\">\r\n <div\r\n *ngTemplateOutlet=\"\r\n childHeaderPlaceholder;\r\n context: {\r\n $implicit: child,\r\n index: i,\r\n sections: sections,\r\n calledFromNestedPlaceholder: true,\r\n }\r\n \"\r\n ></div>\r\n </div>\r\n <div\r\n *ngIf=\"draggingInGroupArea && child?.is_groupable\"\r\n class=\"d-flex gap-2 ms-2\"\r\n style=\"opacity: 0.6\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: child,\r\n showChevron: false,\r\n pinnedRight: pinnedRight,\r\n sections: sections,\r\n index: i\r\n }\r\n \"\r\n ></ng-container>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Flat Header || Single Header Cell-->\r\n <ng-template #flatHeader>\r\n <div\r\n class=\"group-column-wrapper\"\r\n *ngIf=\"col.is_visible && !col['isRowGrouped']\"\r\n >\r\n <!-- Full-height Header Cell (spans 2 rows visually) -->\r\n <div\r\n class=\"header-cell one-row-header-cells\"\r\n [attr.field]=\"col.field\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [style.min-height.px]=\"\r\n showColumnsGrouping ? headerRowHeight * 2 : headerRowHeight\r\n \"\r\n [style.height.px]=\"\r\n showColumnsGrouping ? headerRowHeight * 2 : headerRowHeight\r\n \"\r\n [style.fontWeight]=\"headerFontWeight\"\r\n style=\"grid-row: 1 / span 2\"\r\n >\r\n <div\r\n class=\"d-flex justify-content-between h-100 align-items-center w-100\"\r\n >\r\n <div\r\n class=\"d-flex justify-content-between w-100 align-items-center\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div\r\n class=\"text-ellipsis h-100 d-flex align-items-center w-100\"\r\n [title]=\"col.header\"\r\n >\r\n <div\r\n class=\"text-ellipsis h-100 cursor-pointer\"\r\n [class.editable-header]=\"col?.is_editable\"\r\n [class.filter-applied-on-text]=\"isFilterAppliedOnColumn(col)\"\r\n (click)=\"\r\n openThreeDotsMenu($event, col);\r\n openFilteronThreeDotsClick(col)\r\n \"\r\n >\r\n {{ col.header }}\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"position-relative d-flex\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div\r\n [class.me-2]=\"pinnedRight\"\r\n class=\"d-flex align-items-center\"\r\n *ngIf=\"col?.pinned\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div\r\n [class.me-2]=\"col.order_by\"\r\n class=\"d-flex align-items-center\"\r\n *ngIf=\"sortingConfig?.field == col.field\"\r\n >\r\n <!-- Ascending Sort Icon -->\r\n <span\r\n *ngIf=\"sortingConfig?.order_by == 'asc'\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/sort-asc.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center mt-1 cursor-pointer\"\r\n (click)=\"sortDesc(col)\"\r\n [class.active]=\"sortingConfig?.order_by === 'asc'\"\r\n ></span>\r\n\r\n <!-- Descending Sort Icon -->\r\n <span\r\n *ngIf=\"sortingConfig?.order_by == 'desc'\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/sort-desc.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center mt-1 cursor-pointer\"\r\n (click)=\"sortAsc(col)\"\r\n [class.active]=\"sortingConfig?.order_by === 'desc'\"\r\n ></span>\r\n </div>\r\n <div\r\n class=\"three-dots p-1\"\r\n (click)=\"\r\n openThreeDotsMenu($event, col);\r\n isThreeDotsFilterOpen = false\r\n \"\r\n style=\"cursor: pointer\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/three-dots-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n\r\n <!-- Only show menu if this column is active -->\r\n <div\r\n class=\"position-absolute\"\r\n *ngIf=\"activeCol === col\"\r\n style=\"top: -50%; z-index: 21\"\r\n [style.left.px]=\"\r\n -(!col?.pinned ? centerPinnedHeader.scrollLeft : 0)\r\n \"\r\n [style.top.px]=\"\r\n isThreeDotsFilterOpen\r\n ? showFilterRow || showColumnsGrouping\r\n ? headerRowHeight * 2 - 10\r\n : headerRowHeight - 10\r\n : 0\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n columnMenu;\r\n context: {\r\n col: col,\r\n isNestedTable: false,\r\n section: sections,\r\n columnIndex: columnIndex,\r\n childColIndex: 0\r\n },\r\n \"\r\n ></ng-container>\r\n </div>\r\n\r\n <div\r\n class=\"resize-handle\"\r\n [class.w-100]=\"col.pinned == 'right'\"\r\n (dblclick)=\"autosizeColumn(col)\"\r\n (mousedown)=\"\r\n $event.stopPropagation(); onResizeColumn($event, col)\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filter Cell -->\r\n <div\r\n *ngIf=\"showFilterRow\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n class=\"header-cell filter-cell\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [attr.field]=\"col.field\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n >\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Filter\"\r\n [(ngModel)]=\"col.filterValue\"\r\n (ngModelChange)=\"onFilterChange(col)\"\r\n [readonly]=\"col?.type == 'dropdown' || col?.type == 'image' || col?.type == 'array'\"\r\n [class.disabled-search-input]=\"\r\n col?.type == 'dropdown' || col?.type == 'image' || col?.type == 'array'\r\n \"\r\n (paste)=\"onPasteInFilterRowSearch($event, col)\"\r\n (click)=\"\r\n $event.stopPropagation(); openFilterFromDisabledSearchedInput(col)\r\n \"\r\n (keydown.enter)=\"applyDropdownFilter()\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n <span\r\n class=\"filter-icon-wrapper\"\r\n (click)=\"$event.stopPropagation(); openFilter(col)\"\r\n [class.filter-applied]=\"isFilterAppliedOnColumn(col)\"\r\n [class.pe-none]=\"col?.type == 'image'\"\r\n ><span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <span\r\n *ngIf=\"isFilterAppliedOnColumn(col)\"\r\n style=\"\r\n width: 7px;\r\n height: 7px;\r\n box-shadow: 0px 0px 3px #7486ff;\r\n background-color: rgb(0 163 233);\r\n position: absolute;\r\n right: 4px;\r\n top: 12px;\r\n \"\r\n class=\"rounded-circle d-block\"\r\n ></span\r\n ></span>\r\n\r\n <div\r\n class=\"position-absolute filter-row-filter-wrapper\"\r\n *ngIf=\"activeFilterCell === col\"\r\n style=\"top: 100%; right: 0; z-index: 99\"\r\n [style.left.px]=\"col?.pinned ? 0 : -centerPinnedHeader.scrollLeft\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"filterMenu; context: { col: col }\"\r\n ></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\r\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\r\n<!-- Body Cell Template -->\r\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\r\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\r\n\r\n<ng-template\r\n #rowCell\r\n let-row\r\n let-columns=\"columns\"\r\n let-isEven=\"isEven\"\r\n let-isOdd=\"isOdd\"\r\n let-isLeftSection=\"isLeft\"\r\n let-section=\"section\"\r\n let-rowIndex=\"rowIndex\"\r\n let-isTotalRow=\"isTotalRow\"\r\n>\r\n <!-- Check if row is a group -->\r\n <ng-container\r\n *ngTemplateOutlet=\"groupRowTemplate; context: { $implicit: row, depth: 0 }\"\r\n ></ng-container>\r\n <ng-template #groupRowTemplate let-row let-depth=\"depth\">\r\n <ng-container *ngIf=\"row.isGroup; else regularRow\">\r\n <!-- Group Header -->\r\n <div\r\n class=\"group-header-row d-flex align-items-center\"\r\n [style.height.px]=\"rowHeight\"\r\n [class.border-below]=\"section !== 'center'\"\r\n [style.width]=\"\r\n section === 'center'\r\n ? (centerScrollableBody?.scrollWidth ?? 0) + 'px'\r\n : '100%'\r\n \"\r\n >\r\n <div\r\n *ngIf=\"section == 'left'\"\r\n class=\"h-100 d-flex\"\r\n [style.width.px]=\"leftPinnedHeader.offsetWidth - 1\"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n >\r\n <div\r\n *ngIf=\"showSerialNumber\"\r\n style=\"width: 50px\"\r\n class=\"d-flex align-items-center h-100 border-right justify-content-end pe-2 s-no\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n [style.width.px]=\"55\"\r\n [style.cursor]=\"\r\n 'url(' +\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/arrow-right.svg), auto'\r\n \"\r\n (mousedown)=\"onRowMouseDown(row.__virtualIndex, $event)\"\r\n (mouseover)=\"onRowMouseOver(row.__virtualIndex, $event)\"\r\n [style.color]=\"checkboxesColor\"\r\n >\r\n {{ getStartIndex() + (row.__virtualIndex - 1) || \"\" }}\r\n </div>\r\n <div\r\n *ngIf=\"showCheckboxes\"\r\n style=\"width: 50px\"\r\n class=\"d-flex align-items-center justify-content-center h-100 border-right\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.left-selection-border]=\"\r\n rowSelectedIndexes.has(row.__virtualIndex)\r\n \"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n [style.color]=\"checkboxesColor\"\r\n >\r\n <input\r\n style=\"width: 16px; height: 16px\"\r\n type=\"checkbox\"\r\n [checked]=\"getGroupCheckedState(row) === true\"\r\n [indeterminate]=\"getGroupCheckedState(row) === undefined\"\r\n (change)=\"selectGroupRow($event, row)\"\r\n />\r\n\r\n </div>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"section == 'center'\"\r\n [style.width.px]=\"centerPinnedHeader.scrollWidth\"\r\n [style.minWidth.px]=\"centerPinnedHeader.scrollWidth\"\r\n class=\"d-flex align-items-center ps-2 h-100 border-below\"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n >\r\n <div\r\n class=\"d-flex align-items-center justify-content-between\"\r\n [style.paddingLeft.px]=\"depth > 0 ? depth * 30 : 0\"\r\n >\r\n <span class=\"me-2 filter-icon-wrapper\" (click)=\"toggleExpand(row)\">\r\n <span\r\n class=\"data-grid-svg-icon align-items-center d-flex\"\r\n [inlineSVG]=\"\r\n row.isExpand\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n ></span>\r\n </span>\r\n <strong (click)=\"toggleExpand(row)\" class=\"cursor-pointer\">\r\n {{ row.groupValue }} ({{ countLeafRows(row) }})\r\n </strong>\r\n </div>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"section == 'right'\"\r\n [style.width.px]=\"rightPinnedHeader.offsetWidth\"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n ></div>\r\n </div>\r\n\r\n <!-- Recursive Children -->\r\n <div class=\"group-children\" *ngIf=\"row.isExpand\" [@slideToggle]>\r\n <ng-container\r\n *ngFor=\"let child of row.children; let i = index; trackBy: trackById\"\r\n >\r\n <ng-container *ngIf=\"child.isGroup; else dataRow\">\r\n <!-- Recursive call for nested group -->\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n groupRowTemplate;\r\n context: { $implicit: child, depth: depth + 1 }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n\r\n <ng-template #dataRow>\r\n <!-- Regular data row -->\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: child,\r\n columns: columns,\r\n isEven: i % 2 === 0,\r\n isOdd: i % 2 !== 0,\r\n isLeft: isLeftSection,\r\n section: section,\r\n isTotalRow: isTotalRow\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-template>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </ng-template>\r\n\r\n <!-- Regular row (not a group) -->\r\n <ng-template #regularRow>\r\n <div\r\n class=\"d-flex\"\r\n [style.height.px]=\"rowHeight\"\r\n [style.minHeight.px]=\"rowHeight\"\r\n [style.maxHeight.px]=\"rowHeight\"\r\n >\r\n <span\r\n class=\"d-flex align-items-center justify-content-center cursor-pointer border-below\"\r\n style=\"min-width: 30px; height: 100%\"\r\n *ngIf=\"\r\n section == 'center' && (gridType === 'Assets' || gridType === 'Tasks')\r\n \"\r\n [ngStyle]=\"{\r\n 'background-color': rowSelectedIndexes.has(row.__virtualIndex)\r\n ? null\r\n : getBackgroundColor(row, isEven, section)\r\n }\"\r\n [class.selected-cell]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n >\r\n <span\r\n (click)=\"toggleDetailRowExpand(row)\"\r\n *ngIf=\"row?.detail?.result?.length || gridType === 'Tasks'\"\r\n class=\"data-grid-svg-icon filter-icon-wrapper\"\r\n [inlineSVG]=\"\r\n isDetailsExpanded(row)\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n ></span>\r\n </span>\r\n <div\r\n [style.min-width.px]=\"\r\n section == 'center' && groupedColumns?.length ? groupBoxPadding : 0\r\n \"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n (contextmenu)=\"onRightClick($event, row)\"\r\n [style.height.px]=\"rowHeight\"\r\n class=\"data-grid-row h-100\"\r\n [class.even-row]=\"isEven\"\r\n [class.odd-row]=\"isOdd\"\r\n [class.hovered-row]=\"hoveredRowId === (row._id || row.id)\"\r\n (mouseenter)=\"onRowHover(row)\"\r\n (mouseleave)=\"onRowLeave()\"\r\n [ngStyle]=\"{\r\n 'background-color': getBackgroundColor(row, isEven, section)\r\n }\"\r\n [style.minHeight.px]=\"rowHeight\"\r\n [style.maxHeight.px]=\"rowHeight\"\r\n ></div>\r\n <div\r\n (contextmenu)=\"onRightClick($event, row)\"\r\n [style.height.px]=\"rowHeight\"\r\n class=\"data-grid-row\"\r\n [class.even-row]=\"isEven\"\r\n [class.odd-row]=\"isOdd\"\r\n [class.hovered-row]=\"hoveredRowId === (row._id || row.id)\"\r\n (mouseenter)=\"onRowHover(row)\"\r\n (mouseleave)=\"onRowLeave()\"\r\n [ngStyle]=\"{\r\n 'background-color': getBackgroundColor(row, isEven, section)\r\n }\"\r\n >\r\n <div\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n class=\"select-all-checkbox-cell justify-content-end pe-2 s-no\"\r\n [style.width.px]=\"55\"\r\n *ngIf=\"isLeftSection && showSerialNumber\"\r\n [style.cursor]=\"\r\n 'url(' +\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/arrow-right.svg), auto'\r\n \"\r\n (mousedown)=\"onRowMouseDown(row.__virtualIndex, $event)\"\r\n (mouseover)=\"onRowMouseOver(row.__virtualIndex, $event)\"\r\n [style.color]=\"checkboxesColor\"\r\n >\r\n {{ getStartIndex() + (row.__virtualIndex - 1) }}\r\n </div>\r\n <div\r\n class=\"border-below\"\r\n [style.backgroundColor]=\"\r\n rowSelectedIndexes.has(row.__virtualIndex)\r\n ? selectedRowsBackgroundColor\r\n : checkboxesBackgroundColor\r\n \"\r\n class=\"select-all-checkbox-cell\"\r\n *ngIf=\"isLeftSection && showCheckboxes\"\r\n [class.left-selection-border]=\"\r\n rowSelectedIndexes.has(row.__virtualIndex)\r\n \"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n [style.minHeight.px]=\"rowHeight - 1\"\r\n [style.maxHeight.px]=\"rowHeight\"\r\n >\r\n <input\r\n *ngIf=\"hasAnyVisibleColumn\"\r\n style=\"width: 16px; height: 16px\"\r\n type=\"checkbox\"\r\n [checked]=\"isRowSelected(row)\"\r\n (change)=\"toggleRowSelection(row)\"\r\n />\r\n </div>\r\n\r\n <!-- Render all columns -->\r\n <ng-container\r\n *ngFor=\"\r\n let col of columns;\r\n trackBy: trackByField;\r\n let colIndex = index\r\n \"\r\n >\r\n <ng-container *ngIf=\"col.children?.length > 0; else flatColumn\">\r\n <ng-container\r\n *ngFor=\"\r\n let child of col.children;\r\n trackBy: trackByField;\r\n let subColIndex = index\r\n \"\r\n >\r\n <ng-container *ngIf=\"child?.is_visible && !child?.isRowGrouped\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n cellTemplate;\r\n context: {\r\n col: child,\r\n row: row,\r\n rowIndex: rowIndex,\r\n colIndex: colIndex,\r\n subColIndex: subColIndex,\r\n section: section,\r\n isTotalRow: isTotalRow\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #flatColumn>\r\n <ng-container *ngIf=\"col?.is_visible && !col?.isRowGrouped\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n cellTemplate;\r\n context: {\r\n col: col,\r\n row: row,\r\n rowIndex: rowIndex,\r\n colIndex: colIndex,\r\n subColIndex: null,\r\n section: section,\r\n isTotalRow: isTotalRow\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-template>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div\r\n [@slideToggle]\r\n *ngIf=\"section === 'left' && isDetailsExpanded(row)\"\r\n class=\"accordion-details\"\r\n style=\"max-height: 350px; overflow: hidden\"\r\n [style.maxHeight.px]=\"hasHorizontalScroll ? 339 : 341\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n leftRightNestedPlaceholder;\r\n context: { $implicit: row }\r\n \"\r\n >\r\n </ng-container>\r\n </div>\r\n\r\n <div\r\n [@slideToggle]\r\n *ngIf=\"section === 'center' && isDetailsExpanded(row)\"\r\n class=\"accordion-details center-section\"\r\n style=\"\r\n max-height: 350px;\r\n overflow-y: hidden;\r\n overflow-x: auto;\r\n scrollbar-width: thin;\r\n \"\r\n #nestedTable\r\n [style.width]=\"\r\n hasRightPinnedColumns\r\n ? '100%'\r\n : hasVerticalScroll\r\n ? 'calc(100% - 12px)'\r\n : '100%'\r\n \"\r\n >\r\n <ng-container *ngIf=\"gridType == 'Assets'\">\r\n <ng-container\r\n *ngTemplateOutlet=\"nestedTableTemplate; context: { $implicit: row }\"\r\n ></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"gridType == 'Tasks'\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n taskManagementTemplate;\r\n context: { taskDetails: row }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n <div\r\n [@slideToggle]\r\n *ngIf=\"section === 'right' && isDetailsExpanded(row)\"\r\n class=\"accordion-details\"\r\n style=\"max-height: 350px; overflow: hidden\"\r\n [style.maxHeight.px]=\"hasHorizontalScroll ? 339 : 341\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n leftRightNestedPlaceholder;\r\n context: { $implicit: row }\r\n \"\r\n >\r\n </ng-container>\r\n </div>\r\n </ng-template>\r\n</ng-template>\r\n\r\n<!-- Actual Cell is Here -->\r\n<ng-template\r\n #cellTemplate\r\n let-col=\"col\"\r\n let-row=\"row\"\r\n let-section=\"section\"\r\n let-subColIndex=\"subColIndex\"\r\n let-rowIndex=\"rowIndex\"\r\n let-colIndex=\"colIndex\"\r\n let-isTotalRow=\"isTotalRow\"\r\n>\r\n <div\r\n #cellContainer\r\n (click)=\"\r\n editingKey = ''; setActiveCell(row, col); collapseAllExpandedCells()\r\n \"\r\n [style.fontWeight]=\"bodyFontWeight\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n class=\"cell overflow-visible position-relative data-grid-cell\"\r\n [attr.field]=\"col.field\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.fontSize.px]=\"bodyTextFontsSize\"\r\n [style.minHeight.px]=\"rowHeight\"\r\n [style.maxHeight.px]=\"rowHeight\"\r\n [class.active-cell]=\"\r\n isActiveCell(row, col) && !isEditing(row, col) && selectedKeys.size == 1\r\n \"\r\n (dblclick)=\"\r\n $event.stopPropagation();\r\n $event.preventDefault();\r\n enableEdit(row, col, false, cellContainer)\r\n \"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.first-row-selected]=\"firstSelectedRow === row?.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row?.__virtualIndex\"\r\n tabindex=\"-1\"\r\n (keydown.enter)=\"$event.preventDefault(); enableEdit(row, col)\"\r\n (mousedown)=\"\r\n startSelection(\r\n row.__virtualIndex,\r\n colIndex,\r\n subColIndex ?? 0,\r\n col.field,\r\n $event,\r\n section\r\n )\r\n \"\r\n (mouseenter)=\"\r\n extendSelection(\r\n row.__virtualIndex,\r\n colIndex,\r\n subColIndex ?? 0,\r\n col.field,\r\n $event,\r\n section\r\n )\r\n \"\r\n (mouseup)=\"endSelection()\"\r\n [class.selected-cell]=\"\r\n isSelected(\r\n row.__virtualIndex,\r\n colIndex,\r\n subColIndex ?? 0,\r\n col.field,\r\n section\r\n )\r\n \"\r\n [class.top-border]=\"\r\n isTopBorder(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.bottom-border]=\"\r\n isBottomBorder(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.left-border]=\"\r\n isLeftBorder(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.right-border]=\"\r\n isRightBorder(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.top-left-corner]=\"\r\n isTopLeftCorner(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.top-right-corner]=\"\r\n isTopRightCorner(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.bottom-left-corner]=\"\r\n isBottomLeftCorner(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.bottom-right-corner]=\"\r\n isBottomRightCorner(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n >\r\n <!-- (mousedown)=\"startSelection(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field, $event)\"\r\n (mouseenter)=\"extendSelection(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field, $event)\"\r\n (mouseup)=\"endSelection()\"\r\n [class.selected-cell]=\"isSelected(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field)\" -->\r\n <div\r\n class=\"table-cell\"\r\n [class.active-for-editing]=\"\r\n isEditing(row, col) &&\r\n (getNestedValue(row, col.field)?.length === undefined ||\r\n getNestedValue(row, col.field)?.length <= 50)\r\n \"\r\n >\r\n <div\r\n (click)=\"$event.stopPropagation()\"\r\n *ngIf=\"\r\n isEditing(row, col) &&\r\n (getNestedValue(row, col.field)?.length === undefined ||\r\n (getNestedValue(row, col.field)?.length <= 50 &&\r\n !expandedCells.size));\r\n else viewMode\r\n \"\r\n >\r\n\r\n <ng-container *ngIf=\"col.cellEditor; else builtInEditors\">\r\n <ng-container\r\n [cellEditor]=\"col.cellEditor\"\r\n [rowData]=\"row\"\r\n [colData]=\"col\"\r\n [cellValue]=\"getNestedValue(row, col.field)\"\r\n (editorEvent)=\"finishEdit($event)\"\r\n ></ng-container>\r\n </ng-container>\r\n\r\n <ng-template #builtInEditors>\r\n <ng-container [ngSwitch]=\"col?.type\">\r\n <!-- Text Input -->\r\n <input\r\n [style.height.px]=\"rowHeight - 10\"\r\n *ngSwitchCase=\"'input'\"\r\n type=\"text\"\r\n [(ngModel)]=\"row[col.field]\"\r\n (blur)=\"disableEdit(row, col)\"\r\n autofocus\r\n (keydown.enter)=\"blurInput($event, row, col)\"\r\n class=\"form-control form-control-sm\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n\r\n <!-- Number Input -->\r\n <input\r\n [style.height.px]=\"rowHeight - 8\"\r\n *ngSwitchCase=\"'number'\"\r\n #numberInput=\"ngModel\"\r\n #numberRef\r\n (keypress)=\"allowOnlyNumbers($event)\"\r\n type=\"number\"\r\n required\r\n [(ngModel)]=\"row[col.field]\"\r\n (blur)=\"disableEdit(row, col, numberInput)\"\r\n autofocus\r\n (keydown.enter)=\"blurInput($event, row, col)\"\r\n class=\"form-control form-control-sm\"\r\n [ngClass]=\"{\r\n 'is-invalid': numberInput.invalid\r\n }\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n\r\n <!-- Date Input -->\r\n <input\r\n [style.height.px]=\"rowHeight - 8\"\r\n *ngSwitchCase=\"'date'\"\r\n type=\"date\"\r\n [(ngModel)]=\"row[col.field]\"\r\n (blur)=\"disableEdit(row, col, dateInput)\"\r\n autofocus\r\n class=\"form-control form-control-sm\"\r\n #dateInput=\"ngModel\"\r\n (keydown.enter)=\"blurInput($event, row, col)\"\r\n [ngClass]=\"{\r\n 'is-invalid': dateInput.invalid\r\n }\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n\r\n <!-- Dropdown -->\r\n <!-- ng-select like dropdown -->\r\n <div\r\n *ngSwitchCase=\"'dropdown'\"\r\n class=\"dropdown w-100\"\r\n (blur)=\"disableEdit(row, col)\"\r\n >\r\n <!-- Trigger -->\r\n <button\r\n class=\"form-select form-select-sm text-start w-100 text-ellipsis\"\r\n type=\"button\"\r\n data-bs-toggle=\"dropdown\"\r\n aria-expanded=\"false\"\r\n [style.minHeight.px]=\"rowHeight - 10\"\r\n data-bs-display=\"static\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n >\r\n <ng-container>\r\n {{\r\n getNestedValue(row, col.field)?.value ||\r\n getNestedValue(row, col.field)?.name ||\r\n getNestedValue(row, col.field)\r\n }}\r\n </ng-container>\r\n <ng-template #placeholder> Select options... </ng-template>\r\n </button>\r\n\r\n <!-- Menu -->\r\n <div\r\n class=\"dropdown-menu w-100 p-0 cell-editing-dropdown-menu rounded-3\"\r\n [class.show]=\"isEditing(row, col)\"\r\n >\r\n <!-- Search -->\r\n <div class=\"px-2 py-1 editing-dropdown-search-input\" *ngIf=\"col?.column_dropdown_value?.length > 5\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search...\"\r\n [(ngModel)]=\"editinDropdownSearch\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n </div>\r\n <cdk-virtual-scroll-viewport \r\n itemSize=\"35\" \r\n class=\"dropdown-viewport\"\r\n style=\"height: 120px\"\r\n >\r\n <div\r\n [class.selected]=\"getNestedValue(row, col.field) == option?.value || getNestedValue(row, col.field) == option\"\r\n class=\"px-2 py-1 d-flex align-items-center dropdown-item\"\r\n *cdkVirtualFor=\"\r\n let option of col.column_dropdown_value \r\n | filter : editinDropdownSearch : 'value'\r\n \"\r\n (click)=\"setNestedValue(row, col, option, true); editingKey = null\"\r\n >\r\n <label\r\n \r\n class=\"form-check-label d-flex align-items-center mb-0 cursor-pointer\"\r\n [for]=\"col.field + '-' + (option.value || option)\"\r\n >\r\n {{ option.value || option }}\r\n </label>\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n\r\n </div>\r\n </div>\r\n\r\n <input\r\n *ngSwitchCase=\"'email'\"\r\n [style.height.px]=\"rowHeight - 10\"\r\n [style.maxHeight.px]=\"rowHeight - 10\"\r\n #emailModel=\"ngModel\"\r\n #emailInput\r\n type=\"email\"\r\n [(ngModel)]=\"row[col.field]\"\r\n name=\"{{ col.field }}\"\r\n required\r\n pattern=\"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\"\r\n (blur)=\"disableEdit(row, col, emailModel)\"\r\n (keydown.enter)=\"blurInput($event, row, col)\"\r\n autofocus\r\n class=\"form-control form-control-sm\"\r\n [ngClass]=\"{\r\n 'is-invalid': emailModel.invalid\r\n }\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n <!-- Default fallback -->\r\n <input\r\n *ngSwitchDefault\r\n [style.height.px]=\"rowHeight - 10\"\r\n [style.maxHeight.px]=\"rowHeight - 10\"\r\n #textModel=\"ngModel\"\r\n #textInput\r\n type=\"text\"\r\n (keydown.enter)=\"blurInput($event, row, col)\"\r\n [(ngModel)]=\"row[col.field]\"\r\n name=\"{{ col.field }}\"\r\n required\r\n (blur)=\"disableEdit(row, col, textModel)\"\r\n autofocus\r\n class=\"form-control form-control-sm\"\r\n [ngClass]=\"{\r\n 'is-invalid': textModel.invalid\r\n }\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n </ng-container>\r\n </ng-template>\r\n\r\n </div>\r\n\r\n <!-- Display mode -->\r\n <ng-template #viewMode>\r\n <div\r\n class=\"d-flex justify-content-between align-items-center w-100 overflow-hidden\"\r\n [ngClass]=\"getCellClasses(col, getNestedValue(row, col.field))\"\r\n >\r\n <!-- Field icon (for Tasks grid) -->\r\n <ng-container\r\n *ngIf=\"gridType === 'Tasks' && iconMap[col.field] && !isTotalRow\"\r\n >\r\n <span\r\n class=\"cursor-pointer me-2\"\r\n (click)=\"$event.preventDefault(); $event.stopPropagation()\"\r\n [inlineSVG]=\"iconMap[col.field](row, col)\"\r\n ></span>\r\n </ng-container>\r\n\r\n <!-- \u2705 Custom cell renderer support -->\r\n <ng-container *ngIf=\"col.cellRenderer; else defaultCell\">\r\n <ng-container\r\n [cellRenderInit]=\"col.cellRenderer\"\r\n [rowData]=\"row\"\r\n [colData]=\"col\"\r\n [cellValue]=\"getNestedValue(row, col?.field)\"\r\n (cellEvent)=\"onCellEvent($event)\"\r\n >\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!-- \uD83E\uDDFE Default text-based cell rendering -->\r\n <ng-template #defaultCell>\r\n <div\r\n #cellText\r\n class=\"text-ellipsis flex-grow-1\"\r\n [title]=\"getCellTitle(row, col)\"\r\n >\r\n <!-- Normal cell -->\r\n <ng-container\r\n *ngIf=\"\r\n col?.type !== 'image' &&\r\n col?.field != 'image' &&\r\n col?.field != 'invoice.invoice_image' &&\r\n !isTotalRow\r\n \"\r\n >\r\n <ng-container *ngIf=\"col.is_amount\">{{\r\n currencySymbol\r\n }}</ng-container>\r\n {{getCellTitle(row, col)}}\r\n </ng-container>\r\n\r\n <!-- Total row -->\r\n <ng-container *ngIf=\"isTotalRow\">\r\n {{ getTotalAmount(col) }}\r\n </ng-container>\r\n\r\n <!-- Invoice Image -->\r\n <ng-container *ngIf=\"col.field == 'invoice.invoice_image'\">\r\n <div style=\"display: flex; align-items: center; zoom: 0.7\">\r\n <span\r\n title=\"{{ getNestedValue(row, col.field) || 'Attachment' }}\"\r\n (click)=\"downloadAttchment(getNestedValue(row, col.field))\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/document-icons/' +\r\n getExtention(getNestedValue(row, col.field)) +\r\n '.svg'\r\n \"\r\n ></span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Image cell -->\r\n <ng-container *ngIf=\"col?.type == 'image' && !isTotalRow\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n defaultImagePlaceholder;\r\n context: { row: row, col: col }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n <span\r\n *ngIf=\"\r\n (!col?.cellRenderer && showCellDetailsBox &&\r\n getNestedValue(row, col.field)?.length > 50 && col?.type !== 'image') ||\r\n (isNestedValueArray(row, col.field) &&\r\n getNestedValue(row, col.field)?.length > 1)\r\n \"\r\n class=\"toggle-icon data-grid-svg-icon ms-2 cursor-pointer\"\r\n [inlineSVG]=\"\r\n isExpanded(row, col)\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n (click)=\"\r\n $event.stopPropagation();\r\n toggleExpandOfLongCellText(row, col, columns, true)\r\n \"\r\n (dblclick)=\"$event.preventDefault(); $event.stopPropagation()\"\r\n ></span>\r\n </ng-template>\r\n <!-- Expand / Collapse icon -->\r\n </div>\r\n\r\n <!-- Expanded text -->\r\n <div\r\n class=\"position-absolute w-100 expanded-box\"\r\n *ngIf=\"isExpanded(row, col)\"\r\n [style.zIndex]=\"getZIndex(row, col)\"\r\n style=\"top: 100%; left: 0\"\r\n [attr.id]=\"(row.id || row._id) + '-' + (col.id || col._id)\"\r\n [class.invisible]=\"!showDetailsBox\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n fullTextTemplate;\r\n context: {\r\n row: row,\r\n col: col,\r\n isArray: isNestedValueArray(row, col.field)\r\n }\r\n \"\r\n ></ng-container>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Headers Action List On clicking three dots -->\r\n\r\n<ng-template\r\n #columnMenu\r\n let-col=\"col\"\r\n let-isNestedTable=\"isNestedTable\"\r\n let-columns=\"columns\"\r\n let-section=\"section\"\r\n let-columnIndex=\"columnIndex\"\r\n let-childColIndex=\"childColIndex\"\r\n>\r\n <div\r\n class=\"column-menu three-dots-col-menu\"\r\n [class.visually-hidden]=\"isMenueHidden\"\r\n *ngIf=\"activeCol && !isThreeDotsFilterOpen\"\r\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\r\n (click)=\"$event.stopPropagation()\"\r\n [style.color]=\"headerTextColor\"\r\n >\r\n <!-- Sort Ascending -->\r\n <div class=\"border-below pb-2\" [class.disable-sorting]=\"!col.is_sortable\">\r\n <span class=\"muted-text fs-7\" style=\"margin-left: 12px\">Sort</span>\r\n <div\r\n *ngIf=\"\r\n columnThreedotsMunuConfig?.showAscending &&\r\n (sortingConfig?.field != col.field ||\r\n sortingConfig?.order_by == 'desc')\r\n \"\r\n class=\"column-menu-item\"\r\n (click)=\"sortAsc(activeCol)\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-up.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Sort Ascending\r\n </div>\r\n\r\n <!-- Sort Descending -->\r\n <div\r\n *ngIf=\"\r\n columnThreedotsMunuConfig?.showDescending &&\r\n (sortingConfig?.field != col.field ||\r\n sortingConfig?.order_by == 'asc')\r\n \"\r\n class=\"column-menu-item\"\r\n (click)=\"sortDesc(activeCol)\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-down.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Sort Descending\r\n </div>\r\n\r\n <div\r\n *ngIf=\"\r\n sortingConfig?.field === col.field &&\r\n (sortingConfig?.order_by === 'asc' ||\r\n sortingConfig?.order_by === 'desc')\r\n \"\r\n class=\"column-menu-item\"\r\n (click)=\"resetSort(activeCol)\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrow-counterclockwise.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Reset Sort\r\n </div>\r\n </div>\r\n <div class=\"py-2 border-below three-dots-filter\" [class.disable-sorting]=\"col?.type == 'image' || !col.is_search_able\">\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showFilter\"\r\n class=\"column-menu-item three-dots-filter\"\r\n (click)=\"openFilteronThreeDotsClick(col)\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Filter\r\n </div>\r\n </div>\r\n\r\n <div class=\"py-2 border-below\">\r\n <span class=\"muted-text fs-7\" style=\"margin-left: 12px\">Pin</span>\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showPinleft && col?.pinned !== 'left'\"\r\n class=\"column-menu-item\"\r\n (click)=\"\r\n $event.stopPropagation();\r\n updateColumnPinInSourceByField(\r\n activeCol,\r\n 'left',\r\n isNestedTable,\r\n columns\r\n )\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pin-left.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span\r\n >Pin Left\r\n </div>\r\n\r\n <div\r\n *ngIf=\"\r\n columnThreedotsMunuConfig?.showPinright && col?.pinned !== 'right'\r\n \"\r\n class=\"column-menu-item\"\r\n (click)=\"\r\n $event.stopPropagation();\r\n updateColumnPinInSourceByField(\r\n activeCol,\r\n 'right',\r\n isNestedTable,\r\n columns\r\n )\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pin-right.svg'\"\r\n class=\"data-grid-svg-icon data-grid-svg-icon me-2\"\r\n ></span\r\n >Pin Right\r\n </div>\r\n\r\n <div\r\n *ngIf=\"col?.pinned\"\r\n class=\"column-menu-item\"\r\n (click)=\"\r\n $event.stopPropagation();\r\n updateColumnPinInSourceByField(\r\n activeCol,\r\n null,\r\n isNestedTable,\r\n columns\r\n )\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/layout-three-columns.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span\r\n >Unpin\r\n </div>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showAutosizeThisColumn\"\r\n class=\"column-menu-item\"\r\n (click)=\"autosizeColumn(activeCol)\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrows-expand-vertical.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n Autosize This Column\r\n </div>\r\n\r\n <!-- Autosize All Columns -->\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showAutosizeAllColumns\"\r\n class=\"column-menu-item\"\r\n (click)=\"autosizeAllColumns()\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrows-angle-expand.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span\r\n >Autosize All Columns\r\n </div>\r\n\r\n <!-- Group By -->\r\n <div\r\n *ngIf=\"showRowsGrouping\"\r\n class=\"column-menu-item\"\r\n (click)=\"groupBy(activeCol)\"\r\n [class.disable-sorting]=\"!col.is_groupable\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/diagram-3.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Group by {{ col.header }}\r\n </div>\r\n\r\n <!-- Choose Columns -->\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showChoseColumns\"\r\n class=\"column-menu-item\"\r\n (click)=\"chooseColumns()\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/ui-checks-grid.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Choose Columns\r\n </div>\r\n\r\n <!-- Reset Columns -->\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showResetColumns\"\r\n class=\"column-menu-item\"\r\n (click)=\"resetColumns()\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrow-counterclockwise.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span\r\n >Reset Columns\r\n </div>\r\n </div>\r\n <div\r\n @slideToggle\r\n *ngIf=\"isThreeDotsFilterOpen && col?.is_search_able\"\r\n class=\"three-dots-col-menu position-relative\"\r\n [style.right.px]=\"getDynamicRight(col, section, columnIndex, childColIndex)\"\r\n [class.visually-hidden]=\"isMenueHidden\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"filterMenu; context: { col: col }\"\r\n ></ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Filter Menue -->\r\n<ng-template #filterMenu let-col=\"col\">\r\n <div\r\n class=\"filter-menu-container filter-menu\"\r\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\r\n >\r\n <!-- Dropdown Type -->\r\n <ng-container *ngIf=\"col?.type === 'dropdown'|| col?.type == 'array'; else textFilter\">\r\n <div class=\"filter-dropdown-section p-1\">\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search...\"\r\n type=\"search\"\r\n [(ngModel)]=\"addFilterColumnInput\"\r\n />\r\n\r\n <div class=\"form-check mb-1 mt-2 ms-1 select-all-filter\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [checked]=\"isAllSideFilterOptionsSelected(col)\"\r\n (change)=\"toggleSelectAllSideFilters(col, $event)\"\r\n id=\"selectAll_{{ col.field }}\"\r\n />\r\n <label class=\"form-check-label\" for=\"selectAll_{{ col.field }}\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- <div class=\"dropdown-options ps-1\">\r\n <div\r\n class=\"form-check mb-1\"\r\n *ngFor=\"\r\n let option of selectedColumnForFilter?.column_dropdown_value\r\n | filter : addFilterColumnInput : 'value';\r\n trackBy: trackById;\r\n let i = index\r\n \"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"i\"\r\n [checked]=\"\r\n currentFilterSelectedIds.has(option?.id ?? option?._id ?? option)\r\n \"\r\n (change)=\"toggleSelectionInFilter(option)\"\r\n />\r\n <label class=\"form-check-label fw-semibold\" [for]=\"i\">\r\n {{ option?.value ?? option?.name ?? option }}\r\n </label>\r\n </div>\r\n </div> -->\r\n <cdk-virtual-scroll-viewport\r\n itemSize=\"32\"\r\n class=\"filter-viewport\"\r\n style=\"height: 120px\"\r\n >\r\n <div\r\n class=\"form-check mb-1 ms-1\"\r\n *cdkVirtualFor=\"\r\n let option of selectedColumnForFilter?.column_dropdown_value\r\n | filter : addFilterColumnInput : 'value';\r\n trackBy: trackById\r\n \"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"option?.id ?? option?._id ?? option\"\r\n [checked]=\"\r\n currentFilterSelectedIds.has(option?.id ?? option?._id ?? option)\r\n \"\r\n (change)=\"toggleSelectionInFilter(option)\"\r\n />\r\n\r\n <label\r\n class=\"form-check-label fw-semibold\"\r\n [for]=\"option?.id ?? option?._id ?? option\"\r\n >\r\n {{ ((option?.value ?? option?.name ?? option) | titlecase ) }}\r\n </label>\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Text Filter Section -->\r\n <ng-template #textFilter>\r\n <div class=\"filter-text-section\">\r\n <div class=\"form-group mb-2\">\r\n <select\r\n class=\"form-select form-select-sm custom-select\"\r\n [(ngModel)]=\"firstCondition\"\r\n >\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n\r\n <input\r\n [type]=\"col?.type == 'string' ? 'text' : col?.type\"\r\n class=\"form-control form-control-sm mb-3\"\r\n placeholder=\"Value\"\r\n [(ngModel)]=\"firstValue\"\r\n #filterMenueTextchInput\r\n (keydown.enter)=\"applyDropdownFilter()\"\r\n />\r\n\r\n <div class=\"form-group mb-3 d-flex flex-row\">\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"condition\"\r\n value=\"and\"\r\n id=\"and_{{ col.field }}\"\r\n (change)=\"cdr.detectChanges()\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"and_{{ col.field }}\"\r\n >AND</label\r\n >\r\n </div>\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1 gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"condition\"\r\n value=\"or\"\r\n id=\"or_{{ col.field }}\"\r\n (change)=\"cdr.detectChanges()\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"or_{{ col.field }}\"\r\n >OR</label\r\n >\r\n </div>\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1 gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"condition\"\r\n value=\"none\"\r\n id=\"none_{{ col.field }}\"\r\n (change)=\"cdr.detectChanges()\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"none_{{ col.field }}\"\r\n >None</label\r\n >\r\n </div>\r\n </div>\r\n <div @slideToggle *ngIf=\"firstValue && condition != 'none'\">\r\n <div class=\"form-group mb-2\">\r\n <select\r\n class=\"form-select form-select-sm custom-select\"\r\n [(ngModel)]=\"secondCondition\"\r\n >\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n\r\n <input\r\n [type]=\"col?.type == 'string' ? 'text' : col?.type\"\r\n class=\"form-control form-control-sm mb-3\"\r\n placeholder=\"Second Value\"\r\n [(ngModel)]=\"secondValue\"\r\n />\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Actions -->\r\n <div class=\"d-flex gap-2 mt-2\">\r\n <div\r\n class=\"btn btn-sm btn-primary d-flex justify-content-center align-items-center w-100\"\r\n style=\"height: 30px\"\r\n (click)=\"applyDropdownFilter()\"\r\n >\r\n Apply\r\n </div>\r\n <div\r\n class=\"btn btn-sm btn-secondary d-flex justify-content-center align-items-center w-100\"\r\n style=\"height: 30px\"\r\n (click)=\"resetSideFilter(col)\"\r\n >\r\n Reset\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Side Menue -->\r\n\r\n<!-- Column Pannel / Pivot Mode / Searching -->\r\n\r\n<ng-template #columnPannel>\r\n <div class=\"column-panel-header\">\r\n <!-- Pivot Toggle -->\r\n <div\r\n class=\"form-check form-switch d-flex align-items-center mb-2 pivot-mode px-5 ms-2 d-none\"\r\n >\r\n <input\r\n class=\"form-check-input me-2\"\r\n type=\"checkbox\"\r\n id=\"pivotToggle\"\r\n [(ngModel)]=\"pivotMode\"\r\n />\r\n <label class=\"form-check-label\" for=\"pivotToggle\">Pivot Mode</label>\r\n </div>\r\n\r\n <!-- Select All & Search -->\r\n <div class=\"d-flex align-items-center mb-2 px-3 mt-3\">\r\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n accordionState === 'all'\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : accordionState === 'some'\r\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n (click)=\"toggleAllAccordions()\"\r\n ></span>\r\n </span>\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input me-2\"\r\n [checked]=\"allColumnsSelected()\"\r\n (change)=\"toggleAllColumnsVisibility()\"\r\n />\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search columns...\"\r\n [(ngModel)]=\"columnSearch\"\r\n />\r\n </div>\r\n\r\n <!-- Separator -->\r\n <hr class=\"my-2\" />\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Right Columns Menue -->\r\n\r\n<!-- Column Panel Item Template -->\r\n<ng-template #columnPanelItem let-col=\"col\">\r\n <!-- Group Column -->\r\n <ng-container *ngIf=\"col.children?.length\">\r\n <div class=\"column-group d-flex align-items-center mb-2\">\r\n <span class=\"filter-icon-wrapper me-2\">\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n [class.rotate]=\"col.expanded\"\r\n (click)=\"col.expanded = !col.expanded\"\r\n ></span>\r\n </span>\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input me-2\"\r\n [id]=\"'group_' + col.header\"\r\n [checked]=\"isColumnVisible(col)\"\r\n (change)=\"toggleGroupVisibility(col)\"\r\n />\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center me-2\"\r\n ></span>\r\n <label\r\n class=\"d-flex align-items-center mb-0 w-100\"\r\n [for]=\"'group_' + col.header\"\r\n style=\"cursor: pointer\"\r\n >\r\n <span class=\"text-truncate\">{{ col.header }}</span>\r\n </label>\r\n </div>\r\n <div *ngIf=\"col.expanded\" class=\"ps-4\">\r\n <ng-container *ngFor=\"let child of col.children; trackBy: trackByField\">\r\n <ng-container\r\n *ngTemplateOutlet=\"columnPanelItem; context: { col: child }\"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Leaf Column -->\r\n <ng-container *ngIf=\"!col.children?.length\">\r\n <div class=\"d-flex align-items-center mb-2\">\r\n <span class=\"me-2\" style=\"width: 1.5rem\"></span>\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input me-2\"\r\n [(ngModel)]=\"col.is_visible\"\r\n [id]=\"'col_' + col.field\"\r\n (change)=\"onSideMenuColumnsVisibilityChange()\"\r\n />\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center me-2\"\r\n ></span>\r\n <label\r\n class=\"d-flex align-items-center mb-0 w-100\"\r\n [for]=\"'col_' + col.field\"\r\n style=\"cursor: pointer\"\r\n >\r\n <span class=\"text-truncate\">{{ col.header }}</span>\r\n </label>\r\n </div>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Columns Side Filter -->\r\n<ng-template #sideFilters>\r\n <div class=\"py-3 px-2 pe-3 h-100\">\r\n <div class=\"d-flex align-items-center mb-2\">\r\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n filterAccordionState === 'all'\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : filterAccordionState === 'some'\r\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n (click)=\"toggleAllFilterAccordions()\"\r\n ></span>\r\n </span>\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search...\"\r\n [(ngModel)]=\"columnSearch\"\r\n />\r\n </div>\r\n <div\r\n class=\"overflow-auto side-filter-columns-wrapper\"\r\n style=\"height: calc(100% - 70px); scrollbar-width: thin\"\r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let col of columns | filter : columnSearch : 'header';\r\n trackBy: trackByField\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"filterPannelItem; context: { col: col }\"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #filterPannelItem let-col=\"col\">\r\n <!-- Group Column -->\r\n <ng-container *ngIf=\"col.children?.length\">\r\n <div\r\n class=\"column-group d-flex align-items-center mb-2\"\r\n *ngIf=\"col?.type !== 'image'\"\r\n >\r\n <!-- Chevron toggle -->\r\n <span class=\"filter-icon-wrapper me-2\">\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n [class.rotate]=\"col.expandedFilter\"\r\n (click)=\"col.expandedFilter = !col.expandedFilter\"\r\n ></span>\r\n </span>\r\n\r\n <!-- Group label toggle -->\r\n <label\r\n class=\"d-flex align-items-center mb-0 w-100\"\r\n style=\"cursor: pointer\"\r\n (click)=\"col.expandedFilter = !col.expandedFilter\"\r\n >\r\n <span class=\"fw-bold text-truncate\"\r\n >{{ col.header }}\r\n <span\r\n class=\"text-primary ms-1\"\r\n *ngIf=\"col?.query?._ids?.length || col?.query?._first_value\"\r\n >*</span\r\n >\r\n </span>\r\n </label>\r\n </div>\r\n\r\n <!-- Children columns -->\r\n <div *ngIf=\"col.expandedFilter\" class=\"ps-4\">\r\n <ng-container *ngFor=\"let child of col.children; trackBy: trackByField\">\r\n <ng-container\r\n *ngTemplateOutlet=\"filterPannelItem; context: { col: child }\"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Leaf Column -->\r\n <ng-container *ngIf=\"!col.children?.length\">\r\n <div class=\"d-flex align-items-center mb-2\" *ngIf=\"col?.type !== 'image'\">\r\n <span\r\n class=\"me-2 filter-icon-wrapper me-2\"\r\n (click)=\"col.expandedFilter = !col.expandedFilter\"\r\n >\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n [class.rotate]=\"col.expandedFilter\"\r\n ></span>\r\n </span>\r\n\r\n <label\r\n class=\"d-flex align-items-center mb-0 w-100\"\r\n style=\"cursor: pointer\"\r\n (click)=\"col.expandedFilter = !col.expandedFilter\"\r\n >\r\n <span class=\"text-truncate fw-bold\">{{ col.header }}</span>\r\n </label>\r\n </div>\r\n\r\n <!-- Show filter when expanded -->\r\n <div *ngIf=\"col.expandedFilter\" class=\"ps-4 pe-3\">\r\n <ng-container\r\n *ngTemplateOutlet=\"sideNestedFilter; context: { col: col }\"\r\n ></ng-container>\r\n </div>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Side Nested Filters -->\r\n<ng-template #sideNestedFilter let-col=\"col\">\r\n <div class=\"\">\r\n <!-- Dropdown Type -->\r\n <ng-container *ngIf=\"col?.type === 'dropdown' || col?.type == 'array'; else textFilter\">\r\n <div class=\"p-1\">\r\n <!-- Search -->\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm mb-2\"\r\n placeholder=\"Search...\"\r\n [(ngModel)]=\"sideNestedFilterSearch\"\r\n />\r\n\r\n <!-- Select All -->\r\n <div class=\"form-check mb-1 ms-1 select-all-filter\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [checked]=\"\r\n col.query?._ids?.length == col?.column_dropdown_value?.length\r\n \"\r\n (change)=\"toggleSelectAllSideFilters(col, $event)\"\r\n id=\"selectAll_{{ col.field }}\"\r\n />\r\n <label class=\"form-check-label\" for=\"selectAll_{{ col.field }}\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- Options -->\r\n <!-- <div class=\"dropdown-options\">\r\n <div\r\n class=\"form-check mb-1 ms-1\"\r\n *ngFor=\"\r\n let option of col?.column_dropdown_value\r\n | filter : sideNestedFilterSearch : 'value'\r\n \"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [value]=\"option\"\r\n [checked]=\"\r\n col.query?._ids?.includes(option?._id || option?.id || option)\r\n \"\r\n (change)=\"onOptionToggle(col, option)\"\r\n id=\"option_{{ col.field }}_{{\r\n option?.id || option?._id || option\r\n }}\"\r\n />\r\n <label\r\n class=\"form-check-label\"\r\n [for]=\"\r\n 'option_' +\r\n col.field +\r\n '_' +\r\n (option?.id || option?._id || option)\r\n \"\r\n >\r\n {{ option.value || option }}\r\n </label>\r\n </div>\r\n </div> -->\r\n <cdk-virtual-scroll-viewport\r\n itemSize=\"32\"\r\n class=\"dropdown-viewport\"\r\n style=\"height: 120px\"\r\n >\r\n <div\r\n class=\"form-check mb-1 ms-1\"\r\n *cdkVirtualFor=\"\r\n let option of col?.column_dropdown_value\r\n | filter : sideNestedFilterSearch : 'value'\r\n \"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [value]=\"option\"\r\n [checked]=\"\r\n col.query?._ids?.includes(option?._id || option?.id || option)\r\n \"\r\n (change)=\"onOptionToggle(col, option)\"\r\n id=\"option_{{ col.field }}_{{\r\n option?.id || option?._id || option\r\n }}\"\r\n />\r\n\r\n <label\r\n class=\"form-check-label\"\r\n [for]=\"\r\n 'option_' +\r\n col.field +\r\n '_' +\r\n (option?.id || option?._id || option)\r\n \"\r\n >\r\n {{( (option.value || option) | titlecase ) }}\r\n </label>\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n\r\n\r\n <!-- Actions -->\r\n <!-- <div class=\"d-flex gap-2 mt-2\">\r\n <div\r\n class=\"btn btn-sm btn-primary d-flex justify-content-center align-items-center\"\r\n style=\"height: 22px;\"\r\n (click)=\"applySideFilter(col)\"\r\n >\r\n Apply\r\n </div>\r\n <div\r\n class=\"btn btn-sm btn-secondary d-flex justify-content-center align-items-center\" \r\n style=\"height: 22px;\"\r\n (click)=\"resetSideFilter(col)\"\r\n >\r\n Reset\r\n </div>\r\n </div> -->\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Text Filter Section -->\r\n <ng-template #textFilter>\r\n <div class=\"filter-text-section\">\r\n <div class=\"form-group mb-2\">\r\n <select\r\n class=\"form-select form-select-sm\"\r\n [(ngModel)]=\"col.query.first_condition\"\r\n >\r\n <ng-container *ngIf=\"col?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"col?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"col?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n\r\n <input\r\n [type]=\"col?.type == 'date' ? 'date' : 'text'\"\r\n class=\"form-control form-control-sm mb-3\"\r\n placeholder=\"Value\"\r\n [(ngModel)]=\"col!.query!.first_value\"\r\n />\r\n\r\n <div\r\n class=\"form-group mb-3 d-flex flex-row muted\"\r\n style=\"font-size: 14px\"\r\n >\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"col!.query.condition\"\r\n value=\"and\"\r\n id=\"and_{{ col.field }}\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"and_{{ col.field }}\"\r\n >AND</label\r\n >\r\n </div>\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"col!.query.condition\"\r\n value=\"or\"\r\n id=\"or_{{ col.field }}\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"or_{{ col.field }}\"\r\n >OR</label\r\n >\r\n </div>\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"col!.query.condition\"\r\n value=\"none\"\r\n id=\"none_{{ col.field }}\"\r\n />\r\n <label\r\n class=\"nnonem-check-label mb-0 mt-1\"\r\n for=\"none_{{ col.field }}\"\r\n >None</label\r\n >\r\n </div>\r\n </div>\r\n <ng-container\r\n *ngIf=\"col?.query?.first_value && col?.query?.condition !== 'none'\"\r\n >\r\n <div class=\"form-group mb-2\">\r\n <select\r\n class=\"form-select form-select-sm\"\r\n [(ngModel)]=\"col!.query.second_condition\"\r\n >\r\n <ng-container *ngIf=\"col?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"col?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"col?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n\r\n <input\r\n [type]=\"col?.type == 'date' ? 'date' : 'text'\"\r\n class=\"form-control form-control-sm mb-3\"\r\n placeholder=\"Second Value\"\r\n [(ngModel)]=\"col!.query.second_value\"\r\n />\r\n </ng-container>\r\n <!-- <div class=\"d-flex gap-2\">\r\n <div class=\"btn btn-sm btn-primary d-flex justify-content-center align-items-center\" style=\"height: 22px;\" (click)=\"applyDropdownFilter()\">apply</div>\r\n <div class=\"btn btn-sm btn-secondary d-flex justify-content-center align-items-center\" style=\"height: 22px;\" (click)=\"applyDropdownFilter()\">reset</div>\r\n\r\n </div> -->\r\n </div>\r\n </ng-template>\r\n <div\r\n class=\"d-flex justify-content-center gap-2 border-top\"\r\n style=\"height: 38px\"\r\n >\r\n <button\r\n type=\"button\"\r\n style=\"max-height: 30px\"\r\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\r\n (click)=\"$event.stopPropagation(); removeSideFilter(col)\"\r\n >\r\n <span>Clear</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n style=\"max-height: 30px\"\r\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\r\n (click)=\"applySideFilter(col)\"\r\n [class.disabled]=\"(col?.query.condition !== 'none' && !col?.query?.second_value)\"\r\n [class.pe-none]=\"(col!?.query.condition !== 'none' && !col?.query?.second_value)\"\r\n >\r\n <span style=\"margin-top: -1px\">Apply</span>\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Centr Overlay for showing the chose columns -->\r\n\r\n<div *ngIf=\"showColumnPanel\" class=\"custom-modal-overlay\">\r\n <div\r\n class=\"custom-modal-content\"\r\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"modalColumnPannel\"></ng-container>\r\n </div>\r\n</div>\r\n\r\n<!-- The existing ng-template you provided -->\r\n<ng-template #modalColumnPannel>\r\n <div class=\"column-panel-header\">\r\n <div\r\n class=\"d-flex justify-content-between align-items-center px-2 ps-3 rounded-top-2 moda-header\"\r\n [style.height.px]=\"48\"\r\n >\r\n Choose Columns\r\n <span class=\"filter-icon-wrapper\" (click)=\"closeModalColumnPanel()\"\r\n ><span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/x.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span\r\n ></span>\r\n </div>\r\n <hr class=\"my-0\" />\r\n <div>\r\n <div class=\"d-flex align-items-center px-2 pe-3\" [style.height.px]=\"48\">\r\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n accordionState === 'all'\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : accordionState === 'some'\r\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n (click)=\"toggleAllAccordions()\"\r\n ></span>\r\n </span>\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input me-2\"\r\n [checked]=\"allColumnsSelected()\"\r\n (change)=\"toggleAllColumnsVisibility()\"\r\n />\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search columns...\"\r\n [(ngModel)]=\"choseColumnsSearch\"\r\n />\r\n </div>\r\n\r\n <hr class=\"mt-0 mb-1\" />\r\n <div class=\"px-2 overlay-scrollable\">\r\n <ng-container\r\n *ngFor=\"\r\n let col of columns | filter : choseColumnsSearch : 'header';\r\n trackBy: trackByField\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"columnPanelItem; context: { col: col }\"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #sideMenuRowGroups>\r\n <div class=\"d-flex flex-column h-100 d-none\">\r\n <div class=\"px-3 h-100\">\r\n <div class=\"d-flex gap-3 mb-4\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <span>Row Groups</span>\r\n </div>\r\n <div class=\"h-50\">\r\n <div\r\n class=\"px-3 py-2 border-dashed h-100 d-flex justify-content-center align-items-center\"\r\n style=\"font-size: 14px\"\r\n >\r\n Drag here to set row Groups\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <hr class=\"mt-4\" />\r\n\r\n <div class=\"px-3 h-100\">\r\n <div class=\"d-flex gap-3 mb-4\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <span>Values</span>\r\n </div>\r\n <div class=\"h-50 d-flex\">\r\n <div\r\n class=\"px-3 py-2 border-dashed h-100 d-flex justify-content-center align-items-center\"\r\n style=\"font-size: 14px\"\r\n >\r\n Drag here aggregate\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- *************************************************** -->\r\n<!-- *************************************************** -->\r\n<!-- *************************************************** -->\r\n<!-- Drag Preview Template -->\r\n<!-- *************************************************** -->\r\n<!-- *************************************************** -->\r\n<ng-template #dragPreview let-col>\r\n <div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ col.header }}</div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Drag Placeholder Template -->\r\n<ng-template\r\n #dragPlaceholder\r\n let-col\r\n let-i=\"index\"\r\n let-section=\"section\"\r\n let-draggingInGroupArea=\"draggingInGroupArea\"\r\n>\r\n <div *ngIf=\"!draggingInGroupArea\">\r\n <div\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: { $implicit: col, index: i, section: section }\r\n \"\r\n ></div>\r\n </div>\r\n <div *ngIf=\"draggingInGroupArea\">New Placeholder</div>\r\n</ng-template>\r\n\r\n<!-- Top Group Row Placeholder -->\r\n<ng-template #topGroupingRowPlaceholder let-col let-showChevron=\"showChevron\">\r\n <div class=\"d-flex gap-2\">\r\n <div\r\n class=\"d-flex gap-2 top-row-grouping-placeholder\"\r\n [style.backgroundColor]=\"topGroupedBadgesBackgroundColor\"\r\n >\r\n <span\r\n cdkDragHandle\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <span>{{ col.header }}</span>\r\n <span\r\n (click)=\"ungroupColumn(col)\"\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/x.svg'\"\r\n class=\"cursor-pointer data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n <div *ngIf=\"showChevron\" style=\"opacity: 0.6; font-size: 14px\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template\r\n #childHeaderPlaceholder\r\n let-col\r\n let-pinnedRight=\"pinnedRight\"\r\n let-i=\"index\"\r\n let-sections=\"sections\"\r\n>\r\n <div\r\n class=\"header-cell one-row-header-cells\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n [style.fontWeight]=\"headerFontWeight\"\r\n >\r\n <div class=\"d-flex justify-content-between h-100 align-items-center w-100\">\r\n <div\r\n class=\"d-flex justify-content-between align-items-center w-100\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div\r\n class=\"text-ellipsis h-100 d-flex align-items-center\"\r\n [title]=\"col.header\"\r\n [class.w-100]=\"pinnedRight\"\r\n >\r\n {{ col.header }}\r\n </div>\r\n\r\n <div\r\n class=\"position-relative d-flex\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div class=\"three-dots p-1\" style=\"cursor: pointer\">\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/three-dots-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n\r\n <div class=\"resize-handle\">\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div\r\n *ngIf=\"showFilterRow\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n class=\"header-cell filter-cell\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n style=\"grid-row: 3\"\r\n >\r\n <div\r\n class=\"header-cell filter-cell\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n >\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Filter\"\r\n [(ngModel)]=\"col.filterValue\"\r\n [readonly]=\"col?.type == 'dropdown' || col?.type == 'image' || col?.type == 'array'\"\r\n [class.disabled-search-input]=\"\r\n col?.type == 'dropdown' || col?.type == 'image' || col?.type == 'array'\r\n \"\r\n />\r\n <span\r\n class=\"filter-icon-wrapper\"\r\n (click)=\"activeFilterCell = col; activeCol = null\"\r\n ><span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span\r\n ></span>\r\n\r\n <div\r\n class=\"position-absolute\"\r\n *ngIf=\"activeFilterCell === col\"\r\n style=\"top: 100%; right: 0; z-index: 10; left: 0\"\r\n ></div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #tableLayout>\r\n <div\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"p-3 shadow actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\r\n style=\"width: 320px\"\r\n >\r\n <div class=\"d-flex align-items-center mb-3\">\r\n <button\r\n class=\"btn btn-link p-0\"\r\n style=\"margin-left: -10px\"\r\n (click)=\"toggleActions('setting')\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </button>\r\n <h6 class=\"mb-0 ms-2\" style=\"font-weight: 500\">Table Layout</h6>\r\n </div>\r\n <hr class=\"my-2\" />\r\n <div class=\"w-100 mb-3 d-flex\" role=\"group\">\r\n <input\r\n type=\"radio\"\r\n class=\"btn-check layout-button-check\"\r\n name=\"layoutSize\"\r\n id=\"small\"\r\n autocomplete=\"off\"\r\n (change)=\"changeTableLayout($event, 'small')\"\r\n [checked]=\"selectedTableLayout == 'small'\"\r\n />\r\n <label\r\n class=\"border d-flex flex-column align-items-center layout-button\"\r\n for=\"small\"\r\n [ngStyle]=\"{\r\n color: selectedTableLayout == 'small' ? '#000' : '#727272'\r\n }\"\r\n >\r\n <div class=\"preview-box border mb-1\" style=\"height: 8px\"></div>\r\n Small\r\n </label>\r\n\r\n <input\r\n type=\"radio\"\r\n class=\"btn-check layout-button-check\"\r\n name=\"layoutSize\"\r\n id=\"medium\"\r\n autocomplete=\"off\"\r\n [checked]=\"selectedTableLayout == 'medium'\"\r\n (change)=\"changeTableLayout($event, 'medium')\"\r\n />\r\n <label\r\n class=\"border mx-3 d-flex flex-column align-items-center layout-button\"\r\n for=\"medium\"\r\n [ngStyle]=\"{\r\n color: selectedTableLayout == 'medium' ? '#000' : '#727272'\r\n }\"\r\n >\r\n <div class=\"preview-box border mb-1\" style=\"height: 12px\"></div>\r\n Medium\r\n </label>\r\n\r\n <input\r\n type=\"radio\"\r\n class=\"btn-check layout-button-check\"\r\n name=\"layoutSize\"\r\n id=\"large\"\r\n autocomplete=\"off\"\r\n (change)=\"changeTableLayout($event, 'large')\"\r\n [checked]=\"selectedTableLayout == 'large'\"\r\n />\r\n <label\r\n class=\"border d-flex flex-column align-items-center layout-button\"\r\n for=\"large\"\r\n [ngStyle]=\"{\r\n color: selectedTableLayout == 'large' ? '#000' : '#727272'\r\n }\"\r\n >\r\n <div class=\"preview-box border mb-1\" style=\"height: 16px\"></div>\r\n Large\r\n </label>\r\n </div>\r\n\r\n <hr class=\"my-2\" />\r\n <div class=\"d-flex justify-content-between align-items-center mb-2\">\r\n <span>Show separators</span>\r\n <div class=\"form-check form-switch m-0\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n id=\"separators\"\r\n [(ngModel)]=\"showVerticalBorder\"\r\n (change)=\"onFontChange()\"\r\n />\r\n </div>\r\n </div>\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n <span>Row shading</span>\r\n <div class=\"form-check form-switch m-0\">\r\n <input\r\n class=\"form-check-input\"\r\n [(ngModel)]=\"rowShadingEnabled\"\r\n (change)=\"toggleRowShading()\"\r\n type=\"checkbox\"\r\n id=\"rowShading\"\r\n />\r\n </div>\r\n </div>\r\n <!-- <div class=\"d-flex justify-content-between align-items-center mb-2\">\r\n <span>Show Side Menu</span>\r\n <div class=\"form-check form-switch m-0\">\r\n <input\r\n class=\"form-check-input\"\r\n [(ngModel)]=\"showSideMenu\"\r\n type=\"checkbox\"\r\n id=\"rowShading\"\r\n />\r\n </div>\r\n </div>\r\n <div class=\"d-flex justify-content-between align-items-center mb-2\">\r\n <span>Show Filter Row</span>\r\n <div class=\"form-check form-switch m-0\">\r\n <input\r\n class=\"form-check-input\"\r\n [(ngModel)]=\"showFilterRow\"\r\n type=\"checkbox\"\r\n id=\"rowShading\"\r\n />\r\n </div>\r\n </div> -->\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #tablePreset>\r\n <div\r\n *ngIf=\"activeSubButton !== 'save-preset'\"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"p-3 shadow actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\r\n style=\"width: 280px\"\r\n >\r\n <!-- Header -->\r\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\r\n <div class=\"d-flex align-items-center\">\r\n <button\r\n class=\"btn btn-link p-0\"\r\n style=\"margin-left: -10px\"\r\n (click)=\"toggleActions('setting')\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\r\n class=\"data-grid-svg-icon\"\r\n ></span>\r\n </button>\r\n <h6 class=\"mb-0 ms-2\" style=\"font-weight: 500\">Table Presets</h6>\r\n </div>\r\n <!-- Save Preset Button with Dropdown -->\r\n <div>\r\n <a\r\n class=\"text-decoration-none text-primary\"\r\n type=\"button\"\r\n id=\"savePresetDropdown\"\r\n (click)=\"$event.stopPropagation(); toggleSubActions('save-preset')\"\r\n >\r\n {{ isTablePresetNotChanged ? \"Save preset\" : \"Update Preset\" }}\r\n </a>\r\n </div>\r\n </div>\r\n\r\n <!-- Search -->\r\n <div class=\"mb-3\">\r\n <div class=\"col-12 global-search\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\r\n class=\"data-grid-svg-icon mx-2 position-absolute icon\"\r\n ></span>\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search...\"\r\n [(ngModel)]=\"searchTextPresetTable\"\r\n type=\"search\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Preset List -->\r\n <ng-container\r\n *ngIf=\"\r\n tableView | filter : searchTextPresetTable : 'name' as filteredList\r\n \"\r\n >\r\n <!-- If filteredList exists and none is default -> show fallback -->\r\n <div\r\n class=\" pb-5 overflow-auto\"\r\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight - 250\"\r\n >\r\n <div\r\n class=\"cursor-pointer\"\r\n (click)=\"\r\n clearAllFilters();\r\n openIndex = null;\r\n temp_state.id = '';\r\n activeTopButton = '';\r\n curretaTablePresetForUpdate = null\r\n \"\r\n >\r\n <div class=\"fw-semibold\">Default View</div>\r\n </div>\r\n <div class=\"d-flex justify-content-between\">\r\n <small class=\"text-dark\">Created by system</small>\r\n <span\r\n *ngIf=\"!tableFilterViewId && !hasAnyDefaultView()\"\r\n class=\"badge bg-light text-primary ms-2\"\r\n >Default</span\r\n >\r\n <!-- <span\r\n *ngIf=\"!tableFilterViewId && !hasAnyDefaultView()\"\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\"\r\n class=\"me-2\"\r\n ></span> -->\r\n <div\r\n class=\"dropdown d-flex justify-content-end\"\r\n *ngIf=\"tableFilterViewId\"\r\n ></div>\r\n </div>\r\n\r\n <!-- The list: render each table from filteredList -->\r\n <div\r\n class=\"list-group list-group-flush\"\r\n *ngFor=\"\r\n let table of filteredList;\r\n let i = index;\r\n trackBy: trackByTable\r\n \"\r\n >\r\n <!-- Item -->\r\n <div\r\n (click)=\"\r\n $event.stopPropagation(); openIndex = null; activeTopButton = ''\r\n \"\r\n class=\"list-group-item px-0 d-flex justify-content-between align-items-center\"\r\n >\r\n <div (click)=\"selectFilter(table); openIndex = null\">\r\n <div class=\"fw-semibold\" style=\"cursor: pointer\">\r\n {{ table?.name }}\r\n <!-- {{table?.is_temp}} -->\r\n <span\r\n *ngIf=\"\r\n (table?.is_temp && !temp_state.id) ||\r\n temp_state.id == table.id\r\n \"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n <span\r\n *ngIf=\"table?.is_default\"\r\n class=\"badge bg-light text-primary ms-2\"\r\n >Default</span\r\n >\r\n </div>\r\n <small class=\"text-dark\" *ngIf=\"table?.config?.filterNames\" [title]=\"table?.config?.filterNames\">\r\n {{\r\n table?.config?.filterNames?.length > 25\r\n ? (table?.config?.filterNames | slice:0:25) + '...'\r\n : table?.config?.filterNames\r\n }}\r\n ({{ table?.config?.totalCount }})\r\n </small>\r\n <small class=\"text-dark\" *ngIf=\"!table?.config?.filterNames\">{{ table?.createdAt | date : \"MMM d, y\" }}</small>\r\n </div>\r\n\r\n <div class=\"d-flex align-items-center\">\r\n <span\r\n *ngIf=\"table?.is_default\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n\r\n <div class=\"dropdown\" *ngIf=\"!table?.is_default\">\r\n <div\r\n class=\"dropdown-wrapper\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <button\r\n type=\"button\"\r\n class=\"btn-icon muted-text\"\r\n (click)=\"toggleMenu(i, $event)\"\r\n aria-haspopup=\"true\"\r\n [attr.aria-expanded]=\"openIndex === i\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/horizontal-dots.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n </button>\r\n\r\n <!-- menu -->\r\n <ul\r\n *ngIf=\"openIndex === i\"\r\n class=\"custom-dropdown-menu position-fixed top-auto\"\r\n role=\"menu\"\r\n [style.right.px]=\"'unset'\"\r\n [style.left.px]=\"dataGridContainer.offsetWidth - 200\"\r\n style=\"top: unset; right: unset\"\r\n >\r\n <li role=\"none\">\r\n <button\r\n role=\"menuitem\"\r\n class=\"dropdown-item\"\r\n (click)=\"\r\n actionPreset(table, 'setPreset'); temp_state.id = ''\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/star.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n Set as default\r\n </button>\r\n </li>\r\n\r\n <li role=\"none\" *ngIf=\"!table.confirmDelete\">\r\n <button\r\n role=\"menuitem\"\r\n class=\"dropdown-item text-danger\"\r\n (click)=\"table.confirmDelete = true\"\r\n >\r\n <span\r\n style=\"margin-top: -4px\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/trash-red.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n Delete\r\n </button>\r\n </li>\r\n\r\n <li\r\n role=\"none\"\r\n *ngIf=\"table.confirmDelete\"\r\n class=\"confirm-block\"\r\n >\r\n <div class=\"px-3 py-2 text-center\">\r\n <div class=\"mb-2\">\r\n Are you sure you want to delete <br /><b\r\n >\u201C{{ table?.name }}\u201D</b\r\n >?\r\n </div>\r\n <div class=\"d-flex gap-2\">\r\n <button\r\n class=\"btn btn-sm btn-light me-2\"\r\n (click)=\"table.confirmDelete = false\"\r\n >\r\n Cancel\r\n </button>\r\n <button\r\n class=\"btn btn-sm btn-danger\"\r\n (click)=\"actionPreset(table, 'deletePreset')\"\r\n >\r\n Delete\r\n </button>\r\n </div>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Item End Here -->\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <div\r\n (click)=\"$event.stopPropagation()\"\r\n *ngIf=\"activeSubButton == 'save-preset'\"\r\n class=\"dropdown-menu p-3 badge mt-4 save-preset-dropdown mt-1\"\r\n aria-labelledby=\"savePresetDropdown\"\r\n style=\"min-width: 250px\"\r\n >\r\n <div class=\"fw-bold fs-14px mb-2\">\r\n {{ isTablePresetNotChanged ? \"Save preset\" : \"Update Preset\" }}\r\n </div>\r\n <div class=\"fs-14px mb-2\" style=\"line-height: 20px\">\r\n This will save the current table adjustments as a preset.\r\n </div>\r\n <!-- Input -->\r\n <div class=\"mb-2\">\r\n <label for=\"presetName\" class=\"form-label fs-12px fw-bold\"\r\n >Preset Name</label\r\n >\r\n <div class=\"col-12 global-search\">\r\n <input\r\n #presetNameCtrl=\"ngModel\"\r\n required\r\n [(ngModel)]=\"presetName\"\r\n [ngClass]=\"{\r\n 'is-invalid':\r\n presetNameCtrl.invalid &&\r\n (presetNameCtrl.dirty || presetNameCtrl.touched)\r\n }\"\r\n class=\"form-control form-control-sm ps-2\"\r\n placeholder=\"Enter preset name\"\r\n type=\"text\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Checkbox -->\r\n <div class=\"form-check mb-2\">\r\n <input\r\n class=\"form-check-input\"\r\n [(ngModel)]=\"presetFilter\"\r\n type=\"checkbox\"\r\n id=\"saveFilters\"\r\n />\r\n <label class=\"form-check-label mt-1\" for=\"saveFilters\">\r\n Save active filters\r\n </label>\r\n </div>\r\n\r\n <!-- Save Button -->\r\n <div class=\"d-flex justify-content-center gap-2\" style=\"height: 32px\">\r\n <button\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn border w-100 d-flex align-items-center justify-content-center btn-light\"\r\n (click)=\"$event.stopPropagation(); toggleActions('table-presets')\"\r\n style=\"margin-top: -2px\"\r\n >\r\n <span>Cancel</span>\r\n </button>\r\n <button\r\n [disabled]=\"closeDropdown.preset.loading\"\r\n (click)=\"savePreset(presetNameCtrl)\"\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center\"\r\n >\r\n <span style=\"margin-top: -2px\" *ngIf=\"isTablePresetNotChanged\">\r\n <ng-container *ngIf=\"!closeDropdown.preset.loading\"\r\n >Save</ng-container\r\n >\r\n <ng-container *ngIf=\"closeDropdown.preset.loading\"\r\n ><span class=\"spinner-border spinner-border-sm\"></span\r\n ></ng-container>\r\n </span>\r\n <span style=\"white-space: nowrap\" *ngIf=\"!isTablePresetNotChanged\"\r\n >Update Preset</span\r\n >\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #showHideColumns>\r\n <div\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"p-3 shadow actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\r\n style=\"width: 280px\"\r\n >\r\n <!-- Header -->\r\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\r\n <div class=\"d-flex align-items-center\">\r\n <button\r\n class=\"btn btn-link p-0\"\r\n style=\"margin-left: -10px\"\r\n (click)=\"toggleActions('setting')\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\r\n class=\"data-grid-svg-icon\"\r\n ></span>\r\n </button>\r\n <h6 class=\"mb-0 ms-2\" style=\"font-weight: 500\">Columns</h6>\r\n </div>\r\n <a\r\n (click)=\"resetColumns()\"\r\n href=\"javascript:void(0)\"\r\n class=\"text-primary text-decoration-none d-none\"\r\n >Reset</a\r\n >\r\n </div>\r\n\r\n <!-- Search -->\r\n <div class=\"mb-3\">\r\n <div class=\"col-12 global-search\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\r\n class=\"mx-2 position-absolute icon data-grid-svg-icon\"\r\n ></span>\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search column\"\r\n type=\"search\"\r\n [(ngModel)]=\"topShowHideColumns\"\r\n />\r\n </div>\r\n </div>\r\n <!-- Preset List -->\r\n <div\r\n class=\"list-group list-group-flush\"\r\n style=\"overflow: auto; scrollbar-width: thin\"\r\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight - 220\"\r\n >\r\n <div class=\"muted-text show-hide-table-label d-flex justify-content-between\" *ngIf=\"hasAnyVisibleColumn\">\r\n Show in table\r\n <div class=\"form-check\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n id=\"hide_all\"\r\n [checked]=\"allColumnsSelected()\"\r\n (change)=\"toggleAllColumnsVisibility()\"\r\n />\r\n <label class=\"form-check-label fw-semibold\" for=\"hide_all\">\r\n Show/Hide All \r\n </label>\r\n </div>\r\n </div>\r\n <!-- Item -->\r\n <ng-container\r\n *ngFor=\"\r\n let col of columns | filter : topShowHideColumns : 'header';\r\n trackBy: trackByField\r\n \"\r\n >\r\n <div\r\n *ngIf=\"col.is_visible\"\r\n class=\"list-group-item border-0 px-0 d-flex justify-content-between align-items-center\"\r\n >\r\n <div class=\"d-flex gap-1\">\r\n <div>\r\n <span\r\n *ngIf=\"!col?.pinned\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/grip-vertical.svg'\r\n \"\r\n class=\"cursor-grap data-grid-svg-icon\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n ></span>\r\n <span\r\n *ngIf=\"col?.pinned\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'\r\n \"\r\n class=\"cursor-grap data-grid-svg-icon\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n ></span>\r\n </div>\r\n <div class=\"fw-semibold\">\r\n {{ col.header }}\r\n </div>\r\n </div>\r\n <div\r\n *ngIf=\"!col?.query?.first_value && !col?.query?._ids?.length\"\r\n class=\"d-flex align-items-center cursor-pointer\"\r\n (click)=\"toggleColumnVisibility(col, false)\"\r\n [class.disabled]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\r\n [class.pe-none]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\r\n [class.opacity-50]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/eye.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </div>\r\n <div\r\n *ngIf=\"col?.query?.first_value || col?.query?._ids?.length\"\r\n class=\"d-flex align-items-center\"\r\n style=\"opacity: 0.5\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/eye.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Item End Here -->\r\n\r\n <div\r\n class=\"dropdown-divider\"\r\n *ngIf=\"hasAnyVisibleColumn && hasAnyInVisibleColumn\"\r\n ></div>\r\n\r\n <div\r\n class=\"muted-text show-hide-table-label d-flex justify-content-between\"\r\n *ngIf=\"hasAnyInVisibleColumn\"\r\n >\r\n Hide in table\r\n <div class=\"form-check\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n id=\"show_all\"\r\n [checked]=\"allColumnsSelected()\"\r\n (change)=\"toggleAllColumnsVisibility()\"\r\n />\r\n <label class=\"form-check-label fw-semibold\" for=\"show_all\">\r\n Show/Hide All \r\n </label>\r\n </div>\r\n </div>\r\n <div class=\"list-group list-group-flush\">\r\n <ng-container *ngFor=\"let col of columns; trackBy: trackByField\">\r\n <div\r\n *ngIf=\"!col.is_visible\"\r\n class=\"list-group-item border-0 px-0 d-flex justify-content-between align-items-center\"\r\n >\r\n <div class=\"d-flex gap-1\">\r\n <div>\r\n <span\r\n *ngIf=\"!col?.pinned\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/grip-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon cursor-grap\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n ></span>\r\n <span\r\n *ngIf=\"col?.pinned\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'\r\n \"\r\n class=\"data-grid-svg-icon cursor-grap\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n ></span>\r\n </div>\r\n <div class=\"fw-semibold\">\r\n {{ col.header }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"d-flex align-items-center cursor-pointer\"\r\n (click)=\"toggleColumnVisibility(col, true)\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/eye-cross.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Item End Here -->\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #filterColumns let-col=\"column\">\r\n <div\r\n @slideToggle\r\n *ngIf=\"!isFilterOpen && activeTopButton == 'filter-columns'\"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns\"\r\n style=\"width: 280px; right: unset; max-width: 230px\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n >\r\n <div class=\"mb-2 px-3\">\r\n <div class=\"col-12 global-search\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\r\n class=\"data-grid-svg-icon mx-2 position-absolute icon\"\r\n ></span>\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Filter by\"\r\n type=\"search\"\r\n [(ngModel)]=\"addFilterColumnInput\"\r\n />\r\n </div>\r\n </div>\r\n <div\r\n class=\"list-group list-group-flush\"\r\n style=\"max-height: calc(100vh - 500px); overflow: auto\"\r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let col of columns | filter : addFilterColumnInput : 'header';\r\n trackBy: trackByField\r\n \"\r\n >\r\n <div\r\n (click)=\"openFilter(col)\"\r\n *ngIf=\"\r\n col.is_visible &&\r\n !col?.query?.first_value &&\r\n !col?.query?._ids?.length && col?.type !== 'image' && col.is_search_able\r\n \"\r\n class=\"list-group-item border-0 px-0 d-flex justify-content-between align-items-center dropdown-item cursor-pointer\"\r\n >\r\n <div class=\"d-flex gap-1\">\r\n <div style=\"margin-top: -3px\"></div>\r\n <div class=\"fw-semibold\">\r\n {{ col.header }}\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- Dropdown -->\r\n <div\r\n @slideToggle\r\n *ngIf=\"isFilterOpen && selectedColumnForFilter?.type == 'dropdown' || selectedColumnForFilter?.type == 'array'\"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns pb-2\"\r\n style=\"width: 280px; right: unset; max-width: 230px\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n >\r\n <div class=\"px-3 my-2 border-below py-1 pb-2 mb-3 d-flex ps-1\">\r\n <span\r\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\r\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\r\n ></span\r\n ><b>{{ selectedColumnForFilter?.header }}</b>\r\n </div>\r\n <div class=\"mb-2 px-3\">\r\n <div\r\n class=\"col-12 global-search position-relative border rounded d-flex align-items-center flex-wrap px-2 filter-serach-inpt\"\r\n >\r\n <span\r\n *ngFor=\"let selected of selectedFilterOptions\"\r\n class=\"badge d-flex align-items-center gap-1 me-1 mb-1 top-row-filter-dropdown\"\r\n >\r\n {{ selected?.value ? selected.value : selected }}\r\n <span\r\n (click)=\"toggleSelectionInFilter(selected)\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/cross-primary.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n </span>\r\n <input\r\n class=\"form-control form-control-sm border-0 flex-grow-1\"\r\n style=\"padding: 0\"\r\n [placeholder]=\"selectedFilterOptions?.length ? '' : 'Filter by'\"\r\n type=\"search\"\r\n [(ngModel)]=\"searchTextForFilterDropDown\"\r\n (keydown.backspace)=\"handleBackspace($event)\"\r\n />\r\n </div>\r\n </div>\r\n <div\r\n class=\"list-group list-group-flush\"\r\n style=\"max-height: calc(100vh - 600px); overflow: auto\"\r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let col of selectedColumnForFilter.column_dropdown_value\r\n | filter : searchTextForFilterDropDown : 'value';\r\n let i = index\r\n \"\r\n >\r\n <div\r\n class=\"list-group-item border-0 px-2 d-flex justify-content-between align-items-center dropdown-item cursor-pointer\"\r\n >\r\n <div class=\"form-check\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"i\"\r\n [checked]=\"currentFilterSelectedIds.has(col.id || col._id || col)\"\r\n (change)=\"toggleSelectionInFilter(col)\"\r\n />\r\n <label class=\"form-check-label fw-semibold\" [for]=\"i\">\r\n {{ col?.value || col?.name || col }}\r\n </label>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <div\r\n class=\"d-flex justify-content-center gap-2 px-2 border-top\"\r\n style=\"height: 38px\"\r\n >\r\n <button\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\r\n (click)=\"$event.stopPropagation(); resetFilterChanges()\"\r\n >\r\n <span>Cancel</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\r\n (click)=\"applyDropdownFilter()\"\r\n >\r\n <span style=\"margin-top: -2px\">Save</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- For Text fields and number fields-->\r\n\r\n <div\r\n @slideToggle\r\n *ngIf=\"\r\n isFilterOpen &&\r\n (selectedColumnForFilter?.type == 'string' ||\r\n selectedColumnForFilter?.type == 'number' ||\r\n selectedColumnForFilter?.type == 'date')\r\n \"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns pb-2\"\r\n style=\"width: 210px; right: unset; max-width: 230px\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n >\r\n <div class=\"px-3 border-below py-1 pb-2 d-flex ps-1\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\r\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\r\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\r\n ></span\r\n ><b>{{ selectedColumnForFilter?.header }}</b>\r\n </div>\r\n <div class=\"col-12 position-relative p-2 text-filter\">\r\n <div class=\"mb-2\">\r\n <select\r\n class=\"form-select form-select-sm custom-select border\"\r\n [(ngModel)]=\"firstCondition\"\r\n >\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n <div class=\"mb-2\">\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Enter first value\"\r\n type=\"search\"\r\n [type]=\"\r\n selectedColumnForFilter?.type == 'string'\r\n ? 'text'\r\n : selectedColumnForFilter?.type\r\n \"\r\n [(ngModel)]=\"firstValue\"\r\n (keydown.enter)=\"applyDropdownFilter()\"\r\n />\r\n </div>\r\n <div>\r\n <div class=\"d-flex my-3 d-flex flex-row\" style=\"font-size: 14px\">\r\n <div\r\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"radio\"\r\n id=\"logicalAnd\"\r\n name=\"logicalOperator\"\r\n value=\"and\"\r\n [(ngModel)]=\"condition\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalAnd\"\r\n >AND</label\r\n >\r\n </div>\r\n\r\n <div\r\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"radio\"\r\n id=\"logicalOr\"\r\n name=\"logicalOperator\"\r\n value=\"or\"\r\n [(ngModel)]=\"condition\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalOr\">OR</label>\r\n </div>\r\n\r\n <div\r\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"radio\"\r\n id=\"logicalNone\"\r\n name=\"logicalOperator\"\r\n value=\"none\"\r\n [(ngModel)]=\"condition\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalNone\"\r\n >None</label\r\n >\r\n </div>\r\n </div>\r\n\r\n <ng-container *ngIf=\"condition !== 'none' && firstValue\">\r\n <div class=\"mb-2 mt-3\">\r\n <!-- Second condition select -->\r\n <select\r\n class=\"form-select form-select-sm border\"\r\n [(ngModel)]=\"secondCondition\"\r\n >\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n\r\n <div class=\"mb-2\">\r\n <!-- Second value input -->\r\n <input\r\n [type]=\"\r\n selectedColumnForFilter?.type == 'string'\r\n ? 'text'\r\n : selectedColumnForFilter?.type\r\n \"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Enter second value\"\r\n type=\"search\"\r\n [(ngModel)]=\"secondValue\"\r\n (keydown.enter)=\"applyDropdownFilter()\"\r\n />\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"d-flex justify-content-center gap-2 px-2 border-top\"\r\n style=\"height: 38px\"\r\n >\r\n <button\r\n [disabled]=\"!currentFilterSelectedIds?.size && !firstValue\"\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\r\n (click)=\"$event.stopPropagation(); resetTextFilterChanges()\"\r\n >\r\n <span>Cancel</span>\r\n </button>\r\n <button\r\n [disabled]=\"(currentFilterSelectedIds?.size === 0 && !firstValue) || (condition !== 'none' && !secondValue)\"\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\r\n (click)=\"applyDropdownFilter()\"\r\n >\r\n <span style=\"margin-top: -2px\">Apply</span>\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Edit dropdown here -->\r\n<ng-template let-col>\r\n <div class=\"drop-down-edit\"></div>\r\n</ng-template>\r\n\r\n<ng-template\r\n #fullTextTemplate\r\n let-row=\"row\"\r\n let-col=\"col\"\r\n let-isArray=\"isArray\"\r\n>\r\n <div\r\n class=\"full-text-box\"\r\n (dblclick)=\"$event.stopPropagation(); $event.preventDefault()\"\r\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\r\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight / 2\"\r\n >\r\n <ng-container *ngIf=\"!isEditing(row, col)\">\r\n <div\r\n *ngIf=\"!isArray\"\r\n class=\"full-text-content\"\r\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight / 2\"\r\n (dblclick)=\"\r\n $event.stopPropagation();\r\n $event.preventDefault();\r\n enableEdit(row, col, true)\r\n \"\r\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\r\n >\r\n {{\r\n getNestedValue(row, col.field)?.value ||\r\n getNestedValue(row, col.field)?.name ||\r\n getNestedValue(row, col.field)\r\n }}\r\n </div>\r\n <div *ngIf=\"isArray\">\r\n <ul>\r\n <ng-container\r\n *ngFor=\"let item of getNestedValue(row, col.field); let i = index\"\r\n >\r\n <li *ngIf=\"i !== 0\">\r\n <ng-container>\r\n {{\r\n item?.department_name ||\r\n item?.roleName ||\r\n item?.full_name ||\r\n \"-\"\r\n }}\r\n </ng-container>\r\n </li>\r\n </ng-container>\r\n </ul>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"isEditing(row, col)\">\r\n <textarea\r\n (dblclick)=\"\r\n $event.stopPropagation();\r\n $event.preventDefault();\r\n enableEdit(row, col, true)\r\n \"\r\n #textModel=\"ngModel\"\r\n rows=\"4\"\r\n #textAreadInput\r\n [(ngModel)]=\"row[col.field]\"\r\n name=\"{{ col.field }}\"\r\n required\r\n (blur)=\"disableEdit(row, col, textModel)\"\r\n (keydown.enter)=\"textAreadInput.blur()\"\r\n autofocus\r\n class=\"form-control\"\r\n [ngClass]=\"{\r\n 'is-invalid': textModel.invalid\r\n }\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n ></textarea>\r\n </ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #defaultImagePlaceholder let-row=\"row\" let-col=\"col\">\r\n <span\r\n class=\"px-2 d-flex w-100 cell-content image-placeholder\"\r\n [title]=\"row?.full_name || row?.name || 'N/A'\"\r\n >\r\n <ng-container\r\n *ngIf=\"\r\n row?.logo ||\r\n row?.assetImage ||\r\n row?.invoice?.invoice_image ||\r\n row?.invoice_image;\r\n else placeholder\r\n \"\r\n >\r\n <span\r\n (click)=\"fullscreenImage = row?.profile_pictures?.[4]?.path ||\r\n row?.logo ||\r\n row?.assetImage ||\r\n row?.invoice_image\"\r\n class=\"pic\"\r\n [style.width.px]=\"rowHeight - 10\"\r\n [style.height.px]=\"rowHeight - 10\"\r\n [class.assets-pic]=\"gridType == 'Assets'\"\r\n >\r\n <img\r\n [width]=\"rowHeight - 12\"\r\n [height]=\"rowHeight - 12\"\r\n [style.width.px]=\"rowHeight - 10\"\r\n [style.height.px]=\"rowHeight - 10\"\r\n [src]=\"\r\n row?.profile_pictures?.[4]?.path ||\r\n row?.logo ||\r\n row?.assetImage ||\r\n row?.invoice_image\r\n \"\r\n alt=\"icon\"\r\n class=\"option-icon\"\r\n loading=\"lazy\"\r\n />\r\n </span>\r\n </ng-container>\r\n <!-- <div\r\n class=\"fullscreen-overlay\"\r\n *ngIf=\"fullscreenImage\"\r\n (click)=\"fullscreenImage = null\"\r\n >\r\n <img [src]=\"fullscreenImage\" class=\"fullscreen-img\" />\r\n </div> -->\r\n\r\n <ng-template #placeholder>\r\n <span\r\n [ngClass]=\"getDynamicClass(row?.full_name || row?.name)\"\r\n class=\"pic d-flex align-items-center rounded-circle\"\r\n [style.width.px]=\"rowHeight - 12\"\r\n [style.height.px]=\"rowHeight - 12\"\r\n [style.fontSize.px]=\"rowHeight / 3\"\r\n [class.assets-pic]=\"gridType == 'Assets'\"\r\n >\r\n {{ getInitials(row?.full_name) }}\r\n </span>\r\n </ng-template>\r\n </span>\r\n</ng-template>\r\n\r\n<!-- Right Click Menue -->\r\n<div\r\n [class.invisible]=\"!positionedYet\"\r\n class=\"context-menu p-2\"\r\n *ngIf=\"actionHide && actions?.length\"\r\n [ngStyle]=\"{ 'top.px': yPos, 'left.px': xPos }\"\r\n [class.show]=\"isVisible\"\r\n appendTo=\"body\"\r\n>\r\n <ul>\r\n <li\r\n *ngFor=\"let action of actions\"\r\n class=\"rounded d-flex align-items-center\"\r\n (click)=\"onActionClick(action)\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/' + action + '.svg'\"\r\n class=\"data-grid-svg-icon right-click-menu-icons me-2\"\r\n ></span>\r\n <span class=\"text-capitalize fw-500\">{{ action }}</span>\r\n </li>\r\n </ul>\r\n</div>\r\n\r\n<!-- Details Toggle from bottom -->\r\n\r\n<ng-template #nestedTableTemplate let-row>\r\n <div\r\n class=\"nested-table table table-sm w-100 mb-0 center-nested-table w-100\"\r\n style=\"table-layout: fixed !important\"\r\n #nestedTableContainer\r\n >\r\n <thead\r\n #nestedHeader\r\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\r\n >\r\n <div\r\n cdkDropList\r\n [cdkDropListData]=\"row?.detail.columns\"\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"dropColumn($event, row)\"\r\n (cdkDropListSorted)=\"onNestedColSort($event, previewNestedCols)\"\r\n [style.height.px]=\"nestedTableHeaderRowHeight\"\r\n class=\"d-flex tr border-below\"\r\n >\r\n <div\r\n *ngFor=\"let col of row.detail.columns; let i = index\"\r\n [style.width.px]=\"col?.width || 250\"\r\n [style.minWidth.px]=\"col?.width || 250\"\r\n [style.maxWidth.px]=\"col?.width || 250\"\r\n class=\"px-4 th\"\r\n [attr.field]=\"col.field\"\r\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\r\n cdkDrag\r\n >\r\n <div\r\n class=\"d-flex h-100 justify-content-between position-relative align-items-center\"\r\n >\r\n <div class=\"text-ellipsis\" (click)=\"sortNestedCol(col, row)\">\r\n {{ col.header }}\r\n </div>\r\n <div class=\"d-flex gap-2\">\r\n <span\r\n *ngIf=\"currentSubSortColumn == col.field\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n (col?.order_by == 'desc'\r\n ? 'data-grid/icons/sort-desc.svg'\r\n : 'data-grid/icons/sort-asc.svg')\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center ms-2 start-50\"\r\n >\r\n </span>\r\n <!-- <div\r\n class=\"three-dots p-1\"\r\n (click)=\"openThreeDotsMenu($event, col)\"\r\n style=\"cursor: pointer\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/three-dots-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div> -->\r\n\r\n <!-- Only show menu if this column is active -->\r\n <div\r\n class=\"position-absolute\"\r\n *ngIf=\"activeCol === col\"\r\n style=\"top: -50%; z-index: 21; left: 0\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n columnMenu;\r\n context: {\r\n col: col,\r\n isNestedTable: true,\r\n columns: row?.detail.columns\r\n }\r\n \"\r\n ></ng-container>\r\n </div>\r\n <div\r\n class=\"resize-handle\"\r\n (click)=\"$event.stopPropagation()\"\r\n (mousedown)=\"\r\n $event.preventDefault();\r\n onResizeColumn($event, col);\r\n $event.stopPropagation()\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div>\r\n <ng-template cdkDragPreview>\r\n <div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ col.header }}</div>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </thead>\r\n <div\r\n [style.width.px]=\"nestedHeader.offsetWidth - 10\"\r\n [style.minWidth.px]=\"nestedHeader.offsetWidth - 10\"\r\n >\r\n <cdk-virtual-scroll-viewport\r\n [itemSize]=\"nestedTablerowHeight\"\r\n class=\"viewport\"\r\n [style.height.px]=\"\r\n (row?.detail?.result?.length < 5\r\n ? nestedTablerowHeight * row?.detail?.result?.length + 40\r\n : 300) + (hasHorizontalScroll ? -12 : 1)\r\n \"\r\n [style.width.px]=\"nestedHeader.offsetWidth - 10\"\r\n [style.minWidth.px]=\"nestedHeader.offsetWidth - 10\"\r\n >\r\n <div\r\n class=\"cursor-pointer border-below d-flex tr\"\r\n *cdkVirtualFor=\"let d of row?.detail?.result; trackBy: trackById\"\r\n [style.height.px]=\"nestedTablerowHeight\"\r\n [style.width.px]=\"nestedHeader?.offsetWidth\"\r\n [style.minWidth.px]=\"nestedHeader?.offsetWidth\"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n (contextmenu)=\"onRightClick($event, d)\"\r\n >\r\n <div\r\n class=\"px-4 py-0 td\"\r\n *ngFor=\"let col of previewNestedCols; let j = index\"\r\n [style.fontSize.px]=\"nestedTablerowFontsize\"\r\n [attr.field]=\"col.field\"\r\n [style.width.px]=\"col?.width || 250\"\r\n [style.minWidth.px]=\"col?.width || 250\"\r\n [style.maxWidth.px]=\"col?.width || 250\"\r\n >\r\n <div\r\n [style.height.px]=\"nestedTablerowHeight - 1\"\r\n [style.max-width.px]=\"col?.width\"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <!-- {{ d[col.field] || (col.is_amount ? 0 : \"-\") }} -->\r\n <div\r\n #cellText\r\n class=\"text-ellipsis flex-grow-1\"\r\n [title]=\"\r\n col?.type === 'date'\r\n ? (getNestedValue(d, col.field) | date : dateFormat)\r\n : getNestedValue(d, col.field) || '-'\r\n \"\r\n >\r\n <ng-container *ngIf=\"col?.type !== 'image'\">\r\n <ng-container *ngIf=\"col.is_amount\">{{\r\n currencySymbol\r\n }}</ng-container>\r\n {{\r\n !isNestedValueArray(d, col.field)\r\n ? col?.type === 'date'\r\n ? (isDate(getNestedValue(d, col.field))\r\n ? (getNestedValue(d, col.field) | date: dateFormat)\r\n : (getNestedValue(d, col.field)?.value ||\r\n getNestedValue(d, col.field)?.name ||\r\n getNestedValue(d, col.field) ||\r\n '-'))\r\n : (getNestedValue(d, col.field)?.value ||\r\n getNestedValue(d, col.field)?.name ||\r\n getNestedValue(d, col.field) ||\r\n (col.is_amount ? 0: '-'))\r\n : (getNestedValue(d, col.field)?.[0]?.department_name ||\r\n getNestedValue(d, col.field)?.[0]?.roleName || getNestedValue(d, col.field)?.[0]?.full_name ||\r\n '-')\r\n }}\r\n </ng-container>\r\n <ng-container *ngIf=\"false\">\r\n {{ getTotalAmount(col) }}\r\n </ng-container>\r\n <ng-container *ngIf=\"col?.type == 'image'\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n defaultImagePlaceholder;\r\n context: {\r\n row: d,\r\n col: col,\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #leftRightNestedPlaceholder let-row>\r\n <table\r\n class=\"nested-table table table-sm w-100 mb-0\"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n [style.height.px]=\"\r\n gridType == 'Assets'\r\n ? (nestedTableContainer?.nativeElement?.offsetHeight ?? 0) + 12\r\n : (taskManagementContainer?.nativeElement?.offsetHeight ?? 0)\r\n \"\r\n >\r\n <!-- <div class=\"thead\">\r\n <div\r\n class=\"tr d-flex border-below\"\r\n [style.height.px]=\"nestedTableHeaderRowHeight\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n >\r\n <div class=\"th\" *ngFor=\"let _ of [1, 2, 3, 4, 5]\"></div>\r\n </div>\r\n </div> -->\r\n <!-- <div class=\"tbody\">\r\n <div\r\n class=\"tr border-below\"\r\n [style.height.px]=\"nestedTablerowHeight\"\r\n *ngFor=\"let _ of row?.detail?.result\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n >\r\n <div class=\"td\" *ngFor=\"let __ of [1, 2, 3, 4, 5]\" class=\"py-0\">\r\n <span\r\n [style.height.px]=\"nestedTablerowHeight\"\r\n [style.max-width.px]=\"nestedTablerowHeight\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div> -->\r\n </table>\r\n</ng-template>\r\n\r\n<ng-template #taskManagementTemplate let-taskDetails=\"taskDetails\">\r\n <div\r\n class=\"p-4\"\r\n #taskManagementContainer\r\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\r\n [style.fontFaimly]=\"fontFaimly\"\r\n >\r\n <div class=\"d-flex justify-content-between\">\r\n <div class=\"col-4\">\r\n <div class=\"item-title\">Description</div>\r\n <!-- <div class=\"item-content firstDiv\">\r\n {{ taskDetails.description }}\r\n </div> -->\r\n <p\r\n [style.fontSize]=\"bodyTextFontsSize\"\r\n class=\"item-content firstDiv taskDescription pe-4\"\r\n [innerHTML]=\"getSafeComment(taskDetails?.editor_description)\"\r\n (click)=\"openFullImage($event)\"\r\n ></p>\r\n </div>\r\n <div class=\"col-4\">\r\n <div class=\"item-title\">Attachments</div>\r\n <h5 *ngIf=\"taskDetails?.attachments?.length == 0\">\r\n No Attachments found\r\n </h5>\r\n <div\r\n *ngIf=\"taskDetails?.attachments?.length\"\r\n class=\"item-content d-flex flex-wrap\"\r\n style=\"gap: 10px\"\r\n >\r\n <a\r\n *ngFor=\"let attachement of taskDetails?.attachments; let i = index\"\r\n class=\"symbol-label fs-2 fw-semibold text-success cursor-pointer\"\r\n >\r\n <span\r\n title=\"{{ taskDetails?.attachments_name[i] || 'Attachment' }}\"\r\n (click)=\"downloadAttchment(attachement)\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/document-icons/' +\r\n getExtention(attachement) +\r\n '.svg'\r\n \"\r\n >\r\n </span>\r\n </a>\r\n </div>\r\n </div>\r\n <div class=\"col-4\">\r\n <div class=\"item-title\">\r\n Comments ({{ taskDetails?.comments?.length }})\r\n </div>\r\n <h5 *ngIf=\"taskDetails?.comments?.length == 0\">No Comments found</h5>\r\n <div *ngIf=\"taskDetails?.comments?.length\" class=\"item-content\">\r\n <div class=\"comment\" *ngFor=\"let comment of taskDetails.comments\">\r\n <div class=\"d-flex align-items-center pe-3\">\r\n <img\r\n class=\"pic image-input-wrapper\"\r\n [style.width.px]=\"rowHeight - 12\"\r\n [style.height.px]=\"rowHeight - 12\"\r\n *ngIf=\"comment?.comment_by.logo\"\r\n src=\"{{ comment?.comment_by.logo }}\"\r\n alt=\"{{ comment.comment_by.full_name }}\"\r\n />\r\n <!-- <app-default-image-placeholder *ngIf=\"!comment?.comment_by.logo\" title=\"{{ comment.comment_by.full_name }}\" [name]=\"comment.comment_by.full_name\"></app-default-image-placeholder> -->\r\n <span\r\n *ngIf=\"!comment?.comment_by.logo\"\r\n [ngClass]=\"getDynamicClass(comment.comment_by.full_name)\"\r\n class=\"pic d-flex align-items-center rounded-circle\"\r\n [style.width.px]=\"rowHeight - 12\"\r\n [style.height.px]=\"rowHeight - 12\"\r\n [style.fontSize.px]=\"rowHeight / 3\"\r\n title=\"{{ comment.comment_by.full_name }}\"\r\n >\r\n {{ getInitials(comment.comment_by.full_name) }}\r\n </span>\r\n </div>\r\n <div>\r\n <div class=\"comment-author fs-14px\">\r\n {{ comment?.comment_by.full_name }}\r\n </div>\r\n <div\r\n class=\"comment-content forCommentImg\"\r\n [innerHTML]=\"getSafeComment(comment.comment)\"\r\n ></div>\r\n <div class=\"comment-timestamp\">\r\n {{ comment.comment_date | date }}\r\n </div>\r\n <div class=\"comment-timestamp\">\r\n Replies: ({{ comment.replies.length }})\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n", styles: ["@charset \"UTF-8\";@import\"bootstrap/dist/css/bootstrap.min.css\";.data-grid-table-wrapper{height:100%;width:100%;border:1px solid #d9d9db;border-radius:12px;position:relative}.data-grid-header{position:sticky;top:0}.data-grid-header{display:flex}.header-row{display:grid;width:100%}.header-cell{display:flex;align-items:center;position:relative;width:100%;padding:8px 0 8px 8px;font-weight:700;border-bottom:1px solid #d9d9db;white-space:nowrap;min-width:80px;font-weight:600}.header-cell .filter-applied-on-text{color:#5d9cff!important}.filter-cell{padding:4px!important;display:flex;align-items:center;gap:8px;width:100%}.filter-cell .filter-applied{background-color:#bddef9}.border-right{border-right:1px solid #d9d9db}.merged-grid{display:grid;grid-auto-rows:40px;border-bottom:1px solid #ccc}.span-two-rows{grid-row:span 2;display:flex;justify-content:space-between;align-items:center}.group-header{display:flex;justify-content:space-between;position:relative}.group-header-content{position:sticky;left:10px;overflow:hidden;text-overflow:ellipsis}.resize-handle{width:6px;cursor:e-resize;right:0;top:0;color:#00000026;margin-right:4px}.group-header .resize-handle{top:25%}.h-100{height:100%}.data-grid-body{position:relative;overflow-y:auto;overflow-x:hidden}.cell{padding:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:100%;display:flex;align-items:center}.data-grid-row{display:flex;width:100%;min-width:max-content;align-items:center;border-bottom:1px solid #d9d9db}.hovered-row{background-color:#ccc}.checkbox-row{border-bottom:#d9d9db}.w-100{width:100%}.data-grid-header-wrapper{display:flex;position:relative;overflow:hidden;-webkit-user-select:none;user-select:none}.data-grid-header{display:flex;position:relative;z-index:1}.left-pinned,.right-pinned{position:sticky;top:0}.right-pinned-header{position:absolute;right:0;border-left:1px solid #d9d9db;z-index:unset}.left-pinned{left:0}.right-pinned{right:0;border-left:1px solid #d9d9db}.center-scrollable{z-index:unset!important;overflow-x:auto;overflow-y:visible;white-space:nowrap;scrollbar-width:none;-ms-overflow-style:none}.center-scrollable::-webkit-scrollbar{display:none}.data-grid-body-wrapper{-webkit-user-select:none;user-select:none;display:flex}.center-scrollable-body{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}.center-scrollable-body::-webkit-scrollbar{display:none}.left-pinned-body,.right-pinned-body{position:sticky;top:0;z-index:unset;background:#fff;scrollbar-width:none;-ms-overflow-style:none}.left-pinned-body::-webkit-scrollbar,.right-pinned-body::-webkit-scrollbar{display:none}.left-pinned-body{left:0}.border-end{border-right:1px solid #d9d9db!important}.right-pinned-body{right:0;border-left:1px solid #d9d9db}.fake-scroll-bar{height:14px;overflow:scroll;margin-bottom:10px}.text-ellipsis{overflow:hidden;text-overflow:ellipsis}.select-all-checkbox-cell{width:50px;display:flex;justify-content:center;align-items:center;height:100%;border-right:1px solid #d9d9db}.select-all-checkbox-cell input{width:16px;height:14px}.border-below{border-bottom:1px solid #d9d9db!important}.three-dots{width:22px;height:22px;display:flex;justify-content:center;align-items:center;border-radius:3px;margin-right:8px;cursor:pointer}.three-dots:hover{background-color:#ccc!important}.filter-icon-wrapper{min-height:22px;max-height:22px;min-width:22px;max-width:22px;display:flex;justify-content:center;align-items:center;border-radius:3px;cursor:pointer;transition:background-color .3s ease}.filter-icon-wrapper:hover{background-color:#ccc}.column-menu,.filter-menu{box-shadow:0 0 16px #00000026;border-radius:4px}.column-menu{background:#fff;width:100%;width:240px;border:1px solid #ddd;box-shadow:0 0 16px #00000026;border:1px solid #d9d9db;padding:4px 0;font-size:14px;position:fixed}.column-menu-item{padding:8px 12px;cursor:pointer;display:flex;align-items:center;transition:background-color .2s ease}.column-menu-item:hover{background-color:#deebf7}.pin-parent{position:relative;width:100%!important}.column-submenu{position:absolute;top:0;left:100%;background:#fff;border:1px solid #ddd;width:130px;box-shadow:0 0 16px #00000026;border:1px solid #d9d9db;display:none;padding:4px 0;z-index:10;border-radius:4px}.pin-parent:hover .column-submenu{display:block}.filter-menu-container{position:fixed;width:210px;background:#fff;border:1px solid #ddd;border-radius:4px;padding:12px;box-shadow:0 0 16px #00000026;border:1px solid #d9d9db;z-index:1000;font-size:14px}.filter-menu-header{font-weight:600;margin-bottom:10px}.filter-dropdown-section{max-height:350px;overflow-y:auto}.dropdown-options{overflow-y:auto;scrollbar-width:thin;height:100%}.filter-text-section select,.filter-text-section input{width:100%}.filter-radio-inputs{width:14px!important;height:14px!important}.right-menu{border-left:1px solid #d9d9db;font-size:14px}.border-start{border-left:1px solid #d9d9db!important}.column-panel-item{font-size:.875rem;color:#333}.toggle-icon{cursor:pointer;transition:transform .2s ease}.toggle-icon.rotate{transform:rotate(90deg)}.grab-icon{cursor:grab;color:#6c757d}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cursor-pointer{cursor:pointer}.pivot-mode{height:48px}.chevron-wrapper{width:30px;height:20px;cursor:pointer;border-radius:3px;display:flex;justify-content:center;align-items:center;transition:background-color .3s ease;margin-right:8px}.chevron-wrapper:hover{background-color:#cac7c7}.chevron-wrapper i{font-size:14px}.column-panel-body{height:70%;overflow:auto;scrollbar-width:thin}.side-menue-text{transform:rotate(90deg);position:relative;font-weight:700;margin-top:40px}.columns-button{padding-top:20px;padding-bottom:35px;width:29px}.fake-scroll-content{height:12px}.fake-scrollbar{width:25px}.fake-scrollbar div{min-width:1px}.fake-horizintal-scrollbar div{min-height:1px}.side-filter-columns-wrapper{height:calc(100% - 25px)}.custom-modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;overflow:hidden;display:flex;justify-content:center;align-items:center;z-index:1050}.custom-modal-overlay .moda-header{background-color:#f8f8f8}.custom-modal-content{background-color:#fff;border-radius:8px;min-width:300px;max-width:400px;box-shadow:0 5px 20px #0000004d}.overlay-scrollable{height:250px;overflow:auto}.footer-row{border-top:1px solid #d9d9db;padding-left:32px}.fake-horizintal-scrollbar{position:relative;bottom:17px;overflow-x:auto;overflow-y:hidden;height:17px}.border-dashed{border:1px dashed #d9d9db}.cdk-drag-preview{box-sizing:border-box!important;border-radius:4px!important;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f!important;background-color:#f3f4f5!important;border:1px solid #d9d9db!important;z-index:9999!important}.data-grid-header-wrapper ::ng-deep .cdk-drag-placeholder{display:block!important;background:#fff!important;opacity:1!important}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)!important}.top-row-grouping-placeholder{display:flex;align-items:center;border-radius:12px;font-size:14px;padding-inline:6px;border:1px solid #d9d9db}.top-row-grouping-placeholder .bi-x{cursor:pointer;color:#7a7a7a}.top-row-grouping-placeholder .bi-x:hover{color:#111}.right-pinned-body-wrapper{position:absolute;right:0}.actions-dropdown{position:absolute;right:200px;z-index:1050;background-color:#fff;border-radius:8px!important;cursor:default}.bg-fff{background-color:#fff}.actions-dropdown-setting{right:250px}.action-button{background-color:#007cf5!important;border-radius:8px!important;padding:8px 16px!important;font-size:14px;height:32px;align-items:center}.global-search{max-width:380px!important;display:flex!important;align-items:center!important}.global-search span{margin-top:-4px!important}.global-search input{padding-left:28px;border-radius:8px!important}.global-search input:focus{outline:none!important;box-shadow:none!important}.active .top-icon ::ng-deep svg path{stroke:#007cf5!important}.dropdown-menu{background-color:#fff!important;border:1px solid #d9d9db!important;border-radius:8px!important}.custom-menu{width:220px;border-radius:8px;padding:4px 0;background-color:#fff}.custom-menu .dropdown-item{font-size:14px;padding:8px 14px}.custom-menu .dropdown-item:hover{background-color:#f5f5f5;border-radius:6px}.table-layout{right:0;background:#fff;border-radius:8px!important}.actions-dropdown,.table-layout,.custom-menu,.dropdown-menu{background:#fff;border-radius:8px!important;border:1px solid #ccc!important;background-color:#fff}.preview-box{width:40px;height:10px;border-radius:3px;background-color:transparent;transition:background-color .2s ease-in-out}.btn-check:checked+label .preview-box{background-color:var(--bs-primary)}.preview-box{width:40px;height:10px;border-radius:3px;border:2px solid transparent;transition:border-color .2s ease-in-out}#small:checked+label .preview-box{border-color:#007cf5!important;background-color:transparent!important}#medium:checked+label .preview-box{border-color:#007cf5!important;background-color:transparent!important}#large:checked+label .preview-box{border-color:#007cf5!important;background-color:transparent!important}.btn-check:checked+.btn{background-color:transparent!important;border-color:#007cf5!important}.layout-button{padding:8px 28px!important;width:82px;border-radius:8px!important}.show-hide-table-label{position:sticky;top:0;z-index:99;background:#fff}.cursor-grap{cursor:grabbing}.pagination-container{display:flex;align-items:center;gap:12px;font-size:13px;color:#333}.page-size select{padding:3px 6px;border:1px solid #ccc;border-radius:6px;background:#fff;font-size:13px}.page-info{margin-left:10px}.page-buttons{display:flex;gap:4px;margin-left:auto;align-items:center}.page-buttons button{padding:3px 8px;border:1px solid #ccc;background:#fff;border-radius:4px;cursor:pointer;font-size:13px;line-height:1.2}.page-buttons button.active{background:#eee;font-weight:600}.page-buttons button:disabled{opacity:.5;cursor:not-allowed}.page-buttons span{padding:0 6px;color:#666}.page-size .separator{padding:0 8px;border-right:1px solid #ccc;margin-right:8px}.page-size .separator .actions-dropdown{position:fixed;right:200px;z-index:1050;background-color:#fff}.fs-14px{font-size:14px}.fs-12px{font-size:12px!important}.save-preset-dropdown{background:#fff;color:#111!important;right:0;font-weight:400!important;text-align:left!important;max-width:250px!important;text-wrap:auto!important;top:14px;font-size:14px!important}.add-filter-button{height:28px;cursor:pointer;border-radius:4px}.add-filter-button:hover,.button-filter:hover{color:#000!important}.button-filter:hover ::ng-deep svg path{stroke:#000!important}.table-layout .dropdown-item{border-radius:0!important;padding-inline:16px!important;font-size:14px;padding-block:6px!important}.table-layout .dropdown-item:hover{background-color:transparent!important}.filter-serach-inpt{max-height:230px!important;overflow:auto;scrollbar-width:thin;padding-top:4px;background-color:#f7f7f7;border-color:#dedede;border-radius:8px}.filter-serach-inpt .badge{color:#007cf5!important;background-color:#e6f2ff!important;border-radius:8px!important;padding:8px!important;font-weight:500!important;font-size:12px!important;height:24px!important}.filter-serach-inpt .badge ::ng-deep svg{cursor:pointer}.filter-serach-inpt .badge ::ng-deep svg:hover path{stroke:#040081!important}.filter-serach-inpt input{background-color:#f7f7f7;padding:0;height:26px;margin-top:-5px}.text-filter select{border:0}.text-filter select option{font-size:14px;font-weight:500}.text-filter select:focus{border:0}.text-filter input:focus,.text-filter select:focus{box-shadow:none!important}.active-filters{background-color:#f7f7f7;white-space:nowrap;background:#f7f7f7;padding-inline:8px;height:28px;font-size:14px;font-weight:500;border-radius:8px;box-shadow:none}.active-filters .header-tag{white-space:nowrap}.filter-tags .active{background-color:#e6f2ff}.filter-tags .active .header-tag{color:#007cf5!important}.table-cell{cursor:pointer;width:100%}.table-cell input:focus{outline:0!important;border:0!important;width:100%!important;box-shadow:none!important}.active-for-editing{outline:2.5px solid #007cf5!important;border-radius:4px;border:0!important;width:100%!important}.active-cell{outline:none!important;box-shadow:inset 0 0 0 1.5px #007cf5}span[inlineSVG]{width:16px;height:16px;display:inline-block}.cell .dropdown-menu{min-width:unset!important}.cell .dropdown-menu .item{transition:background-color .3s ease;display:flex;align-items:center;-webkit-user-select:none;user-select:none}.cell .dropdown-menu .item:hover{background-color:#f0f8ff}.cell .cell-editin-dropdown{scrollbar-width:thin!important;-webkit-user-select:none;user-select:none}.fw-semibold{font-weight:500!important}:host ::ng-deep .three-dots-col-menu svg,:host ::ng-deep .three-dots-col-menu svg path{stroke:#000!important}.fs-7{font-size:12px!important}.fs-8{font-size:10px!important}.all-filters-reset-button:hover{opacity:.7}.full-text-box{background:#fff;position:relative;display:flex;align-items:center;z-index:1050;border:1px solid #dedede;border-radius:8px;padding:12px 14px;box-shadow:0 2px 8px #00000026;max-height:400px;overflow:auto}.full-text-box ul{max-height:400px}.full-text-content{border-radius:8px;max-height:70vh;overflow:auto;white-space:pre-wrap}.pic{border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:22px}.pic-comb2{background-color:#fbe7bf;color:#fd7f31}.pic-comb1{background-color:#d9ecbf;color:#65b500}.pic-comb4{background-color:#fdd3d7;color:#f64e60}.w-40px{width:40px}.h-40px{height:40px}.pic{border-radius:50%;overflow:hidden}.image-placeholder .pic{font-size:14px;font-weight:600;letter-spacing:.5px}.header-cell{font-weight:600}.header-cell,.cell{box-sizing:border-box}.transparent-border-right{border-right:1px solid transparent!important}.resizing-highlight{position:relative}.resizing-highlight:before{content:\"\";position:absolute;top:-1px;right:-1px;width:2px;height:calc(100% + 2px);background:#7cb9f6;z-index:1000;pointer-events:none}.resizing-highlight-right{position:relative}.resizing-highlight-right:before{content:\"\";position:absolute;top:-1px;left:-1px;width:2px;height:calc(100% + 2px);background:#7cb9f6;z-index:1000;pointer-events:none}.resizing-highlight-right:first-child{width:1px}.editable-header{border-bottom:1px dashed #666}.muted-text{color:#727272!important}.context-menu{position:fixed;display:none;background:#fff;border:1px solid #dcdcdc;box-shadow:#0000003d 0 3px 8px;z-index:1000;width:150px;border-radius:8px;font-weight:600}.context-menu.show{display:block}.context-menu ul{list-style:none;margin:0;padding:0}.context-menu li{padding:10px;cursor:pointer;color:#99a1b7}.context-menu li ::ng-deep svg{width:16px;height:16px;display:inline-block;color:#727272}.context-menu li ::ng-deep svg path{stroke:#727272}.context-menu li:hover{background-color:#f0f0f5!important}.invisible{visibility:hidden!important}.fw-500{font-weight:500!important}.taskbar{position:fixed;display:flex;justify-content:center;z-index:1000}.taskbar .action-btn{transition:opacity text-decoration .3s ease}.taskbar .action-btn:hover{text-decoration:underline;opacity:.8}.taskbar .delete{color:#ea0000}.selected-count,.action-btn,.dropdown-content a{font-weight:500;font-size:14px}.selected-rows-action-bar{background-color:#1a1a1a;color:#fff;padding:4px 24px;border-radius:8px;display:flex;align-items:center;justify-content:space-between;gap:24px;box-shadow:0 -4px 12px #00000026}.selected-rows-action-bar .btn:active,.selected-rows-action-bar .btn:focus{outline:0!important;border:0!important;border-color:transparent!important}.selected-rows-action-bar .action-btn{color:#fff!important}.cell .dropdown-menu,.cell .form-select,.cell input{color:#000!important}.cell input::placeholder{color:#727272!important}.cell .badge{border-radius:50px!important;height:26px;align-items:center}.cell .badge-danger{color:#ea5353!important;border:1px solid #ea5353!important;background-color:#ff00000d!important}.cell .badge-success{background-color:#84ca8130!important;border:1.5px solid rgb(70,227,114)!important;color:#46e372!important}.cell .badge-warning{background-color:#fff3dc!important;color:orange!important;border:1px solid #ffa000!important}.cell .badge-info{color:#00bad1;background-color:#e8fbfd;border:1px solid #00bad1}.cell .badge-secondary{color:#6c757d;background-color:#f1f3f5;border:1px solid #6c757d}.header-tag ::ng-deep svg path{stroke:#727272!important}.cross-secondary:hover ::ng-deep svg path{stroke:#000!important}.disable-sorting{pointer-events:none;opacity:.5}.rows-grouping-top-container ::ng-deep .cdk-drag-placeholder{background-color:transparent!important}input.is-invalid:focus{border:2.5px solid red!important;outline:none}.table-cell input.is-invalid:focus{border:2.5px solid red!important;outline-color:red!important;outline:none!important;box-shadow:none!important}.active-for-editing:has(input.is-invalid:focus){outline:none!important;box-shadow:none!important;border:0!important}.selected-cell,.row-selected{background-color:#c2e0fe}.first-row-selected{border-top:2px solid #2196f3!important}.last-row-selected{border-bottom:2px solid #2196f3!important}.left-selection-border{border-left:2px solid #2196f3!important}.s-no{font-size:14px;font-weight:500}.top-border{border-top:2px solid #2196f3!important}.bottom-border{border-bottom:2px solid #2196f3!important}.left-border{border-left:2px solid #2196f3!important}.border-left{border-left:1px solid #d9d9db}.right-border{border-right:2px solid #2196f3!important}.top-left-corner{border-top-left-radius:4px}.top-right-corner{border-top-right-radius:4px}.bottom-left-corner{border-bottom-left-radius:4px}.bottom-right-corner{border-bottom-right-radius:4px}.flash-bg{animation:flashAnim 1000s ease}@keyframes flashAnim{0%{background-color:#48a2fc}50%{background-color:#c2e0fe}to{background-color:#c2e0fe}}.cut-flash-bg{animation:cut-flash .8s ease}@keyframes cut-flash{0%{background-color:#f006}50%{background-color:#f00c}to{background-color:#c2e0fe}}.accordion-details .center-section .table .tbody .tr:hover .td{background-color:#f0f8ff!important}.editing-dropdown-search-input input:focus{border:1px solid #86b7fe!important}.nested-table .thead{position:sticky;top:0}.dropdown-wrapper{position:relative;display:inline-block}.btn-icon{background:transparent;border:0;padding:.25rem .5rem;cursor:pointer}.custom-dropdown-menu{position:absolute;right:0;top:calc(100% + 6px);min-width:200px;list-style:none;margin:0;padding:.25rem 0;background:#fff!important;border:1px solid rgba(0,0,0,.08);box-shadow:0 6px 18px #00000014;border-radius:.35rem;z-index:1200}.custom-dropdown-menu .dropdown-item{display:block;width:100%;padding:.5rem 1rem;text-align:left;background:transparent;border:none}.custom-dropdown-menu .dropdown-item:hover{background:#00000008}.cell-editing-dropdown-menu .dropdown-item{width:99%}.cell-editing-dropdown-menu .selected{background-color:#f0f8ff}.confirm-block{padding:0}.center-nested-table .tr:hover .td{background-color:#f0f8ff}.table ::ng-deep .cdk-drag-placeholder{background-color:#fff!important}.assets-pic{border-radius:8px!important}.fullscreen-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000c;display:flex;align-items:center;justify-content:center;z-index:1000;cursor:zoom-out}.fullscreen-img{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 0 15px #00000080}.position-sticky{z-index:2}.viewport{display:block!important;overflow:visible!important}.nested-table ::ng-deep .cdk-virtual-scroll-content-wrapper{padding:0!important}.nested-table ::ng-deep .cdk-virtual-scroll-viewport{overflow-x:hidden!important}.disabled-search-input{background-color:#f5f5f5;cursor:pointer!important}.right-click-menu-icons ::ng-deep svg path{stroke-width:2!important}.loader{animation:rotate 1s infinite;height:50px;width:50px}.loader:before,.loader:after{border-radius:50%;content:\"\";display:block;height:20px;width:20px}.loader:before{animation:ball1 1s infinite;background-color:#fff;box-shadow:30px 0 #ff3d00;margin-bottom:10px}.loader:after{animation:ball2 1s infinite;background-color:#ff3d00;box-shadow:30px 0 #fff}@keyframes rotate{0%{transform:rotate(0) scale(.8)}50%{transform:rotate(360deg) scale(1.2)}to{transform:rotate(720deg) scale(.8)}}@keyframes ball1{0%{box-shadow:30px 0 #ff3d00}50%{box-shadow:0 0 #ff3d00;margin-bottom:0;transform:translate(15px,15px)}to{box-shadow:30px 0 #ff3d00;margin-bottom:10px}}@keyframes ball2{0%{box-shadow:30px 0 #fff}50%{box-shadow:0 0 #fff;margin-top:-20px;transform:translate(15px,15px)}to{box-shadow:30px 0 #fff;margin-top:0}}.rows-grouping-top-container ::ng-deep .cdk-drag-placeholder{opacity:.7!important}.action-button{background-color:#6f61cf!important;color:#fff!important;border-radius:6px!important;font-weight:500!important;margin-top:-4px}.action-button:hover{background-color:#6a5fb3!important}.action-buttons-row .button{display:inline-flex;align-items:center;justify-content:center;overflow:hidden;color:#fff;border-radius:6px;height:34px;padding:0 10px;white-space:nowrap;transition:max-width .4s ease,background-color .3s ease;max-width:40px;background-color:transparent;border:1px solid #6F61CF}.action-buttons-row .button .label-hidden{opacity:0;margin-left:8px;transition:opacity .3s ease;pointer-events:none;display:none}.action-buttons-row .button:hover{max-width:200px;background-color:#6f61cf}.action-buttons-row .button:hover .label-hidden{opacity:1;pointer-events:auto;margin-left:8px!important;display:block}.action-buttons-row ::ng-deep .button .svg-icon svg path{stroke:#6f61cf;transition:fill .3s ease,stroke .3s ease}.action-buttons-row ::ng-deep .button:hover .svg-icon svg path{stroke:#fff!important}::ng-deep .nav-tabs .nav-link{border:none!important;border-bottom:2px solid transparent!important;border-radius:0!important;background:transparent!important}::ng-deep .nav-tabs .nav-link:hover,::ng-deep .nav-tabs .nav-link:focus{border:none!important;border-bottom:2px solid transparent!important;outline:none!important;background:transparent!important}::ng-deep .nav-tabs .nav-link.active{border:none!important;border-bottom:2px solid var(--bs-primary)!important;background:transparent!important;color:var(--bs-primary)!important}.open-top{top:-150%!important}.muted{color:#7a7a7a!important}.item-title{font-size:1.2em;font-weight:700;margin-bottom:10px}.item-image{width:100%;border-radius:10px}.comment{display:flex;align-items:center;margin-bottom:10px}.comment-avatar{width:40px;height:40px;border-radius:50%;margin-right:10px}.comment-author{font-weight:700}.comment-content{font-size:.9em;line-height:1.4}.comment-timestamp{font-size:.8em;color:#888;margin-left:auto}.des_low{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;width:242px;display:block;text-transform:capitalize!important}.firstDiv{word-break:break-word;overflow-wrap:break-word;white-space:normal}.container{display:flex;flex-wrap:wrap;margin:20px;gap:20px;background-color:#fff;padding:20px;border-radius:10px}.item{width:calc(33.33% - 20px);background-color:#fff;padding:20px;border-radius:10px;box-shadow:0 2px 5px #0000001a}.forCommentImg{width:70px;border-radius:16px;margin:8px 0;cursor:pointer}.image-modal img{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 4px 10px #00000080}.full-image-modal{position:fixed;background:#000c;display:flex;justify-content:center;align-items:center;z-index:1000}.full-image-modal .full-image{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 0 10px #fff3}.item-content{font-size:14px;line-height:1.5;max-height:220px;overflow-y:auto}.image-modal.full-image-modal{position:fixed;width:100vw;height:100vh;background-color:#000c;display:flex;justify-content:center;align-items:center;z-index:9999;overflow:hidden;cursor:zoom-out}.image-modal.full-image-modal img{border-radius:8px;box-shadow:0 4px 20px #0006;object-fit:contain;transition:transform .3s ease}.image-modal.full-image-modal img:hover{transform:scale(1.02)}::ng-deep .custom-overlay-wrapper .custom-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000000d9;display:flex;align-items:center;justify-content:center;z-index:9999}::ng-deep .custom-overlay-wrapper .custom-modal{background:#fff;border-radius:12px;box-shadow:0 8px 25px #0003;width:360px;max-width:90%;padding:24px;text-align:center;animation:fadeInScale .25s ease}::ng-deep .custom-overlay-wrapper .custom-modal-body .modal-message{font-size:16px;margin-bottom:20px;color:#333}::ng-deep .custom-overlay-wrapper .modal-actions{display:flex;justify-content:center;gap:12px}::ng-deep .custom-overlay-wrapper .modal-actions button{min-width:90px;padding:8px 14px;border-radius:6px;border:none;font-weight:500;cursor:pointer;transition:background-color .2s ease}::ng-deep .custom-overlay-wrapper .btn-confirm{background-color:#007bff;color:#fff}::ng-deep .custom-overlay-wrapper .btn-confirm:hover{background-color:#0069d9}::ng-deep .custom-overlay-wrapper .btn-cancel{background-color:#e4e4e4;color:#333}::ng-deep .custom-overlay-wrapper .btn-cancel:hover{background-color:#d6d6d6}@keyframes fadeInScale{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.clear-btn{background:linear-gradient(135deg,#f53545,#f53545);border:none;color:#fff;font-size:13px;padding:3px 6px;border-radius:20px;font-weight:500;display:inline-flex;align-items:center;gap:6px;cursor:pointer;transition:all .3s ease;box-shadow:0 2px 6px #ff5f6d66;position:relative;bottom:4px}.clear-btn:hover{transform:translateY(-2px);box-shadow:0 4px 10px #ff5f6d99;background:linear-gradient(135deg,#f53545,#f53545)}.clear-btn i{font-size:16px;vertical-align:middle}.cell-editin-dropdown .deopdown-item{width:100%!important;box-shadow:none!important;border-radius:4px;cursor:pointer;padding-block:8px!important}.cell-editin-dropdown .deopdown-item:hover{background-color:#f1f1f1}\n"], dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i6.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i6.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i6.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i6.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i8.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i8.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i8.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i8.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i8.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i8.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i8.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i8.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i8.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i8.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i9.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i9.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i9.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i9.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: i9.CdkDragPreview, selector: "ng-template[cdkDragPreview]", inputs: ["data", "matchSize"] }, { kind: "directive", type: i9.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "directive", type: i10.InlineSVGDirective, selector: "[inlineSVG]", inputs: ["inlineSVG", "resolveSVGUrl", "replaceContents", "prepend", "injectComponent", "cacheSVG", "setSVGAttributes", "removeSVGAttributes", "forceEvalStyles", "evalScripts", "fallbackImgUrl", "fallbackSVG", "onSVGLoaded"], outputs: ["onSVGInserted", "onSVGFailed"] }, { kind: "directive", type: i11.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i11.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i11.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CellRenderInitDirective, selector: "[cellRenderInit]", inputs: ["cellRenderInit", "rowData", "colData", "cellValue"], outputs: ["cellEvent"] }, { kind: "directive", type: CellEditorDirective, selector: "[cellEditor]", inputs: ["cellEditor", "rowData", "colData", "cellValue"], outputs: ["editorEvent"] }, { kind: "pipe", type: i6.SlicePipe, name: "slice" }, { kind: "pipe", type: i6.TitleCasePipe, name: "titlecase" }, { kind: "pipe", type: i6.DatePipe, name: "date" }, { kind: "pipe", type: FilterPipe, name: "filter" }], animations: [
|
|
6102
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DataGridComponent, selector: "data-grid", inputs: { rowAnimation: "rowAnimation", paginationConfig: "paginationConfig", dataSet: "dataSet", columns: "columns", rowHeight: "rowHeight", headerRowHeight: "headerRowHeight", showVerticalBorder: "showVerticalBorder", evenRowsBackgroundColor: "evenRowsBackgroundColor", oddRowsBackgroundColor: "oddRowsBackgroundColor", headerBackgroundColor: "headerBackgroundColor", checkboxesBackgroundColor: "checkboxesBackgroundColor", showColumnsGrouping: "showColumnsGrouping", rowHoverColor: "rowHoverColor", leftPinnedBackgroundColor: "leftPinnedBackgroundColor", bodyBackgroundColor: "bodyBackgroundColor", rightPinnedBackgroundColor: "rightPinnedBackgroundColor", sidemenuBackgroundColor: "sidemenuBackgroundColor", bodyTextColor: "bodyTextColor", headerTextColor: "headerTextColor", checkboxesColor: "checkboxesColor", headerTextFontsSize: "headerTextFontsSize", bodyTextFontsSize: "bodyTextFontsSize", headerFontWeight: "headerFontWeight", bodyFontWeight: "bodyFontWeight", checkedRowBackgroundColor: "checkedRowBackgroundColor", dropdownsBackgroundColor: "dropdownsBackgroundColor", footerRowBackgroundColor: "footerRowBackgroundColor", footerRowHeight: "footerRowHeight", topGroupedBadgesBackgroundColor: "topGroupedBadgesBackgroundColor", showRowsGrouping: "showRowsGrouping", showFilterRow: "showFilterRow", fontFaimly: "fontFaimly", showSideMenu: "showSideMenu", footerPadding: "footerPadding", topFilterRowHeight: "topFilterRowHeight", rowShadingEnabled: "rowShadingEnabled", showSerialNumber: "showSerialNumber", singleSpaAssetsPath: "singleSpaAssetsPath", filtersConfig: "filtersConfig", loading: "loading", verticalScrollbarWidth: "verticalScrollbarWidth", horizintalScrollbarWidth: "horizintalScrollbarWidth", showCellDetailsBox: "showCellDetailsBox", dateFormat: "dateFormat", tableSearch: "tableSearch", actions: "actions", config: "config", showTaskbar: "showTaskbar", tableName: "tableName", listingType: "listingType", checkboxState: "checkboxState", taskbarActions: "taskbarActions", sortingConfig: "sortingConfig", tableFilterViewId: "tableFilterViewId", selectedTableLayout: "selectedTableLayout", closeDropdown: "closeDropdown", globalSearchText: "globalSearchText", nestedTablerowFontsize: "nestedTablerowFontsize", nestedTableHeaderRowHeight: "nestedTableHeaderRowHeight", nestedTablerowHeight: "nestedTablerowHeight", gridType: "gridType", currencySymbol: "currencySymbol", currencyFormat: "currencyFormat", leftPinnedBoxshadow: "leftPinnedBoxshadow", rightPinnedBoxshadow: "rightPinnedBoxshadow", selectedRowsBackgroundColor: "selectedRowsBackgroundColor", nestedTableHeaderBackgroundColor: "nestedTableHeaderBackgroundColor", nestedTableRowBackgroundColor: "nestedTableRowBackgroundColor", tableView: "tableView", buttons: "buttons", keepMultipleExpandedDetails: "keepMultipleExpandedDetails", showTotalAmountRow: "showTotalAmountRow", enableGlobalSearch: "enableGlobalSearch", tableType: "tableType", enableExport: "enableExport", showFullScreenButton: "showFullScreenButton", enableCut: "enableCut", tabs: "tabs", showCheckboxes: "showCheckboxes", consumerFont: "consumerFont", defaultConfig: "defaultConfig", resetAllFilters: "resetAllFilters", columnThreedotsMunuConfig: "columnThreedotsMunuConfig" }, outputs: { changeLayout: "changeLayout", customCellEvent: "customCellEvent", filterOptions: "filterOptions", genericEvent: "genericEvent", tablePresetConfig: "tablePresetConfig", sortingOrderOptions: "sortingOrderOptions", createUpdateConfigListing: "createUpdateConfigListing" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape($event)", "window:resize": "onResize($event)", "document:keydown": "onKeyDown($event)", "document:paste": "onPaste($event)" } }, viewQueries: [{ propertyName: "globalSearchInput", first: true, predicate: ["globalSearchInput"], descendants: true }, { propertyName: "cellText", first: true, predicate: ["cellText"], descendants: true }, { propertyName: "nestedHeader", first: true, predicate: ["nestedHeader"], descendants: true }, { propertyName: "dataGridContainer", first: true, predicate: ["dataGridContainer"], descendants: true }, { propertyName: "taskManagementContainer", first: true, predicate: ["taskManagementContainer"], descendants: true }, { propertyName: "nestedTableContainer", first: true, predicate: ["nestedTableContainer"], descendants: true }, { propertyName: "leftPinnedBody", first: true, predicate: ["leftPinnedBody"], descendants: true }, { propertyName: "centerPinnedBody", first: true, predicate: ["centerPinnedBody"], descendants: true }, { propertyName: "rightPinnedBody", first: true, predicate: ["rightPinnedBody"], descendants: true }, { propertyName: "leftPinnedHeader", first: true, predicate: ["leftPinnedHeader"], descendants: true }, { propertyName: "centerPinnedHeader", first: true, predicate: ["centerPinnedHeader"], descendants: true }, { propertyName: "rightPinnedHeader", first: true, predicate: ["rightPinnedHeader"], descendants: true }, { propertyName: "columnsGroupedBox", first: true, predicate: ["columnsGroupedBox"], descendants: true }, { propertyName: "centerFakeScrollbar", first: true, predicate: ["centerFakeScrollbar"], descendants: true }, { propertyName: "centerScroll", first: true, predicate: ["centerScroll"], descendants: true }, { propertyName: "mainScroll", first: true, predicate: ["mainScroll"], descendants: true }, { propertyName: "fakeScroll", first: true, predicate: ["fakeScroll"], descendants: true }, { propertyName: "horizintalFakeScroll", first: true, predicate: ["horizintalFakeScroll"], descendants: true }, { propertyName: "centerScrollableBody", first: true, predicate: ["centerScrollableBody"], descendants: true }, { propertyName: "filterMenueSearchInput", first: true, predicate: ["filterMenueSearchInput"], descendants: true }, { propertyName: "filterMenueTextchInput", first: true, predicate: ["filterMenueTextchInput"], descendants: true }, { propertyName: "textAreadInput", first: true, predicate: ["textAreadInput"], descendants: true }, { propertyName: "nestedTable", first: true, predicate: ["nestedTable"], descendants: true }, { propertyName: "fullscreenImageTemplate", first: true, predicate: ["fullscreenImageTemplate"], descendants: true }, { propertyName: "cellHosts", predicate: CellHostDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"position-relative h-100 card-outer\">\n <div class=\"d-flex justify-content-between mb-3 align-items-center position-relative\">\n <div class=\"d-flex gap-2\">\n <div class=\"nav nav-tabs\" *ngIf=\"true\">\n <div class=\"nav nav-tabs\" id=\"nav-tab\" role=\"tablist\">\n <span\n *ngFor=\"let tab of tabs; let i = index\"\n (click)=\"setActiveTab(tab)\"\n class=\"nav-link cursor-pointer\"\n [class.active]=\"activeTab == tab\"\n >\n {{ tab }}\n </span>\n </div>\n </div>\n <div class=\"new_design_dropdown hide_arrow\">\n <a href=\"JavaScript:void(0)\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" data-bs-auto-close=\"outside\"\n class=\"d-flex align-items-center dropdown-toggle justify-content-center dropdown_main_button\">\n All\n </a>\n </div>\n <div>\n <div class=\"btn-group new_design_dropdown hide_arrow\">\n <a href=\"JavaScript:void(0)\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" data-bs-auto-close=\"outside\"\n class=\"d-flex align-items-center dropdown-toggle justify-content-center dropdown_main_button\">\n Unfulfilled\n </a>\n <ul class=\"dropdown-menu\">\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/resetIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span> Reset</span>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/updatePresetIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span> Update and Re-save</span>\n </a>\n </li>\n <hr class=\"mt-1\">\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/infoIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span> Rename</span>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/duplicateIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span>Duplicate</span>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/trashIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span>Delete</span>\n </a>\n </li>\n </ul>\n </div>\n </div>\n <div>\n <div class=\"btn-group new_design_dropdown hide_arrow\">\n <a href=\"JavaScript:void(0)\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" data-bs-auto-close=\"outside\"\n class=\"d-flex align-items-center dropdown-toggle justify-content-center dropdown_main_button\">\n Unpaid\n </a>\n <ul class=\"dropdown-menu\">\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/infoIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span> Test Type</span>\n </a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n <div class=\"d-flex gap-1 align-items-center table-right-top-actions\">\n <div class=\"global-search position-relative\" [style.width.px]=\"350\">\n <span *ngIf=\"enableGlobalSearch\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\n class=\"data-grid-svg-icon ms-2 mt-0 position-absolute icon\" style=\"top: 8px;\"\n ></span>\n <input #globalSearchInput\n *ngIf=\"enableGlobalSearch\"\n class=\"form-control\"\n placeholder=\"Search\"\n [(ngModel)]=\"tableSearch\"\n (keydown.enter)=\"onGlobalSearch()\"\n (input)=\"onSearchInput($event)\"\n type=\"search\"\n />\n </div>\n <!-- <ng-container *ngFor=\"let button of buttons\">\n <div\n class=\"d-flex align-items-center gap-2 action-buttons-row\"\n *ngIf=\"button?.has_permission\"\n >\n <a\n href=\"JavaScript:void(0)\"\n (click)=\"onActionButtonClick(button.name)\"\n class=\"button button-small btn border border-primary btn-active-primary me-2 p-0 d-flex align-items-center justify-content-center px-3\"\n >\n <span\n *ngIf=\"button.is_showIcon\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/' + button.icon + '.svg'\n \"\n class=\"svg-icon svg-icon-2\"\n ></span>\n <span\n class=\"label-hidden text-white\"\n [class.ms-0]=\"button.is_showIcon\"\n >{{ button?.name }}</span\n >\n </a>\n </div>\n </ng-container> -->\n <div *ngIf=\"!showFilterRow\"\n class=\"cursor-pointer position-relative action-buttons-row\"\n (click)=\"toggleOpenFilter()\"\n [class.active]=\"showFilters\">\n <a href=\"JavaScript:void(0)\"\n class=\"p-0 d-flex align-items-center justify-content-center grid-header-icon\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filterIconNew.svg'\" class=\"svg-icon svg-icon-2\"></span>\n </a>\n <span *ngIf=\"activeFilteredColumns?.length\"\n style=\"\n width: 7px;\n height: 7px;\n box-shadow: 0px 0px 3px #0022ff;\n background-color: rgb(0, 60, 255);\n position: absolute;\n right: 8px;\n top: 6px;\n \"\n class=\"rounded-circle d-block\"\n ></span>\n </div>\n <div class=\"cursor-pointer d-none\"\n (click)=\"toggleActions('advance-filter')\"\n [class.active]=\"activeTopButton === 'advance-filter'\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/zoom-charge.svg'\"\n class=\"data-grid-svg-icon top-icon me-2\"\n ></span>\n </div>\n <div class=\"cursor-pointer actions-buttons-row\">\n <div class=\"btn-group new_design_dropdown hide_arrow\">\n <a href=\"JavaScript:void(0)\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" data-bs-auto-close=\"outside\"\n class=\"p-0 d-flex align-items-center dropdown-toggle justify-content-center grid-header-icon\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/sortingIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </a>\n <ul class=\"dropdown-menu dropdown-menu-left productSortingDropdownMenu\">\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div class=\"sorting_icon_input\">\n <input class=\"form-check-input\" type=\"radio\" name=\"exampleRadios\" id=\"productName\" value=\"option1\" checked>\n </div>\n <label class=\"form-check-label mb-0 mt-1\" for=\"productName\">\n Product Name\n </label>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div class=\"sorting_icon_input\">\n <input class=\"form-check-input\" type=\"radio\" name=\"exampleRadios\" id=\"createdDate\" value=\"option1\" checked>\n </div>\n <label class=\"form-check-label mb-0 mt-1\" for=\"createdDate\">\n Created Date\n </label>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div class=\"sorting_icon_input\">\n <input class=\"form-check-input\" type=\"radio\" name=\"exampleRadios\" id=\"updatedDate\" value=\"option1\" checked>\n </div>\n <label class=\"form-check-label mb-0 mt-1\" for=\"updatedDate\">\n Updated Date\n </label>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div class=\"sorting_icon_input\">\n <input class=\"form-check-input\" type=\"radio\" name=\"exampleRadios\" id=\"productType\" value=\"option1\" checked>\n </div>\n <label class=\"form-check-label mb-0 mt-1\" for=\"productType\">\n Product Type\n </label>\n </a>\n </li>\n <hr class=\"my-2\">\n <li class=\"d-flex\" (click)=\"activeFilter('newest')\" [class.active-filter]=\"activeFilterType === 'newest'\">\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrowupIconNew.svg'\"\n class=\"svg-icon svg-icon-2 mb-1 new_old_filter\"\n ></span>\n <span class=\"mt-1 newest\">Newest First</span>\n </a>\n <div *ngIf=\"activeFilterType === 'newest'\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickIconNew.svg'\"\n class=\"svg-icon svg-icon-2 mb-1\"\n ></span>\n </div>\n </li>\n <li class=\"d-flex\" (click)=\"activeFilter('oldest')\" [class.active-filter]=\"activeFilterType === 'oldest'\">\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrowdownIconNew.svg'\"\n class=\"svg-icon svg-icon-2 mb-1 new_old_filter\"\n ></span>\n <span class=\"mt-1 oldest\">Newest First</span>\n </a>\n <div *ngIf=\"activeFilterType === 'oldest'\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickIconNew.svg'\"\n class=\"svg-icon svg-icon-2 mb-1\"\n ></span>\n </div>\n </li>\n </ul>\n </div>\n </div>\n <div class=\"cursor-pointer action-buttons-row\"\n (click)=\"toggleActions('setting')\"\n [class.active]=\"\n activeTopButton === 'setting' ||\n activeTopButton === 'table-layout' ||\n activeTopButton === 'table-presets' ||\n activeTopButton === 'show-hide-columns'\">\n <!-- <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/settings-2.svg'\"\n class=\"data-grid-svg-icon top-icon me-2\"\n ></span> -->\n\n <a href=\"JavaScript:void(0)\"\n class=\"p-0 d-flex align-items-center justify-content-center grid-header-icon\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/settingIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </a>\n\n <div *ngIf=\"activeTopButton === 'setting'\"\n class=\"actions-dropdown mt-1 actions-dropdown-setting\"\n style=\"position: absolute\">\n <div class=\"dropdown-menu show shadow custom-menu setting_dropdown_menu\">\n <!-- Table Layout -->\n <a class=\"dropdown-item py-0 px-2 d-flex justify-content-between align-items-center cursor-pointer\"\n (click)=\"$event.stopPropagation(); toggleActions('table-layout')\">\n <span class=\"d-flex justify-content-between align-items-center\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/layoutIconNew.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown\"\n ></span>\n Table Layout</span\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n class=\"data-grid-svg-icon d-flex align-items-center justify-content-center\"\n ></span>\n </a>\n <!-- Table Presets -->\n <a (click)=\"$event.stopPropagation(); toggleActions('table-presets')\"\n class=\"dropdown-item py-0 px-2 d-flex justify-content-between align-items-center cursor-pointer\">\n <span class=\"d-flex align-items-center justify-content-center\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/list-details.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown d-flex align-items-center justify-content-center\"\n ></span>\n Table Presets</span\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n class=\"data-grid-svg-icon d-flex align-items-center justify-content-center\"\n ></span>\n </a>\n\n <!-- Columns -->\n <a *ngIf=\"!showSideMenu\" (click)=\"$event.stopPropagation(); toggleActions('show-hide-columns')\"\n class=\"dropdown-item py-0 px-2 d-flex justify-content-between align-items-center cursor-pointer\">\n <span class=\"d-flex align-items-center justify-content-center\"><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/eyeIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown me-2\"\n ></span>\n Columns</span>\n <div class=\"d-flex align-items-center gap-2\">\n <span class=\"muted-text\">{{ columnsCount }}</span>\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n class=\"data-grid-svg-icon d-flex align-items-center justify-content-center\"\n ></span>\n </div>\n </a>\n\n <a (click)=\"autosizeAllColumns()\" class=\"dropdown-item py-0 px-2 d-flex justify-content-between align-items-center cursor-pointer\">\n <span class=\"d-flex align-items-center justify-content-center\"><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/resizeIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown me-2\"></span>\n <span>Autosize all columns</span>\n </span>\n <!-- <div class=\"d-flex align-items-center gap-2\">\n <div class=\"form-check form-switch\">\n <input class=\"form-check-input\" type=\"checkbox\" id=\"flexSwitchCheckChecked\">\n <label class=\"form-check-label\" for=\"flexSwitchCheckChecked\"></label>\n </div>\n </div> -->\n </a>\n\n <a class=\"dropdown-item py-0 px-2 d-flex justify-content-between align-items-center cursor-pointer\">\n <span class=\"d-flex align-items-center justify-content-center\"><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/multicellNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown me-2\"></span>\n <span>Multi-cell tooltip mode</span>\n </span>\n <!-- <div class=\"d-flex align-items-center gap-2\">\n <div class=\"form-check form-switch\">\n <input class=\"form-check-input\" type=\"checkbox\" id=\"flexSwitchCheckChecked\">\n <label class=\"form-check-label\" for=\"flexSwitchCheckChecked\"></label>\n </div>\n </div> -->\n </a>\n\n <div class=\"dropdown-divider\"></div>\n\n <!-- Filter -->\n <!-- <a class=\"dropdown-item py-0 px-2 d-flex align-items-center cursor-pointer\"\n (click)=\"toggleOpenFilter(); activeTopButton = '';\"\n *ngIf=\"!showFilterRow\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/filterIconNew.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown d-flex align-items-center justify-content-center cursor-pointer\"\n ></span>\n Filter\n </a> -->\n\n <!-- Download -->\n <a class=\"dropdown-item py-0 px-2 d-flex align-items-center cursor-pointer\"\n (click)=\"downloadCsv('csv')\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/exportIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown d-flex align-items-center justify-content-center cursor-pointer\"\n ></span>\n CSV Export\n </a>\n <a *ngIf=\"enableExport\"\n class=\"dropdown-item py-0 px-2 d-flex align-items-center cursor-pointer\"\n (click)=\"downloadCsv('xlsx')\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/exportIconNew.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown d-flex align-items-center justify-content-center cursor-pointer\"\n ></span>\n Excel Export\n </a>\n <!-- Font Family & Font Size -->\n <div class=\"px-2 pb-2 pt-2\">\n <div class=\"d-flex gap-2\">\n <!-- <select\n class=\"form-select form-select-sm\"\n [(ngModel)]=\"fontFaimly\"\n (change)=\"onFontChange()\"\n >\n <option *ngFor=\"let font of fontFamilies\" [value]=\"font\">\n {{ font }}\n </option>\n </select> -->\n\n <!-- Font Size -->\n <!-- <select\n class=\"form-select form-select-sm\"\n (change)=\"onFontChange()\"\n [(ngModel)]=\"bodyTextFontsSize\"\n >\n <option *ngFor=\"let size of fontSizes\" [value]=\"size\">\n {{ size }}\n </option>\n </select> -->\n </div>\n </div>\n </div>\n </div>\n\n <!-- Table Layout -->\n\n <ng-container *ngIf=\"activeTopButton === 'table-layout'\">\n <div\n *ngTemplateOutlet=\"tableLayout\"\n class=\"actions-dropdown mt-1\"\n style=\"position: absolute\"\n ></div>\n </ng-container>\n\n <!-- Table Presets -->\n <ng-container *ngIf=\"activeTopButton === 'table-presets'\">\n <div\n *ngTemplateOutlet=\"tablePreset\"\n class=\"actions-dropdown mt-1\"\n style=\"position: absolute\"\n ></div>\n </ng-container>\n\n <!-- Table Presets -->\n <ng-container *ngIf=\"activeTopButton === 'show-hide-columns'\">\n <div\n *ngTemplateOutlet=\"showHideColumns\"\n class=\"actions-dropdown mt-1\"\n style=\"position: absolute\"\n ></div>\n </ng-container>\n </div>\n <div class=\"cursor-pointer actions-buttons-row\">\n <div class=\"btn-group new_design_dropdown\">\n <button type=\"button\" class=\"primary_btn_new dropdown-toggle consumerDropdownButton px-2\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\">\n Actions\n </button>\n <ul class=\"dropdown-menu\">\n <li>\n <a class=\"dropdown-item hover_dropdown_bg action_dropdown\" (click)=\"createCustomColumn()\">Create custom column</a>\n </li>\n <ng-container *ngFor=\"let button of buttons\">\n <li *ngIf=\"button?.has_permission\">\n <a class=\"dropdown-item hover_dropdown_bg action_dropdown\" \n href=\"javascript:void(0)\" \n (click)=\"onActionButtonClick(button.name)\">\n <!-- <span *ngIf=\"button.is_showIcon\" \n class=\"me-2\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/' + button.icon + '.svg'\"\n class=\"svg-icon svg-icon-2\"></span>\n </span> -->\n <span>{{ button?.name }}</span>\n </a>\n </li>\n </ng-container>\n </ul>\n </div>\n </div>\n <!-- <div class=\"cursor-pointer actions-buttons-row\" *ngIf=\"buttons.length == 1\">\n <a href=\"JavaScript:void(0)\"\n (click)=\"onActionButtonClick(buttons[0].name)\"\n class=\"btn btn-primary border border-primary py-1 d-flex align-items-center justify-content-center px-3\">\n <span class=\"text-white\"\n [class.ms-0]=\"buttons[0].is_showIcon\"\n >{{ buttons[0].name }}</span>\n </a>\n </div> -->\n <div class=\"action-buttons-row\" *ngIf=\"showFullScreenButton\">\n <a\n *ngIf=\"!isFullScreen\"\n class=\"button button-small btn btn-active-primary border border-primary expend d-flex justify-content-center align-items-center\"\n (click)=\"toggleFullscreen()\"\n data-bs-toggle=\"tooltip\"\n data-bs-placement=\"top\"\n title=\"Minimise\"\n [ngClass]=\"{ minArrow: !isFullScreen, maxArrow: isFullScreen }\"\n style=\"transition: color 0.2s\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/expend.svg'\"\n class=\"svg-icon svg-icon-2 mb-1\"\n ></span>\n </a>\n <a\n *ngIf=\"isFullScreen\"\n class=\"button button-small btn btn-active-primary border border-primary expend d-flex justify-content-center align-items-center\"\n (click)=\"toggleFullscreen()\"\n data-bs-toggle=\"tooltip\"\n data-bs-placement=\"top\"\n title=\"Maximise\"\n [ngClass]=\"{ minArrow: !isFullScreen, maxArrow: isFullScreen }\"\n style=\"transition: color 0.2s\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/minimize.svg'\"\n class=\"svg-icon svg-icon-2 mb-1\"\n ></span>\n </a>\n </div>\n <div>\n <!-- Example single danger button -->\n\n <!-- <button\n type=\"button\"\n class=\"btn btn-primary btn-sm d-flex gap-2 action-button\"\n (click)=\"toggleActions('actions')\"\n >\n Action\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/Vector.svg'\"\n class=\"data-grid-svg-icon\"\n ></span>\n </button>\n <div\n *ngIf=\"activeTopButton === 'actions'\"\n class=\"actions-dropdown mt-1\"\n >\n <div class=\"dropdown-menu show\">\n <a class=\"dropdown-item\" href=\"#\">Action</a>\n <a class=\"dropdown-item\" href=\"#\">Another action</a>\n <a class=\"dropdown-item\" href=\"#\">Something else here</a>\n <div class=\"dropdown-divider\"></div>\n <a class=\"dropdown-item\" href=\"#\">Separated link</a>\n </div>\n </div> -->\n </div>\n </div>\n </div>\n\n <div\n *ngIf=\"showFilters && !showFilterRow\"\n class=\"top-filter-row border-top py-2 d-flex justify-content-between align-items-center\"\n [style.height.px]=\"topFilterRowHeight\"\n >\n <!-- LEFT SIDE (Filter tags + Filter button) -->\n <div class=\"d-flex gap-2 align-items-center\">\n <ng-container>\n <div\n *ngFor=\"let col of activeFilteredColumns; trackBy: trackByField\"\n class=\"filter-tags\"\n >\n <div\n (click)=\"\n isActiveFilterOpen = true;\n activeTopButton = 'filter-columns';\n openFilter(col)\n \"\n class=\"d-flex justify-content-center align-items-center muted-text add-filter-button active-filters\"\n style=\"white-space: nowrap\"\n [class.active]=\"\n col?.field == selectedColumnForFilter?.field &&\n isActiveFilterOpen &&\n activeTopButton == 'filter-columns'\n \"\n >\n <span class=\"header-tag mt-0 d-flex align-items-center left-side-pinned\">\n <span\n *ngIf=\"col?.pinned\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pin.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n {{ col.header }}: {{col.query.first_value || col.query?._ids[0]}}\n <span\n (click)=\"\n $event.stopPropagation(); removeColumnFilterFromColumn(col)\n \"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/filterCrossNew.svg'\n \"\n class=\"data-grid-svg-icon cross-secondary ms-2\"\n ></span>\n </span>\n </div>\n\n <ng-container\n *ngIf=\"\n activeTopButton === 'filter-columns' &&\n col?.field == selectedColumnForFilter?.field &&\n isActiveFilterOpen\n \"\n >\n <div\n *ngTemplateOutlet=\"filterColumns; context: { column: col }\"\n class=\"actions-dropdown mt-1\"\n ></div>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- Filter Button -->\n <div class=\"add-filter-button-menu\">\n <div\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\n class=\"d-flex justify-content-center align-items-center muted-text add-filter-button button-filter\"\n style=\"width: 70px\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/plus.svg'\"\n class=\"me-2 data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n Filter\n </div>\n\n <ng-container\n *ngIf=\"activeTopButton === 'filter-columns' && !isActiveFilterOpen\"\n >\n <div\n *ngTemplateOutlet=\"filterColumns\"\n class=\"actions-dropdown mt-1\"\n ></div>\n </ng-container>\n </div>\n </div>\n\n <!-- RIGHT SIDE (Update + Reset) -->\n <div class=\"d-flex gap-3 align-items-center\">\n <div\n (click)=\"savePreset()\"\n class=\"text-primary cursor-pointer all-filters-reset-button\"\n *ngIf=\"!checkFilterChangesEffect()\"\n >\n Update View\n </div>\n\n <div\n class=\"text-primary cursor-pointer all-filters-reset-button\"\n *ngIf=\"!tableFilterViewId && activeFilteredColumns?.length\"\n (click)=\"clearAllFilters()\">\n Clear filters\n </div>\n </div>\n </div>\n\n <div\n [style.height]=\"\n showFilters ? 'calc(100% - ' + (topFilterRowHeight + footerRowHeight) + 'px)' : 'calc(100% - ' + footerRowHeight + 'px)'\n \"\n cdkDropListGroup\n class=\"data-grid-table-wrapper overflow-hidden\"\n #dataGridContainer\n [style.fontFamily]=\"fontFaimly\"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n id=\"data-grid-main-container\"\n >\n <div\n *ngIf=\"showRowsGrouping\"\n [style.height.px]=\"headerRowHeight\"\n [cdkDropListData]=\"columns\"\n [style.backgroundColor]=\"\n topGroupedBadgesBackgroundColor || headerBackgroundColor\n \"\n cdkDropList\n (cdkDropListEntered)=\"enterToTopRowGrouping($event)\"\n (cdkDropListExited)=\"exitedFromTheTopRow($event)\"\n (cdkDropListDropped)=\"onDropTopGroup($event)\"\n [cdkDropListEnterPredicate]=\"canEnterToRowsGrouping\"\n id=\"rows-grouping-top-container\"\n class=\"border-below d-flex px-4 align-items-center\"\n >\n <div\n class=\"d-flex gap-2 align-items-center\"\n [style.color]=\"headerTextColor\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <div *ngIf=\"!draggingInGroupArea && !groupedColumns?.length\">\n Drag here to set row groups\n </div>\n <div\n cdkDropListOrientation=\"horizontal\"\n cdkDropList\n (cdkDropListDropped)=\"onGroupReorder($event)\"\n class=\"d-flex\"\n >\n <div\n cdkDrag\n [cdkDragLockAxis]=\"'x'\"\n *ngFor=\"\n let child of groupedColumns;\n let i = index;\n trackBy: trackByField\n \"\n class=\"d-flex align-items-center\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: child,\n showChevron:\n groupedColumns.length > 1 && i != groupedColumns.length - 1\n }\n \"\n ></ng-container>\n <ng-template cdkDragPreview\n ><div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n *ngIf=\"!draggingInGroupArea\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ child.header }}</div>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n </div>\n <div\n class=\"d-flex overflow-hidden\"\n [style.height]=\"\n 'calc(100% - ' +\n (showRowsGrouping\n ? headerRowHeight + footerRowHeight\n : footerRowHeight) +\n 'px)'\n \"\n >\n <div\n class=\"h-100\"\n [style.width]=\"\n !showSideMenu\n ? '100%'\n : sideMenuVisible\n ? 'calc(100% - 280px)'\n : 'calc(100% - 30px)'\n \"\n >\n <div class=\"h-100 transition position-relative w-100\">\n <!-- ##################################################################################################################################################################################### -->\n <!-- ##################################################################################################################################################################################### -->\n <!-- Data Grid Header starts here -->\n <!-- ##################################################################################################################################################################################### -->\n <!-- ##################################################################################################################################################################################### -->\n <!-- [style.backgroundColor]=\"headerBackgroundColor\" -->\n <div\n class=\"data-grid-header-wrapper w-100\"\n [style.color]=\"headerTextColor\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n [style.fontSize.px]=\"headerTextFontsSize\"\n [class.border-below]=\"!hasAnyVisibleColumn\"\n [style.height.px]=\"\n showColumnsGrouping && showFilterRow\n ? headerRowHeight * 3\n : showColumnsGrouping || showFilterRow\n ? headerRowHeight * 2\n : headerRowHeight\n \"\n >\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <!-- Data Grid Left Pinned Header starts here -->\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <div\n class=\"data-grid-header left-pinned\"\n #leftPinnedHeader\n [class.border-right]=\"hasLeftPinnedColumns\">\n <div *ngIf=\"showSerialNumber\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n class=\"select-all-checkbox-cell border-below\"\n [style.width.px]=\"55\"\n [style.height.px]=\"\n showColumnsGrouping && showFilterRow\n ? headerRowHeight * 3\n : showColumnsGrouping || showFilterRow\n ? headerRowHeight * 2\n : headerRowHeight\n \"\n >\n S.No\n </div>\n <div *ngIf=\"showCheckboxes\"\n class=\"select-all-checkbox-cell border-below\"\n [style.height.px]=\"\n showColumnsGrouping && showFilterRow\n ? headerRowHeight * 3\n : showColumnsGrouping || showFilterRow\n ? headerRowHeight * 2\n : headerRowHeight\n \"\n >\n <input class=\"serialNoCheckbox\"\n *ngIf=\"hasAnyVisibleColumn\"\n style=\"width: 16px; height: 16px\"\n type=\"checkbox\"\n [indeterminate]=\"isIndeterminateState(dataSet)\"\n [checked]=\"isAllSelected(dataSet)\"\n (change)=\"toggleSelectAll(dataSet)\"\n />\n </div>\n <div\n [style.backgroundColor]=\"headerBackgroundColor\"\n class=\"d-flex\"\n cdkDropList\n id=\"left-pinned-header\"\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"leftPinnedColumns\"\n (cdkDropListEntered)=\"onDropListEnter($event, 'left')\"\n (cdkDropListSorted)=\"\n onSortGroup($event, 'previewLeftPinnedColumns')\n \"\n (cdkDropListDropped)=\"onDropGroup()\"\n style=\"min-width: 1px\"\n >\n <div\n class=\"dragable-header\"\n cdkDrag\n [cdkDragData]=\"col\"\n *ngFor=\"\n let col of leftPinnedColumns;\n let i = index;\n trackBy: trackByField\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n index: i,\n section: 'previewLeftPinnedColumns'\n }\n \"\n ></ng-container>\n <ng-template cdkDragPreview\n ><div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n *ngIf=\"!draggingInGroupArea\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/arrows-move.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ col.header }}</div>\n </div>\n </ng-template>\n <ng-template cdkDragPlaceholder>\n <div *ngIf=\"!draggingInGroupArea\">\n <div\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n index: i,\n section: ''\n }\n \"\n ></div>\n </div>\n <div\n *ngIf=\"draggingInGroupArea\"\n class=\"d-flex gap-2 ms-2\"\n style=\"opacity: 0.6\"\n >\n <ng-container\n *ngIf=\"col?.children?.length; else singleCol\"\n >\n <ng-container\n *ngFor=\"\n let child of col.children;\n let i = index;\n trackBy: trackByField\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: child,\n showChevron:\n col.children.length > 1 &&\n i != col.children.length - 1\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n\n <ng-template #singleCol>\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: col,\n showChevron: col?.children?.length > 1\n }\n \"\n ></ng-container>\n </ng-template>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <!-- Data Grid Center Pinned Header starts here -->\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <div\n class=\"data-grid-header center-scrollable\"\n #centerPinnedHeader\n (scroll)=\"onCenterBodyScroll($event)\"\n id=\"center-pinned-header\"\n cdkDropList\n [cdkDropListConnectedTo]=\"\n showRowsGrouping ? ['rows-grouping-top-container'] : []\n \"\n [cdkDropListData]=\"centerColumns\"\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListSortingDisabled]=\"\n isDisableColumnGrouping && draggingInGroupArea\n \"\n (cdkDropListEntered)=\"onDropListEnter($event, 'center')\"\n (cdkDropListSorted)=\"onSortGroup($event, 'previewCenterColumns')\"\n (cdkDropListDropped)=\"onDropGroup()\"\n [style.maxWidth]=\"\n 'calc(100% - ' +\n (rightPinnedHeader.offsetWidth + leftPinnedHeader.offsetWidth) +\n 'px)'\n \"\n >\n <div\n *ngIf=\"groupedColumns?.length\"\n style=\"min-width: 200px\"\n class=\"h-100 align-items-center\"\n #columnsGroupedBox\n id=\"groupBoxHeaderDiv\"\n >\n <div\n class=\"d-flex w-100 justify-content-between align-items-center border-below\"\n [style.height.px]=\"\n showFilterRow ? headerRowHeight * 2 : headerRowHeight\n \"\n >\n <div class=\"ps-3\">Group</div>\n <div class=\"d-flex\">\n <div\n class=\"three-dots cursor-pointer\"\n (click)=\"\n openThreeDotsMenu($event, 'group');\n isThreeDotsFilterOpen = false\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/three-dots-vertical.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div\n (mousedown)=\"\n $event.stopPropagation(); onResizeGroupBox($event)\n \"\n class=\"resize-handle\"\n style=\"margin-right: -2px\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n </div>\n\n <div\n [style.height.px]=\"headerRowHeight\"\n class=\"border-below\"\n ></div>\n </div>\n <span\n class=\"d-flex align-items-center justify-content-center cursor-pointer border-below\"\n style=\"min-width: 30px; height: 100%\"\n *ngIf=\"gridType === 'Assets' || gridType === 'Tasks'\"\n >\n </span>\n <div\n class=\"dragable-header\"\n (cdkDragStarted)=\"\n checkColumnGroupingStatus(col);\n dragStartOnGroup(col);\n onDragStarted(col)\n \"\n (cdkDragMoved)=\"onDragMoved($event)\"\n (cdkDragEnded)=\"onDragEnded()\"\n cdkDrag\n [cdkDragData]=\"col\"\n *ngFor=\"\n let col of centerColumns;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n index: i,\n section: 'previewCenterColumns'\n }\n \"\n >\n </ng-container>\n <ng-template cdkDragPreview\n ><div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n *ngIf=\"!isOutsideContainer\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n (draggingInGroupArea\n ? 'data-grid/icons/justify.svg'\n : 'data-grid/icons/arrows-move.svg')\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n >\n </span>\n <span\n *ngIf=\"isOutsideContainer\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/eye-cross.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n >\n </span>\n </div>\n <div>{{ col.header }}</div>\n </div>\n </ng-template>\n <ng-template cdkDragPlaceholder>\n <div *ngIf=\"!draggingInGroupArea\">\n <div\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n index: i,\n section: 'centerColumns'\n }\n \"\n ></div>\n </div>\n <div\n *ngIf=\"draggingInGroupArea && !isOutsideContainer\"\n class=\"d-flex gap-2 ms-2\"\n style=\"opacity: 0.6\"\n >\n <ng-container *ngIf=\"col?.children?.length; else singleCol\">\n <ng-container\n *ngFor=\"\n let child of col.children;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container *ngIf=\"child?.is_groupable\">\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: child,\n showChevron:\n col.children.length > 1 &&\n i != col.children.length - 1\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n\n <ng-template #singleCol>\n <ng-container *ngIf=\"col?.is_groupable\">\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: col,\n showChevron: col?.children?.length > 1\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-template>\n </div>\n </ng-template>\n </div>\n </div>\n\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <!-- Data Grid Right Pinned Header starts here -->\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <div\n [style.backgroundColor]=\"headerBackgroundColor\"\n cdkDropList\n id=\"right-pinned-header\"\n [cdkDropListConnectedTo]=\"\n showRowsGrouping ? ['rows-grouping-top-container'] : []\n \"\n cdkDropListOrientation=\"horizontal\"\n class=\"data-grid-header right-pinned\"\n (cdkDropListSorted)=\"\n onSortGroup($event, 'previewRightPinnedColumns')\n \"\n (cdkDropListEntered)=\"onDropListEnter($event, 'right')\"\n (cdkDropListDropped)=\"onDropGroup()\"\n #rightPinnedHeader\n class=\"right-pinned-header d-flex\"\n style=\"min-width: 0.2px\"\n >\n <div\n class=\"dragable-header\"\n cdkDrag\n [cdkDragData]=\"col\"\n *ngFor=\"\n let col of rightPinnedColumns;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n pinnedRight: true,\n index: i,\n section: 'right'\n }\n \"\n ></ng-container>\n <ng-template cdkDragPreview\n ><div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n *ngIf=\"!draggingInGroupArea\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/arrows-move.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ col.header }}</div>\n </div>\n </ng-template>\n <ng-template cdkDragPlaceholder>\n <div *ngIf=\"!draggingInGroupArea\">\n <div\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n index: i,\n section: 'right'\n }\n \"\n ></div>\n </div>\n <div\n *ngIf=\"draggingInGroupArea\"\n class=\"d-flex gap-2 ms-2\"\n style=\"opacity: 0.6\"\n >\n <ng-container *ngIf=\"col?.children?.length; else singleCol\">\n <ng-container\n *ngFor=\"\n let child of col.children;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: child,\n showChevron:\n col.children.length > 1 &&\n i != col.children.length - 1\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n\n <ng-template #singleCol>\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: col,\n showChevron: col?.children?.length > 1\n }\n \"\n ></ng-container>\n </ng-template>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n\n <!--########################################################################################################################################################################################################################### -->\n <!--########################################################################################################################################################################################################################### -->\n <!-- Data Grid Body starts here -->\n <!--########################################################################################################################################################################################################################### -->\n <!--########################################################################################################################################################################################################################### -->\n <div\n class=\"h-100 d-flex justify-content-center align-items-center\"\n *ngIf=\"!dataSet?.length && !loading && !dataSetLoading\">\n <!-- <div\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/record-not-found.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></div> -->\n <div class=\"d-flex flex-column justify-content-center align-items-center\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/no-data-image.svg'\"\n class=\"data-grid-svg-icon mb-3 d-flex justify-content-center align-items-center\">\n </span>\n <p class=\"text_common_16px mb-0\">No data available</p>\n <p class=\"page_refresh mb-0\">Try adjusting filters or refresh the page</p>\n </div>\n </div>\n\n <div\n class=\"position-absolute w-100 h-100 d-flex justify-content-center align-items-center loading-overlay\"\n *ngIf=\"loading || dataSetLoading\"\n style=\"\n z-index: 999;\n backdrop-filter: blur(1px);\n \"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n >\n <div class=\"spinner-border text-primary\" role=\"status\">\n <!-- <span class=\"loader\"></span> -->\n <!-- <span class=\"visually-hidden\">Loading...</span> -->\n <!-- </div> -->\n </div>\n </div>\n\n <div\n class=\"data-grid-body-wrapper position-relative d-flex\"\n [style.height]=\"bodyWrapperHeight\"\n style=\"overflow-y: auto; overflow-x: hidden\"\n #mainScroll\n (scroll)=\"onMainScroll($event)\"\n [style.scrollbarWidth]=\"verticalScrollbarWidth\"\n >\n <!-- LEFT PINNED -->\n <div\n [style.height.px]=\"\n !groupedColumns.length ? originalDataSet.length * rowHeight : 0\n \"\n ></div>\n <!-- [class.transparent-border-right]=\"!hasLeftPinnedColumns\" -->\n <div [class.h-100]=\"originalDataSet.length < 8\">\n <div\n class=\"data-grid-body left-pinned-body w-100\"\n style=\"overflow-y: hidden\"\n [class.border-right]=\"hasLeftPinnedColumns\"\n [class.transparent-border-right]=\"!hasLeftPinnedColumns\"\n [style.boxShadow]=\"leftPinnedBoxshadow\"\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\n [style.backgroundColor]=\"leftPinnedBackgroundColor\"\n [class.h-100]=\"originalDataSet.length < 8\"\n *ngIf=\"!loading && !dataSetLoading\"\n [@rowDynamic]=\"rowAnimation\"\n\n \n >\n <ng-container\n *ngFor=\"\n let row of visibleRows;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: row,\n columns: previewLeftPinnedColumns,\n isEven: (startIndex + i) % 2 === 0,\n isOdd: (startIndex + i) % 2 !== 0,\n isLeft: true,\n section: 'left',\n isTotalRow: false\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: { __virtualIndex: 0 },\n columns: previewLeftPinnedColumns,\n isEven: false,\n isOdd: false,\n section: 'left',\n isTotalRow: true\n }\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n\n <!-- CENTER -->\n <div\n class=\"h-100\"\n [style.width.px]=\"centerPinnedHeader.clientWidth\"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n >\n <div\n class=\"data-grid-body center-scrollable\"\n [class.h-100]=\"originalDataSet.length < 8\"\n style=\"overflow-y: hidden; overflow-x: auto\"\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n #centerScrollableBody\n (scroll)=\"onCenterBodyScroll($event)\"\n [style.boxShadow]=\"leftPinnedBoxshadow\"\n \n >\n <div [@rowDynamic]=\"rowAnimation\" *ngIf=\"!loading && !dataSetLoading\">\n <ng-container\n *ngFor=\"\n let row of visibleRows;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: row,\n columns: previewCenterColumns,\n isEven: (startIndex + i) % 2 === 0,\n isOdd: (startIndex + i) % 2 !== 0,\n section: 'center',\n isTotalRow: false\n }\n \"\n ></ng-container>\n </ng-container>\n </div>\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: { __virtualIndex: 0 },\n columns: previewCenterColumns,\n isEven: false,\n isOdd: false,\n section: 'center',\n isTotalRow: true\n }\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n\n <!-- RIGHT PINNED -->\n <div\n class=\"right-pinned-body-wrapper\"\n *ngIf=\"true\"\n [class.h-100]=\"originalDataSet.length < 8\"\n [style.maxWidth.px]=\"\n isScrollbarVisible\n ? rightPinnedHeader.offsetWidth - 15\n : rightPinnedHeader.offsetWidth\n \"\n [style.backgroundColor]=\"rightPinnedBackgroundColor\"\n [@rowDynamic]=\"rowAnimation\"\n >\n <div\n class=\"data-grid-body right-pinned-body w-100 h-100\"\n style=\"overflow-y: hidden\"\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\n [style.boxShadow]=\"rightPinnedBoxshadow\"\n [style.backgroundColor]=\"rightPinnedBackgroundColor\"\n *ngIf=\"!loading && !dataSetLoading && hasRightPinnedColumns\"\n >\n <ng-container\n *ngFor=\"\n let row of visibleRows;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: row,\n columns: previewRightPinnedColumns,\n isEven: (startIndex + i) % 2 === 0,\n isOdd: (startIndex + i) % 2 !== 0,\n section: 'right',\n isTotalRow: false\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: { __virtualIndex: 0 },\n columns: previewRightPinnedColumns,\n isEven: false,\n isOdd: false,\n section: 'right',\n isTotalRow: true\n }\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n\n <div\n style=\"top: auto; left: auto\"\n (click)=\"\n $event.stopPropagation();\n fullscreenImage = null;\n cdr.detectChanges()\n \"\n [style.width.px]=\"dataGridContainer.offsetWidth\"\n [style.height.px]=\"\n dataGridContainer.offsetHeight - (footerRowHeight + 100)\n \"\n class=\"image-modal full-image-modal\"\n *ngIf=\"fullscreenImage\"\n >\n <img\n (click)=\"$event.stopPropagation()\"\n [src]=\"fullscreenImage\"\n alt=\"Fullscreen Image\"\n />\n </div>\n <div\n *ngIf=\"selectedRows.size > 0 && showTaskbar\"\n class=\"taskbar w-100\"\n [style.bottom.px]=\"85\"\n >\n <div class=\"selected-rows-action-bar\" [@slideUp]>\n <span class=\"selected-count\">\n {{ selectedRows.size }} selected of\n {{\n paginationConfig.totalResults ||\n config?.paginationParams?.totalItems\n }}\n Total\n </span>\n <div class=\"action-buttons d-flex align-items-center\">\n <ng-container\n *ngFor=\"let action of taskbarActions; let i = index\"\n >\n <ng-container *ngIf=\"action?.has_permission\">\n <span\n class=\"action-btn verified btn {{ action }}\"\n (click)=\"onVerifyClick(action?.actionName)\"\n >{{ action?.actionName }}</span\n >\n <span\n *ngIf=\"\n taskbarActions.length > 1 &&\n i !== taskbarActions.length - 1 &&\n taskbarActions[i + 1]?.has_permission\n \"\n class=\"\"\n >|</span\n >\n </ng-container>\n </ng-container>\n <button (click)=\"clearSelectionState(tableType);selectedRows.clear();\" class=\"clear-btn ms-2 mt-2\">\n <i class=\"bi bi-x-circle\"></i> Clear Selection\n </button>\n </div>\n </div>\n </div>\n </div>\n <!-- Vertical Fake scroll Bar -->\n <!-- <div\n (scroll)=\"onMainFakeScroll($event)\"\n class=\"fake-scrollbar fake-scrollbar-vertical d-none\"\n [style.scrollbarWidth]=\"verticalScrollbarWidth\"\n [style.top.px]=\"\n showColumnsGrouping && showFilterRow\n ? headerRowHeight * 3\n : showColumnsGrouping || showFilterRow\n ? headerRowHeight * 2\n : headerRowHeight\n \"\n #fakeScroll\n [style.height]=\"bodyWrapperHeight\"\n style=\"\n overflow-y: auto;\n overflow-x: hidden;\n width: 17px;\n position: absolute;\n right: 0;\n background-color: f1f2f3;\n z-index: 10;\n \"\n >\n <div [style.height.px]=\"rowHeight * dataSetLength\"></div>\n </div> -->\n </div>\n\n <!-- Horizintal Fake Scrollbars -->\n <div\n class=\"d-flex justify-content-between\"\n *ngIf=\"hasScroll\"\n >\n <div\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\n class=\"fake-horizintal-scrollbar\"\n #fakeScroll\n [style.width.px]=\"leftPinnedHeader.offsetWidth\"\n style=\"overflow-x: scroll\"\n ></div>\n <div\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\n (scroll)=\"onCenterBodyScroll($event)\"\n class=\"fake-horizintal-scrollbar\"\n #horizintalFakeScroll\n [style.width.px]=\"centerPinnedHeader.offsetWidth\"\n >\n <div [style.width.px]=\"centerPinnedHeader.scrollWidth - 10\"></div>\n </div>\n <div\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\n class=\"fake-horizintal-scrollbar\"\n #fakeScroll\n [style.width.px]=\"rightPinnedHeader.offsetWidth\"\n style=\"overflow-x: scroll\"\n ></div>\n </div>\n </div>\n\n <!-- Side Menu Implemented Here -->\n <div\n *ngIf=\"showSideMenu\"\n [style.width.px]=\"sideMenuVisible ? 280 : 30\"\n class=\"right-menu h-100\"\n [style.backgroundColor]=\"sidemenuBackgroundColor\"\n >\n <div class=\"h-100 d-flex flex-row-reverse\">\n <div\n style=\"width: 30px\"\n class=\"d-flex flex-column align-items-center cursor-pointer\"\n [class.border-start]=\"sideMenuVisible\"\n >\n <div\n (click)=\"toggleSideMenu('cols')\"\n [class.bg-fff]=\"\n currentOpenedSideMenue == 'cols' && sideMenuVisible\n \"\n [class.border-below]=\"sideMenuVisible\"\n class=\"columns-button d-flex flex-column align-items-center\"\n >\n <div>\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/ui-checks-grid.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div class=\"side-menue-text\">Columns</div>\n </div>\n\n <div\n (click)=\"toggleSideMenu('filtrs')\"\n [class.bg-fff]=\"\n currentOpenedSideMenue == 'filtrs' && sideMenuVisible\n \"\n [class.border-below]=\"\n sideMenuVisible && currentOpenedSideMenue == 'filtrs'\n \"\n class=\"columns-button d-flex flex-column align-items-center\"\n >\n <div>\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div class=\"side-menue-text\">Filter</div>\n </div>\n </div>\n <div\n class=\"h-100\"\n *ngIf=\"sideMenuVisible\"\n [ngStyle]=\"{ width: sideMenuVisible ? '250px' : '' }\"\n >\n <div class=\"h-100\">\n <ng-container\n *ngIf=\"currentOpenedSideMenue == 'cols' && sideMenuVisible\"\n >\n <ng-container *ngTemplateOutlet=\"columnPannel\"></ng-container>\n <!-- Column Items -->\n <div class=\"column-panel-body px-3\">\n <ng-container\n *ngFor=\"let col of columns; trackBy: trackByField\"\n >\n <ng-container\n *ngTemplateOutlet=\"columnPanelItem; context: { col: col }\"\n ></ng-container>\n </ng-container>\n </div>\n <hr />\n\n <div class=\"side-menu-row-groups\" style=\"height: 30%\">\n <ng-container\n *ngTemplateOutlet=\"sideMenuRowGroups\"\n ></ng-container>\n </div>\n </ng-container>\n <ng-container\n *ngIf=\"currentOpenedSideMenue == 'filtrs' && sideMenuVisible\"\n >\n <ng-container *ngTemplateOutlet=\"sideFilters\"></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div\n [style.height.px]=\"footerRowHeight\"\n class=\"border-top\"\n [style.backgroundColor]=\"footerRowBackgroundColor\"\n >\n <!-- Rows: <span class=\"fw-500 ms-1\">{{ dataSet.length }}</span> -->\n\n <div class=\"pagination-container\"\n [style.height.px]=\"footerRowHeight\"\n [style.padding.px]=\"footerPadding\">\n <div class=\"page-size\">\n <select\n [(ngModel)]=\"paginationConfig.limit\"\n (change)=\"onPageSizeChange()\"\n >\n <option *ngFor=\"let size of pageSizeOptions\" [value]=\"size\">\n {{ size }}\n </option>\n </select>\n <span class=\"separator\"> per page </span>\n </div>\n\n <div class=\"page-info\">\n \n {{ (paginationConfig.page - 1) * paginationConfig.limit + 1 }}-{{\n paginationConfig.page * paginationConfig.limit <\n paginationConfig.totalResults\n ? paginationConfig.page * paginationConfig.limit\n : paginationConfig.totalResults\n }}\n of\n {{ paginationConfig.totalResults }}\n results\n </div>\n\n <div class=\"page-buttons\">\n <button\n (click)=\"goToPage(paginationConfig.page - 1)\"\n [disabled]=\"paginationConfig.page === 1\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/chevron-left.svg'\"\n class=\"d-flex justify-content-center align-items-center\"\n ></span>\n </button>\n\n <ng-container *ngFor=\"let page of visiblePages\">\n <button\n *ngIf=\"page !== '...'\"\n (click)=\"goToPage(page)\"\n [class.active]=\"page === paginationConfig.page\"\n >\n {{ page }}\n </button>\n <span *ngIf=\"page === '...'\">...</span>\n </ng-container>\n\n <button\n (click)=\"goToPage(paginationConfig.page + 1)\"\n [disabled]=\"paginationConfig.page === paginationConfig.totalResults\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\"\n class=\"d-flex justify-content-center align-items-center\"\n ></span>\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\n<!-- Header Cell Template -->\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\n\n<ng-template\n #headerCell\n let-col\n let-pinnedRight=\"pinnedRight\"\n let-i=\"index\"\n let-sections=\"section\"\n let-calledFromNestedPlaceholder=\"calledFromNestedPlaceholder\"\n>\n <div>\n <!-- Group Header -->\n <ng-container *ngIf=\"col.children?.length > 0; else flatHeader\">\n <div cdkDroplistGroup class=\"group-column-wrapper\">\n <!-- Parent Header -->\n <div\n *ngIf=\"shouldTheGroupHeaderShow(col)\"\n class=\"header-cell group-header\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n [class.border-right]=\"showVerticalBorder\"\n [style.gridColumn]=\"'span ' + col.children.length\"\n [style.fontWeight]=\"headerFontWeight\"\n [class.flex-row-reverse]=\"pinnedRight\"\n [class.justify-content-end]=\"pinnedRight\"\n style=\"grid-row: 1\"\n >\n <div\n class=\"group-header-content\"\n [title]=\"col.header\"\n [class.ms-2]=\"pinnedRight\"\n >\n {{ col.header }}\n </div>\n <div\n class=\"resize-handle\"\n (dblclick)=\"autosizeColumn(col.children)\"\n (mousedown)=\"\n $event.stopPropagation(); onResizeGroup($event, col, pinnedRight)\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n\n <!-- Child Headers and Filters -->\n\n <div\n class=\"d-flex\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"col.children\"\n (cdkDropListSorted)=\"onChildDroplistSorted($event, sections)\"\n (cdkDropListDropped)=\"onChildDroplistDroped($event)\"\n [cdkDropListSortingDisabled]=\"false\"\n [cdkDropListConnectedTo]=\"\n showRowsGrouping ? ['rows-grouping-top-container'] : []\n \"\n >\n <div\n cdkDrag\n [cdkDragData]=\"child\"\n *ngFor=\"let child of col.children; let i = index\"\n >\n <!-- Child Header -->\n <ng-container *ngIf=\"child.is_visible && !child['isRowGrouped']\">\n <div\n cdkDragHandle\n class=\"header-cell one-row-header-cells cursor-pointer\"\n [class.border-right]=\"showVerticalBorder\"\n [attr.field]=\"child.field\"\n [style.width.px]=\"child.width\"\n [style.min-width.px]=\"child.width\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n [style.fontWeight]=\"headerFontWeight\"\n style=\"grid-row: 2\"\n [class.filter-applied-on-text]=\"isFilterAppliedOnColumn(child)\"\n >\n <div\n class=\"d-flex justify-content-between h-100 align-items-center w-100\"\n >\n <div\n class=\"d-flex justify-content-between align-items-center w-100\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div\n class=\"text-ellipsis h-100 d-flex align-items-center w-100\"\n [title]=\"col.header\"\n [class.w-100]=\"pinnedRight\"\n >\n <div\n class=\"text-ellipsis h-100\"\n [class.editable-header]=\"child?.is_editable\"\n (click)=\"\n openThreeDotsMenu($event, child);\n openFilteronThreeDotsClick(child)\n \"\n >\n {{ child.header }}\n </div>\n </div>\n\n <div\n class=\"position-relative d-flex\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div\n [class.me-2]=\"pinnedRight\"\n class=\"d-flex align-items-center\"\n *ngIf=\"child.pinned\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/pin.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div\n class=\"three-dots p-1 zaid-test\"\n (click)=\"\n openThreeDotsMenu($event, child);\n isThreeDotsFilterOpen = false\n \"\n style=\"cursor: pointer\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/three-dots-vertical.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n\n <!-- Only show menu if this column is active -->\n <div\n class=\"position-absolute\"\n *ngIf=\"activeCol === child\"\n style=\"top: -50%; z-index: 21\"\n [style.left.px]=\"\n -(!child?.pinned ? centerPinnedHeader.scrollLeft : 0)\n \"\n [style.top.px]=\"\n isThreeDotsFilterOpen\n ? showFilterRow || showColumnsGrouping\n ? headerRowHeight * 2 - 10\n : headerRowHeight - 10\n : 0\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n columnMenu;\n context: {\n col: child,\n isNestedTable: false,\n section: sections\n }\n \"\n ></ng-container>\n </div>\n\n <div\n class=\"resize-handle\"\n (dblclick)=\"autosizeColumn(child)\"\n (mousedown)=\"\n $event.stopPropagation();\n onResizeColumn($event, child)\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Filter Cell -->\n <div\n *ngIf=\"showFilterRow\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n class=\"header-cell filter-cell\"\n [class.border-right]=\"showVerticalBorder\"\n [attr.field]=\"child.field\"\n [style.width.px]=\"child.width\"\n [style.min-width.px]=\"child.width\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n [class.border-right]=\"showVerticalBorder\"\n style=\"grid-row: 3\"\n >\n <div\n class=\"header-cell filter-cell\"\n [attr.field]=\"col.field\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n >\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Filter\"\n [(ngModel)]=\"child.filterValue\"\n (ngModelChange)=\"onFilterChange(child)\"\n (paste)=\"onFilterChange(child); applyDropdownFilter()\"\n [readonly]=\"\n child?.type == 'dropdown' || child?.type == 'image'\n \"\n [class.disabled-search-input]=\"\n child?.type == 'dropdown' || child?.type == 'image'\n \"\n (click)=\"\n $event.stopPropagation();\n openFilterFromDisabledSearchedInput(child)\n \"\n (keydown.enter)=\"applyDropdownFilter()\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n <span\n class=\"filter-icon-wrapper\"\n (click)=\"$event.stopPropagation(); openFilter(child)\"\n [class.filter-applied]=\"isFilterAppliedOnColumn(child)\"\n [class.pe-none]=\"child?.type == 'image'\"\n ><span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <span\n *ngIf=\"isFilterAppliedOnColumn(child)\"\n style=\"\n width: 7px;\n height: 7px;\n box-shadow: 0px 0px 3px #7486ff;\n background-color: rgb(0 163 233);\n position: absolute;\n right: 4px;\n top: 12px;\n \"\n class=\"rounded-circle d-block\"\n ></span\n ></span>\n\n <div\n class=\"position-absolute filter-row-filter-wrapper\"\n *ngIf=\"activeFilterCell?.field == child?.field\"\n style=\"top: 100%; right: 0; z-index: 99\"\n [style.left.px]=\"\n child?.pinned ? 0 : -centerPinnedHeader.scrollLeft\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"filterMenu; context: { col: child }\"\n ></ng-container>\n </div>\n </div>\n </div>\n </ng-container>\n <ng-template cdkDragPreview\n ><div class=\"p-2 border d-flex gap-2\">\n <div\n *ngIf=\"\n !draggingInGroupArea ||\n (child.is_groupable && draggingInGroupArea)\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div *ngIf=\"draggingInGroupArea && !child.is_groupable\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/ban.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ child.header }}</div>\n </div>\n </ng-template>\n <ng-template cdkDragPlaceholder>\n <div *ngIf=\"!draggingInGroupArea\" class=\"position-relative\">\n <div\n *ngTemplateOutlet=\"\n childHeaderPlaceholder;\n context: {\n $implicit: child,\n index: i,\n sections: sections,\n calledFromNestedPlaceholder: true,\n }\n \"\n ></div>\n </div>\n <div\n *ngIf=\"draggingInGroupArea && child?.is_groupable\"\n class=\"d-flex gap-2 ms-2\"\n style=\"opacity: 0.6\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: child,\n showChevron: false,\n pinnedRight: pinnedRight,\n sections: sections,\n index: i\n }\n \"\n ></ng-container>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n </ng-container>\n\n <!-- Flat Header || Single Header Cell-->\n <ng-template #flatHeader>\n <div\n class=\"group-column-wrapper\"\n *ngIf=\"col.is_visible && !col['isRowGrouped']\"\n >\n <!-- Full-height Header Cell (spans 2 rows visually) -->\n <div\n class=\"header-cell one-row-header-cells\"\n [attr.field]=\"col.field\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [class.border-right]=\"showVerticalBorder\"\n [style.min-height.px]=\"\n showColumnsGrouping ? headerRowHeight * 2 : headerRowHeight\n \"\n [style.height.px]=\"\n showColumnsGrouping ? headerRowHeight * 2 : headerRowHeight\n \"\n [style.fontWeight]=\"headerFontWeight\"\n style=\"grid-row: 1 / span 2\"\n >\n <div\n class=\"d-flex justify-content-between h-100 align-items-center w-100\"\n >\n <div\n class=\"d-flex justify-content-between w-100 align-items-center\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div\n class=\"text-ellipsis h-100 d-flex align-items-center w-100\"\n [title]=\"col.header\"\n >\n <div\n class=\"text-ellipsis h-100 cursor-pointer\"\n [class.editable-header]=\"col?.is_editable\"\n [class.filter-applied-on-text]=\"isFilterAppliedOnColumn(col)\"\n (click)=\"\n openThreeDotsMenu($event, col);\n openFilteronThreeDotsClick(col)\n \"\n >\n {{ col.header }}\n </div>\n </div>\n\n <div\n class=\"position-relative d-flex align-items-center\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div\n [class.me-2]=\"pinnedRight\" [class.threeDotActive]=\"activeCol === col && !clickedOnSortIcon\"\n class=\"d-flex align-items-center three-dots\"\n *ngIf=\"col?.pinned\">\n <span (click)=\"\n openThreeDotsMenu($event, col, false);\n isThreeDotsFilterOpen = false\n \"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/pin.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown d-flex justify-content-center align-items-center pin_blue_icon\"\n ></span>\n </div>\n <!-- <div\n [class.me-2]=\"col.order_by\"\n class=\"d-flex align-items-center\"\n *ngIf=\"sortingConfig?.field == col.field\">\n <span\n *ngIf=\"sortingConfig?.order_by == 'asc'\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/selectedAscIcon.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center mt-1 cursor-pointer\"\n (click)=\"sortDesc(col)\"\n [class.active]=\"sortingConfig?.order_by === 'asc'\"\n ></span>\n <span\n *ngIf=\"sortingConfig?.order_by == 'desc'\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/selectedAscIcon.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center mt-1 cursor-pointer\"\n (click)=\"sortAsc(col)\"\n [class.active]=\"sortingConfig?.order_by === 'desc'\"\n ></span>\n </div> -->\n <div class=\"three-dots p-1 me-0 zaid-test1\" [class.threeDotActive]=\"activeCol === col && clickedOnSortIcon\"\n (click)=\"openThreeDotsMenu($event, col, true);\"\n style=\"cursor: pointer\">\n <div *ngIf=\"sortingConfig?.field === col.field\" \n class=\"d-flex align-items-center\">\n \n <!-- Ascending Sort Icon -->\n <span\n *ngIf=\"sortingConfig?.order_by == 'asc'\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/sort-ascending-green.svg'\"\n class=\"data-grid-svg-icon ascendingAppliedIcon flex justify-content-center align-items-center cursor-pointer\"\n (click)=\"openThreeDotsMenu($event, col, true)\"\n [class.active]=\"sortingConfig?.order_by === 'asc'\">\n </span>\n\n <!-- Descending Sort Icon -->\n <span\n *ngIf=\"sortingConfig?.order_by == 'desc'\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/sort-ascending-green.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center cursor-pointer rotated-180\"\n (click)=\"openThreeDotsMenu($event, col, true)\"\n [class.active]=\"sortingConfig?.order_by === 'desc'\">\n </span>\n </div>\n <span *ngIf=\"sortingConfig?.field !== col.field\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/sortIconGray.svg'\"\n class=\"data-grid-svg-icon figmaIconSize d-flex justify-content-center align-items-center\"\n (click)=\"openThreeDotsMenu($event, col, true)\">\n </span>\n </div>\n <div class=\"three-dots p-1 zaid-test1\" [class.threeDotActive]=\"activeCol === col && !clickedOnSortIcon\" *ngIf=\"!col?.pinned\"\n (click)=\"\n openThreeDotsMenu($event, col, false);\n isThreeDotsFilterOpen = false\n \"\n style=\"cursor: pointer\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/three-dots-vertical.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown dropdown d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n\n <!-- Only show menu if this column is active -->\n <div\n class=\"position-absolute\"\n *ngIf=\"activeCol === col\"\n style=\"z-index: 21\"\n [style.left.px]=\"\n -(!col?.pinned ? centerPinnedHeader.scrollLeft : 0)\n \"\n [style.top.px]=\"\n isThreeDotsFilterOpen\n ? showFilterRow || showColumnsGrouping\n ? headerRowHeight * 2 - 10\n : headerRowHeight - 10\n : 25\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n columnMenu;\n context: {\n col: col,\n isNestedTable: false,\n section: sections\n }\n \"\n ></ng-container>\n </div>\n\n <div\n class=\"resize-handle\"\n [class.w-100]=\"col.pinned == 'right'\"\n (dblclick)=\"autosizeColumn(col)\"\n (mousedown)=\"\n $event.stopPropagation(); onResizeColumn($event, col)\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Filter Cell -->\n <div\n *ngIf=\"showFilterRow\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n class=\"header-cell filter-cell\"\n [class.border-right]=\"showVerticalBorder\"\n [attr.field]=\"col.field\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n >\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Filter\"\n [(ngModel)]=\"col.filterValue\"\n (ngModelChange)=\"onFilterChange(col)\"\n [readonly]=\"col?.type == 'dropdown' || col?.type == 'image'\"\n [class.disabled-search-input]=\"\n col?.type == 'dropdown' || col?.type == 'image'\n \"\n (paste)=\"onPasteInFilterRowSearch($event, col)\"\n (click)=\"\n $event.stopPropagation(); openFilterFromDisabledSearchedInput(col)\n \"\n (keydown.enter)=\"applyDropdownFilter()\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n <span\n class=\"filter-icon-wrapper\"\n (click)=\"$event.stopPropagation(); openFilter(col)\"\n [class.filter-applied]=\"isFilterAppliedOnColumn(col)\"\n [class.pe-none]=\"col?.type == 'image'\"\n ><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <span\n *ngIf=\"isFilterAppliedOnColumn(col)\"\n style=\"\n width: 7px;\n height: 7px;\n box-shadow: 0px 0px 3px #7486ff;\n background-color: rgb(0 163 233);\n position: absolute;\n right: 4px;\n top: 12px;\n \"\n class=\"rounded-circle d-block\"\n ></span\n ></span>\n\n <div\n class=\"position-absolute filter-row-filter-wrapper\"\n *ngIf=\"activeFilterCell === col\"\n style=\"top: 100%; right: 0; z-index: 99\"\n [style.left.px]=\"col?.pinned ? 0 : -centerPinnedHeader.scrollLeft\"\n >\n <ng-container\n *ngTemplateOutlet=\"filterMenu; context: { col: col }\"\n ></ng-container>\n </div>\n </div>\n </div>\n </ng-template>\n </div>\n</ng-template>\n\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\n<!-- Body Cell Template -->\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\n\n<ng-template\n #rowCell\n let-row\n let-columns=\"columns\"\n let-isEven=\"isEven\"\n let-isOdd=\"isOdd\"\n let-isLeftSection=\"isLeft\"\n let-section=\"section\"\n let-rowIndex=\"rowIndex\"\n let-isTotalRow=\"isTotalRow\"\n>\n <!-- Check if row is a group -->\n <ng-container\n *ngTemplateOutlet=\"groupRowTemplate; context: { $implicit: row, depth: 0 }\"\n ></ng-container>\n <ng-template #groupRowTemplate let-row let-depth=\"depth\">\n <ng-container *ngIf=\"row.isGroup; else regularRow\">\n <!-- Group Header -->\n <div\n class=\"group-header-row d-flex align-items-center\"\n [style.height.px]=\"rowHeight\"\n [class.border-below]=\"section !== 'center'\"\n [style.width]=\"\n section === 'center'\n ? (centerScrollableBody?.scrollWidth ?? 0) + 'px'\n : '100%'\n \"\n >\n <div\n *ngIf=\"section == 'left'\"\n class=\"h-100 d-flex\"\n [style.width.px]=\"leftPinnedHeader.offsetWidth - 1\"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n >\n <div\n *ngIf=\"showSerialNumber\"\n style=\"width: 50px\"\n class=\"d-flex align-items-center h-100 border-right justify-content-end pe-2 s-no\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n [style.width.px]=\"55\"\n [style.cursor]=\"\n 'url(' +\n singleSpaAssetsPath +\n 'data-grid/icons/arrow-right.svg), auto'\n \"\n (mousedown)=\"onRowMouseDown(row.__virtualIndex, $event)\"\n (mouseover)=\"onRowMouseOver(row.__virtualIndex, $event)\"\n [style.color]=\"checkboxesColor\"\n >\n {{ getStartIndex() + (row.__virtualIndex - 1) || \"\" }}\n </div>\n <div\n *ngIf=\"showCheckboxes\"\n style=\"width: 50px\"\n class=\"d-flex align-items-center justify-content-center h-100 border-right\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.left-selection-border]=\"\n rowSelectedIndexes.has(row.__virtualIndex)\n \"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n [style.color]=\"checkboxesColor\"\n >\n <input\n style=\"width: 16px; height: 16px\"\n type=\"checkbox\"\n [checked]=\"getGroupCheckedState(row) === true\"\n [indeterminate]=\"getGroupCheckedState(row) === undefined\"\n (change)=\"selectGroupRow($event, row)\"\n />\n\n </div>\n </div>\n\n <div\n *ngIf=\"section == 'center'\"\n [style.width.px]=\"centerPinnedHeader.scrollWidth\"\n [style.minWidth.px]=\"centerPinnedHeader.scrollWidth\"\n class=\"d-flex align-items-center ps-2 h-100 border-below\"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n >\n <div\n class=\"d-flex align-items-center justify-content-between\"\n [style.paddingLeft.px]=\"depth > 0 ? depth * 30 : 0\"\n >\n <span class=\"me-2 filter-icon-wrapper\" (click)=\"toggleExpand(row)\">\n <span\n class=\"data-grid-svg-icon align-items-center d-flex\"\n [inlineSVG]=\"\n row.isExpand\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n ></span>\n </span>\n <strong (click)=\"toggleExpand(row)\" class=\"cursor-pointer\">\n {{ row.groupValue }} ({{ countLeafRows(row) }})\n </strong>\n </div>\n </div>\n\n <div\n *ngIf=\"section == 'right'\"\n [style.width.px]=\"rightPinnedHeader.offsetWidth\"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n ></div>\n </div>\n\n <!-- Recursive Children -->\n <div class=\"group-children\" *ngIf=\"row.isExpand\" [@slideToggle]>\n <ng-container\n *ngFor=\"let child of row.children; let i = index; trackBy: trackById\"\n >\n <ng-container *ngIf=\"child.isGroup; else dataRow\">\n <!-- Recursive call for nested group -->\n <ng-container\n *ngTemplateOutlet=\"\n groupRowTemplate;\n context: { $implicit: child, depth: depth + 1 }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template #dataRow>\n <!-- Regular data row -->\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: child,\n columns: columns,\n isEven: i % 2 === 0,\n isOdd: i % 2 !== 0,\n isLeft: isLeftSection,\n section: section,\n isTotalRow: isTotalRow\n }\n \"\n ></ng-container>\n </ng-template>\n </ng-container>\n </div>\n </ng-container>\n </ng-template>\n\n <!-- Regular row (not a group) -->\n <ng-template #regularRow>\n <div\n class=\"d-flex\"\n [style.height.px]=\"rowHeight\"\n [style.minHeight.px]=\"rowHeight\"\n [style.maxHeight.px]=\"rowHeight\"\n >\n <span\n class=\"d-flex align-items-center justify-content-center cursor-pointer border-below\"\n style=\"min-width: 30px; height: 100%\"\n *ngIf=\"\n section == 'center' && (gridType === 'Assets' || gridType === 'Tasks')\n \"\n [ngStyle]=\"{\n 'background-color': rowSelectedIndexes.has(row.__virtualIndex)\n ? null\n : getBackgroundColor(row, isEven, section)\n }\"\n [class.selected-cell]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n >\n <span\n (click)=\"toggleDetailRowExpand(row)\"\n *ngIf=\"row?.detail?.result?.length || gridType === 'Tasks'\"\n class=\"data-grid-svg-icon filter-icon-wrapper\"\n [inlineSVG]=\"\n isDetailsExpanded(row)\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n ></span>\n </span>\n <div\n [style.min-width.px]=\"\n section == 'center' && groupedColumns?.length ? groupBoxPadding : 0\n \"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n (contextmenu)=\"onRightClick($event, row)\"\n [style.height.px]=\"rowHeight\"\n class=\"data-grid-row h-100\"\n [class.even-row]=\"isEven\"\n [class.odd-row]=\"isOdd\"\n [class.hovered-row]=\"hoveredRowId === (row._id || row.id)\"\n (mouseenter)=\"onRowHover(row)\"\n (mouseleave)=\"onRowLeave()\"\n [ngStyle]=\"{\n 'background-color': getBackgroundColor(row, isEven, section)\n }\"\n [style.minHeight.px]=\"rowHeight\"\n [style.maxHeight.px]=\"rowHeight\"\n ></div>\n <div\n (contextmenu)=\"onRightClick($event, row)\"\n [style.height.px]=\"rowHeight\"\n class=\"data-grid-row\"\n [class.even-row]=\"isEven\"\n [class.odd-row]=\"isOdd\"\n [class.hovered-row]=\"hoveredRowId === (row._id || row.id)\"\n (mouseenter)=\"onRowHover(row)\"\n (mouseleave)=\"onRowLeave()\"\n [ngStyle]=\"{\n 'background-color': getBackgroundColor(row, isEven, section)\n }\"\n >\n <div\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n class=\"select-all-checkbox-cell justify-content-end pe-2 s-no\"\n [style.width.px]=\"55\"\n *ngIf=\"isLeftSection && showSerialNumber\"\n [style.cursor]=\"\n 'url(' +\n singleSpaAssetsPath +\n 'data-grid/icons/arrow-right.svg), auto'\n \"\n (mousedown)=\"onRowMouseDown(row.__virtualIndex, $event)\"\n (mouseover)=\"onRowMouseOver(row.__virtualIndex, $event)\"\n [style.color]=\"checkboxesColor\"\n >\n {{ getStartIndex() + (row.__virtualIndex - 1) }}\n </div>\n <div\n [style.backgroundColor]=\"\n rowSelectedIndexes.has(row.__virtualIndex)\n ? selectedRowsBackgroundColor\n : checkboxesBackgroundColor\n \"\n class=\"select-all-checkbox-cell\"\n *ngIf=\"isLeftSection && showCheckboxes\"\n [class.left-selection-border]=\"\n rowSelectedIndexes.has(row.__virtualIndex)\n \"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n [style.minHeight.px]=\"rowHeight - 1\"\n [style.maxHeight.px]=\"rowHeight\"\n >\n <input class=\"serialNoCheckbox\"\n *ngIf=\"hasAnyVisibleColumn\"\n style=\"width: 16px; height: 16px\"\n type=\"checkbox\"\n [checked]=\"isRowSelected(row)\"\n (change)=\"toggleRowSelection(row)\"\n />\n </div>\n\n <!-- Render all columns -->\n <ng-container\n *ngFor=\"\n let col of columns;\n trackBy: trackByField;\n let colIndex = index\n \"\n >\n <ng-container *ngIf=\"col.children?.length > 0; else flatColumn\">\n <ng-container\n *ngFor=\"\n let child of col.children;\n trackBy: trackByField;\n let subColIndex = index\n \"\n >\n <ng-container *ngIf=\"child?.is_visible && !child?.isRowGrouped\">\n <ng-container\n *ngTemplateOutlet=\"\n cellTemplate;\n context: {\n col: child,\n row: row,\n rowIndex: rowIndex,\n colIndex: colIndex,\n subColIndex: subColIndex,\n section: section,\n isTotalRow: isTotalRow\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n\n <ng-template #flatColumn>\n <ng-container *ngIf=\"col?.is_visible && !col?.isRowGrouped\">\n <ng-container\n *ngTemplateOutlet=\"\n cellTemplate;\n context: {\n col: col,\n row: row,\n rowIndex: rowIndex,\n colIndex: colIndex,\n subColIndex: null,\n section: section,\n isTotalRow: isTotalRow\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n </div>\n </div>\n\n <div\n [@slideToggle]\n *ngIf=\"section === 'left' && isDetailsExpanded(row)\"\n class=\"accordion-details\"\n style=\"max-height: 350px; overflow: hidden\"\n [style.maxHeight.px]=\"hasHorizontalScroll ? 339 : 341\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n leftRightNestedPlaceholder;\n context: { $implicit: row }\n \"\n >\n </ng-container>\n </div>\n\n <div\n [@slideToggle]\n *ngIf=\"section === 'center' && isDetailsExpanded(row)\"\n class=\"accordion-details center-section\"\n style=\"\n max-height: 350px;\n overflow-y: hidden;\n overflow-x: auto;\n scrollbar-width: thin;\n \"\n #nestedTable\n [style.width]=\"\n hasRightPinnedColumns\n ? '100%'\n : hasVerticalScroll\n ? 'calc(100% - 12px)'\n : '100%'\n \"\n >\n <ng-container *ngIf=\"gridType == 'Assets'\">\n <ng-container\n *ngTemplateOutlet=\"nestedTableTemplate; context: { $implicit: row }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"gridType == 'Tasks'\">\n <ng-container\n *ngTemplateOutlet=\"\n taskManagementTemplate;\n context: { taskDetails: row }\n \"\n ></ng-container>\n </ng-container>\n </div>\n\n <div\n [@slideToggle]\n *ngIf=\"section === 'right' && isDetailsExpanded(row)\"\n class=\"accordion-details\"\n style=\"max-height: 350px; overflow: hidden\"\n [style.maxHeight.px]=\"hasHorizontalScroll ? 339 : 341\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n leftRightNestedPlaceholder;\n context: { $implicit: row }\n \"\n >\n </ng-container>\n </div>\n </ng-template>\n</ng-template>\n\n<!-- Actual Cell is Here -->\n<ng-template\n #cellTemplate\n let-col=\"col\"\n let-row=\"row\"\n let-section=\"section\"\n let-subColIndex=\"subColIndex\"\n let-rowIndex=\"rowIndex\"\n let-colIndex=\"colIndex\"\n let-isTotalRow=\"isTotalRow\"\n>\n <div\n #cellContainer\n (click)=\"\n editingKey = ''; setActiveCell(row, col); collapseAllExpandedCells()\n \"\n [style.fontWeight]=\"bodyFontWeight\"\n [class.border-right]=\"showVerticalBorder\"\n class=\"cell overflow-visible position-relative data-grid-cell\"\n [attr.field]=\"col.field\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.fontSize.px]=\"bodyTextFontsSize\"\n [style.minHeight.px]=\"rowHeight\"\n [style.maxHeight.px]=\"rowHeight\"\n [class.active-cell]=\"\n isActiveCell(row, col) && !isEditing(row, col) && selectedKeys.size == 1\n \"\n (dblclick)=\"\n $event.stopPropagation();\n $event.preventDefault();\n enableEdit(row, col, false, cellContainer)\n \"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.first-row-selected]=\"firstSelectedRow === row?.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row?.__virtualIndex\"\n tabindex=\"-1\"\n (keydown.enter)=\"$event.preventDefault(); enableEdit(row, col)\"\n (mousedown)=\"\n startSelection(\n row.__virtualIndex,\n colIndex,\n subColIndex ?? 0,\n col.field,\n $event,\n section\n )\n \"\n (mouseenter)=\"\n extendSelection(\n row.__virtualIndex,\n colIndex,\n subColIndex ?? 0,\n col.field,\n $event,\n section\n )\n \"\n (mouseup)=\"endSelection()\"\n [class.selected-cell]=\"\n isSelected(\n row.__virtualIndex,\n colIndex,\n subColIndex ?? 0,\n col.field,\n section\n )\n \"\n [class.top-border]=\"\n isTopBorder(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.bottom-border]=\"\n isBottomBorder(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.left-border]=\"\n isLeftBorder(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.right-border]=\"\n isRightBorder(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.top-left-corner]=\"\n isTopLeftCorner(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.top-right-corner]=\"\n isTopRightCorner(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.bottom-left-corner]=\"\n isBottomLeftCorner(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.bottom-right-corner]=\"\n isBottomRightCorner(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n >\n <!-- (mousedown)=\"startSelection(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field, $event)\"\n (mouseenter)=\"extendSelection(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field, $event)\"\n (mouseup)=\"endSelection()\"\n [class.selected-cell]=\"isSelected(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field)\" -->\n <div\n class=\"table-cell\"\n [class.active-for-editing]=\"\n isEditing(row, col) &&\n (getNestedValue(row, col.field)?.length === undefined ||\n getNestedValue(row, col.field)?.length <= 50)\n \"\n >\n <div\n (click)=\"$event.stopPropagation()\"\n *ngIf=\"\n isEditing(row, col) &&\n (getNestedValue(row, col.field)?.length === undefined ||\n (getNestedValue(row, col.field)?.length <= 50 &&\n !expandedCells.size));\n else viewMode\n \"\n >\n <ng-container [ngSwitch]=\"col.type\">\n <!-- Text Input -->\n <input\n [style.height.px]=\"rowHeight - 10\"\n *ngSwitchCase=\"'input'\"\n type=\"text\"\n [(ngModel)]=\"row[col.field]\"\n (blur)=\"disableEdit(row, col)\"\n autofocus\n class=\"form-control form-control-sm\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n\n <!-- Number Input -->\n <input\n [style.height.px]=\"rowHeight - 8\"\n *ngSwitchCase=\"'number'\"\n #numberInput=\"ngModel\"\n #numberRef\n (keypress)=\"allowOnlyNumbers($event)\"\n type=\"number\"\n required\n [(ngModel)]=\"row[col.field]\"\n (blur)=\"disableEdit(row, col)\"\n autofocus\n (keydown.enter)=\"numberRef.blur()\"\n class=\"form-control form-control-sm\"\n [ngClass]=\"{\n 'is-invalid': numberInput.invalid\n }\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n\n <!-- Date Input -->\n <input\n [style.height.px]=\"rowHeight - 8\"\n *ngSwitchCase=\"'date'\"\n type=\"date\"\n [(ngModel)]=\"row[col.field]\"\n (blur)=\"disableEdit(row, col)\"\n autofocus\n class=\"form-control form-control-sm\"\n #dateInput=\"ngModel\"\n [ngClass]=\"{\n 'is-invalid': dateInput.invalid\n }\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n\n <!-- Dropdown -->\n <!-- ng-select like dropdown -->\n <div\n *ngSwitchCase=\"'dropdown'\"\n class=\"dropdown w-100\"\n (blur)=\"disableEdit(row, col)\"\n >\n <!-- Trigger -->\n <button\n class=\"form-select form-select-sm text-start w-100 text-ellipsis\"\n type=\"button\"\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n [style.minHeight.px]=\"rowHeight - 10\"\n data-bs-display=\"static\"\n (mousedown)=\"$event.stopPropagation()\"\n >\n <ng-container>\n {{\n getNestedValue(row, col.field)?.value ||\n getNestedValue(row, col.field)?.name ||\n getNestedValue(row, col.field)\n }}\n </ng-container>\n <ng-template #placeholder> Select options... </ng-template>\n </button>\n\n <!-- Menu -->\n <div\n class=\"dropdown-menu w-100 p-0 cell-editing-dropdown-menu rounded-3\"\n [class.show]=\"isEditing(row, col)\"\n >\n <!-- Search -->\n <div class=\"px-2 py-1 editing-dropdown-search-input\">\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Search...\"\n [(ngModel)]=\"editinDropdownSearch\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n </div>\n\n <!-- Options -->\n <!-- <div\n class=\"cell-editin-dropdown\"\n style=\"max-height: 200px; overflow: auto\"\n >\n <div\n (click)=\"\n setNestedValue(row, col, option, true); editingKey = null\n \"\n class=\"px-2 py-1 d-flex align-items-center deopdown-item\"\n *ngFor=\"\n let option of col.column_dropdown_value\n | filter : editinDropdownSearch: 'value'\n \"\n >\n <label\n class=\"form-check-label d-flex align-items-center mb-0 cursor-pointer\"\n [for]=\"col.field + '-' + option.value || option\"\n >\n {{ option.value || option }}\n </label>\n </div>\n </div> -->\n <cdk-virtual-scroll-viewport \n itemSize=\"35\" \n class=\"dropdown-viewport\"\n style=\"height: 120px\"\n >\n <div\n class=\"px-2 py-1 d-flex align-items-center dropdown-item\"\n *cdkVirtualFor=\"\n let option of col.column_dropdown_value \n | filter : editinDropdownSearch : 'value'\n \"\n (click)=\"setNestedValue(row, col, option, true); editingKey = null\"\n >\n <label\n class=\"form-check-label d-flex align-items-center mb-0 cursor-pointer\"\n [for]=\"col.field + '-' + (option.value || option)\"\n >\n {{ option.value || option }}\n </label>\n </div>\n </cdk-virtual-scroll-viewport>\n\n </div>\n </div>\n\n <input\n *ngSwitchCase=\"'email'\"\n [style.height.px]=\"rowHeight - 10\"\n [style.maxHeight.px]=\"rowHeight - 10\"\n #emailModel=\"ngModel\"\n #emailInput\n type=\"email\"\n [(ngModel)]=\"row[col.field]\"\n name=\"{{ col.field }}\"\n required\n pattern=\"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\"\n (blur)=\"disableEdit(row, col, emailModel)\"\n (keydown.enter)=\"\n emailModel.control.markAsTouched(); emailInput.blur()\n \"\n autofocus\n class=\"form-control form-control-sm\"\n [ngClass]=\"{\n 'is-invalid': emailModel.invalid\n }\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n <!-- Default fallback -->\n <input\n *ngSwitchDefault\n [style.height.px]=\"rowHeight - 10\"\n [style.maxHeight.px]=\"rowHeight - 10\"\n #textModel=\"ngModel\"\n #textInput\n type=\"text\"\n [(ngModel)]=\"row[col.field]\"\n name=\"{{ col.field }}\"\n required\n (blur)=\"disableEdit(row, col, textModel)\"\n (keydown.enter)=\"\n textModel.control.markAsTouched(); textInput.blur()\n \"\n autofocus\n class=\"form-control form-control-sm\"\n [ngClass]=\"{\n 'is-invalid': textModel.invalid\n }\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n </ng-container>\n </div>\n\n <!-- Display mode -->\n <ng-template #viewMode>\n <div\n class=\"d-flex justify-content-between align-items-center overflow-hidden\"\n [ngClass]=\"getCellClasses(col, getNestedValue(row, col.field))\"\n >\n <!-- Field icon (for Tasks grid) -->\n <ng-container\n *ngIf=\"gridType === 'Tasks' && iconMap[col.field] && !isTotalRow\"\n >\n <span\n class=\"cursor-pointer me-2\"\n (click)=\"$event.preventDefault(); $event.stopPropagation()\"\n [inlineSVG]=\"iconMap[col.field](row, col)\"\n ></span>\n </ng-container>\n\n <!-- \u2705 Custom cell renderer support -->\n <ng-container *ngIf=\"col.cellRenderer; else defaultCell\">\n <ng-container\n [cellRenderInit]=\"col.cellRenderer\"\n [rowData]=\"row\"\n [colData]=\"col\"\n [cellValue]=\"getNestedValue(row, col?.field)\"\n (cellEvent)=\"onCellEvent($event)\"\n >\n </ng-container>\n </ng-container>\n\n <!-- \uD83E\uDDFE Default text-based cell rendering -->\n <ng-template #defaultCell>\n <div\n #cellText\n class=\"text-ellipsis flex-grow-1\"\n [title]=\"getCellTitle(row, col)\"\n >\n <!-- Normal cell -->\n <ng-container\n *ngIf=\"\n col.type !== 'image' &&\n col.field != 'image' &&\n col.field != 'invoice.invoice_image' &&\n !isTotalRow\n \"\n >\n <ng-container *ngIf=\"col.is_amount\">{{\n currencySymbol\n }}</ng-container>\n {{getCellTitle(row, col)}}\n </ng-container>\n\n <!-- Total row -->\n <ng-container *ngIf=\"isTotalRow\">\n {{ getTotalAmount(col) }}\n </ng-container>\n\n <!-- Invoice Image -->\n <ng-container *ngIf=\"col.field == 'invoice.invoice_image'\">\n <div style=\"display: flex; align-items: center; zoom: 0.7\">\n <span\n title=\"{{ getNestedValue(row, col.field) || 'Attachment' }}\"\n (click)=\"downloadAttchment(getNestedValue(row, col.field))\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/document-icons/' +\n getExtention(getNestedValue(row, col.field)) +\n '.svg'\n \"\n ></span>\n </div>\n </ng-container>\n\n <!-- Image cell -->\n <ng-container *ngIf=\"col.type == 'image' && !isTotalRow\">\n <ng-container\n *ngTemplateOutlet=\"\n defaultImagePlaceholder;\n context: { row: row, col: col }\n \"\n ></ng-container>\n </ng-container>\n </div>\n <span\n *ngIf=\"\n (!col?.cellRenderer && showCellDetailsBox &&\n getNestedValue(row, col.field)?.length > 50 && col.type !== 'image') ||\n (isNestedValueArray(row, col.field) &&\n getNestedValue(row, col.field)?.length > 1)\n \"\n class=\"toggle-icon data-grid-svg-icon ms-2 cursor-pointer\"\n [inlineSVG]=\"\n isExpanded(row, col)\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n (click)=\"\n $event.stopPropagation();\n toggleExpandOfLongCellText(row, col, columns, true)\n \"\n (dblclick)=\"$event.preventDefault(); $event.stopPropagation()\"\n ></span>\n </ng-template>\n <!-- Expand / Collapse icon -->\n </div>\n\n <!-- Expanded text -->\n <div\n class=\"position-absolute w-100 expanded-box\"\n *ngIf=\"isExpanded(row, col)\"\n [style.zIndex]=\"getZIndex(row, col)\"\n style=\"top: 100%; left: 0\"\n [attr.id]=\"(row.id || row._id) + '-' + (col.id || col._id)\"\n [class.invisible]=\"!showDetailsBox\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n fullTextTemplate;\n context: {\n row: row,\n col: col,\n isArray: isNestedValueArray(row, col.field)\n }\n \"\n ></ng-container>\n </div>\n </ng-template>\n </div>\n </div>\n</ng-template>\n\n<!-- Headers Action List On clicking three dots -->\n\n<ng-template\n #columnMenu\n let-col=\"col\"\n let-isNestedTable=\"isNestedTable\"\n let-columns=\"columns\"\n let-section=\"section\"\n>\n <div\n class=\"column-menu three-dots-col-menu\"\n [class.visually-hidden]=\"isMenueHidden\"\n *ngIf=\"activeCol && !isThreeDotsFilterOpen\"\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\n (click)=\"$event.stopPropagation()\"\n [style.color]=\"headerTextColor\"\n >\n <!-- Sort Ascending -->\n <ng-container *ngIf=\"clickedOnSortIcon\">\n <div class=\"sorting_dropdown\" [class.disable-sorting]=\"!col.is_sortable\">\n <!-- <span class=\"muted-text fs-7\" style=\"margin-left: 12px\">Sort</span> -->\n \n <!-- *ngIf=\"\n columnThreedotsMunuConfig?.showAscending &&\n (sortingConfig?.field != col.field ||\n sortingConfig?.order_by == 'desc')\n \" -->\n <div\n class=\"column-menu-item\" [class.active-sort]=\"sortingConfig?.field === col.field && sortingConfig?.order_by === 'asc'\"\n (click)=\"sortAsc(activeCol);\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/headerSortingIcon.svg'\"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span>\n Sort Ascending\n <span *ngIf=\"sortingConfig?.field === col.field && sortingConfig?.order_by === 'asc'\" [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickBlueIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown no-stroke\" style=\"margin-left: auto;\"\n ></span>\n </div>\n\n <!-- Sort Descending -->\n \n <!-- *ngIf=\"\n columnThreedotsMunuConfig?.showDescending &&\n (sortingConfig?.field != col.field ||\n sortingConfig?.order_by == 'asc')\n \" -->\n <div\n class=\"column-menu-item\" [class.active-sort]=\"sortingConfig?.field === col.field && sortingConfig?.order_by === 'desc'\"\n (click)=\"sortDesc(activeCol);\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/headerSortingIcon1.svg'\"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span>\n Sort Descending\n <span *ngIf=\"sortingConfig?.field === col.field && sortingConfig?.order_by === 'desc'\" [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickBlueIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown no-stroke\" style=\"margin-left: auto;\"\n ></span>\n </div>\n\n <div\n *ngIf=\"\n sortingConfig?.field === col.field &&\n (sortingConfig?.order_by === 'asc' ||\n sortingConfig?.order_by === 'desc')\n \"\n class=\"column-menu-item\"\n (click)=\"resetSort(activeCol)\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/resetSortIconNew.svg'\n \"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span>\n Reset Sort\n </div>\n </div>\n </ng-container>\n <!-- <div class=\"py-2 border-below three-dots-filter\">\n <div\n *ngIf=\"columnThreedotsMunuConfig?.showFilter\"\n class=\"column-menu-item three-dots-filter\"\n (click)=\"openFilteronThreeDotsClick(col)\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n Filter\n </div>\n </div> -->\n\n <ng-container *ngIf=\"!clickedOnSortIcon\">\n <div class=\"sorting_dropdown\">\n <!-- <span class=\"muted-text fs-7\" style=\"margin-left: 12px\">Pin</span> -->\n \n <!-- *ngIf=\"columnThreedotsMunuConfig?.showPinleft && col?.pinned !== 'left'\" -->\n <div\n class=\"column-menu-item\" [class.active-sort]=\"col?.pinned == 'left'\"\n (click)=\"\n $event.stopPropagation();\n updateColumnPinInSourceByField(\n activeCol,\n 'left',\n isNestedTable,\n columns\n )\n \"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pinLeftIconNew.svg'\"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span\n >Pin Left\n <span *ngIf=\"col?.pinned == 'left'\" [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickBlueIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown no-stroke\" style=\"margin-left: auto;\"\n ></span>\n </div>\n <!-- *ngIf=\"\n columnThreedotsMunuConfig?.showPinright && col?.pinned !== 'right'\n \" -->\n <div [class.active-sort]=\"col?.pinned == 'right'\"\n class=\"column-menu-item\"\n (click)=\"\n $event.stopPropagation();\n updateColumnPinInSourceByField(\n activeCol,\n 'right',\n isNestedTable,\n columns\n )\n \"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pinRightIconNew.svg'\"\n class=\"data-grid-svg-icon data-grid-svg-icon me-2 setting_dropdown\"\n ></span\n >Pin Right\n <span *ngIf=\"col?.pinned == 'right'\" [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickBlueIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown no-stroke\" style=\"margin-left: auto;\"\n ></span>\n </div>\n\n <div\n *ngIf=\"col?.pinned\"\n class=\"column-menu-item\"\n (click)=\"\n $event.stopPropagation();\n updateColumnPinInSourceByField(\n activeCol,\n null,\n isNestedTable,\n columns\n )\n \"\n >\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/layout-three-columns.svg'\"\n class=\"data-grid-svg-icon me-2 setting_dropdown d-flex align-items-center justify-content-center\"\n ></span\n >Unpin\n </div>\n </div>\n </ng-container>\n <!-- <div\n *ngIf=\"columnThreedotsMunuConfig?.showAutosizeThisColumn\"\n class=\"column-menu-item\"\n (click)=\"autosizeColumn(activeCol)\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrows-expand-vertical.svg'\n \"\n class=\"me-2\"\n ></span>\n Autosize This Column\n </div> -->\n\n <!-- Autosize All Columns -->\n <!-- <div\n *ngIf=\"columnThreedotsMunuConfig?.showAutosizeAllColumns\"\n class=\"column-menu-item\"\n (click)=\"autosizeAllColumns()\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrows-angle-expand.svg'\n \"\n class=\"data-grid-svg-icon me-2\"\n ></span\n >Autosize All Columns\n </div> -->\n\n <!-- Group By -->\n <div\n *ngIf=\"showRowsGrouping\"\n class=\"column-menu-item\"\n (click)=\"groupBy(activeCol)\"\n [class.disable-sorting]=\"!col.is_groupable\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/diagram-3.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n Group by {{ col.header }}\n </div>\n\n <!-- Choose Columns -->\n <div\n *ngIf=\"columnThreedotsMunuConfig?.showChoseColumns\"\n class=\"column-menu-item\"\n (click)=\"chooseColumns()\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/ui-checks-grid.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n Choose Columns\n </div>\n\n <!-- Reset Columns -->\n <div\n *ngIf=\"columnThreedotsMunuConfig?.showResetColumns\"\n class=\"column-menu-item\"\n (click)=\"resetColumns()\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrow-counterclockwise.svg'\n \"\n class=\"data-grid-svg-icon me-2\"\n ></span\n >Reset Columns\n </div>\n </div>\n <div\n @slideToggle\n *ngIf=\"isThreeDotsFilterOpen\"\n class=\"three-dots-col-menu position-relative\"\n [style.right.px]=\"section == 'right' ? null : col.width - 45\"\n [class.visually-hidden]=\"isMenueHidden\"\n >\n <ng-container\n *ngTemplateOutlet=\"filterMenu; context: { col: col }\"\n ></ng-container>\n </div>\n</ng-template>\n\n<!-- Filter Menue -->\n<ng-template #filterMenu let-col=\"col\">\n <div\n class=\"filter-menu-container filter-menu dropdown_outer\"\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\n >\n <!-- Dropdown Type -->\n <ng-container *ngIf=\"col.type === 'dropdown'; else textFilter\">\n <div class=\"filter-dropdown-section p-1\">\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Search...\"\n type=\"search\"\n [(ngModel)]=\"addFilterColumnInput\"\n />\n\n <div class=\"form-check mb-1 mt-2 ps-4 ms-1\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [checked]=\"isAllSideFilterOptionsSelected(col)\"\n (change)=\"toggleSelectAllSideFilters(col, $event)\"\n id=\"selectAll_{{ col.field }}\"\n />\n <label class=\"form-check-label\" for=\"selectAll_{{ col.field }}\">\n Select All\n </label>\n </div>\n\n <!-- <div class=\"dropdown-options ps-1\">\n <div\n class=\"form-check mb-1\"\n *ngFor=\"\n let option of selectedColumnForFilter?.column_dropdown_value\n | filter : addFilterColumnInput : 'value';\n trackBy: trackById;\n let i = index\n \"\n >\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [id]=\"i\"\n [checked]=\"\n currentFilterSelectedIds.has(option?.id ?? option?._id ?? option)\n \"\n (change)=\"toggleSelectionInFilter(option)\"\n />\n <label class=\"form-check-label fw-semibold\" [for]=\"i\">\n {{ option?.value ?? option?.name ?? option }}\n </label>\n </div>\n </div> -->\n <cdk-virtual-scroll-viewport\n itemSize=\"32\"\n class=\"filter-viewport\"\n style=\"height: 120px\"\n >\n <div\n class=\"form-check mb-1 ms-1\"\n *cdkVirtualFor=\"\n let option of selectedColumnForFilter?.column_dropdown_value\n | filter : addFilterColumnInput : 'value';\n trackBy: trackById\n \"\n >\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [id]=\"option?.id ?? option?._id ?? option\"\n [checked]=\"\n currentFilterSelectedIds.has(option?.id ?? option?._id ?? option)\n \"\n (change)=\"toggleSelectionInFilter(option)\"\n />\n\n <label\n class=\"form-check-label fw-semibold\"\n [for]=\"option?.id ?? option?._id ?? option\"\n >\n {{ option?.value ?? option?.name ?? option }}\n </label>\n </div>\n </cdk-virtual-scroll-viewport>\n </div>\n </ng-container>\n\n <!-- Text Filter Section -->\n <ng-template #textFilter>\n <div class=\"filter-text-section\">\n <div class=\"form-group mb-2\">\n <select\n class=\"form-select form-select-sm custom-select\"\n [(ngModel)]=\"firstCondition\"\n >\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"before\">Less Then </option>\n <option value=\"after\">Greater Then </option>\n <option value=\"less_then_equal\">less then Equal to</option>\n <option value=\"greater_then_equal\">Greater then Equal to </option>\n </ng-container>\n </select>\n </div>\n\n <input\n [type]=\"col.type == 'string' ? 'text' : col.type\"\n class=\"form-control form-control-sm mb-3\"\n placeholder=\"Value\"\n [(ngModel)]=\"firstValue\"\n #filterMenueTextchInput\n (keydown.enter)=\"applyDropdownFilter()\"\n />\n\n <div class=\"form-group mb-3 d-flex flex-row\">\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"condition\"\n value=\"and\"\n id=\"and_{{ col.field }}\"\n (change)=\"cdr.detectChanges()\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"and_{{ col.field }}\"\n >AND</label\n >\n </div>\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1 gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"condition\"\n value=\"or\"\n id=\"or_{{ col.field }}\"\n (change)=\"cdr.detectChanges()\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"or_{{ col.field }}\"\n >OR</label\n >\n </div>\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1 gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"condition\"\n value=\"none\"\n id=\"none_{{ col.field }}\"\n (change)=\"cdr.detectChanges()\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"none_{{ col.field }}\"\n >None</label\n >\n </div>\n </div>\n <div @slideToggle *ngIf=\"firstValue && condition != 'none'\">\n <div class=\"form-group mb-2\">\n <select\n class=\"form-select form-select-sm custom-select\"\n [(ngModel)]=\"secondCondition\"\n >\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"before\">Less Then </option>\n <option value=\"after\">Greater Then </option>\n <option value=\"less_then_equal\">less then Equal to</option>\n <option value=\"greater_then_equal\">Greater then Equal to </option>\n </ng-container>\n </select>\n </div>\n\n <input\n [type]=\"col.type == 'string' ? 'text' : col.type\"\n class=\"form-control form-control-sm mb-3\"\n placeholder=\"Second Value\"\n [(ngModel)]=\"secondValue\"\n />\n </div>\n </div>\n </ng-template>\n\n <!-- Actions -->\n <div class=\"d-flex gap-2 mt-2\">\n <div\n class=\"primary_btn_new flex justify-content-center align-items-center w-100\"\n style=\"height: 30px\"\n (click)=\"applyDropdownFilter()\"\n >\n Apply\n </div>\n <div\n class=\"cancel_btn_new d-flex justify-content-center align-items-center w-100\"\n style=\"height: 30px\"\n (click)=\"resetSideFilter(col)\"\n >\n Reset\n </div>\n </div>\n </div>\n</ng-template>\n\n<!-- Side Menue -->\n\n<!-- Column Pannel / Pivot Mode / Searching -->\n\n<ng-template #columnPannel>\n <div class=\"column-panel-header\">\n <!-- Pivot Toggle -->\n <div\n class=\"form-check form-switch d-flex align-items-center mb-2 pivot-mode px-5 ms-2 d-none\"\n >\n <input\n class=\"form-check-input me-2\"\n type=\"checkbox\"\n id=\"pivotToggle\"\n [(ngModel)]=\"pivotMode\"\n />\n <label class=\"form-check-label\" for=\"pivotToggle\">Pivot Mode</label>\n </div>\n\n <!-- Select All & Search -->\n <div class=\"d-flex align-items-center mb-2 px-3 mt-3\">\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n accordionState === 'all'\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : accordionState === 'some'\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n (click)=\"toggleAllAccordions()\"\n ></span>\n </span>\n <input\n type=\"checkbox\"\n class=\"form-check-input me-2\"\n [checked]=\"allColumnsSelected()\"\n (change)=\"toggleAllColumnsVisibility()\"\n />\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Search columns...\"\n [(ngModel)]=\"columnSearch\"\n />\n </div>\n\n <!-- Separator -->\n <hr class=\"my-2\" />\n </div>\n</ng-template>\n\n<!-- Right Columns Menue -->\n\n<!-- Column Panel Item Template -->\n<ng-template #columnPanelItem let-col=\"col\">\n <!-- Group Column -->\n <ng-container *ngIf=\"col.children?.length\">\n <div class=\"column-group d-flex align-items-center mb-2\">\n <span class=\"filter-icon-wrapper me-2\">\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n [class.rotate]=\"col.expanded\"\n (click)=\"col.expanded = !col.expanded\"\n ></span>\n </span>\n <input\n type=\"checkbox\"\n class=\"form-check-input me-2\"\n [id]=\"'group_' + col.header\"\n [checked]=\"isColumnVisible(col)\"\n (change)=\"toggleGroupVisibility(col)\"\n />\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center me-2\"\n ></span>\n <label\n class=\"d-flex align-items-center mb-0 w-100\"\n [for]=\"'group_' + col.header\"\n style=\"cursor: pointer\"\n >\n <span class=\"text-truncate\">{{ col.header }}</span>\n </label>\n </div>\n <div *ngIf=\"col.expanded\" class=\"ps-4\">\n <ng-container *ngFor=\"let child of col.children; trackBy: trackByField\">\n <ng-container\n *ngTemplateOutlet=\"columnPanelItem; context: { col: child }\"\n ></ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- Leaf Column -->\n <ng-container *ngIf=\"!col.children?.length\">\n <div class=\"d-flex align-items-center mb-2\">\n <span class=\"me-2\" style=\"width: 1.5rem\"></span>\n <input\n type=\"checkbox\"\n class=\"form-check-input me-2\"\n [(ngModel)]=\"col.is_visible\"\n [id]=\"'col_' + col.field\"\n (change)=\"onSideMenuColumnsVisibilityChange()\"\n />\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center me-2\"\n ></span>\n <label\n class=\"d-flex align-items-center mb-0 w-100\"\n [for]=\"'col_' + col.field\"\n style=\"cursor: pointer\"\n >\n <span class=\"text-truncate\">{{ col.header }}</span>\n </label>\n </div>\n </ng-container>\n</ng-template>\n\n<!-- Columns Side Filter -->\n<ng-template #sideFilters>\n <div class=\"py-3 px-2 pe-3 h-100\">\n <div class=\"d-flex align-items-center mb-2\">\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n filterAccordionState === 'all'\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : filterAccordionState === 'some'\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n (click)=\"toggleAllFilterAccordions()\"\n ></span>\n </span>\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Search...\"\n [(ngModel)]=\"columnSearch\"\n />\n </div>\n <div\n class=\"overflow-auto side-filter-columns-wrapper\"\n style=\"height: calc(100% - 70px); scrollbar-width: thin\"\n >\n <ng-container\n *ngFor=\"\n let col of columns | filter : columnSearch : 'header';\n trackBy: trackByField\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"filterPannelItem; context: { col: col }\"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #filterPannelItem let-col=\"col\">\n <!-- Group Column -->\n <ng-container *ngIf=\"col.children?.length\">\n <div\n class=\"column-group d-flex align-items-center mb-2\"\n *ngIf=\"col.type !== 'image'\"\n >\n <!-- Chevron toggle -->\n <span class=\"filter-icon-wrapper me-2\">\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n [class.rotate]=\"col.expandedFilter\"\n (click)=\"col.expandedFilter = !col.expandedFilter\"\n ></span>\n </span>\n\n <!-- Group label toggle -->\n <label\n class=\"d-flex align-items-center mb-0 w-100\"\n style=\"cursor: pointer\"\n (click)=\"col.expandedFilter = !col.expandedFilter\"\n >\n <span class=\"fw-bold text-truncate\"\n >{{ col.header }}\n <span\n class=\"text-primary ms-1\"\n *ngIf=\"col?.query?._ids?.length || col?.query?._first_value\"\n >*</span\n >\n </span>\n </label>\n </div>\n\n <!-- Children columns -->\n <div *ngIf=\"col.expandedFilter\" class=\"ps-4\">\n <ng-container *ngFor=\"let child of col.children; trackBy: trackByField\">\n <ng-container\n *ngTemplateOutlet=\"filterPannelItem; context: { col: child }\"\n ></ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- Leaf Column -->\n <ng-container *ngIf=\"!col.children?.length\">\n <div class=\"d-flex align-items-center mb-2\" *ngIf=\"col.type !== 'image'\">\n <span\n class=\"me-2 filter-icon-wrapper me-2\"\n (click)=\"col.expandedFilter = !col.expandedFilter\"\n >\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n [class.rotate]=\"col.expandedFilter\"\n ></span>\n </span>\n\n <label\n class=\"d-flex align-items-center mb-0 w-100\"\n style=\"cursor: pointer\"\n (click)=\"col.expandedFilter = !col.expandedFilter\"\n >\n <span class=\"text-truncate fw-bold\">{{ col.header }}</span>\n </label>\n </div>\n\n <!-- Show filter when expanded -->\n <div *ngIf=\"col.expandedFilter\" class=\"ps-4 pe-3\">\n <ng-container\n *ngTemplateOutlet=\"sideNestedFilter; context: { col: col }\"\n ></ng-container>\n </div>\n </ng-container>\n</ng-template>\n\n<!-- Side Nested Filters -->\n<ng-template #sideNestedFilter let-col=\"col\">\n <div class=\"\">\n <!-- Dropdown Type -->\n <ng-container *ngIf=\"col.type === 'dropdown'; else textFilter\">\n <div class=\"p-1\">\n <!-- Search -->\n <input\n type=\"text\"\n class=\"form-control form-control-sm mb-2\"\n placeholder=\"Search...\"\n [(ngModel)]=\"sideNestedFilterSearch\"\n />\n\n <!-- Select All -->\n <div class=\"form-check mb-1 ms-1\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [checked]=\"\n col.query?._ids?.length == col?.column_dropdown_value?.length\n \"\n (change)=\"toggleSelectAllSideFilters(col, $event)\"\n id=\"selectAll_{{ col.field }}\"\n />\n <label class=\"form-check-label\" for=\"selectAll_{{ col.field }}\">\n Select All\n </label>\n </div>\n\n <!-- Options -->\n <!-- <div class=\"dropdown-options\">\n <div\n class=\"form-check mb-1 ms-1\"\n *ngFor=\"\n let option of col?.column_dropdown_value\n | filter : sideNestedFilterSearch : 'value'\n \"\n >\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [value]=\"option\"\n [checked]=\"\n col.query?._ids?.includes(option?._id || option?.id || option)\n \"\n (change)=\"onOptionToggle(col, option)\"\n id=\"option_{{ col.field }}_{{\n option?.id || option?._id || option\n }}\"\n />\n <label\n class=\"form-check-label\"\n [for]=\"\n 'option_' +\n col.field +\n '_' +\n (option?.id || option?._id || option)\n \"\n >\n {{ option.value || option }}\n </label>\n </div>\n </div> -->\n <cdk-virtual-scroll-viewport\n itemSize=\"32\"\n class=\"dropdown-viewport\"\n style=\"height: 120px\"\n >\n <div\n class=\"form-check mb-1 ms-1\"\n *cdkVirtualFor=\"\n let option of col?.column_dropdown_value\n | filter : sideNestedFilterSearch : 'value'\n \"\n >\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [value]=\"option\"\n [checked]=\"\n col.query?._ids?.includes(option?._id || option?.id || option)\n \"\n (change)=\"onOptionToggle(col, option)\"\n id=\"option_{{ col.field }}_{{\n option?.id || option?._id || option\n }}\"\n />\n\n <label\n class=\"form-check-label\"\n [for]=\"\n 'option_' +\n col.field +\n '_' +\n (option?.id || option?._id || option)\n \"\n >\n {{ option.value || option }}\n </label>\n </div>\n </cdk-virtual-scroll-viewport>\n\n\n <!-- Actions -->\n <!-- <div class=\"d-flex gap-2 mt-2\">\n <div\n class=\"btn btn-sm btn-primary d-flex justify-content-center align-items-center\"\n style=\"height: 22px;\"\n (click)=\"applySideFilter(col)\"\n >\n Apply\n </div>\n <div\n class=\"btn btn-sm btn-secondary d-flex justify-content-center align-items-center\" \n style=\"height: 22px;\"\n (click)=\"resetSideFilter(col)\"\n >\n Reset\n </div>\n </div> -->\n </div>\n </ng-container>\n\n <!-- Text Filter Section -->\n <ng-template #textFilter>\n <div class=\"filter-text-section\">\n <div class=\"form-group mb-2\">\n <select\n class=\"form-select form-select-sm\"\n [(ngModel)]=\"col.query.first_condition\"\n >\n <ng-container *ngIf=\"col.type !== 'date'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"col.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n </select>\n </div>\n\n <input\n [type]=\"col.type == 'date' ? 'date' : 'text'\"\n class=\"form-control form-control-sm mb-3\"\n placeholder=\"Value\"\n [(ngModel)]=\"col!.query!.first_value\"\n />\n\n <div\n class=\"form-group mb-3 d-flex flex-row muted\"\n style=\"font-size: 14px\"\n >\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"col!.query.condition\"\n value=\"and\"\n id=\"and_{{ col.field }}\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"and_{{ col.field }}\"\n >AND</label\n >\n </div>\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"col!.query.condition\"\n value=\"or\"\n id=\"or_{{ col.field }}\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"or_{{ col.field }}\"\n >OR</label\n >\n </div>\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"col!.query.condition\"\n value=\"none\"\n id=\"none_{{ col.field }}\"\n />\n <label\n class=\"nnonem-check-label mb-0 mt-1\"\n for=\"none_{{ col.field }}\"\n >None</label\n >\n </div>\n </div>\n <ng-container\n *ngIf=\"col?.query?.first_value && col?.query?.condition !== 'none'\"\n >\n <div class=\"form-group mb-2\">\n <select\n class=\"form-select form-select-sm\"\n [(ngModel)]=\"col!.query.second_condition\"\n >\n <ng-container *ngIf=\"col.type !== 'date'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"col.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n </select>\n </div>\n\n <input\n [type]=\"col.type == 'date' ? 'date' : 'text'\"\n class=\"form-control form-control-sm mb-3\"\n placeholder=\"Second Value\"\n [(ngModel)]=\"col!.query.second_value\"\n />\n </ng-container>\n <!-- <div class=\"d-flex gap-2\">\n <div class=\"btn btn-sm btn-primary d-flex justify-content-center align-items-center\" style=\"height: 22px;\" (click)=\"applyDropdownFilter()\">apply</div>\n <div class=\"btn btn-sm btn-secondary d-flex justify-content-center align-items-center\" style=\"height: 22px;\" (click)=\"applyDropdownFilter()\">reset</div>\n\n </div> -->\n </div>\n </ng-template>\n <div\n class=\"d-flex justify-content-center gap-2 border-top\"\n style=\"height: 38px\"\n >\n <button\n type=\"button\"\n style=\"max-height: 30px\"\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\n (click)=\"$event.stopPropagation(); removeSideFilter(col)\"\n >\n <span>Clear</span>\n </button>\n <button\n type=\"button\"\n style=\"max-height: 30px\"\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\n (click)=\"applySideFilter(col)\"\n [class.disabled]=\"(col?.query.condition !== 'none' && !col?.query?.second_value)\"\n [class.pe-none]=\"(col!?.query.condition !== 'none' && !col?.query?.second_value)\"\n >\n <span style=\"margin-top: -1px\">Apply</span>\n </button>\n </div>\n </div>\n</ng-template>\n\n<!-- Centr Overlay for showing the chose columns -->\n\n<div *ngIf=\"showColumnPanel\" class=\"custom-modal-overlay\">\n <div\n class=\"custom-modal-content\"\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container *ngTemplateOutlet=\"modalColumnPannel\"></ng-container>\n </div>\n</div>\n\n<!-- The existing ng-template you provided -->\n<ng-template #modalColumnPannel>\n <div class=\"column-panel-header\">\n <div\n class=\"d-flex justify-content-between align-items-center px-2 ps-3 rounded-top-2 moda-header\"\n [style.height.px]=\"48\"\n >\n Choose Columns\n <span class=\"filter-icon-wrapper\" (click)=\"closeModalColumnPanel()\"\n ><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/x.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span\n ></span>\n </div>\n <hr class=\"my-0\" />\n <div>\n <div class=\"d-flex align-items-center px-2 pe-3\" [style.height.px]=\"48\">\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n accordionState === 'all'\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : accordionState === 'some'\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n (click)=\"toggleAllAccordions()\"\n ></span>\n </span>\n <input\n type=\"checkbox\"\n class=\"form-check-input me-2\"\n [checked]=\"allColumnsSelected()\"\n (change)=\"toggleAllColumnsVisibility()\"\n />\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Search columns...\"\n [(ngModel)]=\"choseColumnsSearch\"\n />\n </div>\n\n <hr class=\"mt-0 mb-1\" />\n <div class=\"px-2 overlay-scrollable\">\n <ng-container\n *ngFor=\"\n let col of columns | filter : choseColumnsSearch : 'header';\n trackBy: trackByField\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"columnPanelItem; context: { col: col }\"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #sideMenuRowGroups>\n <div class=\"d-flex flex-column h-100 d-none\">\n <div class=\"px-3 h-100\">\n <div class=\"d-flex gap-3 mb-4\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <span>Row Groups</span>\n </div>\n <div class=\"h-50\">\n <div\n class=\"px-3 py-2 border-dashed h-100 d-flex justify-content-center align-items-center\"\n style=\"font-size: 14px\"\n >\n Drag here to set row Groups\n </div>\n </div>\n </div>\n\n <hr class=\"mt-4\" />\n\n <div class=\"px-3 h-100\">\n <div class=\"d-flex gap-3 mb-4\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <span>Values</span>\n </div>\n <div class=\"h-50 d-flex\">\n <div\n class=\"px-3 py-2 border-dashed h-100 d-flex justify-content-center align-items-center\"\n style=\"font-size: 14px\"\n >\n Drag here aggregate\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n\n<!-- *************************************************** -->\n<!-- *************************************************** -->\n<!-- *************************************************** -->\n<!-- Drag Preview Template -->\n<!-- *************************************************** -->\n<!-- *************************************************** -->\n<ng-template #dragPreview let-col>\n <div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ col.header }}</div>\n </div>\n</ng-template>\n\n<!-- Drag Placeholder Template -->\n<ng-template\n #dragPlaceholder\n let-col\n let-i=\"index\"\n let-section=\"section\"\n let-draggingInGroupArea=\"draggingInGroupArea\"\n>\n <div *ngIf=\"!draggingInGroupArea\">\n <div\n *ngTemplateOutlet=\"\n headerCell;\n context: { $implicit: col, index: i, section: section }\n \"\n ></div>\n </div>\n <div *ngIf=\"draggingInGroupArea\">New Placeholder</div>\n</ng-template>\n\n<!-- Top Group Row Placeholder -->\n<ng-template #topGroupingRowPlaceholder let-col let-showChevron=\"showChevron\">\n <div class=\"d-flex gap-2\">\n <div\n class=\"d-flex gap-2 top-row-grouping-placeholder\"\n [style.backgroundColor]=\"topGroupedBadgesBackgroundColor\"\n >\n <span\n cdkDragHandle\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <span>{{ col.header }}</span>\n <span\n (click)=\"ungroupColumn(col)\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/x.svg'\"\n class=\"cursor-pointer data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n <div *ngIf=\"showChevron\" style=\"opacity: 0.6; font-size: 14px\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n</ng-template>\n\n<ng-template\n #childHeaderPlaceholder\n let-col\n let-pinnedRight=\"pinnedRight\"\n let-i=\"index\"\n let-sections=\"sections\"\n>\n <div\n class=\"header-cell one-row-header-cells\"\n [class.border-right]=\"showVerticalBorder\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n [style.fontWeight]=\"headerFontWeight\"\n >\n <div class=\"d-flex justify-content-between h-100 align-items-center w-100\">\n <div\n class=\"d-flex justify-content-between align-items-center w-100\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div\n class=\"text-ellipsis h-100 d-flex align-items-center\"\n [title]=\"col.header\"\n [class.w-100]=\"pinnedRight\"\n >\n {{ col.header }}\n </div>\n\n <div\n class=\"position-relative d-flex\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div class=\"three-dots p-1\" style=\"cursor: pointer\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/three-dots-vertical.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n\n <div class=\"resize-handle resize-test\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div\n *ngIf=\"showFilterRow\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n class=\"header-cell filter-cell\"\n [class.border-right]=\"showVerticalBorder\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n [class.border-right]=\"showVerticalBorder\"\n style=\"grid-row: 3\"\n >\n <div\n class=\"header-cell filter-cell\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n >\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Filter\"\n [(ngModel)]=\"col.filterValue\"\n [readonly]=\"col?.type == 'dropdown' || col?.type == 'image'\"\n [class.disabled-search-input]=\"\n col?.type == 'dropdown' || col?.type == 'image'\n \"\n />\n <span\n class=\"filter-icon-wrapper\"\n (click)=\"activeFilterCell = col; activeCol = null\"\n ><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span\n ></span>\n\n <div\n class=\"position-absolute\"\n *ngIf=\"activeFilterCell === col\"\n style=\"top: 100%; right: 0; z-index: 10; left: 0\"\n ></div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #tableLayout>\n <div\n (click)=\"$event.stopPropagation()\"\n class=\"p-3 action_dropdown_new_design actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\n style=\"width: 320px\"\n >\n <div class=\"d-flex align-items-center mb-3\">\n <button\n class=\"btn btn-link p-0\"\n style=\"margin-left: -10px\"\n (click)=\"toggleActions('setting')\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n </button>\n <h6 class=\"mb-0 ms-2 text_common_14px\">Table Layout</h6>\n </div>\n <hr class=\"my-2\" />\n <div class=\"w-100 mb-3 d-flex\" role=\"group\">\n <input\n type=\"radio\"\n class=\"btn-check layout-button-check\"\n name=\"layoutSize\"\n id=\"small\"\n autocomplete=\"off\"\n (change)=\"changeTableLayout($event, 'small')\"\n [checked]=\"selectedTableLayout == 'small'\"\n />\n <label\n class=\"border d-flex flex-column align-items-center layout-button\"\n for=\"small\"\n [ngStyle]=\"{\n color: selectedTableLayout == 'small' ? '#000' : '#727272'\n }\"\n >\n <div class=\"preview-box border mb-1\" style=\"height: 8px\"></div>\n Small\n </label>\n\n <input\n type=\"radio\"\n class=\"btn-check layout-button-check\"\n name=\"layoutSize\"\n id=\"medium\"\n autocomplete=\"off\"\n [checked]=\"selectedTableLayout == 'medium'\"\n (change)=\"changeTableLayout($event, 'medium')\"\n />\n <label\n class=\"border mx-3 d-flex flex-column align-items-center layout-button\"\n for=\"medium\"\n [ngStyle]=\"{\n color: selectedTableLayout == 'medium' ? '#000' : '#727272'\n }\"\n >\n <div class=\"preview-box border mb-1\" style=\"height: 12px\"></div>\n Medium\n </label>\n\n <input\n type=\"radio\"\n class=\"btn-check layout-button-check\"\n name=\"layoutSize\"\n id=\"large\"\n autocomplete=\"off\"\n (change)=\"changeTableLayout($event, 'large')\"\n [checked]=\"selectedTableLayout == 'large'\"\n />\n <label\n class=\"border d-flex flex-column align-items-center layout-button\"\n for=\"large\"\n [ngStyle]=\"{\n color: selectedTableLayout == 'large' ? '#000' : '#727272'\n }\"\n >\n <div class=\"preview-box border mb-1\" style=\"height: 16px\"></div>\n Large\n </label>\n </div>\n\n <hr class=\"my-2\" />\n <div class=\"d-flex justify-content-between align-items-center mb-2\">\n <span>Show separators</span>\n <div class=\"form-check form-switch m-0\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n id=\"separators\"\n [(ngModel)]=\"showVerticalBorder\"\n (change)=\"onFontChange()\"\n />\n </div>\n </div>\n <div class=\"d-flex justify-content-between align-items-center\">\n <span>Row shading</span>\n <div class=\"form-check form-switch m-0\">\n <input\n class=\"form-check-input\"\n [(ngModel)]=\"rowShadingEnabled\"\n (change)=\"toggleRowShading()\"\n type=\"checkbox\"\n id=\"rowShading\"\n />\n </div>\n </div>\n <!-- <div class=\"d-flex justify-content-between align-items-center mb-2\">\n <span>Show Side Menu</span>\n <div class=\"form-check form-switch m-0\">\n <input\n class=\"form-check-input\"\n [(ngModel)]=\"showSideMenu\"\n type=\"checkbox\"\n id=\"rowShading\"\n />\n </div>\n </div>\n <div class=\"d-flex justify-content-between align-items-center mb-2\">\n <span>Show Filter Row</span>\n <div class=\"form-check form-switch m-0\">\n <input\n class=\"form-check-input\"\n [(ngModel)]=\"showFilterRow\"\n type=\"checkbox\"\n id=\"rowShading\"\n />\n </div>\n </div> -->\n </div>\n</ng-template>\n\n<ng-template #tablePreset>\n <div\n *ngIf=\"activeSubButton !== 'save-preset'\"\n (click)=\"$event.stopPropagation()\"\n class=\"p-3 action_dropdown_new_design actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\n style=\"width: 280px\"\n >\n <!-- Header -->\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <div class=\"d-flex align-items-center\">\n <button\n class=\"btn btn-link p-0\"\n style=\"margin-left: -10px\"\n (click)=\"toggleActions('setting')\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\n class=\"data-grid-svg-icon\"\n ></span>\n </button>\n <h6 class=\"mb-0 ms-2 text_common_14px\">Table Presets</h6>\n </div>\n <!-- Save Preset Button with Dropdown -->\n <div>\n <a\n class=\"text-decoration-none text-primary\"\n type=\"button\"\n id=\"savePresetDropdown\"\n (click)=\"$event.stopPropagation(); toggleSubActions('save-preset')\"\n >\n {{ isTablePresetNotChanged ? \"Save preset\" : \"Update Preset\" }}\n </a>\n </div>\n </div>\n\n <!-- Search -->\n <div class=\"mb-3\">\n <div class=\"col-12 global-search position-relative\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\n class=\"data-grid-svg-icon mx-2 position-absolute icon\"\n ></span>\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Search...\"\n [(ngModel)]=\"searchTextPresetTable\"\n type=\"search\"/>\n </div>\n </div>\n\n <!-- Preset List -->\n <ng-container\n *ngIf=\"\n tableView | filter : searchTextPresetTable : 'name' as filteredList\n \"\n >\n <!-- If filteredList exists and none is default -> show fallback -->\n <div\n class=\" pb-5 overflow-auto\"\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight - 250\"\n >\n <div\n class=\"cursor-pointer\"\n (click)=\"\n clearAllFilters();\n openIndex = null;\n temp_state.id = '';\n activeTopButton = '';\n curretaTablePresetForUpdate = null\n \"\n >\n <div class=\"fw-semibold\">Default View</div>\n </div>\n <div class=\"d-flex justify-content-between\">\n <small class=\"text-dark\">Created by system</small>\n <span\n *ngIf=\"!tableFilterViewId && !hasAnyDefaultView()\"\n class=\"badge bg-light text-primary ms-2\"\n >Default</span\n >\n <span\n *ngIf=\"!tableFilterViewId && !hasAnyDefaultView()\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\"\n class=\"me-2\"\n ></span>\n <div\n class=\"dropdown d-flex justify-content-end\"\n *ngIf=\"tableFilterViewId\"\n ></div>\n </div>\n\n <!-- The list: render each table from filteredList -->\n <div\n class=\"list-group list-group-flush\"\n *ngFor=\"\n let table of filteredList;\n let i = index;\n trackBy: trackByTable\n \"\n >\n <!-- Item -->\n <div\n (click)=\"\n $event.stopPropagation(); openIndex = null; activeTopButton = ''\n \"\n class=\"list-group-item px-0 d-flex justify-content-between align-items-center\"\n >\n <div (click)=\"selectFilter(table); openIndex = null\">\n <div class=\"fw-semibold\" style=\"cursor: pointer\">\n {{ table?.name }}\n <!-- {{table?.is_temp}} -->\n <span\n *ngIf=\"\n (table?.is_temp && !temp_state.id) ||\n temp_state.id == table.id\n \"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\n \"\n class=\"me-2\"\n ></span>\n <span\n *ngIf=\"table?.is_default\"\n class=\"badge bg-light text-primary ms-2\"\n >Default</span\n >\n </div>\n <small class=\"text-dark\" *ngIf=\"table?.config?.filterNames\" [title]=\"table?.config?.filterNames\">\n {{\n table?.config?.filterNames?.length > 25\n ? (table?.config?.filterNames | slice:0:25) + '...'\n : table?.config?.filterNames\n }}\n ({{ table?.config?.totalCount }})\n </small>\n <small class=\"text-dark\" *ngIf=\"!table?.config?.filterNames\">{{ table?.createdAt | date : \"MMM d, y\" }}</small>\n </div>\n\n <div class=\"d-flex align-items-center\">\n <span\n *ngIf=\"table?.is_default\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\n \"\n class=\"me-2\"\n ></span>\n\n <div class=\"dropdown\" *ngIf=\"!table?.is_default\">\n <div\n class=\"dropdown-wrapper\"\n (click)=\"$event.stopPropagation()\"\n >\n <button\n type=\"button\"\n class=\"btn-icon muted-text\"\n (click)=\"toggleMenu(i, $event)\"\n aria-haspopup=\"true\"\n [attr.aria-expanded]=\"openIndex === i\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/horizontal-dots.svg'\n \"\n class=\"me-2\"\n ></span>\n </button>\n\n <!-- menu -->\n <ul\n *ngIf=\"openIndex === i\"\n class=\"custom-dropdown-menu position-fixed top-auto\"\n role=\"menu\"\n [style.right.px]=\"'auto'\"\n [style.left.px]=\"dataGridContainer.offsetWidth - 100\"\n style=\"top: unset; right: unset\"\n >\n <li role=\"none\">\n <button\n role=\"menuitem\"\n class=\"dropdown-item\"\n (click)=\"\n actionPreset(table, 'setPreset'); temp_state.id = ''\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/star.svg'\n \"\n class=\"me-2\"\n ></span>\n Set as default\n </button>\n </li>\n\n <li role=\"none\" *ngIf=\"!table.confirmDelete\">\n <button\n role=\"menuitem\"\n class=\"dropdown-item text-danger\"\n (click)=\"table.confirmDelete = true\"\n >\n <span\n style=\"margin-top: -4px\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/trash-red.svg'\n \"\n class=\"me-2\"\n ></span>\n Delete\n </button>\n </li>\n\n <li\n role=\"none\"\n *ngIf=\"table.confirmDelete\"\n class=\"confirm-block\"\n >\n <div class=\"px-3 py-2 text-center\">\n <div class=\"mb-2\">\n Are you sure you want to delete <br /><b\n >\u201C{{ table?.name }}\u201D</b\n >?\n </div>\n <div class=\"d-flex gap-2\">\n <button\n class=\"btn btn-sm btn-light me-2\"\n (click)=\"table.confirmDelete = false\"\n >\n Cancel\n </button>\n <button\n class=\"btn btn-sm btn-danger\"\n (click)=\"actionPreset(table, 'deletePreset')\"\n >\n Delete\n </button>\n </div>\n </div>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n <!-- Item End Here -->\n </div>\n </div>\n </ng-container>\n </div>\n\n <div\n (click)=\"$event.stopPropagation()\"\n *ngIf=\"activeSubButton == 'save-preset'\"\n class=\"dropdown-menu p-3 badge mt-4 save-preset-dropdown mt-1\"\n aria-labelledby=\"savePresetDropdown\"\n style=\"min-width: 250px\"\n >\n <div class=\"fw-bold fs-14px mb-2\">\n {{ isTablePresetNotChanged ? \"Create New Preset\" : \"Update Preset\" }}\n </div>\n <!-- <div class=\"fs-14px mb-2\" style=\"line-height: 20px\">\n This will save the current table adjustments as a preset.\n </div> -->\n <!-- Input -->\n <div class=\"my-3\">\n <label for=\"presetName\" class=\"form-label fs-12px fw-bold\">Name</label>\n <div class=\"col-12 global-search position-relative\">\n <input\n #presetNameCtrl=\"ngModel\"\n required\n [(ngModel)]=\"presetName\"\n [ngClass]=\"{\n 'is-invalid':\n presetNameCtrl.invalid &&\n (presetNameCtrl.dirty || presetNameCtrl.touched)\n }\"\n class=\"form-control form-control-sm ps-2\"\n placeholder=\"Enter preset name\"\n type=\"text\"\n />\n </div>\n </div>\n\n <!-- Checkbox -->\n <div class=\"form-check mb-2\">\n <input\n class=\"form-check-input\"\n [(ngModel)]=\"presetFilter\"\n type=\"checkbox\"\n id=\"saveFilters\"\n />\n <label class=\"form-check-label mt-1\" for=\"saveFilters\">\n Save active filters\n </label>\n </div>\n\n <!-- Save Button -->\n <div class=\"d-flex justify-content-end gap-2\" style=\"height: 32px\">\n <button\n type=\"button\"\n style=\"height: 32px\"\n class=\"cancel_btn_new w-100 d-flex align-items-center justify-content-center\"\n (click)=\"$event.stopPropagation(); toggleActions('table-presets')\"\n style=\"margin-top: -2px\">\n <span>Cancel</span>\n </button>\n <button\n [disabled]=\"closeDropdown.preset.loading\"\n (click)=\"savePreset(presetNameCtrl)\"\n type=\"button\"\n style=\"height: 32px\"\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center\"\n >\n <span style=\"margin-top: -2px\" *ngIf=\"isTablePresetNotChanged\">\n <ng-container *ngIf=\"!closeDropdown.preset.loading\"\n >Create</ng-container\n >\n <ng-container *ngIf=\"closeDropdown.preset.loading\"\n ><span class=\"spinner-border spinner-border-sm\"></span\n ></ng-container>\n </span>\n <span style=\"white-space: nowrap\" *ngIf=\"!isTablePresetNotChanged\"\n >Update Preset</span\n >\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #showHideColumns>\n <div\n (click)=\"$event.stopPropagation()\"\n class=\"p-3 action_dropdown_new_design actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\n style=\"width: 280px\"\n >\n <!-- Header -->\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <div class=\"d-flex align-items-center\">\n <button\n class=\"btn btn-link p-0\"\n style=\"margin-left: -10px\"\n (click)=\"toggleActions('setting')\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\n class=\"data-grid-svg-icon\"\n ></span>\n </button>\n <h6 class=\"mb-0 ms-2 text_common_14px\">Columns</h6>\n </div>\n <a\n (click)=\"resetColumns()\"\n href=\"javascript:void(0)\"\n class=\"text-primary text-decoration-none\"\n >Reset</a\n >\n </div>\n\n <!-- Search -->\n <div class=\"mb-3\">\n <div class=\"col-12 global-search position-relative\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\n class=\"mx-2 position-absolute icon data-grid-svg-icon\"\n ></span>\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Search column\"\n type=\"search\"\n [(ngModel)]=\"topShowHideColumns\"\n />\n </div>\n </div>\n <!-- Preset List -->\n <div\n class=\"list-group list-group-flush\"\n style=\"overflow: auto; scrollbar-width: thin\"\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight - 220\"\n >\n <div class=\"muted-text show-hide-table-label d-flex justify-content-between\" *ngIf=\"hasAnyVisibleColumn\">\n Show in table\n <div class=\"form-check\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n id=\"hide_all\"\n [checked]=\"allColumnsSelected()\"\n (change)=\"toggleAllColumnsVisibility()\"\n />\n <label class=\"form-check-label fw-semibold\" for=\"hide_all\">\n Show/Hide All \n </label>\n </div>\n </div>\n <!-- Item -->\n <ng-container\n *ngFor=\"\n let col of columns | filter : topShowHideColumns : 'header';\n trackBy: trackByField\n \"\n >\n <div\n *ngIf=\"col.is_visible\"\n class=\"list-group-item border-0 px-0 d-flex justify-content-between align-items-center\"\n >\n <div class=\"d-flex gap-1\">\n <div class=\"me-1\">\n <input type=\"checkbox\" [(ngModel)]=\"col.is_visible\" [checked]=\"col.is_visible\">\n <!-- show checkbox instead of icon -->\n <!-- <span\n *ngIf=\"!col?.pinned\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/grip-vertical.svg'\n \"\n class=\"cursor-grap data-grid-svg-icon\"\n (mousedown)=\"$event.preventDefault()\"\n ></span> -->\n <span\n *ngIf=\"col?.pinned\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/pin.svg'\n \"\n class=\"cursor-grap data-grid-svg-icon\"\n (mousedown)=\"$event.preventDefault()\"\n ></span>\n </div>\n <div class=\"fw-semibold\">\n {{ col.header }}\n </div>\n </div>\n <div\n *ngIf=\"!col?.query?.first_value && !col?.query?._ids?.length\"\n class=\"d-flex align-items-center cursor-pointer\"\n (click)=\"toggleColumnVisibility(col, false)\"\n [class.disabled]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\n [class.pe-none]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\n [class.opacity-50]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/columnIconNew(2).svg'\"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span>\n </div>\n <div\n *ngIf=\"col?.query?.first_value || col?.query?._ids?.length\"\n class=\"d-flex align-items-center\"\n style=\"opacity: 0.5\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/eye.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n </div>\n </div>\n </ng-container>\n\n <!-- Item End Here -->\n\n <div\n class=\"dropdown-divider\"\n *ngIf=\"hasAnyVisibleColumn && hasAnyInVisibleColumn\"\n ></div>\n\n <div\n class=\"muted-text show-hide-table-label d-flex justify-content-between\"\n *ngIf=\"hasAnyInVisibleColumn\"\n >\n Hide in table\n <div class=\"form-check\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n id=\"show_all\"\n [checked]=\"allColumnsSelected()\"\n (change)=\"toggleAllColumnsVisibility()\"\n />\n <label class=\"form-check-label fw-semibold\" for=\"show_all\">\n Show/Hide All \n </label>\n </div>\n </div>\n <div class=\"list-group list-group-flush\">\n <ng-container *ngFor=\"let col of columns; trackBy: trackByField\">\n <div\n *ngIf=\"!col.is_visible\"\n class=\"list-group-item border-0 px-0 d-flex justify-content-between align-items-center\"\n >\n <div class=\"d-flex gap-1\">\n <div class=\"me-1\">\n <input type=\"checkbox\" [(ngModel)]=\"col.is_visible\" [checked]=\"col.is_visible\">\n <!-- <span\n *ngIf=\"!col?.pinned\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/grip-vertical.svg'\n \"\n class=\"data-grid-svg-icon cursor-grap\"\n (mousedown)=\"$event.preventDefault()\"\n ></span> -->\n <span\n *ngIf=\"col?.pinned\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/pin.svg'\n \"\n class=\"data-grid-svg-icon cursor-grap\"\n (mousedown)=\"$event.preventDefault()\"\n ></span>\n </div>\n <div class=\"fw-semibold\">\n {{ col.header }}\n </div>\n </div>\n <div\n class=\"d-flex align-items-center cursor-pointer\"\n (click)=\"toggleColumnVisibility(col, true)\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/columnIconNew(2).svg'\n \"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Item End Here -->\n </div>\n </div>\n</ng-template>\n\n<ng-template #filterColumns let-col=\"column\">\n <div\n @slideToggle\n *ngIf=\"!isFilterOpen && activeTopButton == 'filter-columns'\"\n (click)=\"$event.stopPropagation()\"\n class=\"action_dropdown_new_design actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns\"\n style=\"width: 280px; right: unset; max-width: 230px\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n >\n <div class=\"py-2 px-3\">\n <div class=\"col-12 global-search position-relative\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\n class=\"data-grid-svg-icon mx-2 position-absolute icon\"\n ></span>\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Filter by\"\n type=\"search\"\n [(ngModel)]=\"addFilterColumnInput\"\n />\n </div>\n </div>\n <div\n class=\"list-group list-group-flush\"\n style=\"max-height: calc(100vh - 500px); overflow: auto\"\n >\n <ng-container\n *ngFor=\"\n let col of columns | filter : addFilterColumnInput : 'header';\n trackBy: trackByField\n \"\n >\n <div\n (click)=\"openFilter(col)\"\n *ngIf=\"\n col.is_visible &&\n !col?.query?.first_value &&\n !col?.query?._ids?.length && col.type !== 'image'\n \"\n class=\"list-group-item border-0 px-3 d-flex justify-content-between align-items-center dropdown-item cursor-pointer\"\n >\n <div class=\"d-flex align-items-center justify-content-between gap-1 w-100\">\n <!-- <div style=\"margin-top: -3px\"></div> -->\n <div class=\"fw-semibold\">\n {{ col.header }}\n </div>\n <div class=\"d-flex align-items-center justify-content-between\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Dropdown -->\n <div\n @slideToggle\n *ngIf=\"isFilterOpen && selectedColumnForFilter?.type == 'dropdown' || selectedColumnForFilter?.type == 'array'\"\n (click)=\"$event.stopPropagation()\"\n class=\"shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns pb-2\"\n style=\"width: 280px; right: unset; max-width: 230px\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n >\n <div class=\"px-3 my-2 border-below py-1 pb-2 mb-3 d-flex ps-1\">\n <span\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\n ></span\n ><b>{{ selectedColumnForFilter?.header }}</b>\n </div>\n <div class=\"mb-2 px-3\">\n <div\n class=\"col-12 position-relative border rounded d-flex align-items-center flex-wrap px-2 filter-serach-inpt\"\n >\n <span\n *ngFor=\"let selected of selectedFilterOptions\"\n class=\"badge d-flex align-items-center gap-1 me-1 mb-1 top-row-filter-dropdown\"\n >\n {{ selected?.value ? selected.value : selected }}\n <span\n (click)=\"toggleSelectionInFilter(selected)\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/cross-primary.svg'\n \"\n class=\"me-2\"\n ></span>\n </span>\n <input\n class=\"form-control form-control-sm border-0 flex-grow-1\"\n style=\"padding: 0\"\n [placeholder]=\"selectedFilterOptions?.length ? '' : 'Filter by'\"\n type=\"search\"\n [(ngModel)]=\"searchTextForFilterDropDown\"\n (keydown.backspace)=\"handleBackspace($event)\"\n />\n </div>\n </div>\n <div\n class=\"list-group list-group-flush\"\n style=\"max-height: calc(100vh - 600px); overflow: auto\"\n >\n <ng-container\n *ngFor=\"\n let col of selectedColumnForFilter?.column_dropdown_value\n | filter : searchTextForFilterDropDown : 'value';\n let i = index\n \"\n >\n <div\n class=\"list-group-item border-0 px-2 d-flex justify-content-between align-items-center dropdown-item cursor-pointer\"\n >\n <div class=\"form-check\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [id]=\"i\"\n [checked]=\"currentFilterSelectedIds.has(col.id || col._id || col)\"\n (change)=\"toggleSelectionInFilter(col)\"\n />\n <label class=\"form-check-label fw-semibold\" [for]=\"i\">\n {{ col?.value || col?.name || col }}\n </label>\n </div>\n </div>\n </ng-container>\n </div>\n <div\n class=\"d-flex justify-content-center gap-2 px-2 border-top\"\n style=\"height: 38px\"\n >\n <button\n type=\"button\"\n style=\"height: 32px\"\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\n (click)=\"$event.stopPropagation(); resetFilterChanges()\"\n >\n <span>Cancel</span>\n </button>\n <button\n type=\"button\"\n style=\"height: 32px\"\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\n (click)=\"applyDropdownFilter()\"\n >\n <span style=\"margin-top: -2px\">Save</span>\n </button>\n </div>\n </div>\n\n <!-- For Text fields and number fields-->\n\n <div\n @slideToggle\n *ngIf=\"\n isFilterOpen &&\n (selectedColumnForFilter?.type == 'string' ||\n selectedColumnForFilter?.type == 'number' ||\n selectedColumnForFilter?.type == 'date')\n \"\n (click)=\"$event.stopPropagation()\"\n class=\"shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns pb-2\"\n style=\"width: 210px; right: unset; max-width: 230px\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n >\n <div class=\"px-3 border-below py-1 pb-2 d-flex ps-1\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\n ></span\n ><b>{{ selectedColumnForFilter?.header }}</b>\n </div>\n <div class=\"col-12 position-relative p-2 text-filter\">\n <div class=\"mb-2\">\n <select\n class=\"form-select form-select-sm custom-select border\"\n [(ngModel)]=\"firstCondition\"\n >\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"before\">Less Then </option>\n <option value=\"after\">Greater Then </option>\n <option value=\"less_then_equal\">less then Equal to</option>\n <option value=\"greater_then_equal\">Greater then Equal to </option>\n </ng-container>\n </select>\n </div>\n <div class=\"mb-2\">\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Enter first value\"\n type=\"search\"\n [type]=\"\n selectedColumnForFilter?.type == 'string'\n ? 'text'\n : selectedColumnForFilter?.type\n \"\n [(ngModel)]=\"firstValue\"\n (keydown.enter)=\"applyDropdownFilter()\"\n />\n </div>\n <div>\n <div class=\"d-flex my-3 d-flex flex-row\" style=\"font-size: 14px\">\n <div\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input\"\n type=\"radio\"\n id=\"logicalAnd\"\n name=\"logicalOperator\"\n value=\"and\"\n [(ngModel)]=\"condition\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalAnd\"\n >AND</label\n >\n </div>\n\n <div\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input\"\n type=\"radio\"\n id=\"logicalOr\"\n name=\"logicalOperator\"\n value=\"or\"\n [(ngModel)]=\"condition\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalOr\">OR</label>\n </div>\n\n <div\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input\"\n type=\"radio\"\n id=\"logicalNone\"\n name=\"logicalOperator\"\n value=\"none\"\n [(ngModel)]=\"condition\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalNone\"\n >None</label\n >\n </div>\n </div>\n\n <ng-container *ngIf=\"condition !== 'none' && firstValue\">\n <div class=\"mb-2 mt-3\">\n <!-- Second condition select -->\n <select\n class=\"form-select form-select-sm border\"\n [(ngModel)]=\"secondCondition\"\n >\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"before\">Less Then </option>\n <option value=\"after\">Greater Then </option>\n <option value=\"less_then_equal\">less then Equal to</option>\n <option value=\"greater_then_equal\">Greater then Equal to </option>\n </ng-container>\n </select>\n </div>\n\n <div class=\"mb-2\">\n <!-- Second value input -->\n <input\n [type]=\"\n selectedColumnForFilter?.type == 'string'\n ? 'text'\n : selectedColumnForFilter?.type\n \"\n class=\"form-control form-control-sm\"\n placeholder=\"Enter second value\"\n type=\"search\"\n [(ngModel)]=\"secondValue\"\n (keydown.enter)=\"applyDropdownFilter()\"\n />\n </div>\n </ng-container>\n </div>\n </div>\n\n <div\n class=\"d-flex justify-content-center gap-2 px-2 border-top\"\n style=\"height: 38px\"\n >\n <button\n [disabled]=\"!currentFilterSelectedIds?.size && !firstValue\"\n type=\"button\"\n style=\"height: 32px\"\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\n (click)=\"$event.stopPropagation(); resetTextFilterChanges()\"\n >\n <span>Cancel</span>\n </button>\n <button\n [disabled]=\"(currentFilterSelectedIds?.size === 0 && !firstValue) || (condition !== 'none' && !secondValue)\"\n type=\"button\"\n style=\"height: 32px\"\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\n (click)=\"applyDropdownFilter()\"\n >\n <span style=\"margin-top: -2px\">Apply</span>\n </button>\n </div>\n </div>\n</ng-template>\n\n<!-- Edit dropdown here -->\n<ng-template let-col>\n <div class=\"drop-down-edit\"></div>\n</ng-template>\n\n<ng-template\n #fullTextTemplate\n let-row=\"row\"\n let-col=\"col\"\n let-isArray=\"isArray\"\n>\n <div\n class=\"full-text-box\"\n (dblclick)=\"$event.stopPropagation(); $event.preventDefault()\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight / 2\"\n >\n <ng-container *ngIf=\"!isEditing(row, col)\">\n <div\n *ngIf=\"!isArray\"\n class=\"full-text-content\"\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight / 2\"\n (dblclick)=\"\n $event.stopPropagation();\n $event.preventDefault();\n enableEdit(row, col, true)\n \"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n >\n {{\n getNestedValue(row, col.field)?.value ||\n getNestedValue(row, col.field)?.name ||\n getNestedValue(row, col.field)\n }}\n </div>\n <div *ngIf=\"isArray\">\n <ul>\n <ng-container\n *ngFor=\"let item of getNestedValue(row, col.field); let i = index\"\n >\n <li *ngIf=\"i !== 0\">\n <ng-container>\n {{\n item?.department_name ||\n item?.roleName ||\n item?.full_name ||\n \"-\"\n }}\n </ng-container>\n </li>\n </ng-container>\n </ul>\n </div>\n </ng-container>\n <ng-container *ngIf=\"isEditing(row, col)\">\n <textarea\n (dblclick)=\"\n $event.stopPropagation();\n $event.preventDefault();\n enableEdit(row, col, true)\n \"\n #textModel=\"ngModel\"\n rows=\"4\"\n #textAreadInput\n [(ngModel)]=\"row[col.field]\"\n name=\"{{ col.field }}\"\n required\n (blur)=\"disableEdit(row, col, textModel)\"\n (keydown.enter)=\"textAreadInput.blur()\"\n autofocus\n class=\"form-control\"\n [ngClass]=\"{\n 'is-invalid': textModel.invalid\n }\"\n (mousedown)=\"$event.stopPropagation()\"\n ></textarea>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #defaultImagePlaceholder let-row=\"row\" let-col=\"col\">\n <span\n class=\"px-2 d-flex w-100 cell-content image-placeholder\"\n [title]=\"row?.full_name || row?.name || 'N/A'\"\n >\n <ng-container\n *ngIf=\"\n row?.logo ||\n row?.assetImage ||\n row?.invoice?.invoice_image ||\n row?.invoice_image;\n else placeholder\n \"\n >\n <span\n (click)=\"fullscreenImage = row?.profile_pictures?.[4]?.path ||\n row?.logo ||\n row?.assetImage ||\n row?.invoice_image\"\n class=\"pic\"\n [style.width.px]=\"rowHeight - 10\"\n [style.height.px]=\"rowHeight - 10\"\n [class.assets-pic]=\"gridType == 'Assets'\"\n >\n <img\n [width]=\"rowHeight - 12\"\n [height]=\"rowHeight - 12\"\n [style.width.px]=\"rowHeight - 10\"\n [style.height.px]=\"rowHeight - 10\"\n [src]=\"\n row?.profile_pictures?.[4]?.path ||\n row?.logo ||\n row?.assetImage ||\n row?.invoice_image\n \"\n alt=\"icon\"\n class=\"option-icon\"\n loading=\"lazy\"\n />\n </span>\n </ng-container>\n <!-- <div\n class=\"fullscreen-overlay\"\n *ngIf=\"fullscreenImage\"\n (click)=\"fullscreenImage = null\"\n >\n <img [src]=\"fullscreenImage\" class=\"fullscreen-img\" />\n </div> -->\n\n <ng-template #placeholder>\n <span\n [ngClass]=\"getDynamicClass(row?.full_name || row?.name)\"\n class=\"pic d-flex align-items-center rounded-circle\"\n [style.width.px]=\"rowHeight - 12\"\n [style.height.px]=\"rowHeight - 12\"\n [style.fontSize.px]=\"rowHeight / 3\"\n [class.assets-pic]=\"gridType == 'Assets'\"\n >\n {{ getInitials(row?.full_name) }}\n </span>\n </ng-template>\n </span>\n</ng-template>\n\n<!-- Right Click Menue -->\n<div\n [class.invisible]=\"!positionedYet\"\n class=\"context-menu p-2\"\n *ngIf=\"actionHide && actions?.length\"\n [ngStyle]=\"{ 'top.px': yPos, 'left.px': xPos }\"\n [class.show]=\"isVisible\"\n appendTo=\"body\"\n>\n <ul>\n <li\n *ngFor=\"let action of actions\"\n class=\"rounded d-flex align-items-center\"\n (click)=\"onActionClick(action)\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/' + action + '.svg'\"\n class=\"data-grid-svg-icon right-click-menu-icons me-2\"\n ></span>\n <span class=\"text-capitalize fw-500\">{{ action }}</span>\n </li>\n </ul>\n</div>\n\n<!-- Details Toggle from bottom -->\n\n<ng-template #nestedTableTemplate let-row>\n <div\n class=\"nested-table table table-sm w-100 mb-0 center-nested-table w-100\"\n style=\"table-layout: fixed !important\"\n #nestedTableContainer\n >\n <thead\n #nestedHeader\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\n >\n <div\n cdkDropList\n [cdkDropListData]=\"row?.detail.columns\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"dropColumn($event, row)\"\n (cdkDropListSorted)=\"onNestedColSort($event, previewNestedCols)\"\n [style.height.px]=\"nestedTableHeaderRowHeight\"\n class=\"d-flex tr border-below\"\n >\n <div\n *ngFor=\"let col of row.detail.columns; let i = index\"\n [style.width.px]=\"col?.width || 250\"\n [style.minWidth.px]=\"col?.width || 250\"\n [style.maxWidth.px]=\"col?.width || 250\"\n class=\"px-4 th\"\n [attr.field]=\"col.field\"\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\n cdkDrag\n >\n <div\n class=\"d-flex h-100 justify-content-between position-relative align-items-center\"\n >\n <div class=\"text-ellipsis\" (click)=\"sortNestedCol(col, row)\">\n {{ col.header }}\n </div>\n <div class=\"d-flex gap-2\">\n <span\n *ngIf=\"currentSubSortColumn == col.field\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n (col?.order_by == 'desc'\n ? 'data-grid/icons/sort-desc.svg'\n : 'data-grid/icons/sort-asc.svg')\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center ms-2 start-50\"\n >\n </span>\n <!-- <div\n class=\"three-dots p-1\"\n (click)=\"openThreeDotsMenu($event, col)\"\n style=\"cursor: pointer\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/three-dots-vertical.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div> -->\n\n <!-- Only show menu if this column is active -->\n <div\n class=\"position-absolute\"\n *ngIf=\"activeCol === col\"\n style=\"top: -50%; z-index: 21; left: 0\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n columnMenu;\n context: {\n col: col,\n isNestedTable: true,\n columns: row?.detail.columns\n }\n \"\n ></ng-container>\n </div>\n <div\n class=\"resize-handle\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"\n $event.preventDefault();\n onResizeColumn($event, col);\n $event.stopPropagation()\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n </div>\n <ng-template cdkDragPreview>\n <div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ col.header }}</div>\n </div>\n </ng-template>\n </div>\n </div>\n </thead>\n <div\n [style.width.px]=\"nestedHeader.offsetWidth - 10\"\n [style.minWidth.px]=\"nestedHeader.offsetWidth - 10\"\n >\n <cdk-virtual-scroll-viewport\n [itemSize]=\"nestedTablerowHeight\"\n class=\"viewport\"\n [style.height.px]=\"\n (row?.detail?.result?.length < 5\n ? nestedTablerowHeight * row?.detail?.result?.length + 40\n : 300) + (hasHorizontalScroll ? -12 : 1)\n \"\n [style.width.px]=\"nestedHeader.offsetWidth - 10\"\n [style.minWidth.px]=\"nestedHeader.offsetWidth - 10\"\n >\n <div\n class=\"cursor-pointer border-below d-flex tr\"\n *cdkVirtualFor=\"let d of row?.detail?.result; trackBy: trackById\"\n [style.height.px]=\"nestedTablerowHeight\"\n [style.width.px]=\"nestedHeader?.offsetWidth\"\n [style.minWidth.px]=\"nestedHeader?.offsetWidth\"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n (contextmenu)=\"onRightClick($event, d)\"\n >\n <div\n class=\"px-4 py-0 td\"\n *ngFor=\"let col of previewNestedCols; let j = index\"\n [style.fontSize.px]=\"nestedTablerowFontsize\"\n [attr.field]=\"col.field\"\n [style.width.px]=\"col?.width || 250\"\n [style.minWidth.px]=\"col?.width || 250\"\n [style.maxWidth.px]=\"col?.width || 250\"\n >\n <div\n [style.height.px]=\"nestedTablerowHeight - 1\"\n [style.max-width.px]=\"col?.width\"\n class=\"d-flex align-items-center\"\n >\n <!-- {{ d[col.field] || (col.is_amount ? 0 : \"-\") }} -->\n <div\n #cellText\n class=\"text-ellipsis flex-grow-1\"\n [title]=\"\n col.type === 'date'\n ? (getNestedValue(d, col.field) | date : dateFormat)\n : getNestedValue(d, col.field) || '-'\n \"\n >\n <ng-container *ngIf=\"col.type !== 'image'\">\n <ng-container *ngIf=\"col.is_amount\">{{\n currencySymbol\n }}</ng-container>\n {{\n !isNestedValueArray(d, col.field)\n ? col.type === 'date'\n ? (isDate(getNestedValue(d, col.field))\n ? (getNestedValue(d, col.field) | date: dateFormat)\n : (getNestedValue(d, col.field)?.value ||\n getNestedValue(d, col.field)?.name ||\n getNestedValue(d, col.field) ||\n '-'))\n : (getNestedValue(d, col.field)?.value ||\n getNestedValue(d, col.field)?.name ||\n getNestedValue(d, col.field) ||\n (col.is_amount ? 0: '-'))\n : (getNestedValue(d, col.field)?.[0]?.department_name ||\n getNestedValue(d, col.field)?.[0]?.roleName || getNestedValue(d, col.field)?.[0]?.full_name ||\n '-')\n }}\n </ng-container>\n <ng-container *ngIf=\"false\">\n {{ getTotalAmount(col) }}\n </ng-container>\n <ng-container *ngIf=\"col.type == 'image'\">\n <ng-container\n *ngTemplateOutlet=\"\n defaultImagePlaceholder;\n context: {\n row: d,\n col: col,\n }\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n </div>\n </cdk-virtual-scroll-viewport>\n </div>\n </div>\n</ng-template>\n\n<ng-template #leftRightNestedPlaceholder let-row>\n <table\n class=\"nested-table table table-sm w-100 mb-0\"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n [style.height.px]=\"\n gridType == 'Assets'\n ? (nestedTableContainer?.nativeElement?.offsetHeight ?? 0) + 12\n : (taskManagementContainer?.nativeElement?.offsetHeight ?? 0)\n \"\n >\n <!-- <div class=\"thead\">\n <div\n class=\"tr d-flex border-below\"\n [style.height.px]=\"nestedTableHeaderRowHeight\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n >\n <div class=\"th\" *ngFor=\"let _ of [1, 2, 3, 4, 5]\"></div>\n </div>\n </div> -->\n <!-- <div class=\"tbody\">\n <div\n class=\"tr border-below\"\n [style.height.px]=\"nestedTablerowHeight\"\n *ngFor=\"let _ of row?.detail?.result\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n >\n <div class=\"td\" *ngFor=\"let __ of [1, 2, 3, 4, 5]\" class=\"py-0\">\n <span\n [style.height.px]=\"nestedTablerowHeight\"\n [style.max-width.px]=\"nestedTablerowHeight\"\n ></span>\n </div>\n </div>\n </div> -->\n </table>\n</ng-template>\n\n<ng-template #taskManagementTemplate let-taskDetails=\"taskDetails\">\n <div\n class=\"p-4\"\n #taskManagementContainer\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\n [style.fontFaimly]=\"fontFaimly\"\n >\n <div class=\"d-flex justify-content-between\">\n <div class=\"col-4\">\n <div class=\"item-title\">Description</div>\n <!-- <div class=\"item-content firstDiv\">\n {{ taskDetails.description }}\n </div> -->\n <p\n [style.fontSize]=\"bodyTextFontsSize\"\n class=\"item-content firstDiv taskDescription pe-4\"\n [innerHTML]=\"getSafeComment(taskDetails?.editor_description)\"\n (click)=\"openFullImage($event)\"\n ></p>\n </div>\n <div class=\"col-4\">\n <div class=\"item-title\">Attachments</div>\n <h5 *ngIf=\"taskDetails?.attachments?.length == 0\">\n No Attachments found\n </h5>\n <div\n *ngIf=\"taskDetails?.attachments?.length\"\n class=\"item-content d-flex flex-wrap\"\n style=\"gap: 10px\"\n >\n <a\n *ngFor=\"let attachement of taskDetails?.attachments; let i = index\"\n class=\"symbol-label fs-2 fw-semibold text-success cursor-pointer\"\n >\n <span\n title=\"{{ taskDetails?.attachments_name[i] || 'Attachment' }}\"\n (click)=\"downloadAttchment(attachement)\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/document-icons/' +\n getExtention(attachement) +\n '.svg'\n \"\n >\n </span>\n </a>\n </div>\n </div>\n <div class=\"col-4\">\n <div class=\"item-title\">\n Comments ({{ taskDetails?.comments?.length }})\n </div>\n <h5 *ngIf=\"taskDetails?.comments?.length == 0\">No Comments found</h5>\n <div *ngIf=\"taskDetails?.comments?.length\" class=\"item-content\">\n <div class=\"comment\" *ngFor=\"let comment of taskDetails.comments\">\n <div class=\"d-flex align-items-center pe-3\">\n <img\n class=\"pic image-input-wrapper\"\n [style.width.px]=\"rowHeight - 12\"\n [style.height.px]=\"rowHeight - 12\"\n *ngIf=\"comment?.comment_by.logo\"\n src=\"{{ comment?.comment_by.logo }}\"\n alt=\"{{ comment.comment_by.full_name }}\"\n />\n <!-- <app-default-image-placeholder *ngIf=\"!comment?.comment_by.logo\" title=\"{{ comment.comment_by.full_name }}\" [name]=\"comment.comment_by.full_name\"></app-default-image-placeholder> -->\n <span\n *ngIf=\"!comment?.comment_by.logo\"\n [ngClass]=\"getDynamicClass(comment.comment_by.full_name)\"\n class=\"pic d-flex align-items-center rounded-circle\"\n [style.width.px]=\"rowHeight - 12\"\n [style.height.px]=\"rowHeight - 12\"\n [style.fontSize.px]=\"rowHeight / 3\"\n title=\"{{ comment.comment_by.full_name }}\"\n >\n {{ getInitials(comment.comment_by.full_name) }}\n </span>\n </div>\n <div>\n <div class=\"comment-author fs-14px\">\n {{ comment?.comment_by.full_name }}\n </div>\n <div\n class=\"comment-content forCommentImg\"\n [innerHTML]=\"getSafeComment(comment.comment)\"\n ></div>\n <div class=\"comment-timestamp\">\n {{ comment.comment_date | date }}\n </div>\n <div class=\"comment-timestamp\">\n Replies: ({{ comment.replies.length }})\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";@import\"bootstrap/dist/css/bootstrap.min.css\";:host,:host *{font-family:Inter,sans-serif!important}.data-grid-table-wrapper{height:100%;width:100%;border:1px solid #E0E0E0;border-radius:12px;position:relative}.data-grid-header{position:sticky;top:0}.data-grid-header{display:flex}.header-row{display:grid;width:100%}.header-cell{display:flex;align-items:center;position:relative;width:100%;padding:0 0 0 8px;font-weight:700;border-bottom:1px solid #E0E0E0;white-space:nowrap;min-width:80px;font-weight:600}.header-cell .filter-applied-on-text{color:#5d9cff!important}.filter-cell{padding:4px!important;display:flex;align-items:center;gap:8px;width:100%}.filter-cell .filter-applied{background-color:#bddef9}.border-right{border-right:1px solid #E0E0E0}.merged-grid{display:grid;grid-auto-rows:40px;border-bottom:1px solid #ccc}.span-two-rows{grid-row:span 2;display:flex;justify-content:space-between;align-items:center}.group-header{display:flex;justify-content:space-between;position:relative}.group-header-content{position:sticky;left:10px;overflow:hidden;text-overflow:ellipsis}.resize-handle{width:6px;cursor:e-resize;right:0;top:0;color:#00000026;margin-right:4px}:host ::ng-deep .resize-handle svg{stroke-width:2px}.group-header .resize-handle{top:25%}.h-100{height:100%}.data-grid-body{position:relative;overflow-y:auto;overflow-x:hidden}.cell{padding:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:100%;display:flex;align-items:center}.data-grid-row{display:flex;width:100%;min-width:max-content;align-items:center;border-bottom:1px solid #E0E0E0}.hovered-row{background-color:#ccc}.checkbox-row{border-bottom:#E0E0E0}.w-100{width:100%}.data-grid-header-wrapper{display:flex;position:relative;overflow:hidden;-webkit-user-select:none;user-select:none}.data-grid-header{display:flex;position:relative;z-index:1}.left-pinned,.right-pinned{position:sticky;top:0}.right-pinned-header{position:absolute;right:0;border-left:1px solid #E0E0E0;z-index:unset}.left-pinned{left:0}.right-pinned{right:0;border-left:1px solid #E0E0E0}.center-scrollable{z-index:unset!important;overflow-x:auto;overflow-y:visible;white-space:nowrap;scrollbar-width:none;-ms-overflow-style:none}.center-scrollable::-webkit-scrollbar{display:none}.data-grid-body-wrapper{-webkit-user-select:none;user-select:none;display:flex}.center-scrollable-body{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}.center-scrollable-body::-webkit-scrollbar{display:none}.left-pinned-body,.right-pinned-body{position:sticky;top:0;z-index:unset;background:#fff;scrollbar-width:none;-ms-overflow-style:none}.left-pinned-body::-webkit-scrollbar,.right-pinned-body::-webkit-scrollbar{display:none}.left-pinned-body{left:0}.border-end{border-right:1px solid #E0E0E0!important}.right-pinned-body{right:0;border-left:1px solid #E0E0E0}.fake-scroll-bar{height:14px;overflow:scroll;margin-bottom:10px}.text-ellipsis{overflow:hidden;text-overflow:ellipsis}.select-all-checkbox-cell{width:50px;display:flex;justify-content:center;align-items:center;height:100%}.select-all-checkbox-cell input{width:16px;height:14px}.border-below{border-bottom:1px solid #E0E0E0!important}.figmaIconSize.data-grid-svg-icon{width:24px!important;height:24px!important}.actions-dropdown .list-group .list-group-item{color:#1b1f22!important}.productSortingDropdownMenu{width:220px!important}.three-dots{width:24px;height:24px;display:flex;justify-content:center;align-items:center;border-radius:6px;margin-right:4px;margin-left:2px;cursor:pointer}.three-dots:hover,.three-dots.threeDotActive{background-color:#0084ff1a;padding:5px}.rotated-180{transform:scaleY(-1)}.filter-icon-wrapper{min-height:22px;max-height:22px;min-width:22px;max-width:22px;display:flex;justify-content:center;align-items:center;border-radius:3px;cursor:pointer;transition:background-color .3s ease}.filter-icon-wrapper:hover{background-color:#ccc}.column-menu,.filter-menu{box-shadow:0 0 16px #00000026;border-radius:4px}.column-menu{background:#fff;width:100%;width:200px;border:1px solid #ddd;box-shadow:0 0 12px #00000014;border:1px solid #E0E0E0;padding:4px 0;font-size:14px;position:fixed;border-radius:8px}.column-menu-item{padding:8px 12px;cursor:pointer;display:flex;align-items:center;transition:background-color .2s ease}.column-menu-item.active-sort,.column-menu-item:hover{background-color:#0084ff1a}.pin-parent{position:relative;width:100%!important}.column-submenu{position:absolute;top:0;left:100%;background:#fff;border:1px solid #ddd;width:130px;box-shadow:0 0 16px #00000026;border:1px solid #E0E0E0;display:none;padding:4px 0;z-index:10;border-radius:4px}.pin-parent:hover .column-submenu{display:block}.filter-menu-container{position:fixed;width:210px;background:#fff;border:1px solid #ddd;border-radius:4px;padding:12px;box-shadow:0 0 16px #00000026;border:1px solid #E0E0E0;z-index:1000;font-size:14px}.filter-menu-header{font-weight:600;margin-bottom:10px}.filter-dropdown-section{max-height:350px;overflow-y:auto}.dropdown-options{overflow-y:auto;scrollbar-width:thin;height:100%}.filter-text-section select,.filter-text-section input{width:100%}.filter-radio-inputs{width:14px!important;height:14px!important}.right-menu{border-left:1px solid #E0E0E0;font-size:14px}.border-start{border-left:1px solid #E0E0E0!important}.column-panel-item{font-size:.875rem;color:#333}.toggle-icon{cursor:pointer;transition:transform .2s ease}.toggle-icon.rotate{transform:rotate(90deg)}.grab-icon{cursor:grab;color:#6c757d}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cursor-pointer{cursor:pointer}.pivot-mode{height:48px}.chevron-wrapper{width:30px;height:20px;cursor:pointer;border-radius:3px;display:flex;justify-content:center;align-items:center;transition:background-color .3s ease;margin-right:8px}.chevron-wrapper:hover{background-color:#cac7c7}.chevron-wrapper i{font-size:14px}.column-panel-body{height:70%;overflow:auto;scrollbar-width:thin}.side-menue-text{transform:rotate(90deg);position:relative;font-weight:700;margin-top:40px}.columns-button{padding-top:20px;padding-bottom:35px;width:29px}.fake-scroll-content{height:12px}.fake-scrollbar{width:25px}.fake-scrollbar div{min-width:1px}.fake-horizintal-scrollbar div{min-height:1px}.side-filter-columns-wrapper{height:calc(100% - 25px)}.custom-modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;overflow:hidden;display:flex;justify-content:center;align-items:center;z-index:1050}.custom-modal-overlay .moda-header{background-color:#f8f8f8}.custom-modal-content{background-color:#fff;border-radius:8px;min-width:300px;max-width:400px;box-shadow:0 5px 20px #0000004d}.overlay-scrollable{height:250px;overflow:auto}.footer-row{border-top:1px solid #E0E0E0;padding-left:32px}.fake-horizintal-scrollbar{position:relative;bottom:17px;overflow-x:auto;overflow-y:hidden;height:17px}.border-dashed{border:1px dashed #E0E0E0}.cdk-drag-preview{box-sizing:border-box!important;border-radius:4px!important;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f!important;background-color:#f3f4f5!important;border:1px solid #E0E0E0!important;z-index:9999!important}.data-grid-header-wrapper ::ng-deep .cdk-drag-placeholder{display:block!important;background:#fff!important;opacity:1!important}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)!important}.top-row-grouping-placeholder{display:flex;align-items:center;border-radius:12px;font-size:14px;padding-inline:6px;border:1px solid #E0E0E0}.top-row-grouping-placeholder .bi-x{cursor:pointer;color:#7a7a7a}.top-row-grouping-placeholder .bi-x:hover{color:#111}.right-pinned-body-wrapper{position:absolute;right:0}.actions-dropdown{position:absolute;right:200px;z-index:1050;background-color:#fff;border-radius:8px!important;cursor:default}.bg-fff{background-color:#fff}.actions-dropdown-setting{right:250px}.action-button{background-color:#007cf5!important;border-radius:8px!important;padding:8px 16px!important;font-size:14px;height:32px;align-items:center}.global-search{width:100%;display:flex!important;align-items:center!important;height:32px;max-width:335px}.global-search span{margin-top:0!important;top:8px}.global-search input{padding-left:28px;border-radius:8px!important}.global-search input:focus{outline:none!important;box-shadow:none!important}.active .top-icon ::ng-deep svg path{stroke:#007cf5!important}.dropdown-menu{background-color:#fff!important;border:1px solid #E0E0E0!important;border-radius:8px!important}.custom-menu{width:250px;border-radius:8px;padding:4px 0;background-color:#fff}.custom-menu.setting_dropdown_menu{width:270px}.custom-menu .dropdown-item{font-size:14px;padding:8px 14px;color:#1b1f22!important;font-weight:400}.custom-menu .dropdown-item:hover{background-color:#0084ff1a;border-radius:6px}.table-layout{right:0;background:#fff;border-radius:8px!important}.actions-dropdown,.table-layout,.custom-menu,.dropdown-menu{background:#fff;border-radius:8px!important;border:1px solid #E0E0E0!important;background-color:#fff}.action_dropdown_new_design{background:#fff;border-radius:8px!important;border:1px solid #E0E0E0!important;box-shadow:0 2px 12px #00000014}.preview-box{width:40px;height:10px;border-radius:3px;background-color:transparent;transition:background-color .2s ease-in-out}.btn-check:checked+label .preview-box{background-color:var(--bs-primary)}.preview-box{width:40px;height:10px;border-radius:3px;border:2px solid transparent;transition:border-color .2s ease-in-out}#small:checked+label{border-color:#0084ff!important;background-color:#f5f5f5!important;color:#1b1f22!important}#small:checked+label .preview-box{background-color:#fff!important}#medium:checked+label{border-color:#0084ff!important;background-color:#f5f5f5!important;color:#1b1f22!important}#medium:checked+label .preview-box{background-color:#fff!important}#large:checked+label{border-color:#0084ff!important;background-color:#f5f5f5!important;color:#1b1f22!important}#large:checked+label .preview-box{background-color:#fff!important}.btn-check:checked+.btn{background-color:transparent!important;border-color:#007cf5!important}.layout-button{padding:8px 6px!important;width:82px;border-radius:8px!important;color:#1b1f22!important;height:60px;margin-bottom:0!important}.show-hide-table-label{position:sticky;top:0;z-index:99;background:#fff}.cursor-grap{cursor:grabbing}.pagination-container{display:flex;align-items:center;gap:12px;font-size:14px;color:#1b1f22}.page-size select{padding:3px 6px;border:1px solid #E0E0E0;border-radius:6px;background:#fff;font-size:13px}.page-buttons{display:flex;gap:4px;margin-left:auto;align-items:center}.page-buttons button{padding:7px 11px;background:#fff;border-radius:4px;cursor:pointer;font-size:13px;line-height:1.2;border:0;color:#6a6b6d}.page-buttons button.active{font-weight:400;border:1px solid #E0E0E0;border-radius:8px;font-size:14px;color:#1b1f22}.page-buttons button:disabled{opacity:.5;cursor:not-allowed}.page-buttons span{padding:0 6px;color:#666}.page-size .separator{padding:0 8px;border-right:1px solid #E0E0E0}.page-size .separator .actions-dropdown{position:fixed;right:200px;z-index:1050;background-color:#fff}.fs-14px{font-size:14px}.fs-12px{font-size:12px!important}.save-preset-dropdown{background:#fff;color:#111!important;right:0;font-weight:400!important;text-align:left!important;max-width:250px!important;text-wrap:auto!important;top:14px;font-size:14px!important}.add-filter-button{height:28px;cursor:pointer;border-radius:4px}.table-layout .dropdown-item{border-radius:0!important;font-size:14px;padding-block:6px!important}.table-layout .dropdown-item:hover{background-color:transparent!important}.filter-serach-inpt{max-height:230px!important;overflow:auto;scrollbar-width:thin;padding-top:4px;background-color:#f7f7f7;border-color:#dedede;border-radius:8px}.filter-serach-inpt .badge{color:#007cf5!important;background-color:#e6f2ff!important;border-radius:8px!important;padding:8px!important;font-weight:500!important;font-size:12px!important;height:24px!important}.filter-serach-inpt .badge ::ng-deep svg{cursor:pointer}.filter-serach-inpt .badge ::ng-deep svg:hover path{stroke:#040081!important}.filter-serach-inpt input{background-color:#f7f7f7;padding:0;height:26px;margin-top:-5px}.text-filter select{border:0}.text-filter select option{font-size:14px;font-weight:500}.text-filter select:focus{border:0}.text-filter input:focus,.text-filter select:focus{box-shadow:none!important}.active-filters{background-color:#f7f7f7;white-space:nowrap;background:#f7f7f7;padding-inline:8px;height:28px;font-size:14px;font-weight:500;border-radius:8px;box-shadow:none}.active-filters .header-tag{white-space:nowrap;font-size:14px;font-weight:400;color:#1b1f22;background:#ebebeb}.filter-tags .active{background-color:#e6f2ff}.filter-tags .active .header-tag{color:#007cf5!important}.table-cell{cursor:pointer;width:100%}.table-cell input:focus{outline:0!important;border:0!important;width:100%!important;box-shadow:none!important}.active-for-editing{outline:2.5px solid #007cf5!important;border-radius:4px;border:0!important;width:100%!important}.active-cell{outline:none!important;box-shadow:inset 0 0 0 1.5px #007cf5}span[inlineSVG]{width:16px;height:16px;display:inline-block}.cell .dropdown-menu{min-width:unset!important}.cell .dropdown-menu .item{transition:background-color .3s ease;display:flex;align-items:center;-webkit-user-select:none;user-select:none}.cell .dropdown-menu .item:hover{background-color:#f0f8ff}.cell .cell-editin-dropdown{scrollbar-width:thin!important;-webkit-user-select:none;user-select:none}.fw-semibold{font-weight:500!important}:host ::ng-deep .three-dots-col-menu span:not(.no-stroke) svg,:host ::ng-deep .three-dots-col-menu span:not(.no-stroke) svg path{stroke:#000!important}:host ::ng-deep .ascendingAppliedIcon svg{stroke:#006fd6}.fs-7{font-size:12px!important}.fs-8{font-size:10px!important}.all-filters-reset-button:hover{opacity:.7}.full-text-box{background:#fff;position:relative;display:flex;align-items:center;justify-content:center;z-index:1050;border:1px solid #dedede;border-radius:8px;padding:12px 14px;box-shadow:0 2px 8px #00000026}.full-text-content{border-radius:8px;max-height:70vh;overflow:auto;white-space:pre-wrap}.pic{border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:22px}.pic-comb2{background-color:#fbe7bf;color:#fd7f31}.pic-comb1{background-color:#d9ecbf;color:#65b500}.pic-comb4{background-color:#fdd3d7;color:#f64e60}.w-40px{width:40px}.h-40px{height:40px}.pic{border-radius:50%;overflow:hidden}.image-placeholder .pic{font-size:14px;font-weight:600;letter-spacing:.5px}.header-cell{font-weight:600}.header-cell,.cell{box-sizing:border-box}.transparent-border-right{border-right:1px solid transparent!important}.resizing-highlight{position:relative}.resizing-highlight:before{content:\"\";position:absolute;top:-1px;right:-1px;width:2px;height:calc(100% + 2px);background:#7cb9f6;z-index:1000;pointer-events:none}.resizing-highlight-right{position:relative}.resizing-highlight-right:before{content:\"\";position:absolute;top:-1px;left:-1px;width:2px;height:calc(100% + 2px);background:#7cb9f6;z-index:1000;pointer-events:none}.resizing-highlight-right:first-child{width:1px}.editable-header{border-bottom:1px dashed #666}.muted-text{color:#727272!important}.context-menu{position:fixed;display:none;background:#fff;border:1px solid #dcdcdc;box-shadow:#0000003d 0 3px 8px;z-index:1000;width:150px;border-radius:8px;font-weight:600}.context-menu.show{display:block}.context-menu ul{list-style:none;margin:0;padding:0}.context-menu li{padding:10px;cursor:pointer;color:#99a1b7}.context-menu li ::ng-deep svg{width:16px;height:16px;display:inline-block;color:#727272}.context-menu li ::ng-deep svg path{stroke:#727272}.context-menu li:hover{background-color:#f0f0f5!important}.invisible{visibility:hidden!important}.fw-500{font-weight:500!important}.taskbar{position:fixed;display:flex;justify-content:center;z-index:1000}.taskbar .action-btn{transition:opacity text-decoration .3s ease}.taskbar .action-btn:hover{text-decoration:underline;opacity:.8}.taskbar .delete{color:#ea0000}.selected-count,.action-btn,.dropdown-content a{font-weight:500;font-size:14px}.selected-rows-action-bar{background-color:#1a1a1a;color:#fff;padding:4px 24px;border-radius:8px;display:flex;align-items:center;justify-content:space-between;gap:24px;box-shadow:0 -4px 12px #00000026}.selected-rows-action-bar .btn:active,.selected-rows-action-bar .btn:focus{outline:0!important;border:0!important;border-color:transparent!important}.selected-rows-action-bar .action-btn{color:#fff!important}.cell .dropdown-menu,.cell .form-select,.cell input{color:#000!important}.cell input::placeholder{color:#727272!important}.cell .badge{border-radius:4px!important;height:24px;align-items:center;width:-moz-fit-content;width:fit-content}.cell .badge-danger{color:#ea5353!important;border:1px solid #ea5353!important;background-color:#ff00000d!important}.cell .badge-success{background-color:#84ca8130!important;border:1.5px solid rgb(70,227,114)!important;color:#46e372!important}.cell .badge-warning{background-color:#fff3dc!important;color:orange!important;border:1px solid #ffa000!important}.cell .badge-info{color:#00bad1;background-color:#e8fbfd;border:1px solid #00bad1}.cell .badge-secondary{color:#6c757d;background-color:#f1f3f5;border:1px solid #6c757d}.header-tag ::ng-deep svg path{stroke:#727272!important}.cross-secondary:hover ::ng-deep svg path{stroke:#000!important}.disable-sorting{pointer-events:none;opacity:.5}.rows-grouping-top-container ::ng-deep .cdk-drag-placeholder{background-color:transparent!important}input.is-invalid:focus{border:2.5px solid red!important;outline:none}.table-cell input.is-invalid:focus{border:2.5px solid red!important;outline-color:red!important;outline:none!important;box-shadow:none!important}.active-for-editing:has(input.is-invalid:focus){outline:none!important;box-shadow:none!important;border:0!important}.selected-cell,.row-selected{background-color:#c2e0fe}.first-row-selected{border-top:2px solid #2196f3!important}.last-row-selected{border-bottom:2px solid #2196f3!important}.left-selection-border{border-left:2px solid #2196f3!important}.s-no{font-size:14px;font-weight:500}.top-border{border-top:2px solid #2196f3!important}.bottom-border{border-bottom:2px solid #2196f3!important}.left-border{border-left:2px solid #2196f3!important}.border-left{border-left:1px solid #E0E0E0}.right-border{border-right:2px solid #2196f3!important}.top-left-corner{border-top-left-radius:4px}.top-right-corner{border-top-right-radius:4px}.bottom-left-corner{border-bottom-left-radius:4px}.bottom-right-corner{border-bottom-right-radius:4px}.flash-bg{animation:flashAnim 1000s ease}@keyframes flashAnim{0%{background-color:#48a2fc}50%{background-color:#c2e0fe}to{background-color:#c2e0fe}}.cut-flash-bg{animation:cut-flash .8s ease}@keyframes cut-flash{0%{background-color:#f006}50%{background-color:#f00c}to{background-color:#c2e0fe}}.accordion-details .center-section .table .tbody .tr:hover .td{background-color:#f0f8ff!important}.editing-dropdown-search-input input:focus{border:1px solid #86b7fe!important}.nested-table .thead{position:sticky;top:0}.dropdown-wrapper{position:relative;display:inline-block}.btn-icon{background:transparent;border:0;padding:.25rem .5rem;cursor:pointer}.custom-dropdown-menu{position:absolute;right:0;top:calc(100% + 6px);min-width:200px;list-style:none;margin:0;padding:.25rem 0;background:#fff!important;border:1px solid rgba(0,0,0,.08);box-shadow:0 6px 18px #00000014;border-radius:.35rem;z-index:1200}.custom-dropdown-menu .dropdown-item{display:block;width:100%;padding:.5rem 1rem;text-align:left;background:transparent;border:none}.custom-dropdown-menu .dropdown-item:hover{background:#00000008}.confirm-block{padding:0}.center-nested-table .tr:hover .td{background-color:#f0f8ff}.table ::ng-deep .cdk-drag-placeholder{background-color:#fff!important}.assets-pic{border-radius:8px!important}.fullscreen-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000c;display:flex;align-items:center;justify-content:center;z-index:1000;cursor:zoom-out}.fullscreen-img{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 0 15px #00000080}.position-sticky{z-index:2}.viewport{display:block!important;overflow:visible!important}.nested-table ::ng-deep .cdk-virtual-scroll-content-wrapper{padding:0!important}.nested-table ::ng-deep .cdk-virtual-scroll-viewport{overflow-x:hidden!important}.disabled-search-input{background-color:#f5f5f5;cursor:pointer!important}.right-click-menu-icons ::ng-deep svg path{stroke-width:2!important}.loader{animation:rotate 1s infinite;height:50px;width:50px}.loader:before,.loader:after{border-radius:50%;content:\"\";display:block;height:20px;width:20px}.loader:before{animation:ball1 1s infinite;background-color:#fff;box-shadow:30px 0 #ff3d00;margin-bottom:10px}.loader:after{animation:ball2 1s infinite;background-color:#ff3d00;box-shadow:30px 0 #fff}@keyframes rotate{0%{transform:rotate(0) scale(.8)}50%{transform:rotate(360deg) scale(1.2)}to{transform:rotate(720deg) scale(.8)}}@keyframes ball1{0%{box-shadow:30px 0 #ff3d00}50%{box-shadow:0 0 #ff3d00;margin-bottom:0;transform:translate(15px,15px)}to{box-shadow:30px 0 #ff3d00;margin-bottom:10px}}@keyframes ball2{0%{box-shadow:30px 0 #fff}50%{box-shadow:0 0 #fff;margin-top:-20px;transform:translate(15px,15px)}to{box-shadow:30px 0 #fff;margin-top:0}}.rows-grouping-top-container ::ng-deep .cdk-drag-placeholder{opacity:.7!important}.action-button{background-color:#6f61cf!important;color:#fff!important;border-radius:6px!important;font-weight:500!important;margin-top:-4px}.action-button:hover{background-color:#6a5fb3!important}.action-buttons-row .button{display:inline-flex;align-items:center;justify-content:center;overflow:hidden;color:#fff;border-radius:6px;height:34px;padding:0 10px;white-space:nowrap;transition:max-width .4s ease,background-color .3s ease;max-width:40px;background-color:transparent;border:1px solid #6F61CF}.action-buttons-row .button .label-hidden{opacity:0;margin-left:8px;transition:opacity .3s ease;pointer-events:none;display:none}.action-buttons-row .button:hover{max-width:200px;background-color:#6f61cf}.action-buttons-row .button:hover .label-hidden{opacity:1;pointer-events:auto;margin-left:8px!important;display:block}.action-buttons-row ::ng-deep .button .svg-icon svg path{stroke:#6f61cf;transition:fill .3s ease,stroke .3s ease}.action-buttons-row ::ng-deep .button:hover .svg-icon svg path{stroke:#fff!important}::ng-deep .nav-tabs .nav-link{border:none!important;border-bottom:2px solid transparent!important;border-radius:0!important;background:transparent!important}::ng-deep .nav-tabs .nav-link:hover,::ng-deep .nav-tabs .nav-link:focus{border:none!important;border-bottom:2px solid transparent!important;outline:none!important;background:transparent!important}::ng-deep .nav-tabs .nav-link.active{border:none!important;border-bottom:2px solid var(--bs-primary)!important;background:transparent!important;color:var(--bs-primary)!important}.open-top{top:-150%!important}.muted{color:#7a7a7a!important}.item-title{font-size:1.2em;font-weight:700;margin-bottom:10px}.item-image{width:100%;border-radius:10px}.comment{display:flex;align-items:center;margin-bottom:10px}.comment-avatar{width:40px;height:40px;border-radius:50%;margin-right:10px}.comment-author{font-weight:700}.comment-content{font-size:.9em;line-height:1.4}.comment-timestamp{font-size:.8em;color:#888;margin-left:auto}.des_low{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;width:242px;display:block;text-transform:capitalize!important}.firstDiv{word-break:break-word;overflow-wrap:break-word;white-space:normal}.container{display:flex;flex-wrap:wrap;margin:20px;gap:20px;background-color:#fff;padding:20px;border-radius:10px}.item{width:calc(33.33% - 20px);background-color:#fff;padding:20px;border-radius:10px;box-shadow:0 2px 5px #0000001a}.forCommentImg{width:70px;border-radius:16px;margin:8px 0;cursor:pointer}.image-modal img{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 4px 10px #00000080}.full-image-modal{position:fixed;background:#000c;display:flex;justify-content:center;align-items:center;z-index:1000}.full-image-modal .full-image{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 0 10px #fff3}.item-content{font-size:14px;line-height:1.5;max-height:220px;overflow-y:auto}.image-modal.full-image-modal{position:fixed;width:100vw;height:100vh;background-color:#000c;display:flex;justify-content:center;align-items:center;z-index:9999;overflow:hidden;cursor:zoom-out}.image-modal.full-image-modal img{border-radius:8px;box-shadow:0 4px 20px #0006;object-fit:contain;transition:transform .3s ease}.image-modal.full-image-modal img:hover{transform:scale(1.02)}::ng-deep .custom-overlay-wrapper .custom-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000000d9;display:flex;align-items:center;justify-content:center;z-index:9999}::ng-deep .custom-overlay-wrapper .custom-modal{background:#fff;border-radius:12px;box-shadow:0 8px 25px #0003;width:360px;max-width:90%;padding:24px;text-align:center;animation:fadeInScale .25s ease}::ng-deep .custom-overlay-wrapper .custom-modal-body .modal-message{font-size:16px;margin-bottom:20px;color:#333}::ng-deep .custom-overlay-wrapper .modal-actions{display:flex;justify-content:center;gap:12px}::ng-deep .custom-overlay-wrapper .modal-actions button{min-width:90px;padding:8px 14px;border-radius:6px;border:none;font-weight:500;cursor:pointer;transition:background-color .2s ease}::ng-deep .custom-overlay-wrapper .btn-confirm{background-color:#007bff;color:#fff}::ng-deep .custom-overlay-wrapper .btn-confirm:hover{background-color:#0069d9}::ng-deep .custom-overlay-wrapper .btn-cancel{background-color:#e4e4e4;color:#333}::ng-deep .custom-overlay-wrapper .btn-cancel:hover{background-color:#d6d6d6}@keyframes fadeInScale{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.clear-btn{background:linear-gradient(135deg,#f53545,#f53545);border:none;color:#fff;font-size:13px;padding:3px 6px;border-radius:20px;font-weight:500;display:inline-flex;align-items:center;gap:6px;cursor:pointer;transition:all .3s ease;box-shadow:0 2px 6px #ff5f6d66;position:relative;bottom:4px}.clear-btn:hover{transform:translateY(-2px);box-shadow:0 4px 10px #ff5f6d99;background:linear-gradient(135deg,#f53545,#f53545)}.clear-btn i{font-size:16px;vertical-align:middle}.cell-editin-dropdown .deopdown-item{width:100%!important;box-shadow:none!important;border-radius:4px;cursor:pointer;padding-block:8px!important}.cell-editin-dropdown .deopdown-item:hover{background-color:#f1f1f1}.card-outer{border:1px solid var(--semantics-border-subtle-secondary, #E0E0E0);border-radius:16px;padding:16px;background-color:#fff}.consumerDropdownButton{height:32px;display:flex;align-items:center}a.grid-header-icon:hover{background:#e0e0e0;width:32px;height:32px;border-radius:8px;transition:none}a.grid-header-icon{width:32px;height:32px}.action-buttons-row.active a.grid-header-icon,a.grid-header-icon.show{background-color:#e0e0e0;border-radius:8px}.data-grid-svg-icon.setting_dropdown{width:32px!important;height:32px!important}.new_design_dropdown .dropdown_main_button{color:#6a6b6d;text-decoration:none}.new_design_dropdown ul{border-radius:8px!important;border:1px solid #E0E0E0!important;box-shadow:0 0 12px #00000014!important}.new_design_dropdown ul li{color:#1b1f22!important;height:32px}.new_design_dropdown ul li:hover{background:#0084ff1a!important}.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg{height:inherit;border-radius:6px;padding:6px 10px;color:#1b1f22!important;font-size:14px;font-weight:400}.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg .new_old_filter{display:inline-block;width:24px;height:24px}.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg label,.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg span.newest,.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg span.oldest{padding-left:5px}.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg:hover{background-color:transparent!important}.new_design_dropdown ul li .action_dropdown{padding:6px 16px}.new_design_dropdown ul li.active-filter{background-color:#0084ff1a}.new_design_dropdown.hide_arrow .dropdown-toggle:after{display:none}.new_design_dropdown.hide_arrow ul li a label{line-height:1}.dropdown_main_button{border-radius:8px;transition:none;padding:5px 10px}.dropdown_main_button:hover,.dropdown_main_button.show{background:#e0e0e0}.sorting_icon_input{width:24px;height:24px;display:flex;align-items:center;justify-content:center}.sorting_dropdown .column-menu-item{padding:0 6px!important;color:#1b1f22!important;font-size:14px!important;font-weight:400!important}.greenBgHover{background:#0084ff1a!important;border-radius:6px!important}.cancel_btn_new{font-weight:400!important;font-size:14px!important;color:#1b1f22!important;border:none;box-shadow:none;background:transparent;height:32px;padding:3px 14px;display:flex;align-items:center;justify-content:center}.primary_btn_new{font-weight:500!important;font-size:14px!important;color:#fff!important;background:#0084ff;border:none;box-shadow:none;height:32px;padding:3px 14px;display:flex;align-items:center;justify-content:center;border-radius:6px}.dropdown_outer{border:1px solid #E0E0E0;box-shadow:0 2px 12px #00000014;border-radius:8px;font-size:14px}.text_common_14px{font-size:14px;font-weight:400;color:#1b1f22}.text_common_16px{font-size:16px;font-weight:500;color:#1b1f22}.page_refresh{font-size:13px;font-weight:400;color:#6a6b6d}\n"], dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i6.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i6.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i6.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i6.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i8.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i8.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i8.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i8.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i8.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i8.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i8.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i8.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i8.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i8.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i9.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i9.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i9.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i9.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: i9.CdkDragPreview, selector: "ng-template[cdkDragPreview]", inputs: ["data", "matchSize"] }, { kind: "directive", type: i9.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "directive", type: i10.InlineSVGDirective, selector: "[inlineSVG]", inputs: ["inlineSVG", "resolveSVGUrl", "replaceContents", "prepend", "injectComponent", "cacheSVG", "setSVGAttributes", "removeSVGAttributes", "forceEvalStyles", "evalScripts", "fallbackImgUrl", "fallbackSVG", "onSVGLoaded"], outputs: ["onSVGInserted", "onSVGFailed"] }, { kind: "directive", type: i11.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i11.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i11.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CellRenderInitDirective, selector: "[cellRenderInit]", inputs: ["cellRenderInit", "rowData", "colData", "cellValue"], outputs: ["cellEvent"] }, { kind: "pipe", type: i6.SlicePipe, name: "slice" }, { kind: "pipe", type: i6.DatePipe, name: "date" }, { kind: "pipe", type: FilterPipe, name: "filter" }], animations: [
|
|
6128
6103
|
trigger('accordionToggle', [
|
|
6129
6104
|
state('collapsed', style({ height: '0px', overflow: 'unset' })),
|
|
6130
6105
|
state('expanded', style({ height: '*', overflow: 'unset' })),
|
|
@@ -6340,7 +6315,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
6340
6315
|
], { optional: true })
|
|
6341
6316
|
]),
|
|
6342
6317
|
])
|
|
6343
|
-
], template: "<div class=\"position-relative h-100\">\r\n <div\r\n class=\"d-flex justify-content-between mb-2 align-items-center position-relative\"\r\n >\r\n <div class=\"d-flex gap-2\">\r\n <div class=\"nav nav-tabs\" *ngIf=\"true\">\r\n <div class=\"nav nav-tabs\" id=\"nav-tab\" role=\"tablist\">\r\n <span\r\n *ngFor=\"let tab of tabs; let i = index\"\r\n (click)=\"setActiveTab(tab)\"\r\n class=\"nav-link cursor-pointer\"\r\n [class.active]=\"activeTab == tab\"\r\n >\r\n {{ tab }}\r\n </span>\r\n </div>\r\n </div>\r\n <div class=\"global-search\" [style.width.px]=\"350\">\r\n <span\r\n *ngIf=\"enableGlobalSearch\"\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\r\n class=\"data-grid-svg-icon mx-2 position-absolute icon\"\r\n ></span>\r\n <input\r\n *ngIf=\"enableGlobalSearch\"\r\n style=\"height: 36px\"\r\n class=\"form-control\"\r\n placeholder=\"Type to search, then press Enter\"\r\n [(ngModel)]=\"tableSearch\"\r\n (keydown.enter)=\"onGlobalSearch()\"\r\n (input)=\"onSearchInput($event)\"\r\n type=\"search\"\r\n />\r\n </div>\r\n </div>\r\n <div class=\"d-flex gap-2 align-items-center table-right-top-actions\">\r\n <ng-container *ngFor=\"let button of buttons\">\r\n <div\r\n class=\"d-flex align-items-center gap-2 action-buttons-row\"\r\n *ngIf=\"button?.has_permission\"\r\n >\r\n <a\r\n href=\"JavaScript:void(0)\"\r\n (click)=\"onActionButtonClick(button.name)\"\r\n class=\"button button-small btn border border-primary btn-active-primary me-2 p-0 d-flex align-items-center justify-content-center px-3\"\r\n >\r\n <span\r\n *ngIf=\"button.is_showIcon\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/' + button.icon + '.svg'\r\n \"\r\n class=\"svg-icon svg-icon-2\"\r\n ></span>\r\n <span\r\n class=\"label-hidden text-white\"\r\n [class.ms-0]=\"button.is_showIcon\"\r\n >{{ button?.name }}</span\r\n >\r\n </a>\r\n </div>\r\n </ng-container>\r\n <div\r\n *ngIf=\"!showFilterRow\"\r\n class=\"cursor-pointer position-relative action-buttons-row\"\r\n (click)=\"toggleOpenFilter()\"\r\n [class.active]=\"showFilters\"\r\n >\r\n <a\r\n href=\"JavaScript:void(0)\"\r\n class=\"button button-small btn btn-active-primary border border-primary me-2 p-0 d-flex align-items-center justify-content-center px-3\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\r\n class=\"svg-icon svg-icon-2\"\r\n ></span>\r\n <span class=\"label-hidden text-white\">Filters</span>\r\n </a>\r\n <span\r\n *ngIf=\"activeFilteredColumns?.length\"\r\n style=\"\r\n width: 7px;\r\n height: 7px;\r\n box-shadow: 0px 0px 3px #0022ff;\r\n background-color: rgb(0, 60, 255);\r\n position: absolute;\r\n right: 16px;\r\n top: 10px;\r\n \"\r\n class=\"rounded-circle d-block\"\r\n ></span>\r\n </div>\r\n <div\r\n class=\"cursor-pointer d-none\"\r\n (click)=\"toggleActions('advance-filter')\"\r\n [class.active]=\"activeTopButton === 'advance-filter'\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/zoom-charge.svg'\"\r\n class=\"data-grid-svg-icon top-icon me-2\"\r\n ></span>\r\n </div>\r\n <div\r\n class=\"cursor-pointer action-buttons-row\"\r\n (click)=\"toggleActions('setting')\"\r\n [class.active]=\"\r\n activeTopButton === 'setting' ||\r\n activeTopButton === 'table-layout' ||\r\n activeTopButton === 'table-presets' ||\r\n activeTopButton === 'show-hide-columns'\r\n \"\r\n >\r\n <!-- <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/settings-2.svg'\"\r\n class=\"data-grid-svg-icon top-icon me-2\"\r\n ></span> -->\r\n <a\r\n href=\"JavaScript:void(0)\"\r\n class=\"button button-small btn btn-active-primary border border-primary me-2 p-0 d-flex align-items-center justify-content-center px-3\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/settings-2.svg'\"\r\n class=\"svg-icon svg-icon-2\"\r\n ></span>\r\n <span class=\"label-hidden text-white\">Setting</span>\r\n </a>\r\n\r\n <div\r\n *ngIf=\"activeTopButton === 'setting'\"\r\n class=\"actions-dropdown mt-1 actions-dropdown-setting\"\r\n style=\"position: absolute\"\r\n >\r\n <div class=\"dropdown-menu show shadow custom-menu\">\r\n <!-- Table Layout -->\r\n <a\r\n class=\"dropdown-item d-flex justify-content-between align-items-center cursor-pointer\"\r\n (click)=\"$event.stopPropagation(); toggleActions('table-layout')\"\r\n >\r\n <span\r\n ><span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/table-2.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Table Layout</span\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </a>\r\n <!-- Table Presets -->\r\n <a\r\n (click)=\"$event.stopPropagation(); toggleActions('table-presets')\"\r\n class=\"dropdown-item d-flex justify-content-between align-items-center cursor-pointer\"\r\n >\r\n <span\r\n ><span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/list-details.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Table Presets</span\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </a>\r\n\r\n <!-- Columns -->\r\n <a\r\n *ngIf=\"!showSideMenu\"\r\n (click)=\"\r\n $event.stopPropagation(); toggleActions('show-hide-columns')\r\n \"\r\n class=\"dropdown-item d-flex justify-content-between align-items-center cursor-pointer\"\r\n >\r\n <span class=\"align-items-center d-flex\"\r\n ><span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/eye.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Columns</span\r\n >\r\n <div class=\"d-flex gap-2\">\r\n <span class=\"muted-text\">{{ columnsCount }}</span>\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </div>\r\n </a>\r\n\r\n <div class=\"dropdown-divider\"></div>\r\n\r\n <!-- Filter -->\r\n <a\r\n class=\"dropdown-item cursor-pointer\"\r\n (click)=\"toggleOpenFilter(); activeTopButton = '';\"\r\n *ngIf=\"!showFilterRow\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2 mt-1 cursor-pointer\"\r\n ></span>\r\n Filter\r\n </a>\r\n\r\n <!-- Download -->\r\n <a\r\n class=\"dropdown-item cursor-pointer\"\r\n (click)=\"downloadCsv('csv')\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/download.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\r\n ></span>\r\n CSV Export\r\n </a>\r\n <a\r\n *ngIf=\"enableExport\"\r\n class=\"dropdown-item cursor-pointer\"\r\n (click)=\"downloadCsv('xlsx')\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/download.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\r\n ></span>\r\n Excel Export\r\n </a>\r\n <!-- Font Family & Font Size -->\r\n <div class=\"px-2 pb-2 pt-2\">\r\n <div class=\"d-flex gap-2\">\r\n <!-- Font Family -->\r\n <select\r\n class=\"form-select form-select-sm\"\r\n [(ngModel)]=\"fontFaimly\"\r\n (change)=\"onFontChange()\"\r\n >\r\n <option *ngFor=\"let font of fontFamilies\" [value]=\"font\">\r\n {{ font }}\r\n </option>\r\n </select>\r\n\r\n <!-- Font Size -->\r\n <select\r\n class=\"form-select form-select-sm\"\r\n (change)=\"onFontChange()\"\r\n [(ngModel)]=\"bodyTextFontsSize\"\r\n >\r\n <option *ngFor=\"let size of fontSizes\" [value]=\"size\">\r\n {{ size }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Table Layout -->\r\n\r\n <ng-container *ngIf=\"activeTopButton === 'table-layout'\">\r\n <div\r\n *ngTemplateOutlet=\"tableLayout\"\r\n class=\"actions-dropdown mt-1\"\r\n style=\"position: absolute\"\r\n ></div>\r\n </ng-container>\r\n\r\n <!-- Table Presets -->\r\n <ng-container *ngIf=\"activeTopButton === 'table-presets'\">\r\n <div\r\n *ngTemplateOutlet=\"tablePreset\"\r\n class=\"actions-dropdown mt-1\"\r\n style=\"position: absolute\"\r\n ></div>\r\n </ng-container>\r\n\r\n <!-- Table Presets -->\r\n <ng-container *ngIf=\"activeTopButton === 'show-hide-columns'\">\r\n <div\r\n *ngTemplateOutlet=\"showHideColumns\"\r\n class=\"actions-dropdown mt-1\"\r\n style=\"position: absolute\"\r\n ></div>\r\n </ng-container>\r\n </div>\r\n\r\n <div class=\"action-buttons-row\" *ngIf=\"showFullScreenButton\">\r\n <a\r\n *ngIf=\"!isFullScreen\"\r\n class=\"button button-small btn btn-active-primary border border-primary expend d-flex justify-content-center align-items-center\"\r\n (click)=\"toggleFullscreen()\"\r\n data-bs-toggle=\"tooltip\"\r\n data-bs-placement=\"top\"\r\n title=\"Minimise\"\r\n [ngClass]=\"{ minArrow: !isFullScreen, maxArrow: isFullScreen }\"\r\n style=\"transition: color 0.2s\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/expend.svg'\"\r\n class=\"svg-icon svg-icon-2 mb-1\"\r\n ></span>\r\n </a>\r\n <a\r\n *ngIf=\"isFullScreen\"\r\n class=\"button button-small btn btn-active-primary border border-primary expend d-flex justify-content-center align-items-center\"\r\n (click)=\"toggleFullscreen()\"\r\n data-bs-toggle=\"tooltip\"\r\n data-bs-placement=\"top\"\r\n title=\"Maximise\"\r\n [ngClass]=\"{ minArrow: !isFullScreen, maxArrow: isFullScreen }\"\r\n style=\"transition: color 0.2s\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/minimize.svg'\"\r\n class=\"svg-icon svg-icon-2 mb-1\"\r\n ></span>\r\n </a>\r\n </div>\r\n <div>\r\n <!-- Example single danger button -->\r\n\r\n <!-- <button\r\n type=\"button\"\r\n class=\"btn btn-primary btn-sm d-flex gap-2 action-button\"\r\n (click)=\"toggleActions('actions')\"\r\n >\r\n Action\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/Vector.svg'\"\r\n class=\"data-grid-svg-icon\"\r\n ></span>\r\n </button>\r\n <div\r\n *ngIf=\"activeTopButton === 'actions'\"\r\n class=\"actions-dropdown mt-1\"\r\n >\r\n <div class=\"dropdown-menu show\">\r\n <a class=\"dropdown-item\" href=\"#\">Action</a>\r\n <a class=\"dropdown-item\" href=\"#\">Another action</a>\r\n <a class=\"dropdown-item\" href=\"#\">Something else here</a>\r\n <div class=\"dropdown-divider\"></div>\r\n <a class=\"dropdown-item\" href=\"#\">Separated link</a>\r\n </div>\r\n </div> -->\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"showFilters && !showFilterRow\"\r\n class=\"top-filter-row border-top py-2 d-flex justify-content-between align-items-center\"\r\n [style.height.px]=\"topFilterRowHeight\"\r\n >\r\n <!-- LEFT SIDE (Filter tags + Filter button) -->\r\n <div class=\"d-flex gap-2 align-items-center\">\r\n <ng-container>\r\n <div\r\n *ngFor=\"let col of activeFilteredColumns; trackBy: trackByField\"\r\n class=\"filter-tags\"\r\n >\r\n <div\r\n (click)=\"\r\n isActiveFilterOpen = true;\r\n activeTopButton = 'filter-columns';\r\n openFilter(col)\r\n \"\r\n class=\"d-flex justify-content-center align-items-center muted-text add-filter-button active-filters\"\r\n style=\"white-space: nowrap\"\r\n [class.active]=\"\r\n col?.field == selectedColumnForFilter?.field &&\r\n isActiveFilterOpen &&\r\n activeTopButton == 'filter-columns'\r\n \"\r\n >\r\n <span class=\"header-tag mt-0 d-flex align-items-center\">\r\n <span\r\n *ngIf=\"col?.pinned\"\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pin.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n {{ col.header }}\r\n <span\r\n (click)=\"\r\n $event.stopPropagation(); removeColumnFilterFromColumn(col)\r\n \"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/cross-primary.svg'\r\n \"\r\n class=\"data-grid-svg-icon cross-secondary ms-2 mb-1\"\r\n ></span>\r\n </span>\r\n </div>\r\n\r\n <ng-container\r\n *ngIf=\"\r\n activeTopButton === 'filter-columns' &&\r\n col?.field == selectedColumnForFilter?.field &&\r\n isActiveFilterOpen\r\n \"\r\n >\r\n <div\r\n *ngTemplateOutlet=\"filterColumns; context: { column: col }\"\r\n class=\"actions-dropdown mt-1\"\r\n ></div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Filter Button -->\r\n <div class=\"add-filter-button-menu\">\r\n <div\r\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\r\n class=\"d-flex justify-content-center align-items-center muted-text add-filter-button button-filter\"\r\n style=\"width: 70px\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/plus.svg'\"\r\n class=\"me-2 data-grid-svg-icon\"\r\n ></span>\r\n Filter\r\n </div>\r\n\r\n <ng-container\r\n *ngIf=\"activeTopButton === 'filter-columns' && !isActiveFilterOpen\"\r\n >\r\n <div\r\n *ngTemplateOutlet=\"filterColumns\"\r\n class=\"actions-dropdown mt-1\"\r\n ></div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- RIGHT SIDE (Update + Reset) -->\r\n <div class=\"d-flex gap-3 align-items-center\">\r\n <div\r\n (click)=\"savePreset()\"\r\n class=\"text-primary cursor-pointer all-filters-reset-button\"\r\n *ngIf=\"!checkFilterChangesEffect()\"\r\n >\r\n Update View\r\n </div>\r\n\r\n <div\r\n class=\"text-primary cursor-pointer all-filters-reset-button\"\r\n *ngIf=\"!tableFilterViewId && activeFilteredColumns?.length\"\r\n (click)=\"clearAllFilters()\"\r\n >\r\n Reset\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div\r\n [style.height]=\"\r\n showFilters ? 'calc(100% - ' + topFilterRowHeight + 'px)' : '100%'\r\n \"\r\n cdkDropListGroup\r\n class=\"data-grid-table-wrapper overflow-hidden\"\r\n #dataGridContainer\r\n [style.fontFamily]=\"fontFaimly\"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n id=\"data-grid-main-container\"\r\n >\r\n <div\r\n *ngIf=\"showRowsGrouping\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [cdkDropListData]=\"columns\"\r\n [style.backgroundColor]=\"\r\n topGroupedBadgesBackgroundColor || headerBackgroundColor\r\n \"\r\n cdkDropList\r\n (cdkDropListEntered)=\"enterToTopRowGrouping($event)\"\r\n (cdkDropListExited)=\"exitedFromTheTopRow($event)\"\r\n (cdkDropListDropped)=\"onDropTopGroup($event)\"\r\n [cdkDropListEnterPredicate]=\"canEnterToRowsGrouping\"\r\n id=\"rows-grouping-top-container\"\r\n class=\"border-below d-flex px-4 align-items-center\"\r\n >\r\n <div\r\n class=\"d-flex gap-2 align-items-center\"\r\n [style.color]=\"headerTextColor\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <div *ngIf=\"!draggingInGroupArea && !groupedColumns?.length\">\r\n Drag here to set row groups\r\n </div>\r\n <div\r\n cdkDropListOrientation=\"horizontal\"\r\n cdkDropList\r\n (cdkDropListDropped)=\"onGroupReorder($event)\"\r\n class=\"d-flex\"\r\n >\r\n <div\r\n cdkDrag\r\n [cdkDragLockAxis]=\"'x'\"\r\n *ngFor=\"\r\n let child of groupedColumns;\r\n let i = index;\r\n trackBy: trackByField\r\n \"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: child,\r\n showChevron:\r\n groupedColumns.length > 1 && i != groupedColumns.length - 1\r\n }\r\n \"\r\n ></ng-container>\r\n <ng-template cdkDragPreview\r\n ><div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n *ngIf=\"!draggingInGroupArea\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ child.header }}</div>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div\r\n class=\"d-flex overflow-hidden\"\r\n [style.height]=\"\r\n 'calc(100% - ' +\r\n (showRowsGrouping\r\n ? headerRowHeight + footerRowHeight\r\n : footerRowHeight) +\r\n 'px)'\r\n \"\r\n >\r\n <div\r\n class=\"h-100\"\r\n [style.width]=\"\r\n !showSideMenu\r\n ? '100%'\r\n : sideMenuVisible\r\n ? 'calc(100% - 280px)'\r\n : 'calc(100% - 30px)'\r\n \"\r\n >\r\n <div class=\"h-100 transition position-relative w-100\">\r\n <!-- ##################################################################################################################################################################################### -->\r\n <!-- ##################################################################################################################################################################################### -->\r\n <!-- Data Grid Header starts here -->\r\n <!-- ##################################################################################################################################################################################### -->\r\n <!-- ##################################################################################################################################################################################### -->\r\n\r\n <div\r\n class=\"data-grid-header-wrapper w-100\"\r\n [style.color]=\"headerTextColor\"\r\n [style.fontSize.px]=\"headerTextFontsSize\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n [class.border-below]=\"!hasAnyVisibleColumn\"\r\n [style.height.px]=\"\r\n showColumnsGrouping && showFilterRow\r\n ? headerRowHeight * 3\r\n : showColumnsGrouping || showFilterRow\r\n ? headerRowHeight * 2\r\n : headerRowHeight\r\n \"\r\n >\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <!-- Data Grid Left Pinned Header starts here -->\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <div\r\n class=\"data-grid-header left-pinned\"\r\n #leftPinnedHeader\r\n [class.border-right]=\"hasLeftPinnedColumns\"\r\n >\r\n <div\r\n *ngIf=\"showSerialNumber\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n class=\"select-all-checkbox-cell border-below\"\r\n [style.width.px]=\"55\"\r\n [style.height.px]=\"\r\n showColumnsGrouping && showFilterRow\r\n ? headerRowHeight * 3\r\n : showColumnsGrouping || showFilterRow\r\n ? headerRowHeight * 2\r\n : headerRowHeight\r\n \"\r\n >\r\n S.No\r\n </div>\r\n <div\r\n *ngIf=\"showCheckboxes\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n class=\"select-all-checkbox-cell border-below\"\r\n [style.height.px]=\"\r\n showColumnsGrouping && showFilterRow\r\n ? headerRowHeight * 3\r\n : showColumnsGrouping || showFilterRow\r\n ? headerRowHeight * 2\r\n : headerRowHeight\r\n \"\r\n >\r\n <input\r\n *ngIf=\"hasAnyVisibleColumn\"\r\n style=\"width: 16px; height: 16px\"\r\n type=\"checkbox\"\r\n [indeterminate]=\"isIndeterminateState(dataSet)\"\r\n [checked]=\"isAllSelected(dataSet)\"\r\n (change)=\"toggleSelectAll(dataSet)\"\r\n />\r\n </div>\r\n <div\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n class=\"d-flex\"\r\n cdkDropList\r\n id=\"left-pinned-header\"\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListData]=\"leftPinnedColumns\"\r\n (cdkDropListEntered)=\"onDropListEnter($event, 'left')\"\r\n (cdkDropListSorted)=\"\r\n onSortGroup($event, 'previewLeftPinnedColumns')\r\n \"\r\n (cdkDropListDropped)=\"onDropGroup()\"\r\n style=\"min-width: 1px\"\r\n >\r\n <div\r\n class=\"dragable-header\"\r\n cdkDrag\r\n [cdkDragData]=\"col\"\r\n *ngFor=\"\r\n let col of leftPinnedColumns;\r\n let i = index;\r\n trackBy: trackByField\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n index: i,\r\n section: 'previewLeftPinnedColumns'\r\n }\r\n \"\r\n ></ng-container>\r\n <ng-template cdkDragPreview\r\n ><div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n *ngIf=\"!draggingInGroupArea\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/arrows-move.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ col.header }}</div>\r\n </div>\r\n </ng-template>\r\n <ng-template cdkDragPlaceholder>\r\n <div *ngIf=\"!draggingInGroupArea\">\r\n <div\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n index: i,\r\n section: ''\r\n }\r\n \"\r\n ></div>\r\n </div>\r\n <div\r\n *ngIf=\"draggingInGroupArea\"\r\n class=\"d-flex gap-2 ms-2\"\r\n style=\"opacity: 0.6\"\r\n >\r\n <ng-container\r\n *ngIf=\"col?.children?.length; else singleCol\"\r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let child of col.children;\r\n let i = index;\r\n trackBy: trackByField\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: child,\r\n showChevron:\r\n col.children.length > 1 &&\r\n i != col.children.length - 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #singleCol>\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: col,\r\n showChevron: col?.children?.length > 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <!-- Data Grid Center Pinned Header starts here -->\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <div\r\n class=\"data-grid-header center-scrollable\"\r\n #centerPinnedHeader\r\n (scroll)=\"onCenterBodyScroll($event)\"\r\n id=\"center-pinned-header\"\r\n cdkDropList\r\n [cdkDropListConnectedTo]=\"\r\n showRowsGrouping ? ['rows-grouping-top-container'] : []\r\n \"\r\n [cdkDropListData]=\"centerColumns\"\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListSortingDisabled]=\"\r\n isDisableColumnGrouping && draggingInGroupArea\r\n \"\r\n (cdkDropListEntered)=\"onDropListEnter($event, 'center')\"\r\n (cdkDropListSorted)=\"onSortGroup($event, 'previewCenterColumns')\"\r\n (cdkDropListDropped)=\"onDropGroup()\"\r\n [style.maxWidth]=\"\r\n 'calc(100% - ' +\r\n (rightPinnedHeader.offsetWidth + leftPinnedHeader.offsetWidth) +\r\n 'px)'\r\n \"\r\n >\r\n <div\r\n *ngIf=\"groupedColumns?.length\"\r\n style=\"min-width: 200px\"\r\n class=\"h-100 align-items-center\"\r\n #columnsGroupedBox\r\n id=\"groupBoxHeaderDiv\"\r\n >\r\n <div\r\n class=\"d-flex w-100 justify-content-between align-items-center border-below\"\r\n [style.height.px]=\"\r\n showFilterRow ? headerRowHeight * 2 : headerRowHeight\r\n \"\r\n >\r\n <div class=\"ps-3\">Group</div>\r\n <div class=\"d-flex\">\r\n <div\r\n class=\"three-dots cursor-pointer\"\r\n (click)=\"\r\n openThreeDotsMenu($event, 'group');\r\n isThreeDotsFilterOpen = false\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/three-dots-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div\r\n (mousedown)=\"\r\n $event.stopPropagation(); onResizeGroupBox($event)\r\n \"\r\n class=\"resize-handle\"\r\n style=\"margin-right: -2px\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div\r\n [style.height.px]=\"headerRowHeight\"\r\n class=\"border-below\"\r\n ></div>\r\n </div>\r\n <span\r\n class=\"d-flex align-items-center justify-content-center cursor-pointer border-below\"\r\n style=\"min-width: 30px; height: 100%\"\r\n *ngIf=\"gridType === 'Assets' || gridType === 'Tasks'\"\r\n >\r\n </span>\r\n <div\r\n class=\"dragable-header\"\r\n (cdkDragStarted)=\"\r\n checkColumnGroupingStatus(col);\r\n dragStartOnGroup(col);\r\n onDragStarted(col)\r\n \"\r\n (cdkDragMoved)=\"onDragMoved($event)\"\r\n (cdkDragEnded)=\"onDragEnded()\"\r\n cdkDrag\r\n [cdkDragData]=\"col\"\r\n *ngFor=\"\r\n let col of centerColumns;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n index: i,\r\n section: 'previewCenterColumns'\r\n }\r\n \"\r\n >\r\n </ng-container>\r\n <ng-template cdkDragPreview\r\n ><div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n *ngIf=\"!isOutsideContainer\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n (draggingInGroupArea\r\n ? 'data-grid/icons/justify.svg'\r\n : 'data-grid/icons/arrows-move.svg')\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n >\r\n </span>\r\n <span\r\n *ngIf=\"isOutsideContainer\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/eye-cross.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n >\r\n </span>\r\n </div>\r\n <div>{{ col.header }}</div>\r\n </div>\r\n </ng-template>\r\n <ng-template cdkDragPlaceholder>\r\n <div *ngIf=\"!draggingInGroupArea\">\r\n <div\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n index: i,\r\n section: 'centerColumns'\r\n }\r\n \"\r\n ></div>\r\n </div>\r\n <div\r\n *ngIf=\"draggingInGroupArea && !isOutsideContainer\"\r\n class=\"d-flex gap-2 ms-2\"\r\n style=\"opacity: 0.6\"\r\n >\r\n <ng-container *ngIf=\"col?.children?.length; else singleCol\">\r\n <ng-container\r\n *ngFor=\"\r\n let child of col.children;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container *ngIf=\"child?.is_groupable\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: child,\r\n showChevron:\r\n col.children.length > 1 &&\r\n i != col.children.length - 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #singleCol>\r\n <ng-container *ngIf=\"col?.is_groupable\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: col,\r\n showChevron: col?.children?.length > 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <!-- Data Grid Right Pinned Header starts here -->\r\n <!-- ********************************************************************************* -->\r\n <!-- ********************************************************************************* -->\r\n <div\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n cdkDropList\r\n id=\"right-pinned-header\"\r\n [cdkDropListConnectedTo]=\"\r\n showRowsGrouping ? ['rows-grouping-top-container'] : []\r\n \"\r\n cdkDropListOrientation=\"horizontal\"\r\n class=\"data-grid-header right-pinned\"\r\n (cdkDropListSorted)=\"\r\n onSortGroup($event, 'previewRightPinnedColumns')\r\n \"\r\n (cdkDropListEntered)=\"onDropListEnter($event, 'right')\"\r\n (cdkDropListDropped)=\"onDropGroup()\"\r\n #rightPinnedHeader\r\n class=\"right-pinned-header d-flex\"\r\n style=\"min-width: 0.2px\"\r\n >\r\n <div\r\n class=\"dragable-header\"\r\n cdkDrag\r\n [cdkDragData]=\"col\"\r\n *ngFor=\"\r\n let col of rightPinnedColumns;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n pinnedRight: true,\r\n index: i,\r\n section: 'right'\r\n }\r\n \"\r\n ></ng-container>\r\n <ng-template cdkDragPreview\r\n ><div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n *ngIf=\"!draggingInGroupArea\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/arrows-move.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ col.header }}</div>\r\n </div>\r\n </ng-template>\r\n <ng-template cdkDragPlaceholder>\r\n <div *ngIf=\"!draggingInGroupArea\">\r\n <div\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: {\r\n $implicit: col,\r\n index: i,\r\n section: 'right'\r\n }\r\n \"\r\n ></div>\r\n </div>\r\n <div\r\n *ngIf=\"draggingInGroupArea\"\r\n class=\"d-flex gap-2 ms-2\"\r\n style=\"opacity: 0.6\"\r\n >\r\n <ng-container *ngIf=\"col?.children?.length; else singleCol\">\r\n <ng-container\r\n *ngFor=\"\r\n let child of col.children;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: child,\r\n showChevron:\r\n col.children.length > 1 &&\r\n i != col.children.length - 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #singleCol>\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: col,\r\n showChevron: col?.children?.length > 1\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!--########################################################################################################################################################################################################################### -->\r\n <!--########################################################################################################################################################################################################################### -->\r\n <!-- Data Grid Body starts here -->\r\n <!--########################################################################################################################################################################################################################### -->\r\n <!--########################################################################################################################################################################################################################### -->\r\n <div\r\n class=\"h-100 d-flex justify-content-center align-items-center\"\r\n *ngIf=\"!dataSet?.length && !loading && !dataSetLoading\"\r\n >\r\n <!-- <div\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/record-not-found.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></div> -->\r\n <div>No Record Found</div>\r\n </div>\r\n\r\n <div\r\n class=\"position-absolute w-100 h-100 d-flex justify-content-center align-items-center loading-overlay\"\r\n *ngIf=\"loading || dataSetLoading\"\r\n style=\"\r\n z-index: 999;\r\n backdrop-filter: blur(1px);\r\n \"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n >\r\n <div class=\"spinner-border text-primary\" role=\"status\">\r\n <!-- <span class=\"loader\"></span> -->\r\n <!-- <span class=\"visually-hidden\">Loading...</span> -->\r\n <!-- </div> -->\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"data-grid-body-wrapper position-relative d-flex\"\r\n [style.height]=\"bodyWrapperHeight\"\r\n style=\"overflow-y: auto; overflow-x: hidden\"\r\n #mainScroll\r\n (scroll)=\"onMainScroll($event)\"\r\n [style.scrollbarWidth]=\"verticalScrollbarWidth\"\r\n >\r\n <!-- LEFT PINNED -->\r\n <div\r\n [style.height.px]=\"\r\n !groupedColumns.length ? originalDataSet.length * rowHeight : 0\r\n \"\r\n ></div>\r\n <div [class.h-100]=\"originalDataSet.length < 8\">\r\n <div\r\n class=\"data-grid-body left-pinned-body w-100\"\r\n style=\"overflow-y: hidden\"\r\n [class.border-right]=\"hasLeftPinnedColumns\"\r\n [class.transparent-border-right]=\"!hasLeftPinnedColumns\"\r\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\r\n [style.backgroundColor]=\"leftPinnedBackgroundColor\"\r\n [class.h-100]=\"originalDataSet.length < 8\"\r\n *ngIf=\"!loading && !dataSetLoading\"\r\n [@rowDynamic]=\"rowAnimation\"\r\n\r\n \r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let row of visibleRows;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: row,\r\n columns: previewLeftPinnedColumns,\r\n isEven: (startIndex + i) % 2 === 0,\r\n isOdd: (startIndex + i) % 2 !== 0,\r\n isLeft: true,\r\n section: 'left',\r\n isTotalRow: false\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: { __virtualIndex: 0 },\r\n columns: previewLeftPinnedColumns,\r\n isEven: false,\r\n isOdd: false,\r\n section: 'left',\r\n isTotalRow: true\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- CENTER -->\r\n <div\r\n class=\"h-100\"\r\n [style.width.px]=\"centerPinnedHeader.clientWidth\"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n >\r\n <div\r\n class=\"data-grid-body center-scrollable\"\r\n [class.h-100]=\"originalDataSet.length < 8\"\r\n style=\"overflow-y: hidden; overflow-x: auto\"\r\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n #centerScrollableBody\r\n (scroll)=\"onCenterBodyScroll($event)\"\r\n [style.boxShadow]=\"leftPinnedBoxshadow\"\r\n >\r\n <div [@rowDynamic]=\"rowAnimation\" *ngIf=\"!loading && !dataSetLoading\">\r\n <ng-container\r\n *ngFor=\"\r\n let row of visibleRows;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: row,\r\n columns: previewCenterColumns,\r\n isEven: (startIndex + i) % 2 === 0,\r\n isOdd: (startIndex + i) % 2 !== 0,\r\n section: 'center',\r\n isTotalRow: false\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: { __virtualIndex: 0 },\r\n columns: previewCenterColumns,\r\n isEven: false,\r\n isOdd: false,\r\n section: 'center',\r\n isTotalRow: true\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- RIGHT PINNED -->\r\n <div\r\n class=\"right-pinned-body-wrapper\"\r\n *ngIf=\"hasRightPinnedColumns\"\r\n [class.h-100]=\"originalDataSet.length < 8\"\r\n [style.maxWidth.px]=\"\r\n isScrollbarVisible\r\n ? rightPinnedHeader.offsetWidth - 15\r\n : rightPinnedHeader.offsetWidth\r\n \"\r\n [style.backgroundColor]=\"rightPinnedBackgroundColor\"\r\n >\r\n <div\r\n class=\"data-grid-body right-pinned-body w-100 h-100\"\r\n style=\"overflow-y: hidden\"\r\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\r\n [style.boxShadow]=\"rightPinnedBoxshadow\"\r\n [style.backgroundColor]=\"rightPinnedBackgroundColor\"\r\n *ngIf=\"!loading && !dataSetLoading\"\r\n [@rowDynamic]=\"rowAnimation\"\r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let row of visibleRows;\r\n let i = index;\r\n trackBy: trackById\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: row,\r\n columns: previewRightPinnedColumns,\r\n isEven: (startIndex + i) % 2 === 0,\r\n isOdd: (startIndex + i) % 2 !== 0,\r\n section: 'right',\r\n isTotalRow: false\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: { __virtualIndex: 0 },\r\n columns: previewRightPinnedColumns,\r\n isEven: false,\r\n isOdd: false,\r\n section: 'right',\r\n isTotalRow: true\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div\r\n style=\"top: auto; left: auto\"\r\n (click)=\"\r\n $event.stopPropagation();\r\n fullscreenImage = null;\r\n cdr.detectChanges()\r\n \"\r\n [style.width.px]=\"dataGridContainer.offsetWidth\"\r\n [style.height.px]=\"\r\n dataGridContainer.offsetHeight - (footerRowHeight + 100)\r\n \"\r\n class=\"image-modal full-image-modal\"\r\n *ngIf=\"fullscreenImage\"\r\n >\r\n <img\r\n (click)=\"$event.stopPropagation()\"\r\n [src]=\"fullscreenImage\"\r\n alt=\"Fullscreen Image\"\r\n />\r\n </div>\r\n <div\r\n *ngIf=\"selectedRows.size > 0 && showTaskbar\"\r\n class=\"taskbar w-100\"\r\n [style.bottom.px]=\"85\"\r\n >\r\n <div class=\"selected-rows-action-bar\" [@slideUp]>\r\n <span class=\"selected-count\">\r\n {{ selectedRows.size }} selected of\r\n {{\r\n paginationConfig.totalResults ||\r\n config?.paginationParams?.totalItems\r\n }}\r\n Total\r\n </span>\r\n <div class=\"action-buttons d-flex align-items-center\">\r\n <ng-container\r\n *ngFor=\"let action of taskbarActions; let i = index\"\r\n >\r\n <ng-container *ngIf=\"action?.has_permission\">\r\n <span\r\n class=\"action-btn verified btn {{ action }}\"\r\n (click)=\"onVerifyClick(action?.actionName)\"\r\n >{{ action?.actionName }}</span\r\n >\r\n <span\r\n *ngIf=\"\r\n taskbarActions.length > 1 &&\r\n i !== taskbarActions.length - 1 &&\r\n taskbarActions[i + 1]?.has_permission\r\n \"\r\n class=\"\"\r\n >|</span\r\n >\r\n </ng-container>\r\n </ng-container>\r\n <button (click)=\"clearSelectionState(tableType);selectedRows.clear();\" class=\"clear-btn ms-2 mt-2\">\r\n <i class=\"bi bi-x-circle\"></i> Clear Selection\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Vertical Fake scroll Bar -->\r\n <!-- <div\r\n (scroll)=\"onMainFakeScroll($event)\"\r\n class=\"fake-scrollbar fake-scrollbar-vertical d-none\"\r\n [style.scrollbarWidth]=\"verticalScrollbarWidth\"\r\n [style.top.px]=\"\r\n showColumnsGrouping && showFilterRow\r\n ? headerRowHeight * 3\r\n : showColumnsGrouping || showFilterRow\r\n ? headerRowHeight * 2\r\n : headerRowHeight\r\n \"\r\n #fakeScroll\r\n [style.height]=\"bodyWrapperHeight\"\r\n style=\"\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n width: 17px;\r\n position: absolute;\r\n right: 0;\r\n background-color: f1f2f3;\r\n z-index: 10;\r\n \"\r\n >\r\n <div [style.height.px]=\"rowHeight * dataSetLength\"></div>\r\n </div> -->\r\n </div>\r\n\r\n <!-- Horizintal Fake Scrollbars -->\r\n <div\r\n class=\"d-flex justify-content-between\"\r\n *ngIf=\"hasScroll && !shouldRestoreScroll\"\r\n >\r\n <div\r\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\r\n class=\"fake-horizintal-scrollbar\"\r\n #fakeScroll\r\n [style.width.px]=\"leftPinnedHeader.offsetWidth\"\r\n style=\"overflow-x: scroll\"\r\n ></div>\r\n <div\r\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\r\n (scroll)=\"onCenterBodyScroll($event)\"\r\n class=\"fake-horizintal-scrollbar\"\r\n #horizintalFakeScroll\r\n [style.width.px]=\"centerPinnedHeader.offsetWidth\"\r\n >\r\n <div [style.width.px]=\"centerPinnedHeader.scrollWidth - 10\"></div>\r\n </div>\r\n <div\r\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\r\n class=\"fake-horizintal-scrollbar\"\r\n #fakeScroll\r\n [style.width.px]=\"rightPinnedHeader.offsetWidth\"\r\n style=\"overflow-x: scroll\"\r\n ></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Side Menu Implemented Here -->\r\n <div\r\n *ngIf=\"showSideMenu\"\r\n [style.width.px]=\"sideMenuVisible ? 280 : 30\"\r\n class=\"right-menu h-100\"\r\n [style.backgroundColor]=\"sidemenuBackgroundColor\"\r\n >\r\n <div class=\"h-100 d-flex flex-row-reverse\">\r\n <div\r\n style=\"width: 30px\"\r\n class=\"d-flex flex-column align-items-center cursor-pointer\"\r\n [class.border-start]=\"sideMenuVisible\"\r\n >\r\n <div\r\n (click)=\"toggleSideMenu('cols')\"\r\n [class.bg-fff]=\"\r\n currentOpenedSideMenue == 'cols' && sideMenuVisible\r\n \"\r\n [class.border-below]=\"sideMenuVisible\"\r\n class=\"columns-button d-flex flex-column align-items-center\"\r\n >\r\n <div>\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/ui-checks-grid.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div class=\"side-menue-text\">Columns</div>\r\n </div>\r\n\r\n <div\r\n (click)=\"toggleSideMenu('filtrs')\"\r\n [class.bg-fff]=\"\r\n currentOpenedSideMenue == 'filtrs' && sideMenuVisible\r\n \"\r\n [class.border-below]=\"\r\n sideMenuVisible && currentOpenedSideMenue == 'filtrs'\r\n \"\r\n class=\"columns-button d-flex flex-column align-items-center\"\r\n >\r\n <div>\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div class=\"side-menue-text\">Filter</div>\r\n </div>\r\n </div>\r\n <div\r\n class=\"h-100\"\r\n *ngIf=\"sideMenuVisible\"\r\n [ngStyle]=\"{ width: sideMenuVisible ? '250px' : '' }\"\r\n >\r\n <div class=\"h-100\">\r\n <ng-container\r\n *ngIf=\"currentOpenedSideMenue == 'cols' && sideMenuVisible\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"columnPannel\"></ng-container>\r\n <!-- Column Items -->\r\n <div class=\"column-panel-body px-3\">\r\n <ng-container\r\n *ngFor=\"let col of columns; trackBy: trackByField\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"columnPanelItem; context: { col: col }\"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n <hr />\r\n\r\n <div class=\"side-menu-row-groups\" style=\"height: 30%\">\r\n <ng-container\r\n *ngTemplateOutlet=\"sideMenuRowGroups\"\r\n ></ng-container>\r\n </div>\r\n </ng-container>\r\n <ng-container\r\n *ngIf=\"currentOpenedSideMenue == 'filtrs' && sideMenuVisible\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sideFilters\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div\r\n [style.height.px]=\"footerRowHeight\"\r\n class=\"border-top\"\r\n [style.backgroundColor]=\"footerRowBackgroundColor\"\r\n >\r\n <!-- Rows: <span class=\"fw-500 ms-1\">{{ dataSet.length }}</span> -->\r\n\r\n <div\r\n class=\"pagination-container\"\r\n [style.height.px]=\"footerRowHeight\"\r\n [style.padding.px]=\"footerPadding\"\r\n >\r\n <div class=\"page-size\">\r\n <select\r\n [(ngModel)]=\"paginationConfig.limit\"\r\n (change)=\"onPageSizeChange()\"\r\n >\r\n <option *ngFor=\"let size of pageSizeOptions\" [value]=\"size\">\r\n {{ size }}\r\n </option>\r\n </select>\r\n <span class=\"separator\"> per page </span>\r\n </div>\r\n\r\n <div class=\"page-info\">\r\n Results:\r\n {{ (paginationConfig.page - 1) * paginationConfig.limit + 1 }}-{{\r\n paginationConfig.page * paginationConfig.limit <\r\n paginationConfig.totalResults\r\n ? paginationConfig.page * paginationConfig.limit\r\n : paginationConfig.totalResults\r\n }}\r\n of\r\n {{ paginationConfig.totalResults }}\r\n </div>\r\n\r\n <div class=\"page-buttons\">\r\n <button\r\n (click)=\"goToPage(paginationConfig.page - 1)\"\r\n [disabled]=\"paginationConfig.page === 1\"\r\n >\r\n \u2039\r\n </button>\r\n\r\n <ng-container *ngFor=\"let page of visiblePages\">\r\n <button\r\n *ngIf=\"page !== '...'\"\r\n (click)=\"goToPage(page)\"\r\n [class.active]=\"page === paginationConfig.page\"\r\n >\r\n {{ page }}\r\n </button>\r\n <span *ngIf=\"page === '...'\">...</span>\r\n </ng-container>\r\n\r\n <button\r\n (click)=\"goToPage(paginationConfig.page + 1)\"\r\n [disabled]=\"paginationConfig.page === paginationConfig.totalResults\"\r\n >\r\n \u203A\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\r\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\r\n<!-- Header Cell Template -->\r\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\r\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\r\n\r\n<ng-template\r\n #headerCell\r\n let-col\r\n let-pinnedRight=\"pinnedRight\"\r\n let-i=\"index\"\r\n let-columnIndex=\"index\"\r\n let-sections=\"section\"\r\n let-calledFromNestedPlaceholder=\"calledFromNestedPlaceholder\"\r\n>\r\n <div>\r\n <!-- Group Header -->\r\n <ng-container *ngIf=\"col.children?.length > 0; else flatHeader\">\r\n <div cdkDroplistGroup class=\"group-column-wrapper\">\r\n <!-- Parent Header -->\r\n <div\r\n *ngIf=\"shouldTheGroupHeaderShow(col)\"\r\n class=\"header-cell group-header\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [style.gridColumn]=\"'span ' + col.children.length\"\r\n [style.fontWeight]=\"headerFontWeight\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n [class.justify-content-end]=\"pinnedRight\"\r\n style=\"grid-row: 1\"\r\n >\r\n <div\r\n class=\"group-header-content\"\r\n [title]=\"col.header\"\r\n [class.ms-2]=\"pinnedRight\"\r\n >\r\n {{ col.header }}\r\n </div>\r\n <div\r\n class=\"resize-handle\"\r\n (dblclick)=\"autosizeColumn(col.children)\"\r\n (mousedown)=\"\r\n $event.stopPropagation(); onResizeGroup($event, col, pinnedRight)\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Child Headers and Filters -->\r\n\r\n <div\r\n class=\"d-flex\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListData]=\"col.children\"\r\n (cdkDropListSorted)=\"onChildDroplistSorted($event, sections)\"\r\n (cdkDropListDropped)=\"onChildDroplistDroped($event)\"\r\n [cdkDropListSortingDisabled]=\"false\"\r\n [cdkDropListConnectedTo]=\"\r\n showRowsGrouping ? ['rows-grouping-top-container'] : []\r\n \"\r\n >\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"child\"\r\n *ngFor=\"let child of col.children; let i = index\"\r\n >\r\n <!-- Child Header -->\r\n <ng-container *ngIf=\"child.is_visible && !child['isRowGrouped']\">\r\n <div\r\n cdkDragHandle\r\n class=\"header-cell one-row-header-cells cursor-pointer\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [attr.field]=\"child.field\"\r\n [style.width.px]=\"child.width\"\r\n [style.min-width.px]=\"child.width\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n [style.fontWeight]=\"headerFontWeight\"\r\n style=\"grid-row: 2\"\r\n [class.filter-applied-on-text]=\"isFilterAppliedOnColumn(child)\"\r\n >\r\n <div\r\n class=\"d-flex justify-content-between h-100 align-items-center w-100\"\r\n >\r\n <div\r\n class=\"d-flex justify-content-between align-items-center w-100\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div\r\n class=\"text-ellipsis h-100 d-flex align-items-center w-100\"\r\n [title]=\"col.header\"\r\n [class.w-100]=\"pinnedRight\"\r\n >\r\n <div\r\n class=\"text-ellipsis h-100\"\r\n [class.editable-header]=\"child?.is_editable\"\r\n (click)=\"\r\n openThreeDotsMenu($event, child);\r\n openFilteronThreeDotsClick(child)\r\n \"\r\n >\r\n {{ child.header }}\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"position-relative d-flex\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div\r\n [class.me-2]=\"pinnedRight\"\r\n class=\"d-flex align-items-center\"\r\n *ngIf=\"child.pinned\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div\r\n class=\"three-dots p-1\"\r\n (click)=\"\r\n openThreeDotsMenu($event, child);\r\n isThreeDotsFilterOpen = false\r\n \"\r\n style=\"cursor: pointer\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/three-dots-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n\r\n <!-- Only show menu if this column is active -->\r\n <div\r\n class=\"position-absolute\"\r\n *ngIf=\"activeCol === child\"\r\n style=\"top: -50%; z-index: 21\"\r\n [style.left.px]=\"\r\n -(!child?.pinned ? centerPinnedHeader.scrollLeft : 0)\r\n \"\r\n [style.top.px]=\"\r\n isThreeDotsFilterOpen\r\n ? showFilterRow || showColumnsGrouping\r\n ? headerRowHeight * 2 - 10\r\n : headerRowHeight - 10\r\n : 0\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n columnMenu;\r\n context: {\r\n col: child,\r\n isNestedTable: false,\r\n section: sections,\r\n columnIndex: columnIndex,\r\n childColIndex: i\r\n }\r\n \"\r\n ></ng-container>\r\n </div>\r\n\r\n <div\r\n class=\"resize-handle\"\r\n (dblclick)=\"autosizeColumn(child)\"\r\n (mousedown)=\"\r\n $event.stopPropagation();\r\n onResizeColumn($event, child)\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filter Cell -->\r\n <div\r\n *ngIf=\"showFilterRow\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n class=\"header-cell filter-cell\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [attr.field]=\"child.field\"\r\n [style.width.px]=\"child.width\"\r\n [style.min-width.px]=\"child.width\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n style=\"grid-row: 3\"\r\n >\r\n <div\r\n class=\"header-cell filter-cell\"\r\n [attr.field]=\"col.field\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n >\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Filter\"\r\n [(ngModel)]=\"child.filterValue\"\r\n (ngModelChange)=\"onFilterChange(child)\"\r\n (paste)=\"onFilterChange(child); applyDropdownFilter()\"\r\n [readonly]=\"\r\n child?.type == 'dropdown' || child?.type == 'image' || child?.type == 'array'\r\n \"\r\n [class.disabled-search-input]=\"\r\n child?.type == 'dropdown' || child?.type == 'image' || child?.type == 'array'\r\n \"\r\n (click)=\"\r\n $event.stopPropagation();\r\n openFilterFromDisabledSearchedInput(child)\r\n \"\r\n (keydown.enter)=\"applyDropdownFilter()\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n <span\r\n class=\"filter-icon-wrapper\"\r\n (click)=\"$event.stopPropagation(); openFilter(child)\"\r\n [class.filter-applied]=\"isFilterAppliedOnColumn(child)\"\r\n [class.pe-none]=\"child?.type == 'image'\"\r\n ><span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <span\r\n *ngIf=\"isFilterAppliedOnColumn(child)\"\r\n style=\"\r\n width: 7px;\r\n height: 7px;\r\n box-shadow: 0px 0px 3px #7486ff;\r\n background-color: rgb(0 163 233);\r\n position: absolute;\r\n right: 4px;\r\n top: 12px;\r\n \"\r\n class=\"rounded-circle d-block\"\r\n ></span\r\n ></span>\r\n\r\n <div\r\n class=\"position-absolute filter-row-filter-wrapper\"\r\n *ngIf=\"activeFilterCell?.field == child?.field\"\r\n style=\"top: 100%; right: 0; z-index: 99\"\r\n [style.left.px]=\"\r\n child?.pinned ? 0 : -centerPinnedHeader.scrollLeft\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"filterMenu; context: { col: child }\"\r\n ></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n <ng-template cdkDragPreview\r\n ><div class=\"p-2 border d-flex gap-2\">\r\n <div\r\n *ngIf=\"\r\n !draggingInGroupArea ||\r\n (child.is_groupable && draggingInGroupArea)\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div *ngIf=\"draggingInGroupArea && !child.is_groupable\">\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/ban.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ child.header }}</div>\r\n </div>\r\n </ng-template>\r\n <ng-template cdkDragPlaceholder>\r\n <div *ngIf=\"!draggingInGroupArea\" class=\"position-relative\">\r\n <div\r\n *ngTemplateOutlet=\"\r\n childHeaderPlaceholder;\r\n context: {\r\n $implicit: child,\r\n index: i,\r\n sections: sections,\r\n calledFromNestedPlaceholder: true,\r\n }\r\n \"\r\n ></div>\r\n </div>\r\n <div\r\n *ngIf=\"draggingInGroupArea && child?.is_groupable\"\r\n class=\"d-flex gap-2 ms-2\"\r\n style=\"opacity: 0.6\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n topGroupingRowPlaceholder;\r\n context: {\r\n $implicit: child,\r\n showChevron: false,\r\n pinnedRight: pinnedRight,\r\n sections: sections,\r\n index: i\r\n }\r\n \"\r\n ></ng-container>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Flat Header || Single Header Cell-->\r\n <ng-template #flatHeader>\r\n <div\r\n class=\"group-column-wrapper\"\r\n *ngIf=\"col.is_visible && !col['isRowGrouped']\"\r\n >\r\n <!-- Full-height Header Cell (spans 2 rows visually) -->\r\n <div\r\n class=\"header-cell one-row-header-cells\"\r\n [attr.field]=\"col.field\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [style.min-height.px]=\"\r\n showColumnsGrouping ? headerRowHeight * 2 : headerRowHeight\r\n \"\r\n [style.height.px]=\"\r\n showColumnsGrouping ? headerRowHeight * 2 : headerRowHeight\r\n \"\r\n [style.fontWeight]=\"headerFontWeight\"\r\n style=\"grid-row: 1 / span 2\"\r\n >\r\n <div\r\n class=\"d-flex justify-content-between h-100 align-items-center w-100\"\r\n >\r\n <div\r\n class=\"d-flex justify-content-between w-100 align-items-center\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div\r\n class=\"text-ellipsis h-100 d-flex align-items-center w-100\"\r\n [title]=\"col.header\"\r\n >\r\n <div\r\n class=\"text-ellipsis h-100 cursor-pointer\"\r\n [class.editable-header]=\"col?.is_editable\"\r\n [class.filter-applied-on-text]=\"isFilterAppliedOnColumn(col)\"\r\n (click)=\"\r\n openThreeDotsMenu($event, col);\r\n openFilteronThreeDotsClick(col)\r\n \"\r\n >\r\n {{ col.header }}\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"position-relative d-flex\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div\r\n [class.me-2]=\"pinnedRight\"\r\n class=\"d-flex align-items-center\"\r\n *ngIf=\"col?.pinned\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div\r\n [class.me-2]=\"col.order_by\"\r\n class=\"d-flex align-items-center\"\r\n *ngIf=\"sortingConfig?.field == col.field\"\r\n >\r\n <!-- Ascending Sort Icon -->\r\n <span\r\n *ngIf=\"sortingConfig?.order_by == 'asc'\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/sort-asc.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center mt-1 cursor-pointer\"\r\n (click)=\"sortDesc(col)\"\r\n [class.active]=\"sortingConfig?.order_by === 'asc'\"\r\n ></span>\r\n\r\n <!-- Descending Sort Icon -->\r\n <span\r\n *ngIf=\"sortingConfig?.order_by == 'desc'\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/sort-desc.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center mt-1 cursor-pointer\"\r\n (click)=\"sortAsc(col)\"\r\n [class.active]=\"sortingConfig?.order_by === 'desc'\"\r\n ></span>\r\n </div>\r\n <div\r\n class=\"three-dots p-1\"\r\n (click)=\"\r\n openThreeDotsMenu($event, col);\r\n isThreeDotsFilterOpen = false\r\n \"\r\n style=\"cursor: pointer\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/three-dots-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n\r\n <!-- Only show menu if this column is active -->\r\n <div\r\n class=\"position-absolute\"\r\n *ngIf=\"activeCol === col\"\r\n style=\"top: -50%; z-index: 21\"\r\n [style.left.px]=\"\r\n -(!col?.pinned ? centerPinnedHeader.scrollLeft : 0)\r\n \"\r\n [style.top.px]=\"\r\n isThreeDotsFilterOpen\r\n ? showFilterRow || showColumnsGrouping\r\n ? headerRowHeight * 2 - 10\r\n : headerRowHeight - 10\r\n : 0\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n columnMenu;\r\n context: {\r\n col: col,\r\n isNestedTable: false,\r\n section: sections,\r\n columnIndex: columnIndex,\r\n childColIndex: 0\r\n },\r\n \"\r\n ></ng-container>\r\n </div>\r\n\r\n <div\r\n class=\"resize-handle\"\r\n [class.w-100]=\"col.pinned == 'right'\"\r\n (dblclick)=\"autosizeColumn(col)\"\r\n (mousedown)=\"\r\n $event.stopPropagation(); onResizeColumn($event, col)\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filter Cell -->\r\n <div\r\n *ngIf=\"showFilterRow\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n class=\"header-cell filter-cell\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [attr.field]=\"col.field\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n >\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Filter\"\r\n [(ngModel)]=\"col.filterValue\"\r\n (ngModelChange)=\"onFilterChange(col)\"\r\n [readonly]=\"col?.type == 'dropdown' || col?.type == 'image' || col?.type == 'array'\"\r\n [class.disabled-search-input]=\"\r\n col?.type == 'dropdown' || col?.type == 'image' || col?.type == 'array'\r\n \"\r\n (paste)=\"onPasteInFilterRowSearch($event, col)\"\r\n (click)=\"\r\n $event.stopPropagation(); openFilterFromDisabledSearchedInput(col)\r\n \"\r\n (keydown.enter)=\"applyDropdownFilter()\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n <span\r\n class=\"filter-icon-wrapper\"\r\n (click)=\"$event.stopPropagation(); openFilter(col)\"\r\n [class.filter-applied]=\"isFilterAppliedOnColumn(col)\"\r\n [class.pe-none]=\"col?.type == 'image'\"\r\n ><span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <span\r\n *ngIf=\"isFilterAppliedOnColumn(col)\"\r\n style=\"\r\n width: 7px;\r\n height: 7px;\r\n box-shadow: 0px 0px 3px #7486ff;\r\n background-color: rgb(0 163 233);\r\n position: absolute;\r\n right: 4px;\r\n top: 12px;\r\n \"\r\n class=\"rounded-circle d-block\"\r\n ></span\r\n ></span>\r\n\r\n <div\r\n class=\"position-absolute filter-row-filter-wrapper\"\r\n *ngIf=\"activeFilterCell === col\"\r\n style=\"top: 100%; right: 0; z-index: 99\"\r\n [style.left.px]=\"col?.pinned ? 0 : -centerPinnedHeader.scrollLeft\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"filterMenu; context: { col: col }\"\r\n ></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\r\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\r\n<!-- Body Cell Template -->\r\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\r\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\r\n\r\n<ng-template\r\n #rowCell\r\n let-row\r\n let-columns=\"columns\"\r\n let-isEven=\"isEven\"\r\n let-isOdd=\"isOdd\"\r\n let-isLeftSection=\"isLeft\"\r\n let-section=\"section\"\r\n let-rowIndex=\"rowIndex\"\r\n let-isTotalRow=\"isTotalRow\"\r\n>\r\n <!-- Check if row is a group -->\r\n <ng-container\r\n *ngTemplateOutlet=\"groupRowTemplate; context: { $implicit: row, depth: 0 }\"\r\n ></ng-container>\r\n <ng-template #groupRowTemplate let-row let-depth=\"depth\">\r\n <ng-container *ngIf=\"row.isGroup; else regularRow\">\r\n <!-- Group Header -->\r\n <div\r\n class=\"group-header-row d-flex align-items-center\"\r\n [style.height.px]=\"rowHeight\"\r\n [class.border-below]=\"section !== 'center'\"\r\n [style.width]=\"\r\n section === 'center'\r\n ? (centerScrollableBody?.scrollWidth ?? 0) + 'px'\r\n : '100%'\r\n \"\r\n >\r\n <div\r\n *ngIf=\"section == 'left'\"\r\n class=\"h-100 d-flex\"\r\n [style.width.px]=\"leftPinnedHeader.offsetWidth - 1\"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n >\r\n <div\r\n *ngIf=\"showSerialNumber\"\r\n style=\"width: 50px\"\r\n class=\"d-flex align-items-center h-100 border-right justify-content-end pe-2 s-no\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n [style.width.px]=\"55\"\r\n [style.cursor]=\"\r\n 'url(' +\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/arrow-right.svg), auto'\r\n \"\r\n (mousedown)=\"onRowMouseDown(row.__virtualIndex, $event)\"\r\n (mouseover)=\"onRowMouseOver(row.__virtualIndex, $event)\"\r\n [style.color]=\"checkboxesColor\"\r\n >\r\n {{ getStartIndex() + (row.__virtualIndex - 1) || \"\" }}\r\n </div>\r\n <div\r\n *ngIf=\"showCheckboxes\"\r\n style=\"width: 50px\"\r\n class=\"d-flex align-items-center justify-content-center h-100 border-right\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.left-selection-border]=\"\r\n rowSelectedIndexes.has(row.__virtualIndex)\r\n \"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n [style.color]=\"checkboxesColor\"\r\n >\r\n <input\r\n style=\"width: 16px; height: 16px\"\r\n type=\"checkbox\"\r\n [checked]=\"getGroupCheckedState(row) === true\"\r\n [indeterminate]=\"getGroupCheckedState(row) === undefined\"\r\n (change)=\"selectGroupRow($event, row)\"\r\n />\r\n\r\n </div>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"section == 'center'\"\r\n [style.width.px]=\"centerPinnedHeader.scrollWidth\"\r\n [style.minWidth.px]=\"centerPinnedHeader.scrollWidth\"\r\n class=\"d-flex align-items-center ps-2 h-100 border-below\"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n >\r\n <div\r\n class=\"d-flex align-items-center justify-content-between\"\r\n [style.paddingLeft.px]=\"depth > 0 ? depth * 30 : 0\"\r\n >\r\n <span class=\"me-2 filter-icon-wrapper\" (click)=\"toggleExpand(row)\">\r\n <span\r\n class=\"data-grid-svg-icon align-items-center d-flex\"\r\n [inlineSVG]=\"\r\n row.isExpand\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n ></span>\r\n </span>\r\n <strong (click)=\"toggleExpand(row)\" class=\"cursor-pointer\">\r\n {{ row.groupValue }} ({{ countLeafRows(row) }})\r\n </strong>\r\n </div>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"section == 'right'\"\r\n [style.width.px]=\"rightPinnedHeader.offsetWidth\"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n ></div>\r\n </div>\r\n\r\n <!-- Recursive Children -->\r\n <div class=\"group-children\" *ngIf=\"row.isExpand\" [@slideToggle]>\r\n <ng-container\r\n *ngFor=\"let child of row.children; let i = index; trackBy: trackById\"\r\n >\r\n <ng-container *ngIf=\"child.isGroup; else dataRow\">\r\n <!-- Recursive call for nested group -->\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n groupRowTemplate;\r\n context: { $implicit: child, depth: depth + 1 }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n\r\n <ng-template #dataRow>\r\n <!-- Regular data row -->\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n rowCell;\r\n context: {\r\n $implicit: child,\r\n columns: columns,\r\n isEven: i % 2 === 0,\r\n isOdd: i % 2 !== 0,\r\n isLeft: isLeftSection,\r\n section: section,\r\n isTotalRow: isTotalRow\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-template>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </ng-template>\r\n\r\n <!-- Regular row (not a group) -->\r\n <ng-template #regularRow>\r\n <div\r\n class=\"d-flex\"\r\n [style.height.px]=\"rowHeight\"\r\n [style.minHeight.px]=\"rowHeight\"\r\n [style.maxHeight.px]=\"rowHeight\"\r\n >\r\n <span\r\n class=\"d-flex align-items-center justify-content-center cursor-pointer border-below\"\r\n style=\"min-width: 30px; height: 100%\"\r\n *ngIf=\"\r\n section == 'center' && (gridType === 'Assets' || gridType === 'Tasks')\r\n \"\r\n [ngStyle]=\"{\r\n 'background-color': rowSelectedIndexes.has(row.__virtualIndex)\r\n ? null\r\n : getBackgroundColor(row, isEven, section)\r\n }\"\r\n [class.selected-cell]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n >\r\n <span\r\n (click)=\"toggleDetailRowExpand(row)\"\r\n *ngIf=\"row?.detail?.result?.length || gridType === 'Tasks'\"\r\n class=\"data-grid-svg-icon filter-icon-wrapper\"\r\n [inlineSVG]=\"\r\n isDetailsExpanded(row)\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n ></span>\r\n </span>\r\n <div\r\n [style.min-width.px]=\"\r\n section == 'center' && groupedColumns?.length ? groupBoxPadding : 0\r\n \"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n (contextmenu)=\"onRightClick($event, row)\"\r\n [style.height.px]=\"rowHeight\"\r\n class=\"data-grid-row h-100\"\r\n [class.even-row]=\"isEven\"\r\n [class.odd-row]=\"isOdd\"\r\n [class.hovered-row]=\"hoveredRowId === (row._id || row.id)\"\r\n (mouseenter)=\"onRowHover(row)\"\r\n (mouseleave)=\"onRowLeave()\"\r\n [ngStyle]=\"{\r\n 'background-color': getBackgroundColor(row, isEven, section)\r\n }\"\r\n [style.minHeight.px]=\"rowHeight\"\r\n [style.maxHeight.px]=\"rowHeight\"\r\n ></div>\r\n <div\r\n (contextmenu)=\"onRightClick($event, row)\"\r\n [style.height.px]=\"rowHeight\"\r\n class=\"data-grid-row\"\r\n [class.even-row]=\"isEven\"\r\n [class.odd-row]=\"isOdd\"\r\n [class.hovered-row]=\"hoveredRowId === (row._id || row.id)\"\r\n (mouseenter)=\"onRowHover(row)\"\r\n (mouseleave)=\"onRowLeave()\"\r\n [ngStyle]=\"{\r\n 'background-color': getBackgroundColor(row, isEven, section)\r\n }\"\r\n >\r\n <div\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n class=\"select-all-checkbox-cell justify-content-end pe-2 s-no\"\r\n [style.width.px]=\"55\"\r\n *ngIf=\"isLeftSection && showSerialNumber\"\r\n [style.cursor]=\"\r\n 'url(' +\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/arrow-right.svg), auto'\r\n \"\r\n (mousedown)=\"onRowMouseDown(row.__virtualIndex, $event)\"\r\n (mouseover)=\"onRowMouseOver(row.__virtualIndex, $event)\"\r\n [style.color]=\"checkboxesColor\"\r\n >\r\n {{ getStartIndex() + (row.__virtualIndex - 1) }}\r\n </div>\r\n <div\r\n class=\"border-below\"\r\n [style.backgroundColor]=\"\r\n rowSelectedIndexes.has(row.__virtualIndex)\r\n ? selectedRowsBackgroundColor\r\n : checkboxesBackgroundColor\r\n \"\r\n class=\"select-all-checkbox-cell\"\r\n *ngIf=\"isLeftSection && showCheckboxes\"\r\n [class.left-selection-border]=\"\r\n rowSelectedIndexes.has(row.__virtualIndex)\r\n \"\r\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\r\n [style.minHeight.px]=\"rowHeight - 1\"\r\n [style.maxHeight.px]=\"rowHeight\"\r\n >\r\n <input\r\n *ngIf=\"hasAnyVisibleColumn\"\r\n style=\"width: 16px; height: 16px\"\r\n type=\"checkbox\"\r\n [checked]=\"isRowSelected(row)\"\r\n (change)=\"toggleRowSelection(row)\"\r\n />\r\n </div>\r\n\r\n <!-- Render all columns -->\r\n <ng-container\r\n *ngFor=\"\r\n let col of columns;\r\n trackBy: trackByField;\r\n let colIndex = index\r\n \"\r\n >\r\n <ng-container *ngIf=\"col.children?.length > 0; else flatColumn\">\r\n <ng-container\r\n *ngFor=\"\r\n let child of col.children;\r\n trackBy: trackByField;\r\n let subColIndex = index\r\n \"\r\n >\r\n <ng-container *ngIf=\"child?.is_visible && !child?.isRowGrouped\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n cellTemplate;\r\n context: {\r\n col: child,\r\n row: row,\r\n rowIndex: rowIndex,\r\n colIndex: colIndex,\r\n subColIndex: subColIndex,\r\n section: section,\r\n isTotalRow: isTotalRow\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #flatColumn>\r\n <ng-container *ngIf=\"col?.is_visible && !col?.isRowGrouped\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n cellTemplate;\r\n context: {\r\n col: col,\r\n row: row,\r\n rowIndex: rowIndex,\r\n colIndex: colIndex,\r\n subColIndex: null,\r\n section: section,\r\n isTotalRow: isTotalRow\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </ng-template>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div\r\n [@slideToggle]\r\n *ngIf=\"section === 'left' && isDetailsExpanded(row)\"\r\n class=\"accordion-details\"\r\n style=\"max-height: 350px; overflow: hidden\"\r\n [style.maxHeight.px]=\"hasHorizontalScroll ? 339 : 341\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n leftRightNestedPlaceholder;\r\n context: { $implicit: row }\r\n \"\r\n >\r\n </ng-container>\r\n </div>\r\n\r\n <div\r\n [@slideToggle]\r\n *ngIf=\"section === 'center' && isDetailsExpanded(row)\"\r\n class=\"accordion-details center-section\"\r\n style=\"\r\n max-height: 350px;\r\n overflow-y: hidden;\r\n overflow-x: auto;\r\n scrollbar-width: thin;\r\n \"\r\n #nestedTable\r\n [style.width]=\"\r\n hasRightPinnedColumns\r\n ? '100%'\r\n : hasVerticalScroll\r\n ? 'calc(100% - 12px)'\r\n : '100%'\r\n \"\r\n >\r\n <ng-container *ngIf=\"gridType == 'Assets'\">\r\n <ng-container\r\n *ngTemplateOutlet=\"nestedTableTemplate; context: { $implicit: row }\"\r\n ></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"gridType == 'Tasks'\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n taskManagementTemplate;\r\n context: { taskDetails: row }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n <div\r\n [@slideToggle]\r\n *ngIf=\"section === 'right' && isDetailsExpanded(row)\"\r\n class=\"accordion-details\"\r\n style=\"max-height: 350px; overflow: hidden\"\r\n [style.maxHeight.px]=\"hasHorizontalScroll ? 339 : 341\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n leftRightNestedPlaceholder;\r\n context: { $implicit: row }\r\n \"\r\n >\r\n </ng-container>\r\n </div>\r\n </ng-template>\r\n</ng-template>\r\n\r\n<!-- Actual Cell is Here -->\r\n<ng-template\r\n #cellTemplate\r\n let-col=\"col\"\r\n let-row=\"row\"\r\n let-section=\"section\"\r\n let-subColIndex=\"subColIndex\"\r\n let-rowIndex=\"rowIndex\"\r\n let-colIndex=\"colIndex\"\r\n let-isTotalRow=\"isTotalRow\"\r\n>\r\n <div\r\n #cellContainer\r\n (click)=\"\r\n editingKey = ''; setActiveCell(row, col); collapseAllExpandedCells()\r\n \"\r\n [style.fontWeight]=\"bodyFontWeight\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n class=\"cell overflow-visible position-relative data-grid-cell\"\r\n [attr.field]=\"col.field\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.fontSize.px]=\"bodyTextFontsSize\"\r\n [style.minHeight.px]=\"rowHeight\"\r\n [style.maxHeight.px]=\"rowHeight\"\r\n [class.active-cell]=\"\r\n isActiveCell(row, col) && !isEditing(row, col) && selectedKeys.size == 1\r\n \"\r\n (dblclick)=\"\r\n $event.stopPropagation();\r\n $event.preventDefault();\r\n enableEdit(row, col, false, cellContainer)\r\n \"\r\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\r\n [class.first-row-selected]=\"firstSelectedRow === row?.__virtualIndex\"\r\n [class.last-row-selected]=\"lastSelectedRow === row?.__virtualIndex\"\r\n tabindex=\"-1\"\r\n (keydown.enter)=\"$event.preventDefault(); enableEdit(row, col)\"\r\n (mousedown)=\"\r\n startSelection(\r\n row.__virtualIndex,\r\n colIndex,\r\n subColIndex ?? 0,\r\n col.field,\r\n $event,\r\n section\r\n )\r\n \"\r\n (mouseenter)=\"\r\n extendSelection(\r\n row.__virtualIndex,\r\n colIndex,\r\n subColIndex ?? 0,\r\n col.field,\r\n $event,\r\n section\r\n )\r\n \"\r\n (mouseup)=\"endSelection()\"\r\n [class.selected-cell]=\"\r\n isSelected(\r\n row.__virtualIndex,\r\n colIndex,\r\n subColIndex ?? 0,\r\n col.field,\r\n section\r\n )\r\n \"\r\n [class.top-border]=\"\r\n isTopBorder(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.bottom-border]=\"\r\n isBottomBorder(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.left-border]=\"\r\n isLeftBorder(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.right-border]=\"\r\n isRightBorder(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.top-left-corner]=\"\r\n isTopLeftCorner(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.top-right-corner]=\"\r\n isTopRightCorner(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.bottom-left-corner]=\"\r\n isBottomLeftCorner(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n [class.bottom-right-corner]=\"\r\n isBottomRightCorner(row.__virtualIndex, colIndex, subColIndex, section)\r\n \"\r\n >\r\n <!-- (mousedown)=\"startSelection(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field, $event)\"\r\n (mouseenter)=\"extendSelection(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field, $event)\"\r\n (mouseup)=\"endSelection()\"\r\n [class.selected-cell]=\"isSelected(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field)\" -->\r\n <div\r\n class=\"table-cell\"\r\n [class.active-for-editing]=\"\r\n isEditing(row, col) &&\r\n (getNestedValue(row, col.field)?.length === undefined ||\r\n getNestedValue(row, col.field)?.length <= 50)\r\n \"\r\n >\r\n <div\r\n (click)=\"$event.stopPropagation()\"\r\n *ngIf=\"\r\n isEditing(row, col) &&\r\n (getNestedValue(row, col.field)?.length === undefined ||\r\n (getNestedValue(row, col.field)?.length <= 50 &&\r\n !expandedCells.size));\r\n else viewMode\r\n \"\r\n >\r\n\r\n <ng-container *ngIf=\"col.cellEditor; else builtInEditors\">\r\n <ng-container\r\n [cellEditor]=\"col.cellEditor\"\r\n [rowData]=\"row\"\r\n [colData]=\"col\"\r\n [cellValue]=\"getNestedValue(row, col.field)\"\r\n (editorEvent)=\"finishEdit($event)\"\r\n ></ng-container>\r\n </ng-container>\r\n\r\n <ng-template #builtInEditors>\r\n <ng-container [ngSwitch]=\"col?.type\">\r\n <!-- Text Input -->\r\n <input\r\n [style.height.px]=\"rowHeight - 10\"\r\n *ngSwitchCase=\"'input'\"\r\n type=\"text\"\r\n [(ngModel)]=\"row[col.field]\"\r\n (blur)=\"disableEdit(row, col)\"\r\n autofocus\r\n (keydown.enter)=\"blurInput($event, row, col)\"\r\n class=\"form-control form-control-sm\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n\r\n <!-- Number Input -->\r\n <input\r\n [style.height.px]=\"rowHeight - 8\"\r\n *ngSwitchCase=\"'number'\"\r\n #numberInput=\"ngModel\"\r\n #numberRef\r\n (keypress)=\"allowOnlyNumbers($event)\"\r\n type=\"number\"\r\n required\r\n [(ngModel)]=\"row[col.field]\"\r\n (blur)=\"disableEdit(row, col, numberInput)\"\r\n autofocus\r\n (keydown.enter)=\"blurInput($event, row, col)\"\r\n class=\"form-control form-control-sm\"\r\n [ngClass]=\"{\r\n 'is-invalid': numberInput.invalid\r\n }\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n\r\n <!-- Date Input -->\r\n <input\r\n [style.height.px]=\"rowHeight - 8\"\r\n *ngSwitchCase=\"'date'\"\r\n type=\"date\"\r\n [(ngModel)]=\"row[col.field]\"\r\n (blur)=\"disableEdit(row, col, dateInput)\"\r\n autofocus\r\n class=\"form-control form-control-sm\"\r\n #dateInput=\"ngModel\"\r\n (keydown.enter)=\"blurInput($event, row, col)\"\r\n [ngClass]=\"{\r\n 'is-invalid': dateInput.invalid\r\n }\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n\r\n <!-- Dropdown -->\r\n <!-- ng-select like dropdown -->\r\n <div\r\n *ngSwitchCase=\"'dropdown'\"\r\n class=\"dropdown w-100\"\r\n (blur)=\"disableEdit(row, col)\"\r\n >\r\n <!-- Trigger -->\r\n <button\r\n class=\"form-select form-select-sm text-start w-100 text-ellipsis\"\r\n type=\"button\"\r\n data-bs-toggle=\"dropdown\"\r\n aria-expanded=\"false\"\r\n [style.minHeight.px]=\"rowHeight - 10\"\r\n data-bs-display=\"static\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n >\r\n <ng-container>\r\n {{\r\n getNestedValue(row, col.field)?.value ||\r\n getNestedValue(row, col.field)?.name ||\r\n getNestedValue(row, col.field)\r\n }}\r\n </ng-container>\r\n <ng-template #placeholder> Select options... </ng-template>\r\n </button>\r\n\r\n <!-- Menu -->\r\n <div\r\n class=\"dropdown-menu w-100 p-0 cell-editing-dropdown-menu rounded-3\"\r\n [class.show]=\"isEditing(row, col)\"\r\n >\r\n <!-- Search -->\r\n <div class=\"px-2 py-1 editing-dropdown-search-input\" *ngIf=\"col?.column_dropdown_value?.length > 5\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search...\"\r\n [(ngModel)]=\"editinDropdownSearch\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n </div>\r\n <cdk-virtual-scroll-viewport \r\n itemSize=\"35\" \r\n class=\"dropdown-viewport\"\r\n style=\"height: 120px\"\r\n >\r\n <div\r\n [class.selected]=\"getNestedValue(row, col.field) == option?.value || getNestedValue(row, col.field) == option\"\r\n class=\"px-2 py-1 d-flex align-items-center dropdown-item\"\r\n *cdkVirtualFor=\"\r\n let option of col.column_dropdown_value \r\n | filter : editinDropdownSearch : 'value'\r\n \"\r\n (click)=\"setNestedValue(row, col, option, true); editingKey = null\"\r\n >\r\n <label\r\n \r\n class=\"form-check-label d-flex align-items-center mb-0 cursor-pointer\"\r\n [for]=\"col.field + '-' + (option.value || option)\"\r\n >\r\n {{ option.value || option }}\r\n </label>\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n\r\n </div>\r\n </div>\r\n\r\n <input\r\n *ngSwitchCase=\"'email'\"\r\n [style.height.px]=\"rowHeight - 10\"\r\n [style.maxHeight.px]=\"rowHeight - 10\"\r\n #emailModel=\"ngModel\"\r\n #emailInput\r\n type=\"email\"\r\n [(ngModel)]=\"row[col.field]\"\r\n name=\"{{ col.field }}\"\r\n required\r\n pattern=\"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\"\r\n (blur)=\"disableEdit(row, col, emailModel)\"\r\n (keydown.enter)=\"blurInput($event, row, col)\"\r\n autofocus\r\n class=\"form-control form-control-sm\"\r\n [ngClass]=\"{\r\n 'is-invalid': emailModel.invalid\r\n }\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n <!-- Default fallback -->\r\n <input\r\n *ngSwitchDefault\r\n [style.height.px]=\"rowHeight - 10\"\r\n [style.maxHeight.px]=\"rowHeight - 10\"\r\n #textModel=\"ngModel\"\r\n #textInput\r\n type=\"text\"\r\n (keydown.enter)=\"blurInput($event, row, col)\"\r\n [(ngModel)]=\"row[col.field]\"\r\n name=\"{{ col.field }}\"\r\n required\r\n (blur)=\"disableEdit(row, col, textModel)\"\r\n autofocus\r\n class=\"form-control form-control-sm\"\r\n [ngClass]=\"{\r\n 'is-invalid': textModel.invalid\r\n }\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n />\r\n </ng-container>\r\n </ng-template>\r\n\r\n </div>\r\n\r\n <!-- Display mode -->\r\n <ng-template #viewMode>\r\n <div\r\n class=\"d-flex justify-content-between align-items-center w-100 overflow-hidden\"\r\n [ngClass]=\"getCellClasses(col, getNestedValue(row, col.field))\"\r\n >\r\n <!-- Field icon (for Tasks grid) -->\r\n <ng-container\r\n *ngIf=\"gridType === 'Tasks' && iconMap[col.field] && !isTotalRow\"\r\n >\r\n <span\r\n class=\"cursor-pointer me-2\"\r\n (click)=\"$event.preventDefault(); $event.stopPropagation()\"\r\n [inlineSVG]=\"iconMap[col.field](row, col)\"\r\n ></span>\r\n </ng-container>\r\n\r\n <!-- \u2705 Custom cell renderer support -->\r\n <ng-container *ngIf=\"col.cellRenderer; else defaultCell\">\r\n <ng-container\r\n [cellRenderInit]=\"col.cellRenderer\"\r\n [rowData]=\"row\"\r\n [colData]=\"col\"\r\n [cellValue]=\"getNestedValue(row, col?.field)\"\r\n (cellEvent)=\"onCellEvent($event)\"\r\n >\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!-- \uD83E\uDDFE Default text-based cell rendering -->\r\n <ng-template #defaultCell>\r\n <div\r\n #cellText\r\n class=\"text-ellipsis flex-grow-1\"\r\n [title]=\"getCellTitle(row, col)\"\r\n >\r\n <!-- Normal cell -->\r\n <ng-container\r\n *ngIf=\"\r\n col?.type !== 'image' &&\r\n col?.field != 'image' &&\r\n col?.field != 'invoice.invoice_image' &&\r\n !isTotalRow\r\n \"\r\n >\r\n <ng-container *ngIf=\"col.is_amount\">{{\r\n currencySymbol\r\n }}</ng-container>\r\n {{getCellTitle(row, col)}}\r\n </ng-container>\r\n\r\n <!-- Total row -->\r\n <ng-container *ngIf=\"isTotalRow\">\r\n {{ getTotalAmount(col) }}\r\n </ng-container>\r\n\r\n <!-- Invoice Image -->\r\n <ng-container *ngIf=\"col.field == 'invoice.invoice_image'\">\r\n <div style=\"display: flex; align-items: center; zoom: 0.7\">\r\n <span\r\n title=\"{{ getNestedValue(row, col.field) || 'Attachment' }}\"\r\n (click)=\"downloadAttchment(getNestedValue(row, col.field))\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/document-icons/' +\r\n getExtention(getNestedValue(row, col.field)) +\r\n '.svg'\r\n \"\r\n ></span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Image cell -->\r\n <ng-container *ngIf=\"col?.type == 'image' && !isTotalRow\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n defaultImagePlaceholder;\r\n context: { row: row, col: col }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n <span\r\n *ngIf=\"\r\n (!col?.cellRenderer && showCellDetailsBox &&\r\n getNestedValue(row, col.field)?.length > 50 && col?.type !== 'image') ||\r\n (isNestedValueArray(row, col.field) &&\r\n getNestedValue(row, col.field)?.length > 1)\r\n \"\r\n class=\"toggle-icon data-grid-svg-icon ms-2 cursor-pointer\"\r\n [inlineSVG]=\"\r\n isExpanded(row, col)\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n (click)=\"\r\n $event.stopPropagation();\r\n toggleExpandOfLongCellText(row, col, columns, true)\r\n \"\r\n (dblclick)=\"$event.preventDefault(); $event.stopPropagation()\"\r\n ></span>\r\n </ng-template>\r\n <!-- Expand / Collapse icon -->\r\n </div>\r\n\r\n <!-- Expanded text -->\r\n <div\r\n class=\"position-absolute w-100 expanded-box\"\r\n *ngIf=\"isExpanded(row, col)\"\r\n [style.zIndex]=\"getZIndex(row, col)\"\r\n style=\"top: 100%; left: 0\"\r\n [attr.id]=\"(row.id || row._id) + '-' + (col.id || col._id)\"\r\n [class.invisible]=\"!showDetailsBox\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n fullTextTemplate;\r\n context: {\r\n row: row,\r\n col: col,\r\n isArray: isNestedValueArray(row, col.field)\r\n }\r\n \"\r\n ></ng-container>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Headers Action List On clicking three dots -->\r\n\r\n<ng-template\r\n #columnMenu\r\n let-col=\"col\"\r\n let-isNestedTable=\"isNestedTable\"\r\n let-columns=\"columns\"\r\n let-section=\"section\"\r\n let-columnIndex=\"columnIndex\"\r\n let-childColIndex=\"childColIndex\"\r\n>\r\n <div\r\n class=\"column-menu three-dots-col-menu\"\r\n [class.visually-hidden]=\"isMenueHidden\"\r\n *ngIf=\"activeCol && !isThreeDotsFilterOpen\"\r\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\r\n (click)=\"$event.stopPropagation()\"\r\n [style.color]=\"headerTextColor\"\r\n >\r\n <!-- Sort Ascending -->\r\n <div class=\"border-below pb-2\" [class.disable-sorting]=\"!col.is_sortable\">\r\n <span class=\"muted-text fs-7\" style=\"margin-left: 12px\">Sort</span>\r\n <div\r\n *ngIf=\"\r\n columnThreedotsMunuConfig?.showAscending &&\r\n (sortingConfig?.field != col.field ||\r\n sortingConfig?.order_by == 'desc')\r\n \"\r\n class=\"column-menu-item\"\r\n (click)=\"sortAsc(activeCol)\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-up.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Sort Ascending\r\n </div>\r\n\r\n <!-- Sort Descending -->\r\n <div\r\n *ngIf=\"\r\n columnThreedotsMunuConfig?.showDescending &&\r\n (sortingConfig?.field != col.field ||\r\n sortingConfig?.order_by == 'asc')\r\n \"\r\n class=\"column-menu-item\"\r\n (click)=\"sortDesc(activeCol)\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-down.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Sort Descending\r\n </div>\r\n\r\n <div\r\n *ngIf=\"\r\n sortingConfig?.field === col.field &&\r\n (sortingConfig?.order_by === 'asc' ||\r\n sortingConfig?.order_by === 'desc')\r\n \"\r\n class=\"column-menu-item\"\r\n (click)=\"resetSort(activeCol)\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrow-counterclockwise.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Reset Sort\r\n </div>\r\n </div>\r\n <div class=\"py-2 border-below three-dots-filter\" [class.disable-sorting]=\"col?.type == 'image' || !col.is_search_able\">\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showFilter\"\r\n class=\"column-menu-item three-dots-filter\"\r\n (click)=\"openFilteronThreeDotsClick(col)\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Filter\r\n </div>\r\n </div>\r\n\r\n <div class=\"py-2 border-below\">\r\n <span class=\"muted-text fs-7\" style=\"margin-left: 12px\">Pin</span>\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showPinleft && col?.pinned !== 'left'\"\r\n class=\"column-menu-item\"\r\n (click)=\"\r\n $event.stopPropagation();\r\n updateColumnPinInSourceByField(\r\n activeCol,\r\n 'left',\r\n isNestedTable,\r\n columns\r\n )\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pin-left.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span\r\n >Pin Left\r\n </div>\r\n\r\n <div\r\n *ngIf=\"\r\n columnThreedotsMunuConfig?.showPinright && col?.pinned !== 'right'\r\n \"\r\n class=\"column-menu-item\"\r\n (click)=\"\r\n $event.stopPropagation();\r\n updateColumnPinInSourceByField(\r\n activeCol,\r\n 'right',\r\n isNestedTable,\r\n columns\r\n )\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pin-right.svg'\"\r\n class=\"data-grid-svg-icon data-grid-svg-icon me-2\"\r\n ></span\r\n >Pin Right\r\n </div>\r\n\r\n <div\r\n *ngIf=\"col?.pinned\"\r\n class=\"column-menu-item\"\r\n (click)=\"\r\n $event.stopPropagation();\r\n updateColumnPinInSourceByField(\r\n activeCol,\r\n null,\r\n isNestedTable,\r\n columns\r\n )\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/layout-three-columns.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span\r\n >Unpin\r\n </div>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showAutosizeThisColumn\"\r\n class=\"column-menu-item\"\r\n (click)=\"autosizeColumn(activeCol)\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrows-expand-vertical.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n Autosize This Column\r\n </div>\r\n\r\n <!-- Autosize All Columns -->\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showAutosizeAllColumns\"\r\n class=\"column-menu-item\"\r\n (click)=\"autosizeAllColumns()\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrows-angle-expand.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span\r\n >Autosize All Columns\r\n </div>\r\n\r\n <!-- Group By -->\r\n <div\r\n *ngIf=\"showRowsGrouping\"\r\n class=\"column-menu-item\"\r\n (click)=\"groupBy(activeCol)\"\r\n [class.disable-sorting]=\"!col.is_groupable\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/diagram-3.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Group by {{ col.header }}\r\n </div>\r\n\r\n <!-- Choose Columns -->\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showChoseColumns\"\r\n class=\"column-menu-item\"\r\n (click)=\"chooseColumns()\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/ui-checks-grid.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n Choose Columns\r\n </div>\r\n\r\n <!-- Reset Columns -->\r\n <div\r\n *ngIf=\"columnThreedotsMunuConfig?.showResetColumns\"\r\n class=\"column-menu-item\"\r\n (click)=\"resetColumns()\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrow-counterclockwise.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span\r\n >Reset Columns\r\n </div>\r\n </div>\r\n <div\r\n @slideToggle\r\n *ngIf=\"isThreeDotsFilterOpen && col?.is_search_able\"\r\n class=\"three-dots-col-menu position-relative\"\r\n [style.right.px]=\"getDynamicRight(col, section, columnIndex, childColIndex)\"\r\n [class.visually-hidden]=\"isMenueHidden\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"filterMenu; context: { col: col }\"\r\n ></ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Filter Menue -->\r\n<ng-template #filterMenu let-col=\"col\">\r\n <div\r\n class=\"filter-menu-container filter-menu\"\r\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\r\n >\r\n <!-- Dropdown Type -->\r\n <ng-container *ngIf=\"col?.type === 'dropdown'|| col?.type == 'array'; else textFilter\">\r\n <div class=\"filter-dropdown-section p-1\">\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search...\"\r\n type=\"search\"\r\n [(ngModel)]=\"addFilterColumnInput\"\r\n />\r\n\r\n <div class=\"form-check mb-1 mt-2 ms-1 select-all-filter\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [checked]=\"isAllSideFilterOptionsSelected(col)\"\r\n (change)=\"toggleSelectAllSideFilters(col, $event)\"\r\n id=\"selectAll_{{ col.field }}\"\r\n />\r\n <label class=\"form-check-label\" for=\"selectAll_{{ col.field }}\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- <div class=\"dropdown-options ps-1\">\r\n <div\r\n class=\"form-check mb-1\"\r\n *ngFor=\"\r\n let option of selectedColumnForFilter?.column_dropdown_value\r\n | filter : addFilterColumnInput : 'value';\r\n trackBy: trackById;\r\n let i = index\r\n \"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"i\"\r\n [checked]=\"\r\n currentFilterSelectedIds.has(option?.id ?? option?._id ?? option)\r\n \"\r\n (change)=\"toggleSelectionInFilter(option)\"\r\n />\r\n <label class=\"form-check-label fw-semibold\" [for]=\"i\">\r\n {{ option?.value ?? option?.name ?? option }}\r\n </label>\r\n </div>\r\n </div> -->\r\n <cdk-virtual-scroll-viewport\r\n itemSize=\"32\"\r\n class=\"filter-viewport\"\r\n style=\"height: 120px\"\r\n >\r\n <div\r\n class=\"form-check mb-1 ms-1\"\r\n *cdkVirtualFor=\"\r\n let option of selectedColumnForFilter?.column_dropdown_value\r\n | filter : addFilterColumnInput : 'value';\r\n trackBy: trackById\r\n \"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"option?.id ?? option?._id ?? option\"\r\n [checked]=\"\r\n currentFilterSelectedIds.has(option?.id ?? option?._id ?? option)\r\n \"\r\n (change)=\"toggleSelectionInFilter(option)\"\r\n />\r\n\r\n <label\r\n class=\"form-check-label fw-semibold\"\r\n [for]=\"option?.id ?? option?._id ?? option\"\r\n >\r\n {{ ((option?.value ?? option?.name ?? option) | titlecase ) }}\r\n </label>\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Text Filter Section -->\r\n <ng-template #textFilter>\r\n <div class=\"filter-text-section\">\r\n <div class=\"form-group mb-2\">\r\n <select\r\n class=\"form-select form-select-sm custom-select\"\r\n [(ngModel)]=\"firstCondition\"\r\n >\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n\r\n <input\r\n [type]=\"col?.type == 'string' ? 'text' : col?.type\"\r\n class=\"form-control form-control-sm mb-3\"\r\n placeholder=\"Value\"\r\n [(ngModel)]=\"firstValue\"\r\n #filterMenueTextchInput\r\n (keydown.enter)=\"applyDropdownFilter()\"\r\n />\r\n\r\n <div class=\"form-group mb-3 d-flex flex-row\">\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"condition\"\r\n value=\"and\"\r\n id=\"and_{{ col.field }}\"\r\n (change)=\"cdr.detectChanges()\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"and_{{ col.field }}\"\r\n >AND</label\r\n >\r\n </div>\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1 gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"condition\"\r\n value=\"or\"\r\n id=\"or_{{ col.field }}\"\r\n (change)=\"cdr.detectChanges()\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"or_{{ col.field }}\"\r\n >OR</label\r\n >\r\n </div>\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1 gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"condition\"\r\n value=\"none\"\r\n id=\"none_{{ col.field }}\"\r\n (change)=\"cdr.detectChanges()\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"none_{{ col.field }}\"\r\n >None</label\r\n >\r\n </div>\r\n </div>\r\n <div @slideToggle *ngIf=\"firstValue && condition != 'none'\">\r\n <div class=\"form-group mb-2\">\r\n <select\r\n class=\"form-select form-select-sm custom-select\"\r\n [(ngModel)]=\"secondCondition\"\r\n >\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n\r\n <input\r\n [type]=\"col?.type == 'string' ? 'text' : col?.type\"\r\n class=\"form-control form-control-sm mb-3\"\r\n placeholder=\"Second Value\"\r\n [(ngModel)]=\"secondValue\"\r\n />\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Actions -->\r\n <div class=\"d-flex gap-2 mt-2\">\r\n <div\r\n class=\"btn btn-sm btn-primary d-flex justify-content-center align-items-center w-100\"\r\n style=\"height: 30px\"\r\n (click)=\"applyDropdownFilter()\"\r\n >\r\n Apply\r\n </div>\r\n <div\r\n class=\"btn btn-sm btn-secondary d-flex justify-content-center align-items-center w-100\"\r\n style=\"height: 30px\"\r\n (click)=\"resetSideFilter(col)\"\r\n >\r\n Reset\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Side Menue -->\r\n\r\n<!-- Column Pannel / Pivot Mode / Searching -->\r\n\r\n<ng-template #columnPannel>\r\n <div class=\"column-panel-header\">\r\n <!-- Pivot Toggle -->\r\n <div\r\n class=\"form-check form-switch d-flex align-items-center mb-2 pivot-mode px-5 ms-2 d-none\"\r\n >\r\n <input\r\n class=\"form-check-input me-2\"\r\n type=\"checkbox\"\r\n id=\"pivotToggle\"\r\n [(ngModel)]=\"pivotMode\"\r\n />\r\n <label class=\"form-check-label\" for=\"pivotToggle\">Pivot Mode</label>\r\n </div>\r\n\r\n <!-- Select All & Search -->\r\n <div class=\"d-flex align-items-center mb-2 px-3 mt-3\">\r\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n accordionState === 'all'\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : accordionState === 'some'\r\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n (click)=\"toggleAllAccordions()\"\r\n ></span>\r\n </span>\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input me-2\"\r\n [checked]=\"allColumnsSelected()\"\r\n (change)=\"toggleAllColumnsVisibility()\"\r\n />\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search columns...\"\r\n [(ngModel)]=\"columnSearch\"\r\n />\r\n </div>\r\n\r\n <!-- Separator -->\r\n <hr class=\"my-2\" />\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Right Columns Menue -->\r\n\r\n<!-- Column Panel Item Template -->\r\n<ng-template #columnPanelItem let-col=\"col\">\r\n <!-- Group Column -->\r\n <ng-container *ngIf=\"col.children?.length\">\r\n <div class=\"column-group d-flex align-items-center mb-2\">\r\n <span class=\"filter-icon-wrapper me-2\">\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n [class.rotate]=\"col.expanded\"\r\n (click)=\"col.expanded = !col.expanded\"\r\n ></span>\r\n </span>\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input me-2\"\r\n [id]=\"'group_' + col.header\"\r\n [checked]=\"isColumnVisible(col)\"\r\n (change)=\"toggleGroupVisibility(col)\"\r\n />\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center me-2\"\r\n ></span>\r\n <label\r\n class=\"d-flex align-items-center mb-0 w-100\"\r\n [for]=\"'group_' + col.header\"\r\n style=\"cursor: pointer\"\r\n >\r\n <span class=\"text-truncate\">{{ col.header }}</span>\r\n </label>\r\n </div>\r\n <div *ngIf=\"col.expanded\" class=\"ps-4\">\r\n <ng-container *ngFor=\"let child of col.children; trackBy: trackByField\">\r\n <ng-container\r\n *ngTemplateOutlet=\"columnPanelItem; context: { col: child }\"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Leaf Column -->\r\n <ng-container *ngIf=\"!col.children?.length\">\r\n <div class=\"d-flex align-items-center mb-2\">\r\n <span class=\"me-2\" style=\"width: 1.5rem\"></span>\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input me-2\"\r\n [(ngModel)]=\"col.is_visible\"\r\n [id]=\"'col_' + col.field\"\r\n (change)=\"onSideMenuColumnsVisibilityChange()\"\r\n />\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center me-2\"\r\n ></span>\r\n <label\r\n class=\"d-flex align-items-center mb-0 w-100\"\r\n [for]=\"'col_' + col.field\"\r\n style=\"cursor: pointer\"\r\n >\r\n <span class=\"text-truncate\">{{ col.header }}</span>\r\n </label>\r\n </div>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Columns Side Filter -->\r\n<ng-template #sideFilters>\r\n <div class=\"py-3 px-2 pe-3 h-100\">\r\n <div class=\"d-flex align-items-center mb-2\">\r\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n filterAccordionState === 'all'\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : filterAccordionState === 'some'\r\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n (click)=\"toggleAllFilterAccordions()\"\r\n ></span>\r\n </span>\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search...\"\r\n [(ngModel)]=\"columnSearch\"\r\n />\r\n </div>\r\n <div\r\n class=\"overflow-auto side-filter-columns-wrapper\"\r\n style=\"height: calc(100% - 70px); scrollbar-width: thin\"\r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let col of columns | filter : columnSearch : 'header';\r\n trackBy: trackByField\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"filterPannelItem; context: { col: col }\"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #filterPannelItem let-col=\"col\">\r\n <!-- Group Column -->\r\n <ng-container *ngIf=\"col.children?.length\">\r\n <div\r\n class=\"column-group d-flex align-items-center mb-2\"\r\n *ngIf=\"col?.type !== 'image'\"\r\n >\r\n <!-- Chevron toggle -->\r\n <span class=\"filter-icon-wrapper me-2\">\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n [class.rotate]=\"col.expandedFilter\"\r\n (click)=\"col.expandedFilter = !col.expandedFilter\"\r\n ></span>\r\n </span>\r\n\r\n <!-- Group label toggle -->\r\n <label\r\n class=\"d-flex align-items-center mb-0 w-100\"\r\n style=\"cursor: pointer\"\r\n (click)=\"col.expandedFilter = !col.expandedFilter\"\r\n >\r\n <span class=\"fw-bold text-truncate\"\r\n >{{ col.header }}\r\n <span\r\n class=\"text-primary ms-1\"\r\n *ngIf=\"col?.query?._ids?.length || col?.query?._first_value\"\r\n >*</span\r\n >\r\n </span>\r\n </label>\r\n </div>\r\n\r\n <!-- Children columns -->\r\n <div *ngIf=\"col.expandedFilter\" class=\"ps-4\">\r\n <ng-container *ngFor=\"let child of col.children; trackBy: trackByField\">\r\n <ng-container\r\n *ngTemplateOutlet=\"filterPannelItem; context: { col: child }\"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Leaf Column -->\r\n <ng-container *ngIf=\"!col.children?.length\">\r\n <div class=\"d-flex align-items-center mb-2\" *ngIf=\"col?.type !== 'image'\">\r\n <span\r\n class=\"me-2 filter-icon-wrapper me-2\"\r\n (click)=\"col.expandedFilter = !col.expandedFilter\"\r\n >\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n [class.rotate]=\"col.expandedFilter\"\r\n ></span>\r\n </span>\r\n\r\n <label\r\n class=\"d-flex align-items-center mb-0 w-100\"\r\n style=\"cursor: pointer\"\r\n (click)=\"col.expandedFilter = !col.expandedFilter\"\r\n >\r\n <span class=\"text-truncate fw-bold\">{{ col.header }}</span>\r\n </label>\r\n </div>\r\n\r\n <!-- Show filter when expanded -->\r\n <div *ngIf=\"col.expandedFilter\" class=\"ps-4 pe-3\">\r\n <ng-container\r\n *ngTemplateOutlet=\"sideNestedFilter; context: { col: col }\"\r\n ></ng-container>\r\n </div>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Side Nested Filters -->\r\n<ng-template #sideNestedFilter let-col=\"col\">\r\n <div class=\"\">\r\n <!-- Dropdown Type -->\r\n <ng-container *ngIf=\"col?.type === 'dropdown' || col?.type == 'array'; else textFilter\">\r\n <div class=\"p-1\">\r\n <!-- Search -->\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm mb-2\"\r\n placeholder=\"Search...\"\r\n [(ngModel)]=\"sideNestedFilterSearch\"\r\n />\r\n\r\n <!-- Select All -->\r\n <div class=\"form-check mb-1 ms-1 select-all-filter\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [checked]=\"\r\n col.query?._ids?.length == col?.column_dropdown_value?.length\r\n \"\r\n (change)=\"toggleSelectAllSideFilters(col, $event)\"\r\n id=\"selectAll_{{ col.field }}\"\r\n />\r\n <label class=\"form-check-label\" for=\"selectAll_{{ col.field }}\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- Options -->\r\n <!-- <div class=\"dropdown-options\">\r\n <div\r\n class=\"form-check mb-1 ms-1\"\r\n *ngFor=\"\r\n let option of col?.column_dropdown_value\r\n | filter : sideNestedFilterSearch : 'value'\r\n \"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [value]=\"option\"\r\n [checked]=\"\r\n col.query?._ids?.includes(option?._id || option?.id || option)\r\n \"\r\n (change)=\"onOptionToggle(col, option)\"\r\n id=\"option_{{ col.field }}_{{\r\n option?.id || option?._id || option\r\n }}\"\r\n />\r\n <label\r\n class=\"form-check-label\"\r\n [for]=\"\r\n 'option_' +\r\n col.field +\r\n '_' +\r\n (option?.id || option?._id || option)\r\n \"\r\n >\r\n {{ option.value || option }}\r\n </label>\r\n </div>\r\n </div> -->\r\n <cdk-virtual-scroll-viewport\r\n itemSize=\"32\"\r\n class=\"dropdown-viewport\"\r\n style=\"height: 120px\"\r\n >\r\n <div\r\n class=\"form-check mb-1 ms-1\"\r\n *cdkVirtualFor=\"\r\n let option of col?.column_dropdown_value\r\n | filter : sideNestedFilterSearch : 'value'\r\n \"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [value]=\"option\"\r\n [checked]=\"\r\n col.query?._ids?.includes(option?._id || option?.id || option)\r\n \"\r\n (change)=\"onOptionToggle(col, option)\"\r\n id=\"option_{{ col.field }}_{{\r\n option?.id || option?._id || option\r\n }}\"\r\n />\r\n\r\n <label\r\n class=\"form-check-label\"\r\n [for]=\"\r\n 'option_' +\r\n col.field +\r\n '_' +\r\n (option?.id || option?._id || option)\r\n \"\r\n >\r\n {{( (option.value || option) | titlecase ) }}\r\n </label>\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n\r\n\r\n <!-- Actions -->\r\n <!-- <div class=\"d-flex gap-2 mt-2\">\r\n <div\r\n class=\"btn btn-sm btn-primary d-flex justify-content-center align-items-center\"\r\n style=\"height: 22px;\"\r\n (click)=\"applySideFilter(col)\"\r\n >\r\n Apply\r\n </div>\r\n <div\r\n class=\"btn btn-sm btn-secondary d-flex justify-content-center align-items-center\" \r\n style=\"height: 22px;\"\r\n (click)=\"resetSideFilter(col)\"\r\n >\r\n Reset\r\n </div>\r\n </div> -->\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Text Filter Section -->\r\n <ng-template #textFilter>\r\n <div class=\"filter-text-section\">\r\n <div class=\"form-group mb-2\">\r\n <select\r\n class=\"form-select form-select-sm\"\r\n [(ngModel)]=\"col.query.first_condition\"\r\n >\r\n <ng-container *ngIf=\"col?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"col?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"col?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n\r\n <input\r\n [type]=\"col?.type == 'date' ? 'date' : 'text'\"\r\n class=\"form-control form-control-sm mb-3\"\r\n placeholder=\"Value\"\r\n [(ngModel)]=\"col!.query!.first_value\"\r\n />\r\n\r\n <div\r\n class=\"form-group mb-3 d-flex flex-row muted\"\r\n style=\"font-size: 14px\"\r\n >\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"col!.query.condition\"\r\n value=\"and\"\r\n id=\"and_{{ col.field }}\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"and_{{ col.field }}\"\r\n >AND</label\r\n >\r\n </div>\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"col!.query.condition\"\r\n value=\"or\"\r\n id=\"or_{{ col.field }}\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"or_{{ col.field }}\"\r\n >OR</label\r\n >\r\n </div>\r\n <div\r\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input filter-radio-inputs\"\r\n type=\"radio\"\r\n name=\"condition\"\r\n [(ngModel)]=\"col!.query.condition\"\r\n value=\"none\"\r\n id=\"none_{{ col.field }}\"\r\n />\r\n <label\r\n class=\"nnonem-check-label mb-0 mt-1\"\r\n for=\"none_{{ col.field }}\"\r\n >None</label\r\n >\r\n </div>\r\n </div>\r\n <ng-container\r\n *ngIf=\"col?.query?.first_value && col?.query?.condition !== 'none'\"\r\n >\r\n <div class=\"form-group mb-2\">\r\n <select\r\n class=\"form-select form-select-sm\"\r\n [(ngModel)]=\"col!.query.second_condition\"\r\n >\r\n <ng-container *ngIf=\"col?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"col?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"col?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n\r\n <input\r\n [type]=\"col?.type == 'date' ? 'date' : 'text'\"\r\n class=\"form-control form-control-sm mb-3\"\r\n placeholder=\"Second Value\"\r\n [(ngModel)]=\"col!.query.second_value\"\r\n />\r\n </ng-container>\r\n <!-- <div class=\"d-flex gap-2\">\r\n <div class=\"btn btn-sm btn-primary d-flex justify-content-center align-items-center\" style=\"height: 22px;\" (click)=\"applyDropdownFilter()\">apply</div>\r\n <div class=\"btn btn-sm btn-secondary d-flex justify-content-center align-items-center\" style=\"height: 22px;\" (click)=\"applyDropdownFilter()\">reset</div>\r\n\r\n </div> -->\r\n </div>\r\n </ng-template>\r\n <div\r\n class=\"d-flex justify-content-center gap-2 border-top\"\r\n style=\"height: 38px\"\r\n >\r\n <button\r\n type=\"button\"\r\n style=\"max-height: 30px\"\r\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\r\n (click)=\"$event.stopPropagation(); removeSideFilter(col)\"\r\n >\r\n <span>Clear</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n style=\"max-height: 30px\"\r\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\r\n (click)=\"applySideFilter(col)\"\r\n [class.disabled]=\"(col?.query.condition !== 'none' && !col?.query?.second_value)\"\r\n [class.pe-none]=\"(col!?.query.condition !== 'none' && !col?.query?.second_value)\"\r\n >\r\n <span style=\"margin-top: -1px\">Apply</span>\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Centr Overlay for showing the chose columns -->\r\n\r\n<div *ngIf=\"showColumnPanel\" class=\"custom-modal-overlay\">\r\n <div\r\n class=\"custom-modal-content\"\r\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"modalColumnPannel\"></ng-container>\r\n </div>\r\n</div>\r\n\r\n<!-- The existing ng-template you provided -->\r\n<ng-template #modalColumnPannel>\r\n <div class=\"column-panel-header\">\r\n <div\r\n class=\"d-flex justify-content-between align-items-center px-2 ps-3 rounded-top-2 moda-header\"\r\n [style.height.px]=\"48\"\r\n >\r\n Choose Columns\r\n <span class=\"filter-icon-wrapper\" (click)=\"closeModalColumnPanel()\"\r\n ><span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/x.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span\r\n ></span>\r\n </div>\r\n <hr class=\"my-0\" />\r\n <div>\r\n <div class=\"d-flex align-items-center px-2 pe-3\" [style.height.px]=\"48\">\r\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\r\n <span\r\n class=\"toggle-icon data-grid-svg-icon\"\r\n [inlineSVG]=\"\r\n accordionState === 'all'\r\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\r\n : accordionState === 'some'\r\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\r\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\r\n \"\r\n (click)=\"toggleAllAccordions()\"\r\n ></span>\r\n </span>\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input me-2\"\r\n [checked]=\"allColumnsSelected()\"\r\n (change)=\"toggleAllColumnsVisibility()\"\r\n />\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search columns...\"\r\n [(ngModel)]=\"choseColumnsSearch\"\r\n />\r\n </div>\r\n\r\n <hr class=\"mt-0 mb-1\" />\r\n <div class=\"px-2 overlay-scrollable\">\r\n <ng-container\r\n *ngFor=\"\r\n let col of columns | filter : choseColumnsSearch : 'header';\r\n trackBy: trackByField\r\n \"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"columnPanelItem; context: { col: col }\"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #sideMenuRowGroups>\r\n <div class=\"d-flex flex-column h-100 d-none\">\r\n <div class=\"px-3 h-100\">\r\n <div class=\"d-flex gap-3 mb-4\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <span>Row Groups</span>\r\n </div>\r\n <div class=\"h-50\">\r\n <div\r\n class=\"px-3 py-2 border-dashed h-100 d-flex justify-content-center align-items-center\"\r\n style=\"font-size: 14px\"\r\n >\r\n Drag here to set row Groups\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <hr class=\"mt-4\" />\r\n\r\n <div class=\"px-3 h-100\">\r\n <div class=\"d-flex gap-3 mb-4\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <span>Values</span>\r\n </div>\r\n <div class=\"h-50 d-flex\">\r\n <div\r\n class=\"px-3 py-2 border-dashed h-100 d-flex justify-content-center align-items-center\"\r\n style=\"font-size: 14px\"\r\n >\r\n Drag here aggregate\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- *************************************************** -->\r\n<!-- *************************************************** -->\r\n<!-- *************************************************** -->\r\n<!-- Drag Preview Template -->\r\n<!-- *************************************************** -->\r\n<!-- *************************************************** -->\r\n<ng-template #dragPreview let-col>\r\n <div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ col.header }}</div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Drag Placeholder Template -->\r\n<ng-template\r\n #dragPlaceholder\r\n let-col\r\n let-i=\"index\"\r\n let-section=\"section\"\r\n let-draggingInGroupArea=\"draggingInGroupArea\"\r\n>\r\n <div *ngIf=\"!draggingInGroupArea\">\r\n <div\r\n *ngTemplateOutlet=\"\r\n headerCell;\r\n context: { $implicit: col, index: i, section: section }\r\n \"\r\n ></div>\r\n </div>\r\n <div *ngIf=\"draggingInGroupArea\">New Placeholder</div>\r\n</ng-template>\r\n\r\n<!-- Top Group Row Placeholder -->\r\n<ng-template #topGroupingRowPlaceholder let-col let-showChevron=\"showChevron\">\r\n <div class=\"d-flex gap-2\">\r\n <div\r\n class=\"d-flex gap-2 top-row-grouping-placeholder\"\r\n [style.backgroundColor]=\"topGroupedBadgesBackgroundColor\"\r\n >\r\n <span\r\n cdkDragHandle\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n <span>{{ col.header }}</span>\r\n <span\r\n (click)=\"ungroupColumn(col)\"\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/x.svg'\"\r\n class=\"cursor-pointer data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n <div *ngIf=\"showChevron\" style=\"opacity: 0.6; font-size: 14px\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template\r\n #childHeaderPlaceholder\r\n let-col\r\n let-pinnedRight=\"pinnedRight\"\r\n let-i=\"index\"\r\n let-sections=\"sections\"\r\n>\r\n <div\r\n class=\"header-cell one-row-header-cells\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n [style.fontWeight]=\"headerFontWeight\"\r\n >\r\n <div class=\"d-flex justify-content-between h-100 align-items-center w-100\">\r\n <div\r\n class=\"d-flex justify-content-between align-items-center w-100\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div\r\n class=\"text-ellipsis h-100 d-flex align-items-center\"\r\n [title]=\"col.header\"\r\n [class.w-100]=\"pinnedRight\"\r\n >\r\n {{ col.header }}\r\n </div>\r\n\r\n <div\r\n class=\"position-relative d-flex\"\r\n [class.flex-row-reverse]=\"pinnedRight\"\r\n >\r\n <div class=\"three-dots p-1\" style=\"cursor: pointer\">\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/three-dots-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n\r\n <div class=\"resize-handle\">\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div\r\n *ngIf=\"showFilterRow\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n class=\"header-cell filter-cell\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n [class.border-right]=\"showVerticalBorder\"\r\n style=\"grid-row: 3\"\r\n >\r\n <div\r\n class=\"header-cell filter-cell\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n [style.width.px]=\"col.width\"\r\n [style.min-width.px]=\"col.width\"\r\n [style.height.px]=\"headerRowHeight\"\r\n [style.min-height.px]=\"headerRowHeight\"\r\n [style.max-height.px]=\"headerRowHeight\"\r\n >\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Filter\"\r\n [(ngModel)]=\"col.filterValue\"\r\n [readonly]=\"col?.type == 'dropdown' || col?.type == 'image' || col?.type == 'array'\"\r\n [class.disabled-search-input]=\"\r\n col?.type == 'dropdown' || col?.type == 'image' || col?.type == 'array'\r\n \"\r\n />\r\n <span\r\n class=\"filter-icon-wrapper\"\r\n (click)=\"activeFilterCell = col; activeCol = null\"\r\n ><span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span\r\n ></span>\r\n\r\n <div\r\n class=\"position-absolute\"\r\n *ngIf=\"activeFilterCell === col\"\r\n style=\"top: 100%; right: 0; z-index: 10; left: 0\"\r\n ></div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #tableLayout>\r\n <div\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"p-3 shadow actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\r\n style=\"width: 320px\"\r\n >\r\n <div class=\"d-flex align-items-center mb-3\">\r\n <button\r\n class=\"btn btn-link p-0\"\r\n style=\"margin-left: -10px\"\r\n (click)=\"toggleActions('setting')\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </button>\r\n <h6 class=\"mb-0 ms-2\" style=\"font-weight: 500\">Table Layout</h6>\r\n </div>\r\n <hr class=\"my-2\" />\r\n <div class=\"w-100 mb-3 d-flex\" role=\"group\">\r\n <input\r\n type=\"radio\"\r\n class=\"btn-check layout-button-check\"\r\n name=\"layoutSize\"\r\n id=\"small\"\r\n autocomplete=\"off\"\r\n (change)=\"changeTableLayout($event, 'small')\"\r\n [checked]=\"selectedTableLayout == 'small'\"\r\n />\r\n <label\r\n class=\"border d-flex flex-column align-items-center layout-button\"\r\n for=\"small\"\r\n [ngStyle]=\"{\r\n color: selectedTableLayout == 'small' ? '#000' : '#727272'\r\n }\"\r\n >\r\n <div class=\"preview-box border mb-1\" style=\"height: 8px\"></div>\r\n Small\r\n </label>\r\n\r\n <input\r\n type=\"radio\"\r\n class=\"btn-check layout-button-check\"\r\n name=\"layoutSize\"\r\n id=\"medium\"\r\n autocomplete=\"off\"\r\n [checked]=\"selectedTableLayout == 'medium'\"\r\n (change)=\"changeTableLayout($event, 'medium')\"\r\n />\r\n <label\r\n class=\"border mx-3 d-flex flex-column align-items-center layout-button\"\r\n for=\"medium\"\r\n [ngStyle]=\"{\r\n color: selectedTableLayout == 'medium' ? '#000' : '#727272'\r\n }\"\r\n >\r\n <div class=\"preview-box border mb-1\" style=\"height: 12px\"></div>\r\n Medium\r\n </label>\r\n\r\n <input\r\n type=\"radio\"\r\n class=\"btn-check layout-button-check\"\r\n name=\"layoutSize\"\r\n id=\"large\"\r\n autocomplete=\"off\"\r\n (change)=\"changeTableLayout($event, 'large')\"\r\n [checked]=\"selectedTableLayout == 'large'\"\r\n />\r\n <label\r\n class=\"border d-flex flex-column align-items-center layout-button\"\r\n for=\"large\"\r\n [ngStyle]=\"{\r\n color: selectedTableLayout == 'large' ? '#000' : '#727272'\r\n }\"\r\n >\r\n <div class=\"preview-box border mb-1\" style=\"height: 16px\"></div>\r\n Large\r\n </label>\r\n </div>\r\n\r\n <hr class=\"my-2\" />\r\n <div class=\"d-flex justify-content-between align-items-center mb-2\">\r\n <span>Show separators</span>\r\n <div class=\"form-check form-switch m-0\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n id=\"separators\"\r\n [(ngModel)]=\"showVerticalBorder\"\r\n (change)=\"onFontChange()\"\r\n />\r\n </div>\r\n </div>\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n <span>Row shading</span>\r\n <div class=\"form-check form-switch m-0\">\r\n <input\r\n class=\"form-check-input\"\r\n [(ngModel)]=\"rowShadingEnabled\"\r\n (change)=\"toggleRowShading()\"\r\n type=\"checkbox\"\r\n id=\"rowShading\"\r\n />\r\n </div>\r\n </div>\r\n <!-- <div class=\"d-flex justify-content-between align-items-center mb-2\">\r\n <span>Show Side Menu</span>\r\n <div class=\"form-check form-switch m-0\">\r\n <input\r\n class=\"form-check-input\"\r\n [(ngModel)]=\"showSideMenu\"\r\n type=\"checkbox\"\r\n id=\"rowShading\"\r\n />\r\n </div>\r\n </div>\r\n <div class=\"d-flex justify-content-between align-items-center mb-2\">\r\n <span>Show Filter Row</span>\r\n <div class=\"form-check form-switch m-0\">\r\n <input\r\n class=\"form-check-input\"\r\n [(ngModel)]=\"showFilterRow\"\r\n type=\"checkbox\"\r\n id=\"rowShading\"\r\n />\r\n </div>\r\n </div> -->\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #tablePreset>\r\n <div\r\n *ngIf=\"activeSubButton !== 'save-preset'\"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"p-3 shadow actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\r\n style=\"width: 280px\"\r\n >\r\n <!-- Header -->\r\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\r\n <div class=\"d-flex align-items-center\">\r\n <button\r\n class=\"btn btn-link p-0\"\r\n style=\"margin-left: -10px\"\r\n (click)=\"toggleActions('setting')\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\r\n class=\"data-grid-svg-icon\"\r\n ></span>\r\n </button>\r\n <h6 class=\"mb-0 ms-2\" style=\"font-weight: 500\">Table Presets</h6>\r\n </div>\r\n <!-- Save Preset Button with Dropdown -->\r\n <div>\r\n <a\r\n class=\"text-decoration-none text-primary\"\r\n type=\"button\"\r\n id=\"savePresetDropdown\"\r\n (click)=\"$event.stopPropagation(); toggleSubActions('save-preset')\"\r\n >\r\n {{ isTablePresetNotChanged ? \"Save preset\" : \"Update Preset\" }}\r\n </a>\r\n </div>\r\n </div>\r\n\r\n <!-- Search -->\r\n <div class=\"mb-3\">\r\n <div class=\"col-12 global-search\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\r\n class=\"data-grid-svg-icon mx-2 position-absolute icon\"\r\n ></span>\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search...\"\r\n [(ngModel)]=\"searchTextPresetTable\"\r\n type=\"search\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Preset List -->\r\n <ng-container\r\n *ngIf=\"\r\n tableView | filter : searchTextPresetTable : 'name' as filteredList\r\n \"\r\n >\r\n <!-- If filteredList exists and none is default -> show fallback -->\r\n <div\r\n class=\" pb-5 overflow-auto\"\r\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight - 250\"\r\n >\r\n <div\r\n class=\"cursor-pointer\"\r\n (click)=\"\r\n clearAllFilters();\r\n openIndex = null;\r\n temp_state.id = '';\r\n activeTopButton = '';\r\n curretaTablePresetForUpdate = null\r\n \"\r\n >\r\n <div class=\"fw-semibold\">Default View</div>\r\n </div>\r\n <div class=\"d-flex justify-content-between\">\r\n <small class=\"text-dark\">Created by system</small>\r\n <span\r\n *ngIf=\"!tableFilterViewId && !hasAnyDefaultView()\"\r\n class=\"badge bg-light text-primary ms-2\"\r\n >Default</span\r\n >\r\n <!-- <span\r\n *ngIf=\"!tableFilterViewId && !hasAnyDefaultView()\"\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\"\r\n class=\"me-2\"\r\n ></span> -->\r\n <div\r\n class=\"dropdown d-flex justify-content-end\"\r\n *ngIf=\"tableFilterViewId\"\r\n ></div>\r\n </div>\r\n\r\n <!-- The list: render each table from filteredList -->\r\n <div\r\n class=\"list-group list-group-flush\"\r\n *ngFor=\"\r\n let table of filteredList;\r\n let i = index;\r\n trackBy: trackByTable\r\n \"\r\n >\r\n <!-- Item -->\r\n <div\r\n (click)=\"\r\n $event.stopPropagation(); openIndex = null; activeTopButton = ''\r\n \"\r\n class=\"list-group-item px-0 d-flex justify-content-between align-items-center\"\r\n >\r\n <div (click)=\"selectFilter(table); openIndex = null\">\r\n <div class=\"fw-semibold\" style=\"cursor: pointer\">\r\n {{ table?.name }}\r\n <!-- {{table?.is_temp}} -->\r\n <span\r\n *ngIf=\"\r\n (table?.is_temp && !temp_state.id) ||\r\n temp_state.id == table.id\r\n \"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n <span\r\n *ngIf=\"table?.is_default\"\r\n class=\"badge bg-light text-primary ms-2\"\r\n >Default</span\r\n >\r\n </div>\r\n <small class=\"text-dark\" *ngIf=\"table?.config?.filterNames\" [title]=\"table?.config?.filterNames\">\r\n {{\r\n table?.config?.filterNames?.length > 25\r\n ? (table?.config?.filterNames | slice:0:25) + '...'\r\n : table?.config?.filterNames\r\n }}\r\n ({{ table?.config?.totalCount }})\r\n </small>\r\n <small class=\"text-dark\" *ngIf=\"!table?.config?.filterNames\">{{ table?.createdAt | date : \"MMM d, y\" }}</small>\r\n </div>\r\n\r\n <div class=\"d-flex align-items-center\">\r\n <span\r\n *ngIf=\"table?.is_default\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n\r\n <div class=\"dropdown\" *ngIf=\"!table?.is_default\">\r\n <div\r\n class=\"dropdown-wrapper\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <button\r\n type=\"button\"\r\n class=\"btn-icon muted-text\"\r\n (click)=\"toggleMenu(i, $event)\"\r\n aria-haspopup=\"true\"\r\n [attr.aria-expanded]=\"openIndex === i\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/horizontal-dots.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n </button>\r\n\r\n <!-- menu -->\r\n <ul\r\n *ngIf=\"openIndex === i\"\r\n class=\"custom-dropdown-menu position-fixed top-auto\"\r\n role=\"menu\"\r\n [style.right.px]=\"'unset'\"\r\n [style.left.px]=\"dataGridContainer.offsetWidth - 200\"\r\n style=\"top: unset; right: unset\"\r\n >\r\n <li role=\"none\">\r\n <button\r\n role=\"menuitem\"\r\n class=\"dropdown-item\"\r\n (click)=\"\r\n actionPreset(table, 'setPreset'); temp_state.id = ''\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/star.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n Set as default\r\n </button>\r\n </li>\r\n\r\n <li role=\"none\" *ngIf=\"!table.confirmDelete\">\r\n <button\r\n role=\"menuitem\"\r\n class=\"dropdown-item text-danger\"\r\n (click)=\"table.confirmDelete = true\"\r\n >\r\n <span\r\n style=\"margin-top: -4px\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/trash-red.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n Delete\r\n </button>\r\n </li>\r\n\r\n <li\r\n role=\"none\"\r\n *ngIf=\"table.confirmDelete\"\r\n class=\"confirm-block\"\r\n >\r\n <div class=\"px-3 py-2 text-center\">\r\n <div class=\"mb-2\">\r\n Are you sure you want to delete <br /><b\r\n >\u201C{{ table?.name }}\u201D</b\r\n >?\r\n </div>\r\n <div class=\"d-flex gap-2\">\r\n <button\r\n class=\"btn btn-sm btn-light me-2\"\r\n (click)=\"table.confirmDelete = false\"\r\n >\r\n Cancel\r\n </button>\r\n <button\r\n class=\"btn btn-sm btn-danger\"\r\n (click)=\"actionPreset(table, 'deletePreset')\"\r\n >\r\n Delete\r\n </button>\r\n </div>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Item End Here -->\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <div\r\n (click)=\"$event.stopPropagation()\"\r\n *ngIf=\"activeSubButton == 'save-preset'\"\r\n class=\"dropdown-menu p-3 badge mt-4 save-preset-dropdown mt-1\"\r\n aria-labelledby=\"savePresetDropdown\"\r\n style=\"min-width: 250px\"\r\n >\r\n <div class=\"fw-bold fs-14px mb-2\">\r\n {{ isTablePresetNotChanged ? \"Save preset\" : \"Update Preset\" }}\r\n </div>\r\n <div class=\"fs-14px mb-2\" style=\"line-height: 20px\">\r\n This will save the current table adjustments as a preset.\r\n </div>\r\n <!-- Input -->\r\n <div class=\"mb-2\">\r\n <label for=\"presetName\" class=\"form-label fs-12px fw-bold\"\r\n >Preset Name</label\r\n >\r\n <div class=\"col-12 global-search\">\r\n <input\r\n #presetNameCtrl=\"ngModel\"\r\n required\r\n [(ngModel)]=\"presetName\"\r\n [ngClass]=\"{\r\n 'is-invalid':\r\n presetNameCtrl.invalid &&\r\n (presetNameCtrl.dirty || presetNameCtrl.touched)\r\n }\"\r\n class=\"form-control form-control-sm ps-2\"\r\n placeholder=\"Enter preset name\"\r\n type=\"text\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Checkbox -->\r\n <div class=\"form-check mb-2\">\r\n <input\r\n class=\"form-check-input\"\r\n [(ngModel)]=\"presetFilter\"\r\n type=\"checkbox\"\r\n id=\"saveFilters\"\r\n />\r\n <label class=\"form-check-label mt-1\" for=\"saveFilters\">\r\n Save active filters\r\n </label>\r\n </div>\r\n\r\n <!-- Save Button -->\r\n <div class=\"d-flex justify-content-center gap-2\" style=\"height: 32px\">\r\n <button\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn border w-100 d-flex align-items-center justify-content-center btn-light\"\r\n (click)=\"$event.stopPropagation(); toggleActions('table-presets')\"\r\n style=\"margin-top: -2px\"\r\n >\r\n <span>Cancel</span>\r\n </button>\r\n <button\r\n [disabled]=\"closeDropdown.preset.loading\"\r\n (click)=\"savePreset(presetNameCtrl)\"\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center\"\r\n >\r\n <span style=\"margin-top: -2px\" *ngIf=\"isTablePresetNotChanged\">\r\n <ng-container *ngIf=\"!closeDropdown.preset.loading\"\r\n >Save</ng-container\r\n >\r\n <ng-container *ngIf=\"closeDropdown.preset.loading\"\r\n ><span class=\"spinner-border spinner-border-sm\"></span\r\n ></ng-container>\r\n </span>\r\n <span style=\"white-space: nowrap\" *ngIf=\"!isTablePresetNotChanged\"\r\n >Update Preset</span\r\n >\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #showHideColumns>\r\n <div\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"p-3 shadow actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\r\n style=\"width: 280px\"\r\n >\r\n <!-- Header -->\r\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\r\n <div class=\"d-flex align-items-center\">\r\n <button\r\n class=\"btn btn-link p-0\"\r\n style=\"margin-left: -10px\"\r\n (click)=\"toggleActions('setting')\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\r\n class=\"data-grid-svg-icon\"\r\n ></span>\r\n </button>\r\n <h6 class=\"mb-0 ms-2\" style=\"font-weight: 500\">Columns</h6>\r\n </div>\r\n <a\r\n (click)=\"resetColumns()\"\r\n href=\"javascript:void(0)\"\r\n class=\"text-primary text-decoration-none d-none\"\r\n >Reset</a\r\n >\r\n </div>\r\n\r\n <!-- Search -->\r\n <div class=\"mb-3\">\r\n <div class=\"col-12 global-search\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\r\n class=\"mx-2 position-absolute icon data-grid-svg-icon\"\r\n ></span>\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search column\"\r\n type=\"search\"\r\n [(ngModel)]=\"topShowHideColumns\"\r\n />\r\n </div>\r\n </div>\r\n <!-- Preset List -->\r\n <div\r\n class=\"list-group list-group-flush\"\r\n style=\"overflow: auto; scrollbar-width: thin\"\r\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight - 220\"\r\n >\r\n <div class=\"muted-text show-hide-table-label d-flex justify-content-between\" *ngIf=\"hasAnyVisibleColumn\">\r\n Show in table\r\n <div class=\"form-check\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n id=\"hide_all\"\r\n [checked]=\"allColumnsSelected()\"\r\n (change)=\"toggleAllColumnsVisibility()\"\r\n />\r\n <label class=\"form-check-label fw-semibold\" for=\"hide_all\">\r\n Show/Hide All \r\n </label>\r\n </div>\r\n </div>\r\n <!-- Item -->\r\n <ng-container\r\n *ngFor=\"\r\n let col of columns | filter : topShowHideColumns : 'header';\r\n trackBy: trackByField\r\n \"\r\n >\r\n <div\r\n *ngIf=\"col.is_visible\"\r\n class=\"list-group-item border-0 px-0 d-flex justify-content-between align-items-center\"\r\n >\r\n <div class=\"d-flex gap-1\">\r\n <div>\r\n <span\r\n *ngIf=\"!col?.pinned\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/grip-vertical.svg'\r\n \"\r\n class=\"cursor-grap data-grid-svg-icon\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n ></span>\r\n <span\r\n *ngIf=\"col?.pinned\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'\r\n \"\r\n class=\"cursor-grap data-grid-svg-icon\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n ></span>\r\n </div>\r\n <div class=\"fw-semibold\">\r\n {{ col.header }}\r\n </div>\r\n </div>\r\n <div\r\n *ngIf=\"!col?.query?.first_value && !col?.query?._ids?.length\"\r\n class=\"d-flex align-items-center cursor-pointer\"\r\n (click)=\"toggleColumnVisibility(col, false)\"\r\n [class.disabled]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\r\n [class.pe-none]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\r\n [class.opacity-50]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/eye.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </div>\r\n <div\r\n *ngIf=\"col?.query?.first_value || col?.query?._ids?.length\"\r\n class=\"d-flex align-items-center\"\r\n style=\"opacity: 0.5\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/eye.svg'\"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Item End Here -->\r\n\r\n <div\r\n class=\"dropdown-divider\"\r\n *ngIf=\"hasAnyVisibleColumn && hasAnyInVisibleColumn\"\r\n ></div>\r\n\r\n <div\r\n class=\"muted-text show-hide-table-label d-flex justify-content-between\"\r\n *ngIf=\"hasAnyInVisibleColumn\"\r\n >\r\n Hide in table\r\n <div class=\"form-check\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n id=\"show_all\"\r\n [checked]=\"allColumnsSelected()\"\r\n (change)=\"toggleAllColumnsVisibility()\"\r\n />\r\n <label class=\"form-check-label fw-semibold\" for=\"show_all\">\r\n Show/Hide All \r\n </label>\r\n </div>\r\n </div>\r\n <div class=\"list-group list-group-flush\">\r\n <ng-container *ngFor=\"let col of columns; trackBy: trackByField\">\r\n <div\r\n *ngIf=\"!col.is_visible\"\r\n class=\"list-group-item border-0 px-0 d-flex justify-content-between align-items-center\"\r\n >\r\n <div class=\"d-flex gap-1\">\r\n <div>\r\n <span\r\n *ngIf=\"!col?.pinned\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/grip-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon cursor-grap\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n ></span>\r\n <span\r\n *ngIf=\"col?.pinned\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/pin-blue.svg'\r\n \"\r\n class=\"data-grid-svg-icon cursor-grap\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n ></span>\r\n </div>\r\n <div class=\"fw-semibold\">\r\n {{ col.header }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"d-flex align-items-center cursor-pointer\"\r\n (click)=\"toggleColumnVisibility(col, true)\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/eye-cross.svg'\r\n \"\r\n class=\"data-grid-svg-icon me-2\"\r\n ></span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Item End Here -->\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #filterColumns let-col=\"column\">\r\n <div\r\n @slideToggle\r\n *ngIf=\"!isFilterOpen && activeTopButton == 'filter-columns'\"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns\"\r\n style=\"width: 280px; right: unset; max-width: 230px\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n >\r\n <div class=\"mb-2 px-3\">\r\n <div class=\"col-12 global-search\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\r\n class=\"data-grid-svg-icon mx-2 position-absolute icon\"\r\n ></span>\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Filter by\"\r\n type=\"search\"\r\n [(ngModel)]=\"addFilterColumnInput\"\r\n />\r\n </div>\r\n </div>\r\n <div\r\n class=\"list-group list-group-flush\"\r\n style=\"max-height: calc(100vh - 500px); overflow: auto\"\r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let col of columns | filter : addFilterColumnInput : 'header';\r\n trackBy: trackByField\r\n \"\r\n >\r\n <div\r\n (click)=\"openFilter(col)\"\r\n *ngIf=\"\r\n col.is_visible &&\r\n !col?.query?.first_value &&\r\n !col?.query?._ids?.length && col?.type !== 'image' && col.is_search_able\r\n \"\r\n class=\"list-group-item border-0 px-0 d-flex justify-content-between align-items-center dropdown-item cursor-pointer\"\r\n >\r\n <div class=\"d-flex gap-1\">\r\n <div style=\"margin-top: -3px\"></div>\r\n <div class=\"fw-semibold\">\r\n {{ col.header }}\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- Dropdown -->\r\n <div\r\n @slideToggle\r\n *ngIf=\"isFilterOpen && selectedColumnForFilter?.type == 'dropdown' || selectedColumnForFilter?.type == 'array'\"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns pb-2\"\r\n style=\"width: 280px; right: unset; max-width: 230px\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n >\r\n <div class=\"px-3 my-2 border-below py-1 pb-2 mb-3 d-flex ps-1\">\r\n <span\r\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\r\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\r\n ></span\r\n ><b>{{ selectedColumnForFilter?.header }}</b>\r\n </div>\r\n <div class=\"mb-2 px-3\">\r\n <div\r\n class=\"col-12 global-search position-relative border rounded d-flex align-items-center flex-wrap px-2 filter-serach-inpt\"\r\n >\r\n <span\r\n *ngFor=\"let selected of selectedFilterOptions\"\r\n class=\"badge d-flex align-items-center gap-1 me-1 mb-1 top-row-filter-dropdown\"\r\n >\r\n {{ selected?.value ? selected.value : selected }}\r\n <span\r\n (click)=\"toggleSelectionInFilter(selected)\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/cross-primary.svg'\r\n \"\r\n class=\"me-2\"\r\n ></span>\r\n </span>\r\n <input\r\n class=\"form-control form-control-sm border-0 flex-grow-1\"\r\n style=\"padding: 0\"\r\n [placeholder]=\"selectedFilterOptions?.length ? '' : 'Filter by'\"\r\n type=\"search\"\r\n [(ngModel)]=\"searchTextForFilterDropDown\"\r\n (keydown.backspace)=\"handleBackspace($event)\"\r\n />\r\n </div>\r\n </div>\r\n <div\r\n class=\"list-group list-group-flush\"\r\n style=\"max-height: calc(100vh - 600px); overflow: auto\"\r\n >\r\n <ng-container\r\n *ngFor=\"\r\n let col of selectedColumnForFilter.column_dropdown_value\r\n | filter : searchTextForFilterDropDown : 'value';\r\n let i = index\r\n \"\r\n >\r\n <div\r\n class=\"list-group-item border-0 px-2 d-flex justify-content-between align-items-center dropdown-item cursor-pointer\"\r\n >\r\n <div class=\"form-check\">\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"i\"\r\n [checked]=\"currentFilterSelectedIds.has(col.id || col._id || col)\"\r\n (change)=\"toggleSelectionInFilter(col)\"\r\n />\r\n <label class=\"form-check-label fw-semibold\" [for]=\"i\">\r\n {{ col?.value || col?.name || col }}\r\n </label>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <div\r\n class=\"d-flex justify-content-center gap-2 px-2 border-top\"\r\n style=\"height: 38px\"\r\n >\r\n <button\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\r\n (click)=\"$event.stopPropagation(); resetFilterChanges()\"\r\n >\r\n <span>Cancel</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\r\n (click)=\"applyDropdownFilter()\"\r\n >\r\n <span style=\"margin-top: -2px\">Save</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- For Text fields and number fields-->\r\n\r\n <div\r\n @slideToggle\r\n *ngIf=\"\r\n isFilterOpen &&\r\n (selectedColumnForFilter?.type == 'string' ||\r\n selectedColumnForFilter?.type == 'number' ||\r\n selectedColumnForFilter?.type == 'date')\r\n \"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns pb-2\"\r\n style=\"width: 210px; right: unset; max-width: 230px\"\r\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\r\n >\r\n <div class=\"px-3 border-below py-1 pb-2 d-flex ps-1\">\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\r\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\r\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\r\n ></span\r\n ><b>{{ selectedColumnForFilter?.header }}</b>\r\n </div>\r\n <div class=\"col-12 position-relative p-2 text-filter\">\r\n <div class=\"mb-2\">\r\n <select\r\n class=\"form-select form-select-sm custom-select border\"\r\n [(ngModel)]=\"firstCondition\"\r\n >\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n <div class=\"mb-2\">\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Enter first value\"\r\n type=\"search\"\r\n [type]=\"\r\n selectedColumnForFilter?.type == 'string'\r\n ? 'text'\r\n : selectedColumnForFilter?.type\r\n \"\r\n [(ngModel)]=\"firstValue\"\r\n (keydown.enter)=\"applyDropdownFilter()\"\r\n />\r\n </div>\r\n <div>\r\n <div class=\"d-flex my-3 d-flex flex-row\" style=\"font-size: 14px\">\r\n <div\r\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"radio\"\r\n id=\"logicalAnd\"\r\n name=\"logicalOperator\"\r\n value=\"and\"\r\n [(ngModel)]=\"condition\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalAnd\"\r\n >AND</label\r\n >\r\n </div>\r\n\r\n <div\r\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"radio\"\r\n id=\"logicalOr\"\r\n name=\"logicalOperator\"\r\n value=\"or\"\r\n [(ngModel)]=\"condition\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalOr\">OR</label>\r\n </div>\r\n\r\n <div\r\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"radio\"\r\n id=\"logicalNone\"\r\n name=\"logicalOperator\"\r\n value=\"none\"\r\n [(ngModel)]=\"condition\"\r\n />\r\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalNone\"\r\n >None</label\r\n >\r\n </div>\r\n </div>\r\n\r\n <ng-container *ngIf=\"condition !== 'none' && firstValue\">\r\n <div class=\"mb-2 mt-3\">\r\n <!-- Second condition select -->\r\n <select\r\n class=\"form-select form-select-sm border\"\r\n [(ngModel)]=\"secondCondition\"\r\n >\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\r\n <option value=\"contain\">Contains</option>\r\n <option value=\"does_not_contain\">Does Not Contain</option>\r\n <option value=\"equal\">Equals</option>\r\n <option value=\"before\">Starts With</option>\r\n <option value=\"after\">Ends With</option>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"not_equal\">Not Equal</option>\r\n <option value=\"after\">After</option>\r\n <option value=\"before\">Before</option>\r\n </ng-container>\r\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\r\n <option value=\"equal\">Equals To</option>\r\n <option value=\"before\">Less Then </option>\r\n <option value=\"after\">Greater Then </option>\r\n <option value=\"less_then_equal\">less then Equal to</option>\r\n <option value=\"greater_then_equal\">Greater then Equal to </option>\r\n </ng-container>\r\n </select>\r\n </div>\r\n\r\n <div class=\"mb-2\">\r\n <!-- Second value input -->\r\n <input\r\n [type]=\"\r\n selectedColumnForFilter?.type == 'string'\r\n ? 'text'\r\n : selectedColumnForFilter?.type\r\n \"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Enter second value\"\r\n type=\"search\"\r\n [(ngModel)]=\"secondValue\"\r\n (keydown.enter)=\"applyDropdownFilter()\"\r\n />\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"d-flex justify-content-center gap-2 px-2 border-top\"\r\n style=\"height: 38px\"\r\n >\r\n <button\r\n [disabled]=\"!currentFilterSelectedIds?.size && !firstValue\"\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\r\n (click)=\"$event.stopPropagation(); resetTextFilterChanges()\"\r\n >\r\n <span>Cancel</span>\r\n </button>\r\n <button\r\n [disabled]=\"(currentFilterSelectedIds?.size === 0 && !firstValue) || (condition !== 'none' && !secondValue)\"\r\n type=\"button\"\r\n style=\"height: 32px\"\r\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\r\n (click)=\"applyDropdownFilter()\"\r\n >\r\n <span style=\"margin-top: -2px\">Apply</span>\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Edit dropdown here -->\r\n<ng-template let-col>\r\n <div class=\"drop-down-edit\"></div>\r\n</ng-template>\r\n\r\n<ng-template\r\n #fullTextTemplate\r\n let-row=\"row\"\r\n let-col=\"col\"\r\n let-isArray=\"isArray\"\r\n>\r\n <div\r\n class=\"full-text-box\"\r\n (dblclick)=\"$event.stopPropagation(); $event.preventDefault()\"\r\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\r\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight / 2\"\r\n >\r\n <ng-container *ngIf=\"!isEditing(row, col)\">\r\n <div\r\n *ngIf=\"!isArray\"\r\n class=\"full-text-content\"\r\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight / 2\"\r\n (dblclick)=\"\r\n $event.stopPropagation();\r\n $event.preventDefault();\r\n enableEdit(row, col, true)\r\n \"\r\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\r\n >\r\n {{\r\n getNestedValue(row, col.field)?.value ||\r\n getNestedValue(row, col.field)?.name ||\r\n getNestedValue(row, col.field)\r\n }}\r\n </div>\r\n <div *ngIf=\"isArray\">\r\n <ul>\r\n <ng-container\r\n *ngFor=\"let item of getNestedValue(row, col.field); let i = index\"\r\n >\r\n <li *ngIf=\"i !== 0\">\r\n <ng-container>\r\n {{\r\n item?.department_name ||\r\n item?.roleName ||\r\n item?.full_name ||\r\n \"-\"\r\n }}\r\n </ng-container>\r\n </li>\r\n </ng-container>\r\n </ul>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"isEditing(row, col)\">\r\n <textarea\r\n (dblclick)=\"\r\n $event.stopPropagation();\r\n $event.preventDefault();\r\n enableEdit(row, col, true)\r\n \"\r\n #textModel=\"ngModel\"\r\n rows=\"4\"\r\n #textAreadInput\r\n [(ngModel)]=\"row[col.field]\"\r\n name=\"{{ col.field }}\"\r\n required\r\n (blur)=\"disableEdit(row, col, textModel)\"\r\n (keydown.enter)=\"textAreadInput.blur()\"\r\n autofocus\r\n class=\"form-control\"\r\n [ngClass]=\"{\r\n 'is-invalid': textModel.invalid\r\n }\"\r\n (mousedown)=\"$event.stopPropagation()\"\r\n ></textarea>\r\n </ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #defaultImagePlaceholder let-row=\"row\" let-col=\"col\">\r\n <span\r\n class=\"px-2 d-flex w-100 cell-content image-placeholder\"\r\n [title]=\"row?.full_name || row?.name || 'N/A'\"\r\n >\r\n <ng-container\r\n *ngIf=\"\r\n row?.logo ||\r\n row?.assetImage ||\r\n row?.invoice?.invoice_image ||\r\n row?.invoice_image;\r\n else placeholder\r\n \"\r\n >\r\n <span\r\n (click)=\"fullscreenImage = row?.profile_pictures?.[4]?.path ||\r\n row?.logo ||\r\n row?.assetImage ||\r\n row?.invoice_image\"\r\n class=\"pic\"\r\n [style.width.px]=\"rowHeight - 10\"\r\n [style.height.px]=\"rowHeight - 10\"\r\n [class.assets-pic]=\"gridType == 'Assets'\"\r\n >\r\n <img\r\n [width]=\"rowHeight - 12\"\r\n [height]=\"rowHeight - 12\"\r\n [style.width.px]=\"rowHeight - 10\"\r\n [style.height.px]=\"rowHeight - 10\"\r\n [src]=\"\r\n row?.profile_pictures?.[4]?.path ||\r\n row?.logo ||\r\n row?.assetImage ||\r\n row?.invoice_image\r\n \"\r\n alt=\"icon\"\r\n class=\"option-icon\"\r\n loading=\"lazy\"\r\n />\r\n </span>\r\n </ng-container>\r\n <!-- <div\r\n class=\"fullscreen-overlay\"\r\n *ngIf=\"fullscreenImage\"\r\n (click)=\"fullscreenImage = null\"\r\n >\r\n <img [src]=\"fullscreenImage\" class=\"fullscreen-img\" />\r\n </div> -->\r\n\r\n <ng-template #placeholder>\r\n <span\r\n [ngClass]=\"getDynamicClass(row?.full_name || row?.name)\"\r\n class=\"pic d-flex align-items-center rounded-circle\"\r\n [style.width.px]=\"rowHeight - 12\"\r\n [style.height.px]=\"rowHeight - 12\"\r\n [style.fontSize.px]=\"rowHeight / 3\"\r\n [class.assets-pic]=\"gridType == 'Assets'\"\r\n >\r\n {{ getInitials(row?.full_name) }}\r\n </span>\r\n </ng-template>\r\n </span>\r\n</ng-template>\r\n\r\n<!-- Right Click Menue -->\r\n<div\r\n [class.invisible]=\"!positionedYet\"\r\n class=\"context-menu p-2\"\r\n *ngIf=\"actionHide && actions?.length\"\r\n [ngStyle]=\"{ 'top.px': yPos, 'left.px': xPos }\"\r\n [class.show]=\"isVisible\"\r\n appendTo=\"body\"\r\n>\r\n <ul>\r\n <li\r\n *ngFor=\"let action of actions\"\r\n class=\"rounded d-flex align-items-center\"\r\n (click)=\"onActionClick(action)\"\r\n >\r\n <span\r\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/' + action + '.svg'\"\r\n class=\"data-grid-svg-icon right-click-menu-icons me-2\"\r\n ></span>\r\n <span class=\"text-capitalize fw-500\">{{ action }}</span>\r\n </li>\r\n </ul>\r\n</div>\r\n\r\n<!-- Details Toggle from bottom -->\r\n\r\n<ng-template #nestedTableTemplate let-row>\r\n <div\r\n class=\"nested-table table table-sm w-100 mb-0 center-nested-table w-100\"\r\n style=\"table-layout: fixed !important\"\r\n #nestedTableContainer\r\n >\r\n <thead\r\n #nestedHeader\r\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\r\n >\r\n <div\r\n cdkDropList\r\n [cdkDropListData]=\"row?.detail.columns\"\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"dropColumn($event, row)\"\r\n (cdkDropListSorted)=\"onNestedColSort($event, previewNestedCols)\"\r\n [style.height.px]=\"nestedTableHeaderRowHeight\"\r\n class=\"d-flex tr border-below\"\r\n >\r\n <div\r\n *ngFor=\"let col of row.detail.columns; let i = index\"\r\n [style.width.px]=\"col?.width || 250\"\r\n [style.minWidth.px]=\"col?.width || 250\"\r\n [style.maxWidth.px]=\"col?.width || 250\"\r\n class=\"px-4 th\"\r\n [attr.field]=\"col.field\"\r\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\r\n cdkDrag\r\n >\r\n <div\r\n class=\"d-flex h-100 justify-content-between position-relative align-items-center\"\r\n >\r\n <div class=\"text-ellipsis\" (click)=\"sortNestedCol(col, row)\">\r\n {{ col.header }}\r\n </div>\r\n <div class=\"d-flex gap-2\">\r\n <span\r\n *ngIf=\"currentSubSortColumn == col.field\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n (col?.order_by == 'desc'\r\n ? 'data-grid/icons/sort-desc.svg'\r\n : 'data-grid/icons/sort-asc.svg')\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center ms-2 start-50\"\r\n >\r\n </span>\r\n <!-- <div\r\n class=\"three-dots p-1\"\r\n (click)=\"openThreeDotsMenu($event, col)\"\r\n style=\"cursor: pointer\"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/icons/three-dots-vertical.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div> -->\r\n\r\n <!-- Only show menu if this column is active -->\r\n <div\r\n class=\"position-absolute\"\r\n *ngIf=\"activeCol === col\"\r\n style=\"top: -50%; z-index: 21; left: 0\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n columnMenu;\r\n context: {\r\n col: col,\r\n isNestedTable: true,\r\n columns: row?.detail.columns\r\n }\r\n \"\r\n ></ng-container>\r\n </div>\r\n <div\r\n class=\"resize-handle\"\r\n (click)=\"$event.stopPropagation()\"\r\n (mousedown)=\"\r\n $event.preventDefault();\r\n onResizeColumn($event, col);\r\n $event.stopPropagation()\r\n \"\r\n >\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/resize-handle.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div>\r\n <ng-template cdkDragPreview>\r\n <div class=\"p-2 border d-flex gap-2\">\r\n <div>\r\n <span\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\r\n \"\r\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\r\n ></span>\r\n </div>\r\n <div>{{ col.header }}</div>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </thead>\r\n <div\r\n [style.width.px]=\"nestedHeader.offsetWidth - 10\"\r\n [style.minWidth.px]=\"nestedHeader.offsetWidth - 10\"\r\n >\r\n <cdk-virtual-scroll-viewport\r\n [itemSize]=\"nestedTablerowHeight\"\r\n class=\"viewport\"\r\n [style.height.px]=\"\r\n (row?.detail?.result?.length < 5\r\n ? nestedTablerowHeight * row?.detail?.result?.length + 40\r\n : 300) + (hasHorizontalScroll ? -12 : 1)\r\n \"\r\n [style.width.px]=\"nestedHeader.offsetWidth - 10\"\r\n [style.minWidth.px]=\"nestedHeader.offsetWidth - 10\"\r\n >\r\n <div\r\n class=\"cursor-pointer border-below d-flex tr\"\r\n *cdkVirtualFor=\"let d of row?.detail?.result; trackBy: trackById\"\r\n [style.height.px]=\"nestedTablerowHeight\"\r\n [style.width.px]=\"nestedHeader?.offsetWidth\"\r\n [style.minWidth.px]=\"nestedHeader?.offsetWidth\"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n (contextmenu)=\"onRightClick($event, d)\"\r\n >\r\n <div\r\n class=\"px-4 py-0 td\"\r\n *ngFor=\"let col of previewNestedCols; let j = index\"\r\n [style.fontSize.px]=\"nestedTablerowFontsize\"\r\n [attr.field]=\"col.field\"\r\n [style.width.px]=\"col?.width || 250\"\r\n [style.minWidth.px]=\"col?.width || 250\"\r\n [style.maxWidth.px]=\"col?.width || 250\"\r\n >\r\n <div\r\n [style.height.px]=\"nestedTablerowHeight - 1\"\r\n [style.max-width.px]=\"col?.width\"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <!-- {{ d[col.field] || (col.is_amount ? 0 : \"-\") }} -->\r\n <div\r\n #cellText\r\n class=\"text-ellipsis flex-grow-1\"\r\n [title]=\"\r\n col?.type === 'date'\r\n ? (getNestedValue(d, col.field) | date : dateFormat)\r\n : getNestedValue(d, col.field) || '-'\r\n \"\r\n >\r\n <ng-container *ngIf=\"col?.type !== 'image'\">\r\n <ng-container *ngIf=\"col.is_amount\">{{\r\n currencySymbol\r\n }}</ng-container>\r\n {{\r\n !isNestedValueArray(d, col.field)\r\n ? col?.type === 'date'\r\n ? (isDate(getNestedValue(d, col.field))\r\n ? (getNestedValue(d, col.field) | date: dateFormat)\r\n : (getNestedValue(d, col.field)?.value ||\r\n getNestedValue(d, col.field)?.name ||\r\n getNestedValue(d, col.field) ||\r\n '-'))\r\n : (getNestedValue(d, col.field)?.value ||\r\n getNestedValue(d, col.field)?.name ||\r\n getNestedValue(d, col.field) ||\r\n (col.is_amount ? 0: '-'))\r\n : (getNestedValue(d, col.field)?.[0]?.department_name ||\r\n getNestedValue(d, col.field)?.[0]?.roleName || getNestedValue(d, col.field)?.[0]?.full_name ||\r\n '-')\r\n }}\r\n </ng-container>\r\n <ng-container *ngIf=\"false\">\r\n {{ getTotalAmount(col) }}\r\n </ng-container>\r\n <ng-container *ngIf=\"col?.type == 'image'\">\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n defaultImagePlaceholder;\r\n context: {\r\n row: d,\r\n col: col,\r\n }\r\n \"\r\n ></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </cdk-virtual-scroll-viewport>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #leftRightNestedPlaceholder let-row>\r\n <table\r\n class=\"nested-table table table-sm w-100 mb-0\"\r\n [style.backgroundColor]=\"bodyBackgroundColor\"\r\n [style.height.px]=\"\r\n gridType == 'Assets'\r\n ? (nestedTableContainer?.nativeElement?.offsetHeight ?? 0) + 12\r\n : (taskManagementContainer?.nativeElement?.offsetHeight ?? 0)\r\n \"\r\n >\r\n <!-- <div class=\"thead\">\r\n <div\r\n class=\"tr d-flex border-below\"\r\n [style.height.px]=\"nestedTableHeaderRowHeight\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n >\r\n <div class=\"th\" *ngFor=\"let _ of [1, 2, 3, 4, 5]\"></div>\r\n </div>\r\n </div> -->\r\n <!-- <div class=\"tbody\">\r\n <div\r\n class=\"tr border-below\"\r\n [style.height.px]=\"nestedTablerowHeight\"\r\n *ngFor=\"let _ of row?.detail?.result\"\r\n [style.backgroundColor]=\"headerBackgroundColor\"\r\n >\r\n <div class=\"td\" *ngFor=\"let __ of [1, 2, 3, 4, 5]\" class=\"py-0\">\r\n <span\r\n [style.height.px]=\"nestedTablerowHeight\"\r\n [style.max-width.px]=\"nestedTablerowHeight\"\r\n ></span>\r\n </div>\r\n </div>\r\n </div> -->\r\n </table>\r\n</ng-template>\r\n\r\n<ng-template #taskManagementTemplate let-taskDetails=\"taskDetails\">\r\n <div\r\n class=\"p-4\"\r\n #taskManagementContainer\r\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\r\n [style.fontFaimly]=\"fontFaimly\"\r\n >\r\n <div class=\"d-flex justify-content-between\">\r\n <div class=\"col-4\">\r\n <div class=\"item-title\">Description</div>\r\n <!-- <div class=\"item-content firstDiv\">\r\n {{ taskDetails.description }}\r\n </div> -->\r\n <p\r\n [style.fontSize]=\"bodyTextFontsSize\"\r\n class=\"item-content firstDiv taskDescription pe-4\"\r\n [innerHTML]=\"getSafeComment(taskDetails?.editor_description)\"\r\n (click)=\"openFullImage($event)\"\r\n ></p>\r\n </div>\r\n <div class=\"col-4\">\r\n <div class=\"item-title\">Attachments</div>\r\n <h5 *ngIf=\"taskDetails?.attachments?.length == 0\">\r\n No Attachments found\r\n </h5>\r\n <div\r\n *ngIf=\"taskDetails?.attachments?.length\"\r\n class=\"item-content d-flex flex-wrap\"\r\n style=\"gap: 10px\"\r\n >\r\n <a\r\n *ngFor=\"let attachement of taskDetails?.attachments; let i = index\"\r\n class=\"symbol-label fs-2 fw-semibold text-success cursor-pointer\"\r\n >\r\n <span\r\n title=\"{{ taskDetails?.attachments_name[i] || 'Attachment' }}\"\r\n (click)=\"downloadAttchment(attachement)\"\r\n [inlineSVG]=\"\r\n singleSpaAssetsPath +\r\n 'data-grid/document-icons/' +\r\n getExtention(attachement) +\r\n '.svg'\r\n \"\r\n >\r\n </span>\r\n </a>\r\n </div>\r\n </div>\r\n <div class=\"col-4\">\r\n <div class=\"item-title\">\r\n Comments ({{ taskDetails?.comments?.length }})\r\n </div>\r\n <h5 *ngIf=\"taskDetails?.comments?.length == 0\">No Comments found</h5>\r\n <div *ngIf=\"taskDetails?.comments?.length\" class=\"item-content\">\r\n <div class=\"comment\" *ngFor=\"let comment of taskDetails.comments\">\r\n <div class=\"d-flex align-items-center pe-3\">\r\n <img\r\n class=\"pic image-input-wrapper\"\r\n [style.width.px]=\"rowHeight - 12\"\r\n [style.height.px]=\"rowHeight - 12\"\r\n *ngIf=\"comment?.comment_by.logo\"\r\n src=\"{{ comment?.comment_by.logo }}\"\r\n alt=\"{{ comment.comment_by.full_name }}\"\r\n />\r\n <!-- <app-default-image-placeholder *ngIf=\"!comment?.comment_by.logo\" title=\"{{ comment.comment_by.full_name }}\" [name]=\"comment.comment_by.full_name\"></app-default-image-placeholder> -->\r\n <span\r\n *ngIf=\"!comment?.comment_by.logo\"\r\n [ngClass]=\"getDynamicClass(comment.comment_by.full_name)\"\r\n class=\"pic d-flex align-items-center rounded-circle\"\r\n [style.width.px]=\"rowHeight - 12\"\r\n [style.height.px]=\"rowHeight - 12\"\r\n [style.fontSize.px]=\"rowHeight / 3\"\r\n title=\"{{ comment.comment_by.full_name }}\"\r\n >\r\n {{ getInitials(comment.comment_by.full_name) }}\r\n </span>\r\n </div>\r\n <div>\r\n <div class=\"comment-author fs-14px\">\r\n {{ comment?.comment_by.full_name }}\r\n </div>\r\n <div\r\n class=\"comment-content forCommentImg\"\r\n [innerHTML]=\"getSafeComment(comment.comment)\"\r\n ></div>\r\n <div class=\"comment-timestamp\">\r\n {{ comment.comment_date | date }}\r\n </div>\r\n <div class=\"comment-timestamp\">\r\n Replies: ({{ comment.replies.length }})\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n", styles: ["@charset \"UTF-8\";@import\"bootstrap/dist/css/bootstrap.min.css\";.data-grid-table-wrapper{height:100%;width:100%;border:1px solid #d9d9db;border-radius:12px;position:relative}.data-grid-header{position:sticky;top:0}.data-grid-header{display:flex}.header-row{display:grid;width:100%}.header-cell{display:flex;align-items:center;position:relative;width:100%;padding:8px 0 8px 8px;font-weight:700;border-bottom:1px solid #d9d9db;white-space:nowrap;min-width:80px;font-weight:600}.header-cell .filter-applied-on-text{color:#5d9cff!important}.filter-cell{padding:4px!important;display:flex;align-items:center;gap:8px;width:100%}.filter-cell .filter-applied{background-color:#bddef9}.border-right{border-right:1px solid #d9d9db}.merged-grid{display:grid;grid-auto-rows:40px;border-bottom:1px solid #ccc}.span-two-rows{grid-row:span 2;display:flex;justify-content:space-between;align-items:center}.group-header{display:flex;justify-content:space-between;position:relative}.group-header-content{position:sticky;left:10px;overflow:hidden;text-overflow:ellipsis}.resize-handle{width:6px;cursor:e-resize;right:0;top:0;color:#00000026;margin-right:4px}.group-header .resize-handle{top:25%}.h-100{height:100%}.data-grid-body{position:relative;overflow-y:auto;overflow-x:hidden}.cell{padding:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:100%;display:flex;align-items:center}.data-grid-row{display:flex;width:100%;min-width:max-content;align-items:center;border-bottom:1px solid #d9d9db}.hovered-row{background-color:#ccc}.checkbox-row{border-bottom:#d9d9db}.w-100{width:100%}.data-grid-header-wrapper{display:flex;position:relative;overflow:hidden;-webkit-user-select:none;user-select:none}.data-grid-header{display:flex;position:relative;z-index:1}.left-pinned,.right-pinned{position:sticky;top:0}.right-pinned-header{position:absolute;right:0;border-left:1px solid #d9d9db;z-index:unset}.left-pinned{left:0}.right-pinned{right:0;border-left:1px solid #d9d9db}.center-scrollable{z-index:unset!important;overflow-x:auto;overflow-y:visible;white-space:nowrap;scrollbar-width:none;-ms-overflow-style:none}.center-scrollable::-webkit-scrollbar{display:none}.data-grid-body-wrapper{-webkit-user-select:none;user-select:none;display:flex}.center-scrollable-body{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}.center-scrollable-body::-webkit-scrollbar{display:none}.left-pinned-body,.right-pinned-body{position:sticky;top:0;z-index:unset;background:#fff;scrollbar-width:none;-ms-overflow-style:none}.left-pinned-body::-webkit-scrollbar,.right-pinned-body::-webkit-scrollbar{display:none}.left-pinned-body{left:0}.border-end{border-right:1px solid #d9d9db!important}.right-pinned-body{right:0;border-left:1px solid #d9d9db}.fake-scroll-bar{height:14px;overflow:scroll;margin-bottom:10px}.text-ellipsis{overflow:hidden;text-overflow:ellipsis}.select-all-checkbox-cell{width:50px;display:flex;justify-content:center;align-items:center;height:100%;border-right:1px solid #d9d9db}.select-all-checkbox-cell input{width:16px;height:14px}.border-below{border-bottom:1px solid #d9d9db!important}.three-dots{width:22px;height:22px;display:flex;justify-content:center;align-items:center;border-radius:3px;margin-right:8px;cursor:pointer}.three-dots:hover{background-color:#ccc!important}.filter-icon-wrapper{min-height:22px;max-height:22px;min-width:22px;max-width:22px;display:flex;justify-content:center;align-items:center;border-radius:3px;cursor:pointer;transition:background-color .3s ease}.filter-icon-wrapper:hover{background-color:#ccc}.column-menu,.filter-menu{box-shadow:0 0 16px #00000026;border-radius:4px}.column-menu{background:#fff;width:100%;width:240px;border:1px solid #ddd;box-shadow:0 0 16px #00000026;border:1px solid #d9d9db;padding:4px 0;font-size:14px;position:fixed}.column-menu-item{padding:8px 12px;cursor:pointer;display:flex;align-items:center;transition:background-color .2s ease}.column-menu-item:hover{background-color:#deebf7}.pin-parent{position:relative;width:100%!important}.column-submenu{position:absolute;top:0;left:100%;background:#fff;border:1px solid #ddd;width:130px;box-shadow:0 0 16px #00000026;border:1px solid #d9d9db;display:none;padding:4px 0;z-index:10;border-radius:4px}.pin-parent:hover .column-submenu{display:block}.filter-menu-container{position:fixed;width:210px;background:#fff;border:1px solid #ddd;border-radius:4px;padding:12px;box-shadow:0 0 16px #00000026;border:1px solid #d9d9db;z-index:1000;font-size:14px}.filter-menu-header{font-weight:600;margin-bottom:10px}.filter-dropdown-section{max-height:350px;overflow-y:auto}.dropdown-options{overflow-y:auto;scrollbar-width:thin;height:100%}.filter-text-section select,.filter-text-section input{width:100%}.filter-radio-inputs{width:14px!important;height:14px!important}.right-menu{border-left:1px solid #d9d9db;font-size:14px}.border-start{border-left:1px solid #d9d9db!important}.column-panel-item{font-size:.875rem;color:#333}.toggle-icon{cursor:pointer;transition:transform .2s ease}.toggle-icon.rotate{transform:rotate(90deg)}.grab-icon{cursor:grab;color:#6c757d}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cursor-pointer{cursor:pointer}.pivot-mode{height:48px}.chevron-wrapper{width:30px;height:20px;cursor:pointer;border-radius:3px;display:flex;justify-content:center;align-items:center;transition:background-color .3s ease;margin-right:8px}.chevron-wrapper:hover{background-color:#cac7c7}.chevron-wrapper i{font-size:14px}.column-panel-body{height:70%;overflow:auto;scrollbar-width:thin}.side-menue-text{transform:rotate(90deg);position:relative;font-weight:700;margin-top:40px}.columns-button{padding-top:20px;padding-bottom:35px;width:29px}.fake-scroll-content{height:12px}.fake-scrollbar{width:25px}.fake-scrollbar div{min-width:1px}.fake-horizintal-scrollbar div{min-height:1px}.side-filter-columns-wrapper{height:calc(100% - 25px)}.custom-modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;overflow:hidden;display:flex;justify-content:center;align-items:center;z-index:1050}.custom-modal-overlay .moda-header{background-color:#f8f8f8}.custom-modal-content{background-color:#fff;border-radius:8px;min-width:300px;max-width:400px;box-shadow:0 5px 20px #0000004d}.overlay-scrollable{height:250px;overflow:auto}.footer-row{border-top:1px solid #d9d9db;padding-left:32px}.fake-horizintal-scrollbar{position:relative;bottom:17px;overflow-x:auto;overflow-y:hidden;height:17px}.border-dashed{border:1px dashed #d9d9db}.cdk-drag-preview{box-sizing:border-box!important;border-radius:4px!important;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f!important;background-color:#f3f4f5!important;border:1px solid #d9d9db!important;z-index:9999!important}.data-grid-header-wrapper ::ng-deep .cdk-drag-placeholder{display:block!important;background:#fff!important;opacity:1!important}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)!important}.top-row-grouping-placeholder{display:flex;align-items:center;border-radius:12px;font-size:14px;padding-inline:6px;border:1px solid #d9d9db}.top-row-grouping-placeholder .bi-x{cursor:pointer;color:#7a7a7a}.top-row-grouping-placeholder .bi-x:hover{color:#111}.right-pinned-body-wrapper{position:absolute;right:0}.actions-dropdown{position:absolute;right:200px;z-index:1050;background-color:#fff;border-radius:8px!important;cursor:default}.bg-fff{background-color:#fff}.actions-dropdown-setting{right:250px}.action-button{background-color:#007cf5!important;border-radius:8px!important;padding:8px 16px!important;font-size:14px;height:32px;align-items:center}.global-search{max-width:380px!important;display:flex!important;align-items:center!important}.global-search span{margin-top:-4px!important}.global-search input{padding-left:28px;border-radius:8px!important}.global-search input:focus{outline:none!important;box-shadow:none!important}.active .top-icon ::ng-deep svg path{stroke:#007cf5!important}.dropdown-menu{background-color:#fff!important;border:1px solid #d9d9db!important;border-radius:8px!important}.custom-menu{width:220px;border-radius:8px;padding:4px 0;background-color:#fff}.custom-menu .dropdown-item{font-size:14px;padding:8px 14px}.custom-menu .dropdown-item:hover{background-color:#f5f5f5;border-radius:6px}.table-layout{right:0;background:#fff;border-radius:8px!important}.actions-dropdown,.table-layout,.custom-menu,.dropdown-menu{background:#fff;border-radius:8px!important;border:1px solid #ccc!important;background-color:#fff}.preview-box{width:40px;height:10px;border-radius:3px;background-color:transparent;transition:background-color .2s ease-in-out}.btn-check:checked+label .preview-box{background-color:var(--bs-primary)}.preview-box{width:40px;height:10px;border-radius:3px;border:2px solid transparent;transition:border-color .2s ease-in-out}#small:checked+label .preview-box{border-color:#007cf5!important;background-color:transparent!important}#medium:checked+label .preview-box{border-color:#007cf5!important;background-color:transparent!important}#large:checked+label .preview-box{border-color:#007cf5!important;background-color:transparent!important}.btn-check:checked+.btn{background-color:transparent!important;border-color:#007cf5!important}.layout-button{padding:8px 28px!important;width:82px;border-radius:8px!important}.show-hide-table-label{position:sticky;top:0;z-index:99;background:#fff}.cursor-grap{cursor:grabbing}.pagination-container{display:flex;align-items:center;gap:12px;font-size:13px;color:#333}.page-size select{padding:3px 6px;border:1px solid #ccc;border-radius:6px;background:#fff;font-size:13px}.page-info{margin-left:10px}.page-buttons{display:flex;gap:4px;margin-left:auto;align-items:center}.page-buttons button{padding:3px 8px;border:1px solid #ccc;background:#fff;border-radius:4px;cursor:pointer;font-size:13px;line-height:1.2}.page-buttons button.active{background:#eee;font-weight:600}.page-buttons button:disabled{opacity:.5;cursor:not-allowed}.page-buttons span{padding:0 6px;color:#666}.page-size .separator{padding:0 8px;border-right:1px solid #ccc;margin-right:8px}.page-size .separator .actions-dropdown{position:fixed;right:200px;z-index:1050;background-color:#fff}.fs-14px{font-size:14px}.fs-12px{font-size:12px!important}.save-preset-dropdown{background:#fff;color:#111!important;right:0;font-weight:400!important;text-align:left!important;max-width:250px!important;text-wrap:auto!important;top:14px;font-size:14px!important}.add-filter-button{height:28px;cursor:pointer;border-radius:4px}.add-filter-button:hover,.button-filter:hover{color:#000!important}.button-filter:hover ::ng-deep svg path{stroke:#000!important}.table-layout .dropdown-item{border-radius:0!important;padding-inline:16px!important;font-size:14px;padding-block:6px!important}.table-layout .dropdown-item:hover{background-color:transparent!important}.filter-serach-inpt{max-height:230px!important;overflow:auto;scrollbar-width:thin;padding-top:4px;background-color:#f7f7f7;border-color:#dedede;border-radius:8px}.filter-serach-inpt .badge{color:#007cf5!important;background-color:#e6f2ff!important;border-radius:8px!important;padding:8px!important;font-weight:500!important;font-size:12px!important;height:24px!important}.filter-serach-inpt .badge ::ng-deep svg{cursor:pointer}.filter-serach-inpt .badge ::ng-deep svg:hover path{stroke:#040081!important}.filter-serach-inpt input{background-color:#f7f7f7;padding:0;height:26px;margin-top:-5px}.text-filter select{border:0}.text-filter select option{font-size:14px;font-weight:500}.text-filter select:focus{border:0}.text-filter input:focus,.text-filter select:focus{box-shadow:none!important}.active-filters{background-color:#f7f7f7;white-space:nowrap;background:#f7f7f7;padding-inline:8px;height:28px;font-size:14px;font-weight:500;border-radius:8px;box-shadow:none}.active-filters .header-tag{white-space:nowrap}.filter-tags .active{background-color:#e6f2ff}.filter-tags .active .header-tag{color:#007cf5!important}.table-cell{cursor:pointer;width:100%}.table-cell input:focus{outline:0!important;border:0!important;width:100%!important;box-shadow:none!important}.active-for-editing{outline:2.5px solid #007cf5!important;border-radius:4px;border:0!important;width:100%!important}.active-cell{outline:none!important;box-shadow:inset 0 0 0 1.5px #007cf5}span[inlineSVG]{width:16px;height:16px;display:inline-block}.cell .dropdown-menu{min-width:unset!important}.cell .dropdown-menu .item{transition:background-color .3s ease;display:flex;align-items:center;-webkit-user-select:none;user-select:none}.cell .dropdown-menu .item:hover{background-color:#f0f8ff}.cell .cell-editin-dropdown{scrollbar-width:thin!important;-webkit-user-select:none;user-select:none}.fw-semibold{font-weight:500!important}:host ::ng-deep .three-dots-col-menu svg,:host ::ng-deep .three-dots-col-menu svg path{stroke:#000!important}.fs-7{font-size:12px!important}.fs-8{font-size:10px!important}.all-filters-reset-button:hover{opacity:.7}.full-text-box{background:#fff;position:relative;display:flex;align-items:center;z-index:1050;border:1px solid #dedede;border-radius:8px;padding:12px 14px;box-shadow:0 2px 8px #00000026;max-height:400px;overflow:auto}.full-text-box ul{max-height:400px}.full-text-content{border-radius:8px;max-height:70vh;overflow:auto;white-space:pre-wrap}.pic{border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:22px}.pic-comb2{background-color:#fbe7bf;color:#fd7f31}.pic-comb1{background-color:#d9ecbf;color:#65b500}.pic-comb4{background-color:#fdd3d7;color:#f64e60}.w-40px{width:40px}.h-40px{height:40px}.pic{border-radius:50%;overflow:hidden}.image-placeholder .pic{font-size:14px;font-weight:600;letter-spacing:.5px}.header-cell{font-weight:600}.header-cell,.cell{box-sizing:border-box}.transparent-border-right{border-right:1px solid transparent!important}.resizing-highlight{position:relative}.resizing-highlight:before{content:\"\";position:absolute;top:-1px;right:-1px;width:2px;height:calc(100% + 2px);background:#7cb9f6;z-index:1000;pointer-events:none}.resizing-highlight-right{position:relative}.resizing-highlight-right:before{content:\"\";position:absolute;top:-1px;left:-1px;width:2px;height:calc(100% + 2px);background:#7cb9f6;z-index:1000;pointer-events:none}.resizing-highlight-right:first-child{width:1px}.editable-header{border-bottom:1px dashed #666}.muted-text{color:#727272!important}.context-menu{position:fixed;display:none;background:#fff;border:1px solid #dcdcdc;box-shadow:#0000003d 0 3px 8px;z-index:1000;width:150px;border-radius:8px;font-weight:600}.context-menu.show{display:block}.context-menu ul{list-style:none;margin:0;padding:0}.context-menu li{padding:10px;cursor:pointer;color:#99a1b7}.context-menu li ::ng-deep svg{width:16px;height:16px;display:inline-block;color:#727272}.context-menu li ::ng-deep svg path{stroke:#727272}.context-menu li:hover{background-color:#f0f0f5!important}.invisible{visibility:hidden!important}.fw-500{font-weight:500!important}.taskbar{position:fixed;display:flex;justify-content:center;z-index:1000}.taskbar .action-btn{transition:opacity text-decoration .3s ease}.taskbar .action-btn:hover{text-decoration:underline;opacity:.8}.taskbar .delete{color:#ea0000}.selected-count,.action-btn,.dropdown-content a{font-weight:500;font-size:14px}.selected-rows-action-bar{background-color:#1a1a1a;color:#fff;padding:4px 24px;border-radius:8px;display:flex;align-items:center;justify-content:space-between;gap:24px;box-shadow:0 -4px 12px #00000026}.selected-rows-action-bar .btn:active,.selected-rows-action-bar .btn:focus{outline:0!important;border:0!important;border-color:transparent!important}.selected-rows-action-bar .action-btn{color:#fff!important}.cell .dropdown-menu,.cell .form-select,.cell input{color:#000!important}.cell input::placeholder{color:#727272!important}.cell .badge{border-radius:50px!important;height:26px;align-items:center}.cell .badge-danger{color:#ea5353!important;border:1px solid #ea5353!important;background-color:#ff00000d!important}.cell .badge-success{background-color:#84ca8130!important;border:1.5px solid rgb(70,227,114)!important;color:#46e372!important}.cell .badge-warning{background-color:#fff3dc!important;color:orange!important;border:1px solid #ffa000!important}.cell .badge-info{color:#00bad1;background-color:#e8fbfd;border:1px solid #00bad1}.cell .badge-secondary{color:#6c757d;background-color:#f1f3f5;border:1px solid #6c757d}.header-tag ::ng-deep svg path{stroke:#727272!important}.cross-secondary:hover ::ng-deep svg path{stroke:#000!important}.disable-sorting{pointer-events:none;opacity:.5}.rows-grouping-top-container ::ng-deep .cdk-drag-placeholder{background-color:transparent!important}input.is-invalid:focus{border:2.5px solid red!important;outline:none}.table-cell input.is-invalid:focus{border:2.5px solid red!important;outline-color:red!important;outline:none!important;box-shadow:none!important}.active-for-editing:has(input.is-invalid:focus){outline:none!important;box-shadow:none!important;border:0!important}.selected-cell,.row-selected{background-color:#c2e0fe}.first-row-selected{border-top:2px solid #2196f3!important}.last-row-selected{border-bottom:2px solid #2196f3!important}.left-selection-border{border-left:2px solid #2196f3!important}.s-no{font-size:14px;font-weight:500}.top-border{border-top:2px solid #2196f3!important}.bottom-border{border-bottom:2px solid #2196f3!important}.left-border{border-left:2px solid #2196f3!important}.border-left{border-left:1px solid #d9d9db}.right-border{border-right:2px solid #2196f3!important}.top-left-corner{border-top-left-radius:4px}.top-right-corner{border-top-right-radius:4px}.bottom-left-corner{border-bottom-left-radius:4px}.bottom-right-corner{border-bottom-right-radius:4px}.flash-bg{animation:flashAnim 1000s ease}@keyframes flashAnim{0%{background-color:#48a2fc}50%{background-color:#c2e0fe}to{background-color:#c2e0fe}}.cut-flash-bg{animation:cut-flash .8s ease}@keyframes cut-flash{0%{background-color:#f006}50%{background-color:#f00c}to{background-color:#c2e0fe}}.accordion-details .center-section .table .tbody .tr:hover .td{background-color:#f0f8ff!important}.editing-dropdown-search-input input:focus{border:1px solid #86b7fe!important}.nested-table .thead{position:sticky;top:0}.dropdown-wrapper{position:relative;display:inline-block}.btn-icon{background:transparent;border:0;padding:.25rem .5rem;cursor:pointer}.custom-dropdown-menu{position:absolute;right:0;top:calc(100% + 6px);min-width:200px;list-style:none;margin:0;padding:.25rem 0;background:#fff!important;border:1px solid rgba(0,0,0,.08);box-shadow:0 6px 18px #00000014;border-radius:.35rem;z-index:1200}.custom-dropdown-menu .dropdown-item{display:block;width:100%;padding:.5rem 1rem;text-align:left;background:transparent;border:none}.custom-dropdown-menu .dropdown-item:hover{background:#00000008}.cell-editing-dropdown-menu .dropdown-item{width:99%}.cell-editing-dropdown-menu .selected{background-color:#f0f8ff}.confirm-block{padding:0}.center-nested-table .tr:hover .td{background-color:#f0f8ff}.table ::ng-deep .cdk-drag-placeholder{background-color:#fff!important}.assets-pic{border-radius:8px!important}.fullscreen-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000c;display:flex;align-items:center;justify-content:center;z-index:1000;cursor:zoom-out}.fullscreen-img{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 0 15px #00000080}.position-sticky{z-index:2}.viewport{display:block!important;overflow:visible!important}.nested-table ::ng-deep .cdk-virtual-scroll-content-wrapper{padding:0!important}.nested-table ::ng-deep .cdk-virtual-scroll-viewport{overflow-x:hidden!important}.disabled-search-input{background-color:#f5f5f5;cursor:pointer!important}.right-click-menu-icons ::ng-deep svg path{stroke-width:2!important}.loader{animation:rotate 1s infinite;height:50px;width:50px}.loader:before,.loader:after{border-radius:50%;content:\"\";display:block;height:20px;width:20px}.loader:before{animation:ball1 1s infinite;background-color:#fff;box-shadow:30px 0 #ff3d00;margin-bottom:10px}.loader:after{animation:ball2 1s infinite;background-color:#ff3d00;box-shadow:30px 0 #fff}@keyframes rotate{0%{transform:rotate(0) scale(.8)}50%{transform:rotate(360deg) scale(1.2)}to{transform:rotate(720deg) scale(.8)}}@keyframes ball1{0%{box-shadow:30px 0 #ff3d00}50%{box-shadow:0 0 #ff3d00;margin-bottom:0;transform:translate(15px,15px)}to{box-shadow:30px 0 #ff3d00;margin-bottom:10px}}@keyframes ball2{0%{box-shadow:30px 0 #fff}50%{box-shadow:0 0 #fff;margin-top:-20px;transform:translate(15px,15px)}to{box-shadow:30px 0 #fff;margin-top:0}}.rows-grouping-top-container ::ng-deep .cdk-drag-placeholder{opacity:.7!important}.action-button{background-color:#6f61cf!important;color:#fff!important;border-radius:6px!important;font-weight:500!important;margin-top:-4px}.action-button:hover{background-color:#6a5fb3!important}.action-buttons-row .button{display:inline-flex;align-items:center;justify-content:center;overflow:hidden;color:#fff;border-radius:6px;height:34px;padding:0 10px;white-space:nowrap;transition:max-width .4s ease,background-color .3s ease;max-width:40px;background-color:transparent;border:1px solid #6F61CF}.action-buttons-row .button .label-hidden{opacity:0;margin-left:8px;transition:opacity .3s ease;pointer-events:none;display:none}.action-buttons-row .button:hover{max-width:200px;background-color:#6f61cf}.action-buttons-row .button:hover .label-hidden{opacity:1;pointer-events:auto;margin-left:8px!important;display:block}.action-buttons-row ::ng-deep .button .svg-icon svg path{stroke:#6f61cf;transition:fill .3s ease,stroke .3s ease}.action-buttons-row ::ng-deep .button:hover .svg-icon svg path{stroke:#fff!important}::ng-deep .nav-tabs .nav-link{border:none!important;border-bottom:2px solid transparent!important;border-radius:0!important;background:transparent!important}::ng-deep .nav-tabs .nav-link:hover,::ng-deep .nav-tabs .nav-link:focus{border:none!important;border-bottom:2px solid transparent!important;outline:none!important;background:transparent!important}::ng-deep .nav-tabs .nav-link.active{border:none!important;border-bottom:2px solid var(--bs-primary)!important;background:transparent!important;color:var(--bs-primary)!important}.open-top{top:-150%!important}.muted{color:#7a7a7a!important}.item-title{font-size:1.2em;font-weight:700;margin-bottom:10px}.item-image{width:100%;border-radius:10px}.comment{display:flex;align-items:center;margin-bottom:10px}.comment-avatar{width:40px;height:40px;border-radius:50%;margin-right:10px}.comment-author{font-weight:700}.comment-content{font-size:.9em;line-height:1.4}.comment-timestamp{font-size:.8em;color:#888;margin-left:auto}.des_low{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;width:242px;display:block;text-transform:capitalize!important}.firstDiv{word-break:break-word;overflow-wrap:break-word;white-space:normal}.container{display:flex;flex-wrap:wrap;margin:20px;gap:20px;background-color:#fff;padding:20px;border-radius:10px}.item{width:calc(33.33% - 20px);background-color:#fff;padding:20px;border-radius:10px;box-shadow:0 2px 5px #0000001a}.forCommentImg{width:70px;border-radius:16px;margin:8px 0;cursor:pointer}.image-modal img{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 4px 10px #00000080}.full-image-modal{position:fixed;background:#000c;display:flex;justify-content:center;align-items:center;z-index:1000}.full-image-modal .full-image{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 0 10px #fff3}.item-content{font-size:14px;line-height:1.5;max-height:220px;overflow-y:auto}.image-modal.full-image-modal{position:fixed;width:100vw;height:100vh;background-color:#000c;display:flex;justify-content:center;align-items:center;z-index:9999;overflow:hidden;cursor:zoom-out}.image-modal.full-image-modal img{border-radius:8px;box-shadow:0 4px 20px #0006;object-fit:contain;transition:transform .3s ease}.image-modal.full-image-modal img:hover{transform:scale(1.02)}::ng-deep .custom-overlay-wrapper .custom-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000000d9;display:flex;align-items:center;justify-content:center;z-index:9999}::ng-deep .custom-overlay-wrapper .custom-modal{background:#fff;border-radius:12px;box-shadow:0 8px 25px #0003;width:360px;max-width:90%;padding:24px;text-align:center;animation:fadeInScale .25s ease}::ng-deep .custom-overlay-wrapper .custom-modal-body .modal-message{font-size:16px;margin-bottom:20px;color:#333}::ng-deep .custom-overlay-wrapper .modal-actions{display:flex;justify-content:center;gap:12px}::ng-deep .custom-overlay-wrapper .modal-actions button{min-width:90px;padding:8px 14px;border-radius:6px;border:none;font-weight:500;cursor:pointer;transition:background-color .2s ease}::ng-deep .custom-overlay-wrapper .btn-confirm{background-color:#007bff;color:#fff}::ng-deep .custom-overlay-wrapper .btn-confirm:hover{background-color:#0069d9}::ng-deep .custom-overlay-wrapper .btn-cancel{background-color:#e4e4e4;color:#333}::ng-deep .custom-overlay-wrapper .btn-cancel:hover{background-color:#d6d6d6}@keyframes fadeInScale{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.clear-btn{background:linear-gradient(135deg,#f53545,#f53545);border:none;color:#fff;font-size:13px;padding:3px 6px;border-radius:20px;font-weight:500;display:inline-flex;align-items:center;gap:6px;cursor:pointer;transition:all .3s ease;box-shadow:0 2px 6px #ff5f6d66;position:relative;bottom:4px}.clear-btn:hover{transform:translateY(-2px);box-shadow:0 4px 10px #ff5f6d99;background:linear-gradient(135deg,#f53545,#f53545)}.clear-btn i{font-size:16px;vertical-align:middle}.cell-editin-dropdown .deopdown-item{width:100%!important;box-shadow:none!important;border-radius:4px;cursor:pointer;padding-block:8px!important}.cell-editin-dropdown .deopdown-item:hover{background-color:#f1f1f1}\n"] }]
|
|
6318
|
+
], template: "<div class=\"position-relative h-100 card-outer\">\n <div class=\"d-flex justify-content-between mb-3 align-items-center position-relative\">\n <div class=\"d-flex gap-2\">\n <div class=\"nav nav-tabs\" *ngIf=\"true\">\n <div class=\"nav nav-tabs\" id=\"nav-tab\" role=\"tablist\">\n <span\n *ngFor=\"let tab of tabs; let i = index\"\n (click)=\"setActiveTab(tab)\"\n class=\"nav-link cursor-pointer\"\n [class.active]=\"activeTab == tab\"\n >\n {{ tab }}\n </span>\n </div>\n </div>\n <div class=\"new_design_dropdown hide_arrow\">\n <a href=\"JavaScript:void(0)\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" data-bs-auto-close=\"outside\"\n class=\"d-flex align-items-center dropdown-toggle justify-content-center dropdown_main_button\">\n All\n </a>\n </div>\n <div>\n <div class=\"btn-group new_design_dropdown hide_arrow\">\n <a href=\"JavaScript:void(0)\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" data-bs-auto-close=\"outside\"\n class=\"d-flex align-items-center dropdown-toggle justify-content-center dropdown_main_button\">\n Unfulfilled\n </a>\n <ul class=\"dropdown-menu\">\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/resetIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span> Reset</span>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/updatePresetIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span> Update and Re-save</span>\n </a>\n </li>\n <hr class=\"mt-1\">\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/infoIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span> Rename</span>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/duplicateIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span>Duplicate</span>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/trashIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span>Delete</span>\n </a>\n </li>\n </ul>\n </div>\n </div>\n <div>\n <div class=\"btn-group new_design_dropdown hide_arrow\">\n <a href=\"JavaScript:void(0)\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" data-bs-auto-close=\"outside\"\n class=\"d-flex align-items-center dropdown-toggle justify-content-center dropdown_main_button\">\n Unpaid\n </a>\n <ul class=\"dropdown-menu\">\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/infoIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </div>\n <span> Test Type</span>\n </a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n <div class=\"d-flex gap-1 align-items-center table-right-top-actions\">\n <div class=\"global-search position-relative\" [style.width.px]=\"350\">\n <span *ngIf=\"enableGlobalSearch\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\n class=\"data-grid-svg-icon ms-2 mt-0 position-absolute icon\" style=\"top: 8px;\"\n ></span>\n <input #globalSearchInput\n *ngIf=\"enableGlobalSearch\"\n class=\"form-control\"\n placeholder=\"Search\"\n [(ngModel)]=\"tableSearch\"\n (keydown.enter)=\"onGlobalSearch()\"\n (input)=\"onSearchInput($event)\"\n type=\"search\"\n />\n </div>\n <!-- <ng-container *ngFor=\"let button of buttons\">\n <div\n class=\"d-flex align-items-center gap-2 action-buttons-row\"\n *ngIf=\"button?.has_permission\"\n >\n <a\n href=\"JavaScript:void(0)\"\n (click)=\"onActionButtonClick(button.name)\"\n class=\"button button-small btn border border-primary btn-active-primary me-2 p-0 d-flex align-items-center justify-content-center px-3\"\n >\n <span\n *ngIf=\"button.is_showIcon\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/' + button.icon + '.svg'\n \"\n class=\"svg-icon svg-icon-2\"\n ></span>\n <span\n class=\"label-hidden text-white\"\n [class.ms-0]=\"button.is_showIcon\"\n >{{ button?.name }}</span\n >\n </a>\n </div>\n </ng-container> -->\n <div *ngIf=\"!showFilterRow\"\n class=\"cursor-pointer position-relative action-buttons-row\"\n (click)=\"toggleOpenFilter()\"\n [class.active]=\"showFilters\">\n <a href=\"JavaScript:void(0)\"\n class=\"p-0 d-flex align-items-center justify-content-center grid-header-icon\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filterIconNew.svg'\" class=\"svg-icon svg-icon-2\"></span>\n </a>\n <span *ngIf=\"activeFilteredColumns?.length\"\n style=\"\n width: 7px;\n height: 7px;\n box-shadow: 0px 0px 3px #0022ff;\n background-color: rgb(0, 60, 255);\n position: absolute;\n right: 8px;\n top: 6px;\n \"\n class=\"rounded-circle d-block\"\n ></span>\n </div>\n <div class=\"cursor-pointer d-none\"\n (click)=\"toggleActions('advance-filter')\"\n [class.active]=\"activeTopButton === 'advance-filter'\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/zoom-charge.svg'\"\n class=\"data-grid-svg-icon top-icon me-2\"\n ></span>\n </div>\n <div class=\"cursor-pointer actions-buttons-row\">\n <div class=\"btn-group new_design_dropdown hide_arrow\">\n <a href=\"JavaScript:void(0)\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" data-bs-auto-close=\"outside\"\n class=\"p-0 d-flex align-items-center dropdown-toggle justify-content-center grid-header-icon\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/sortingIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </a>\n <ul class=\"dropdown-menu dropdown-menu-left productSortingDropdownMenu\">\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div class=\"sorting_icon_input\">\n <input class=\"form-check-input\" type=\"radio\" name=\"exampleRadios\" id=\"productName\" value=\"option1\" checked>\n </div>\n <label class=\"form-check-label mb-0 mt-1\" for=\"productName\">\n Product Name\n </label>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div class=\"sorting_icon_input\">\n <input class=\"form-check-input\" type=\"radio\" name=\"exampleRadios\" id=\"createdDate\" value=\"option1\" checked>\n </div>\n <label class=\"form-check-label mb-0 mt-1\" for=\"createdDate\">\n Created Date\n </label>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div class=\"sorting_icon_input\">\n <input class=\"form-check-input\" type=\"radio\" name=\"exampleRadios\" id=\"updatedDate\" value=\"option1\" checked>\n </div>\n <label class=\"form-check-label mb-0 mt-1\" for=\"updatedDate\">\n Updated Date\n </label>\n </a>\n </li>\n <li>\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <div class=\"sorting_icon_input\">\n <input class=\"form-check-input\" type=\"radio\" name=\"exampleRadios\" id=\"productType\" value=\"option1\" checked>\n </div>\n <label class=\"form-check-label mb-0 mt-1\" for=\"productType\">\n Product Type\n </label>\n </a>\n </li>\n <hr class=\"my-2\">\n <li class=\"d-flex\" (click)=\"activeFilter('newest')\" [class.active-filter]=\"activeFilterType === 'newest'\">\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrowupIconNew.svg'\"\n class=\"svg-icon svg-icon-2 mb-1 new_old_filter\"\n ></span>\n <span class=\"mt-1 newest\">Newest First</span>\n </a>\n <div *ngIf=\"activeFilterType === 'newest'\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickIconNew.svg'\"\n class=\"svg-icon svg-icon-2 mb-1\"\n ></span>\n </div>\n </li>\n <li class=\"d-flex\" (click)=\"activeFilter('oldest')\" [class.active-filter]=\"activeFilterType === 'oldest'\">\n <a class=\"dropdown-item hover_dropdown_bg d-flex align-items-center\" href=\"javascript:void(0)\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrowdownIconNew.svg'\"\n class=\"svg-icon svg-icon-2 mb-1 new_old_filter\"\n ></span>\n <span class=\"mt-1 oldest\">Newest First</span>\n </a>\n <div *ngIf=\"activeFilterType === 'oldest'\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickIconNew.svg'\"\n class=\"svg-icon svg-icon-2 mb-1\"\n ></span>\n </div>\n </li>\n </ul>\n </div>\n </div>\n <div class=\"cursor-pointer action-buttons-row\"\n (click)=\"toggleActions('setting')\"\n [class.active]=\"\n activeTopButton === 'setting' ||\n activeTopButton === 'table-layout' ||\n activeTopButton === 'table-presets' ||\n activeTopButton === 'show-hide-columns'\">\n <!-- <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/settings-2.svg'\"\n class=\"data-grid-svg-icon top-icon me-2\"\n ></span> -->\n\n <a href=\"JavaScript:void(0)\"\n class=\"p-0 d-flex align-items-center justify-content-center grid-header-icon\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/settingIconNew.svg'\"\n class=\"svg-icon svg-icon-2\"\n ></span>\n </a>\n\n <div *ngIf=\"activeTopButton === 'setting'\"\n class=\"actions-dropdown mt-1 actions-dropdown-setting\"\n style=\"position: absolute\">\n <div class=\"dropdown-menu show shadow custom-menu setting_dropdown_menu\">\n <!-- Table Layout -->\n <a class=\"dropdown-item py-0 px-2 d-flex justify-content-between align-items-center cursor-pointer\"\n (click)=\"$event.stopPropagation(); toggleActions('table-layout')\">\n <span class=\"d-flex justify-content-between align-items-center\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/layoutIconNew.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown\"\n ></span>\n Table Layout</span\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n class=\"data-grid-svg-icon d-flex align-items-center justify-content-center\"\n ></span>\n </a>\n <!-- Table Presets -->\n <a (click)=\"$event.stopPropagation(); toggleActions('table-presets')\"\n class=\"dropdown-item py-0 px-2 d-flex justify-content-between align-items-center cursor-pointer\">\n <span class=\"d-flex align-items-center justify-content-center\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/list-details.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown d-flex align-items-center justify-content-center\"\n ></span>\n Table Presets</span\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n class=\"data-grid-svg-icon d-flex align-items-center justify-content-center\"\n ></span>\n </a>\n\n <!-- Columns -->\n <a *ngIf=\"!showSideMenu\" (click)=\"$event.stopPropagation(); toggleActions('show-hide-columns')\"\n class=\"dropdown-item py-0 px-2 d-flex justify-content-between align-items-center cursor-pointer\">\n <span class=\"d-flex align-items-center justify-content-center\"><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/eyeIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown me-2\"\n ></span>\n Columns</span>\n <div class=\"d-flex align-items-center gap-2\">\n <span class=\"muted-text\">{{ columnsCount }}</span>\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n class=\"data-grid-svg-icon d-flex align-items-center justify-content-center\"\n ></span>\n </div>\n </a>\n\n <a (click)=\"autosizeAllColumns()\" class=\"dropdown-item py-0 px-2 d-flex justify-content-between align-items-center cursor-pointer\">\n <span class=\"d-flex align-items-center justify-content-center\"><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/resizeIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown me-2\"></span>\n <span>Autosize all columns</span>\n </span>\n <!-- <div class=\"d-flex align-items-center gap-2\">\n <div class=\"form-check form-switch\">\n <input class=\"form-check-input\" type=\"checkbox\" id=\"flexSwitchCheckChecked\">\n <label class=\"form-check-label\" for=\"flexSwitchCheckChecked\"></label>\n </div>\n </div> -->\n </a>\n\n <a class=\"dropdown-item py-0 px-2 d-flex justify-content-between align-items-center cursor-pointer\">\n <span class=\"d-flex align-items-center justify-content-center\"><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/multicellNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown me-2\"></span>\n <span>Multi-cell tooltip mode</span>\n </span>\n <!-- <div class=\"d-flex align-items-center gap-2\">\n <div class=\"form-check form-switch\">\n <input class=\"form-check-input\" type=\"checkbox\" id=\"flexSwitchCheckChecked\">\n <label class=\"form-check-label\" for=\"flexSwitchCheckChecked\"></label>\n </div>\n </div> -->\n </a>\n\n <div class=\"dropdown-divider\"></div>\n\n <!-- Filter -->\n <!-- <a class=\"dropdown-item py-0 px-2 d-flex align-items-center cursor-pointer\"\n (click)=\"toggleOpenFilter(); activeTopButton = '';\"\n *ngIf=\"!showFilterRow\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/filterIconNew.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown d-flex align-items-center justify-content-center cursor-pointer\"\n ></span>\n Filter\n </a> -->\n\n <!-- Download -->\n <a class=\"dropdown-item py-0 px-2 d-flex align-items-center cursor-pointer\"\n (click)=\"downloadCsv('csv')\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/exportIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown d-flex align-items-center justify-content-center cursor-pointer\"\n ></span>\n CSV Export\n </a>\n <a *ngIf=\"enableExport\"\n class=\"dropdown-item py-0 px-2 d-flex align-items-center cursor-pointer\"\n (click)=\"downloadCsv('xlsx')\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/exportIconNew.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown d-flex align-items-center justify-content-center cursor-pointer\"\n ></span>\n Excel Export\n </a>\n <!-- Font Family & Font Size -->\n <div class=\"px-2 pb-2 pt-2\">\n <div class=\"d-flex gap-2\">\n <!-- <select\n class=\"form-select form-select-sm\"\n [(ngModel)]=\"fontFaimly\"\n (change)=\"onFontChange()\"\n >\n <option *ngFor=\"let font of fontFamilies\" [value]=\"font\">\n {{ font }}\n </option>\n </select> -->\n\n <!-- Font Size -->\n <!-- <select\n class=\"form-select form-select-sm\"\n (change)=\"onFontChange()\"\n [(ngModel)]=\"bodyTextFontsSize\"\n >\n <option *ngFor=\"let size of fontSizes\" [value]=\"size\">\n {{ size }}\n </option>\n </select> -->\n </div>\n </div>\n </div>\n </div>\n\n <!-- Table Layout -->\n\n <ng-container *ngIf=\"activeTopButton === 'table-layout'\">\n <div\n *ngTemplateOutlet=\"tableLayout\"\n class=\"actions-dropdown mt-1\"\n style=\"position: absolute\"\n ></div>\n </ng-container>\n\n <!-- Table Presets -->\n <ng-container *ngIf=\"activeTopButton === 'table-presets'\">\n <div\n *ngTemplateOutlet=\"tablePreset\"\n class=\"actions-dropdown mt-1\"\n style=\"position: absolute\"\n ></div>\n </ng-container>\n\n <!-- Table Presets -->\n <ng-container *ngIf=\"activeTopButton === 'show-hide-columns'\">\n <div\n *ngTemplateOutlet=\"showHideColumns\"\n class=\"actions-dropdown mt-1\"\n style=\"position: absolute\"\n ></div>\n </ng-container>\n </div>\n <div class=\"cursor-pointer actions-buttons-row\">\n <div class=\"btn-group new_design_dropdown\">\n <button type=\"button\" class=\"primary_btn_new dropdown-toggle consumerDropdownButton px-2\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\">\n Actions\n </button>\n <ul class=\"dropdown-menu\">\n <li>\n <a class=\"dropdown-item hover_dropdown_bg action_dropdown\" (click)=\"createCustomColumn()\">Create custom column</a>\n </li>\n <ng-container *ngFor=\"let button of buttons\">\n <li *ngIf=\"button?.has_permission\">\n <a class=\"dropdown-item hover_dropdown_bg action_dropdown\" \n href=\"javascript:void(0)\" \n (click)=\"onActionButtonClick(button.name)\">\n <!-- <span *ngIf=\"button.is_showIcon\" \n class=\"me-2\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/' + button.icon + '.svg'\"\n class=\"svg-icon svg-icon-2\"></span>\n </span> -->\n <span>{{ button?.name }}</span>\n </a>\n </li>\n </ng-container>\n </ul>\n </div>\n </div>\n <!-- <div class=\"cursor-pointer actions-buttons-row\" *ngIf=\"buttons.length == 1\">\n <a href=\"JavaScript:void(0)\"\n (click)=\"onActionButtonClick(buttons[0].name)\"\n class=\"btn btn-primary border border-primary py-1 d-flex align-items-center justify-content-center px-3\">\n <span class=\"text-white\"\n [class.ms-0]=\"buttons[0].is_showIcon\"\n >{{ buttons[0].name }}</span>\n </a>\n </div> -->\n <div class=\"action-buttons-row\" *ngIf=\"showFullScreenButton\">\n <a\n *ngIf=\"!isFullScreen\"\n class=\"button button-small btn btn-active-primary border border-primary expend d-flex justify-content-center align-items-center\"\n (click)=\"toggleFullscreen()\"\n data-bs-toggle=\"tooltip\"\n data-bs-placement=\"top\"\n title=\"Minimise\"\n [ngClass]=\"{ minArrow: !isFullScreen, maxArrow: isFullScreen }\"\n style=\"transition: color 0.2s\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/expend.svg'\"\n class=\"svg-icon svg-icon-2 mb-1\"\n ></span>\n </a>\n <a\n *ngIf=\"isFullScreen\"\n class=\"button button-small btn btn-active-primary border border-primary expend d-flex justify-content-center align-items-center\"\n (click)=\"toggleFullscreen()\"\n data-bs-toggle=\"tooltip\"\n data-bs-placement=\"top\"\n title=\"Maximise\"\n [ngClass]=\"{ minArrow: !isFullScreen, maxArrow: isFullScreen }\"\n style=\"transition: color 0.2s\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/minimize.svg'\"\n class=\"svg-icon svg-icon-2 mb-1\"\n ></span>\n </a>\n </div>\n <div>\n <!-- Example single danger button -->\n\n <!-- <button\n type=\"button\"\n class=\"btn btn-primary btn-sm d-flex gap-2 action-button\"\n (click)=\"toggleActions('actions')\"\n >\n Action\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/Vector.svg'\"\n class=\"data-grid-svg-icon\"\n ></span>\n </button>\n <div\n *ngIf=\"activeTopButton === 'actions'\"\n class=\"actions-dropdown mt-1\"\n >\n <div class=\"dropdown-menu show\">\n <a class=\"dropdown-item\" href=\"#\">Action</a>\n <a class=\"dropdown-item\" href=\"#\">Another action</a>\n <a class=\"dropdown-item\" href=\"#\">Something else here</a>\n <div class=\"dropdown-divider\"></div>\n <a class=\"dropdown-item\" href=\"#\">Separated link</a>\n </div>\n </div> -->\n </div>\n </div>\n </div>\n\n <div\n *ngIf=\"showFilters && !showFilterRow\"\n class=\"top-filter-row border-top py-2 d-flex justify-content-between align-items-center\"\n [style.height.px]=\"topFilterRowHeight\"\n >\n <!-- LEFT SIDE (Filter tags + Filter button) -->\n <div class=\"d-flex gap-2 align-items-center\">\n <ng-container>\n <div\n *ngFor=\"let col of activeFilteredColumns; trackBy: trackByField\"\n class=\"filter-tags\"\n >\n <div\n (click)=\"\n isActiveFilterOpen = true;\n activeTopButton = 'filter-columns';\n openFilter(col)\n \"\n class=\"d-flex justify-content-center align-items-center muted-text add-filter-button active-filters\"\n style=\"white-space: nowrap\"\n [class.active]=\"\n col?.field == selectedColumnForFilter?.field &&\n isActiveFilterOpen &&\n activeTopButton == 'filter-columns'\n \"\n >\n <span class=\"header-tag mt-0 d-flex align-items-center left-side-pinned\">\n <span\n *ngIf=\"col?.pinned\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pin.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n {{ col.header }}: {{col.query.first_value || col.query?._ids[0]}}\n <span\n (click)=\"\n $event.stopPropagation(); removeColumnFilterFromColumn(col)\n \"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/filterCrossNew.svg'\n \"\n class=\"data-grid-svg-icon cross-secondary ms-2\"\n ></span>\n </span>\n </div>\n\n <ng-container\n *ngIf=\"\n activeTopButton === 'filter-columns' &&\n col?.field == selectedColumnForFilter?.field &&\n isActiveFilterOpen\n \"\n >\n <div\n *ngTemplateOutlet=\"filterColumns; context: { column: col }\"\n class=\"actions-dropdown mt-1\"\n ></div>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- Filter Button -->\n <div class=\"add-filter-button-menu\">\n <div\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\n class=\"d-flex justify-content-center align-items-center muted-text add-filter-button button-filter\"\n style=\"width: 70px\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/plus.svg'\"\n class=\"me-2 data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n Filter\n </div>\n\n <ng-container\n *ngIf=\"activeTopButton === 'filter-columns' && !isActiveFilterOpen\"\n >\n <div\n *ngTemplateOutlet=\"filterColumns\"\n class=\"actions-dropdown mt-1\"\n ></div>\n </ng-container>\n </div>\n </div>\n\n <!-- RIGHT SIDE (Update + Reset) -->\n <div class=\"d-flex gap-3 align-items-center\">\n <div\n (click)=\"savePreset()\"\n class=\"text-primary cursor-pointer all-filters-reset-button\"\n *ngIf=\"!checkFilterChangesEffect()\"\n >\n Update View\n </div>\n\n <div\n class=\"text-primary cursor-pointer all-filters-reset-button\"\n *ngIf=\"!tableFilterViewId && activeFilteredColumns?.length\"\n (click)=\"clearAllFilters()\">\n Clear filters\n </div>\n </div>\n </div>\n\n <div\n [style.height]=\"\n showFilters ? 'calc(100% - ' + (topFilterRowHeight + footerRowHeight) + 'px)' : 'calc(100% - ' + footerRowHeight + 'px)'\n \"\n cdkDropListGroup\n class=\"data-grid-table-wrapper overflow-hidden\"\n #dataGridContainer\n [style.fontFamily]=\"fontFaimly\"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n id=\"data-grid-main-container\"\n >\n <div\n *ngIf=\"showRowsGrouping\"\n [style.height.px]=\"headerRowHeight\"\n [cdkDropListData]=\"columns\"\n [style.backgroundColor]=\"\n topGroupedBadgesBackgroundColor || headerBackgroundColor\n \"\n cdkDropList\n (cdkDropListEntered)=\"enterToTopRowGrouping($event)\"\n (cdkDropListExited)=\"exitedFromTheTopRow($event)\"\n (cdkDropListDropped)=\"onDropTopGroup($event)\"\n [cdkDropListEnterPredicate]=\"canEnterToRowsGrouping\"\n id=\"rows-grouping-top-container\"\n class=\"border-below d-flex px-4 align-items-center\"\n >\n <div\n class=\"d-flex gap-2 align-items-center\"\n [style.color]=\"headerTextColor\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <div *ngIf=\"!draggingInGroupArea && !groupedColumns?.length\">\n Drag here to set row groups\n </div>\n <div\n cdkDropListOrientation=\"horizontal\"\n cdkDropList\n (cdkDropListDropped)=\"onGroupReorder($event)\"\n class=\"d-flex\"\n >\n <div\n cdkDrag\n [cdkDragLockAxis]=\"'x'\"\n *ngFor=\"\n let child of groupedColumns;\n let i = index;\n trackBy: trackByField\n \"\n class=\"d-flex align-items-center\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: child,\n showChevron:\n groupedColumns.length > 1 && i != groupedColumns.length - 1\n }\n \"\n ></ng-container>\n <ng-template cdkDragPreview\n ><div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n *ngIf=\"!draggingInGroupArea\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ child.header }}</div>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n </div>\n <div\n class=\"d-flex overflow-hidden\"\n [style.height]=\"\n 'calc(100% - ' +\n (showRowsGrouping\n ? headerRowHeight + footerRowHeight\n : footerRowHeight) +\n 'px)'\n \"\n >\n <div\n class=\"h-100\"\n [style.width]=\"\n !showSideMenu\n ? '100%'\n : sideMenuVisible\n ? 'calc(100% - 280px)'\n : 'calc(100% - 30px)'\n \"\n >\n <div class=\"h-100 transition position-relative w-100\">\n <!-- ##################################################################################################################################################################################### -->\n <!-- ##################################################################################################################################################################################### -->\n <!-- Data Grid Header starts here -->\n <!-- ##################################################################################################################################################################################### -->\n <!-- ##################################################################################################################################################################################### -->\n <!-- [style.backgroundColor]=\"headerBackgroundColor\" -->\n <div\n class=\"data-grid-header-wrapper w-100\"\n [style.color]=\"headerTextColor\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n [style.fontSize.px]=\"headerTextFontsSize\"\n [class.border-below]=\"!hasAnyVisibleColumn\"\n [style.height.px]=\"\n showColumnsGrouping && showFilterRow\n ? headerRowHeight * 3\n : showColumnsGrouping || showFilterRow\n ? headerRowHeight * 2\n : headerRowHeight\n \"\n >\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <!-- Data Grid Left Pinned Header starts here -->\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <div\n class=\"data-grid-header left-pinned\"\n #leftPinnedHeader\n [class.border-right]=\"hasLeftPinnedColumns\">\n <div *ngIf=\"showSerialNumber\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n class=\"select-all-checkbox-cell border-below\"\n [style.width.px]=\"55\"\n [style.height.px]=\"\n showColumnsGrouping && showFilterRow\n ? headerRowHeight * 3\n : showColumnsGrouping || showFilterRow\n ? headerRowHeight * 2\n : headerRowHeight\n \"\n >\n S.No\n </div>\n <div *ngIf=\"showCheckboxes\"\n class=\"select-all-checkbox-cell border-below\"\n [style.height.px]=\"\n showColumnsGrouping && showFilterRow\n ? headerRowHeight * 3\n : showColumnsGrouping || showFilterRow\n ? headerRowHeight * 2\n : headerRowHeight\n \"\n >\n <input class=\"serialNoCheckbox\"\n *ngIf=\"hasAnyVisibleColumn\"\n style=\"width: 16px; height: 16px\"\n type=\"checkbox\"\n [indeterminate]=\"isIndeterminateState(dataSet)\"\n [checked]=\"isAllSelected(dataSet)\"\n (change)=\"toggleSelectAll(dataSet)\"\n />\n </div>\n <div\n [style.backgroundColor]=\"headerBackgroundColor\"\n class=\"d-flex\"\n cdkDropList\n id=\"left-pinned-header\"\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"leftPinnedColumns\"\n (cdkDropListEntered)=\"onDropListEnter($event, 'left')\"\n (cdkDropListSorted)=\"\n onSortGroup($event, 'previewLeftPinnedColumns')\n \"\n (cdkDropListDropped)=\"onDropGroup()\"\n style=\"min-width: 1px\"\n >\n <div\n class=\"dragable-header\"\n cdkDrag\n [cdkDragData]=\"col\"\n *ngFor=\"\n let col of leftPinnedColumns;\n let i = index;\n trackBy: trackByField\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n index: i,\n section: 'previewLeftPinnedColumns'\n }\n \"\n ></ng-container>\n <ng-template cdkDragPreview\n ><div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n *ngIf=\"!draggingInGroupArea\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/arrows-move.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ col.header }}</div>\n </div>\n </ng-template>\n <ng-template cdkDragPlaceholder>\n <div *ngIf=\"!draggingInGroupArea\">\n <div\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n index: i,\n section: ''\n }\n \"\n ></div>\n </div>\n <div\n *ngIf=\"draggingInGroupArea\"\n class=\"d-flex gap-2 ms-2\"\n style=\"opacity: 0.6\"\n >\n <ng-container\n *ngIf=\"col?.children?.length; else singleCol\"\n >\n <ng-container\n *ngFor=\"\n let child of col.children;\n let i = index;\n trackBy: trackByField\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: child,\n showChevron:\n col.children.length > 1 &&\n i != col.children.length - 1\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n\n <ng-template #singleCol>\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: col,\n showChevron: col?.children?.length > 1\n }\n \"\n ></ng-container>\n </ng-template>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <!-- Data Grid Center Pinned Header starts here -->\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <div\n class=\"data-grid-header center-scrollable\"\n #centerPinnedHeader\n (scroll)=\"onCenterBodyScroll($event)\"\n id=\"center-pinned-header\"\n cdkDropList\n [cdkDropListConnectedTo]=\"\n showRowsGrouping ? ['rows-grouping-top-container'] : []\n \"\n [cdkDropListData]=\"centerColumns\"\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListSortingDisabled]=\"\n isDisableColumnGrouping && draggingInGroupArea\n \"\n (cdkDropListEntered)=\"onDropListEnter($event, 'center')\"\n (cdkDropListSorted)=\"onSortGroup($event, 'previewCenterColumns')\"\n (cdkDropListDropped)=\"onDropGroup()\"\n [style.maxWidth]=\"\n 'calc(100% - ' +\n (rightPinnedHeader.offsetWidth + leftPinnedHeader.offsetWidth) +\n 'px)'\n \"\n >\n <div\n *ngIf=\"groupedColumns?.length\"\n style=\"min-width: 200px\"\n class=\"h-100 align-items-center\"\n #columnsGroupedBox\n id=\"groupBoxHeaderDiv\"\n >\n <div\n class=\"d-flex w-100 justify-content-between align-items-center border-below\"\n [style.height.px]=\"\n showFilterRow ? headerRowHeight * 2 : headerRowHeight\n \"\n >\n <div class=\"ps-3\">Group</div>\n <div class=\"d-flex\">\n <div\n class=\"three-dots cursor-pointer\"\n (click)=\"\n openThreeDotsMenu($event, 'group');\n isThreeDotsFilterOpen = false\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/three-dots-vertical.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div\n (mousedown)=\"\n $event.stopPropagation(); onResizeGroupBox($event)\n \"\n class=\"resize-handle\"\n style=\"margin-right: -2px\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n </div>\n\n <div\n [style.height.px]=\"headerRowHeight\"\n class=\"border-below\"\n ></div>\n </div>\n <span\n class=\"d-flex align-items-center justify-content-center cursor-pointer border-below\"\n style=\"min-width: 30px; height: 100%\"\n *ngIf=\"gridType === 'Assets' || gridType === 'Tasks'\"\n >\n </span>\n <div\n class=\"dragable-header\"\n (cdkDragStarted)=\"\n checkColumnGroupingStatus(col);\n dragStartOnGroup(col);\n onDragStarted(col)\n \"\n (cdkDragMoved)=\"onDragMoved($event)\"\n (cdkDragEnded)=\"onDragEnded()\"\n cdkDrag\n [cdkDragData]=\"col\"\n *ngFor=\"\n let col of centerColumns;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n index: i,\n section: 'previewCenterColumns'\n }\n \"\n >\n </ng-container>\n <ng-template cdkDragPreview\n ><div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n *ngIf=\"!isOutsideContainer\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n (draggingInGroupArea\n ? 'data-grid/icons/justify.svg'\n : 'data-grid/icons/arrows-move.svg')\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n >\n </span>\n <span\n *ngIf=\"isOutsideContainer\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/eye-cross.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n >\n </span>\n </div>\n <div>{{ col.header }}</div>\n </div>\n </ng-template>\n <ng-template cdkDragPlaceholder>\n <div *ngIf=\"!draggingInGroupArea\">\n <div\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n index: i,\n section: 'centerColumns'\n }\n \"\n ></div>\n </div>\n <div\n *ngIf=\"draggingInGroupArea && !isOutsideContainer\"\n class=\"d-flex gap-2 ms-2\"\n style=\"opacity: 0.6\"\n >\n <ng-container *ngIf=\"col?.children?.length; else singleCol\">\n <ng-container\n *ngFor=\"\n let child of col.children;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container *ngIf=\"child?.is_groupable\">\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: child,\n showChevron:\n col.children.length > 1 &&\n i != col.children.length - 1\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n\n <ng-template #singleCol>\n <ng-container *ngIf=\"col?.is_groupable\">\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: col,\n showChevron: col?.children?.length > 1\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-template>\n </div>\n </ng-template>\n </div>\n </div>\n\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <!-- Data Grid Right Pinned Header starts here -->\n <!-- ********************************************************************************* -->\n <!-- ********************************************************************************* -->\n <div\n [style.backgroundColor]=\"headerBackgroundColor\"\n cdkDropList\n id=\"right-pinned-header\"\n [cdkDropListConnectedTo]=\"\n showRowsGrouping ? ['rows-grouping-top-container'] : []\n \"\n cdkDropListOrientation=\"horizontal\"\n class=\"data-grid-header right-pinned\"\n (cdkDropListSorted)=\"\n onSortGroup($event, 'previewRightPinnedColumns')\n \"\n (cdkDropListEntered)=\"onDropListEnter($event, 'right')\"\n (cdkDropListDropped)=\"onDropGroup()\"\n #rightPinnedHeader\n class=\"right-pinned-header d-flex\"\n style=\"min-width: 0.2px\"\n >\n <div\n class=\"dragable-header\"\n cdkDrag\n [cdkDragData]=\"col\"\n *ngFor=\"\n let col of rightPinnedColumns;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n pinnedRight: true,\n index: i,\n section: 'right'\n }\n \"\n ></ng-container>\n <ng-template cdkDragPreview\n ><div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n *ngIf=\"!draggingInGroupArea\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/arrows-move.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ col.header }}</div>\n </div>\n </ng-template>\n <ng-template cdkDragPlaceholder>\n <div *ngIf=\"!draggingInGroupArea\">\n <div\n *ngTemplateOutlet=\"\n headerCell;\n context: {\n $implicit: col,\n index: i,\n section: 'right'\n }\n \"\n ></div>\n </div>\n <div\n *ngIf=\"draggingInGroupArea\"\n class=\"d-flex gap-2 ms-2\"\n style=\"opacity: 0.6\"\n >\n <ng-container *ngIf=\"col?.children?.length; else singleCol\">\n <ng-container\n *ngFor=\"\n let child of col.children;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: child,\n showChevron:\n col.children.length > 1 &&\n i != col.children.length - 1\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n\n <ng-template #singleCol>\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: col,\n showChevron: col?.children?.length > 1\n }\n \"\n ></ng-container>\n </ng-template>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n\n <!--########################################################################################################################################################################################################################### -->\n <!--########################################################################################################################################################################################################################### -->\n <!-- Data Grid Body starts here -->\n <!--########################################################################################################################################################################################################################### -->\n <!--########################################################################################################################################################################################################################### -->\n <div\n class=\"h-100 d-flex justify-content-center align-items-center\"\n *ngIf=\"!dataSet?.length && !loading && !dataSetLoading\">\n <!-- <div\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/record-not-found.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></div> -->\n <div class=\"d-flex flex-column justify-content-center align-items-center\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/no-data-image.svg'\"\n class=\"data-grid-svg-icon mb-3 d-flex justify-content-center align-items-center\">\n </span>\n <p class=\"text_common_16px mb-0\">No data available</p>\n <p class=\"page_refresh mb-0\">Try adjusting filters or refresh the page</p>\n </div>\n </div>\n\n <div\n class=\"position-absolute w-100 h-100 d-flex justify-content-center align-items-center loading-overlay\"\n *ngIf=\"loading || dataSetLoading\"\n style=\"\n z-index: 999;\n backdrop-filter: blur(1px);\n \"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n >\n <div class=\"spinner-border text-primary\" role=\"status\">\n <!-- <span class=\"loader\"></span> -->\n <!-- <span class=\"visually-hidden\">Loading...</span> -->\n <!-- </div> -->\n </div>\n </div>\n\n <div\n class=\"data-grid-body-wrapper position-relative d-flex\"\n [style.height]=\"bodyWrapperHeight\"\n style=\"overflow-y: auto; overflow-x: hidden\"\n #mainScroll\n (scroll)=\"onMainScroll($event)\"\n [style.scrollbarWidth]=\"verticalScrollbarWidth\"\n >\n <!-- LEFT PINNED -->\n <div\n [style.height.px]=\"\n !groupedColumns.length ? originalDataSet.length * rowHeight : 0\n \"\n ></div>\n <!-- [class.transparent-border-right]=\"!hasLeftPinnedColumns\" -->\n <div [class.h-100]=\"originalDataSet.length < 8\">\n <div\n class=\"data-grid-body left-pinned-body w-100\"\n style=\"overflow-y: hidden\"\n [class.border-right]=\"hasLeftPinnedColumns\"\n [class.transparent-border-right]=\"!hasLeftPinnedColumns\"\n [style.boxShadow]=\"leftPinnedBoxshadow\"\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\n [style.backgroundColor]=\"leftPinnedBackgroundColor\"\n [class.h-100]=\"originalDataSet.length < 8\"\n *ngIf=\"!loading && !dataSetLoading\"\n [@rowDynamic]=\"rowAnimation\"\n\n \n >\n <ng-container\n *ngFor=\"\n let row of visibleRows;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: row,\n columns: previewLeftPinnedColumns,\n isEven: (startIndex + i) % 2 === 0,\n isOdd: (startIndex + i) % 2 !== 0,\n isLeft: true,\n section: 'left',\n isTotalRow: false\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: { __virtualIndex: 0 },\n columns: previewLeftPinnedColumns,\n isEven: false,\n isOdd: false,\n section: 'left',\n isTotalRow: true\n }\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n\n <!-- CENTER -->\n <div\n class=\"h-100\"\n [style.width.px]=\"centerPinnedHeader.clientWidth\"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n >\n <div\n class=\"data-grid-body center-scrollable\"\n [class.h-100]=\"originalDataSet.length < 8\"\n style=\"overflow-y: hidden; overflow-x: auto\"\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n #centerScrollableBody\n (scroll)=\"onCenterBodyScroll($event)\"\n [style.boxShadow]=\"leftPinnedBoxshadow\"\n \n >\n <div [@rowDynamic]=\"rowAnimation\" *ngIf=\"!loading && !dataSetLoading\">\n <ng-container\n *ngFor=\"\n let row of visibleRows;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: row,\n columns: previewCenterColumns,\n isEven: (startIndex + i) % 2 === 0,\n isOdd: (startIndex + i) % 2 !== 0,\n section: 'center',\n isTotalRow: false\n }\n \"\n ></ng-container>\n </ng-container>\n </div>\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: { __virtualIndex: 0 },\n columns: previewCenterColumns,\n isEven: false,\n isOdd: false,\n section: 'center',\n isTotalRow: true\n }\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n\n <!-- RIGHT PINNED -->\n <div\n class=\"right-pinned-body-wrapper\"\n *ngIf=\"true\"\n [class.h-100]=\"originalDataSet.length < 8\"\n [style.maxWidth.px]=\"\n isScrollbarVisible\n ? rightPinnedHeader.offsetWidth - 15\n : rightPinnedHeader.offsetWidth\n \"\n [style.backgroundColor]=\"rightPinnedBackgroundColor\"\n [@rowDynamic]=\"rowAnimation\"\n >\n <div\n class=\"data-grid-body right-pinned-body w-100 h-100\"\n style=\"overflow-y: hidden\"\n [style.transform]=\"'translateY(' + translateY + 'px)'\"\n [style.boxShadow]=\"rightPinnedBoxshadow\"\n [style.backgroundColor]=\"rightPinnedBackgroundColor\"\n *ngIf=\"!loading && !dataSetLoading && hasRightPinnedColumns\"\n >\n <ng-container\n *ngFor=\"\n let row of visibleRows;\n let i = index;\n trackBy: trackById\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: row,\n columns: previewRightPinnedColumns,\n isEven: (startIndex + i) % 2 === 0,\n isOdd: (startIndex + i) % 2 !== 0,\n section: 'right',\n isTotalRow: false\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"showTotalAmountRow && originalDataSet?.length\">\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: { __virtualIndex: 0 },\n columns: previewRightPinnedColumns,\n isEven: false,\n isOdd: false,\n section: 'right',\n isTotalRow: true\n }\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n\n <div\n style=\"top: auto; left: auto\"\n (click)=\"\n $event.stopPropagation();\n fullscreenImage = null;\n cdr.detectChanges()\n \"\n [style.width.px]=\"dataGridContainer.offsetWidth\"\n [style.height.px]=\"\n dataGridContainer.offsetHeight - (footerRowHeight + 100)\n \"\n class=\"image-modal full-image-modal\"\n *ngIf=\"fullscreenImage\"\n >\n <img\n (click)=\"$event.stopPropagation()\"\n [src]=\"fullscreenImage\"\n alt=\"Fullscreen Image\"\n />\n </div>\n <div\n *ngIf=\"selectedRows.size > 0 && showTaskbar\"\n class=\"taskbar w-100\"\n [style.bottom.px]=\"85\"\n >\n <div class=\"selected-rows-action-bar\" [@slideUp]>\n <span class=\"selected-count\">\n {{ selectedRows.size }} selected of\n {{\n paginationConfig.totalResults ||\n config?.paginationParams?.totalItems\n }}\n Total\n </span>\n <div class=\"action-buttons d-flex align-items-center\">\n <ng-container\n *ngFor=\"let action of taskbarActions; let i = index\"\n >\n <ng-container *ngIf=\"action?.has_permission\">\n <span\n class=\"action-btn verified btn {{ action }}\"\n (click)=\"onVerifyClick(action?.actionName)\"\n >{{ action?.actionName }}</span\n >\n <span\n *ngIf=\"\n taskbarActions.length > 1 &&\n i !== taskbarActions.length - 1 &&\n taskbarActions[i + 1]?.has_permission\n \"\n class=\"\"\n >|</span\n >\n </ng-container>\n </ng-container>\n <button (click)=\"clearSelectionState(tableType);selectedRows.clear();\" class=\"clear-btn ms-2 mt-2\">\n <i class=\"bi bi-x-circle\"></i> Clear Selection\n </button>\n </div>\n </div>\n </div>\n </div>\n <!-- Vertical Fake scroll Bar -->\n <!-- <div\n (scroll)=\"onMainFakeScroll($event)\"\n class=\"fake-scrollbar fake-scrollbar-vertical d-none\"\n [style.scrollbarWidth]=\"verticalScrollbarWidth\"\n [style.top.px]=\"\n showColumnsGrouping && showFilterRow\n ? headerRowHeight * 3\n : showColumnsGrouping || showFilterRow\n ? headerRowHeight * 2\n : headerRowHeight\n \"\n #fakeScroll\n [style.height]=\"bodyWrapperHeight\"\n style=\"\n overflow-y: auto;\n overflow-x: hidden;\n width: 17px;\n position: absolute;\n right: 0;\n background-color: f1f2f3;\n z-index: 10;\n \"\n >\n <div [style.height.px]=\"rowHeight * dataSetLength\"></div>\n </div> -->\n </div>\n\n <!-- Horizintal Fake Scrollbars -->\n <div\n class=\"d-flex justify-content-between\"\n *ngIf=\"hasScroll\"\n >\n <div\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\n class=\"fake-horizintal-scrollbar\"\n #fakeScroll\n [style.width.px]=\"leftPinnedHeader.offsetWidth\"\n style=\"overflow-x: scroll\"\n ></div>\n <div\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\n (scroll)=\"onCenterBodyScroll($event)\"\n class=\"fake-horizintal-scrollbar\"\n #horizintalFakeScroll\n [style.width.px]=\"centerPinnedHeader.offsetWidth\"\n >\n <div [style.width.px]=\"centerPinnedHeader.scrollWidth - 10\"></div>\n </div>\n <div\n [style.scrollbarWidth]=\"horizintalScrollbarWidth\"\n class=\"fake-horizintal-scrollbar\"\n #fakeScroll\n [style.width.px]=\"rightPinnedHeader.offsetWidth\"\n style=\"overflow-x: scroll\"\n ></div>\n </div>\n </div>\n\n <!-- Side Menu Implemented Here -->\n <div\n *ngIf=\"showSideMenu\"\n [style.width.px]=\"sideMenuVisible ? 280 : 30\"\n class=\"right-menu h-100\"\n [style.backgroundColor]=\"sidemenuBackgroundColor\"\n >\n <div class=\"h-100 d-flex flex-row-reverse\">\n <div\n style=\"width: 30px\"\n class=\"d-flex flex-column align-items-center cursor-pointer\"\n [class.border-start]=\"sideMenuVisible\"\n >\n <div\n (click)=\"toggleSideMenu('cols')\"\n [class.bg-fff]=\"\n currentOpenedSideMenue == 'cols' && sideMenuVisible\n \"\n [class.border-below]=\"sideMenuVisible\"\n class=\"columns-button d-flex flex-column align-items-center\"\n >\n <div>\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/ui-checks-grid.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div class=\"side-menue-text\">Columns</div>\n </div>\n\n <div\n (click)=\"toggleSideMenu('filtrs')\"\n [class.bg-fff]=\"\n currentOpenedSideMenue == 'filtrs' && sideMenuVisible\n \"\n [class.border-below]=\"\n sideMenuVisible && currentOpenedSideMenue == 'filtrs'\n \"\n class=\"columns-button d-flex flex-column align-items-center\"\n >\n <div>\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div class=\"side-menue-text\">Filter</div>\n </div>\n </div>\n <div\n class=\"h-100\"\n *ngIf=\"sideMenuVisible\"\n [ngStyle]=\"{ width: sideMenuVisible ? '250px' : '' }\"\n >\n <div class=\"h-100\">\n <ng-container\n *ngIf=\"currentOpenedSideMenue == 'cols' && sideMenuVisible\"\n >\n <ng-container *ngTemplateOutlet=\"columnPannel\"></ng-container>\n <!-- Column Items -->\n <div class=\"column-panel-body px-3\">\n <ng-container\n *ngFor=\"let col of columns; trackBy: trackByField\"\n >\n <ng-container\n *ngTemplateOutlet=\"columnPanelItem; context: { col: col }\"\n ></ng-container>\n </ng-container>\n </div>\n <hr />\n\n <div class=\"side-menu-row-groups\" style=\"height: 30%\">\n <ng-container\n *ngTemplateOutlet=\"sideMenuRowGroups\"\n ></ng-container>\n </div>\n </ng-container>\n <ng-container\n *ngIf=\"currentOpenedSideMenue == 'filtrs' && sideMenuVisible\"\n >\n <ng-container *ngTemplateOutlet=\"sideFilters\"></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div\n [style.height.px]=\"footerRowHeight\"\n class=\"border-top\"\n [style.backgroundColor]=\"footerRowBackgroundColor\"\n >\n <!-- Rows: <span class=\"fw-500 ms-1\">{{ dataSet.length }}</span> -->\n\n <div class=\"pagination-container\"\n [style.height.px]=\"footerRowHeight\"\n [style.padding.px]=\"footerPadding\">\n <div class=\"page-size\">\n <select\n [(ngModel)]=\"paginationConfig.limit\"\n (change)=\"onPageSizeChange()\"\n >\n <option *ngFor=\"let size of pageSizeOptions\" [value]=\"size\">\n {{ size }}\n </option>\n </select>\n <span class=\"separator\"> per page </span>\n </div>\n\n <div class=\"page-info\">\n \n {{ (paginationConfig.page - 1) * paginationConfig.limit + 1 }}-{{\n paginationConfig.page * paginationConfig.limit <\n paginationConfig.totalResults\n ? paginationConfig.page * paginationConfig.limit\n : paginationConfig.totalResults\n }}\n of\n {{ paginationConfig.totalResults }}\n results\n </div>\n\n <div class=\"page-buttons\">\n <button\n (click)=\"goToPage(paginationConfig.page - 1)\"\n [disabled]=\"paginationConfig.page === 1\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/chevron-left.svg'\"\n class=\"d-flex justify-content-center align-items-center\"\n ></span>\n </button>\n\n <ng-container *ngFor=\"let page of visiblePages\">\n <button\n *ngIf=\"page !== '...'\"\n (click)=\"goToPage(page)\"\n [class.active]=\"page === paginationConfig.page\"\n >\n {{ page }}\n </button>\n <span *ngIf=\"page === '...'\">...</span>\n </ng-container>\n\n <button\n (click)=\"goToPage(paginationConfig.page + 1)\"\n [disabled]=\"paginationConfig.page === paginationConfig.totalResults\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\"\n class=\"d-flex justify-content-center align-items-center\"\n ></span>\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\n<!-- Header Cell Template -->\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\n<!-- ------------------------------------------------------------------------------------------------------------------------ -->\n\n<ng-template\n #headerCell\n let-col\n let-pinnedRight=\"pinnedRight\"\n let-i=\"index\"\n let-sections=\"section\"\n let-calledFromNestedPlaceholder=\"calledFromNestedPlaceholder\"\n>\n <div>\n <!-- Group Header -->\n <ng-container *ngIf=\"col.children?.length > 0; else flatHeader\">\n <div cdkDroplistGroup class=\"group-column-wrapper\">\n <!-- Parent Header -->\n <div\n *ngIf=\"shouldTheGroupHeaderShow(col)\"\n class=\"header-cell group-header\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n [class.border-right]=\"showVerticalBorder\"\n [style.gridColumn]=\"'span ' + col.children.length\"\n [style.fontWeight]=\"headerFontWeight\"\n [class.flex-row-reverse]=\"pinnedRight\"\n [class.justify-content-end]=\"pinnedRight\"\n style=\"grid-row: 1\"\n >\n <div\n class=\"group-header-content\"\n [title]=\"col.header\"\n [class.ms-2]=\"pinnedRight\"\n >\n {{ col.header }}\n </div>\n <div\n class=\"resize-handle\"\n (dblclick)=\"autosizeColumn(col.children)\"\n (mousedown)=\"\n $event.stopPropagation(); onResizeGroup($event, col, pinnedRight)\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n\n <!-- Child Headers and Filters -->\n\n <div\n class=\"d-flex\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"col.children\"\n (cdkDropListSorted)=\"onChildDroplistSorted($event, sections)\"\n (cdkDropListDropped)=\"onChildDroplistDroped($event)\"\n [cdkDropListSortingDisabled]=\"false\"\n [cdkDropListConnectedTo]=\"\n showRowsGrouping ? ['rows-grouping-top-container'] : []\n \"\n >\n <div\n cdkDrag\n [cdkDragData]=\"child\"\n *ngFor=\"let child of col.children; let i = index\"\n >\n <!-- Child Header -->\n <ng-container *ngIf=\"child.is_visible && !child['isRowGrouped']\">\n <div\n cdkDragHandle\n class=\"header-cell one-row-header-cells cursor-pointer\"\n [class.border-right]=\"showVerticalBorder\"\n [attr.field]=\"child.field\"\n [style.width.px]=\"child.width\"\n [style.min-width.px]=\"child.width\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n [style.fontWeight]=\"headerFontWeight\"\n style=\"grid-row: 2\"\n [class.filter-applied-on-text]=\"isFilterAppliedOnColumn(child)\"\n >\n <div\n class=\"d-flex justify-content-between h-100 align-items-center w-100\"\n >\n <div\n class=\"d-flex justify-content-between align-items-center w-100\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div\n class=\"text-ellipsis h-100 d-flex align-items-center w-100\"\n [title]=\"col.header\"\n [class.w-100]=\"pinnedRight\"\n >\n <div\n class=\"text-ellipsis h-100\"\n [class.editable-header]=\"child?.is_editable\"\n (click)=\"\n openThreeDotsMenu($event, child);\n openFilteronThreeDotsClick(child)\n \"\n >\n {{ child.header }}\n </div>\n </div>\n\n <div\n class=\"position-relative d-flex\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div\n [class.me-2]=\"pinnedRight\"\n class=\"d-flex align-items-center\"\n *ngIf=\"child.pinned\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/pin.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div\n class=\"three-dots p-1 zaid-test\"\n (click)=\"\n openThreeDotsMenu($event, child);\n isThreeDotsFilterOpen = false\n \"\n style=\"cursor: pointer\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/three-dots-vertical.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n\n <!-- Only show menu if this column is active -->\n <div\n class=\"position-absolute\"\n *ngIf=\"activeCol === child\"\n style=\"top: -50%; z-index: 21\"\n [style.left.px]=\"\n -(!child?.pinned ? centerPinnedHeader.scrollLeft : 0)\n \"\n [style.top.px]=\"\n isThreeDotsFilterOpen\n ? showFilterRow || showColumnsGrouping\n ? headerRowHeight * 2 - 10\n : headerRowHeight - 10\n : 0\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n columnMenu;\n context: {\n col: child,\n isNestedTable: false,\n section: sections\n }\n \"\n ></ng-container>\n </div>\n\n <div\n class=\"resize-handle\"\n (dblclick)=\"autosizeColumn(child)\"\n (mousedown)=\"\n $event.stopPropagation();\n onResizeColumn($event, child)\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Filter Cell -->\n <div\n *ngIf=\"showFilterRow\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n class=\"header-cell filter-cell\"\n [class.border-right]=\"showVerticalBorder\"\n [attr.field]=\"child.field\"\n [style.width.px]=\"child.width\"\n [style.min-width.px]=\"child.width\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n [class.border-right]=\"showVerticalBorder\"\n style=\"grid-row: 3\"\n >\n <div\n class=\"header-cell filter-cell\"\n [attr.field]=\"col.field\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n >\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Filter\"\n [(ngModel)]=\"child.filterValue\"\n (ngModelChange)=\"onFilterChange(child)\"\n (paste)=\"onFilterChange(child); applyDropdownFilter()\"\n [readonly]=\"\n child?.type == 'dropdown' || child?.type == 'image'\n \"\n [class.disabled-search-input]=\"\n child?.type == 'dropdown' || child?.type == 'image'\n \"\n (click)=\"\n $event.stopPropagation();\n openFilterFromDisabledSearchedInput(child)\n \"\n (keydown.enter)=\"applyDropdownFilter()\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n <span\n class=\"filter-icon-wrapper\"\n (click)=\"$event.stopPropagation(); openFilter(child)\"\n [class.filter-applied]=\"isFilterAppliedOnColumn(child)\"\n [class.pe-none]=\"child?.type == 'image'\"\n ><span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <span\n *ngIf=\"isFilterAppliedOnColumn(child)\"\n style=\"\n width: 7px;\n height: 7px;\n box-shadow: 0px 0px 3px #7486ff;\n background-color: rgb(0 163 233);\n position: absolute;\n right: 4px;\n top: 12px;\n \"\n class=\"rounded-circle d-block\"\n ></span\n ></span>\n\n <div\n class=\"position-absolute filter-row-filter-wrapper\"\n *ngIf=\"activeFilterCell?.field == child?.field\"\n style=\"top: 100%; right: 0; z-index: 99\"\n [style.left.px]=\"\n child?.pinned ? 0 : -centerPinnedHeader.scrollLeft\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"filterMenu; context: { col: child }\"\n ></ng-container>\n </div>\n </div>\n </div>\n </ng-container>\n <ng-template cdkDragPreview\n ><div class=\"p-2 border d-flex gap-2\">\n <div\n *ngIf=\"\n !draggingInGroupArea ||\n (child.is_groupable && draggingInGroupArea)\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div *ngIf=\"draggingInGroupArea && !child.is_groupable\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/ban.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ child.header }}</div>\n </div>\n </ng-template>\n <ng-template cdkDragPlaceholder>\n <div *ngIf=\"!draggingInGroupArea\" class=\"position-relative\">\n <div\n *ngTemplateOutlet=\"\n childHeaderPlaceholder;\n context: {\n $implicit: child,\n index: i,\n sections: sections,\n calledFromNestedPlaceholder: true,\n }\n \"\n ></div>\n </div>\n <div\n *ngIf=\"draggingInGroupArea && child?.is_groupable\"\n class=\"d-flex gap-2 ms-2\"\n style=\"opacity: 0.6\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n topGroupingRowPlaceholder;\n context: {\n $implicit: child,\n showChevron: false,\n pinnedRight: pinnedRight,\n sections: sections,\n index: i\n }\n \"\n ></ng-container>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n </ng-container>\n\n <!-- Flat Header || Single Header Cell-->\n <ng-template #flatHeader>\n <div\n class=\"group-column-wrapper\"\n *ngIf=\"col.is_visible && !col['isRowGrouped']\"\n >\n <!-- Full-height Header Cell (spans 2 rows visually) -->\n <div\n class=\"header-cell one-row-header-cells\"\n [attr.field]=\"col.field\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [class.border-right]=\"showVerticalBorder\"\n [style.min-height.px]=\"\n showColumnsGrouping ? headerRowHeight * 2 : headerRowHeight\n \"\n [style.height.px]=\"\n showColumnsGrouping ? headerRowHeight * 2 : headerRowHeight\n \"\n [style.fontWeight]=\"headerFontWeight\"\n style=\"grid-row: 1 / span 2\"\n >\n <div\n class=\"d-flex justify-content-between h-100 align-items-center w-100\"\n >\n <div\n class=\"d-flex justify-content-between w-100 align-items-center\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div\n class=\"text-ellipsis h-100 d-flex align-items-center w-100\"\n [title]=\"col.header\"\n >\n <div\n class=\"text-ellipsis h-100 cursor-pointer\"\n [class.editable-header]=\"col?.is_editable\"\n [class.filter-applied-on-text]=\"isFilterAppliedOnColumn(col)\"\n (click)=\"\n openThreeDotsMenu($event, col);\n openFilteronThreeDotsClick(col)\n \"\n >\n {{ col.header }}\n </div>\n </div>\n\n <div\n class=\"position-relative d-flex align-items-center\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div\n [class.me-2]=\"pinnedRight\" [class.threeDotActive]=\"activeCol === col && !clickedOnSortIcon\"\n class=\"d-flex align-items-center three-dots\"\n *ngIf=\"col?.pinned\">\n <span (click)=\"\n openThreeDotsMenu($event, col, false);\n isThreeDotsFilterOpen = false\n \"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/pin.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown d-flex justify-content-center align-items-center pin_blue_icon\"\n ></span>\n </div>\n <!-- <div\n [class.me-2]=\"col.order_by\"\n class=\"d-flex align-items-center\"\n *ngIf=\"sortingConfig?.field == col.field\">\n <span\n *ngIf=\"sortingConfig?.order_by == 'asc'\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/selectedAscIcon.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center mt-1 cursor-pointer\"\n (click)=\"sortDesc(col)\"\n [class.active]=\"sortingConfig?.order_by === 'asc'\"\n ></span>\n <span\n *ngIf=\"sortingConfig?.order_by == 'desc'\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/selectedAscIcon.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center mt-1 cursor-pointer\"\n (click)=\"sortAsc(col)\"\n [class.active]=\"sortingConfig?.order_by === 'desc'\"\n ></span>\n </div> -->\n <div class=\"three-dots p-1 me-0 zaid-test1\" [class.threeDotActive]=\"activeCol === col && clickedOnSortIcon\"\n (click)=\"openThreeDotsMenu($event, col, true);\"\n style=\"cursor: pointer\">\n <div *ngIf=\"sortingConfig?.field === col.field\" \n class=\"d-flex align-items-center\">\n \n <!-- Ascending Sort Icon -->\n <span\n *ngIf=\"sortingConfig?.order_by == 'asc'\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/sort-ascending-green.svg'\"\n class=\"data-grid-svg-icon ascendingAppliedIcon flex justify-content-center align-items-center cursor-pointer\"\n (click)=\"openThreeDotsMenu($event, col, true)\"\n [class.active]=\"sortingConfig?.order_by === 'asc'\">\n </span>\n\n <!-- Descending Sort Icon -->\n <span\n *ngIf=\"sortingConfig?.order_by == 'desc'\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/sort-ascending-green.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center cursor-pointer rotated-180\"\n (click)=\"openThreeDotsMenu($event, col, true)\"\n [class.active]=\"sortingConfig?.order_by === 'desc'\">\n </span>\n </div>\n <span *ngIf=\"sortingConfig?.field !== col.field\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/sortIconGray.svg'\"\n class=\"data-grid-svg-icon figmaIconSize d-flex justify-content-center align-items-center\"\n (click)=\"openThreeDotsMenu($event, col, true)\">\n </span>\n </div>\n <div class=\"three-dots p-1 zaid-test1\" [class.threeDotActive]=\"activeCol === col && !clickedOnSortIcon\" *ngIf=\"!col?.pinned\"\n (click)=\"\n openThreeDotsMenu($event, col, false);\n isThreeDotsFilterOpen = false\n \"\n style=\"cursor: pointer\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/three-dots-vertical.svg'\n \"\n class=\"data-grid-svg-icon setting_dropdown dropdown d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n\n <!-- Only show menu if this column is active -->\n <div\n class=\"position-absolute\"\n *ngIf=\"activeCol === col\"\n style=\"z-index: 21\"\n [style.left.px]=\"\n -(!col?.pinned ? centerPinnedHeader.scrollLeft : 0)\n \"\n [style.top.px]=\"\n isThreeDotsFilterOpen\n ? showFilterRow || showColumnsGrouping\n ? headerRowHeight * 2 - 10\n : headerRowHeight - 10\n : 25\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n columnMenu;\n context: {\n col: col,\n isNestedTable: false,\n section: sections\n }\n \"\n ></ng-container>\n </div>\n\n <div\n class=\"resize-handle\"\n [class.w-100]=\"col.pinned == 'right'\"\n (dblclick)=\"autosizeColumn(col)\"\n (mousedown)=\"\n $event.stopPropagation(); onResizeColumn($event, col)\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Filter Cell -->\n <div\n *ngIf=\"showFilterRow\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n class=\"header-cell filter-cell\"\n [class.border-right]=\"showVerticalBorder\"\n [attr.field]=\"col.field\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n >\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Filter\"\n [(ngModel)]=\"col.filterValue\"\n (ngModelChange)=\"onFilterChange(col)\"\n [readonly]=\"col?.type == 'dropdown' || col?.type == 'image'\"\n [class.disabled-search-input]=\"\n col?.type == 'dropdown' || col?.type == 'image'\n \"\n (paste)=\"onPasteInFilterRowSearch($event, col)\"\n (click)=\"\n $event.stopPropagation(); openFilterFromDisabledSearchedInput(col)\n \"\n (keydown.enter)=\"applyDropdownFilter()\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n <span\n class=\"filter-icon-wrapper\"\n (click)=\"$event.stopPropagation(); openFilter(col)\"\n [class.filter-applied]=\"isFilterAppliedOnColumn(col)\"\n [class.pe-none]=\"col?.type == 'image'\"\n ><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <span\n *ngIf=\"isFilterAppliedOnColumn(col)\"\n style=\"\n width: 7px;\n height: 7px;\n box-shadow: 0px 0px 3px #7486ff;\n background-color: rgb(0 163 233);\n position: absolute;\n right: 4px;\n top: 12px;\n \"\n class=\"rounded-circle d-block\"\n ></span\n ></span>\n\n <div\n class=\"position-absolute filter-row-filter-wrapper\"\n *ngIf=\"activeFilterCell === col\"\n style=\"top: 100%; right: 0; z-index: 99\"\n [style.left.px]=\"col?.pinned ? 0 : -centerPinnedHeader.scrollLeft\"\n >\n <ng-container\n *ngTemplateOutlet=\"filterMenu; context: { col: col }\"\n ></ng-container>\n </div>\n </div>\n </div>\n </ng-template>\n </div>\n</ng-template>\n\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\n<!-- Body Cell Template -->\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\n<!-- -------------------------------------------------------------------------------------------------------------------------------------------------------------------- -->\n\n<ng-template\n #rowCell\n let-row\n let-columns=\"columns\"\n let-isEven=\"isEven\"\n let-isOdd=\"isOdd\"\n let-isLeftSection=\"isLeft\"\n let-section=\"section\"\n let-rowIndex=\"rowIndex\"\n let-isTotalRow=\"isTotalRow\"\n>\n <!-- Check if row is a group -->\n <ng-container\n *ngTemplateOutlet=\"groupRowTemplate; context: { $implicit: row, depth: 0 }\"\n ></ng-container>\n <ng-template #groupRowTemplate let-row let-depth=\"depth\">\n <ng-container *ngIf=\"row.isGroup; else regularRow\">\n <!-- Group Header -->\n <div\n class=\"group-header-row d-flex align-items-center\"\n [style.height.px]=\"rowHeight\"\n [class.border-below]=\"section !== 'center'\"\n [style.width]=\"\n section === 'center'\n ? (centerScrollableBody?.scrollWidth ?? 0) + 'px'\n : '100%'\n \"\n >\n <div\n *ngIf=\"section == 'left'\"\n class=\"h-100 d-flex\"\n [style.width.px]=\"leftPinnedHeader.offsetWidth - 1\"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n >\n <div\n *ngIf=\"showSerialNumber\"\n style=\"width: 50px\"\n class=\"d-flex align-items-center h-100 border-right justify-content-end pe-2 s-no\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n [style.width.px]=\"55\"\n [style.cursor]=\"\n 'url(' +\n singleSpaAssetsPath +\n 'data-grid/icons/arrow-right.svg), auto'\n \"\n (mousedown)=\"onRowMouseDown(row.__virtualIndex, $event)\"\n (mouseover)=\"onRowMouseOver(row.__virtualIndex, $event)\"\n [style.color]=\"checkboxesColor\"\n >\n {{ getStartIndex() + (row.__virtualIndex - 1) || \"\" }}\n </div>\n <div\n *ngIf=\"showCheckboxes\"\n style=\"width: 50px\"\n class=\"d-flex align-items-center justify-content-center h-100 border-right\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.left-selection-border]=\"\n rowSelectedIndexes.has(row.__virtualIndex)\n \"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n [style.color]=\"checkboxesColor\"\n >\n <input\n style=\"width: 16px; height: 16px\"\n type=\"checkbox\"\n [checked]=\"getGroupCheckedState(row) === true\"\n [indeterminate]=\"getGroupCheckedState(row) === undefined\"\n (change)=\"selectGroupRow($event, row)\"\n />\n\n </div>\n </div>\n\n <div\n *ngIf=\"section == 'center'\"\n [style.width.px]=\"centerPinnedHeader.scrollWidth\"\n [style.minWidth.px]=\"centerPinnedHeader.scrollWidth\"\n class=\"d-flex align-items-center ps-2 h-100 border-below\"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n >\n <div\n class=\"d-flex align-items-center justify-content-between\"\n [style.paddingLeft.px]=\"depth > 0 ? depth * 30 : 0\"\n >\n <span class=\"me-2 filter-icon-wrapper\" (click)=\"toggleExpand(row)\">\n <span\n class=\"data-grid-svg-icon align-items-center d-flex\"\n [inlineSVG]=\"\n row.isExpand\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n ></span>\n </span>\n <strong (click)=\"toggleExpand(row)\" class=\"cursor-pointer\">\n {{ row.groupValue }} ({{ countLeafRows(row) }})\n </strong>\n </div>\n </div>\n\n <div\n *ngIf=\"section == 'right'\"\n [style.width.px]=\"rightPinnedHeader.offsetWidth\"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n ></div>\n </div>\n\n <!-- Recursive Children -->\n <div class=\"group-children\" *ngIf=\"row.isExpand\" [@slideToggle]>\n <ng-container\n *ngFor=\"let child of row.children; let i = index; trackBy: trackById\"\n >\n <ng-container *ngIf=\"child.isGroup; else dataRow\">\n <!-- Recursive call for nested group -->\n <ng-container\n *ngTemplateOutlet=\"\n groupRowTemplate;\n context: { $implicit: child, depth: depth + 1 }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template #dataRow>\n <!-- Regular data row -->\n <ng-container\n *ngTemplateOutlet=\"\n rowCell;\n context: {\n $implicit: child,\n columns: columns,\n isEven: i % 2 === 0,\n isOdd: i % 2 !== 0,\n isLeft: isLeftSection,\n section: section,\n isTotalRow: isTotalRow\n }\n \"\n ></ng-container>\n </ng-template>\n </ng-container>\n </div>\n </ng-container>\n </ng-template>\n\n <!-- Regular row (not a group) -->\n <ng-template #regularRow>\n <div\n class=\"d-flex\"\n [style.height.px]=\"rowHeight\"\n [style.minHeight.px]=\"rowHeight\"\n [style.maxHeight.px]=\"rowHeight\"\n >\n <span\n class=\"d-flex align-items-center justify-content-center cursor-pointer border-below\"\n style=\"min-width: 30px; height: 100%\"\n *ngIf=\"\n section == 'center' && (gridType === 'Assets' || gridType === 'Tasks')\n \"\n [ngStyle]=\"{\n 'background-color': rowSelectedIndexes.has(row.__virtualIndex)\n ? null\n : getBackgroundColor(row, isEven, section)\n }\"\n [class.selected-cell]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n >\n <span\n (click)=\"toggleDetailRowExpand(row)\"\n *ngIf=\"row?.detail?.result?.length || gridType === 'Tasks'\"\n class=\"data-grid-svg-icon filter-icon-wrapper\"\n [inlineSVG]=\"\n isDetailsExpanded(row)\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n ></span>\n </span>\n <div\n [style.min-width.px]=\"\n section == 'center' && groupedColumns?.length ? groupBoxPadding : 0\n \"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n (contextmenu)=\"onRightClick($event, row)\"\n [style.height.px]=\"rowHeight\"\n class=\"data-grid-row h-100\"\n [class.even-row]=\"isEven\"\n [class.odd-row]=\"isOdd\"\n [class.hovered-row]=\"hoveredRowId === (row._id || row.id)\"\n (mouseenter)=\"onRowHover(row)\"\n (mouseleave)=\"onRowLeave()\"\n [ngStyle]=\"{\n 'background-color': getBackgroundColor(row, isEven, section)\n }\"\n [style.minHeight.px]=\"rowHeight\"\n [style.maxHeight.px]=\"rowHeight\"\n ></div>\n <div\n (contextmenu)=\"onRightClick($event, row)\"\n [style.height.px]=\"rowHeight\"\n class=\"data-grid-row\"\n [class.even-row]=\"isEven\"\n [class.odd-row]=\"isOdd\"\n [class.hovered-row]=\"hoveredRowId === (row._id || row.id)\"\n (mouseenter)=\"onRowHover(row)\"\n (mouseleave)=\"onRowLeave()\"\n [ngStyle]=\"{\n 'background-color': getBackgroundColor(row, isEven, section)\n }\"\n >\n <div\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n class=\"select-all-checkbox-cell justify-content-end pe-2 s-no\"\n [style.width.px]=\"55\"\n *ngIf=\"isLeftSection && showSerialNumber\"\n [style.cursor]=\"\n 'url(' +\n singleSpaAssetsPath +\n 'data-grid/icons/arrow-right.svg), auto'\n \"\n (mousedown)=\"onRowMouseDown(row.__virtualIndex, $event)\"\n (mouseover)=\"onRowMouseOver(row.__virtualIndex, $event)\"\n [style.color]=\"checkboxesColor\"\n >\n {{ getStartIndex() + (row.__virtualIndex - 1) }}\n </div>\n <div\n [style.backgroundColor]=\"\n rowSelectedIndexes.has(row.__virtualIndex)\n ? selectedRowsBackgroundColor\n : checkboxesBackgroundColor\n \"\n class=\"select-all-checkbox-cell\"\n *ngIf=\"isLeftSection && showCheckboxes\"\n [class.left-selection-border]=\"\n rowSelectedIndexes.has(row.__virtualIndex)\n \"\n [class.first-row-selected]=\"firstSelectedRow === row.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row.__virtualIndex\"\n [style.minHeight.px]=\"rowHeight - 1\"\n [style.maxHeight.px]=\"rowHeight\"\n >\n <input class=\"serialNoCheckbox\"\n *ngIf=\"hasAnyVisibleColumn\"\n style=\"width: 16px; height: 16px\"\n type=\"checkbox\"\n [checked]=\"isRowSelected(row)\"\n (change)=\"toggleRowSelection(row)\"\n />\n </div>\n\n <!-- Render all columns -->\n <ng-container\n *ngFor=\"\n let col of columns;\n trackBy: trackByField;\n let colIndex = index\n \"\n >\n <ng-container *ngIf=\"col.children?.length > 0; else flatColumn\">\n <ng-container\n *ngFor=\"\n let child of col.children;\n trackBy: trackByField;\n let subColIndex = index\n \"\n >\n <ng-container *ngIf=\"child?.is_visible && !child?.isRowGrouped\">\n <ng-container\n *ngTemplateOutlet=\"\n cellTemplate;\n context: {\n col: child,\n row: row,\n rowIndex: rowIndex,\n colIndex: colIndex,\n subColIndex: subColIndex,\n section: section,\n isTotalRow: isTotalRow\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n\n <ng-template #flatColumn>\n <ng-container *ngIf=\"col?.is_visible && !col?.isRowGrouped\">\n <ng-container\n *ngTemplateOutlet=\"\n cellTemplate;\n context: {\n col: col,\n row: row,\n rowIndex: rowIndex,\n colIndex: colIndex,\n subColIndex: null,\n section: section,\n isTotalRow: isTotalRow\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n </div>\n </div>\n\n <div\n [@slideToggle]\n *ngIf=\"section === 'left' && isDetailsExpanded(row)\"\n class=\"accordion-details\"\n style=\"max-height: 350px; overflow: hidden\"\n [style.maxHeight.px]=\"hasHorizontalScroll ? 339 : 341\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n leftRightNestedPlaceholder;\n context: { $implicit: row }\n \"\n >\n </ng-container>\n </div>\n\n <div\n [@slideToggle]\n *ngIf=\"section === 'center' && isDetailsExpanded(row)\"\n class=\"accordion-details center-section\"\n style=\"\n max-height: 350px;\n overflow-y: hidden;\n overflow-x: auto;\n scrollbar-width: thin;\n \"\n #nestedTable\n [style.width]=\"\n hasRightPinnedColumns\n ? '100%'\n : hasVerticalScroll\n ? 'calc(100% - 12px)'\n : '100%'\n \"\n >\n <ng-container *ngIf=\"gridType == 'Assets'\">\n <ng-container\n *ngTemplateOutlet=\"nestedTableTemplate; context: { $implicit: row }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"gridType == 'Tasks'\">\n <ng-container\n *ngTemplateOutlet=\"\n taskManagementTemplate;\n context: { taskDetails: row }\n \"\n ></ng-container>\n </ng-container>\n </div>\n\n <div\n [@slideToggle]\n *ngIf=\"section === 'right' && isDetailsExpanded(row)\"\n class=\"accordion-details\"\n style=\"max-height: 350px; overflow: hidden\"\n [style.maxHeight.px]=\"hasHorizontalScroll ? 339 : 341\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n leftRightNestedPlaceholder;\n context: { $implicit: row }\n \"\n >\n </ng-container>\n </div>\n </ng-template>\n</ng-template>\n\n<!-- Actual Cell is Here -->\n<ng-template\n #cellTemplate\n let-col=\"col\"\n let-row=\"row\"\n let-section=\"section\"\n let-subColIndex=\"subColIndex\"\n let-rowIndex=\"rowIndex\"\n let-colIndex=\"colIndex\"\n let-isTotalRow=\"isTotalRow\"\n>\n <div\n #cellContainer\n (click)=\"\n editingKey = ''; setActiveCell(row, col); collapseAllExpandedCells()\n \"\n [style.fontWeight]=\"bodyFontWeight\"\n [class.border-right]=\"showVerticalBorder\"\n class=\"cell overflow-visible position-relative data-grid-cell\"\n [attr.field]=\"col.field\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.fontSize.px]=\"bodyTextFontsSize\"\n [style.minHeight.px]=\"rowHeight\"\n [style.maxHeight.px]=\"rowHeight\"\n [class.active-cell]=\"\n isActiveCell(row, col) && !isEditing(row, col) && selectedKeys.size == 1\n \"\n (dblclick)=\"\n $event.stopPropagation();\n $event.preventDefault();\n enableEdit(row, col, false, cellContainer)\n \"\n [class.row-selected]=\"rowSelectedIndexes.has(row.__virtualIndex)\"\n [class.first-row-selected]=\"firstSelectedRow === row?.__virtualIndex\"\n [class.last-row-selected]=\"lastSelectedRow === row?.__virtualIndex\"\n tabindex=\"-1\"\n (keydown.enter)=\"$event.preventDefault(); enableEdit(row, col)\"\n (mousedown)=\"\n startSelection(\n row.__virtualIndex,\n colIndex,\n subColIndex ?? 0,\n col.field,\n $event,\n section\n )\n \"\n (mouseenter)=\"\n extendSelection(\n row.__virtualIndex,\n colIndex,\n subColIndex ?? 0,\n col.field,\n $event,\n section\n )\n \"\n (mouseup)=\"endSelection()\"\n [class.selected-cell]=\"\n isSelected(\n row.__virtualIndex,\n colIndex,\n subColIndex ?? 0,\n col.field,\n section\n )\n \"\n [class.top-border]=\"\n isTopBorder(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.bottom-border]=\"\n isBottomBorder(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.left-border]=\"\n isLeftBorder(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.right-border]=\"\n isRightBorder(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.top-left-corner]=\"\n isTopLeftCorner(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.top-right-corner]=\"\n isTopRightCorner(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.bottom-left-corner]=\"\n isBottomLeftCorner(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n [class.bottom-right-corner]=\"\n isBottomRightCorner(row.__virtualIndex, colIndex, subColIndex, section)\n \"\n >\n <!-- (mousedown)=\"startSelection(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field, $event)\"\n (mouseenter)=\"extendSelection(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field, $event)\"\n (mouseup)=\"endSelection()\"\n [class.selected-cell]=\"isSelected(row.__virtualIndex, colIndex, subColIndex ?? 0, col.field)\" -->\n <div\n class=\"table-cell\"\n [class.active-for-editing]=\"\n isEditing(row, col) &&\n (getNestedValue(row, col.field)?.length === undefined ||\n getNestedValue(row, col.field)?.length <= 50)\n \"\n >\n <div\n (click)=\"$event.stopPropagation()\"\n *ngIf=\"\n isEditing(row, col) &&\n (getNestedValue(row, col.field)?.length === undefined ||\n (getNestedValue(row, col.field)?.length <= 50 &&\n !expandedCells.size));\n else viewMode\n \"\n >\n <ng-container [ngSwitch]=\"col.type\">\n <!-- Text Input -->\n <input\n [style.height.px]=\"rowHeight - 10\"\n *ngSwitchCase=\"'input'\"\n type=\"text\"\n [(ngModel)]=\"row[col.field]\"\n (blur)=\"disableEdit(row, col)\"\n autofocus\n class=\"form-control form-control-sm\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n\n <!-- Number Input -->\n <input\n [style.height.px]=\"rowHeight - 8\"\n *ngSwitchCase=\"'number'\"\n #numberInput=\"ngModel\"\n #numberRef\n (keypress)=\"allowOnlyNumbers($event)\"\n type=\"number\"\n required\n [(ngModel)]=\"row[col.field]\"\n (blur)=\"disableEdit(row, col)\"\n autofocus\n (keydown.enter)=\"numberRef.blur()\"\n class=\"form-control form-control-sm\"\n [ngClass]=\"{\n 'is-invalid': numberInput.invalid\n }\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n\n <!-- Date Input -->\n <input\n [style.height.px]=\"rowHeight - 8\"\n *ngSwitchCase=\"'date'\"\n type=\"date\"\n [(ngModel)]=\"row[col.field]\"\n (blur)=\"disableEdit(row, col)\"\n autofocus\n class=\"form-control form-control-sm\"\n #dateInput=\"ngModel\"\n [ngClass]=\"{\n 'is-invalid': dateInput.invalid\n }\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n\n <!-- Dropdown -->\n <!-- ng-select like dropdown -->\n <div\n *ngSwitchCase=\"'dropdown'\"\n class=\"dropdown w-100\"\n (blur)=\"disableEdit(row, col)\"\n >\n <!-- Trigger -->\n <button\n class=\"form-select form-select-sm text-start w-100 text-ellipsis\"\n type=\"button\"\n data-bs-toggle=\"dropdown\"\n aria-expanded=\"false\"\n [style.minHeight.px]=\"rowHeight - 10\"\n data-bs-display=\"static\"\n (mousedown)=\"$event.stopPropagation()\"\n >\n <ng-container>\n {{\n getNestedValue(row, col.field)?.value ||\n getNestedValue(row, col.field)?.name ||\n getNestedValue(row, col.field)\n }}\n </ng-container>\n <ng-template #placeholder> Select options... </ng-template>\n </button>\n\n <!-- Menu -->\n <div\n class=\"dropdown-menu w-100 p-0 cell-editing-dropdown-menu rounded-3\"\n [class.show]=\"isEditing(row, col)\"\n >\n <!-- Search -->\n <div class=\"px-2 py-1 editing-dropdown-search-input\">\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Search...\"\n [(ngModel)]=\"editinDropdownSearch\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n </div>\n\n <!-- Options -->\n <!-- <div\n class=\"cell-editin-dropdown\"\n style=\"max-height: 200px; overflow: auto\"\n >\n <div\n (click)=\"\n setNestedValue(row, col, option, true); editingKey = null\n \"\n class=\"px-2 py-1 d-flex align-items-center deopdown-item\"\n *ngFor=\"\n let option of col.column_dropdown_value\n | filter : editinDropdownSearch: 'value'\n \"\n >\n <label\n class=\"form-check-label d-flex align-items-center mb-0 cursor-pointer\"\n [for]=\"col.field + '-' + option.value || option\"\n >\n {{ option.value || option }}\n </label>\n </div>\n </div> -->\n <cdk-virtual-scroll-viewport \n itemSize=\"35\" \n class=\"dropdown-viewport\"\n style=\"height: 120px\"\n >\n <div\n class=\"px-2 py-1 d-flex align-items-center dropdown-item\"\n *cdkVirtualFor=\"\n let option of col.column_dropdown_value \n | filter : editinDropdownSearch : 'value'\n \"\n (click)=\"setNestedValue(row, col, option, true); editingKey = null\"\n >\n <label\n class=\"form-check-label d-flex align-items-center mb-0 cursor-pointer\"\n [for]=\"col.field + '-' + (option.value || option)\"\n >\n {{ option.value || option }}\n </label>\n </div>\n </cdk-virtual-scroll-viewport>\n\n </div>\n </div>\n\n <input\n *ngSwitchCase=\"'email'\"\n [style.height.px]=\"rowHeight - 10\"\n [style.maxHeight.px]=\"rowHeight - 10\"\n #emailModel=\"ngModel\"\n #emailInput\n type=\"email\"\n [(ngModel)]=\"row[col.field]\"\n name=\"{{ col.field }}\"\n required\n pattern=\"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\"\n (blur)=\"disableEdit(row, col, emailModel)\"\n (keydown.enter)=\"\n emailModel.control.markAsTouched(); emailInput.blur()\n \"\n autofocus\n class=\"form-control form-control-sm\"\n [ngClass]=\"{\n 'is-invalid': emailModel.invalid\n }\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n <!-- Default fallback -->\n <input\n *ngSwitchDefault\n [style.height.px]=\"rowHeight - 10\"\n [style.maxHeight.px]=\"rowHeight - 10\"\n #textModel=\"ngModel\"\n #textInput\n type=\"text\"\n [(ngModel)]=\"row[col.field]\"\n name=\"{{ col.field }}\"\n required\n (blur)=\"disableEdit(row, col, textModel)\"\n (keydown.enter)=\"\n textModel.control.markAsTouched(); textInput.blur()\n \"\n autofocus\n class=\"form-control form-control-sm\"\n [ngClass]=\"{\n 'is-invalid': textModel.invalid\n }\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n </ng-container>\n </div>\n\n <!-- Display mode -->\n <ng-template #viewMode>\n <div\n class=\"d-flex justify-content-between align-items-center overflow-hidden\"\n [ngClass]=\"getCellClasses(col, getNestedValue(row, col.field))\"\n >\n <!-- Field icon (for Tasks grid) -->\n <ng-container\n *ngIf=\"gridType === 'Tasks' && iconMap[col.field] && !isTotalRow\"\n >\n <span\n class=\"cursor-pointer me-2\"\n (click)=\"$event.preventDefault(); $event.stopPropagation()\"\n [inlineSVG]=\"iconMap[col.field](row, col)\"\n ></span>\n </ng-container>\n\n <!-- \u2705 Custom cell renderer support -->\n <ng-container *ngIf=\"col.cellRenderer; else defaultCell\">\n <ng-container\n [cellRenderInit]=\"col.cellRenderer\"\n [rowData]=\"row\"\n [colData]=\"col\"\n [cellValue]=\"getNestedValue(row, col?.field)\"\n (cellEvent)=\"onCellEvent($event)\"\n >\n </ng-container>\n </ng-container>\n\n <!-- \uD83E\uDDFE Default text-based cell rendering -->\n <ng-template #defaultCell>\n <div\n #cellText\n class=\"text-ellipsis flex-grow-1\"\n [title]=\"getCellTitle(row, col)\"\n >\n <!-- Normal cell -->\n <ng-container\n *ngIf=\"\n col.type !== 'image' &&\n col.field != 'image' &&\n col.field != 'invoice.invoice_image' &&\n !isTotalRow\n \"\n >\n <ng-container *ngIf=\"col.is_amount\">{{\n currencySymbol\n }}</ng-container>\n {{getCellTitle(row, col)}}\n </ng-container>\n\n <!-- Total row -->\n <ng-container *ngIf=\"isTotalRow\">\n {{ getTotalAmount(col) }}\n </ng-container>\n\n <!-- Invoice Image -->\n <ng-container *ngIf=\"col.field == 'invoice.invoice_image'\">\n <div style=\"display: flex; align-items: center; zoom: 0.7\">\n <span\n title=\"{{ getNestedValue(row, col.field) || 'Attachment' }}\"\n (click)=\"downloadAttchment(getNestedValue(row, col.field))\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/document-icons/' +\n getExtention(getNestedValue(row, col.field)) +\n '.svg'\n \"\n ></span>\n </div>\n </ng-container>\n\n <!-- Image cell -->\n <ng-container *ngIf=\"col.type == 'image' && !isTotalRow\">\n <ng-container\n *ngTemplateOutlet=\"\n defaultImagePlaceholder;\n context: { row: row, col: col }\n \"\n ></ng-container>\n </ng-container>\n </div>\n <span\n *ngIf=\"\n (!col?.cellRenderer && showCellDetailsBox &&\n getNestedValue(row, col.field)?.length > 50 && col.type !== 'image') ||\n (isNestedValueArray(row, col.field) &&\n getNestedValue(row, col.field)?.length > 1)\n \"\n class=\"toggle-icon data-grid-svg-icon ms-2 cursor-pointer\"\n [inlineSVG]=\"\n isExpanded(row, col)\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n (click)=\"\n $event.stopPropagation();\n toggleExpandOfLongCellText(row, col, columns, true)\n \"\n (dblclick)=\"$event.preventDefault(); $event.stopPropagation()\"\n ></span>\n </ng-template>\n <!-- Expand / Collapse icon -->\n </div>\n\n <!-- Expanded text -->\n <div\n class=\"position-absolute w-100 expanded-box\"\n *ngIf=\"isExpanded(row, col)\"\n [style.zIndex]=\"getZIndex(row, col)\"\n style=\"top: 100%; left: 0\"\n [attr.id]=\"(row.id || row._id) + '-' + (col.id || col._id)\"\n [class.invisible]=\"!showDetailsBox\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n fullTextTemplate;\n context: {\n row: row,\n col: col,\n isArray: isNestedValueArray(row, col.field)\n }\n \"\n ></ng-container>\n </div>\n </ng-template>\n </div>\n </div>\n</ng-template>\n\n<!-- Headers Action List On clicking three dots -->\n\n<ng-template\n #columnMenu\n let-col=\"col\"\n let-isNestedTable=\"isNestedTable\"\n let-columns=\"columns\"\n let-section=\"section\"\n>\n <div\n class=\"column-menu three-dots-col-menu\"\n [class.visually-hidden]=\"isMenueHidden\"\n *ngIf=\"activeCol && !isThreeDotsFilterOpen\"\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\n (click)=\"$event.stopPropagation()\"\n [style.color]=\"headerTextColor\"\n >\n <!-- Sort Ascending -->\n <ng-container *ngIf=\"clickedOnSortIcon\">\n <div class=\"sorting_dropdown\" [class.disable-sorting]=\"!col.is_sortable\">\n <!-- <span class=\"muted-text fs-7\" style=\"margin-left: 12px\">Sort</span> -->\n \n <!-- *ngIf=\"\n columnThreedotsMunuConfig?.showAscending &&\n (sortingConfig?.field != col.field ||\n sortingConfig?.order_by == 'desc')\n \" -->\n <div\n class=\"column-menu-item\" [class.active-sort]=\"sortingConfig?.field === col.field && sortingConfig?.order_by === 'asc'\"\n (click)=\"sortAsc(activeCol);\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/headerSortingIcon.svg'\"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span>\n Sort Ascending\n <span *ngIf=\"sortingConfig?.field === col.field && sortingConfig?.order_by === 'asc'\" [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickBlueIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown no-stroke\" style=\"margin-left: auto;\"\n ></span>\n </div>\n\n <!-- Sort Descending -->\n \n <!-- *ngIf=\"\n columnThreedotsMunuConfig?.showDescending &&\n (sortingConfig?.field != col.field ||\n sortingConfig?.order_by == 'asc')\n \" -->\n <div\n class=\"column-menu-item\" [class.active-sort]=\"sortingConfig?.field === col.field && sortingConfig?.order_by === 'desc'\"\n (click)=\"sortDesc(activeCol);\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/headerSortingIcon1.svg'\"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span>\n Sort Descending\n <span *ngIf=\"sortingConfig?.field === col.field && sortingConfig?.order_by === 'desc'\" [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickBlueIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown no-stroke\" style=\"margin-left: auto;\"\n ></span>\n </div>\n\n <div\n *ngIf=\"\n sortingConfig?.field === col.field &&\n (sortingConfig?.order_by === 'asc' ||\n sortingConfig?.order_by === 'desc')\n \"\n class=\"column-menu-item\"\n (click)=\"resetSort(activeCol)\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/resetSortIconNew.svg'\n \"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span>\n Reset Sort\n </div>\n </div>\n </ng-container>\n <!-- <div class=\"py-2 border-below three-dots-filter\">\n <div\n *ngIf=\"columnThreedotsMunuConfig?.showFilter\"\n class=\"column-menu-item three-dots-filter\"\n (click)=\"openFilteronThreeDotsClick(col)\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n Filter\n </div>\n </div> -->\n\n <ng-container *ngIf=\"!clickedOnSortIcon\">\n <div class=\"sorting_dropdown\">\n <!-- <span class=\"muted-text fs-7\" style=\"margin-left: 12px\">Pin</span> -->\n \n <!-- *ngIf=\"columnThreedotsMunuConfig?.showPinleft && col?.pinned !== 'left'\" -->\n <div\n class=\"column-menu-item\" [class.active-sort]=\"col?.pinned == 'left'\"\n (click)=\"\n $event.stopPropagation();\n updateColumnPinInSourceByField(\n activeCol,\n 'left',\n isNestedTable,\n columns\n )\n \"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pinLeftIconNew.svg'\"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span\n >Pin Left\n <span *ngIf=\"col?.pinned == 'left'\" [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickBlueIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown no-stroke\" style=\"margin-left: auto;\"\n ></span>\n </div>\n <!-- *ngIf=\"\n columnThreedotsMunuConfig?.showPinright && col?.pinned !== 'right'\n \" -->\n <div [class.active-sort]=\"col?.pinned == 'right'\"\n class=\"column-menu-item\"\n (click)=\"\n $event.stopPropagation();\n updateColumnPinInSourceByField(\n activeCol,\n 'right',\n isNestedTable,\n columns\n )\n \"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/pinRightIconNew.svg'\"\n class=\"data-grid-svg-icon data-grid-svg-icon me-2 setting_dropdown\"\n ></span\n >Pin Right\n <span *ngIf=\"col?.pinned == 'right'\" [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/tickBlueIconNew.svg'\"\n class=\"data-grid-svg-icon setting_dropdown no-stroke\" style=\"margin-left: auto;\"\n ></span>\n </div>\n\n <div\n *ngIf=\"col?.pinned\"\n class=\"column-menu-item\"\n (click)=\"\n $event.stopPropagation();\n updateColumnPinInSourceByField(\n activeCol,\n null,\n isNestedTable,\n columns\n )\n \"\n >\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/layout-three-columns.svg'\"\n class=\"data-grid-svg-icon me-2 setting_dropdown d-flex align-items-center justify-content-center\"\n ></span\n >Unpin\n </div>\n </div>\n </ng-container>\n <!-- <div\n *ngIf=\"columnThreedotsMunuConfig?.showAutosizeThisColumn\"\n class=\"column-menu-item\"\n (click)=\"autosizeColumn(activeCol)\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrows-expand-vertical.svg'\n \"\n class=\"me-2\"\n ></span>\n Autosize This Column\n </div> -->\n\n <!-- Autosize All Columns -->\n <!-- <div\n *ngIf=\"columnThreedotsMunuConfig?.showAutosizeAllColumns\"\n class=\"column-menu-item\"\n (click)=\"autosizeAllColumns()\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrows-angle-expand.svg'\n \"\n class=\"data-grid-svg-icon me-2\"\n ></span\n >Autosize All Columns\n </div> -->\n\n <!-- Group By -->\n <div\n *ngIf=\"showRowsGrouping\"\n class=\"column-menu-item\"\n (click)=\"groupBy(activeCol)\"\n [class.disable-sorting]=\"!col.is_groupable\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/diagram-3.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n Group by {{ col.header }}\n </div>\n\n <!-- Choose Columns -->\n <div\n *ngIf=\"columnThreedotsMunuConfig?.showChoseColumns\"\n class=\"column-menu-item\"\n (click)=\"chooseColumns()\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/ui-checks-grid.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n Choose Columns\n </div>\n\n <!-- Reset Columns -->\n <div\n *ngIf=\"columnThreedotsMunuConfig?.showResetColumns\"\n class=\"column-menu-item\"\n (click)=\"resetColumns()\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrow-counterclockwise.svg'\n \"\n class=\"data-grid-svg-icon me-2\"\n ></span\n >Reset Columns\n </div>\n </div>\n <div\n @slideToggle\n *ngIf=\"isThreeDotsFilterOpen\"\n class=\"three-dots-col-menu position-relative\"\n [style.right.px]=\"section == 'right' ? null : col.width - 45\"\n [class.visually-hidden]=\"isMenueHidden\"\n >\n <ng-container\n *ngTemplateOutlet=\"filterMenu; context: { col: col }\"\n ></ng-container>\n </div>\n</ng-template>\n\n<!-- Filter Menue -->\n<ng-template #filterMenu let-col=\"col\">\n <div\n class=\"filter-menu-container filter-menu dropdown_outer\"\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\n >\n <!-- Dropdown Type -->\n <ng-container *ngIf=\"col.type === 'dropdown'; else textFilter\">\n <div class=\"filter-dropdown-section p-1\">\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Search...\"\n type=\"search\"\n [(ngModel)]=\"addFilterColumnInput\"\n />\n\n <div class=\"form-check mb-1 mt-2 ps-4 ms-1\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [checked]=\"isAllSideFilterOptionsSelected(col)\"\n (change)=\"toggleSelectAllSideFilters(col, $event)\"\n id=\"selectAll_{{ col.field }}\"\n />\n <label class=\"form-check-label\" for=\"selectAll_{{ col.field }}\">\n Select All\n </label>\n </div>\n\n <!-- <div class=\"dropdown-options ps-1\">\n <div\n class=\"form-check mb-1\"\n *ngFor=\"\n let option of selectedColumnForFilter?.column_dropdown_value\n | filter : addFilterColumnInput : 'value';\n trackBy: trackById;\n let i = index\n \"\n >\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [id]=\"i\"\n [checked]=\"\n currentFilterSelectedIds.has(option?.id ?? option?._id ?? option)\n \"\n (change)=\"toggleSelectionInFilter(option)\"\n />\n <label class=\"form-check-label fw-semibold\" [for]=\"i\">\n {{ option?.value ?? option?.name ?? option }}\n </label>\n </div>\n </div> -->\n <cdk-virtual-scroll-viewport\n itemSize=\"32\"\n class=\"filter-viewport\"\n style=\"height: 120px\"\n >\n <div\n class=\"form-check mb-1 ms-1\"\n *cdkVirtualFor=\"\n let option of selectedColumnForFilter?.column_dropdown_value\n | filter : addFilterColumnInput : 'value';\n trackBy: trackById\n \"\n >\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [id]=\"option?.id ?? option?._id ?? option\"\n [checked]=\"\n currentFilterSelectedIds.has(option?.id ?? option?._id ?? option)\n \"\n (change)=\"toggleSelectionInFilter(option)\"\n />\n\n <label\n class=\"form-check-label fw-semibold\"\n [for]=\"option?.id ?? option?._id ?? option\"\n >\n {{ option?.value ?? option?.name ?? option }}\n </label>\n </div>\n </cdk-virtual-scroll-viewport>\n </div>\n </ng-container>\n\n <!-- Text Filter Section -->\n <ng-template #textFilter>\n <div class=\"filter-text-section\">\n <div class=\"form-group mb-2\">\n <select\n class=\"form-select form-select-sm custom-select\"\n [(ngModel)]=\"firstCondition\"\n >\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"before\">Less Then </option>\n <option value=\"after\">Greater Then </option>\n <option value=\"less_then_equal\">less then Equal to</option>\n <option value=\"greater_then_equal\">Greater then Equal to </option>\n </ng-container>\n </select>\n </div>\n\n <input\n [type]=\"col.type == 'string' ? 'text' : col.type\"\n class=\"form-control form-control-sm mb-3\"\n placeholder=\"Value\"\n [(ngModel)]=\"firstValue\"\n #filterMenueTextchInput\n (keydown.enter)=\"applyDropdownFilter()\"\n />\n\n <div class=\"form-group mb-3 d-flex flex-row\">\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"condition\"\n value=\"and\"\n id=\"and_{{ col.field }}\"\n (change)=\"cdr.detectChanges()\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"and_{{ col.field }}\"\n >AND</label\n >\n </div>\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1 gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"condition\"\n value=\"or\"\n id=\"or_{{ col.field }}\"\n (change)=\"cdr.detectChanges()\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"or_{{ col.field }}\"\n >OR</label\n >\n </div>\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1 gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"condition\"\n value=\"none\"\n id=\"none_{{ col.field }}\"\n (change)=\"cdr.detectChanges()\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"none_{{ col.field }}\"\n >None</label\n >\n </div>\n </div>\n <div @slideToggle *ngIf=\"firstValue && condition != 'none'\">\n <div class=\"form-group mb-2\">\n <select\n class=\"form-select form-select-sm custom-select\"\n [(ngModel)]=\"secondCondition\"\n >\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"before\">Less Then </option>\n <option value=\"after\">Greater Then </option>\n <option value=\"less_then_equal\">less then Equal to</option>\n <option value=\"greater_then_equal\">Greater then Equal to </option>\n </ng-container>\n </select>\n </div>\n\n <input\n [type]=\"col.type == 'string' ? 'text' : col.type\"\n class=\"form-control form-control-sm mb-3\"\n placeholder=\"Second Value\"\n [(ngModel)]=\"secondValue\"\n />\n </div>\n </div>\n </ng-template>\n\n <!-- Actions -->\n <div class=\"d-flex gap-2 mt-2\">\n <div\n class=\"primary_btn_new flex justify-content-center align-items-center w-100\"\n style=\"height: 30px\"\n (click)=\"applyDropdownFilter()\"\n >\n Apply\n </div>\n <div\n class=\"cancel_btn_new d-flex justify-content-center align-items-center w-100\"\n style=\"height: 30px\"\n (click)=\"resetSideFilter(col)\"\n >\n Reset\n </div>\n </div>\n </div>\n</ng-template>\n\n<!-- Side Menue -->\n\n<!-- Column Pannel / Pivot Mode / Searching -->\n\n<ng-template #columnPannel>\n <div class=\"column-panel-header\">\n <!-- Pivot Toggle -->\n <div\n class=\"form-check form-switch d-flex align-items-center mb-2 pivot-mode px-5 ms-2 d-none\"\n >\n <input\n class=\"form-check-input me-2\"\n type=\"checkbox\"\n id=\"pivotToggle\"\n [(ngModel)]=\"pivotMode\"\n />\n <label class=\"form-check-label\" for=\"pivotToggle\">Pivot Mode</label>\n </div>\n\n <!-- Select All & Search -->\n <div class=\"d-flex align-items-center mb-2 px-3 mt-3\">\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n accordionState === 'all'\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : accordionState === 'some'\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n (click)=\"toggleAllAccordions()\"\n ></span>\n </span>\n <input\n type=\"checkbox\"\n class=\"form-check-input me-2\"\n [checked]=\"allColumnsSelected()\"\n (change)=\"toggleAllColumnsVisibility()\"\n />\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Search columns...\"\n [(ngModel)]=\"columnSearch\"\n />\n </div>\n\n <!-- Separator -->\n <hr class=\"my-2\" />\n </div>\n</ng-template>\n\n<!-- Right Columns Menue -->\n\n<!-- Column Panel Item Template -->\n<ng-template #columnPanelItem let-col=\"col\">\n <!-- Group Column -->\n <ng-container *ngIf=\"col.children?.length\">\n <div class=\"column-group d-flex align-items-center mb-2\">\n <span class=\"filter-icon-wrapper me-2\">\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n [class.rotate]=\"col.expanded\"\n (click)=\"col.expanded = !col.expanded\"\n ></span>\n </span>\n <input\n type=\"checkbox\"\n class=\"form-check-input me-2\"\n [id]=\"'group_' + col.header\"\n [checked]=\"isColumnVisible(col)\"\n (change)=\"toggleGroupVisibility(col)\"\n />\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center me-2\"\n ></span>\n <label\n class=\"d-flex align-items-center mb-0 w-100\"\n [for]=\"'group_' + col.header\"\n style=\"cursor: pointer\"\n >\n <span class=\"text-truncate\">{{ col.header }}</span>\n </label>\n </div>\n <div *ngIf=\"col.expanded\" class=\"ps-4\">\n <ng-container *ngFor=\"let child of col.children; trackBy: trackByField\">\n <ng-container\n *ngTemplateOutlet=\"columnPanelItem; context: { col: child }\"\n ></ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- Leaf Column -->\n <ng-container *ngIf=\"!col.children?.length\">\n <div class=\"d-flex align-items-center mb-2\">\n <span class=\"me-2\" style=\"width: 1.5rem\"></span>\n <input\n type=\"checkbox\"\n class=\"form-check-input me-2\"\n [(ngModel)]=\"col.is_visible\"\n [id]=\"'col_' + col.field\"\n (change)=\"onSideMenuColumnsVisibilityChange()\"\n />\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center me-2\"\n ></span>\n <label\n class=\"d-flex align-items-center mb-0 w-100\"\n [for]=\"'col_' + col.field\"\n style=\"cursor: pointer\"\n >\n <span class=\"text-truncate\">{{ col.header }}</span>\n </label>\n </div>\n </ng-container>\n</ng-template>\n\n<!-- Columns Side Filter -->\n<ng-template #sideFilters>\n <div class=\"py-3 px-2 pe-3 h-100\">\n <div class=\"d-flex align-items-center mb-2\">\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n filterAccordionState === 'all'\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : filterAccordionState === 'some'\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n (click)=\"toggleAllFilterAccordions()\"\n ></span>\n </span>\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Search...\"\n [(ngModel)]=\"columnSearch\"\n />\n </div>\n <div\n class=\"overflow-auto side-filter-columns-wrapper\"\n style=\"height: calc(100% - 70px); scrollbar-width: thin\"\n >\n <ng-container\n *ngFor=\"\n let col of columns | filter : columnSearch : 'header';\n trackBy: trackByField\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"filterPannelItem; context: { col: col }\"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #filterPannelItem let-col=\"col\">\n <!-- Group Column -->\n <ng-container *ngIf=\"col.children?.length\">\n <div\n class=\"column-group d-flex align-items-center mb-2\"\n *ngIf=\"col.type !== 'image'\"\n >\n <!-- Chevron toggle -->\n <span class=\"filter-icon-wrapper me-2\">\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n [class.rotate]=\"col.expandedFilter\"\n (click)=\"col.expandedFilter = !col.expandedFilter\"\n ></span>\n </span>\n\n <!-- Group label toggle -->\n <label\n class=\"d-flex align-items-center mb-0 w-100\"\n style=\"cursor: pointer\"\n (click)=\"col.expandedFilter = !col.expandedFilter\"\n >\n <span class=\"fw-bold text-truncate\"\n >{{ col.header }}\n <span\n class=\"text-primary ms-1\"\n *ngIf=\"col?.query?._ids?.length || col?.query?._first_value\"\n >*</span\n >\n </span>\n </label>\n </div>\n\n <!-- Children columns -->\n <div *ngIf=\"col.expandedFilter\" class=\"ps-4\">\n <ng-container *ngFor=\"let child of col.children; trackBy: trackByField\">\n <ng-container\n *ngTemplateOutlet=\"filterPannelItem; context: { col: child }\"\n ></ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- Leaf Column -->\n <ng-container *ngIf=\"!col.children?.length\">\n <div class=\"d-flex align-items-center mb-2\" *ngIf=\"col.type !== 'image'\">\n <span\n class=\"me-2 filter-icon-wrapper me-2\"\n (click)=\"col.expandedFilter = !col.expandedFilter\"\n >\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n [class.rotate]=\"col.expandedFilter\"\n ></span>\n </span>\n\n <label\n class=\"d-flex align-items-center mb-0 w-100\"\n style=\"cursor: pointer\"\n (click)=\"col.expandedFilter = !col.expandedFilter\"\n >\n <span class=\"text-truncate fw-bold\">{{ col.header }}</span>\n </label>\n </div>\n\n <!-- Show filter when expanded -->\n <div *ngIf=\"col.expandedFilter\" class=\"ps-4 pe-3\">\n <ng-container\n *ngTemplateOutlet=\"sideNestedFilter; context: { col: col }\"\n ></ng-container>\n </div>\n </ng-container>\n</ng-template>\n\n<!-- Side Nested Filters -->\n<ng-template #sideNestedFilter let-col=\"col\">\n <div class=\"\">\n <!-- Dropdown Type -->\n <ng-container *ngIf=\"col.type === 'dropdown'; else textFilter\">\n <div class=\"p-1\">\n <!-- Search -->\n <input\n type=\"text\"\n class=\"form-control form-control-sm mb-2\"\n placeholder=\"Search...\"\n [(ngModel)]=\"sideNestedFilterSearch\"\n />\n\n <!-- Select All -->\n <div class=\"form-check mb-1 ms-1\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [checked]=\"\n col.query?._ids?.length == col?.column_dropdown_value?.length\n \"\n (change)=\"toggleSelectAllSideFilters(col, $event)\"\n id=\"selectAll_{{ col.field }}\"\n />\n <label class=\"form-check-label\" for=\"selectAll_{{ col.field }}\">\n Select All\n </label>\n </div>\n\n <!-- Options -->\n <!-- <div class=\"dropdown-options\">\n <div\n class=\"form-check mb-1 ms-1\"\n *ngFor=\"\n let option of col?.column_dropdown_value\n | filter : sideNestedFilterSearch : 'value'\n \"\n >\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [value]=\"option\"\n [checked]=\"\n col.query?._ids?.includes(option?._id || option?.id || option)\n \"\n (change)=\"onOptionToggle(col, option)\"\n id=\"option_{{ col.field }}_{{\n option?.id || option?._id || option\n }}\"\n />\n <label\n class=\"form-check-label\"\n [for]=\"\n 'option_' +\n col.field +\n '_' +\n (option?.id || option?._id || option)\n \"\n >\n {{ option.value || option }}\n </label>\n </div>\n </div> -->\n <cdk-virtual-scroll-viewport\n itemSize=\"32\"\n class=\"dropdown-viewport\"\n style=\"height: 120px\"\n >\n <div\n class=\"form-check mb-1 ms-1\"\n *cdkVirtualFor=\"\n let option of col?.column_dropdown_value\n | filter : sideNestedFilterSearch : 'value'\n \"\n >\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [value]=\"option\"\n [checked]=\"\n col.query?._ids?.includes(option?._id || option?.id || option)\n \"\n (change)=\"onOptionToggle(col, option)\"\n id=\"option_{{ col.field }}_{{\n option?.id || option?._id || option\n }}\"\n />\n\n <label\n class=\"form-check-label\"\n [for]=\"\n 'option_' +\n col.field +\n '_' +\n (option?.id || option?._id || option)\n \"\n >\n {{ option.value || option }}\n </label>\n </div>\n </cdk-virtual-scroll-viewport>\n\n\n <!-- Actions -->\n <!-- <div class=\"d-flex gap-2 mt-2\">\n <div\n class=\"btn btn-sm btn-primary d-flex justify-content-center align-items-center\"\n style=\"height: 22px;\"\n (click)=\"applySideFilter(col)\"\n >\n Apply\n </div>\n <div\n class=\"btn btn-sm btn-secondary d-flex justify-content-center align-items-center\" \n style=\"height: 22px;\"\n (click)=\"resetSideFilter(col)\"\n >\n Reset\n </div>\n </div> -->\n </div>\n </ng-container>\n\n <!-- Text Filter Section -->\n <ng-template #textFilter>\n <div class=\"filter-text-section\">\n <div class=\"form-group mb-2\">\n <select\n class=\"form-select form-select-sm\"\n [(ngModel)]=\"col.query.first_condition\"\n >\n <ng-container *ngIf=\"col.type !== 'date'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"col.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n </select>\n </div>\n\n <input\n [type]=\"col.type == 'date' ? 'date' : 'text'\"\n class=\"form-control form-control-sm mb-3\"\n placeholder=\"Value\"\n [(ngModel)]=\"col!.query!.first_value\"\n />\n\n <div\n class=\"form-group mb-3 d-flex flex-row muted\"\n style=\"font-size: 14px\"\n >\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"col!.query.condition\"\n value=\"and\"\n id=\"and_{{ col.field }}\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"and_{{ col.field }}\"\n >AND</label\n >\n </div>\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"col!.query.condition\"\n value=\"or\"\n id=\"or_{{ col.field }}\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"or_{{ col.field }}\"\n >OR</label\n >\n </div>\n <div\n class=\"form-check form-check-inline m-0 col-4 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input filter-radio-inputs\"\n type=\"radio\"\n name=\"condition\"\n [(ngModel)]=\"col!.query.condition\"\n value=\"none\"\n id=\"none_{{ col.field }}\"\n />\n <label\n class=\"nnonem-check-label mb-0 mt-1\"\n for=\"none_{{ col.field }}\"\n >None</label\n >\n </div>\n </div>\n <ng-container\n *ngIf=\"col?.query?.first_value && col?.query?.condition !== 'none'\"\n >\n <div class=\"form-group mb-2\">\n <select\n class=\"form-select form-select-sm\"\n [(ngModel)]=\"col!.query.second_condition\"\n >\n <ng-container *ngIf=\"col.type !== 'date'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"col.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n </select>\n </div>\n\n <input\n [type]=\"col.type == 'date' ? 'date' : 'text'\"\n class=\"form-control form-control-sm mb-3\"\n placeholder=\"Second Value\"\n [(ngModel)]=\"col!.query.second_value\"\n />\n </ng-container>\n <!-- <div class=\"d-flex gap-2\">\n <div class=\"btn btn-sm btn-primary d-flex justify-content-center align-items-center\" style=\"height: 22px;\" (click)=\"applyDropdownFilter()\">apply</div>\n <div class=\"btn btn-sm btn-secondary d-flex justify-content-center align-items-center\" style=\"height: 22px;\" (click)=\"applyDropdownFilter()\">reset</div>\n\n </div> -->\n </div>\n </ng-template>\n <div\n class=\"d-flex justify-content-center gap-2 border-top\"\n style=\"height: 38px\"\n >\n <button\n type=\"button\"\n style=\"max-height: 30px\"\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\n (click)=\"$event.stopPropagation(); removeSideFilter(col)\"\n >\n <span>Clear</span>\n </button>\n <button\n type=\"button\"\n style=\"max-height: 30px\"\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\n (click)=\"applySideFilter(col)\"\n [class.disabled]=\"(col?.query.condition !== 'none' && !col?.query?.second_value)\"\n [class.pe-none]=\"(col!?.query.condition !== 'none' && !col?.query?.second_value)\"\n >\n <span style=\"margin-top: -1px\">Apply</span>\n </button>\n </div>\n </div>\n</ng-template>\n\n<!-- Centr Overlay for showing the chose columns -->\n\n<div *ngIf=\"showColumnPanel\" class=\"custom-modal-overlay\">\n <div\n class=\"custom-modal-content\"\n [style.backgroundColor]=\"dropdownsBackgroundColor\"\n (click)=\"$event.stopPropagation()\"\n >\n <ng-container *ngTemplateOutlet=\"modalColumnPannel\"></ng-container>\n </div>\n</div>\n\n<!-- The existing ng-template you provided -->\n<ng-template #modalColumnPannel>\n <div class=\"column-panel-header\">\n <div\n class=\"d-flex justify-content-between align-items-center px-2 ps-3 rounded-top-2 moda-header\"\n [style.height.px]=\"48\"\n >\n Choose Columns\n <span class=\"filter-icon-wrapper\" (click)=\"closeModalColumnPanel()\"\n ><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/x.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span\n ></span>\n </div>\n <hr class=\"my-0\" />\n <div>\n <div class=\"d-flex align-items-center px-2 pe-3\" [style.height.px]=\"48\">\n <span class=\"filter-icon-wrapper me-2\" *ngIf=\"showColumnsGrouping\">\n <span\n class=\"toggle-icon data-grid-svg-icon\"\n [inlineSVG]=\"\n accordionState === 'all'\n ? singleSpaAssetsPath + 'data-grid/icons/chevron-down.svg'\n : accordionState === 'some'\n ? singleSpaAssetsPath + 'data-grid/icons/dash.svg'\n : singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\n \"\n (click)=\"toggleAllAccordions()\"\n ></span>\n </span>\n <input\n type=\"checkbox\"\n class=\"form-check-input me-2\"\n [checked]=\"allColumnsSelected()\"\n (change)=\"toggleAllColumnsVisibility()\"\n />\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Search columns...\"\n [(ngModel)]=\"choseColumnsSearch\"\n />\n </div>\n\n <hr class=\"mt-0 mb-1\" />\n <div class=\"px-2 overlay-scrollable\">\n <ng-container\n *ngFor=\"\n let col of columns | filter : choseColumnsSearch : 'header';\n trackBy: trackByField\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"columnPanelItem; context: { col: col }\"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #sideMenuRowGroups>\n <div class=\"d-flex flex-column h-100 d-none\">\n <div class=\"px-3 h-100\">\n <div class=\"d-flex gap-3 mb-4\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <span>Row Groups</span>\n </div>\n <div class=\"h-50\">\n <div\n class=\"px-3 py-2 border-dashed h-100 d-flex justify-content-center align-items-center\"\n style=\"font-size: 14px\"\n >\n Drag here to set row Groups\n </div>\n </div>\n </div>\n\n <hr class=\"mt-4\" />\n\n <div class=\"px-3 h-100\">\n <div class=\"d-flex gap-3 mb-4\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/justify.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <span>Values</span>\n </div>\n <div class=\"h-50 d-flex\">\n <div\n class=\"px-3 py-2 border-dashed h-100 d-flex justify-content-center align-items-center\"\n style=\"font-size: 14px\"\n >\n Drag here aggregate\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n\n<!-- *************************************************** -->\n<!-- *************************************************** -->\n<!-- *************************************************** -->\n<!-- Drag Preview Template -->\n<!-- *************************************************** -->\n<!-- *************************************************** -->\n<ng-template #dragPreview let-col>\n <div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ col.header }}</div>\n </div>\n</ng-template>\n\n<!-- Drag Placeholder Template -->\n<ng-template\n #dragPlaceholder\n let-col\n let-i=\"index\"\n let-section=\"section\"\n let-draggingInGroupArea=\"draggingInGroupArea\"\n>\n <div *ngIf=\"!draggingInGroupArea\">\n <div\n *ngTemplateOutlet=\"\n headerCell;\n context: { $implicit: col, index: i, section: section }\n \"\n ></div>\n </div>\n <div *ngIf=\"draggingInGroupArea\">New Placeholder</div>\n</ng-template>\n\n<!-- Top Group Row Placeholder -->\n<ng-template #topGroupingRowPlaceholder let-col let-showChevron=\"showChevron\">\n <div class=\"d-flex gap-2\">\n <div\n class=\"d-flex gap-2 top-row-grouping-placeholder\"\n [style.backgroundColor]=\"topGroupedBadgesBackgroundColor\"\n >\n <span\n cdkDragHandle\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/grid-3x2-gap.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n <span>{{ col.header }}</span>\n <span\n (click)=\"ungroupColumn(col)\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/x.svg'\"\n class=\"cursor-pointer data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n <div *ngIf=\"showChevron\" style=\"opacity: 0.6; font-size: 14px\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n</ng-template>\n\n<ng-template\n #childHeaderPlaceholder\n let-col\n let-pinnedRight=\"pinnedRight\"\n let-i=\"index\"\n let-sections=\"sections\"\n>\n <div\n class=\"header-cell one-row-header-cells\"\n [class.border-right]=\"showVerticalBorder\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n [style.fontWeight]=\"headerFontWeight\"\n >\n <div class=\"d-flex justify-content-between h-100 align-items-center w-100\">\n <div\n class=\"d-flex justify-content-between align-items-center w-100\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div\n class=\"text-ellipsis h-100 d-flex align-items-center\"\n [title]=\"col.header\"\n [class.w-100]=\"pinnedRight\"\n >\n {{ col.header }}\n </div>\n\n <div\n class=\"position-relative d-flex\"\n [class.flex-row-reverse]=\"pinnedRight\"\n >\n <div class=\"three-dots p-1\" style=\"cursor: pointer\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/three-dots-vertical.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n\n <div class=\"resize-handle resize-test\">\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div\n *ngIf=\"showFilterRow\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n class=\"header-cell filter-cell\"\n [class.border-right]=\"showVerticalBorder\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n [class.border-right]=\"showVerticalBorder\"\n style=\"grid-row: 3\"\n >\n <div\n class=\"header-cell filter-cell\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n [style.width.px]=\"col.width\"\n [style.min-width.px]=\"col.width\"\n [style.height.px]=\"headerRowHeight\"\n [style.min-height.px]=\"headerRowHeight\"\n [style.max-height.px]=\"headerRowHeight\"\n >\n <input\n type=\"text\"\n class=\"form-control form-control-sm\"\n placeholder=\"Filter\"\n [(ngModel)]=\"col.filterValue\"\n [readonly]=\"col?.type == 'dropdown' || col?.type == 'image'\"\n [class.disabled-search-input]=\"\n col?.type == 'dropdown' || col?.type == 'image'\n \"\n />\n <span\n class=\"filter-icon-wrapper\"\n (click)=\"activeFilterCell = col; activeCol = null\"\n ><span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/filter-2.svg'\"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span\n ></span>\n\n <div\n class=\"position-absolute\"\n *ngIf=\"activeFilterCell === col\"\n style=\"top: 100%; right: 0; z-index: 10; left: 0\"\n ></div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #tableLayout>\n <div\n (click)=\"$event.stopPropagation()\"\n class=\"p-3 action_dropdown_new_design actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\n style=\"width: 320px\"\n >\n <div class=\"d-flex align-items-center mb-3\">\n <button\n class=\"btn btn-link p-0\"\n style=\"margin-left: -10px\"\n (click)=\"toggleActions('setting')\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n </button>\n <h6 class=\"mb-0 ms-2 text_common_14px\">Table Layout</h6>\n </div>\n <hr class=\"my-2\" />\n <div class=\"w-100 mb-3 d-flex\" role=\"group\">\n <input\n type=\"radio\"\n class=\"btn-check layout-button-check\"\n name=\"layoutSize\"\n id=\"small\"\n autocomplete=\"off\"\n (change)=\"changeTableLayout($event, 'small')\"\n [checked]=\"selectedTableLayout == 'small'\"\n />\n <label\n class=\"border d-flex flex-column align-items-center layout-button\"\n for=\"small\"\n [ngStyle]=\"{\n color: selectedTableLayout == 'small' ? '#000' : '#727272'\n }\"\n >\n <div class=\"preview-box border mb-1\" style=\"height: 8px\"></div>\n Small\n </label>\n\n <input\n type=\"radio\"\n class=\"btn-check layout-button-check\"\n name=\"layoutSize\"\n id=\"medium\"\n autocomplete=\"off\"\n [checked]=\"selectedTableLayout == 'medium'\"\n (change)=\"changeTableLayout($event, 'medium')\"\n />\n <label\n class=\"border mx-3 d-flex flex-column align-items-center layout-button\"\n for=\"medium\"\n [ngStyle]=\"{\n color: selectedTableLayout == 'medium' ? '#000' : '#727272'\n }\"\n >\n <div class=\"preview-box border mb-1\" style=\"height: 12px\"></div>\n Medium\n </label>\n\n <input\n type=\"radio\"\n class=\"btn-check layout-button-check\"\n name=\"layoutSize\"\n id=\"large\"\n autocomplete=\"off\"\n (change)=\"changeTableLayout($event, 'large')\"\n [checked]=\"selectedTableLayout == 'large'\"\n />\n <label\n class=\"border d-flex flex-column align-items-center layout-button\"\n for=\"large\"\n [ngStyle]=\"{\n color: selectedTableLayout == 'large' ? '#000' : '#727272'\n }\"\n >\n <div class=\"preview-box border mb-1\" style=\"height: 16px\"></div>\n Large\n </label>\n </div>\n\n <hr class=\"my-2\" />\n <div class=\"d-flex justify-content-between align-items-center mb-2\">\n <span>Show separators</span>\n <div class=\"form-check form-switch m-0\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n id=\"separators\"\n [(ngModel)]=\"showVerticalBorder\"\n (change)=\"onFontChange()\"\n />\n </div>\n </div>\n <div class=\"d-flex justify-content-between align-items-center\">\n <span>Row shading</span>\n <div class=\"form-check form-switch m-0\">\n <input\n class=\"form-check-input\"\n [(ngModel)]=\"rowShadingEnabled\"\n (change)=\"toggleRowShading()\"\n type=\"checkbox\"\n id=\"rowShading\"\n />\n </div>\n </div>\n <!-- <div class=\"d-flex justify-content-between align-items-center mb-2\">\n <span>Show Side Menu</span>\n <div class=\"form-check form-switch m-0\">\n <input\n class=\"form-check-input\"\n [(ngModel)]=\"showSideMenu\"\n type=\"checkbox\"\n id=\"rowShading\"\n />\n </div>\n </div>\n <div class=\"d-flex justify-content-between align-items-center mb-2\">\n <span>Show Filter Row</span>\n <div class=\"form-check form-switch m-0\">\n <input\n class=\"form-check-input\"\n [(ngModel)]=\"showFilterRow\"\n type=\"checkbox\"\n id=\"rowShading\"\n />\n </div>\n </div> -->\n </div>\n</ng-template>\n\n<ng-template #tablePreset>\n <div\n *ngIf=\"activeSubButton !== 'save-preset'\"\n (click)=\"$event.stopPropagation()\"\n class=\"p-3 action_dropdown_new_design actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\n style=\"width: 280px\"\n >\n <!-- Header -->\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <div class=\"d-flex align-items-center\">\n <button\n class=\"btn btn-link p-0\"\n style=\"margin-left: -10px\"\n (click)=\"toggleActions('setting')\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\n class=\"data-grid-svg-icon\"\n ></span>\n </button>\n <h6 class=\"mb-0 ms-2 text_common_14px\">Table Presets</h6>\n </div>\n <!-- Save Preset Button with Dropdown -->\n <div>\n <a\n class=\"text-decoration-none text-primary\"\n type=\"button\"\n id=\"savePresetDropdown\"\n (click)=\"$event.stopPropagation(); toggleSubActions('save-preset')\"\n >\n {{ isTablePresetNotChanged ? \"Save preset\" : \"Update Preset\" }}\n </a>\n </div>\n </div>\n\n <!-- Search -->\n <div class=\"mb-3\">\n <div class=\"col-12 global-search position-relative\">\n <span [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\n class=\"data-grid-svg-icon mx-2 position-absolute icon\"\n ></span>\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Search...\"\n [(ngModel)]=\"searchTextPresetTable\"\n type=\"search\"/>\n </div>\n </div>\n\n <!-- Preset List -->\n <ng-container\n *ngIf=\"\n tableView | filter : searchTextPresetTable : 'name' as filteredList\n \"\n >\n <!-- If filteredList exists and none is default -> show fallback -->\n <div\n class=\" pb-5 overflow-auto\"\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight - 250\"\n >\n <div\n class=\"cursor-pointer\"\n (click)=\"\n clearAllFilters();\n openIndex = null;\n temp_state.id = '';\n activeTopButton = '';\n curretaTablePresetForUpdate = null\n \"\n >\n <div class=\"fw-semibold\">Default View</div>\n </div>\n <div class=\"d-flex justify-content-between\">\n <small class=\"text-dark\">Created by system</small>\n <span\n *ngIf=\"!tableFilterViewId && !hasAnyDefaultView()\"\n class=\"badge bg-light text-primary ms-2\"\n >Default</span\n >\n <span\n *ngIf=\"!tableFilterViewId && !hasAnyDefaultView()\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\"\n class=\"me-2\"\n ></span>\n <div\n class=\"dropdown d-flex justify-content-end\"\n *ngIf=\"tableFilterViewId\"\n ></div>\n </div>\n\n <!-- The list: render each table from filteredList -->\n <div\n class=\"list-group list-group-flush\"\n *ngFor=\"\n let table of filteredList;\n let i = index;\n trackBy: trackByTable\n \"\n >\n <!-- Item -->\n <div\n (click)=\"\n $event.stopPropagation(); openIndex = null; activeTopButton = ''\n \"\n class=\"list-group-item px-0 d-flex justify-content-between align-items-center\"\n >\n <div (click)=\"selectFilter(table); openIndex = null\">\n <div class=\"fw-semibold\" style=\"cursor: pointer\">\n {{ table?.name }}\n <!-- {{table?.is_temp}} -->\n <span\n *ngIf=\"\n (table?.is_temp && !temp_state.id) ||\n temp_state.id == table.id\n \"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\n \"\n class=\"me-2\"\n ></span>\n <span\n *ngIf=\"table?.is_default\"\n class=\"badge bg-light text-primary ms-2\"\n >Default</span\n >\n </div>\n <small class=\"text-dark\" *ngIf=\"table?.config?.filterNames\" [title]=\"table?.config?.filterNames\">\n {{\n table?.config?.filterNames?.length > 25\n ? (table?.config?.filterNames | slice:0:25) + '...'\n : table?.config?.filterNames\n }}\n ({{ table?.config?.totalCount }})\n </small>\n <small class=\"text-dark\" *ngIf=\"!table?.config?.filterNames\">{{ table?.createdAt | date : \"MMM d, y\" }}</small>\n </div>\n\n <div class=\"d-flex align-items-center\">\n <span\n *ngIf=\"table?.is_default\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/check-blue.svg'\n \"\n class=\"me-2\"\n ></span>\n\n <div class=\"dropdown\" *ngIf=\"!table?.is_default\">\n <div\n class=\"dropdown-wrapper\"\n (click)=\"$event.stopPropagation()\"\n >\n <button\n type=\"button\"\n class=\"btn-icon muted-text\"\n (click)=\"toggleMenu(i, $event)\"\n aria-haspopup=\"true\"\n [attr.aria-expanded]=\"openIndex === i\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/horizontal-dots.svg'\n \"\n class=\"me-2\"\n ></span>\n </button>\n\n <!-- menu -->\n <ul\n *ngIf=\"openIndex === i\"\n class=\"custom-dropdown-menu position-fixed top-auto\"\n role=\"menu\"\n [style.right.px]=\"'auto'\"\n [style.left.px]=\"dataGridContainer.offsetWidth - 100\"\n style=\"top: unset; right: unset\"\n >\n <li role=\"none\">\n <button\n role=\"menuitem\"\n class=\"dropdown-item\"\n (click)=\"\n actionPreset(table, 'setPreset'); temp_state.id = ''\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/star.svg'\n \"\n class=\"me-2\"\n ></span>\n Set as default\n </button>\n </li>\n\n <li role=\"none\" *ngIf=\"!table.confirmDelete\">\n <button\n role=\"menuitem\"\n class=\"dropdown-item text-danger\"\n (click)=\"table.confirmDelete = true\"\n >\n <span\n style=\"margin-top: -4px\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/trash-red.svg'\n \"\n class=\"me-2\"\n ></span>\n Delete\n </button>\n </li>\n\n <li\n role=\"none\"\n *ngIf=\"table.confirmDelete\"\n class=\"confirm-block\"\n >\n <div class=\"px-3 py-2 text-center\">\n <div class=\"mb-2\">\n Are you sure you want to delete <br /><b\n >\u201C{{ table?.name }}\u201D</b\n >?\n </div>\n <div class=\"d-flex gap-2\">\n <button\n class=\"btn btn-sm btn-light me-2\"\n (click)=\"table.confirmDelete = false\"\n >\n Cancel\n </button>\n <button\n class=\"btn btn-sm btn-danger\"\n (click)=\"actionPreset(table, 'deletePreset')\"\n >\n Delete\n </button>\n </div>\n </div>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n <!-- Item End Here -->\n </div>\n </div>\n </ng-container>\n </div>\n\n <div\n (click)=\"$event.stopPropagation()\"\n *ngIf=\"activeSubButton == 'save-preset'\"\n class=\"dropdown-menu p-3 badge mt-4 save-preset-dropdown mt-1\"\n aria-labelledby=\"savePresetDropdown\"\n style=\"min-width: 250px\"\n >\n <div class=\"fw-bold fs-14px mb-2\">\n {{ isTablePresetNotChanged ? \"Create New Preset\" : \"Update Preset\" }}\n </div>\n <!-- <div class=\"fs-14px mb-2\" style=\"line-height: 20px\">\n This will save the current table adjustments as a preset.\n </div> -->\n <!-- Input -->\n <div class=\"my-3\">\n <label for=\"presetName\" class=\"form-label fs-12px fw-bold\">Name</label>\n <div class=\"col-12 global-search position-relative\">\n <input\n #presetNameCtrl=\"ngModel\"\n required\n [(ngModel)]=\"presetName\"\n [ngClass]=\"{\n 'is-invalid':\n presetNameCtrl.invalid &&\n (presetNameCtrl.dirty || presetNameCtrl.touched)\n }\"\n class=\"form-control form-control-sm ps-2\"\n placeholder=\"Enter preset name\"\n type=\"text\"\n />\n </div>\n </div>\n\n <!-- Checkbox -->\n <div class=\"form-check mb-2\">\n <input\n class=\"form-check-input\"\n [(ngModel)]=\"presetFilter\"\n type=\"checkbox\"\n id=\"saveFilters\"\n />\n <label class=\"form-check-label mt-1\" for=\"saveFilters\">\n Save active filters\n </label>\n </div>\n\n <!-- Save Button -->\n <div class=\"d-flex justify-content-end gap-2\" style=\"height: 32px\">\n <button\n type=\"button\"\n style=\"height: 32px\"\n class=\"cancel_btn_new w-100 d-flex align-items-center justify-content-center\"\n (click)=\"$event.stopPropagation(); toggleActions('table-presets')\"\n style=\"margin-top: -2px\">\n <span>Cancel</span>\n </button>\n <button\n [disabled]=\"closeDropdown.preset.loading\"\n (click)=\"savePreset(presetNameCtrl)\"\n type=\"button\"\n style=\"height: 32px\"\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center\"\n >\n <span style=\"margin-top: -2px\" *ngIf=\"isTablePresetNotChanged\">\n <ng-container *ngIf=\"!closeDropdown.preset.loading\"\n >Create</ng-container\n >\n <ng-container *ngIf=\"closeDropdown.preset.loading\"\n ><span class=\"spinner-border spinner-border-sm\"></span\n ></ng-container>\n </span>\n <span style=\"white-space: nowrap\" *ngIf=\"!isTablePresetNotChanged\"\n >Update Preset</span\n >\n </button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #showHideColumns>\n <div\n (click)=\"$event.stopPropagation()\"\n class=\"p-3 action_dropdown_new_design actions-dropdown mt-1 dropdown-menu show shadow custom-menu table-layout\"\n style=\"width: 280px\"\n >\n <!-- Header -->\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <div class=\"d-flex align-items-center\">\n <button\n class=\"btn btn-link p-0\"\n style=\"margin-left: -10px\"\n (click)=\"toggleActions('setting')\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\n class=\"data-grid-svg-icon\"\n ></span>\n </button>\n <h6 class=\"mb-0 ms-2 text_common_14px\">Columns</h6>\n </div>\n <a\n (click)=\"resetColumns()\"\n href=\"javascript:void(0)\"\n class=\"text-primary text-decoration-none\"\n >Reset</a\n >\n </div>\n\n <!-- Search -->\n <div class=\"mb-3\">\n <div class=\"col-12 global-search position-relative\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\n class=\"mx-2 position-absolute icon data-grid-svg-icon\"\n ></span>\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Search column\"\n type=\"search\"\n [(ngModel)]=\"topShowHideColumns\"\n />\n </div>\n </div>\n <!-- Preset List -->\n <div\n class=\"list-group list-group-flush\"\n style=\"overflow: auto; scrollbar-width: thin\"\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight - 220\"\n >\n <div class=\"muted-text show-hide-table-label d-flex justify-content-between\" *ngIf=\"hasAnyVisibleColumn\">\n Show in table\n <div class=\"form-check\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n id=\"hide_all\"\n [checked]=\"allColumnsSelected()\"\n (change)=\"toggleAllColumnsVisibility()\"\n />\n <label class=\"form-check-label fw-semibold\" for=\"hide_all\">\n Show/Hide All \n </label>\n </div>\n </div>\n <!-- Item -->\n <ng-container\n *ngFor=\"\n let col of columns | filter : topShowHideColumns : 'header';\n trackBy: trackByField\n \"\n >\n <div\n *ngIf=\"col.is_visible\"\n class=\"list-group-item border-0 px-0 d-flex justify-content-between align-items-center\"\n >\n <div class=\"d-flex gap-1\">\n <div class=\"me-1\">\n <input type=\"checkbox\" [(ngModel)]=\"col.is_visible\" [checked]=\"col.is_visible\">\n <!-- show checkbox instead of icon -->\n <!-- <span\n *ngIf=\"!col?.pinned\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/grip-vertical.svg'\n \"\n class=\"cursor-grap data-grid-svg-icon\"\n (mousedown)=\"$event.preventDefault()\"\n ></span> -->\n <span\n *ngIf=\"col?.pinned\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/pin.svg'\n \"\n class=\"cursor-grap data-grid-svg-icon\"\n (mousedown)=\"$event.preventDefault()\"\n ></span>\n </div>\n <div class=\"fw-semibold\">\n {{ col.header }}\n </div>\n </div>\n <div\n *ngIf=\"!col?.query?.first_value && !col?.query?._ids?.length\"\n class=\"d-flex align-items-center cursor-pointer\"\n (click)=\"toggleColumnVisibility(col, false)\"\n [class.disabled]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\n [class.pe-none]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\n [class.opacity-50]=\"visibleColumns().length <= 2 || col?.is_always_visible\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/columnIconNew(2).svg'\"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span>\n </div>\n <div\n *ngIf=\"col?.query?.first_value || col?.query?._ids?.length\"\n class=\"d-flex align-items-center\"\n style=\"opacity: 0.5\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/eye.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n </div>\n </div>\n </ng-container>\n\n <!-- Item End Here -->\n\n <div\n class=\"dropdown-divider\"\n *ngIf=\"hasAnyVisibleColumn && hasAnyInVisibleColumn\"\n ></div>\n\n <div\n class=\"muted-text show-hide-table-label d-flex justify-content-between\"\n *ngIf=\"hasAnyInVisibleColumn\"\n >\n Hide in table\n <div class=\"form-check\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n id=\"show_all\"\n [checked]=\"allColumnsSelected()\"\n (change)=\"toggleAllColumnsVisibility()\"\n />\n <label class=\"form-check-label fw-semibold\" for=\"show_all\">\n Show/Hide All \n </label>\n </div>\n </div>\n <div class=\"list-group list-group-flush\">\n <ng-container *ngFor=\"let col of columns; trackBy: trackByField\">\n <div\n *ngIf=\"!col.is_visible\"\n class=\"list-group-item border-0 px-0 d-flex justify-content-between align-items-center\"\n >\n <div class=\"d-flex gap-1\">\n <div class=\"me-1\">\n <input type=\"checkbox\" [(ngModel)]=\"col.is_visible\" [checked]=\"col.is_visible\">\n <!-- <span\n *ngIf=\"!col?.pinned\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/grip-vertical.svg'\n \"\n class=\"data-grid-svg-icon cursor-grap\"\n (mousedown)=\"$event.preventDefault()\"\n ></span> -->\n <span\n *ngIf=\"col?.pinned\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/pin.svg'\n \"\n class=\"data-grid-svg-icon cursor-grap\"\n (mousedown)=\"$event.preventDefault()\"\n ></span>\n </div>\n <div class=\"fw-semibold\">\n {{ col.header }}\n </div>\n </div>\n <div\n class=\"d-flex align-items-center cursor-pointer\"\n (click)=\"toggleColumnVisibility(col, true)\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/columnIconNew(2).svg'\n \"\n class=\"data-grid-svg-icon me-2 setting_dropdown\"\n ></span>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Item End Here -->\n </div>\n </div>\n</ng-template>\n\n<ng-template #filterColumns let-col=\"column\">\n <div\n @slideToggle\n *ngIf=\"!isFilterOpen && activeTopButton == 'filter-columns'\"\n (click)=\"$event.stopPropagation()\"\n class=\"action_dropdown_new_design actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns\"\n style=\"width: 280px; right: unset; max-width: 230px\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n >\n <div class=\"py-2 px-3\">\n <div class=\"col-12 global-search position-relative\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/search.svg'\"\n class=\"data-grid-svg-icon mx-2 position-absolute icon\"\n ></span>\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Filter by\"\n type=\"search\"\n [(ngModel)]=\"addFilterColumnInput\"\n />\n </div>\n </div>\n <div\n class=\"list-group list-group-flush\"\n style=\"max-height: calc(100vh - 500px); overflow: auto\"\n >\n <ng-container\n *ngFor=\"\n let col of columns | filter : addFilterColumnInput : 'header';\n trackBy: trackByField\n \"\n >\n <div\n (click)=\"openFilter(col)\"\n *ngIf=\"\n col.is_visible &&\n !col?.query?.first_value &&\n !col?.query?._ids?.length && col.type !== 'image'\n \"\n class=\"list-group-item border-0 px-3 d-flex justify-content-between align-items-center dropdown-item cursor-pointer\"\n >\n <div class=\"d-flex align-items-center justify-content-between gap-1 w-100\">\n <!-- <div style=\"margin-top: -3px\"></div> -->\n <div class=\"fw-semibold\">\n {{ col.header }}\n </div>\n <div class=\"d-flex align-items-center justify-content-between\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/chevron-right.svg'\"\n class=\"data-grid-svg-icon me-2\"\n ></span>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Dropdown -->\n <div\n @slideToggle\n *ngIf=\"isFilterOpen && selectedColumnForFilter?.type == 'dropdown' || selectedColumnForFilter?.type == 'array'\"\n (click)=\"$event.stopPropagation()\"\n class=\"shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns pb-2\"\n style=\"width: 280px; right: unset; max-width: 230px\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n >\n <div class=\"px-3 my-2 border-below py-1 pb-2 mb-3 d-flex ps-1\">\n <span\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\n ></span\n ><b>{{ selectedColumnForFilter?.header }}</b>\n </div>\n <div class=\"mb-2 px-3\">\n <div\n class=\"col-12 position-relative border rounded d-flex align-items-center flex-wrap px-2 filter-serach-inpt\"\n >\n <span\n *ngFor=\"let selected of selectedFilterOptions\"\n class=\"badge d-flex align-items-center gap-1 me-1 mb-1 top-row-filter-dropdown\"\n >\n {{ selected?.value ? selected.value : selected }}\n <span\n (click)=\"toggleSelectionInFilter(selected)\"\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/cross-primary.svg'\n \"\n class=\"me-2\"\n ></span>\n </span>\n <input\n class=\"form-control form-control-sm border-0 flex-grow-1\"\n style=\"padding: 0\"\n [placeholder]=\"selectedFilterOptions?.length ? '' : 'Filter by'\"\n type=\"search\"\n [(ngModel)]=\"searchTextForFilterDropDown\"\n (keydown.backspace)=\"handleBackspace($event)\"\n />\n </div>\n </div>\n <div\n class=\"list-group list-group-flush\"\n style=\"max-height: calc(100vh - 600px); overflow: auto\"\n >\n <ng-container\n *ngFor=\"\n let col of selectedColumnForFilter?.column_dropdown_value\n | filter : searchTextForFilterDropDown : 'value';\n let i = index\n \"\n >\n <div\n class=\"list-group-item border-0 px-2 d-flex justify-content-between align-items-center dropdown-item cursor-pointer\"\n >\n <div class=\"form-check\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [id]=\"i\"\n [checked]=\"currentFilterSelectedIds.has(col.id || col._id || col)\"\n (change)=\"toggleSelectionInFilter(col)\"\n />\n <label class=\"form-check-label fw-semibold\" [for]=\"i\">\n {{ col?.value || col?.name || col }}\n </label>\n </div>\n </div>\n </ng-container>\n </div>\n <div\n class=\"d-flex justify-content-center gap-2 px-2 border-top\"\n style=\"height: 38px\"\n >\n <button\n type=\"button\"\n style=\"height: 32px\"\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\n (click)=\"$event.stopPropagation(); resetFilterChanges()\"\n >\n <span>Cancel</span>\n </button>\n <button\n type=\"button\"\n style=\"height: 32px\"\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\n (click)=\"applyDropdownFilter()\"\n >\n <span style=\"margin-top: -2px\">Save</span>\n </button>\n </div>\n </div>\n\n <!-- For Text fields and number fields-->\n\n <div\n @slideToggle\n *ngIf=\"\n isFilterOpen &&\n (selectedColumnForFilter?.type == 'string' ||\n selectedColumnForFilter?.type == 'number' ||\n selectedColumnForFilter?.type == 'date')\n \"\n (click)=\"$event.stopPropagation()\"\n class=\"shadow actions-dropdown mt-1 show shadow custom-menu table-layout filter-columns pb-2\"\n style=\"width: 210px; right: unset; max-width: 230px\"\n [style.backgroundColor]=\"checkboxesBackgroundColor\"\n >\n <div class=\"px-3 border-below py-1 pb-2 d-flex ps-1\">\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/arrow-left.svg'\"\n (click)=\"toggleActions('filter-columns'); isActiveFilterOpen = false\"\n class=\"data-grid-svg-icon me-2 cursor-pointer\"\n ></span\n ><b>{{ selectedColumnForFilter?.header }}</b>\n </div>\n <div class=\"col-12 position-relative p-2 text-filter\">\n <div class=\"mb-2\">\n <select\n class=\"form-select form-select-sm custom-select border\"\n [(ngModel)]=\"firstCondition\"\n >\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"before\">Less Then </option>\n <option value=\"after\">Greater Then </option>\n <option value=\"less_then_equal\">less then Equal to</option>\n <option value=\"greater_then_equal\">Greater then Equal to </option>\n </ng-container>\n </select>\n </div>\n <div class=\"mb-2\">\n <input\n class=\"form-control form-control-sm\"\n placeholder=\"Enter first value\"\n type=\"search\"\n [type]=\"\n selectedColumnForFilter?.type == 'string'\n ? 'text'\n : selectedColumnForFilter?.type\n \"\n [(ngModel)]=\"firstValue\"\n (keydown.enter)=\"applyDropdownFilter()\"\n />\n </div>\n <div>\n <div class=\"d-flex my-3 d-flex flex-row\" style=\"font-size: 14px\">\n <div\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input\"\n type=\"radio\"\n id=\"logicalAnd\"\n name=\"logicalOperator\"\n value=\"and\"\n [(ngModel)]=\"condition\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalAnd\"\n >AND</label\n >\n </div>\n\n <div\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input\"\n type=\"radio\"\n id=\"logicalOr\"\n name=\"logicalOperator\"\n value=\"or\"\n [(ngModel)]=\"condition\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalOr\">OR</label>\n </div>\n\n <div\n class=\"form-check form-check-inline col-4 m-0 d-flex align-items-center gap-1\"\n >\n <input\n class=\"form-check-input\"\n type=\"radio\"\n id=\"logicalNone\"\n name=\"logicalOperator\"\n value=\"none\"\n [(ngModel)]=\"condition\"\n />\n <label class=\"form-check-label mb-0 mt-1\" for=\"logicalNone\"\n >None</label\n >\n </div>\n </div>\n\n <ng-container *ngIf=\"condition !== 'none' && firstValue\">\n <div class=\"mb-2 mt-3\">\n <!-- Second condition select -->\n <select\n class=\"form-select form-select-sm border\"\n [(ngModel)]=\"secondCondition\"\n >\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'string'\">\n <option value=\"contain\">Contains</option>\n <option value=\"does_not_contain\">Does Not Contain</option>\n <option value=\"equal\">Equals</option>\n <option value=\"before\">Starts With</option>\n <option value=\"after\">Ends With</option>\n </ng-container>\n\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'date'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"not_equal\">Not Equal</option>\n <option value=\"after\">After</option>\n <option value=\"before\">Before</option>\n </ng-container>\n <ng-container *ngIf=\"selectedColumnForFilter?.type == 'number'\">\n <option value=\"equal\">Equals To</option>\n <option value=\"before\">Less Then </option>\n <option value=\"after\">Greater Then </option>\n <option value=\"less_then_equal\">less then Equal to</option>\n <option value=\"greater_then_equal\">Greater then Equal to </option>\n </ng-container>\n </select>\n </div>\n\n <div class=\"mb-2\">\n <!-- Second value input -->\n <input\n [type]=\"\n selectedColumnForFilter?.type == 'string'\n ? 'text'\n : selectedColumnForFilter?.type\n \"\n class=\"form-control form-control-sm\"\n placeholder=\"Enter second value\"\n type=\"search\"\n [(ngModel)]=\"secondValue\"\n (keydown.enter)=\"applyDropdownFilter()\"\n />\n </div>\n </ng-container>\n </div>\n </div>\n\n <div\n class=\"d-flex justify-content-center gap-2 px-2 border-top\"\n style=\"height: 38px\"\n >\n <button\n [disabled]=\"!currentFilterSelectedIds?.size && !firstValue\"\n type=\"button\"\n style=\"height: 32px\"\n class=\"btn btn-outline-secondary btn-light border w-100 d-flex align-items-center justify-content-center mt-1 btn-light\"\n (click)=\"$event.stopPropagation(); resetTextFilterChanges()\"\n >\n <span>Cancel</span>\n </button>\n <button\n [disabled]=\"(currentFilterSelectedIds?.size === 0 && !firstValue) || (condition !== 'none' && !secondValue)\"\n type=\"button\"\n style=\"height: 32px\"\n class=\"btn btn-primary w-100 d-flex align-items-center justify-content-center mt-1\"\n (click)=\"applyDropdownFilter()\"\n >\n <span style=\"margin-top: -2px\">Apply</span>\n </button>\n </div>\n </div>\n</ng-template>\n\n<!-- Edit dropdown here -->\n<ng-template let-col>\n <div class=\"drop-down-edit\"></div>\n</ng-template>\n\n<ng-template\n #fullTextTemplate\n let-row=\"row\"\n let-col=\"col\"\n let-isArray=\"isArray\"\n>\n <div\n class=\"full-text-box\"\n (dblclick)=\"$event.stopPropagation(); $event.preventDefault()\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight / 2\"\n >\n <ng-container *ngIf=\"!isEditing(row, col)\">\n <div\n *ngIf=\"!isArray\"\n class=\"full-text-content\"\n [style.maxHeight.px]=\"dataGridContainer.offsetHeight / 2\"\n (dblclick)=\"\n $event.stopPropagation();\n $event.preventDefault();\n enableEdit(row, col, true)\n \"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n >\n {{\n getNestedValue(row, col.field)?.value ||\n getNestedValue(row, col.field)?.name ||\n getNestedValue(row, col.field)\n }}\n </div>\n <div *ngIf=\"isArray\">\n <ul>\n <ng-container\n *ngFor=\"let item of getNestedValue(row, col.field); let i = index\"\n >\n <li *ngIf=\"i !== 0\">\n <ng-container>\n {{\n item?.department_name ||\n item?.roleName ||\n item?.full_name ||\n \"-\"\n }}\n </ng-container>\n </li>\n </ng-container>\n </ul>\n </div>\n </ng-container>\n <ng-container *ngIf=\"isEditing(row, col)\">\n <textarea\n (dblclick)=\"\n $event.stopPropagation();\n $event.preventDefault();\n enableEdit(row, col, true)\n \"\n #textModel=\"ngModel\"\n rows=\"4\"\n #textAreadInput\n [(ngModel)]=\"row[col.field]\"\n name=\"{{ col.field }}\"\n required\n (blur)=\"disableEdit(row, col, textModel)\"\n (keydown.enter)=\"textAreadInput.blur()\"\n autofocus\n class=\"form-control\"\n [ngClass]=\"{\n 'is-invalid': textModel.invalid\n }\"\n (mousedown)=\"$event.stopPropagation()\"\n ></textarea>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #defaultImagePlaceholder let-row=\"row\" let-col=\"col\">\n <span\n class=\"px-2 d-flex w-100 cell-content image-placeholder\"\n [title]=\"row?.full_name || row?.name || 'N/A'\"\n >\n <ng-container\n *ngIf=\"\n row?.logo ||\n row?.assetImage ||\n row?.invoice?.invoice_image ||\n row?.invoice_image;\n else placeholder\n \"\n >\n <span\n (click)=\"fullscreenImage = row?.profile_pictures?.[4]?.path ||\n row?.logo ||\n row?.assetImage ||\n row?.invoice_image\"\n class=\"pic\"\n [style.width.px]=\"rowHeight - 10\"\n [style.height.px]=\"rowHeight - 10\"\n [class.assets-pic]=\"gridType == 'Assets'\"\n >\n <img\n [width]=\"rowHeight - 12\"\n [height]=\"rowHeight - 12\"\n [style.width.px]=\"rowHeight - 10\"\n [style.height.px]=\"rowHeight - 10\"\n [src]=\"\n row?.profile_pictures?.[4]?.path ||\n row?.logo ||\n row?.assetImage ||\n row?.invoice_image\n \"\n alt=\"icon\"\n class=\"option-icon\"\n loading=\"lazy\"\n />\n </span>\n </ng-container>\n <!-- <div\n class=\"fullscreen-overlay\"\n *ngIf=\"fullscreenImage\"\n (click)=\"fullscreenImage = null\"\n >\n <img [src]=\"fullscreenImage\" class=\"fullscreen-img\" />\n </div> -->\n\n <ng-template #placeholder>\n <span\n [ngClass]=\"getDynamicClass(row?.full_name || row?.name)\"\n class=\"pic d-flex align-items-center rounded-circle\"\n [style.width.px]=\"rowHeight - 12\"\n [style.height.px]=\"rowHeight - 12\"\n [style.fontSize.px]=\"rowHeight / 3\"\n [class.assets-pic]=\"gridType == 'Assets'\"\n >\n {{ getInitials(row?.full_name) }}\n </span>\n </ng-template>\n </span>\n</ng-template>\n\n<!-- Right Click Menue -->\n<div\n [class.invisible]=\"!positionedYet\"\n class=\"context-menu p-2\"\n *ngIf=\"actionHide && actions?.length\"\n [ngStyle]=\"{ 'top.px': yPos, 'left.px': xPos }\"\n [class.show]=\"isVisible\"\n appendTo=\"body\"\n>\n <ul>\n <li\n *ngFor=\"let action of actions\"\n class=\"rounded d-flex align-items-center\"\n (click)=\"onActionClick(action)\"\n >\n <span\n [inlineSVG]=\"singleSpaAssetsPath + 'data-grid/icons/' + action + '.svg'\"\n class=\"data-grid-svg-icon right-click-menu-icons me-2\"\n ></span>\n <span class=\"text-capitalize fw-500\">{{ action }}</span>\n </li>\n </ul>\n</div>\n\n<!-- Details Toggle from bottom -->\n\n<ng-template #nestedTableTemplate let-row>\n <div\n class=\"nested-table table table-sm w-100 mb-0 center-nested-table w-100\"\n style=\"table-layout: fixed !important\"\n #nestedTableContainer\n >\n <thead\n #nestedHeader\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\n >\n <div\n cdkDropList\n [cdkDropListData]=\"row?.detail.columns\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"dropColumn($event, row)\"\n (cdkDropListSorted)=\"onNestedColSort($event, previewNestedCols)\"\n [style.height.px]=\"nestedTableHeaderRowHeight\"\n class=\"d-flex tr border-below\"\n >\n <div\n *ngFor=\"let col of row.detail.columns; let i = index\"\n [style.width.px]=\"col?.width || 250\"\n [style.minWidth.px]=\"col?.width || 250\"\n [style.maxWidth.px]=\"col?.width || 250\"\n class=\"px-4 th\"\n [attr.field]=\"col.field\"\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\n cdkDrag\n >\n <div\n class=\"d-flex h-100 justify-content-between position-relative align-items-center\"\n >\n <div class=\"text-ellipsis\" (click)=\"sortNestedCol(col, row)\">\n {{ col.header }}\n </div>\n <div class=\"d-flex gap-2\">\n <span\n *ngIf=\"currentSubSortColumn == col.field\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n (col?.order_by == 'desc'\n ? 'data-grid/icons/sort-desc.svg'\n : 'data-grid/icons/sort-asc.svg')\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center ms-2 start-50\"\n >\n </span>\n <!-- <div\n class=\"three-dots p-1\"\n (click)=\"openThreeDotsMenu($event, col)\"\n style=\"cursor: pointer\"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/icons/three-dots-vertical.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div> -->\n\n <!-- Only show menu if this column is active -->\n <div\n class=\"position-absolute\"\n *ngIf=\"activeCol === col\"\n style=\"top: -50%; z-index: 21; left: 0\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n columnMenu;\n context: {\n col: col,\n isNestedTable: true,\n columns: row?.detail.columns\n }\n \"\n ></ng-container>\n </div>\n <div\n class=\"resize-handle\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"\n $event.preventDefault();\n onResizeColumn($event, col);\n $event.stopPropagation()\n \"\n >\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/resize-handle1.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n </div>\n </div>\n <ng-template cdkDragPreview>\n <div class=\"p-2 border d-flex gap-2\">\n <div>\n <span\n [inlineSVG]=\"\n singleSpaAssetsPath + 'data-grid/icons/arrows-move.svg'\n \"\n class=\"data-grid-svg-icon d-flex justify-content-center align-items-center\"\n ></span>\n </div>\n <div>{{ col.header }}</div>\n </div>\n </ng-template>\n </div>\n </div>\n </thead>\n <div\n [style.width.px]=\"nestedHeader.offsetWidth - 10\"\n [style.minWidth.px]=\"nestedHeader.offsetWidth - 10\"\n >\n <cdk-virtual-scroll-viewport\n [itemSize]=\"nestedTablerowHeight\"\n class=\"viewport\"\n [style.height.px]=\"\n (row?.detail?.result?.length < 5\n ? nestedTablerowHeight * row?.detail?.result?.length + 40\n : 300) + (hasHorizontalScroll ? -12 : 1)\n \"\n [style.width.px]=\"nestedHeader.offsetWidth - 10\"\n [style.minWidth.px]=\"nestedHeader.offsetWidth - 10\"\n >\n <div\n class=\"cursor-pointer border-below d-flex tr\"\n *cdkVirtualFor=\"let d of row?.detail?.result; trackBy: trackById\"\n [style.height.px]=\"nestedTablerowHeight\"\n [style.width.px]=\"nestedHeader?.offsetWidth\"\n [style.minWidth.px]=\"nestedHeader?.offsetWidth\"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n (contextmenu)=\"onRightClick($event, d)\"\n >\n <div\n class=\"px-4 py-0 td\"\n *ngFor=\"let col of previewNestedCols; let j = index\"\n [style.fontSize.px]=\"nestedTablerowFontsize\"\n [attr.field]=\"col.field\"\n [style.width.px]=\"col?.width || 250\"\n [style.minWidth.px]=\"col?.width || 250\"\n [style.maxWidth.px]=\"col?.width || 250\"\n >\n <div\n [style.height.px]=\"nestedTablerowHeight - 1\"\n [style.max-width.px]=\"col?.width\"\n class=\"d-flex align-items-center\"\n >\n <!-- {{ d[col.field] || (col.is_amount ? 0 : \"-\") }} -->\n <div\n #cellText\n class=\"text-ellipsis flex-grow-1\"\n [title]=\"\n col.type === 'date'\n ? (getNestedValue(d, col.field) | date : dateFormat)\n : getNestedValue(d, col.field) || '-'\n \"\n >\n <ng-container *ngIf=\"col.type !== 'image'\">\n <ng-container *ngIf=\"col.is_amount\">{{\n currencySymbol\n }}</ng-container>\n {{\n !isNestedValueArray(d, col.field)\n ? col.type === 'date'\n ? (isDate(getNestedValue(d, col.field))\n ? (getNestedValue(d, col.field) | date: dateFormat)\n : (getNestedValue(d, col.field)?.value ||\n getNestedValue(d, col.field)?.name ||\n getNestedValue(d, col.field) ||\n '-'))\n : (getNestedValue(d, col.field)?.value ||\n getNestedValue(d, col.field)?.name ||\n getNestedValue(d, col.field) ||\n (col.is_amount ? 0: '-'))\n : (getNestedValue(d, col.field)?.[0]?.department_name ||\n getNestedValue(d, col.field)?.[0]?.roleName || getNestedValue(d, col.field)?.[0]?.full_name ||\n '-')\n }}\n </ng-container>\n <ng-container *ngIf=\"false\">\n {{ getTotalAmount(col) }}\n </ng-container>\n <ng-container *ngIf=\"col.type == 'image'\">\n <ng-container\n *ngTemplateOutlet=\"\n defaultImagePlaceholder;\n context: {\n row: d,\n col: col,\n }\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n </div>\n </cdk-virtual-scroll-viewport>\n </div>\n </div>\n</ng-template>\n\n<ng-template #leftRightNestedPlaceholder let-row>\n <table\n class=\"nested-table table table-sm w-100 mb-0\"\n [style.backgroundColor]=\"bodyBackgroundColor\"\n [style.height.px]=\"\n gridType == 'Assets'\n ? (nestedTableContainer?.nativeElement?.offsetHeight ?? 0) + 12\n : (taskManagementContainer?.nativeElement?.offsetHeight ?? 0)\n \"\n >\n <!-- <div class=\"thead\">\n <div\n class=\"tr d-flex border-below\"\n [style.height.px]=\"nestedTableHeaderRowHeight\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n >\n <div class=\"th\" *ngFor=\"let _ of [1, 2, 3, 4, 5]\"></div>\n </div>\n </div> -->\n <!-- <div class=\"tbody\">\n <div\n class=\"tr border-below\"\n [style.height.px]=\"nestedTablerowHeight\"\n *ngFor=\"let _ of row?.detail?.result\"\n [style.backgroundColor]=\"headerBackgroundColor\"\n >\n <div class=\"td\" *ngFor=\"let __ of [1, 2, 3, 4, 5]\" class=\"py-0\">\n <span\n [style.height.px]=\"nestedTablerowHeight\"\n [style.max-width.px]=\"nestedTablerowHeight\"\n ></span>\n </div>\n </div>\n </div> -->\n </table>\n</ng-template>\n\n<ng-template #taskManagementTemplate let-taskDetails=\"taskDetails\">\n <div\n class=\"p-4\"\n #taskManagementContainer\n [style.backgroundColor]=\"nestedTableHeaderBackgroundColor\"\n [style.fontFaimly]=\"fontFaimly\"\n >\n <div class=\"d-flex justify-content-between\">\n <div class=\"col-4\">\n <div class=\"item-title\">Description</div>\n <!-- <div class=\"item-content firstDiv\">\n {{ taskDetails.description }}\n </div> -->\n <p\n [style.fontSize]=\"bodyTextFontsSize\"\n class=\"item-content firstDiv taskDescription pe-4\"\n [innerHTML]=\"getSafeComment(taskDetails?.editor_description)\"\n (click)=\"openFullImage($event)\"\n ></p>\n </div>\n <div class=\"col-4\">\n <div class=\"item-title\">Attachments</div>\n <h5 *ngIf=\"taskDetails?.attachments?.length == 0\">\n No Attachments found\n </h5>\n <div\n *ngIf=\"taskDetails?.attachments?.length\"\n class=\"item-content d-flex flex-wrap\"\n style=\"gap: 10px\"\n >\n <a\n *ngFor=\"let attachement of taskDetails?.attachments; let i = index\"\n class=\"symbol-label fs-2 fw-semibold text-success cursor-pointer\"\n >\n <span\n title=\"{{ taskDetails?.attachments_name[i] || 'Attachment' }}\"\n (click)=\"downloadAttchment(attachement)\"\n [inlineSVG]=\"\n singleSpaAssetsPath +\n 'data-grid/document-icons/' +\n getExtention(attachement) +\n '.svg'\n \"\n >\n </span>\n </a>\n </div>\n </div>\n <div class=\"col-4\">\n <div class=\"item-title\">\n Comments ({{ taskDetails?.comments?.length }})\n </div>\n <h5 *ngIf=\"taskDetails?.comments?.length == 0\">No Comments found</h5>\n <div *ngIf=\"taskDetails?.comments?.length\" class=\"item-content\">\n <div class=\"comment\" *ngFor=\"let comment of taskDetails.comments\">\n <div class=\"d-flex align-items-center pe-3\">\n <img\n class=\"pic image-input-wrapper\"\n [style.width.px]=\"rowHeight - 12\"\n [style.height.px]=\"rowHeight - 12\"\n *ngIf=\"comment?.comment_by.logo\"\n src=\"{{ comment?.comment_by.logo }}\"\n alt=\"{{ comment.comment_by.full_name }}\"\n />\n <!-- <app-default-image-placeholder *ngIf=\"!comment?.comment_by.logo\" title=\"{{ comment.comment_by.full_name }}\" [name]=\"comment.comment_by.full_name\"></app-default-image-placeholder> -->\n <span\n *ngIf=\"!comment?.comment_by.logo\"\n [ngClass]=\"getDynamicClass(comment.comment_by.full_name)\"\n class=\"pic d-flex align-items-center rounded-circle\"\n [style.width.px]=\"rowHeight - 12\"\n [style.height.px]=\"rowHeight - 12\"\n [style.fontSize.px]=\"rowHeight / 3\"\n title=\"{{ comment.comment_by.full_name }}\"\n >\n {{ getInitials(comment.comment_by.full_name) }}\n </span>\n </div>\n <div>\n <div class=\"comment-author fs-14px\">\n {{ comment?.comment_by.full_name }}\n </div>\n <div\n class=\"comment-content forCommentImg\"\n [innerHTML]=\"getSafeComment(comment.comment)\"\n ></div>\n <div class=\"comment-timestamp\">\n {{ comment.comment_date | date }}\n </div>\n <div class=\"comment-timestamp\">\n Replies: ({{ comment.replies.length }})\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";@import\"bootstrap/dist/css/bootstrap.min.css\";:host,:host *{font-family:Inter,sans-serif!important}.data-grid-table-wrapper{height:100%;width:100%;border:1px solid #E0E0E0;border-radius:12px;position:relative}.data-grid-header{position:sticky;top:0}.data-grid-header{display:flex}.header-row{display:grid;width:100%}.header-cell{display:flex;align-items:center;position:relative;width:100%;padding:0 0 0 8px;font-weight:700;border-bottom:1px solid #E0E0E0;white-space:nowrap;min-width:80px;font-weight:600}.header-cell .filter-applied-on-text{color:#5d9cff!important}.filter-cell{padding:4px!important;display:flex;align-items:center;gap:8px;width:100%}.filter-cell .filter-applied{background-color:#bddef9}.border-right{border-right:1px solid #E0E0E0}.merged-grid{display:grid;grid-auto-rows:40px;border-bottom:1px solid #ccc}.span-two-rows{grid-row:span 2;display:flex;justify-content:space-between;align-items:center}.group-header{display:flex;justify-content:space-between;position:relative}.group-header-content{position:sticky;left:10px;overflow:hidden;text-overflow:ellipsis}.resize-handle{width:6px;cursor:e-resize;right:0;top:0;color:#00000026;margin-right:4px}:host ::ng-deep .resize-handle svg{stroke-width:2px}.group-header .resize-handle{top:25%}.h-100{height:100%}.data-grid-body{position:relative;overflow-y:auto;overflow-x:hidden}.cell{padding:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:100%;display:flex;align-items:center}.data-grid-row{display:flex;width:100%;min-width:max-content;align-items:center;border-bottom:1px solid #E0E0E0}.hovered-row{background-color:#ccc}.checkbox-row{border-bottom:#E0E0E0}.w-100{width:100%}.data-grid-header-wrapper{display:flex;position:relative;overflow:hidden;-webkit-user-select:none;user-select:none}.data-grid-header{display:flex;position:relative;z-index:1}.left-pinned,.right-pinned{position:sticky;top:0}.right-pinned-header{position:absolute;right:0;border-left:1px solid #E0E0E0;z-index:unset}.left-pinned{left:0}.right-pinned{right:0;border-left:1px solid #E0E0E0}.center-scrollable{z-index:unset!important;overflow-x:auto;overflow-y:visible;white-space:nowrap;scrollbar-width:none;-ms-overflow-style:none}.center-scrollable::-webkit-scrollbar{display:none}.data-grid-body-wrapper{-webkit-user-select:none;user-select:none;display:flex}.center-scrollable-body{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}.center-scrollable-body::-webkit-scrollbar{display:none}.left-pinned-body,.right-pinned-body{position:sticky;top:0;z-index:unset;background:#fff;scrollbar-width:none;-ms-overflow-style:none}.left-pinned-body::-webkit-scrollbar,.right-pinned-body::-webkit-scrollbar{display:none}.left-pinned-body{left:0}.border-end{border-right:1px solid #E0E0E0!important}.right-pinned-body{right:0;border-left:1px solid #E0E0E0}.fake-scroll-bar{height:14px;overflow:scroll;margin-bottom:10px}.text-ellipsis{overflow:hidden;text-overflow:ellipsis}.select-all-checkbox-cell{width:50px;display:flex;justify-content:center;align-items:center;height:100%}.select-all-checkbox-cell input{width:16px;height:14px}.border-below{border-bottom:1px solid #E0E0E0!important}.figmaIconSize.data-grid-svg-icon{width:24px!important;height:24px!important}.actions-dropdown .list-group .list-group-item{color:#1b1f22!important}.productSortingDropdownMenu{width:220px!important}.three-dots{width:24px;height:24px;display:flex;justify-content:center;align-items:center;border-radius:6px;margin-right:4px;margin-left:2px;cursor:pointer}.three-dots:hover,.three-dots.threeDotActive{background-color:#0084ff1a;padding:5px}.rotated-180{transform:scaleY(-1)}.filter-icon-wrapper{min-height:22px;max-height:22px;min-width:22px;max-width:22px;display:flex;justify-content:center;align-items:center;border-radius:3px;cursor:pointer;transition:background-color .3s ease}.filter-icon-wrapper:hover{background-color:#ccc}.column-menu,.filter-menu{box-shadow:0 0 16px #00000026;border-radius:4px}.column-menu{background:#fff;width:100%;width:200px;border:1px solid #ddd;box-shadow:0 0 12px #00000014;border:1px solid #E0E0E0;padding:4px 0;font-size:14px;position:fixed;border-radius:8px}.column-menu-item{padding:8px 12px;cursor:pointer;display:flex;align-items:center;transition:background-color .2s ease}.column-menu-item.active-sort,.column-menu-item:hover{background-color:#0084ff1a}.pin-parent{position:relative;width:100%!important}.column-submenu{position:absolute;top:0;left:100%;background:#fff;border:1px solid #ddd;width:130px;box-shadow:0 0 16px #00000026;border:1px solid #E0E0E0;display:none;padding:4px 0;z-index:10;border-radius:4px}.pin-parent:hover .column-submenu{display:block}.filter-menu-container{position:fixed;width:210px;background:#fff;border:1px solid #ddd;border-radius:4px;padding:12px;box-shadow:0 0 16px #00000026;border:1px solid #E0E0E0;z-index:1000;font-size:14px}.filter-menu-header{font-weight:600;margin-bottom:10px}.filter-dropdown-section{max-height:350px;overflow-y:auto}.dropdown-options{overflow-y:auto;scrollbar-width:thin;height:100%}.filter-text-section select,.filter-text-section input{width:100%}.filter-radio-inputs{width:14px!important;height:14px!important}.right-menu{border-left:1px solid #E0E0E0;font-size:14px}.border-start{border-left:1px solid #E0E0E0!important}.column-panel-item{font-size:.875rem;color:#333}.toggle-icon{cursor:pointer;transition:transform .2s ease}.toggle-icon.rotate{transform:rotate(90deg)}.grab-icon{cursor:grab;color:#6c757d}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cursor-pointer{cursor:pointer}.pivot-mode{height:48px}.chevron-wrapper{width:30px;height:20px;cursor:pointer;border-radius:3px;display:flex;justify-content:center;align-items:center;transition:background-color .3s ease;margin-right:8px}.chevron-wrapper:hover{background-color:#cac7c7}.chevron-wrapper i{font-size:14px}.column-panel-body{height:70%;overflow:auto;scrollbar-width:thin}.side-menue-text{transform:rotate(90deg);position:relative;font-weight:700;margin-top:40px}.columns-button{padding-top:20px;padding-bottom:35px;width:29px}.fake-scroll-content{height:12px}.fake-scrollbar{width:25px}.fake-scrollbar div{min-width:1px}.fake-horizintal-scrollbar div{min-height:1px}.side-filter-columns-wrapper{height:calc(100% - 25px)}.custom-modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;overflow:hidden;display:flex;justify-content:center;align-items:center;z-index:1050}.custom-modal-overlay .moda-header{background-color:#f8f8f8}.custom-modal-content{background-color:#fff;border-radius:8px;min-width:300px;max-width:400px;box-shadow:0 5px 20px #0000004d}.overlay-scrollable{height:250px;overflow:auto}.footer-row{border-top:1px solid #E0E0E0;padding-left:32px}.fake-horizintal-scrollbar{position:relative;bottom:17px;overflow-x:auto;overflow-y:hidden;height:17px}.border-dashed{border:1px dashed #E0E0E0}.cdk-drag-preview{box-sizing:border-box!important;border-radius:4px!important;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f!important;background-color:#f3f4f5!important;border:1px solid #E0E0E0!important;z-index:9999!important}.data-grid-header-wrapper ::ng-deep .cdk-drag-placeholder{display:block!important;background:#fff!important;opacity:1!important}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)!important}.top-row-grouping-placeholder{display:flex;align-items:center;border-radius:12px;font-size:14px;padding-inline:6px;border:1px solid #E0E0E0}.top-row-grouping-placeholder .bi-x{cursor:pointer;color:#7a7a7a}.top-row-grouping-placeholder .bi-x:hover{color:#111}.right-pinned-body-wrapper{position:absolute;right:0}.actions-dropdown{position:absolute;right:200px;z-index:1050;background-color:#fff;border-radius:8px!important;cursor:default}.bg-fff{background-color:#fff}.actions-dropdown-setting{right:250px}.action-button{background-color:#007cf5!important;border-radius:8px!important;padding:8px 16px!important;font-size:14px;height:32px;align-items:center}.global-search{width:100%;display:flex!important;align-items:center!important;height:32px;max-width:335px}.global-search span{margin-top:0!important;top:8px}.global-search input{padding-left:28px;border-radius:8px!important}.global-search input:focus{outline:none!important;box-shadow:none!important}.active .top-icon ::ng-deep svg path{stroke:#007cf5!important}.dropdown-menu{background-color:#fff!important;border:1px solid #E0E0E0!important;border-radius:8px!important}.custom-menu{width:250px;border-radius:8px;padding:4px 0;background-color:#fff}.custom-menu.setting_dropdown_menu{width:270px}.custom-menu .dropdown-item{font-size:14px;padding:8px 14px;color:#1b1f22!important;font-weight:400}.custom-menu .dropdown-item:hover{background-color:#0084ff1a;border-radius:6px}.table-layout{right:0;background:#fff;border-radius:8px!important}.actions-dropdown,.table-layout,.custom-menu,.dropdown-menu{background:#fff;border-radius:8px!important;border:1px solid #E0E0E0!important;background-color:#fff}.action_dropdown_new_design{background:#fff;border-radius:8px!important;border:1px solid #E0E0E0!important;box-shadow:0 2px 12px #00000014}.preview-box{width:40px;height:10px;border-radius:3px;background-color:transparent;transition:background-color .2s ease-in-out}.btn-check:checked+label .preview-box{background-color:var(--bs-primary)}.preview-box{width:40px;height:10px;border-radius:3px;border:2px solid transparent;transition:border-color .2s ease-in-out}#small:checked+label{border-color:#0084ff!important;background-color:#f5f5f5!important;color:#1b1f22!important}#small:checked+label .preview-box{background-color:#fff!important}#medium:checked+label{border-color:#0084ff!important;background-color:#f5f5f5!important;color:#1b1f22!important}#medium:checked+label .preview-box{background-color:#fff!important}#large:checked+label{border-color:#0084ff!important;background-color:#f5f5f5!important;color:#1b1f22!important}#large:checked+label .preview-box{background-color:#fff!important}.btn-check:checked+.btn{background-color:transparent!important;border-color:#007cf5!important}.layout-button{padding:8px 6px!important;width:82px;border-radius:8px!important;color:#1b1f22!important;height:60px;margin-bottom:0!important}.show-hide-table-label{position:sticky;top:0;z-index:99;background:#fff}.cursor-grap{cursor:grabbing}.pagination-container{display:flex;align-items:center;gap:12px;font-size:14px;color:#1b1f22}.page-size select{padding:3px 6px;border:1px solid #E0E0E0;border-radius:6px;background:#fff;font-size:13px}.page-buttons{display:flex;gap:4px;margin-left:auto;align-items:center}.page-buttons button{padding:7px 11px;background:#fff;border-radius:4px;cursor:pointer;font-size:13px;line-height:1.2;border:0;color:#6a6b6d}.page-buttons button.active{font-weight:400;border:1px solid #E0E0E0;border-radius:8px;font-size:14px;color:#1b1f22}.page-buttons button:disabled{opacity:.5;cursor:not-allowed}.page-buttons span{padding:0 6px;color:#666}.page-size .separator{padding:0 8px;border-right:1px solid #E0E0E0}.page-size .separator .actions-dropdown{position:fixed;right:200px;z-index:1050;background-color:#fff}.fs-14px{font-size:14px}.fs-12px{font-size:12px!important}.save-preset-dropdown{background:#fff;color:#111!important;right:0;font-weight:400!important;text-align:left!important;max-width:250px!important;text-wrap:auto!important;top:14px;font-size:14px!important}.add-filter-button{height:28px;cursor:pointer;border-radius:4px}.table-layout .dropdown-item{border-radius:0!important;font-size:14px;padding-block:6px!important}.table-layout .dropdown-item:hover{background-color:transparent!important}.filter-serach-inpt{max-height:230px!important;overflow:auto;scrollbar-width:thin;padding-top:4px;background-color:#f7f7f7;border-color:#dedede;border-radius:8px}.filter-serach-inpt .badge{color:#007cf5!important;background-color:#e6f2ff!important;border-radius:8px!important;padding:8px!important;font-weight:500!important;font-size:12px!important;height:24px!important}.filter-serach-inpt .badge ::ng-deep svg{cursor:pointer}.filter-serach-inpt .badge ::ng-deep svg:hover path{stroke:#040081!important}.filter-serach-inpt input{background-color:#f7f7f7;padding:0;height:26px;margin-top:-5px}.text-filter select{border:0}.text-filter select option{font-size:14px;font-weight:500}.text-filter select:focus{border:0}.text-filter input:focus,.text-filter select:focus{box-shadow:none!important}.active-filters{background-color:#f7f7f7;white-space:nowrap;background:#f7f7f7;padding-inline:8px;height:28px;font-size:14px;font-weight:500;border-radius:8px;box-shadow:none}.active-filters .header-tag{white-space:nowrap;font-size:14px;font-weight:400;color:#1b1f22;background:#ebebeb}.filter-tags .active{background-color:#e6f2ff}.filter-tags .active .header-tag{color:#007cf5!important}.table-cell{cursor:pointer;width:100%}.table-cell input:focus{outline:0!important;border:0!important;width:100%!important;box-shadow:none!important}.active-for-editing{outline:2.5px solid #007cf5!important;border-radius:4px;border:0!important;width:100%!important}.active-cell{outline:none!important;box-shadow:inset 0 0 0 1.5px #007cf5}span[inlineSVG]{width:16px;height:16px;display:inline-block}.cell .dropdown-menu{min-width:unset!important}.cell .dropdown-menu .item{transition:background-color .3s ease;display:flex;align-items:center;-webkit-user-select:none;user-select:none}.cell .dropdown-menu .item:hover{background-color:#f0f8ff}.cell .cell-editin-dropdown{scrollbar-width:thin!important;-webkit-user-select:none;user-select:none}.fw-semibold{font-weight:500!important}:host ::ng-deep .three-dots-col-menu span:not(.no-stroke) svg,:host ::ng-deep .three-dots-col-menu span:not(.no-stroke) svg path{stroke:#000!important}:host ::ng-deep .ascendingAppliedIcon svg{stroke:#006fd6}.fs-7{font-size:12px!important}.fs-8{font-size:10px!important}.all-filters-reset-button:hover{opacity:.7}.full-text-box{background:#fff;position:relative;display:flex;align-items:center;justify-content:center;z-index:1050;border:1px solid #dedede;border-radius:8px;padding:12px 14px;box-shadow:0 2px 8px #00000026}.full-text-content{border-radius:8px;max-height:70vh;overflow:auto;white-space:pre-wrap}.pic{border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:22px}.pic-comb2{background-color:#fbe7bf;color:#fd7f31}.pic-comb1{background-color:#d9ecbf;color:#65b500}.pic-comb4{background-color:#fdd3d7;color:#f64e60}.w-40px{width:40px}.h-40px{height:40px}.pic{border-radius:50%;overflow:hidden}.image-placeholder .pic{font-size:14px;font-weight:600;letter-spacing:.5px}.header-cell{font-weight:600}.header-cell,.cell{box-sizing:border-box}.transparent-border-right{border-right:1px solid transparent!important}.resizing-highlight{position:relative}.resizing-highlight:before{content:\"\";position:absolute;top:-1px;right:-1px;width:2px;height:calc(100% + 2px);background:#7cb9f6;z-index:1000;pointer-events:none}.resizing-highlight-right{position:relative}.resizing-highlight-right:before{content:\"\";position:absolute;top:-1px;left:-1px;width:2px;height:calc(100% + 2px);background:#7cb9f6;z-index:1000;pointer-events:none}.resizing-highlight-right:first-child{width:1px}.editable-header{border-bottom:1px dashed #666}.muted-text{color:#727272!important}.context-menu{position:fixed;display:none;background:#fff;border:1px solid #dcdcdc;box-shadow:#0000003d 0 3px 8px;z-index:1000;width:150px;border-radius:8px;font-weight:600}.context-menu.show{display:block}.context-menu ul{list-style:none;margin:0;padding:0}.context-menu li{padding:10px;cursor:pointer;color:#99a1b7}.context-menu li ::ng-deep svg{width:16px;height:16px;display:inline-block;color:#727272}.context-menu li ::ng-deep svg path{stroke:#727272}.context-menu li:hover{background-color:#f0f0f5!important}.invisible{visibility:hidden!important}.fw-500{font-weight:500!important}.taskbar{position:fixed;display:flex;justify-content:center;z-index:1000}.taskbar .action-btn{transition:opacity text-decoration .3s ease}.taskbar .action-btn:hover{text-decoration:underline;opacity:.8}.taskbar .delete{color:#ea0000}.selected-count,.action-btn,.dropdown-content a{font-weight:500;font-size:14px}.selected-rows-action-bar{background-color:#1a1a1a;color:#fff;padding:4px 24px;border-radius:8px;display:flex;align-items:center;justify-content:space-between;gap:24px;box-shadow:0 -4px 12px #00000026}.selected-rows-action-bar .btn:active,.selected-rows-action-bar .btn:focus{outline:0!important;border:0!important;border-color:transparent!important}.selected-rows-action-bar .action-btn{color:#fff!important}.cell .dropdown-menu,.cell .form-select,.cell input{color:#000!important}.cell input::placeholder{color:#727272!important}.cell .badge{border-radius:4px!important;height:24px;align-items:center;width:-moz-fit-content;width:fit-content}.cell .badge-danger{color:#ea5353!important;border:1px solid #ea5353!important;background-color:#ff00000d!important}.cell .badge-success{background-color:#84ca8130!important;border:1.5px solid rgb(70,227,114)!important;color:#46e372!important}.cell .badge-warning{background-color:#fff3dc!important;color:orange!important;border:1px solid #ffa000!important}.cell .badge-info{color:#00bad1;background-color:#e8fbfd;border:1px solid #00bad1}.cell .badge-secondary{color:#6c757d;background-color:#f1f3f5;border:1px solid #6c757d}.header-tag ::ng-deep svg path{stroke:#727272!important}.cross-secondary:hover ::ng-deep svg path{stroke:#000!important}.disable-sorting{pointer-events:none;opacity:.5}.rows-grouping-top-container ::ng-deep .cdk-drag-placeholder{background-color:transparent!important}input.is-invalid:focus{border:2.5px solid red!important;outline:none}.table-cell input.is-invalid:focus{border:2.5px solid red!important;outline-color:red!important;outline:none!important;box-shadow:none!important}.active-for-editing:has(input.is-invalid:focus){outline:none!important;box-shadow:none!important;border:0!important}.selected-cell,.row-selected{background-color:#c2e0fe}.first-row-selected{border-top:2px solid #2196f3!important}.last-row-selected{border-bottom:2px solid #2196f3!important}.left-selection-border{border-left:2px solid #2196f3!important}.s-no{font-size:14px;font-weight:500}.top-border{border-top:2px solid #2196f3!important}.bottom-border{border-bottom:2px solid #2196f3!important}.left-border{border-left:2px solid #2196f3!important}.border-left{border-left:1px solid #E0E0E0}.right-border{border-right:2px solid #2196f3!important}.top-left-corner{border-top-left-radius:4px}.top-right-corner{border-top-right-radius:4px}.bottom-left-corner{border-bottom-left-radius:4px}.bottom-right-corner{border-bottom-right-radius:4px}.flash-bg{animation:flashAnim 1000s ease}@keyframes flashAnim{0%{background-color:#48a2fc}50%{background-color:#c2e0fe}to{background-color:#c2e0fe}}.cut-flash-bg{animation:cut-flash .8s ease}@keyframes cut-flash{0%{background-color:#f006}50%{background-color:#f00c}to{background-color:#c2e0fe}}.accordion-details .center-section .table .tbody .tr:hover .td{background-color:#f0f8ff!important}.editing-dropdown-search-input input:focus{border:1px solid #86b7fe!important}.nested-table .thead{position:sticky;top:0}.dropdown-wrapper{position:relative;display:inline-block}.btn-icon{background:transparent;border:0;padding:.25rem .5rem;cursor:pointer}.custom-dropdown-menu{position:absolute;right:0;top:calc(100% + 6px);min-width:200px;list-style:none;margin:0;padding:.25rem 0;background:#fff!important;border:1px solid rgba(0,0,0,.08);box-shadow:0 6px 18px #00000014;border-radius:.35rem;z-index:1200}.custom-dropdown-menu .dropdown-item{display:block;width:100%;padding:.5rem 1rem;text-align:left;background:transparent;border:none}.custom-dropdown-menu .dropdown-item:hover{background:#00000008}.confirm-block{padding:0}.center-nested-table .tr:hover .td{background-color:#f0f8ff}.table ::ng-deep .cdk-drag-placeholder{background-color:#fff!important}.assets-pic{border-radius:8px!important}.fullscreen-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000c;display:flex;align-items:center;justify-content:center;z-index:1000;cursor:zoom-out}.fullscreen-img{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 0 15px #00000080}.position-sticky{z-index:2}.viewport{display:block!important;overflow:visible!important}.nested-table ::ng-deep .cdk-virtual-scroll-content-wrapper{padding:0!important}.nested-table ::ng-deep .cdk-virtual-scroll-viewport{overflow-x:hidden!important}.disabled-search-input{background-color:#f5f5f5;cursor:pointer!important}.right-click-menu-icons ::ng-deep svg path{stroke-width:2!important}.loader{animation:rotate 1s infinite;height:50px;width:50px}.loader:before,.loader:after{border-radius:50%;content:\"\";display:block;height:20px;width:20px}.loader:before{animation:ball1 1s infinite;background-color:#fff;box-shadow:30px 0 #ff3d00;margin-bottom:10px}.loader:after{animation:ball2 1s infinite;background-color:#ff3d00;box-shadow:30px 0 #fff}@keyframes rotate{0%{transform:rotate(0) scale(.8)}50%{transform:rotate(360deg) scale(1.2)}to{transform:rotate(720deg) scale(.8)}}@keyframes ball1{0%{box-shadow:30px 0 #ff3d00}50%{box-shadow:0 0 #ff3d00;margin-bottom:0;transform:translate(15px,15px)}to{box-shadow:30px 0 #ff3d00;margin-bottom:10px}}@keyframes ball2{0%{box-shadow:30px 0 #fff}50%{box-shadow:0 0 #fff;margin-top:-20px;transform:translate(15px,15px)}to{box-shadow:30px 0 #fff;margin-top:0}}.rows-grouping-top-container ::ng-deep .cdk-drag-placeholder{opacity:.7!important}.action-button{background-color:#6f61cf!important;color:#fff!important;border-radius:6px!important;font-weight:500!important;margin-top:-4px}.action-button:hover{background-color:#6a5fb3!important}.action-buttons-row .button{display:inline-flex;align-items:center;justify-content:center;overflow:hidden;color:#fff;border-radius:6px;height:34px;padding:0 10px;white-space:nowrap;transition:max-width .4s ease,background-color .3s ease;max-width:40px;background-color:transparent;border:1px solid #6F61CF}.action-buttons-row .button .label-hidden{opacity:0;margin-left:8px;transition:opacity .3s ease;pointer-events:none;display:none}.action-buttons-row .button:hover{max-width:200px;background-color:#6f61cf}.action-buttons-row .button:hover .label-hidden{opacity:1;pointer-events:auto;margin-left:8px!important;display:block}.action-buttons-row ::ng-deep .button .svg-icon svg path{stroke:#6f61cf;transition:fill .3s ease,stroke .3s ease}.action-buttons-row ::ng-deep .button:hover .svg-icon svg path{stroke:#fff!important}::ng-deep .nav-tabs .nav-link{border:none!important;border-bottom:2px solid transparent!important;border-radius:0!important;background:transparent!important}::ng-deep .nav-tabs .nav-link:hover,::ng-deep .nav-tabs .nav-link:focus{border:none!important;border-bottom:2px solid transparent!important;outline:none!important;background:transparent!important}::ng-deep .nav-tabs .nav-link.active{border:none!important;border-bottom:2px solid var(--bs-primary)!important;background:transparent!important;color:var(--bs-primary)!important}.open-top{top:-150%!important}.muted{color:#7a7a7a!important}.item-title{font-size:1.2em;font-weight:700;margin-bottom:10px}.item-image{width:100%;border-radius:10px}.comment{display:flex;align-items:center;margin-bottom:10px}.comment-avatar{width:40px;height:40px;border-radius:50%;margin-right:10px}.comment-author{font-weight:700}.comment-content{font-size:.9em;line-height:1.4}.comment-timestamp{font-size:.8em;color:#888;margin-left:auto}.des_low{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;width:242px;display:block;text-transform:capitalize!important}.firstDiv{word-break:break-word;overflow-wrap:break-word;white-space:normal}.container{display:flex;flex-wrap:wrap;margin:20px;gap:20px;background-color:#fff;padding:20px;border-radius:10px}.item{width:calc(33.33% - 20px);background-color:#fff;padding:20px;border-radius:10px;box-shadow:0 2px 5px #0000001a}.forCommentImg{width:70px;border-radius:16px;margin:8px 0;cursor:pointer}.image-modal img{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 4px 10px #00000080}.full-image-modal{position:fixed;background:#000c;display:flex;justify-content:center;align-items:center;z-index:1000}.full-image-modal .full-image{max-width:90%;max-height:90%;border-radius:8px;box-shadow:0 0 10px #fff3}.item-content{font-size:14px;line-height:1.5;max-height:220px;overflow-y:auto}.image-modal.full-image-modal{position:fixed;width:100vw;height:100vh;background-color:#000c;display:flex;justify-content:center;align-items:center;z-index:9999;overflow:hidden;cursor:zoom-out}.image-modal.full-image-modal img{border-radius:8px;box-shadow:0 4px 20px #0006;object-fit:contain;transition:transform .3s ease}.image-modal.full-image-modal img:hover{transform:scale(1.02)}::ng-deep .custom-overlay-wrapper .custom-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000000d9;display:flex;align-items:center;justify-content:center;z-index:9999}::ng-deep .custom-overlay-wrapper .custom-modal{background:#fff;border-radius:12px;box-shadow:0 8px 25px #0003;width:360px;max-width:90%;padding:24px;text-align:center;animation:fadeInScale .25s ease}::ng-deep .custom-overlay-wrapper .custom-modal-body .modal-message{font-size:16px;margin-bottom:20px;color:#333}::ng-deep .custom-overlay-wrapper .modal-actions{display:flex;justify-content:center;gap:12px}::ng-deep .custom-overlay-wrapper .modal-actions button{min-width:90px;padding:8px 14px;border-radius:6px;border:none;font-weight:500;cursor:pointer;transition:background-color .2s ease}::ng-deep .custom-overlay-wrapper .btn-confirm{background-color:#007bff;color:#fff}::ng-deep .custom-overlay-wrapper .btn-confirm:hover{background-color:#0069d9}::ng-deep .custom-overlay-wrapper .btn-cancel{background-color:#e4e4e4;color:#333}::ng-deep .custom-overlay-wrapper .btn-cancel:hover{background-color:#d6d6d6}@keyframes fadeInScale{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.clear-btn{background:linear-gradient(135deg,#f53545,#f53545);border:none;color:#fff;font-size:13px;padding:3px 6px;border-radius:20px;font-weight:500;display:inline-flex;align-items:center;gap:6px;cursor:pointer;transition:all .3s ease;box-shadow:0 2px 6px #ff5f6d66;position:relative;bottom:4px}.clear-btn:hover{transform:translateY(-2px);box-shadow:0 4px 10px #ff5f6d99;background:linear-gradient(135deg,#f53545,#f53545)}.clear-btn i{font-size:16px;vertical-align:middle}.cell-editin-dropdown .deopdown-item{width:100%!important;box-shadow:none!important;border-radius:4px;cursor:pointer;padding-block:8px!important}.cell-editin-dropdown .deopdown-item:hover{background-color:#f1f1f1}.card-outer{border:1px solid var(--semantics-border-subtle-secondary, #E0E0E0);border-radius:16px;padding:16px;background-color:#fff}.consumerDropdownButton{height:32px;display:flex;align-items:center}a.grid-header-icon:hover{background:#e0e0e0;width:32px;height:32px;border-radius:8px;transition:none}a.grid-header-icon{width:32px;height:32px}.action-buttons-row.active a.grid-header-icon,a.grid-header-icon.show{background-color:#e0e0e0;border-radius:8px}.data-grid-svg-icon.setting_dropdown{width:32px!important;height:32px!important}.new_design_dropdown .dropdown_main_button{color:#6a6b6d;text-decoration:none}.new_design_dropdown ul{border-radius:8px!important;border:1px solid #E0E0E0!important;box-shadow:0 0 12px #00000014!important}.new_design_dropdown ul li{color:#1b1f22!important;height:32px}.new_design_dropdown ul li:hover{background:#0084ff1a!important}.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg{height:inherit;border-radius:6px;padding:6px 10px;color:#1b1f22!important;font-size:14px;font-weight:400}.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg .new_old_filter{display:inline-block;width:24px;height:24px}.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg label,.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg span.newest,.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg span.oldest{padding-left:5px}.new_design_dropdown ul li a.dropdown-item.hover_dropdown_bg:hover{background-color:transparent!important}.new_design_dropdown ul li .action_dropdown{padding:6px 16px}.new_design_dropdown ul li.active-filter{background-color:#0084ff1a}.new_design_dropdown.hide_arrow .dropdown-toggle:after{display:none}.new_design_dropdown.hide_arrow ul li a label{line-height:1}.dropdown_main_button{border-radius:8px;transition:none;padding:5px 10px}.dropdown_main_button:hover,.dropdown_main_button.show{background:#e0e0e0}.sorting_icon_input{width:24px;height:24px;display:flex;align-items:center;justify-content:center}.sorting_dropdown .column-menu-item{padding:0 6px!important;color:#1b1f22!important;font-size:14px!important;font-weight:400!important}.greenBgHover{background:#0084ff1a!important;border-radius:6px!important}.cancel_btn_new{font-weight:400!important;font-size:14px!important;color:#1b1f22!important;border:none;box-shadow:none;background:transparent;height:32px;padding:3px 14px;display:flex;align-items:center;justify-content:center}.primary_btn_new{font-weight:500!important;font-size:14px!important;color:#fff!important;background:#0084ff;border:none;box-shadow:none;height:32px;padding:3px 14px;display:flex;align-items:center;justify-content:center;border-radius:6px}.dropdown_outer{border:1px solid #E0E0E0;box-shadow:0 2px 12px #00000014;border-radius:8px;font-size:14px}.text_common_14px{font-size:14px;font-weight:400;color:#1b1f22}.text_common_16px{font-size:16px;font-weight:500;color:#1b1f22}.page_refresh{font-size:13px;font-weight:400;color:#6a6b6d}\n"] }]
|
|
6344
6319
|
}], ctorParameters: function () { return [{ type: SplitColumnsService }, { type: i0.ChangeDetectorRef }, { type: CommonService }, { type: i0.ElementRef }, { type: i0.NgZone }, { type: CopyServiceService }, { type: i0.Renderer2 }, { type: i4.DomSanitizer }, { type: ExportService }, { type: i6.DatePipe }, { type: FormatCurrencyPipe }]; }, propDecorators: { rowAnimation: [{
|
|
6345
6320
|
type: Input
|
|
6346
6321
|
}], paginationConfig: [{
|
|
@@ -6499,7 +6474,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
6499
6474
|
type: Input
|
|
6500
6475
|
}], showCheckboxes: [{
|
|
6501
6476
|
type: Input
|
|
6502
|
-
}],
|
|
6477
|
+
}], consumerFont: [{
|
|
6478
|
+
type: Input
|
|
6479
|
+
}], defaultConfig: [{
|
|
6503
6480
|
type: Input
|
|
6504
6481
|
}], resetAllFilters: [{
|
|
6505
6482
|
type: Input
|
|
@@ -6508,6 +6485,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
6508
6485
|
}], cellHosts: [{
|
|
6509
6486
|
type: ViewChildren,
|
|
6510
6487
|
args: [CellHostDirective]
|
|
6488
|
+
}], globalSearchInput: [{
|
|
6489
|
+
type: ViewChild,
|
|
6490
|
+
args: ['globalSearchInput']
|
|
6511
6491
|
}], changeLayout: [{
|
|
6512
6492
|
type: Output
|
|
6513
6493
|
}], customCellEvent: [{
|
|
@@ -6608,6 +6588,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
6608
6588
|
args: ['fullscreenImageTemplate']
|
|
6609
6589
|
}] } });
|
|
6610
6590
|
|
|
6591
|
+
class CellEditorDirective {
|
|
6592
|
+
constructor(vcr, injector) {
|
|
6593
|
+
this.vcr = vcr;
|
|
6594
|
+
this.injector = injector;
|
|
6595
|
+
// Parent component listens using:
|
|
6596
|
+
// (editorEvent)="finishEdit($event)"
|
|
6597
|
+
this.editorEvent = new EventEmitter();
|
|
6598
|
+
}
|
|
6599
|
+
ngOnInit() {
|
|
6600
|
+
if (!this.componentType)
|
|
6601
|
+
return;
|
|
6602
|
+
// ✅ Dynamically create the editor component
|
|
6603
|
+
const componentRef = this.vcr.createComponent(this.componentType, {
|
|
6604
|
+
injector: Injector.create({
|
|
6605
|
+
providers: [
|
|
6606
|
+
{ provide: 'rowData', useValue: this.rowData },
|
|
6607
|
+
{ provide: 'colData', useValue: this.colData },
|
|
6608
|
+
{ provide: 'cellValue', useValue: this.cellValue }
|
|
6609
|
+
],
|
|
6610
|
+
parent: this.injector
|
|
6611
|
+
})
|
|
6612
|
+
});
|
|
6613
|
+
// -----------------------------------------------
|
|
6614
|
+
// 1️⃣ Call custom lifecycle hook if it exists
|
|
6615
|
+
// -----------------------------------------------
|
|
6616
|
+
if (typeof componentRef.instance.editorInit === 'function') {
|
|
6617
|
+
componentRef.instance.editorInit({
|
|
6618
|
+
row: this.rowData,
|
|
6619
|
+
col: this.colData,
|
|
6620
|
+
value: this.cellValue
|
|
6621
|
+
});
|
|
6622
|
+
}
|
|
6623
|
+
// -----------------------------------------------
|
|
6624
|
+
// 2️⃣ Auto-detect all @Output() EventEmitters
|
|
6625
|
+
// -----------------------------------------------
|
|
6626
|
+
for (const key of Object.keys(componentRef.instance)) {
|
|
6627
|
+
const property = componentRef.instance[key];
|
|
6628
|
+
// Check if any property is an EventEmitter
|
|
6629
|
+
if (property instanceof EventEmitter) {
|
|
6630
|
+
property.subscribe((value) => {
|
|
6631
|
+
this.editorEvent.emit({
|
|
6632
|
+
eventName: key,
|
|
6633
|
+
data: {
|
|
6634
|
+
row: this.rowData,
|
|
6635
|
+
col: this.colData,
|
|
6636
|
+
value
|
|
6637
|
+
}
|
|
6638
|
+
});
|
|
6639
|
+
});
|
|
6640
|
+
}
|
|
6641
|
+
}
|
|
6642
|
+
}
|
|
6643
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellEditorDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
6644
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: CellEditorDirective, selector: "[cellEditor]", inputs: { componentType: ["cellEditor", "componentType"], rowData: "rowData", colData: "colData", cellValue: "cellValue" }, outputs: { editorEvent: "editorEvent" }, ngImport: i0 }); }
|
|
6645
|
+
}
|
|
6646
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellEditorDirective, decorators: [{
|
|
6647
|
+
type: Directive,
|
|
6648
|
+
args: [{
|
|
6649
|
+
selector: '[cellEditor]'
|
|
6650
|
+
}]
|
|
6651
|
+
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.Injector }]; }, propDecorators: { componentType: [{
|
|
6652
|
+
type: Input,
|
|
6653
|
+
args: ['cellEditor']
|
|
6654
|
+
}], rowData: [{
|
|
6655
|
+
type: Input
|
|
6656
|
+
}], colData: [{
|
|
6657
|
+
type: Input
|
|
6658
|
+
}], cellValue: [{
|
|
6659
|
+
type: Input
|
|
6660
|
+
}], editorEvent: [{
|
|
6661
|
+
type: Output
|
|
6662
|
+
}] } });
|
|
6663
|
+
|
|
6611
6664
|
// format-index.pipe.ts
|
|
6612
6665
|
class FormatIndexPipe {
|
|
6613
6666
|
transform(value) {
|
|
@@ -6647,6 +6700,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
6647
6700
|
/*
|
|
6648
6701
|
* Public API Surface of data-grid
|
|
6649
6702
|
*/
|
|
6703
|
+
// import './lib/styles/styles.css';
|
|
6650
6704
|
|
|
6651
6705
|
/**
|
|
6652
6706
|
* Generated bundle index. Do not edit.
|