eru-grid 0.0.18 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/eru-grid.mjs +261 -929
- package/fesm2022/eru-grid.mjs.map +1 -1
- package/index.d.ts +46 -206
- package/package.json +1 -1
package/fesm2022/eru-grid.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Injectable, inject, signal, computed, DOCUMENT, effect, Directive, InjectionToken, forwardRef, Input, Component, ElementRef, input, ChangeDetectorRef, model, Renderer2, ViewChild, ViewEncapsulation, ChangeDetectionStrategy, HostListener } from '@angular/core';
|
|
3
|
-
import { of, delay } from 'rxjs';
|
|
4
3
|
import * as i2$1 from '@angular/common';
|
|
5
4
|
import { NgFor, NgIf, NgClass, DatePipe, CommonModule } from '@angular/common';
|
|
6
5
|
import { CdkListbox, CdkOption } from '@angular/cdk/listbox';
|
|
@@ -101,53 +100,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
101
100
|
}]
|
|
102
101
|
}] });
|
|
103
102
|
|
|
104
|
-
/**
|
|
105
|
-
* Type definitions for Excel export functionality
|
|
106
|
-
*/
|
|
107
|
-
/**
|
|
108
|
-
* Type guard to check if a property is a cell reference (not a special Excel property)
|
|
109
|
-
*/
|
|
110
|
-
function isCellReference(key) {
|
|
111
|
-
return !key.startsWith('!');
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Type guard to check if a property is a special Excel property
|
|
115
|
-
*/
|
|
116
|
-
function isExcelSpecialProperty(key) {
|
|
117
|
-
return key.startsWith('!');
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Color palette for Excel export styling
|
|
121
|
-
*/
|
|
122
|
-
const EXCEL_COLORS = {
|
|
123
|
-
// Header colors (blue gradient)
|
|
124
|
-
HEADER_PRIMARY: '4472C4',
|
|
125
|
-
HEADER_SECONDARY: '5B9BD5',
|
|
126
|
-
HEADER_TERTIARY: 'A5A5A5',
|
|
127
|
-
HEADER_QUATERNARY: '70AD47',
|
|
128
|
-
// Subtotal colors
|
|
129
|
-
SUBTOTAL_HEADER: 'FFD700', // Gold
|
|
130
|
-
SUBTOTAL_ROW: 'F0F8FF', // Light blue
|
|
131
|
-
GRAND_TOTAL_ROW: 'E6E6FA', // Light purple
|
|
132
|
-
// Border colors
|
|
133
|
-
BORDER_DARK: '000000', // Black
|
|
134
|
-
BORDER_LIGHT: 'CCCCCC', // Light gray
|
|
135
|
-
// Text colors
|
|
136
|
-
TEXT_WHITE: 'FFFFFF',
|
|
137
|
-
TEXT_BLACK: '000000',
|
|
138
|
-
TEXT_DARK: '333333'
|
|
139
|
-
};
|
|
140
|
-
/**
|
|
141
|
-
* Default Excel export configuration
|
|
142
|
-
*/
|
|
143
|
-
const DEFAULT_EXCEL_CONFIG = {
|
|
144
|
-
filename: 'pivot-table.xlsx',
|
|
145
|
-
sheetName: 'Pivot Table',
|
|
146
|
-
includeHeaders: true,
|
|
147
|
-
includeStyling: true,
|
|
148
|
-
includeMerges: true
|
|
149
|
-
};
|
|
150
|
-
|
|
151
103
|
class PivotTransformService {
|
|
152
104
|
columnGroupState = {};
|
|
153
105
|
/**
|
|
@@ -1848,352 +1800,12 @@ class PivotTransformService {
|
|
|
1848
1800
|
}
|
|
1849
1801
|
return groups;
|
|
1850
1802
|
}
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
return pivotResult.columnDefinitions.map(col => {
|
|
1858
|
-
const value = row[col.name];
|
|
1859
|
-
return typeof value === 'string' && value.includes(',')
|
|
1860
|
-
? `"${value}"`
|
|
1861
|
-
: value || '';
|
|
1862
|
-
}).join(',');
|
|
1863
|
-
});
|
|
1864
|
-
return [headers, ...rows].join('\n');
|
|
1865
|
-
}
|
|
1866
|
-
/**
|
|
1867
|
-
* Export pivot data to Excel format with proper formatting, cell merging, and styling
|
|
1868
|
-
* Returns a workbook object compatible with xlsx library
|
|
1869
|
-
*/
|
|
1870
|
-
exportToExcel(pivotResult, options) {
|
|
1871
|
-
const { data, columnDefinitions, headerStructure, configuration } = pivotResult;
|
|
1872
|
-
const exportOptions = { ...DEFAULT_EXCEL_CONFIG, ...options };
|
|
1873
|
-
if (!headerStructure) {
|
|
1874
|
-
throw new Error('Header structure is required for Excel export');
|
|
1875
|
-
}
|
|
1876
|
-
// Use simplified approach that works reliably
|
|
1877
|
-
const sheet = this.createSimplifiedXlsxSheet(data, columnDefinitions, headerStructure, configuration, exportOptions);
|
|
1878
|
-
const workbook = {
|
|
1879
|
-
SheetNames: [exportOptions.sheetName],
|
|
1880
|
-
Sheets: {
|
|
1881
|
-
[exportOptions.sheetName]: sheet
|
|
1882
|
-
}
|
|
1883
|
-
};
|
|
1884
|
-
return workbook;
|
|
1885
|
-
}
|
|
1886
|
-
/**
|
|
1887
|
-
* Export pivot data to Excel file using xlsx library
|
|
1888
|
-
* This method requires the xlsx library to be installed: npm install xlsx
|
|
1889
|
-
* Usage:
|
|
1890
|
-
* import * as XLSX from 'xlsx';
|
|
1891
|
-
* const workbook = pivotService.exportToExcel(pivotResult);
|
|
1892
|
-
* XLSX.writeFile(workbook, 'pivot-table.xlsx');
|
|
1893
|
-
*/
|
|
1894
|
-
exportToExcelFile(pivotResult, filename = 'pivot-table.xlsx') {
|
|
1895
|
-
const workbook = this.exportToExcel(pivotResult);
|
|
1896
|
-
// This requires xlsx library
|
|
1897
|
-
// import * as XLSX from 'xlsx';
|
|
1898
|
-
// XLSX.writeFile(workbook, filename);
|
|
1899
|
-
console.log('Excel workbook created. Use XLSX.writeFile(workbook, filename) to save the file.');
|
|
1900
|
-
console.log('Workbook structure:', workbook);
|
|
1901
|
-
}
|
|
1902
|
-
/**
|
|
1903
|
-
* Create xlsx-compatible sheet with proper formatting and cell merging
|
|
1904
|
-
*/
|
|
1905
|
-
createXlsxSheet(data, columnDefinitions, headerStructure, rowspanInfo, configuration, options) {
|
|
1906
|
-
const sheet = {};
|
|
1907
|
-
const merges = [];
|
|
1908
|
-
// Start row for data (after headers)
|
|
1909
|
-
let currentRow = headerStructure.maxDepth + 1;
|
|
1910
|
-
// Add header rows with proper formatting
|
|
1911
|
-
if (options.includeHeaders) {
|
|
1912
|
-
this.addXlsxHeaders(sheet, headerStructure, merges, options);
|
|
1913
|
-
}
|
|
1914
|
-
// Add data rows with rowspan handling
|
|
1915
|
-
this.addXlsxDataRows(sheet, data, columnDefinitions, rowspanInfo, currentRow, merges, options);
|
|
1916
|
-
// Set column widths
|
|
1917
|
-
this.setXlsxColumnWidths(sheet, columnDefinitions);
|
|
1918
|
-
// Set merge ranges - only if we have valid merges
|
|
1919
|
-
if (options.includeMerges && merges.length > 0) {
|
|
1920
|
-
// Filter out invalid merges
|
|
1921
|
-
const validMerges = merges.filter(merge => merge.s && merge.e &&
|
|
1922
|
-
merge.s.r >= 0 && merge.s.c >= 0 &&
|
|
1923
|
-
merge.e.r >= 0 && merge.e.c >= 0 &&
|
|
1924
|
-
merge.s.r <= merge.e.r && merge.s.c <= merge.e.c);
|
|
1925
|
-
if (validMerges.length > 0) {
|
|
1926
|
-
sheet['!merges'] = validMerges;
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
// Set sheet range
|
|
1930
|
-
const range = this.getXlsxRange(sheet);
|
|
1931
|
-
if (range) {
|
|
1932
|
-
sheet['!ref'] = range;
|
|
1933
|
-
}
|
|
1934
|
-
return sheet;
|
|
1935
|
-
}
|
|
1936
|
-
/**
|
|
1937
|
-
* Create Excel sheet with proper formatting and cell merging (legacy method)
|
|
1938
|
-
*/
|
|
1939
|
-
createExcelSheet(data, columnDefinitions, headerStructure, rowspanInfo, configuration, options) {
|
|
1940
|
-
const sheet = {};
|
|
1941
|
-
// Define cell ranges for merging
|
|
1942
|
-
const merges = [];
|
|
1943
|
-
// Start row for data (after headers)
|
|
1944
|
-
let currentRow = headerStructure.maxDepth + 1;
|
|
1945
|
-
// Add header rows with proper formatting
|
|
1946
|
-
if (options.includeHeaders) {
|
|
1947
|
-
this.addExcelHeaders(sheet, headerStructure, merges, options);
|
|
1948
|
-
}
|
|
1949
|
-
// Add data rows with rowspan handling
|
|
1950
|
-
this.addExcelDataRows(sheet, data, columnDefinitions, rowspanInfo, currentRow, merges, options);
|
|
1951
|
-
// Set column widths
|
|
1952
|
-
this.setExcelColumnWidths(sheet, columnDefinitions);
|
|
1953
|
-
// Apply styling
|
|
1954
|
-
if (options.includeStyling) {
|
|
1955
|
-
this.applyExcelStyling(sheet, headerStructure, data, configuration);
|
|
1956
|
-
}
|
|
1957
|
-
// Set merge ranges
|
|
1958
|
-
if (options.includeMerges) {
|
|
1959
|
-
sheet['!merges'] = merges.map(range => {
|
|
1960
|
-
const [startCell, endCell] = range.split(':');
|
|
1961
|
-
const startRef = this.parseExcelCellRef(startCell);
|
|
1962
|
-
const endRef = this.parseExcelCellRef(endCell);
|
|
1963
|
-
return {
|
|
1964
|
-
s: { r: startRef.row, c: startRef.col },
|
|
1965
|
-
e: { r: endRef.row, c: endRef.col }
|
|
1966
|
-
};
|
|
1967
|
-
});
|
|
1968
|
-
}
|
|
1969
|
-
return sheet;
|
|
1970
|
-
}
|
|
1971
|
-
/**
|
|
1972
|
-
* Add Excel header rows with proper formatting and merging
|
|
1973
|
-
*/
|
|
1974
|
-
addExcelHeaders(sheet, headerStructure, merges, options) {
|
|
1975
|
-
const { headerRows, maxDepth } = headerStructure;
|
|
1976
|
-
headerRows.forEach((headerRow, rowIndex) => {
|
|
1977
|
-
headerRow.forEach((header, colIndex) => {
|
|
1978
|
-
const cellRef = this.getExcelCellRef(rowIndex, colIndex);
|
|
1979
|
-
sheet[cellRef] = {
|
|
1980
|
-
v: header.label,
|
|
1981
|
-
t: 's',
|
|
1982
|
-
s: this.getHeaderCellStyle(header, rowIndex, maxDepth)
|
|
1983
|
-
};
|
|
1984
|
-
// Add merge ranges for headers with colspan > 1
|
|
1985
|
-
if (header.colspan > 1) {
|
|
1986
|
-
const endCol = colIndex + header.colspan - 1;
|
|
1987
|
-
const mergeRange = `${cellRef}:${this.getExcelCellRef(rowIndex, endCol)}`;
|
|
1988
|
-
merges.push(mergeRange);
|
|
1989
|
-
}
|
|
1990
|
-
// Add merge ranges for headers with rowspan > 1
|
|
1991
|
-
if (header.rowspan > 1) {
|
|
1992
|
-
const endRow = rowIndex + header.rowspan - 1;
|
|
1993
|
-
const mergeRange = `${cellRef}:${this.getExcelCellRef(endRow, colIndex)}`;
|
|
1994
|
-
merges.push(mergeRange);
|
|
1995
|
-
}
|
|
1996
|
-
});
|
|
1997
|
-
});
|
|
1998
|
-
}
|
|
1999
|
-
/**
|
|
2000
|
-
* Add Excel data rows with rowspan handling
|
|
2001
|
-
*/
|
|
2002
|
-
addExcelDataRows(sheet, data, columnDefinitions, rowspanInfo, startRow, merges, options) {
|
|
2003
|
-
data.forEach((row, rowIndex) => {
|
|
2004
|
-
const excelRowIndex = startRow + rowIndex;
|
|
2005
|
-
columnDefinitions.forEach((col, colIndex) => {
|
|
2006
|
-
const cellRef = this.getExcelCellRef(excelRowIndex, colIndex);
|
|
2007
|
-
const value = row[col.name];
|
|
2008
|
-
// Check if this cell should be merged (rowspan)
|
|
2009
|
-
const rowspanKey = `${rowIndex}_${col.name}`;
|
|
2010
|
-
const spanInfo = rowspanInfo.get(rowspanKey);
|
|
2011
|
-
if (spanInfo && spanInfo.skip) {
|
|
2012
|
-
// Skip this cell as it's merged with a previous cell
|
|
2013
|
-
return;
|
|
2014
|
-
}
|
|
2015
|
-
// Set cell value and style
|
|
2016
|
-
sheet[cellRef] = {
|
|
2017
|
-
v: this.formatExcelValue(value, col.datatype),
|
|
2018
|
-
t: this.getExcelValueType(value, col.datatype),
|
|
2019
|
-
s: this.getDataCellStyle(row, col, spanInfo)
|
|
2020
|
-
};
|
|
2021
|
-
// Add merge range if this cell has rowspan > 1
|
|
2022
|
-
if (spanInfo && spanInfo.rowspan > 1) {
|
|
2023
|
-
const endRow = excelRowIndex + spanInfo.rowspan - 1;
|
|
2024
|
-
const mergeRange = `${cellRef}:${this.getExcelCellRef(endRow, colIndex)}`;
|
|
2025
|
-
merges.push(mergeRange);
|
|
2026
|
-
}
|
|
2027
|
-
});
|
|
2028
|
-
});
|
|
2029
|
-
}
|
|
2030
|
-
/**
|
|
2031
|
-
* Get Excel cell reference (e.g., A1, B2, etc.)
|
|
2032
|
-
*/
|
|
2033
|
-
getExcelCellRef(row, col) {
|
|
2034
|
-
const colLetter = this.getExcelColumnLetter(col);
|
|
2035
|
-
return `${colLetter}${row + 1}`;
|
|
2036
|
-
}
|
|
2037
|
-
/**
|
|
2038
|
-
* Convert column index to Excel column letter
|
|
2039
|
-
*/
|
|
2040
|
-
getExcelColumnLetter(col) {
|
|
2041
|
-
let result = '';
|
|
2042
|
-
while (col >= 0) {
|
|
2043
|
-
result = String.fromCharCode(65 + (col % 26)) + result;
|
|
2044
|
-
col = Math.floor(col / 26) - 1;
|
|
2045
|
-
}
|
|
2046
|
-
return result;
|
|
2047
|
-
}
|
|
2048
|
-
/**
|
|
2049
|
-
* Format value for Excel based on data type
|
|
2050
|
-
*/
|
|
2051
|
-
formatExcelValue(value, datatype) {
|
|
2052
|
-
if (value === null || value === undefined)
|
|
2053
|
-
return '';
|
|
2054
|
-
switch (datatype) {
|
|
2055
|
-
case 'number':
|
|
2056
|
-
case 'currency':
|
|
2057
|
-
return typeof value === 'number' ? value : parseFloat(value) || 0;
|
|
2058
|
-
case 'date':
|
|
2059
|
-
return value instanceof Date ? value : new Date(value);
|
|
2060
|
-
default:
|
|
2061
|
-
return String(value);
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
/**
|
|
2065
|
-
* Get Excel value type
|
|
2066
|
-
*/
|
|
2067
|
-
getExcelValueType(value, datatype) {
|
|
2068
|
-
if (value === null || value === undefined)
|
|
2069
|
-
return 's';
|
|
2070
|
-
switch (datatype) {
|
|
2071
|
-
case 'number':
|
|
2072
|
-
case 'currency':
|
|
2073
|
-
return 'n';
|
|
2074
|
-
case 'date':
|
|
2075
|
-
return 'd';
|
|
2076
|
-
default:
|
|
2077
|
-
return 's';
|
|
2078
|
-
}
|
|
2079
|
-
}
|
|
2080
|
-
/**
|
|
2081
|
-
* Get header cell style
|
|
2082
|
-
*/
|
|
2083
|
-
getHeaderCellStyle(header, rowIndex, maxDepth) {
|
|
2084
|
-
const baseStyle = {
|
|
2085
|
-
font: { bold: true, color: { rgb: EXCEL_COLORS.TEXT_WHITE } },
|
|
2086
|
-
fill: { fgColor: { rgb: this.getHeaderColor(rowIndex, maxDepth) } },
|
|
2087
|
-
alignment: { horizontal: 'center', vertical: 'center' },
|
|
2088
|
-
border: {
|
|
2089
|
-
top: { style: 'thin', color: { rgb: EXCEL_COLORS.BORDER_DARK } },
|
|
2090
|
-
bottom: { style: 'thin', color: { rgb: EXCEL_COLORS.BORDER_DARK } },
|
|
2091
|
-
left: { style: 'thin', color: { rgb: EXCEL_COLORS.BORDER_DARK } },
|
|
2092
|
-
right: { style: 'thin', color: { rgb: EXCEL_COLORS.BORDER_DARK } }
|
|
2093
|
-
}
|
|
2094
|
-
};
|
|
2095
|
-
// Special styling for subtotals
|
|
2096
|
-
if (header.isSubtotal) {
|
|
2097
|
-
baseStyle.fill.fgColor.rgb = EXCEL_COLORS.SUBTOTAL_HEADER;
|
|
2098
|
-
baseStyle.font.color.rgb = EXCEL_COLORS.TEXT_BLACK;
|
|
2099
|
-
}
|
|
2100
|
-
return baseStyle;
|
|
2101
|
-
}
|
|
2102
|
-
/**
|
|
2103
|
-
* Get data cell style
|
|
2104
|
-
*/
|
|
2105
|
-
getDataCellStyle(row, col, spanInfo) {
|
|
2106
|
-
const baseStyle = {
|
|
2107
|
-
alignment: { horizontal: 'center', vertical: 'center' },
|
|
2108
|
-
border: {
|
|
2109
|
-
top: { style: 'thin', color: { rgb: EXCEL_COLORS.BORDER_LIGHT } },
|
|
2110
|
-
bottom: { style: 'thin', color: { rgb: EXCEL_COLORS.BORDER_LIGHT } },
|
|
2111
|
-
left: { style: 'thin', color: { rgb: EXCEL_COLORS.BORDER_LIGHT } },
|
|
2112
|
-
right: { style: 'thin', color: { rgb: EXCEL_COLORS.BORDER_LIGHT } }
|
|
2113
|
-
}
|
|
2114
|
-
};
|
|
2115
|
-
// Special styling for subtotal and grand total rows
|
|
2116
|
-
if (row._isSubtotal) {
|
|
2117
|
-
baseStyle.fill = { fgColor: { rgb: EXCEL_COLORS.SUBTOTAL_ROW } };
|
|
2118
|
-
baseStyle.font = { bold: true };
|
|
2119
|
-
}
|
|
2120
|
-
else if (row._isGrandTotal) {
|
|
2121
|
-
baseStyle.fill = { fgColor: { rgb: EXCEL_COLORS.GRAND_TOTAL_ROW } };
|
|
2122
|
-
baseStyle.font = { bold: true };
|
|
2123
|
-
}
|
|
2124
|
-
// Number formatting
|
|
2125
|
-
if (col.datatype === 'number' || col.datatype === 'currency') {
|
|
2126
|
-
baseStyle.numFmt = col.datatype === 'currency' ? '$#,##0.00' : '#,##0.00';
|
|
2127
|
-
}
|
|
2128
|
-
return baseStyle;
|
|
2129
|
-
}
|
|
2130
|
-
/**
|
|
2131
|
-
* Get header color based on row index and depth
|
|
2132
|
-
*/
|
|
2133
|
-
getHeaderColor(rowIndex, maxDepth) {
|
|
2134
|
-
const colors = [
|
|
2135
|
-
EXCEL_COLORS.HEADER_PRIMARY,
|
|
2136
|
-
EXCEL_COLORS.HEADER_SECONDARY,
|
|
2137
|
-
EXCEL_COLORS.HEADER_TERTIARY,
|
|
2138
|
-
EXCEL_COLORS.HEADER_QUATERNARY
|
|
2139
|
-
];
|
|
2140
|
-
return colors[rowIndex % colors.length];
|
|
2141
|
-
}
|
|
2142
|
-
/**
|
|
2143
|
-
* Set column widths based on field definitions
|
|
2144
|
-
*/
|
|
2145
|
-
setExcelColumnWidths(sheet, columnDefinitions) {
|
|
2146
|
-
const colWidths = [];
|
|
2147
|
-
columnDefinitions.forEach(col => {
|
|
2148
|
-
// Convert field_size to Excel column width (Excel uses character units)
|
|
2149
|
-
const width = Math.max(col.field_size / 7, 10); // Minimum width of 10
|
|
2150
|
-
colWidths.push({ wch: width });
|
|
2151
|
-
});
|
|
2152
|
-
sheet['!cols'] = colWidths;
|
|
2153
|
-
}
|
|
2154
|
-
/**
|
|
2155
|
-
* Apply additional Excel styling
|
|
2156
|
-
*/
|
|
2157
|
-
applyExcelStyling(sheet, headerStructure, data, configuration) {
|
|
2158
|
-
// Set sheet properties
|
|
2159
|
-
sheet['!ref'] = this.getExcelRange(headerStructure.maxDepth + data.length + 1, configuration.rows.length + 10);
|
|
2160
|
-
// Add freeze panes (freeze header rows)
|
|
2161
|
-
sheet['!freeze'] = { xSplit: configuration.rows.length, ySplit: headerStructure.maxDepth };
|
|
2162
|
-
// Set print settings
|
|
2163
|
-
sheet['!print'] = {
|
|
2164
|
-
orientation: 'landscape',
|
|
2165
|
-
fitToPage: true,
|
|
2166
|
-
fitToWidth: 1,
|
|
2167
|
-
fitToHeight: 0
|
|
2168
|
-
};
|
|
2169
|
-
}
|
|
2170
|
-
/**
|
|
2171
|
-
* Get Excel range reference
|
|
2172
|
-
*/
|
|
2173
|
-
getExcelRange(maxRow, maxCol) {
|
|
2174
|
-
const startCell = this.getExcelCellRef(0, 0);
|
|
2175
|
-
const endCell = this.getExcelCellRef(maxRow - 1, maxCol - 1);
|
|
2176
|
-
return `${startCell}:${endCell}`;
|
|
2177
|
-
}
|
|
2178
|
-
/**
|
|
2179
|
-
* Parse Excel cell reference to row and column indices
|
|
2180
|
-
*/
|
|
2181
|
-
parseExcelCellRef(cellRef) {
|
|
2182
|
-
const match = cellRef.match(/^([A-Z]+)(\d+)$/);
|
|
2183
|
-
if (!match) {
|
|
2184
|
-
throw new Error(`Invalid cell reference: ${cellRef}`);
|
|
2185
|
-
}
|
|
2186
|
-
const colStr = match[1];
|
|
2187
|
-
const rowStr = match[2];
|
|
2188
|
-
// Convert column letters to index
|
|
2189
|
-
let col = 0;
|
|
2190
|
-
for (let i = 0; i < colStr.length; i++) {
|
|
2191
|
-
col = col * 26 + (colStr.charCodeAt(i) - 64);
|
|
2192
|
-
}
|
|
2193
|
-
col -= 1; // Convert to 0-based index
|
|
2194
|
-
const row = parseInt(rowStr) - 1; // Convert to 0-based index
|
|
2195
|
-
return { row, col };
|
|
2196
|
-
}
|
|
1803
|
+
// Excel/CSV export methods removed
|
|
1804
|
+
// Export functionality should be implemented in the consuming application
|
|
1805
|
+
// Previously removed methods: exportToCsv, exportToExcel, exportToExcelFile, createXlsxSheet,
|
|
1806
|
+
// createSimplifiedXlsxSheet, addXlsxHeaders, addXlsxDataRows, setXlsxColumnWidths,
|
|
1807
|
+
// applyXlsxStyling, getXlsxHeaderStyle, getXlsxDataStyle, formatXlsxValue,
|
|
1808
|
+
// getXlsxValueType, getXlsxRange, generateRowKeyForExcel, and all xlsx helper methods
|
|
2197
1809
|
/**
|
|
2198
1810
|
* Initialize column group state based on configuration
|
|
2199
1811
|
*/
|
|
@@ -2749,264 +2361,6 @@ class PivotTransformService {
|
|
|
2749
2361
|
});
|
|
2750
2362
|
return groups;
|
|
2751
2363
|
}
|
|
2752
|
-
// ==================== XLSX-COMPATIBLE METHODS ====================
|
|
2753
|
-
/**
|
|
2754
|
-
* Create simplified xlsx sheet that works reliably without complex merging
|
|
2755
|
-
*/
|
|
2756
|
-
createSimplifiedXlsxSheet(data, columnDefinitions, headerStructure, configuration, options) {
|
|
2757
|
-
const sheet = {};
|
|
2758
|
-
let rowIndex = 1;
|
|
2759
|
-
// Add headers from header structure
|
|
2760
|
-
if (options.includeHeaders && headerStructure.headerRows) {
|
|
2761
|
-
headerStructure.headerRows.forEach((headerRow, headerRowIndex) => {
|
|
2762
|
-
headerRow.forEach((header, colIndex) => {
|
|
2763
|
-
const cellRef = this.getExcelCellRef(headerRowIndex, colIndex);
|
|
2764
|
-
sheet[cellRef] = {
|
|
2765
|
-
v: header.label,
|
|
2766
|
-
t: 's',
|
|
2767
|
-
s: {
|
|
2768
|
-
font: { bold: true, color: { rgb: EXCEL_COLORS.TEXT_WHITE } },
|
|
2769
|
-
fill: { fgColor: { rgb: EXCEL_COLORS.HEADER_PRIMARY } },
|
|
2770
|
-
alignment: { horizontal: 'center', vertical: 'center' }
|
|
2771
|
-
}
|
|
2772
|
-
};
|
|
2773
|
-
});
|
|
2774
|
-
rowIndex++;
|
|
2775
|
-
});
|
|
2776
|
-
}
|
|
2777
|
-
else {
|
|
2778
|
-
// Fallback: simple headers from column definitions
|
|
2779
|
-
columnDefinitions.forEach((col, colIndex) => {
|
|
2780
|
-
const cellRef = this.getExcelCellRef(0, colIndex);
|
|
2781
|
-
sheet[cellRef] = {
|
|
2782
|
-
v: col.label || col.name,
|
|
2783
|
-
t: 's',
|
|
2784
|
-
s: {
|
|
2785
|
-
font: { bold: true, color: { rgb: EXCEL_COLORS.TEXT_WHITE } },
|
|
2786
|
-
fill: { fgColor: { rgb: EXCEL_COLORS.HEADER_PRIMARY } },
|
|
2787
|
-
alignment: { horizontal: 'center', vertical: 'center' }
|
|
2788
|
-
}
|
|
2789
|
-
};
|
|
2790
|
-
});
|
|
2791
|
-
rowIndex = 2;
|
|
2792
|
-
}
|
|
2793
|
-
// Add data rows
|
|
2794
|
-
data.forEach((row) => {
|
|
2795
|
-
columnDefinitions.forEach((col, colIndex) => {
|
|
2796
|
-
const cellRef = this.getExcelCellRef(rowIndex - 1, colIndex);
|
|
2797
|
-
const value = row[col.name];
|
|
2798
|
-
let cellStyle = {
|
|
2799
|
-
alignment: { horizontal: 'center', vertical: 'center' }
|
|
2800
|
-
};
|
|
2801
|
-
// Add styling for special rows
|
|
2802
|
-
if (row['isGrandTotal']) {
|
|
2803
|
-
cellStyle.font = { bold: true };
|
|
2804
|
-
cellStyle.fill = { fgColor: { rgb: EXCEL_COLORS.GRAND_TOTAL_ROW } };
|
|
2805
|
-
}
|
|
2806
|
-
else if (row['isSubtotal']) {
|
|
2807
|
-
cellStyle.font = { bold: true };
|
|
2808
|
-
cellStyle.fill = { fgColor: { rgb: EXCEL_COLORS.SUBTOTAL_ROW } };
|
|
2809
|
-
}
|
|
2810
|
-
sheet[cellRef] = {
|
|
2811
|
-
v: this.formatXlsxValue(value, col.datatype),
|
|
2812
|
-
t: this.getXlsxValueType(col.datatype),
|
|
2813
|
-
s: cellStyle
|
|
2814
|
-
};
|
|
2815
|
-
});
|
|
2816
|
-
rowIndex++;
|
|
2817
|
-
});
|
|
2818
|
-
// Set range
|
|
2819
|
-
const maxCol = columnDefinitions.length - 1;
|
|
2820
|
-
const maxRow = rowIndex - 1;
|
|
2821
|
-
sheet['!ref'] = `A1:${this.getExcelCellRef(maxRow - 1, maxCol)}`;
|
|
2822
|
-
// Set column widths
|
|
2823
|
-
sheet['!cols'] = columnDefinitions.map(col => ({
|
|
2824
|
-
wch: Math.max(col.label?.length || col.name.length, 15)
|
|
2825
|
-
}));
|
|
2826
|
-
return sheet;
|
|
2827
|
-
}
|
|
2828
|
-
/**
|
|
2829
|
-
* Add headers to xlsx sheet with proper formatting
|
|
2830
|
-
*/
|
|
2831
|
-
addXlsxHeaders(sheet, headerStructure, merges, options) {
|
|
2832
|
-
const { headerRows } = headerStructure;
|
|
2833
|
-
// Add each header row
|
|
2834
|
-
headerRows.forEach((headerRow, rowIndex) => {
|
|
2835
|
-
headerRow.forEach((header, colIndex) => {
|
|
2836
|
-
const cellRef = this.getExcelCellRef(rowIndex, colIndex);
|
|
2837
|
-
const cell = {
|
|
2838
|
-
v: header.label,
|
|
2839
|
-
t: 's'
|
|
2840
|
-
};
|
|
2841
|
-
// Add styling
|
|
2842
|
-
if (options.includeStyling) {
|
|
2843
|
-
cell.s = this.getXlsxHeaderStyle(header);
|
|
2844
|
-
}
|
|
2845
|
-
sheet[cellRef] = cell;
|
|
2846
|
-
// Handle colspan merging
|
|
2847
|
-
if (header.colspan > 1) {
|
|
2848
|
-
const endCol = colIndex + header.colspan - 1;
|
|
2849
|
-
merges.push({
|
|
2850
|
-
s: { r: rowIndex, c: colIndex },
|
|
2851
|
-
e: { r: rowIndex, c: endCol }
|
|
2852
|
-
});
|
|
2853
|
-
}
|
|
2854
|
-
// Handle rowspan merging
|
|
2855
|
-
if (header.rowspan > 1) {
|
|
2856
|
-
const endRow = rowIndex + header.rowspan - 1;
|
|
2857
|
-
merges.push({
|
|
2858
|
-
s: { r: rowIndex, c: colIndex },
|
|
2859
|
-
e: { r: endRow, c: colIndex }
|
|
2860
|
-
});
|
|
2861
|
-
}
|
|
2862
|
-
});
|
|
2863
|
-
});
|
|
2864
|
-
}
|
|
2865
|
-
/**
|
|
2866
|
-
* Add data rows to xlsx sheet with rowspan handling
|
|
2867
|
-
*/
|
|
2868
|
-
addXlsxDataRows(sheet, data, columnDefinitions, rowspanInfo, startRow, merges, options) {
|
|
2869
|
-
let currentRow = startRow;
|
|
2870
|
-
data.forEach((row, rowIndex) => {
|
|
2871
|
-
const rowKey = this.generateRowKeyForExcel(row);
|
|
2872
|
-
const spanInfo = rowspanInfo.get(rowKey);
|
|
2873
|
-
if (spanInfo && spanInfo.skip) {
|
|
2874
|
-
return; // Skip this row as it's merged with parent
|
|
2875
|
-
}
|
|
2876
|
-
// Add row data
|
|
2877
|
-
columnDefinitions.forEach((col, colIndex) => {
|
|
2878
|
-
const cellRef = this.getExcelCellRef(currentRow, colIndex);
|
|
2879
|
-
const value = row[col.name];
|
|
2880
|
-
const cell = {
|
|
2881
|
-
v: this.formatXlsxValue(value, col.datatype),
|
|
2882
|
-
t: this.getXlsxValueType(col.datatype)
|
|
2883
|
-
};
|
|
2884
|
-
// Add styling
|
|
2885
|
-
if (options.includeStyling) {
|
|
2886
|
-
cell.s = this.getXlsxDataStyle(row, col);
|
|
2887
|
-
}
|
|
2888
|
-
sheet[cellRef] = cell;
|
|
2889
|
-
});
|
|
2890
|
-
// Handle rowspan merging
|
|
2891
|
-
if (spanInfo && spanInfo.rowspan > 1) {
|
|
2892
|
-
const endRow = currentRow + spanInfo.rowspan - 1;
|
|
2893
|
-
columnDefinitions.forEach((col, colIndex) => {
|
|
2894
|
-
merges.push({
|
|
2895
|
-
s: { r: currentRow, c: colIndex },
|
|
2896
|
-
e: { r: endRow, c: colIndex }
|
|
2897
|
-
});
|
|
2898
|
-
});
|
|
2899
|
-
}
|
|
2900
|
-
currentRow++;
|
|
2901
|
-
});
|
|
2902
|
-
}
|
|
2903
|
-
/**
|
|
2904
|
-
* Set column widths for xlsx sheet
|
|
2905
|
-
*/
|
|
2906
|
-
setXlsxColumnWidths(sheet, columnDefinitions) {
|
|
2907
|
-
const colWidths = [];
|
|
2908
|
-
columnDefinitions.forEach(col => {
|
|
2909
|
-
colWidths.push({
|
|
2910
|
-
wch: Math.max(col.name.length, 15) // Minimum width of 15 characters
|
|
2911
|
-
});
|
|
2912
|
-
});
|
|
2913
|
-
sheet['!cols'] = colWidths;
|
|
2914
|
-
}
|
|
2915
|
-
/**
|
|
2916
|
-
* Apply styling to xlsx sheet
|
|
2917
|
-
*/
|
|
2918
|
-
applyXlsxStyling(sheet, headerStructure, data, configuration) {
|
|
2919
|
-
// Styling is applied during cell creation in addXlsxHeaders and addXlsxDataRows
|
|
2920
|
-
// This method can be used for additional global styling if needed
|
|
2921
|
-
}
|
|
2922
|
-
/**
|
|
2923
|
-
* Get xlsx header cell style
|
|
2924
|
-
*/
|
|
2925
|
-
getXlsxHeaderStyle(header) {
|
|
2926
|
-
return {
|
|
2927
|
-
font: { bold: true, color: { rgb: EXCEL_COLORS.TEXT_WHITE } },
|
|
2928
|
-
fill: { fgColor: { rgb: EXCEL_COLORS.HEADER_PRIMARY } },
|
|
2929
|
-
alignment: { horizontal: 'center', vertical: 'center' }
|
|
2930
|
-
};
|
|
2931
|
-
}
|
|
2932
|
-
/**
|
|
2933
|
-
* Get xlsx data cell style
|
|
2934
|
-
*/
|
|
2935
|
-
getXlsxDataStyle(row, column) {
|
|
2936
|
-
const baseStyle = {
|
|
2937
|
-
alignment: { horizontal: 'center', vertical: 'center' }
|
|
2938
|
-
};
|
|
2939
|
-
// Add specific styling based on row type
|
|
2940
|
-
if (row['isGrandTotal']) {
|
|
2941
|
-
baseStyle.font = { bold: true };
|
|
2942
|
-
baseStyle.fill = { fgColor: { rgb: EXCEL_COLORS.GRAND_TOTAL_ROW } };
|
|
2943
|
-
}
|
|
2944
|
-
else if (row['isSubtotal']) {
|
|
2945
|
-
baseStyle.font = { bold: true };
|
|
2946
|
-
baseStyle.fill = { fgColor: { rgb: EXCEL_COLORS.SUBTOTAL_ROW } };
|
|
2947
|
-
}
|
|
2948
|
-
return baseStyle;
|
|
2949
|
-
}
|
|
2950
|
-
/**
|
|
2951
|
-
* Format value for xlsx
|
|
2952
|
-
*/
|
|
2953
|
-
formatXlsxValue(value, type) {
|
|
2954
|
-
if (value === null || value === undefined) {
|
|
2955
|
-
return '';
|
|
2956
|
-
}
|
|
2957
|
-
switch (type) {
|
|
2958
|
-
case 'number':
|
|
2959
|
-
return typeof value === 'number' ? value : parseFloat(value) || 0;
|
|
2960
|
-
case 'date':
|
|
2961
|
-
return value instanceof Date ? value : new Date(value);
|
|
2962
|
-
default:
|
|
2963
|
-
return String(value);
|
|
2964
|
-
}
|
|
2965
|
-
}
|
|
2966
|
-
/**
|
|
2967
|
-
* Get xlsx value type
|
|
2968
|
-
*/
|
|
2969
|
-
getXlsxValueType(type) {
|
|
2970
|
-
switch (type) {
|
|
2971
|
-
case 'number':
|
|
2972
|
-
return 'n';
|
|
2973
|
-
case 'date':
|
|
2974
|
-
return 'd';
|
|
2975
|
-
default:
|
|
2976
|
-
return 's';
|
|
2977
|
-
}
|
|
2978
|
-
}
|
|
2979
|
-
/**
|
|
2980
|
-
* Get xlsx sheet range
|
|
2981
|
-
*/
|
|
2982
|
-
getXlsxRange(sheet) {
|
|
2983
|
-
const cells = Object.keys(sheet).filter(key => key.match(/^[A-Z]+\d+$/));
|
|
2984
|
-
if (cells.length === 0)
|
|
2985
|
-
return null;
|
|
2986
|
-
const rows = cells.map(cell => parseInt(cell.replace(/[A-Z]+/, '')));
|
|
2987
|
-
const cols = cells.map(cell => this.parseExcelCellRef(cell).col);
|
|
2988
|
-
const minRow = Math.min(...rows);
|
|
2989
|
-
const maxRow = Math.max(...rows);
|
|
2990
|
-
const minCol = Math.min(...cols);
|
|
2991
|
-
const maxCol = Math.max(...cols);
|
|
2992
|
-
const startCell = this.getExcelCellRef(minRow, minCol);
|
|
2993
|
-
const endCell = this.getExcelCellRef(maxRow, maxCol);
|
|
2994
|
-
return `${startCell}:${endCell}`;
|
|
2995
|
-
}
|
|
2996
|
-
/**
|
|
2997
|
-
* Generate row key for Excel export
|
|
2998
|
-
*/
|
|
2999
|
-
generateRowKeyForExcel(row) {
|
|
3000
|
-
// Create a unique key for the row based on its data
|
|
3001
|
-
const keyParts = [];
|
|
3002
|
-
// Add dimension values
|
|
3003
|
-
Object.keys(row).forEach(key => {
|
|
3004
|
-
if (key !== 'isSubtotal' && key !== 'isGrandTotal' && row[key] !== null && row[key] !== undefined) {
|
|
3005
|
-
keyParts.push(`${key}:${row[key]}`);
|
|
3006
|
-
}
|
|
3007
|
-
});
|
|
3008
|
-
return keyParts.join('|');
|
|
3009
|
-
}
|
|
3010
2364
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: PivotTransformService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3011
2365
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: PivotTransformService, providedIn: 'root' });
|
|
3012
2366
|
}
|
|
@@ -3047,7 +2401,9 @@ class EruGridStore {
|
|
|
3047
2401
|
// Pivot-specific signals
|
|
3048
2402
|
_pivotConfiguration = signal(null, ...(ngDevMode ? [{ debugName: "_pivotConfiguration" }] : []));
|
|
3049
2403
|
_pivotResult = signal(null, ...(ngDevMode ? [{ debugName: "_pivotResult" }] : []));
|
|
3050
|
-
|
|
2404
|
+
_drilldown = signal(null, ...(ngDevMode ? [{ debugName: "_drilldown" }] : []));
|
|
2405
|
+
// Data request signal for virtual scrolling pagination
|
|
2406
|
+
_dataRequest = signal(null, ...(ngDevMode ? [{ debugName: "_dataRequest" }] : []));
|
|
3051
2407
|
// Computed signals
|
|
3052
2408
|
columns = this._columns.asReadonly();
|
|
3053
2409
|
groups = this._groups.asReadonly();
|
|
@@ -3060,7 +2416,9 @@ class EruGridStore {
|
|
|
3060
2416
|
// Pivot-specific readonly signals
|
|
3061
2417
|
pivotConfiguration = this._pivotConfiguration.asReadonly();
|
|
3062
2418
|
pivotResult = this._pivotResult.asReadonly();
|
|
3063
|
-
|
|
2419
|
+
drilldown = this._drilldown.asReadonly();
|
|
2420
|
+
// Data request readonly signal (exposed to consumers)
|
|
2421
|
+
dataRequest = this._dataRequest.asReadonly();
|
|
3064
2422
|
// Computed properties
|
|
3065
2423
|
selectedRows = computed(() => this.rows().filter(row => this.selectedRowIds().has(row.entity_id)), ...(ngDevMode ? [{ debugName: "selectedRows" }] : []));
|
|
3066
2424
|
totalSelectedCount = computed(() => this.selectedRowIds().size, ...(ngDevMode ? [{ debugName: "totalSelectedCount" }] : []));
|
|
@@ -3343,13 +2701,9 @@ class EruGridStore {
|
|
|
3343
2701
|
setError(error) {
|
|
3344
2702
|
this._error.set(error);
|
|
3345
2703
|
}
|
|
3346
|
-
// Data fetching method
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
const endIndex = startIndex + pageSize;
|
|
3350
|
-
const data = this.configuration().data?.slice(startIndex, endIndex) || [];
|
|
3351
|
-
return of(data).pipe(delay(1000));
|
|
3352
|
-
}
|
|
2704
|
+
// Data fetching method - REMOVED
|
|
2705
|
+
// This method has been removed as part of refactoring to signal-based architecture
|
|
2706
|
+
// Data fetching is now handled by the consuming application via dataRequest signal
|
|
3353
2707
|
// Helper methods
|
|
3354
2708
|
isRowSelected(rowId) {
|
|
3355
2709
|
return this.selectedRowIds().has(rowId);
|
|
@@ -3454,20 +2808,8 @@ class EruGridStore {
|
|
|
3454
2808
|
this._pivotResult.set(null);
|
|
3455
2809
|
this.transformToPivot();
|
|
3456
2810
|
}
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
if (!pivotResult) {
|
|
3460
|
-
return null;
|
|
3461
|
-
}
|
|
3462
|
-
return this.pivotTransformService.exportToCsv(pivotResult);
|
|
3463
|
-
}
|
|
3464
|
-
exportPivotToExcel() {
|
|
3465
|
-
const pivotResult = this.pivotResult();
|
|
3466
|
-
if (!pivotResult) {
|
|
3467
|
-
return null;
|
|
3468
|
-
}
|
|
3469
|
-
return this.pivotTransformService.exportToExcel(pivotResult);
|
|
3470
|
-
}
|
|
2811
|
+
// Excel/CSV export methods removed
|
|
2812
|
+
// Export functionality should be implemented in the consuming application
|
|
3471
2813
|
validatePivotConfiguration(config) {
|
|
3472
2814
|
return this.gridConfigService.validatePivotConfiguration(config);
|
|
3473
2815
|
}
|
|
@@ -3550,22 +2892,74 @@ class EruGridStore {
|
|
|
3550
2892
|
isFreezeGrandTotalEnabled() {
|
|
3551
2893
|
return this.configuration().config?.freezeGrandTotal ?? false;
|
|
3552
2894
|
}
|
|
3553
|
-
|
|
3554
|
-
if (
|
|
3555
|
-
drilldown.
|
|
2895
|
+
setDrilldown(drilldown, columnValues) {
|
|
2896
|
+
if (this.isPivotMode()) {
|
|
2897
|
+
if (drilldown.frozenGrandTotalCell) {
|
|
2898
|
+
drilldown.rowData = this.pivotGrandTotalData()[0];
|
|
2899
|
+
}
|
|
2900
|
+
else {
|
|
2901
|
+
drilldown.rowData = this.pivotDisplayData()[parseInt(drilldown.rowId)];
|
|
2902
|
+
}
|
|
3556
2903
|
}
|
|
3557
2904
|
else {
|
|
3558
|
-
drilldown.rowData = this.
|
|
2905
|
+
drilldown.rowData = this.rows()[parseInt(drilldown.rowId) - 2];
|
|
3559
2906
|
}
|
|
3560
2907
|
const columnValuesArray = columnValues.split('|');
|
|
3561
2908
|
const cols = this.configuration()?.pivot?.cols;
|
|
3562
2909
|
columnValuesArray.forEach((value, index) => {
|
|
3563
2910
|
drilldown.rowData[cols[index]] = value;
|
|
3564
2911
|
});
|
|
3565
|
-
|
|
2912
|
+
console.log('🔄 SET DRILLDOWN: Drilldown', drilldown);
|
|
2913
|
+
this._drilldown.set(drilldown);
|
|
3566
2914
|
}
|
|
3567
2915
|
clearPivotDrilldown() {
|
|
3568
|
-
this.
|
|
2916
|
+
this._drilldown.set(null);
|
|
2917
|
+
}
|
|
2918
|
+
// Data request methods for signal-based virtual scrolling
|
|
2919
|
+
/**
|
|
2920
|
+
* Emit a data request signal (called by grid component)
|
|
2921
|
+
*/
|
|
2922
|
+
setDataRequest(request) {
|
|
2923
|
+
console.log('📤 Grid Store: Emitting data request', request);
|
|
2924
|
+
this._dataRequest.set(request);
|
|
2925
|
+
}
|
|
2926
|
+
/**
|
|
2927
|
+
* Clear the data request signal (called by consumer after handling)
|
|
2928
|
+
*/
|
|
2929
|
+
clearDataRequest() {
|
|
2930
|
+
this._dataRequest.set(null);
|
|
2931
|
+
}
|
|
2932
|
+
/**
|
|
2933
|
+
* Mark a group as loading (called by grid component before requesting)
|
|
2934
|
+
*/
|
|
2935
|
+
startGroupLoading(groupId) {
|
|
2936
|
+
this.updateGroupLoadingState(groupId, true);
|
|
2937
|
+
}
|
|
2938
|
+
/**
|
|
2939
|
+
* Complete loading for a group (called by consumer after data received)
|
|
2940
|
+
*/
|
|
2941
|
+
completeGroupLoading(groupId) {
|
|
2942
|
+
this.updateGroupLoadingState(groupId, false);
|
|
2943
|
+
}
|
|
2944
|
+
/**
|
|
2945
|
+
* Add rows for a specific group (called by consumer with API data)
|
|
2946
|
+
*/
|
|
2947
|
+
addRowsForGroup(groupId, rows, hasMore) {
|
|
2948
|
+
console.log(`✅ Grid Store: Received ${rows.length} rows for group ${groupId}`);
|
|
2949
|
+
// Add rows to existing rows
|
|
2950
|
+
const existingRows = this.rows();
|
|
2951
|
+
const newRows = [...existingRows, ...rows];
|
|
2952
|
+
this._rows.set(newRows);
|
|
2953
|
+
// Update group state
|
|
2954
|
+
this.updateGroupAfterLoading(groupId, rows.length, !hasMore);
|
|
2955
|
+
}
|
|
2956
|
+
/**
|
|
2957
|
+
* Handle error for data request (called by consumer when API fails)
|
|
2958
|
+
*/
|
|
2959
|
+
handleDataRequestError(groupId, error) {
|
|
2960
|
+
console.error(`❌ Grid Store: Data request failed for group ${groupId}`, error);
|
|
2961
|
+
this.updateGroupLoadingState(groupId, false);
|
|
2962
|
+
this.setError(`Failed to load data for group ${groupId}`);
|
|
3569
2963
|
}
|
|
3570
2964
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: EruGridStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3571
2965
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: EruGridStore });
|
|
@@ -3871,18 +3265,8 @@ class EruGridService {
|
|
|
3871
3265
|
clear_pivot() {
|
|
3872
3266
|
this.eruGridStore.clearPivot();
|
|
3873
3267
|
}
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
*/
|
|
3877
|
-
export_pivot_to_csv() {
|
|
3878
|
-
return this.eruGridStore.exportPivotToCsv();
|
|
3879
|
-
}
|
|
3880
|
-
/**
|
|
3881
|
-
* Export pivot data to Excel format
|
|
3882
|
-
*/
|
|
3883
|
-
export_pivot_to_excel() {
|
|
3884
|
-
return this.eruGridStore.exportPivotToExcel();
|
|
3885
|
-
}
|
|
3268
|
+
// Excel/CSV export methods removed
|
|
3269
|
+
// Export functionality should be implemented in the consuming application
|
|
3886
3270
|
/**
|
|
3887
3271
|
* Validate pivot configuration
|
|
3888
3272
|
*/
|
|
@@ -4544,7 +3928,7 @@ class DataCellComponent {
|
|
|
4544
3928
|
columnValue: this.currentValue()
|
|
4545
3929
|
});
|
|
4546
3930
|
console.log(columnValues);
|
|
4547
|
-
this.eruGridStore().
|
|
3931
|
+
this.eruGridStore().setDrilldown({
|
|
4548
3932
|
frozenGrandTotalCell: this.frozenGrandTotalCell(),
|
|
4549
3933
|
columnName: columnName.join('_'),
|
|
4550
3934
|
rowId: rowId,
|
|
@@ -5500,8 +4884,6 @@ class EruGridComponent {
|
|
|
5500
4884
|
initialTotalWidth = 0;
|
|
5501
4885
|
vp;
|
|
5502
4886
|
groups = computed(() => this.gridStore.groups(), ...(ngDevMode ? [{ debugName: "groups" }] : []));
|
|
5503
|
-
rowLoadQueue = [];
|
|
5504
|
-
isProcessingQueue = false;
|
|
5505
4887
|
// Computed properties using the new GridStore
|
|
5506
4888
|
groupedRows = computed(() => this.createGroupedRows(), ...(ngDevMode ? [{ debugName: "groupedRows" }] : []));
|
|
5507
4889
|
columns = computed(() => this.gridStore.columns(), ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
@@ -5596,13 +4978,13 @@ class EruGridComponent {
|
|
|
5596
4978
|
let totalWidth = columns.reduce((total, column) => total + column.field_size, 0);
|
|
5597
4979
|
return totalWidth;
|
|
5598
4980
|
}
|
|
5599
|
-
getContainerHeight() {
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
4981
|
+
/* getContainerHeight(): number {
|
|
4982
|
+
const element = this.rowContainer?.nativeElement;
|
|
4983
|
+
if (element) {
|
|
4984
|
+
return element.clientHeight;
|
|
5603
4985
|
}
|
|
5604
|
-
|
|
5605
|
-
}
|
|
4986
|
+
return window.innerHeight; // Fallback to viewport height
|
|
4987
|
+
} */
|
|
5606
4988
|
getMinHeightPx() {
|
|
5607
4989
|
//const parentHeight = this.getContainerHeight();
|
|
5608
4990
|
let headerHeight = 0;
|
|
@@ -5639,14 +5021,16 @@ class EruGridComponent {
|
|
|
5639
5021
|
* Get the rendered range (what's in the DOM including buffer)
|
|
5640
5022
|
* @returns Object with start, end, and count of rendered items
|
|
5641
5023
|
*/
|
|
5642
|
-
getRenderedRange() {
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5024
|
+
/* getRenderedRange(): { start: number; end: number; count: number } {
|
|
5025
|
+
if (!this.viewport) {
|
|
5026
|
+
return { start: 0, end: 0, count: 0 };
|
|
5027
|
+
}
|
|
5028
|
+
|
|
5029
|
+
const range = this.viewport.getRenderedRange();
|
|
5030
|
+
const count = range.end - range.start;
|
|
5031
|
+
|
|
5032
|
+
return { start: range.start, end: range.end, count };
|
|
5033
|
+
} */
|
|
5650
5034
|
ROWS_PER_PAGE = 50;
|
|
5651
5035
|
SCROLL_THRESHOLD = 10;
|
|
5652
5036
|
lastLoadedGroupIds = new Set();
|
|
@@ -5724,7 +5108,7 @@ class EruGridComponent {
|
|
|
5724
5108
|
const rows = this.gridStore.rows();
|
|
5725
5109
|
const groups = this.gridStore.groups();
|
|
5726
5110
|
console.log("groups", groups);
|
|
5727
|
-
console.log("rows", rows);
|
|
5111
|
+
console.log("rows", rows?.length);
|
|
5728
5112
|
const flattenedRows = [];
|
|
5729
5113
|
if (groups.length > 0) {
|
|
5730
5114
|
groups.forEach(group => {
|
|
@@ -5754,70 +5138,25 @@ class EruGridComponent {
|
|
|
5754
5138
|
flattenedRows.push({ type: 'row', group: undefined, row });
|
|
5755
5139
|
});
|
|
5756
5140
|
}
|
|
5757
|
-
console.log("flattenedRows", flattenedRows);
|
|
5141
|
+
console.log("flattenedRows", flattenedRows?.length);
|
|
5758
5142
|
return flattenedRows;
|
|
5759
5143
|
}
|
|
5760
5144
|
initializeGroups() {
|
|
5761
5145
|
this.fetchInitialRows();
|
|
5762
5146
|
}
|
|
5763
5147
|
fetchInitialRows() {
|
|
5148
|
+
console.log("fetchInitialRows", this.gridStore.groups());
|
|
5764
5149
|
this.gridStore.groups().forEach(group => {
|
|
5765
5150
|
if (group.isExpanded) {
|
|
5766
|
-
this.
|
|
5767
|
-
}
|
|
5768
|
-
});
|
|
5769
|
-
}
|
|
5770
|
-
fetchRowsForGroup(groupId, page, pageSize = this.ROWS_PER_PAGE) {
|
|
5771
|
-
return new Promise((resolve, reject) => {
|
|
5772
|
-
const group = this.gridStore.groups().find(g => g.id === groupId);
|
|
5773
|
-
if (!group || !group.hasMoreRows) {
|
|
5774
|
-
resolve();
|
|
5775
|
-
return;
|
|
5776
|
-
}
|
|
5777
|
-
if (group.isLoading) {
|
|
5778
|
-
resolve();
|
|
5779
|
-
return;
|
|
5151
|
+
this.requestRowsForGroup(group);
|
|
5780
5152
|
}
|
|
5781
|
-
this.gridStore.updateGroupLoadingState(groupId, true);
|
|
5782
|
-
const skip = page * pageSize;
|
|
5783
|
-
const loadTimeout = setTimeout(() => {
|
|
5784
|
-
this.gridStore.updateGroupLoadingState(groupId, false);
|
|
5785
|
-
reject(new Error('Task loading timed out'));
|
|
5786
|
-
}, 10000);
|
|
5787
|
-
this.gridStore.fetchNewRowData(pageSize, skip, group).subscribe({
|
|
5788
|
-
next: (response) => {
|
|
5789
|
-
clearTimeout(loadTimeout);
|
|
5790
|
-
if (!response || response.length === 0) {
|
|
5791
|
-
this.gridStore.updateGroupAfterLoading(groupId, 0, true);
|
|
5792
|
-
resolve();
|
|
5793
|
-
return;
|
|
5794
|
-
}
|
|
5795
|
-
const newRows = this.normalizeRowData(response.map((r) => ({ ...r, groupId })), group);
|
|
5796
|
-
this.gridStore.addRows(newRows);
|
|
5797
|
-
this.gridStore.updateGroupAfterLoading(groupId, newRows.length);
|
|
5798
|
-
this.changeDetectorRef.markForCheck();
|
|
5799
|
-
resolve();
|
|
5800
|
-
},
|
|
5801
|
-
error: (error) => {
|
|
5802
|
-
clearTimeout(loadTimeout);
|
|
5803
|
-
console.error(`Error loading tasks for group ${groupId}:`, error);
|
|
5804
|
-
this.gridStore.updateGroupLoadingState(groupId, false);
|
|
5805
|
-
this.markGroupAsNoMoreRows(groupId);
|
|
5806
|
-
reject(error);
|
|
5807
|
-
}
|
|
5808
|
-
});
|
|
5809
5153
|
});
|
|
5810
5154
|
}
|
|
5155
|
+
// fetchRowsForGroup - REMOVED
|
|
5156
|
+
// Data fetching is now handled by the consuming application via signal
|
|
5157
|
+
// See requestRowsForGroup() method below for the new approach
|
|
5811
5158
|
onScroll(scrollIndex) {
|
|
5812
|
-
|
|
5813
|
-
const visibleGroups = this.getVisibleGroups();
|
|
5814
|
-
visibleGroups.forEach(group => {
|
|
5815
|
-
if (group.isExpanded &&
|
|
5816
|
-
group.hasMoreRows &&
|
|
5817
|
-
!group.isLoading) {
|
|
5818
|
-
this.checkGroupRowLoading(group);
|
|
5819
|
-
}
|
|
5820
|
-
});
|
|
5159
|
+
console.log("onScroll called", scrollIndex);
|
|
5821
5160
|
this.checkAndLoadMoreRows();
|
|
5822
5161
|
}
|
|
5823
5162
|
getVisibleGroups() {
|
|
@@ -5836,7 +5175,7 @@ class EruGridComponent {
|
|
|
5836
5175
|
.filter((group) => group !== undefined);
|
|
5837
5176
|
}
|
|
5838
5177
|
getGroupItemAtIndex(index) {
|
|
5839
|
-
const groupItems = this.
|
|
5178
|
+
const groupItems = this.groupedRows();
|
|
5840
5179
|
return groupItems[index];
|
|
5841
5180
|
}
|
|
5842
5181
|
checkAndLoadMoreRows() {
|
|
@@ -5845,6 +5184,7 @@ class EruGridComponent {
|
|
|
5845
5184
|
const renderedRange = this.viewport.getRenderedRange();
|
|
5846
5185
|
const dataLength = this.viewport.getDataLength();
|
|
5847
5186
|
const isNearEnd = renderedRange.end >= (dataLength - this.SCROLL_THRESHOLD);
|
|
5187
|
+
console.log("isNearEnd", renderedRange, dataLength, isNearEnd);
|
|
5848
5188
|
if (isNearEnd) {
|
|
5849
5189
|
this.intelligentRowLoading();
|
|
5850
5190
|
}
|
|
@@ -5856,38 +5196,41 @@ class EruGridComponent {
|
|
|
5856
5196
|
!group.isLoading &&
|
|
5857
5197
|
!this.lastLoadedGroupIds.has(group.id));
|
|
5858
5198
|
const sortedGroupsToLoad = groupsToLoad.sort((a, b) => (a.currentLoadedRows || 0) - (b.currentLoadedRows || 0));
|
|
5199
|
+
console.log("sortedGroupsToLoad", sortedGroupsToLoad);
|
|
5859
5200
|
if (sortedGroupsToLoad.length > 0) {
|
|
5860
5201
|
const groupToLoad = sortedGroupsToLoad[0];
|
|
5861
|
-
|
|
5862
|
-
this.
|
|
5863
|
-
setTimeout(() => {
|
|
5864
|
-
this.lastLoadedGroupIds.delete(groupToLoad.id);
|
|
5865
|
-
}, 5000);
|
|
5866
|
-
}
|
|
5867
|
-
}
|
|
5868
|
-
checkGroupRowLoading(group) {
|
|
5869
|
-
const shouldLoadRows = group.currentLoadedRows < group.totalRowCount &&
|
|
5870
|
-
!this.lastLoadedGroupIds.has(group.id);
|
|
5871
|
-
if (shouldLoadRows) {
|
|
5872
|
-
this.queueRowLoading(group);
|
|
5873
|
-
}
|
|
5874
|
-
}
|
|
5875
|
-
queueRowLoading(group) {
|
|
5876
|
-
if (!group) {
|
|
5877
|
-
const groups = this.gridStore.groups();
|
|
5878
|
-
group = groups.find(g => g.isExpanded &&
|
|
5879
|
-
g.hasMoreRows &&
|
|
5880
|
-
!g.isLoading);
|
|
5881
|
-
}
|
|
5882
|
-
if (group) {
|
|
5883
|
-
this.rowLoadQueue.push({
|
|
5884
|
-
groupId: group.id,
|
|
5885
|
-
page: group.currentPage || 0,
|
|
5886
|
-
pageSize: group.totalRowCount < this.ROWS_PER_PAGE ? group.totalRowCount : this.ROWS_PER_PAGE
|
|
5887
|
-
});
|
|
5888
|
-
this.processRowLoadQueue();
|
|
5202
|
+
console.log("groupToLoad", groupToLoad);
|
|
5203
|
+
this.requestRowsForGroup(groupToLoad);
|
|
5889
5204
|
}
|
|
5890
5205
|
}
|
|
5206
|
+
// queueRowLoading - REPLACED with requestRowsForGroup
|
|
5207
|
+
// This method has been replaced with direct signal emission
|
|
5208
|
+
/**
|
|
5209
|
+
* Request rows for a specific group via signal
|
|
5210
|
+
*/
|
|
5211
|
+
requestRowsForGroup(group) {
|
|
5212
|
+
// Prevent duplicate requests
|
|
5213
|
+
console.log("requestRowsForGroup", group);
|
|
5214
|
+
if (this.lastLoadedGroupIds.has(group.id))
|
|
5215
|
+
return;
|
|
5216
|
+
const request = {
|
|
5217
|
+
groupId: group.id,
|
|
5218
|
+
page: group.currentPage || 0,
|
|
5219
|
+
pageSize: group.totalRowCount < this.ROWS_PER_PAGE ? group.totalRowCount : this.ROWS_PER_PAGE,
|
|
5220
|
+
timestamp: Date.now(),
|
|
5221
|
+
groupTitle: group.title
|
|
5222
|
+
};
|
|
5223
|
+
console.log('📤 Grid Component: Emitting data request', request);
|
|
5224
|
+
// Emit signal via store
|
|
5225
|
+
this.gridStore.setDataRequest(request);
|
|
5226
|
+
// Mark group as loading
|
|
5227
|
+
this.gridStore.startGroupLoading(group.id);
|
|
5228
|
+
// Prevent duplicate requests for 5 seconds
|
|
5229
|
+
this.lastLoadedGroupIds.add(group.id);
|
|
5230
|
+
setTimeout(() => {
|
|
5231
|
+
this.lastLoadedGroupIds.delete(group.id);
|
|
5232
|
+
}, 1000);
|
|
5233
|
+
}
|
|
5891
5234
|
trackByColumnFn(index, column) {
|
|
5892
5235
|
return column.name;
|
|
5893
5236
|
}
|
|
@@ -5951,35 +5294,36 @@ class EruGridComponent {
|
|
|
5951
5294
|
this.gridStore.setColumns(normalizedColumns);
|
|
5952
5295
|
}
|
|
5953
5296
|
// Enhanced method to normalize row data
|
|
5954
|
-
normalizeRowData(rows, group) {
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5297
|
+
/* private normalizeRowData(rows: any[], group?: RowGroup): any[] {
|
|
5298
|
+
return rows.map(row => ({
|
|
5299
|
+
...row,
|
|
5300
|
+
|
|
5301
|
+
groupTitle: group?.title,
|
|
5302
|
+
|
|
5303
|
+
displayValue: this.getDisplayValue(row),
|
|
5304
|
+
height: 50
|
|
5305
|
+
}));
|
|
5306
|
+
} */
|
|
5307
|
+
/* private getDisplayValue(row: any, column?: string): string {
|
|
5308
|
+
if (!column) {
|
|
5309
|
+
return this.getGenericRowDisplay(row);
|
|
5310
|
+
}
|
|
5311
|
+
|
|
5312
|
+
const value = row[column];
|
|
5313
|
+
if (value === null || value === undefined) return '';
|
|
5314
|
+
if (typeof value === 'string') return value.trim();
|
|
5315
|
+
if (typeof value === 'number') return value.toString();
|
|
5316
|
+
|
|
5317
|
+
return JSON.stringify(value);
|
|
5318
|
+
} */
|
|
5319
|
+
/* private getGenericRowDisplay(row: any): string {
|
|
5320
|
+
const displayProps = ['title', 'id', 'status'];
|
|
5321
|
+
return displayProps
|
|
5322
|
+
.map(prop => row[prop])
|
|
5323
|
+
.filter(value => value != null)
|
|
5324
|
+
.join(' - ')
|
|
5325
|
+
.trim();
|
|
5326
|
+
} */
|
|
5983
5327
|
toggleRowSelection(event, row) {
|
|
5984
5328
|
event.stopPropagation();
|
|
5985
5329
|
const checkbox = event.target;
|
|
@@ -6024,45 +5368,24 @@ class EruGridComponent {
|
|
|
6024
5368
|
getSelectedRows() {
|
|
6025
5369
|
return Array.from(this.gridStore.selectedRowIds());
|
|
6026
5370
|
}
|
|
6027
|
-
markGroupAsNoMoreRows(groupId) {
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
}
|
|
5371
|
+
/* private markGroupAsNoMoreRows(groupId: string) {
|
|
5372
|
+
// This functionality is now handled by GridStore.updateGroupAfterLoading
|
|
5373
|
+
this.gridStore.updateGroupAfterLoading(groupId, 0, true);
|
|
5374
|
+
} */
|
|
6031
5375
|
toggleGroupExpansion(groupId) {
|
|
6032
5376
|
const group = this.gridStore.groups().find(g => g.id === groupId);
|
|
6033
5377
|
if (!group)
|
|
6034
5378
|
return;
|
|
6035
5379
|
const newExpandedState = !group.isExpanded;
|
|
6036
5380
|
this.gridStore.toggleGroupExpansion(groupId);
|
|
5381
|
+
// Request data when expanding group with no data
|
|
6037
5382
|
if (newExpandedState && (!group.rows || group.rows.length === 0)) {
|
|
6038
|
-
this.
|
|
6039
|
-
.catch(error => {
|
|
6040
|
-
console.error(`Error loading rows for expanded group ${groupId}:`, error);
|
|
6041
|
-
});
|
|
6042
|
-
}
|
|
6043
|
-
}
|
|
6044
|
-
processRowLoadQueue() {
|
|
6045
|
-
if (this.isProcessingQueue)
|
|
6046
|
-
return;
|
|
6047
|
-
if (this.rowLoadQueue.length === 0) {
|
|
6048
|
-
this.isProcessingQueue = false;
|
|
6049
|
-
return;
|
|
6050
|
-
}
|
|
6051
|
-
this.isProcessingQueue = true;
|
|
6052
|
-
const nextLoad = this.rowLoadQueue.shift();
|
|
6053
|
-
if (nextLoad) {
|
|
6054
|
-
this.fetchRowsForGroup(nextLoad.groupId, nextLoad.page, nextLoad.pageSize)
|
|
6055
|
-
.then(() => {
|
|
6056
|
-
this.isProcessingQueue = false;
|
|
6057
|
-
this.processRowLoadQueue();
|
|
6058
|
-
})
|
|
6059
|
-
.catch(error => {
|
|
6060
|
-
console.error('Error loading rows:', error);
|
|
6061
|
-
this.isProcessingQueue = false;
|
|
6062
|
-
this.processRowLoadQueue();
|
|
6063
|
-
});
|
|
5383
|
+
this.requestRowsForGroup(group);
|
|
6064
5384
|
}
|
|
6065
5385
|
}
|
|
5386
|
+
// processRowLoadQueue - REMOVED
|
|
5387
|
+
// Queue-based loading is replaced with direct signal emission
|
|
5388
|
+
// See requestRowsForGroup() method for the new approach
|
|
6066
5389
|
// Collapsible column methods
|
|
6067
5390
|
/**
|
|
6068
5391
|
* Toggle collapse/expand state of a column group
|
|
@@ -6149,94 +5472,103 @@ class EruGridComponent {
|
|
|
6149
5472
|
* Get rowspan value for a specific cell - VIRTUAL SCROLLING COMPATIBLE
|
|
6150
5473
|
* This is a compatibility wrapper around getEffectiveRowspan
|
|
6151
5474
|
*/
|
|
6152
|
-
getCellRowspan(rowIndex, columnName) {
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
5475
|
+
/* getCellRowspan(rowIndex: number, columnName: string): number {
|
|
5476
|
+
const effectiveRowspan = this.getEffectiveRowspan(rowIndex, columnName);
|
|
5477
|
+
return effectiveRowspan || 1;
|
|
5478
|
+
} */
|
|
6156
5479
|
/**
|
|
6157
5480
|
* Get columns that should be frozen on the left (all row dimensions up to and including freezeField)
|
|
6158
5481
|
*/
|
|
6159
|
-
getRowDimensionColumns() {
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
5482
|
+
/* getRowDimensionColumns(): any[] {
|
|
5483
|
+
if (!this.gridStore.isFreezeEnabled()) return [];
|
|
5484
|
+
|
|
5485
|
+
const freezeField = this.gridStore.getFreezeField();
|
|
5486
|
+
if (!freezeField) return [];
|
|
5487
|
+
|
|
5488
|
+
const allColumns = this.getLeafColumns();
|
|
5489
|
+
const pivotConfig = this.gridStore.pivotConfiguration();
|
|
5490
|
+
|
|
5491
|
+
if (!pivotConfig?.rows) return [];
|
|
5492
|
+
|
|
5493
|
+
// Find the index of the freeze field in the row dimensions
|
|
5494
|
+
const freezeFieldIndex = pivotConfig.rows.indexOf(freezeField);
|
|
5495
|
+
if (freezeFieldIndex === -1) return [];
|
|
5496
|
+
|
|
5497
|
+
// Return all row dimension columns up to and including the freeze field
|
|
5498
|
+
const rowDimensionsToFreeze = pivotConfig.rows.slice(0, freezeFieldIndex + 1);
|
|
5499
|
+
return allColumns.filter(col => rowDimensionsToFreeze.includes(col.name));
|
|
5500
|
+
} */
|
|
6177
5501
|
/**
|
|
6178
5502
|
* Get columns that should be scrollable on the right (all except frozen fields)
|
|
6179
5503
|
*/
|
|
6180
|
-
getColumnDimensionColumns() {
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
5504
|
+
/* getColumnDimensionColumns(): any[] {
|
|
5505
|
+
const allColumns = this.getLeafColumns();
|
|
5506
|
+
|
|
5507
|
+
if (!this.gridStore.isFreezeEnabled()) return allColumns;
|
|
5508
|
+
|
|
5509
|
+
const freezeField = this.gridStore.getFreezeField();
|
|
5510
|
+
if (!freezeField) return allColumns;
|
|
5511
|
+
|
|
5512
|
+
const pivotConfig = this.gridStore.pivotConfiguration();
|
|
5513
|
+
if (!pivotConfig?.rows) return allColumns;
|
|
5514
|
+
|
|
5515
|
+
// Find the index of the freeze field in the row dimensions
|
|
5516
|
+
const freezeFieldIndex = pivotConfig.rows.indexOf(freezeField);
|
|
5517
|
+
if (freezeFieldIndex === -1) return allColumns;
|
|
5518
|
+
|
|
5519
|
+
// Get all row dimensions that should be frozen
|
|
5520
|
+
const rowDimensionsToFreeze = pivotConfig.rows.slice(0, freezeFieldIndex + 1);
|
|
5521
|
+
|
|
5522
|
+
// Return all columns except the frozen row dimensions
|
|
5523
|
+
return allColumns.filter(col => !rowDimensionsToFreeze.includes(col.name));
|
|
5524
|
+
} */
|
|
6199
5525
|
/**
|
|
6200
5526
|
* Get headers that should be frozen (all row dimension headers up to and including freezeField)
|
|
6201
5527
|
*/
|
|
6202
|
-
getRowDimensionHeaders(headerRow) {
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
5528
|
+
/* getRowDimensionHeaders(headerRow: any[]): any[] {
|
|
5529
|
+
if (!this.gridStore.isFreezeEnabled()) return [];
|
|
5530
|
+
|
|
5531
|
+
const freezeField = this.gridStore.getFreezeField();
|
|
5532
|
+
if (!freezeField) return [];
|
|
5533
|
+
|
|
5534
|
+
const pivotConfig = this.gridStore.pivotConfiguration();
|
|
5535
|
+
if (!pivotConfig?.rows) return [];
|
|
5536
|
+
|
|
5537
|
+
// Find the index of the freeze field in the row dimensions
|
|
5538
|
+
const freezeFieldIndex = pivotConfig.rows.indexOf(freezeField);
|
|
5539
|
+
if (freezeFieldIndex === -1) return [];
|
|
5540
|
+
|
|
5541
|
+
// Get all row dimensions that should be frozen
|
|
5542
|
+
const rowDimensionsToFreeze = pivotConfig.rows.slice(0, freezeFieldIndex + 1);
|
|
5543
|
+
|
|
5544
|
+
return headerRow.filter(header =>
|
|
5545
|
+
rowDimensionsToFreeze.includes(header.name) ||
|
|
5546
|
+
(header.name && rowDimensionsToFreeze.includes(header.name))
|
|
5547
|
+
);
|
|
5548
|
+
} */
|
|
6220
5549
|
/**
|
|
6221
5550
|
* Get headers that should be scrollable (all except frozen fields)
|
|
6222
5551
|
*/
|
|
6223
|
-
getColumnDimensionHeaders(headerRow) {
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
5552
|
+
/* getColumnDimensionHeaders(headerRow: any[]): any[] {
|
|
5553
|
+
if (!this.gridStore.isFreezeEnabled()) return headerRow;
|
|
5554
|
+
|
|
5555
|
+
const freezeField = this.gridStore.getFreezeField();
|
|
5556
|
+
if (!freezeField) return headerRow;
|
|
5557
|
+
|
|
5558
|
+
const pivotConfig = this.gridStore.pivotConfiguration();
|
|
5559
|
+
if (!pivotConfig?.rows) return headerRow;
|
|
5560
|
+
|
|
5561
|
+
// Find the index of the freeze field in the row dimensions
|
|
5562
|
+
const freezeFieldIndex = pivotConfig.rows.indexOf(freezeField);
|
|
5563
|
+
if (freezeFieldIndex === -1) return headerRow;
|
|
5564
|
+
|
|
5565
|
+
// Get all row dimensions that should be frozen
|
|
5566
|
+
const rowDimensionsToFreeze = pivotConfig.rows.slice(0, freezeFieldIndex + 1);
|
|
5567
|
+
|
|
5568
|
+
return headerRow.filter(header =>
|
|
5569
|
+
!rowDimensionsToFreeze.includes(header.name)
|
|
5570
|
+
);
|
|
5571
|
+
} */
|
|
6240
5572
|
/**
|
|
6241
5573
|
* Check if a column should be sticky (frozen on the left)
|
|
6242
5574
|
*/
|
|
@@ -6424,7 +5756,7 @@ class EruGridComponent {
|
|
|
6424
5756
|
return this.columns().length;
|
|
6425
5757
|
}
|
|
6426
5758
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: EruGridComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
6427
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.3", type: EruGridComponent, isStandalone: true, selector: "eru-grid", inputs: { gridConfig: "gridConfig" }, providers: [EruGridStore, EruGridService], viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true }, { propertyName: "rowContainer", first: true, predicate: ["rowContainer"], descendants: true }, { propertyName: "headerScroller", first: true, predicate: ["headerScroller"], descendants: true, read: ElementRef }, { propertyName: "gtScroller", first: true, predicate: ["gtScroller"], descendants: true, read: ElementRef }, { propertyName: "vp", first: true, predicate: ["vp"], descendants: true }], ngImport: i0, template: "<!-- <div style=\"background: #f0f0f0; font-size: 12px; border-bottom: 1px solid #ccc;\">\n currentPivotScrollIndex {{currentPivotScrollIndex()}} | \n firstDataRowIndex {{firstDataRowIndex()}} | \n firstTr {{firstTr}} |\n maxDepth {{maxDepth()}}\n</div> -->\n<div class=\"incremental-row-container eru-grid\" #rowContainer \n [class.pivot-mode]=\"gridStore.isPivotMode()\"\n [class.table-mode]=\"!gridStore.isPivotMode()\">\n \n <!-- Pivot Mode Template -->\n @if (gridStore.isPivotMode()) {\n <ng-container >\n <div class=\"pivot-container\" style=\"display: flex; flex-direction: column; height: 100%;\"\n [style]=\"'--table-min-height: ' + getInitialMinHeightPx() + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <!-- Debug info for first visible row -->\n \n \n <div class=\"pivot-single-table\" style=\"height: 100%; width: 100%; overflow: hidden; display: flex; flex-direction: column;\">\n @if (freezeHeader()) {\n <div #headerScroller class=\"header-shell\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n @if(grandTotalPosition() === 'before' && freezeGrandTotal()) {\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n }\n </table> \n </div>\n } \n <!-- Virtual Scrolled Table Body -->\n <div>\n <cdk-virtual-scroll-viewport\n #vp\n [itemSize]=\"50\"\n class=\"viewport pivot-viewport\"\n [class.apply-cdk-width]=\"applyCdkWidth()\"\n (scrolledIndexChange)=\"onPivotScroll($event)\"\n (scroll)=\"onBodyScroll($event)\"\n style=\"overflow: auto;\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\"\n >\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n @if (!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container> \n }\n <!-- Table Body with Virtual Scrolling -->\n <tbody class=\"pivot-tbody\">\n \n <tr *cdkVirtualFor=\"let pivotRow of gridStore.pivotDisplayData(); \n trackBy: trackByPivotRowFn; \n let i = index\"\n class=\"pivot-row\"\n [class.subtotal-row]=\"pivotRow._isSubtotal\"\n [class.grand-total-row]=\"pivotRow._isGrandTotal\"\n [class.subtotal-bold]=\"pivotRow._isSubtotal && subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"pivotRow._isSubtotal && subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"pivotRow._isSubtotal && subTotalStyle() === 'highlighted'\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\"\n [attr.data-pivot-row]=\"i\">\n @if ((!pivotRow._isGrandTotal && freezeGrandTotal() ) || (!freezeGrandTotal() )) { \n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n @if (!shouldSkipCell(i, column.name)) {\n <td\n [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\"\n [style.height.px]=\"50\"\n [attr.xx]=\"i\"> \n <div class=\"cell-content pivot-cell-content\">\n <data-cell\n [class.aggregation]=\"!!column.aggregationFunction\"\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\"\n [column]=\"column\"\n [drillable]=\"column.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n </div>\n </td>\n }\n }\n } @else {\n <td [style.height.px]=\"50\" [attr.colspan]=\"getLeafColumns().length\"> </td>\n }\n </tr> \n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n\n </div>\n @if (freezeGrandTotal() && grandTotalPosition() === 'after') {\n <div #gtScroller class=\"header-shell gt-shell\"\n [class.adjust-bottom]=\"!applyCdkWidth()\"\n [class.adjust-bottom-vs]=\"adjustScrollWidth()\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n \n </table> \n </div>\n }\n \n\n </div>\n </div>\n </ng-container>\n} @else {\n \n<!-- Table Mode Template -->\n <ng-container>\n <cdk-virtual-scroll-viewport\n [itemSize]=\"30\"\n class=\"viewport table-viewport\"\n (scrolledIndexChange)=\"onScroll($event)\"\n >\n <div class=\"table-wrapper\">\n \n <table class=\"eru-grid-table\" [class.show-column-lines]=\"showColumnLines()\" [class.show-column-lines]=\"showColumnLines()\">\n <thead>\n <tr>\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\"></th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"column-header\">\n {{column.label}}\n </th>\n </tr>\n </thead>\n <tbody *ngIf=\"columns() as columnsList\">\n <ng-container *cdkVirtualFor=\"let groupItem of groupedRows();\n trackBy: trackByGroupItemFn;\n let i = index;\n let first=first\">\n <tr\n *ngIf=\"groupItem.type === 'header' && groups().length > 1\"\n class=\"group-header\"\n (click)=\"toggleGroupExpansion(groupItem.group?.id || '')\"\n >\n \n <td class=\"checkbox-column\" style=\"border: none;\">\n {{ groupItem.group?.isExpanded ? '\u25BC' : '\u25B6' }}\n </td>\n \n <td [attr.colspan]=\"2\" style=\"border: none;\">\n <span class=\"group-title\">\n {{ groupItem.group?.title }}\n </span>\n <span class=\"group-row-count\">\n ({{ groupItem.group?.currentLoadedRows || 0 }}/{{ groupItem.group?.totalRowCount || 0 }})\n </span>\n </td>\n </tr>\n <tr *ngIf=\"groupItem.type === 'table-header' && groups().length > 1\" style=\"background:#fafafa\">\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isGroupSelected(groupItem.group?.id || '')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleGroupSelection($event, groupItem.group?.id || '')\"\n >\n </th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn;let i =index\"\n style=\"text-align: center;\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"true\"\n [columnConfig]=\"column\"\n [columnDraggable]=\"i\"\n class=\"column-header\">\n <div class=\"column-drag-handle\"></div>\n {{column.label}} {{column.symbol}}\n </th>\n </tr>\n <tr\n *ngIf=\"groupItem.type === 'row' && groupItem.group?.isExpanded\"\n class=\"row-item\"\n [attr.data-row-id]=\"groupItem.row?.entity_id\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n >\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isRowSelected(groupItem.row?.entity_id)\"\n (change)=\"toggleRowSelection($event, groupItem.row)\"\n >\n </td>\n }\n <td #cell *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"data-cell\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n [matTooltipClass]=\"'error-message'\"\n [matTooltip]=\"datacell.error()?'Error: ' + datacell.error():''\"\n matTooltipPosition=\"below\"\n >\n <div class=\"cell-content\">\n <data-cell\n #datacell \n [td]=cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"groupItem.row?.[column.name] || ''\"\n [column]=\"column\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [drillable]=\"column.enableDrilldown || false\"\n [id]=\"groupItem.row?.['entity_id'] || '_' ||column.name\"\n [eruGridStore]=\"gridStore\"\n ></data-cell>\n </div>\n </td>\n </tr>\n\n <tr\n *ngIf=\"groupItem.type === 'ghost-loading' && groupItem.group?.isExpanded\"\n class=\"ghost-loading-row\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n >\n <td class=\"checkbox-column\"></td>\n <td *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"ghost-cell-container\"\n >\n <div class=\"ghost-cell\"></div>\n </td>\n </tr>\n\n <tr\n *ngIf=\"groupItem.type === 'row-place-holder'\"\n class=\"group-separator\"\n >\n <td [attr.colspan]=\"groupSeperatorColSpan()\" class=\"separator-cell\"></td>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </div>\n </cdk-virtual-scroll-viewport>\n </ng-container> \n}\n</div>\n\n <!-- Pivot Table Header Template -->\n <ng-template #pivotTableHead>\n <thead>\n @if (hasNestedHeaders()) {\n <ng-container >\n @for (headerRow of getHeaderRows(); track headerRow; let rowIndex = $index) {\n <tr class=\"pivot-header pivot-header-container\" \n [class.pivot-header-level]=\"'level-' + rowIndex\">\n @for (header of headerRow; track trackByHeaderFn($index, header); let colIndex = $index) {\n <th\n [attr.colspan]=\"header.colspan\"\n [attr.rowspan]=\"header.rowspan\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable') && header.level === 0\"\n class=\"column-header pivot-column-header nested-header\"\n [class.row-dimension-header]=\"isRowDimensionHeader(header)\"\n [class.column-dimension-header]=\"!isRowDimensionHeader(header)\"\n [class.expanded]=\"header.isExpanded\"\n [class.collapsed]=\"!header.isExpanded\"\n [class.sticky-column]=\"isStickyColumn(header.name, colIndex)\"\n [style.position]=\"isStickyColumn(header.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(header.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(header.name, colIndex) ? 100 : 1\"\n style=\"min-height: 40px; height: auto; padding: 8px 6px;\">\n <div class=\"header-content\">\n \n <data-cell\n [fieldSize]=\"header.field_size\"\n [columnDatatype]=\"header.dataType\"\n [columnName]=\"header.name\"\n [value]=\"header.label\"\n [column]=\"header\"\n [frozenGrandTotalCell]=\"true\"\n [drillable]=\"header.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + $index + '_' + header.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n <!-- <span class=\"header-label header-wrap-text\">{{header.label}}</span> -->\n <!-- <button *ngIf=\"!isRowDimensionHeader(header)\" \n class=\"collapse-toggle-btn\"\n [title]=\"header.isExpanded ? 'Collapse group' : 'Expand group'\"\n (click)=\"toggleColumnGroup(header.groupKey)\"\n type=\"button\">\n <span class=\"collapse-icon\">+</span>\n </button> -->\n </div>\n </th>\n }\n </tr>\n }\n </ng-container>\n } @else {\n <!-- Simple header fallback -->\n <ng-container>\n <tr class=\"pivot-header\" [class.freeze-header-enabled]=\"freezeHeader()\">\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <th [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [columnConfig]=\"column\"\n class=\"column-header pivot-column-header\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 100 : 1\"\n style = \"min-height: 40px;height: auto;padding: 8px 6px;position: relative;left: 0px;z-index: 1\">\n {{column.label}}\n </th>\n }\n </tr>\n </ng-container>\n }\n \n </thead>\n</ng-template>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #pivotColGroup>\n <colgroup>\n @for (column of getLeafColumns(); track trackByColumnFn($index, column)) {\n <col [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n </colgroup>\n</ng-template>\n\n<ng-template #pivotGrandTotal>\n<tbody class=\"pivot-tbody\">\n @for (pivotRow of gridStore.pivotGrandTotalData(); track trackByPivotRowFn($index, pivotRow); let i = $index) {\n <tr \n class=\"pivot-row grand-total-row\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\"\n [attr.data-pivot-row]=\"i\">\n <!-- <td colspan=\"20\">{{pivotRow | json}}</td> -->\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td\n [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\" \n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\"\n [style.height.px]=\"50\"\n [attr.xx]=\"i\"> \n <div class=\"cell-content pivot-cell-content\">\n <data-cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\"\n [column]=\"column\"\n [frozenGrandTotalCell]=\"true\"\n [drillable]=\"column.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n </div>\n </td>\n }\n </tr>\n}\n</tbody>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%;height:100%;font-family:var(--grid-font-family);--grid-primary: #6750a4;--grid-on-primary: #ffffff;--grid-surface: #fef7ff;--grid-surface-variant: #e7e0ec;--grid-surface-container: #f3edf7;--grid-surface-container-high: #ede7f0;--grid-on-surface: #1d1b20;--grid-on-surface-variant: #49454f;--grid-outline: #79757f;--grid-outline-variant: #cac4d0;--grid-error: #ba1a1a;--grid-error-container: #ffdad6;--grid-font-family: \"Poppins\", \"Roboto\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--grid-font-size-body: 12px;--grid-font-size-caption: 12px !important;--grid-line-height-body: 1;--grid-aggregation-text-align: right;--grid-number-text-align: right;--grid-spacing-xxs: 2px;--grid-spacing-xs: 4px;--grid-spacing-sm: 8px;--grid-spacing-md: 16px;--grid-spacing-lg: 24px;--grid-border-radius: 4px;--grid-elevation-1: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 1px 3px 1px rgba(0, 0, 0, .15);--grid-elevation-2: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 2px 6px 2px rgba(0, 0, 0, .15)}.incremental-row-container{padding:10px;width:100%;height:100%;min-height:var(--table-min-height, 400px);max-height:none;overflow:auto;position:relative;background-color:var(--grid-surface);border-radius:var(--grid-border-radius);box-shadow:var(--grid-elevation-1);font-family:var(--grid-font-family)}.viewport{overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface);scrollbar-gutter:stable}.viewport.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.table-viewport{background-color:var(--grid-surface);height:auto;min-height:var(--table-min-height, 300px);max-height:80vh;overflow-x:auto;overflow-y:auto}.pivot-viewport{min-height:var(--table-min-height, 300px);overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface)}.pivot-viewport .cdk-virtual-scroll-content-wrapper{width:auto;height:auto}.table-wrapper{min-width:100%;overflow-x:visible}.incremental-row-container .eru-grid-table,.eru-grid-table{width:100%!important;border-collapse:separate;border-spacing:0;table-layout:fixed!important;background-color:var(--grid-surface);color:var(--grid-on-surface);font-size:var(--grid-font-size-body);line-height:var(--grid-line-height-body)}.eru-grid-table th,.eru-grid-table td{text-align:left;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;background-color:var(--grid-surface);color:var(--grid-on-surface);min-width:0;max-width:100%!important;box-sizing:border-box;position:relative}.eru-grid-table th:hover,.eru-grid-table td:hover{background-color:var(--grid-surface-variant)}.eru-grid-table thead{background-color:var(--grid-surface-container);transform:translateZ(0);will-change:transform;backface-visibility:hidden}.eru-grid-table thead.freeze-header-enabled{box-shadow:0 2px 4px #0000001a;border-bottom:2px solid var(--grid-outline)}.eru-grid-table thead th{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-weight:500;font-size:var(--grid-font-size-caption)}.checkbox-column{width:50px;min-width:50px;max-width:50px;text-align:center;border:1px solid var(--grid-outline);background-color:var(--grid-surface-container)}.checkbox-column input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--grid-primary);border-radius:var(--grid-border-radius)}.checkbox-column input[type=checkbox]:focus{outline:2px solid var(--grid-primary);outline-offset:2px}.group-header{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-size:var(--grid-font-size-caption);font-weight:500;border-bottom:1px solid var(--grid-outline);cursor:pointer;transition:background-color .2s ease}.group-header:hover{background-color:var(--grid-surface-container-high)}.group-header .group-title{font-weight:600;color:var(--grid-primary)}.group-header .group-row-count{color:var(--grid-on-surface-variant);font-size:var(--grid-font-size-caption);margin-left:var(--grid-spacing-sm)}.row-item{border:1px solid var(--grid-outline);background-color:var(--grid-surface);transition:background-color .2s ease,box-shadow .2s ease}.row-item:hover{background-color:var(--grid-surface-variant);box-shadow:var(--grid-elevation-1)}.column-header{font-weight:500;text-align:center!important;font-size:var(--grid-font-size-caption, 12px);position:relative;-webkit-user-select:none;user-select:none;background-color:var(--grid-surface-container);color:var(--grid-on-surface)}.column-header:hover{background-color:var(--grid-surface-container-high)}.column-drag-handle{position:absolute;left:0;top:0;bottom:0;width:12px;cursor:grab;opacity:0;transition:opacity .2s ease,background-color .2s ease;z-index:2;display:flex;align-items:center;justify-content:center;border-right:1px solid transparent}.column-drag-handle:after{content:\"\\22ee\\22ee\";font-size:14px;color:var(--grid-on-surface-variant);transform:rotate(90deg)}.column-drag-handle:hover{background-color:var(--grid-surface-container-high);border-right-color:var(--grid-outline)}.column-header:hover .column-drag-handle{opacity:1}.column-drag-handle:active{cursor:grabbing}.dragging{opacity:1;background-color:var(--grid-surface-container);box-shadow:var(--grid-elevation-2)}.drag-over{background-color:var(--grid-surface-container);border-color:var(--grid-primary)}.data-cell{background-color:var(--grid-surface);color:var(--grid-on-surface);font-size:var(--grid-font-size-body)}.cell-content{align-items:center}.cell-content .mdc-text-field{padding:0px var(--grid-spacing-xxs)!important}.cell-display-text{align-items:center;padding:0px var(--grid-spacing-xs)}.ghost-loading-row{background-color:transparent}.ghost-cell-container{padding:var(--grid-spacing-sm)}.ghost-cell{height:20px;width:100%;background-color:var(--grid-surface-container);animation:pulse 1.5s ease-in-out infinite;border-radius:var(--grid-border-radius)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.column-resizer{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;background-color:transparent;transition:background-color .2s ease}.column-resizer:hover{background-color:var(--grid-primary)}.group-separator{height:var(--grid-spacing-sm);background-color:var(--grid-surface-variant)}.group-separator .separator-cell{background-color:var(--grid-surface-variant);border:none;height:var(--grid-spacing-sm)}.error-state{background-color:var(--grid-error-container);color:var(--grid-error);border-color:var(--grid-error)}.error-message{background-color:var(--grid-error);color:#fff;padding:var(--grid-spacing-sm);border-radius:var(--grid-border-radius);font-size:var(--grid-font-size-caption)}.incremental-row-container .eru-grid-table tbody,.incremental-row-container .eru-grid-table{position:relative}.incremental-row-container .eru-grid-table.show-column-lines{border-right:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-top:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table:not(.show-column-lines){border:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table thead:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:calc(var(--grid-outline-width, 1px) * 2);background-color:var(--grid-outline, #e0e0e0);pointer-events:none;z-index:10}.incremental-row-container .eru-grid-table.show-column-lines thead th{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-column-lines tbody td{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-row-lines thead th{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-row-lines tbody td{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}@media (max-width: 768px){.incremental-row-container{height:600px}.eru-grid-table th,.eru-grid-table td{font-size:var(--grid-font-size-caption)}.checkbox-column{width:40px;min-width:40px;max-width:40px}}@media (prefers-contrast: high){.eru-grid-table th,.eru-grid-table td{border-width:2px}.row-item:hover{border-width:2px;border-color:var(--grid-primary)}}@media (prefers-reduced-motion: reduce){.row-item,.column-drag-handle,.ghost-cell{transition:none;animation:none}}.pivot-table .nested-header{text-align:center;font-weight:600;background:var(--grid-surface-container)}.pivot-table .nested-header.row-dimension-header{background:var(--grid-surface-container);font-weight:600}.pivot-table .pivot-header-leafcols{padding:0;margin:0;height:0}.pivot-table .pivot-header-level.level-0 .nested-header{font-size:14px;padding:12px 8px}.pivot-table .pivot-header-level.level-1 .nested-header{font-size:13px;padding:10px 6px}.pivot-table .pivot-header-level.level-2 .nested-header{font-size:12px;padding:8px 4px}.pivot-table .nested-header:hover{background:var(--grid-surface-variant);color:var(--grid-primary);transition:all .2s ease}.pivot-table .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-table .pivot-cell-content{display:flex;justify-content:center;align-items:center;min-height:38px}.pivot-table .rowspan-cell{vertical-align:middle}.pivot-table .rowspan-cell .pivot-cell-content{height:100%}.pivot-mode .incremental-row-container{display:flex;flex-direction:column;height:auto;max-height:85vh;overflow:auto}.pivot-mode .h-shell{position:relative;width:calc(100% - var(--scrollbar-width, 17px))!important;top:0;z-index:1;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .h-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell{position:relative;bottom:50px;flex-shrink:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .gt-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell table{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.pivot-mode .gt-shell.adjust-bottom-vs{bottom:66px!important}.pivot-mode .gt-shell.adjust-bottom:not(.adjust-bottom-vs){bottom:calc(66px - var(--scrollbar-width, 17px))!important}.pivot-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .header-shell::-webkit-scrollbar{display:none}.pivot-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.pivot-mode .header-shell .eru-grid-table{margin-bottom:0;width:100%;table-layout:fixed}.pivot-mode .header-shell .eru-grid-table thead{background:var(--grid-surface-container)}.pivot-mode .header-shell .eru-grid-table thead th{background:var(--grid-surface-container);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .header-shell .eru-grid-table thead th.sticky-column{position:sticky;background:var(--grid-surface-container);z-index:111}.pivot-mode .header-shell .eru-grid-table tbody td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-container{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.pivot-mode .pivot-table{width:auto!important;min-width:100%!important;table-layout:fixed!important;width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important}.pivot-mode .pivot-table td,.pivot-mode .pivot-table th{box-sizing:border-box!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-table *{max-width:var(--col-width)!important;box-sizing:border-box!important}.pivot-mode .pivot-table colgroup{width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex-basis:var(--col-width)!important;flex:0 0 var(--col-width)!important}.pivot-mode .pivot-table table{width:100%!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important}.pivot-mode .pivot-table[style*=--table-total-width]{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:0 0 var(--col-width)!important;flex-basis:var(--col-width)!important;flex-grow:0!important;flex-shrink:0!important;overflow:hidden!important}.pivot-mode .pivot-table tbody td,.pivot-mode .pivot-table thead th{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.pivot-mode .pivot-table .cell-content,.pivot-mode .pivot-table data-cell{width:100%!important;max-width:100%!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;display:block!important}.pivot-mode .pivot-table table{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-tbody tr.pivot-row{min-height:50px!important;height:50px!important}.pivot-mode .pivot-tbody tr.pivot-row:hover{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-tbody tr.pivot-row:nth-child(2n){background-color:#00000005}.pivot-mode .pivot-tbody tr.pivot-row td{min-height:50px!important;height:50px!important;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content{min-height:48px;display:flex;align-items:center;justify-content:center}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content data-cell{width:100%;min-height:46px;display:flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0}.pivot-mode .pivot-cell{vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-mode .pivot-cell .cell-content{display:flex;justify-content:center;align-items:center;min-height:40px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:0}.pivot-mode .pivot-table .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.pivot-mode .pivot-table .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .subtotal-row td:first-child{color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row td.aggregated-value{font-weight:500;color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.pivot-mode .pivot-table .subtotal-bold td{font-weight:600!important;font-style:normal!important}.pivot-mode .pivot-table .subtotal-bold td.aggregated-value{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td{font-style:italic!important}.pivot-mode .pivot-table .subtotal-italic td:first-child{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.pivot-mode .pivot-table .subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted td.aggregated-value{font-weight:500!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted:hover,.pivot-mode .pivot-table .subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-row{background-color:var(--grid-surface-container-high)!important;font-weight:700;font-size:var(--grid-font-size-body)}.pivot-mode .pivot-table .grand-total-row td{background-color:var(--grid-surface-container-high)!important;color:var(--grid-on-surface)}.pivot-mode .pivot-table .grand-total-row td:first-child{font-style:normal;font-weight:800;color:var(--grid-primary)}.pivot-mode .pivot-table .grand-total-row td.aggregated-value{font-weight:500;color:var(--grid-primary);font-family:Roboto Mono,monospace}.pivot-mode .pivot-table .grand-total-row:hover,.pivot-mode .pivot-table .grand-total-row:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-bold td{font-weight:700!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-bold td.aggregated-value{font-weight:700!important}.pivot-mode .pivot-table .grand-total-italic td,.pivot-mode .pivot-table .grand-total-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted{background-color:var(--grid-primary)!important;box-shadow:var(--grid-elevation-2)!important}.pivot-mode .pivot-table .grand-total-highlighted td{background-color:var(--grid-primary)!important;color:var(--grid-on-primary)!important;font-weight:500!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-highlighted td.aggregated-value{color:var(--grid-on-primary)!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted:hover,.pivot-mode .pivot-table .grand-total-highlighted:hover td{background-color:var(--grid-primary)!important}.pivot-mode .pivot-table .collapsible-header{position:relative}.pivot-mode .pivot-table .collapsible-header .header-content{display:flex;align-items:center;justify-content:space-between;gap:var(--grid-spacing-xs);padding:var(--grid-spacing-xs) var(--grid-spacing-sm)}.pivot-mode .pivot-table .collapsible-header .header-label{flex:1;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn{background:none;border:none;cursor:pointer;padding:var(--grid-spacing-xxs);margin:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:var(--grid-border-radius);color:var(--grid-on-surface-variant);transition:all .2s ease;font-size:12px;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:hover{background-color:var(--grid-surface-container);color:var(--grid-primary);transform:scale(1.1)}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:focus{outline:2px solid var(--grid-primary);outline-offset:1px}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn .collapse-icon{display:block;line-height:1;font-family:monospace;font-size:14px}.pivot-mode .pivot-table .collapsible-header.expanded .collapse-toggle-btn .collapse-icon{color:var(--grid-primary)}.pivot-mode .pivot-table .collapsible-header.collapsed{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .header-label{font-style:italic;color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .collapse-toggle-btn .collapse-icon{color:var(--grid-outline)}.pivot-mode .pivot-table .collapsible-header:hover{background-color:var(--grid-surface-container)}.pivot-mode .pivot-table .collapsible-header:hover .header-label{color:var(--grid-on-surface)}.pivot-mode .pivot-table .pivot-single-table{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden;min-height:var(--table-min-height)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container{flex-shrink:0;background:var(--grid-surface)!important;overflow-x:auto;overflow-y:hidden;min-height:100px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table{width:auto;min-width:100%;height:auto!important;min-height:100px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th{background:var(--grid-surface-container)!important;padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:40px!important;height:auto!important;position:relative;visibility:visible!important;color:var(--grid-on-surface)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:101!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container{flex:1;overflow:auto;min-height:300px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-viewport{height:100%!important;width:100%!important;overflow-x:auto!important;overflow-y:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table{width:auto;min-width:100%;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td{padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:32px!important;height:auto!important;background:var(--grid-surface)!important;color:var(--grid-on-surface)!important;visibility:visible!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td.sticky-column,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:100!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr{height:auto!important;min-height:50px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr.pivot-row,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr.pivot-row{visibility:visible!important;display:table-row!important}.pivot-mode .pivot-table .collapsed-column-group{background-color:var(--grid-surface-container);border-left:3px solid var(--grid-primary)}.pivot-mode .pivot-table .collapsed-column-group:hover{background-color:var(--grid-surface-container-high)}.pivot-row.subtotal-row{background-color:var(--grid-surface-variant);font-weight:500}.pivot-row.subtotal-row.subtotal-bold{font-weight:500}.pivot-row.subtotal-row.subtotal-italic{font-style:italic}.pivot-row.subtotal-row.subtotal-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.grand-total-row{background-color:var(--grid-surface-container);font-weight:600}.pivot-row.grand-total-row.grand-total-bold{font-weight:800}.pivot-row.grand-total-row.grand-total-italic{font-style:italic}.pivot-row.grand-total-row.grand-total-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.first-visible-row{background-color:#6750a41a!important;position:relative}.pivot-row.first-visible-row:before{content:\"\\1f441\\fe0f First Visible\";position:absolute;top:-20px;left:0;background:var(--grid-primary);color:var(--grid-on-primary);padding:2px 6px;font-size:10px;border-radius:2px;z-index:1000}.header-wrap-text{white-space:pre-wrap;word-break:auto-phrase}\n"], dependencies: [{ kind: "component", type: DataCellComponent, selector: "data-cell", inputs: ["eruGridStore", "fieldSize", "columnDatatype", "columnName", "column", "value", "id", "frozenGrandTotalCell", "td", "drillable", "mode", "isEditable"], outputs: ["tdChange"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1$2.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1$2.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1$2.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: ResizeColumnDirective, selector: "[resizeColumn]", inputs: ["resizeColumn", "index", "columnConfig", "gridConfig"] }, { kind: "directive", type: ColumnDragDirective, selector: "[columnDraggable]", inputs: ["columnDraggable"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
5759
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.3", type: EruGridComponent, isStandalone: true, selector: "eru-grid", inputs: { gridConfig: "gridConfig" }, providers: [EruGridStore, EruGridService], viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true }, { propertyName: "rowContainer", first: true, predicate: ["rowContainer"], descendants: true }, { propertyName: "headerScroller", first: true, predicate: ["headerScroller"], descendants: true, read: ElementRef }, { propertyName: "gtScroller", first: true, predicate: ["gtScroller"], descendants: true, read: ElementRef }, { propertyName: "vp", first: true, predicate: ["vp"], descendants: true }], ngImport: i0, template: "<!-- <div style=\"background: #f0f0f0; font-size: 12px; border-bottom: 1px solid #ccc;\">\n currentPivotScrollIndex {{currentPivotScrollIndex()}} | \n firstDataRowIndex {{firstDataRowIndex()}} | \n firstTr {{firstTr}} |\n maxDepth {{maxDepth()}}\n</div> -->\n<div class=\"incremental-row-container eru-grid\" #rowContainer \n [class.pivot-mode]=\"gridStore.isPivotMode()\"\n [class.table-mode]=\"!gridStore.isPivotMode()\">\n \n <!-- Pivot Mode Template -->\n @if (gridStore.isPivotMode()) {\n <ng-container >\n <div class=\"pivot-container\" style=\"display: flex; flex-direction: column; height: 100%;\"\n [style]=\"'--table-min-height: ' + getInitialMinHeightPx() + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <!-- Debug info for first visible row -->\n \n \n <div class=\"pivot-single-table\" style=\"height: 100%; width: 100%; overflow: hidden; display: flex; flex-direction: column;\">\n @if (freezeHeader()) {\n <div #headerScroller class=\"header-shell\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n @if(grandTotalPosition() === 'before' && freezeGrandTotal()) {\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n }\n </table> \n </div>\n } \n <!-- Virtual Scrolled Table Body -->\n <div>\n <cdk-virtual-scroll-viewport\n #vp\n [itemSize]=\"50\"\n class=\"viewport pivot-viewport\"\n [class.apply-cdk-width]=\"applyCdkWidth()\"\n (scrolledIndexChange)=\"onPivotScroll($event)\"\n (scroll)=\"onBodyScroll($event)\"\n style=\"overflow: auto;\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\"\n >\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n @if (!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container> \n }\n <!-- Table Body with Virtual Scrolling -->\n <tbody class=\"pivot-tbody\">\n \n <tr *cdkVirtualFor=\"let pivotRow of gridStore.pivotDisplayData(); \n trackBy: trackByPivotRowFn; \n let i = index\"\n class=\"pivot-row\"\n [class.subtotal-row]=\"pivotRow._isSubtotal\"\n [class.grand-total-row]=\"pivotRow._isGrandTotal\"\n [class.subtotal-bold]=\"pivotRow._isSubtotal && subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"pivotRow._isSubtotal && subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"pivotRow._isSubtotal && subTotalStyle() === 'highlighted'\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\"\n [attr.data-pivot-row]=\"i\">\n @if ((!pivotRow._isGrandTotal && freezeGrandTotal() ) || (!freezeGrandTotal() )) { \n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n @if (!shouldSkipCell(i, column.name)) {\n <td\n [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\"\n [style.height.px]=\"50\"\n [attr.xx]=\"i\"> \n <div class=\"cell-content pivot-cell-content\">\n <data-cell\n [class.aggregation]=\"!!column.aggregationFunction\"\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\"\n [column]=\"column\"\n [drillable]=\"column.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n </div>\n </td>\n }\n }\n } @else {\n <td [style.height.px]=\"50\" [attr.colspan]=\"getLeafColumns().length\"> </td>\n }\n </tr> \n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n\n </div>\n @if (freezeGrandTotal() && grandTotalPosition() === 'after') {\n <div #gtScroller class=\"header-shell gt-shell\"\n [class.adjust-bottom]=\"!applyCdkWidth()\"\n [class.adjust-bottom-vs]=\"adjustScrollWidth()\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n \n </table> \n </div>\n }\n \n\n </div>\n </div>\n </ng-container>\n} @else {\n \n<!-- Table Mode Template -->\n <ng-container>\n <cdk-virtual-scroll-viewport\n [itemSize]=\"30\"\n class=\"viewport table-viewport\"\n (scrolledIndexChange)=\"onScroll($event)\"\n >\n <div class=\"table-wrapper\">\n \n <table class=\"eru-grid-table\" [class.show-column-lines]=\"showColumnLines()\" [class.show-column-lines]=\"showColumnLines()\">\n <thead>\n <tr>\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\"></th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"column-header table-column-header\">\n {{column.label}}\n </th>\n </tr>\n </thead>\n <tbody *ngIf=\"columns() as columnsList\">\n <ng-container *cdkVirtualFor=\"let groupItem of groupedRows();\n trackBy: trackByGroupItemFn;\n let i = index;\n let first=first\">\n <tr\n *ngIf=\"groupItem.type === 'header' && groups().length > 1\"\n class=\"group-header\"\n (click)=\"toggleGroupExpansion(groupItem.group?.id || '')\"\n >\n \n <td class=\"checkbox-column\" style=\"border: none;\">\n {{ groupItem.group?.isExpanded ? '\u25BC' : '\u25B6' }}\n </td>\n \n <td [attr.colspan]=\"2\" style=\"border: none;\">\n <span class=\"group-title\">\n {{ groupItem.group?.title }}\n </span>\n <span class=\"group-row-count\">\n ({{ groupItem.group?.currentLoadedRows || 0 }}/{{ groupItem.group?.totalRowCount || 0 }})\n </span>\n </td>\n </tr>\n <tr *ngIf=\"groupItem.type === 'table-header' && groups().length > 1\" style=\"background:#fafafa\">\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isGroupSelected(groupItem.group?.id || '')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleGroupSelection($event, groupItem.group?.id || '')\"\n >\n </th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn;let i =index\"\n style=\"text-align: center;\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"true\"\n [columnConfig]=\"column\"\n [columnDraggable]=\"i\"\n class=\"column-header\">\n <div class=\"column-drag-handle\"></div>\n {{column.label}} {{column.symbol}}\n </th>\n </tr>\n <tr\n *ngIf=\"groupItem.type === 'row' && groupItem.group?.isExpanded\"\n class=\"row-item\"\n [attr.data-row-id]=\"groupItem.row?.entity_id\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n >\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isRowSelected(groupItem.row?.entity_id)\"\n (change)=\"toggleRowSelection($event, groupItem.row)\"\n >\n </td>\n }\n <td #cell *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"data-cell\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n [matTooltipClass]=\"'error-message'\"\n [matTooltip]=\"datacell.error()?'Error: ' + datacell.error():''\"\n matTooltipPosition=\"below\"\n >\n <div class=\"cell-content\">\n <data-cell\n #datacell \n [td]=cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"groupItem.row?.[column.name] || ''\"\n [column]=\"column\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [drillable]=\"column.enableDrilldown || false\"\n [id]=\"i + '_' + column.name\"\n [eruGridStore]=\"gridStore\"\n ></data-cell>\n </div>\n </td>\n </tr>\n\n <tr\n *ngIf=\"groupItem.type === 'ghost-loading' && groupItem.group?.isExpanded\"\n class=\"ghost-loading-row\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n >\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\"></th>\n }\n <td *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"ghost-cell-container\"\n >\n <div class=\"ghost-cell\"></div>\n </td>\n </tr>\n\n <tr\n *ngIf=\"groupItem.type === 'row-place-holder'\"\n class=\"group-separator\"\n >\n <td [attr.colspan]=\"groupSeperatorColSpan()\" class=\"separator-cell\"></td>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </div>\n </cdk-virtual-scroll-viewport>\n </ng-container> \n}\n</div>\n\n <!-- Pivot Table Header Template -->\n <ng-template #pivotTableHead>\n <thead>\n @if (hasNestedHeaders()) {\n <ng-container >\n @for (headerRow of getHeaderRows(); track headerRow; let rowIndex = $index) {\n <tr class=\"pivot-header pivot-header-container\" \n [class.pivot-header-level]=\"'level-' + rowIndex\">\n @for (header of headerRow; track trackByHeaderFn($index, header); let colIndex = $index) {\n <th\n [attr.colspan]=\"header.colspan\"\n [attr.rowspan]=\"header.rowspan\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable') && header.level === 0\"\n class=\"column-header pivot-column-header nested-header\"\n [class.row-dimension-header]=\"isRowDimensionHeader(header)\"\n [class.column-dimension-header]=\"!isRowDimensionHeader(header)\"\n [class.expanded]=\"header.isExpanded\"\n [class.collapsed]=\"!header.isExpanded\"\n [class.sticky-column]=\"isStickyColumn(header.name, colIndex)\"\n [style.position]=\"isStickyColumn(header.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(header.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(header.name, colIndex) ? 100 : 1\"\n style=\"min-height: 40px; height: auto; padding: 8px 6px;\">\n <div class=\"header-content\">\n \n <data-cell\n [fieldSize]=\"header.field_size\"\n [columnDatatype]=\"header.dataType\"\n [columnName]=\"header.name\"\n [value]=\"header.label\"\n [column]=\"header\"\n [frozenGrandTotalCell]=\"true\"\n [drillable]=\"header.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + $index + '_' + header.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n <!-- <span class=\"header-label header-wrap-text\">{{header.label}}</span> -->\n <!-- <button *ngIf=\"!isRowDimensionHeader(header)\" \n class=\"collapse-toggle-btn\"\n [title]=\"header.isExpanded ? 'Collapse group' : 'Expand group'\"\n (click)=\"toggleColumnGroup(header.groupKey)\"\n type=\"button\">\n <span class=\"collapse-icon\">+</span>\n </button> -->\n </div>\n </th>\n }\n </tr>\n }\n </ng-container>\n } @else {\n <!-- Simple header fallback -->\n <ng-container>\n <tr class=\"pivot-header\" [class.freeze-header-enabled]=\"freezeHeader()\">\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <th [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [columnConfig]=\"column\"\n class=\"column-header pivot-column-header\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 100 : 1\"\n style = \"min-height: 40px;height: auto;padding: 8px 6px;position: relative;left: 0px;z-index: 1\">\n {{column.label}}\n </th>\n }\n </tr>\n </ng-container>\n }\n \n </thead>\n</ng-template>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #pivotColGroup>\n <colgroup>\n @for (column of getLeafColumns(); track trackByColumnFn($index, column)) {\n <col [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n </colgroup>\n</ng-template>\n\n<ng-template #pivotGrandTotal>\n<tbody class=\"pivot-tbody\">\n @for (pivotRow of gridStore.pivotGrandTotalData(); track trackByPivotRowFn($index, pivotRow); let i = $index) {\n <tr \n class=\"pivot-row grand-total-row\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\"\n [attr.data-pivot-row]=\"i\">\n <!-- <td colspan=\"20\">{{pivotRow | json}}</td> -->\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td\n [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\" \n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\"\n [style.height.px]=\"50\"\n [attr.xx]=\"i\"> \n <div class=\"cell-content pivot-cell-content\">\n <data-cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\"\n [column]=\"column\"\n [frozenGrandTotalCell]=\"true\"\n [drillable]=\"column.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n </div>\n </td>\n }\n </tr>\n}\n</tbody>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%;height:100%;font-family:var(--grid-font-family);--grid-primary: #6750a4;--grid-on-primary: #ffffff;--grid-surface: #fef7ff;--grid-surface-variant: #e7e0ec;--grid-surface-container: #f3edf7;--grid-surface-container-high: #ede7f0;--grid-on-surface: #1d1b20;--grid-on-surface-variant: #49454f;--grid-outline: #79757f;--grid-outline-variant: #cac4d0;--grid-error: #ba1a1a;--grid-error-container: #ffdad6;--grid-font-family: \"Poppins\", \"Roboto\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--grid-font-size-body: 12px;--grid-font-size-caption: 12px !important;--grid-line-height-body: 1;--grid-aggregation-text-align: right;--grid-number-text-align: right;--grid-spacing-xxs: 2px;--grid-spacing-xs: 4px;--grid-spacing-sm: 8px;--grid-spacing-md: 16px;--grid-spacing-lg: 24px;--grid-border-radius: 4px;--grid-elevation-1: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 1px 3px 1px rgba(0, 0, 0, .15);--grid-elevation-2: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 2px 6px 2px rgba(0, 0, 0, .15)}.incremental-row-container{padding:10px;width:100%;height:100%;min-height:var(--table-min-height, 400px);max-height:none;overflow:auto;position:relative;background-color:var(--grid-surface);border-radius:var(--grid-border-radius);box-shadow:var(--grid-elevation-1);font-family:var(--grid-font-family)}.viewport{overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface);scrollbar-gutter:stable}.viewport.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.table-viewport{background-color:var(--grid-surface);height:auto;min-height:var(--table-min-height, 300px);max-height:80vh;overflow-x:auto;overflow-y:auto}.pivot-viewport{min-height:var(--table-min-height, 300px);overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface)}.pivot-viewport .cdk-virtual-scroll-content-wrapper{width:auto;height:auto}.table-wrapper{min-width:100%;overflow-x:visible}.incremental-row-container .eru-grid-table,.eru-grid-table{width:100%!important;border-collapse:separate;border-spacing:0;table-layout:fixed!important;background-color:var(--grid-surface);color:var(--grid-on-surface);font-size:var(--grid-font-size-body);line-height:var(--grid-line-height-body)}.eru-grid-table th,.eru-grid-table td{text-align:left;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;background-color:var(--grid-surface);color:var(--grid-on-surface);min-width:0;max-width:100%!important;box-sizing:border-box;position:relative}.eru-grid-table th:hover,.eru-grid-table td:hover{background-color:var(--grid-surface-variant)}.eru-grid-table thead{background-color:var(--grid-surface-container);transform:translateZ(0);will-change:transform;backface-visibility:hidden}.eru-grid-table thead.freeze-header-enabled{box-shadow:0 2px 4px #0000001a;border-bottom:2px solid var(--grid-outline)}.eru-grid-table thead th{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-weight:500;font-size:var(--grid-font-size-caption)}.checkbox-column{width:50px;min-width:50px;max-width:50px;text-align:center;border:1px solid var(--grid-outline);background-color:var(--grid-surface-container)}.checkbox-column input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--grid-primary);border-radius:var(--grid-border-radius)}.checkbox-column input[type=checkbox]:focus{outline:2px solid var(--grid-primary);outline-offset:2px}.group-header{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-size:var(--grid-font-size-caption);font-weight:500;border-bottom:1px solid var(--grid-outline);cursor:pointer;transition:background-color .2s ease}.group-header:hover{background-color:var(--grid-surface-container-high)}.group-header .group-title{font-weight:600;color:var(--grid-primary)}.group-header .group-row-count{color:var(--grid-on-surface-variant);font-size:var(--grid-font-size-caption);margin-left:var(--grid-spacing-sm)}.row-item{border:1px solid var(--grid-outline);background-color:var(--grid-surface);transition:background-color .2s ease,box-shadow .2s ease}.row-item:hover{background-color:var(--grid-surface-variant);box-shadow:var(--grid-elevation-1)}.table-column-header{padding:12px 8px}.column-header{font-weight:500;text-align:center!important;font-size:var(--grid-font-size-caption, 12px);position:relative;-webkit-user-select:none;user-select:none;background-color:var(--grid-surface-container);color:var(--grid-on-surface)}.column-header:hover{background-color:var(--grid-surface-container-high)}.column-drag-handle{position:absolute;left:0;top:0;bottom:0;width:12px;cursor:grab;opacity:0;transition:opacity .2s ease,background-color .2s ease;z-index:2;display:flex;align-items:center;justify-content:center;border-right:1px solid transparent}.column-drag-handle:after{content:\"\\22ee\\22ee\";font-size:14px;color:var(--grid-on-surface-variant);transform:rotate(90deg)}.column-drag-handle:hover{background-color:var(--grid-surface-container-high);border-right-color:var(--grid-outline)}.column-header:hover .column-drag-handle{opacity:1}.column-drag-handle:active{cursor:grabbing}.dragging{opacity:1;background-color:var(--grid-surface-container);box-shadow:var(--grid-elevation-2)}.drag-over{background-color:var(--grid-surface-container);border-color:var(--grid-primary)}.data-cell{background-color:var(--grid-surface);color:var(--grid-on-surface);font-size:var(--grid-font-size-body)}.cell-content{align-items:center}.cell-content .mdc-text-field{padding:0px var(--grid-spacing-xxs)!important}.cell-display-text{align-items:center;padding:0px var(--grid-spacing-xs)}.ghost-loading-row{background-color:transparent}.ghost-cell-container{padding:var(--grid-spacing-sm)}.ghost-cell{height:20px;width:100%;background-color:var(--grid-surface-container);animation:pulse 1.5s ease-in-out infinite;border-radius:var(--grid-border-radius)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.column-resizer{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;background-color:transparent;transition:background-color .2s ease}.column-resizer:hover{background-color:var(--grid-primary)}.group-separator{height:var(--grid-spacing-sm);background-color:var(--grid-surface-variant)}.group-separator .separator-cell{background-color:var(--grid-surface-variant);border:none;height:var(--grid-spacing-sm)}.error-state{background-color:var(--grid-error-container);color:var(--grid-error);border-color:var(--grid-error)}.error-message{background-color:var(--grid-error);color:#fff;padding:var(--grid-spacing-sm);border-radius:var(--grid-border-radius);font-size:var(--grid-font-size-caption)}.incremental-row-container .eru-grid-table tbody,.incremental-row-container .eru-grid-table{position:relative}.incremental-row-container .eru-grid-table.show-column-lines{border-right:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-top:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table:not(.show-column-lines){border:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table thead:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:calc(var(--grid-outline-width, 1px) * 2);background-color:var(--grid-outline, #e0e0e0);pointer-events:none;z-index:10}.incremental-row-container .eru-grid-table.show-column-lines thead th{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-column-lines tbody td{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-row-lines thead th{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-row-lines tbody td{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}@media (max-width: 768px){.incremental-row-container{height:600px}.eru-grid-table th,.eru-grid-table td{font-size:var(--grid-font-size-caption)}.checkbox-column{width:40px;min-width:40px;max-width:40px}}@media (prefers-contrast: high){.eru-grid-table th,.eru-grid-table td{border-width:2px}.row-item:hover{border-width:2px;border-color:var(--grid-primary)}}@media (prefers-reduced-motion: reduce){.row-item,.column-drag-handle,.ghost-cell{transition:none;animation:none}}.pivot-table .nested-header{text-align:center;font-weight:600;background:var(--grid-surface-container)}.pivot-table .nested-header.row-dimension-header{background:var(--grid-surface-container);font-weight:600}.pivot-table .pivot-header-leafcols{padding:0;margin:0;height:0}.pivot-table .pivot-header-level.level-0 .nested-header{font-size:14px;padding:12px 8px}.pivot-table .pivot-header-level.level-1 .nested-header{font-size:13px;padding:10px 6px}.pivot-table .pivot-header-level.level-2 .nested-header{font-size:12px;padding:8px 4px}.pivot-table .nested-header:hover{background:var(--grid-surface-variant);color:var(--grid-primary);transition:all .2s ease}.pivot-table .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-table .pivot-cell-content{display:flex;justify-content:center;align-items:center;min-height:38px}.pivot-table .rowspan-cell{vertical-align:middle}.pivot-table .rowspan-cell .pivot-cell-content{height:100%}.pivot-mode .incremental-row-container{display:flex;flex-direction:column;height:auto;max-height:85vh;overflow:auto}.pivot-mode .h-shell{position:relative;width:calc(100% - var(--scrollbar-width, 17px))!important;top:0;z-index:1;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .h-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell{position:relative;bottom:50px;flex-shrink:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .gt-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell table{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.pivot-mode .gt-shell.adjust-bottom-vs{bottom:66px!important}.pivot-mode .gt-shell.adjust-bottom:not(.adjust-bottom-vs){bottom:calc(66px - var(--scrollbar-width, 17px))!important}.pivot-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .header-shell::-webkit-scrollbar{display:none}.pivot-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.pivot-mode .header-shell .eru-grid-table{margin-bottom:0;width:100%;table-layout:fixed}.pivot-mode .header-shell .eru-grid-table thead{background:var(--grid-surface-container)}.pivot-mode .header-shell .eru-grid-table thead th{background:var(--grid-surface-container);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .header-shell .eru-grid-table thead th.sticky-column{position:sticky;background:var(--grid-surface-container);z-index:111}.pivot-mode .header-shell .eru-grid-table tbody td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-container{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.pivot-mode .pivot-table{width:auto!important;min-width:100%!important;table-layout:fixed!important;width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important}.pivot-mode .pivot-table td,.pivot-mode .pivot-table th{box-sizing:border-box!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-table *{max-width:var(--col-width)!important;box-sizing:border-box!important}.pivot-mode .pivot-table colgroup{width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex-basis:var(--col-width)!important;flex:0 0 var(--col-width)!important}.pivot-mode .pivot-table table{width:100%!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important}.pivot-mode .pivot-table[style*=--table-total-width]{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:0 0 var(--col-width)!important;flex-basis:var(--col-width)!important;flex-grow:0!important;flex-shrink:0!important;overflow:hidden!important}.pivot-mode .pivot-table tbody td,.pivot-mode .pivot-table thead th{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.pivot-mode .pivot-table .cell-content,.pivot-mode .pivot-table data-cell{width:100%!important;max-width:100%!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;display:block!important}.pivot-mode .pivot-table table{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-tbody tr.pivot-row{min-height:50px!important;height:50px!important}.pivot-mode .pivot-tbody tr.pivot-row:hover{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-tbody tr.pivot-row:nth-child(2n){background-color:#00000005}.pivot-mode .pivot-tbody tr.pivot-row td{min-height:50px!important;height:50px!important;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content{min-height:48px;display:flex;align-items:center;justify-content:center}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content data-cell{width:100%;min-height:46px;display:flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0}.pivot-mode .pivot-cell{vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-mode .pivot-cell .cell-content{display:flex;justify-content:center;align-items:center;min-height:40px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:0}.pivot-mode .pivot-table .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.pivot-mode .pivot-table .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .subtotal-row td:first-child{color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row td.aggregated-value{font-weight:500;color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.pivot-mode .pivot-table .subtotal-bold td{font-weight:600!important;font-style:normal!important}.pivot-mode .pivot-table .subtotal-bold td.aggregated-value{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td{font-style:italic!important}.pivot-mode .pivot-table .subtotal-italic td:first-child{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.pivot-mode .pivot-table .subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted td.aggregated-value{font-weight:500!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted:hover,.pivot-mode .pivot-table .subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-row{background-color:var(--grid-surface-container-high)!important;font-weight:700;font-size:var(--grid-font-size-body)}.pivot-mode .pivot-table .grand-total-row td{background-color:var(--grid-surface-container-high)!important;color:var(--grid-on-surface)}.pivot-mode .pivot-table .grand-total-row td:first-child{font-style:normal;font-weight:800;color:var(--grid-primary)}.pivot-mode .pivot-table .grand-total-row td.aggregated-value{font-weight:500;color:var(--grid-primary);font-family:Roboto Mono,monospace}.pivot-mode .pivot-table .grand-total-row:hover,.pivot-mode .pivot-table .grand-total-row:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-bold td{font-weight:700!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-bold td.aggregated-value{font-weight:700!important}.pivot-mode .pivot-table .grand-total-italic td,.pivot-mode .pivot-table .grand-total-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted{background-color:var(--grid-primary)!important;box-shadow:var(--grid-elevation-2)!important}.pivot-mode .pivot-table .grand-total-highlighted td{background-color:var(--grid-primary)!important;color:var(--grid-on-primary)!important;font-weight:500!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-highlighted td.aggregated-value{color:var(--grid-on-primary)!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted:hover,.pivot-mode .pivot-table .grand-total-highlighted:hover td{background-color:var(--grid-primary)!important}.pivot-mode .pivot-table .collapsible-header{position:relative}.pivot-mode .pivot-table .collapsible-header .header-content{display:flex;align-items:center;justify-content:space-between;gap:var(--grid-spacing-xs);padding:var(--grid-spacing-xs) var(--grid-spacing-sm)}.pivot-mode .pivot-table .collapsible-header .header-label{flex:1;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn{background:none;border:none;cursor:pointer;padding:var(--grid-spacing-xxs);margin:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:var(--grid-border-radius);color:var(--grid-on-surface-variant);transition:all .2s ease;font-size:12px;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:hover{background-color:var(--grid-surface-container);color:var(--grid-primary);transform:scale(1.1)}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:focus{outline:2px solid var(--grid-primary);outline-offset:1px}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn .collapse-icon{display:block;line-height:1;font-family:monospace;font-size:14px}.pivot-mode .pivot-table .collapsible-header.expanded .collapse-toggle-btn .collapse-icon{color:var(--grid-primary)}.pivot-mode .pivot-table .collapsible-header.collapsed{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .header-label{font-style:italic;color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .collapse-toggle-btn .collapse-icon{color:var(--grid-outline)}.pivot-mode .pivot-table .collapsible-header:hover{background-color:var(--grid-surface-container)}.pivot-mode .pivot-table .collapsible-header:hover .header-label{color:var(--grid-on-surface)}.pivot-mode .pivot-table .pivot-single-table{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden;min-height:var(--table-min-height)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container{flex-shrink:0;background:var(--grid-surface)!important;overflow-x:auto;overflow-y:hidden;min-height:100px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table{width:auto;min-width:100%;height:auto!important;min-height:100px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th{background:var(--grid-surface-container)!important;padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:40px!important;height:auto!important;position:relative;visibility:visible!important;color:var(--grid-on-surface)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:101!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container{flex:1;overflow:auto;min-height:300px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-viewport{height:100%!important;width:100%!important;overflow-x:auto!important;overflow-y:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table{width:auto;min-width:100%;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td{padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:32px!important;height:auto!important;background:var(--grid-surface)!important;color:var(--grid-on-surface)!important;visibility:visible!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td.sticky-column,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:100!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr{height:auto!important;min-height:50px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr.pivot-row,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr.pivot-row{visibility:visible!important;display:table-row!important}.pivot-mode .pivot-table .collapsed-column-group{background-color:var(--grid-surface-container);border-left:3px solid var(--grid-primary)}.pivot-mode .pivot-table .collapsed-column-group:hover{background-color:var(--grid-surface-container-high)}.pivot-row.subtotal-row{background-color:var(--grid-surface-variant);font-weight:500}.pivot-row.subtotal-row.subtotal-bold{font-weight:500}.pivot-row.subtotal-row.subtotal-italic{font-style:italic}.pivot-row.subtotal-row.subtotal-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.grand-total-row{background-color:var(--grid-surface-container);font-weight:600}.pivot-row.grand-total-row.grand-total-bold{font-weight:800}.pivot-row.grand-total-row.grand-total-italic{font-style:italic}.pivot-row.grand-total-row.grand-total-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.first-visible-row{background-color:#6750a41a!important;position:relative}.pivot-row.first-visible-row:before{content:\"\\1f441\\fe0f First Visible\";position:absolute;top:-20px;left:0;background:var(--grid-primary);color:var(--grid-on-primary);padding:2px 6px;font-size:10px;border-radius:2px;z-index:1000}.header-wrap-text{white-space:pre-wrap;word-break:auto-phrase}\n"], dependencies: [{ kind: "component", type: DataCellComponent, selector: "data-cell", inputs: ["eruGridStore", "fieldSize", "columnDatatype", "columnName", "column", "value", "id", "frozenGrandTotalCell", "td", "drillable", "mode", "isEditable"], outputs: ["tdChange"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1$2.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1$2.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1$2.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: ResizeColumnDirective, selector: "[resizeColumn]", inputs: ["resizeColumn", "index", "columnConfig", "gridConfig"] }, { kind: "directive", type: ColumnDragDirective, selector: "[columnDraggable]", inputs: ["columnDraggable"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
6428
5760
|
}
|
|
6429
5761
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: EruGridComponent, decorators: [{
|
|
6430
5762
|
type: Component,
|
|
@@ -6435,7 +5767,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
6435
5767
|
MatTooltipModule,
|
|
6436
5768
|
ResizeColumnDirective,
|
|
6437
5769
|
ColumnDragDirective
|
|
6438
|
-
], template: "<!-- <div style=\"background: #f0f0f0; font-size: 12px; border-bottom: 1px solid #ccc;\">\n currentPivotScrollIndex {{currentPivotScrollIndex()}} | \n firstDataRowIndex {{firstDataRowIndex()}} | \n firstTr {{firstTr}} |\n maxDepth {{maxDepth()}}\n</div> -->\n<div class=\"incremental-row-container eru-grid\" #rowContainer \n [class.pivot-mode]=\"gridStore.isPivotMode()\"\n [class.table-mode]=\"!gridStore.isPivotMode()\">\n \n <!-- Pivot Mode Template -->\n @if (gridStore.isPivotMode()) {\n <ng-container >\n <div class=\"pivot-container\" style=\"display: flex; flex-direction: column; height: 100%;\"\n [style]=\"'--table-min-height: ' + getInitialMinHeightPx() + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <!-- Debug info for first visible row -->\n \n \n <div class=\"pivot-single-table\" style=\"height: 100%; width: 100%; overflow: hidden; display: flex; flex-direction: column;\">\n @if (freezeHeader()) {\n <div #headerScroller class=\"header-shell\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n @if(grandTotalPosition() === 'before' && freezeGrandTotal()) {\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n }\n </table> \n </div>\n } \n <!-- Virtual Scrolled Table Body -->\n <div>\n <cdk-virtual-scroll-viewport\n #vp\n [itemSize]=\"50\"\n class=\"viewport pivot-viewport\"\n [class.apply-cdk-width]=\"applyCdkWidth()\"\n (scrolledIndexChange)=\"onPivotScroll($event)\"\n (scroll)=\"onBodyScroll($event)\"\n style=\"overflow: auto;\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\"\n >\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n @if (!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container> \n }\n <!-- Table Body with Virtual Scrolling -->\n <tbody class=\"pivot-tbody\">\n \n <tr *cdkVirtualFor=\"let pivotRow of gridStore.pivotDisplayData(); \n trackBy: trackByPivotRowFn; \n let i = index\"\n class=\"pivot-row\"\n [class.subtotal-row]=\"pivotRow._isSubtotal\"\n [class.grand-total-row]=\"pivotRow._isGrandTotal\"\n [class.subtotal-bold]=\"pivotRow._isSubtotal && subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"pivotRow._isSubtotal && subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"pivotRow._isSubtotal && subTotalStyle() === 'highlighted'\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\"\n [attr.data-pivot-row]=\"i\">\n @if ((!pivotRow._isGrandTotal && freezeGrandTotal() ) || (!freezeGrandTotal() )) { \n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n @if (!shouldSkipCell(i, column.name)) {\n <td\n [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\"\n [style.height.px]=\"50\"\n [attr.xx]=\"i\"> \n <div class=\"cell-content pivot-cell-content\">\n <data-cell\n [class.aggregation]=\"!!column.aggregationFunction\"\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\"\n [column]=\"column\"\n [drillable]=\"column.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n </div>\n </td>\n }\n }\n } @else {\n <td [style.height.px]=\"50\" [attr.colspan]=\"getLeafColumns().length\"> </td>\n }\n </tr> \n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n\n </div>\n @if (freezeGrandTotal() && grandTotalPosition() === 'after') {\n <div #gtScroller class=\"header-shell gt-shell\"\n [class.adjust-bottom]=\"!applyCdkWidth()\"\n [class.adjust-bottom-vs]=\"adjustScrollWidth()\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n \n </table> \n </div>\n }\n \n\n </div>\n </div>\n </ng-container>\n} @else {\n \n<!-- Table Mode Template -->\n <ng-container>\n <cdk-virtual-scroll-viewport\n [itemSize]=\"30\"\n class=\"viewport table-viewport\"\n (scrolledIndexChange)=\"onScroll($event)\"\n >\n <div class=\"table-wrapper\">\n \n <table class=\"eru-grid-table\" [class.show-column-lines]=\"showColumnLines()\" [class.show-column-lines]=\"showColumnLines()\">\n <thead>\n <tr>\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\"></th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"column-header\">\n {{column.label}}\n </th>\n </tr>\n </thead>\n <tbody *ngIf=\"columns() as columnsList\">\n <ng-container *cdkVirtualFor=\"let groupItem of groupedRows();\n trackBy: trackByGroupItemFn;\n let i = index;\n let first=first\">\n <tr\n *ngIf=\"groupItem.type === 'header' && groups().length > 1\"\n class=\"group-header\"\n (click)=\"toggleGroupExpansion(groupItem.group?.id || '')\"\n >\n \n <td class=\"checkbox-column\" style=\"border: none;\">\n {{ groupItem.group?.isExpanded ? '\u25BC' : '\u25B6' }}\n </td>\n \n <td [attr.colspan]=\"2\" style=\"border: none;\">\n <span class=\"group-title\">\n {{ groupItem.group?.title }}\n </span>\n <span class=\"group-row-count\">\n ({{ groupItem.group?.currentLoadedRows || 0 }}/{{ groupItem.group?.totalRowCount || 0 }})\n </span>\n </td>\n </tr>\n <tr *ngIf=\"groupItem.type === 'table-header' && groups().length > 1\" style=\"background:#fafafa\">\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isGroupSelected(groupItem.group?.id || '')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleGroupSelection($event, groupItem.group?.id || '')\"\n >\n </th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn;let i =index\"\n style=\"text-align: center;\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"true\"\n [columnConfig]=\"column\"\n [columnDraggable]=\"i\"\n class=\"column-header\">\n <div class=\"column-drag-handle\"></div>\n {{column.label}} {{column.symbol}}\n </th>\n </tr>\n <tr\n *ngIf=\"groupItem.type === 'row' && groupItem.group?.isExpanded\"\n class=\"row-item\"\n [attr.data-row-id]=\"groupItem.row?.entity_id\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n >\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isRowSelected(groupItem.row?.entity_id)\"\n (change)=\"toggleRowSelection($event, groupItem.row)\"\n >\n </td>\n }\n <td #cell *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"data-cell\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n [matTooltipClass]=\"'error-message'\"\n [matTooltip]=\"datacell.error()?'Error: ' + datacell.error():''\"\n matTooltipPosition=\"below\"\n >\n <div class=\"cell-content\">\n <data-cell\n #datacell \n [td]=cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"groupItem.row?.[column.name] || ''\"\n [column]=\"column\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [drillable]=\"column.enableDrilldown || false\"\n [id]=\"groupItem.row?.['entity_id'] || '_' ||column.name\"\n [eruGridStore]=\"gridStore\"\n ></data-cell>\n </div>\n </td>\n </tr>\n\n <tr\n *ngIf=\"groupItem.type === 'ghost-loading' && groupItem.group?.isExpanded\"\n class=\"ghost-loading-row\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n >\n <td class=\"checkbox-column\"></td>\n <td *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"ghost-cell-container\"\n >\n <div class=\"ghost-cell\"></div>\n </td>\n </tr>\n\n <tr\n *ngIf=\"groupItem.type === 'row-place-holder'\"\n class=\"group-separator\"\n >\n <td [attr.colspan]=\"groupSeperatorColSpan()\" class=\"separator-cell\"></td>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </div>\n </cdk-virtual-scroll-viewport>\n </ng-container> \n}\n</div>\n\n <!-- Pivot Table Header Template -->\n <ng-template #pivotTableHead>\n <thead>\n @if (hasNestedHeaders()) {\n <ng-container >\n @for (headerRow of getHeaderRows(); track headerRow; let rowIndex = $index) {\n <tr class=\"pivot-header pivot-header-container\" \n [class.pivot-header-level]=\"'level-' + rowIndex\">\n @for (header of headerRow; track trackByHeaderFn($index, header); let colIndex = $index) {\n <th\n [attr.colspan]=\"header.colspan\"\n [attr.rowspan]=\"header.rowspan\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable') && header.level === 0\"\n class=\"column-header pivot-column-header nested-header\"\n [class.row-dimension-header]=\"isRowDimensionHeader(header)\"\n [class.column-dimension-header]=\"!isRowDimensionHeader(header)\"\n [class.expanded]=\"header.isExpanded\"\n [class.collapsed]=\"!header.isExpanded\"\n [class.sticky-column]=\"isStickyColumn(header.name, colIndex)\"\n [style.position]=\"isStickyColumn(header.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(header.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(header.name, colIndex) ? 100 : 1\"\n style=\"min-height: 40px; height: auto; padding: 8px 6px;\">\n <div class=\"header-content\">\n \n <data-cell\n [fieldSize]=\"header.field_size\"\n [columnDatatype]=\"header.dataType\"\n [columnName]=\"header.name\"\n [value]=\"header.label\"\n [column]=\"header\"\n [frozenGrandTotalCell]=\"true\"\n [drillable]=\"header.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + $index + '_' + header.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n <!-- <span class=\"header-label header-wrap-text\">{{header.label}}</span> -->\n <!-- <button *ngIf=\"!isRowDimensionHeader(header)\" \n class=\"collapse-toggle-btn\"\n [title]=\"header.isExpanded ? 'Collapse group' : 'Expand group'\"\n (click)=\"toggleColumnGroup(header.groupKey)\"\n type=\"button\">\n <span class=\"collapse-icon\">+</span>\n </button> -->\n </div>\n </th>\n }\n </tr>\n }\n </ng-container>\n } @else {\n <!-- Simple header fallback -->\n <ng-container>\n <tr class=\"pivot-header\" [class.freeze-header-enabled]=\"freezeHeader()\">\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <th [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [columnConfig]=\"column\"\n class=\"column-header pivot-column-header\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 100 : 1\"\n style = \"min-height: 40px;height: auto;padding: 8px 6px;position: relative;left: 0px;z-index: 1\">\n {{column.label}}\n </th>\n }\n </tr>\n </ng-container>\n }\n \n </thead>\n</ng-template>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #pivotColGroup>\n <colgroup>\n @for (column of getLeafColumns(); track trackByColumnFn($index, column)) {\n <col [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n </colgroup>\n</ng-template>\n\n<ng-template #pivotGrandTotal>\n<tbody class=\"pivot-tbody\">\n @for (pivotRow of gridStore.pivotGrandTotalData(); track trackByPivotRowFn($index, pivotRow); let i = $index) {\n <tr \n class=\"pivot-row grand-total-row\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\"\n [attr.data-pivot-row]=\"i\">\n <!-- <td colspan=\"20\">{{pivotRow | json}}</td> -->\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td\n [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\" \n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\"\n [style.height.px]=\"50\"\n [attr.xx]=\"i\"> \n <div class=\"cell-content pivot-cell-content\">\n <data-cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\"\n [column]=\"column\"\n [frozenGrandTotalCell]=\"true\"\n [drillable]=\"column.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n </div>\n </td>\n }\n </tr>\n}\n</tbody>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%;height:100%;font-family:var(--grid-font-family);--grid-primary: #6750a4;--grid-on-primary: #ffffff;--grid-surface: #fef7ff;--grid-surface-variant: #e7e0ec;--grid-surface-container: #f3edf7;--grid-surface-container-high: #ede7f0;--grid-on-surface: #1d1b20;--grid-on-surface-variant: #49454f;--grid-outline: #79757f;--grid-outline-variant: #cac4d0;--grid-error: #ba1a1a;--grid-error-container: #ffdad6;--grid-font-family: \"Poppins\", \"Roboto\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--grid-font-size-body: 12px;--grid-font-size-caption: 12px !important;--grid-line-height-body: 1;--grid-aggregation-text-align: right;--grid-number-text-align: right;--grid-spacing-xxs: 2px;--grid-spacing-xs: 4px;--grid-spacing-sm: 8px;--grid-spacing-md: 16px;--grid-spacing-lg: 24px;--grid-border-radius: 4px;--grid-elevation-1: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 1px 3px 1px rgba(0, 0, 0, .15);--grid-elevation-2: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 2px 6px 2px rgba(0, 0, 0, .15)}.incremental-row-container{padding:10px;width:100%;height:100%;min-height:var(--table-min-height, 400px);max-height:none;overflow:auto;position:relative;background-color:var(--grid-surface);border-radius:var(--grid-border-radius);box-shadow:var(--grid-elevation-1);font-family:var(--grid-font-family)}.viewport{overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface);scrollbar-gutter:stable}.viewport.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.table-viewport{background-color:var(--grid-surface);height:auto;min-height:var(--table-min-height, 300px);max-height:80vh;overflow-x:auto;overflow-y:auto}.pivot-viewport{min-height:var(--table-min-height, 300px);overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface)}.pivot-viewport .cdk-virtual-scroll-content-wrapper{width:auto;height:auto}.table-wrapper{min-width:100%;overflow-x:visible}.incremental-row-container .eru-grid-table,.eru-grid-table{width:100%!important;border-collapse:separate;border-spacing:0;table-layout:fixed!important;background-color:var(--grid-surface);color:var(--grid-on-surface);font-size:var(--grid-font-size-body);line-height:var(--grid-line-height-body)}.eru-grid-table th,.eru-grid-table td{text-align:left;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;background-color:var(--grid-surface);color:var(--grid-on-surface);min-width:0;max-width:100%!important;box-sizing:border-box;position:relative}.eru-grid-table th:hover,.eru-grid-table td:hover{background-color:var(--grid-surface-variant)}.eru-grid-table thead{background-color:var(--grid-surface-container);transform:translateZ(0);will-change:transform;backface-visibility:hidden}.eru-grid-table thead.freeze-header-enabled{box-shadow:0 2px 4px #0000001a;border-bottom:2px solid var(--grid-outline)}.eru-grid-table thead th{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-weight:500;font-size:var(--grid-font-size-caption)}.checkbox-column{width:50px;min-width:50px;max-width:50px;text-align:center;border:1px solid var(--grid-outline);background-color:var(--grid-surface-container)}.checkbox-column input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--grid-primary);border-radius:var(--grid-border-radius)}.checkbox-column input[type=checkbox]:focus{outline:2px solid var(--grid-primary);outline-offset:2px}.group-header{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-size:var(--grid-font-size-caption);font-weight:500;border-bottom:1px solid var(--grid-outline);cursor:pointer;transition:background-color .2s ease}.group-header:hover{background-color:var(--grid-surface-container-high)}.group-header .group-title{font-weight:600;color:var(--grid-primary)}.group-header .group-row-count{color:var(--grid-on-surface-variant);font-size:var(--grid-font-size-caption);margin-left:var(--grid-spacing-sm)}.row-item{border:1px solid var(--grid-outline);background-color:var(--grid-surface);transition:background-color .2s ease,box-shadow .2s ease}.row-item:hover{background-color:var(--grid-surface-variant);box-shadow:var(--grid-elevation-1)}.column-header{font-weight:500;text-align:center!important;font-size:var(--grid-font-size-caption, 12px);position:relative;-webkit-user-select:none;user-select:none;background-color:var(--grid-surface-container);color:var(--grid-on-surface)}.column-header:hover{background-color:var(--grid-surface-container-high)}.column-drag-handle{position:absolute;left:0;top:0;bottom:0;width:12px;cursor:grab;opacity:0;transition:opacity .2s ease,background-color .2s ease;z-index:2;display:flex;align-items:center;justify-content:center;border-right:1px solid transparent}.column-drag-handle:after{content:\"\\22ee\\22ee\";font-size:14px;color:var(--grid-on-surface-variant);transform:rotate(90deg)}.column-drag-handle:hover{background-color:var(--grid-surface-container-high);border-right-color:var(--grid-outline)}.column-header:hover .column-drag-handle{opacity:1}.column-drag-handle:active{cursor:grabbing}.dragging{opacity:1;background-color:var(--grid-surface-container);box-shadow:var(--grid-elevation-2)}.drag-over{background-color:var(--grid-surface-container);border-color:var(--grid-primary)}.data-cell{background-color:var(--grid-surface);color:var(--grid-on-surface);font-size:var(--grid-font-size-body)}.cell-content{align-items:center}.cell-content .mdc-text-field{padding:0px var(--grid-spacing-xxs)!important}.cell-display-text{align-items:center;padding:0px var(--grid-spacing-xs)}.ghost-loading-row{background-color:transparent}.ghost-cell-container{padding:var(--grid-spacing-sm)}.ghost-cell{height:20px;width:100%;background-color:var(--grid-surface-container);animation:pulse 1.5s ease-in-out infinite;border-radius:var(--grid-border-radius)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.column-resizer{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;background-color:transparent;transition:background-color .2s ease}.column-resizer:hover{background-color:var(--grid-primary)}.group-separator{height:var(--grid-spacing-sm);background-color:var(--grid-surface-variant)}.group-separator .separator-cell{background-color:var(--grid-surface-variant);border:none;height:var(--grid-spacing-sm)}.error-state{background-color:var(--grid-error-container);color:var(--grid-error);border-color:var(--grid-error)}.error-message{background-color:var(--grid-error);color:#fff;padding:var(--grid-spacing-sm);border-radius:var(--grid-border-radius);font-size:var(--grid-font-size-caption)}.incremental-row-container .eru-grid-table tbody,.incremental-row-container .eru-grid-table{position:relative}.incremental-row-container .eru-grid-table.show-column-lines{border-right:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-top:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table:not(.show-column-lines){border:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table thead:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:calc(var(--grid-outline-width, 1px) * 2);background-color:var(--grid-outline, #e0e0e0);pointer-events:none;z-index:10}.incremental-row-container .eru-grid-table.show-column-lines thead th{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-column-lines tbody td{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-row-lines thead th{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-row-lines tbody td{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}@media (max-width: 768px){.incremental-row-container{height:600px}.eru-grid-table th,.eru-grid-table td{font-size:var(--grid-font-size-caption)}.checkbox-column{width:40px;min-width:40px;max-width:40px}}@media (prefers-contrast: high){.eru-grid-table th,.eru-grid-table td{border-width:2px}.row-item:hover{border-width:2px;border-color:var(--grid-primary)}}@media (prefers-reduced-motion: reduce){.row-item,.column-drag-handle,.ghost-cell{transition:none;animation:none}}.pivot-table .nested-header{text-align:center;font-weight:600;background:var(--grid-surface-container)}.pivot-table .nested-header.row-dimension-header{background:var(--grid-surface-container);font-weight:600}.pivot-table .pivot-header-leafcols{padding:0;margin:0;height:0}.pivot-table .pivot-header-level.level-0 .nested-header{font-size:14px;padding:12px 8px}.pivot-table .pivot-header-level.level-1 .nested-header{font-size:13px;padding:10px 6px}.pivot-table .pivot-header-level.level-2 .nested-header{font-size:12px;padding:8px 4px}.pivot-table .nested-header:hover{background:var(--grid-surface-variant);color:var(--grid-primary);transition:all .2s ease}.pivot-table .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-table .pivot-cell-content{display:flex;justify-content:center;align-items:center;min-height:38px}.pivot-table .rowspan-cell{vertical-align:middle}.pivot-table .rowspan-cell .pivot-cell-content{height:100%}.pivot-mode .incremental-row-container{display:flex;flex-direction:column;height:auto;max-height:85vh;overflow:auto}.pivot-mode .h-shell{position:relative;width:calc(100% - var(--scrollbar-width, 17px))!important;top:0;z-index:1;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .h-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell{position:relative;bottom:50px;flex-shrink:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .gt-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell table{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.pivot-mode .gt-shell.adjust-bottom-vs{bottom:66px!important}.pivot-mode .gt-shell.adjust-bottom:not(.adjust-bottom-vs){bottom:calc(66px - var(--scrollbar-width, 17px))!important}.pivot-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .header-shell::-webkit-scrollbar{display:none}.pivot-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.pivot-mode .header-shell .eru-grid-table{margin-bottom:0;width:100%;table-layout:fixed}.pivot-mode .header-shell .eru-grid-table thead{background:var(--grid-surface-container)}.pivot-mode .header-shell .eru-grid-table thead th{background:var(--grid-surface-container);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .header-shell .eru-grid-table thead th.sticky-column{position:sticky;background:var(--grid-surface-container);z-index:111}.pivot-mode .header-shell .eru-grid-table tbody td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-container{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.pivot-mode .pivot-table{width:auto!important;min-width:100%!important;table-layout:fixed!important;width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important}.pivot-mode .pivot-table td,.pivot-mode .pivot-table th{box-sizing:border-box!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-table *{max-width:var(--col-width)!important;box-sizing:border-box!important}.pivot-mode .pivot-table colgroup{width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex-basis:var(--col-width)!important;flex:0 0 var(--col-width)!important}.pivot-mode .pivot-table table{width:100%!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important}.pivot-mode .pivot-table[style*=--table-total-width]{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:0 0 var(--col-width)!important;flex-basis:var(--col-width)!important;flex-grow:0!important;flex-shrink:0!important;overflow:hidden!important}.pivot-mode .pivot-table tbody td,.pivot-mode .pivot-table thead th{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.pivot-mode .pivot-table .cell-content,.pivot-mode .pivot-table data-cell{width:100%!important;max-width:100%!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;display:block!important}.pivot-mode .pivot-table table{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-tbody tr.pivot-row{min-height:50px!important;height:50px!important}.pivot-mode .pivot-tbody tr.pivot-row:hover{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-tbody tr.pivot-row:nth-child(2n){background-color:#00000005}.pivot-mode .pivot-tbody tr.pivot-row td{min-height:50px!important;height:50px!important;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content{min-height:48px;display:flex;align-items:center;justify-content:center}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content data-cell{width:100%;min-height:46px;display:flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0}.pivot-mode .pivot-cell{vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-mode .pivot-cell .cell-content{display:flex;justify-content:center;align-items:center;min-height:40px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:0}.pivot-mode .pivot-table .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.pivot-mode .pivot-table .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .subtotal-row td:first-child{color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row td.aggregated-value{font-weight:500;color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.pivot-mode .pivot-table .subtotal-bold td{font-weight:600!important;font-style:normal!important}.pivot-mode .pivot-table .subtotal-bold td.aggregated-value{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td{font-style:italic!important}.pivot-mode .pivot-table .subtotal-italic td:first-child{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.pivot-mode .pivot-table .subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted td.aggregated-value{font-weight:500!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted:hover,.pivot-mode .pivot-table .subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-row{background-color:var(--grid-surface-container-high)!important;font-weight:700;font-size:var(--grid-font-size-body)}.pivot-mode .pivot-table .grand-total-row td{background-color:var(--grid-surface-container-high)!important;color:var(--grid-on-surface)}.pivot-mode .pivot-table .grand-total-row td:first-child{font-style:normal;font-weight:800;color:var(--grid-primary)}.pivot-mode .pivot-table .grand-total-row td.aggregated-value{font-weight:500;color:var(--grid-primary);font-family:Roboto Mono,monospace}.pivot-mode .pivot-table .grand-total-row:hover,.pivot-mode .pivot-table .grand-total-row:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-bold td{font-weight:700!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-bold td.aggregated-value{font-weight:700!important}.pivot-mode .pivot-table .grand-total-italic td,.pivot-mode .pivot-table .grand-total-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted{background-color:var(--grid-primary)!important;box-shadow:var(--grid-elevation-2)!important}.pivot-mode .pivot-table .grand-total-highlighted td{background-color:var(--grid-primary)!important;color:var(--grid-on-primary)!important;font-weight:500!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-highlighted td.aggregated-value{color:var(--grid-on-primary)!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted:hover,.pivot-mode .pivot-table .grand-total-highlighted:hover td{background-color:var(--grid-primary)!important}.pivot-mode .pivot-table .collapsible-header{position:relative}.pivot-mode .pivot-table .collapsible-header .header-content{display:flex;align-items:center;justify-content:space-between;gap:var(--grid-spacing-xs);padding:var(--grid-spacing-xs) var(--grid-spacing-sm)}.pivot-mode .pivot-table .collapsible-header .header-label{flex:1;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn{background:none;border:none;cursor:pointer;padding:var(--grid-spacing-xxs);margin:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:var(--grid-border-radius);color:var(--grid-on-surface-variant);transition:all .2s ease;font-size:12px;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:hover{background-color:var(--grid-surface-container);color:var(--grid-primary);transform:scale(1.1)}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:focus{outline:2px solid var(--grid-primary);outline-offset:1px}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn .collapse-icon{display:block;line-height:1;font-family:monospace;font-size:14px}.pivot-mode .pivot-table .collapsible-header.expanded .collapse-toggle-btn .collapse-icon{color:var(--grid-primary)}.pivot-mode .pivot-table .collapsible-header.collapsed{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .header-label{font-style:italic;color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .collapse-toggle-btn .collapse-icon{color:var(--grid-outline)}.pivot-mode .pivot-table .collapsible-header:hover{background-color:var(--grid-surface-container)}.pivot-mode .pivot-table .collapsible-header:hover .header-label{color:var(--grid-on-surface)}.pivot-mode .pivot-table .pivot-single-table{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden;min-height:var(--table-min-height)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container{flex-shrink:0;background:var(--grid-surface)!important;overflow-x:auto;overflow-y:hidden;min-height:100px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table{width:auto;min-width:100%;height:auto!important;min-height:100px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th{background:var(--grid-surface-container)!important;padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:40px!important;height:auto!important;position:relative;visibility:visible!important;color:var(--grid-on-surface)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:101!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container{flex:1;overflow:auto;min-height:300px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-viewport{height:100%!important;width:100%!important;overflow-x:auto!important;overflow-y:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table{width:auto;min-width:100%;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td{padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:32px!important;height:auto!important;background:var(--grid-surface)!important;color:var(--grid-on-surface)!important;visibility:visible!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td.sticky-column,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:100!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr{height:auto!important;min-height:50px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr.pivot-row,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr.pivot-row{visibility:visible!important;display:table-row!important}.pivot-mode .pivot-table .collapsed-column-group{background-color:var(--grid-surface-container);border-left:3px solid var(--grid-primary)}.pivot-mode .pivot-table .collapsed-column-group:hover{background-color:var(--grid-surface-container-high)}.pivot-row.subtotal-row{background-color:var(--grid-surface-variant);font-weight:500}.pivot-row.subtotal-row.subtotal-bold{font-weight:500}.pivot-row.subtotal-row.subtotal-italic{font-style:italic}.pivot-row.subtotal-row.subtotal-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.grand-total-row{background-color:var(--grid-surface-container);font-weight:600}.pivot-row.grand-total-row.grand-total-bold{font-weight:800}.pivot-row.grand-total-row.grand-total-italic{font-style:italic}.pivot-row.grand-total-row.grand-total-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.first-visible-row{background-color:#6750a41a!important;position:relative}.pivot-row.first-visible-row:before{content:\"\\1f441\\fe0f First Visible\";position:absolute;top:-20px;left:0;background:var(--grid-primary);color:var(--grid-on-primary);padding:2px 6px;font-size:10px;border-radius:2px;z-index:1000}.header-wrap-text{white-space:pre-wrap;word-break:auto-phrase}\n"] }]
|
|
5770
|
+
], template: "<!-- <div style=\"background: #f0f0f0; font-size: 12px; border-bottom: 1px solid #ccc;\">\n currentPivotScrollIndex {{currentPivotScrollIndex()}} | \n firstDataRowIndex {{firstDataRowIndex()}} | \n firstTr {{firstTr}} |\n maxDepth {{maxDepth()}}\n</div> -->\n<div class=\"incremental-row-container eru-grid\" #rowContainer \n [class.pivot-mode]=\"gridStore.isPivotMode()\"\n [class.table-mode]=\"!gridStore.isPivotMode()\">\n \n <!-- Pivot Mode Template -->\n @if (gridStore.isPivotMode()) {\n <ng-container >\n <div class=\"pivot-container\" style=\"display: flex; flex-direction: column; height: 100%;\"\n [style]=\"'--table-min-height: ' + getInitialMinHeightPx() + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <!-- Debug info for first visible row -->\n \n \n <div class=\"pivot-single-table\" style=\"height: 100%; width: 100%; overflow: hidden; display: flex; flex-direction: column;\">\n @if (freezeHeader()) {\n <div #headerScroller class=\"header-shell\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n @if(grandTotalPosition() === 'before' && freezeGrandTotal()) {\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n }\n </table> \n </div>\n } \n <!-- Virtual Scrolled Table Body -->\n <div>\n <cdk-virtual-scroll-viewport\n #vp\n [itemSize]=\"50\"\n class=\"viewport pivot-viewport\"\n [class.apply-cdk-width]=\"applyCdkWidth()\"\n (scrolledIndexChange)=\"onPivotScroll($event)\"\n (scroll)=\"onBodyScroll($event)\"\n style=\"overflow: auto;\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\"\n >\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n @if (!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container> \n }\n <!-- Table Body with Virtual Scrolling -->\n <tbody class=\"pivot-tbody\">\n \n <tr *cdkVirtualFor=\"let pivotRow of gridStore.pivotDisplayData(); \n trackBy: trackByPivotRowFn; \n let i = index\"\n class=\"pivot-row\"\n [class.subtotal-row]=\"pivotRow._isSubtotal\"\n [class.grand-total-row]=\"pivotRow._isGrandTotal\"\n [class.subtotal-bold]=\"pivotRow._isSubtotal && subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"pivotRow._isSubtotal && subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"pivotRow._isSubtotal && subTotalStyle() === 'highlighted'\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\"\n [attr.data-pivot-row]=\"i\">\n @if ((!pivotRow._isGrandTotal && freezeGrandTotal() ) || (!freezeGrandTotal() )) { \n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n @if (!shouldSkipCell(i, column.name)) {\n <td\n [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\"\n [style.height.px]=\"50\"\n [attr.xx]=\"i\"> \n <div class=\"cell-content pivot-cell-content\">\n <data-cell\n [class.aggregation]=\"!!column.aggregationFunction\"\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\"\n [column]=\"column\"\n [drillable]=\"column.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n </div>\n </td>\n }\n }\n } @else {\n <td [style.height.px]=\"50\" [attr.colspan]=\"getLeafColumns().length\"> </td>\n }\n </tr> \n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n\n </div>\n @if (freezeGrandTotal() && grandTotalPosition() === 'after') {\n <div #gtScroller class=\"header-shell gt-shell\"\n [class.adjust-bottom]=\"!applyCdkWidth()\"\n [class.adjust-bottom-vs]=\"adjustScrollWidth()\">\n <table class=\"eru-grid-table pivot-table\" \n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" \n [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n \n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n \n </table> \n </div>\n }\n \n\n </div>\n </div>\n </ng-container>\n} @else {\n \n<!-- Table Mode Template -->\n <ng-container>\n <cdk-virtual-scroll-viewport\n [itemSize]=\"30\"\n class=\"viewport table-viewport\"\n (scrolledIndexChange)=\"onScroll($event)\"\n >\n <div class=\"table-wrapper\">\n \n <table class=\"eru-grid-table\" [class.show-column-lines]=\"showColumnLines()\" [class.show-column-lines]=\"showColumnLines()\">\n <thead>\n <tr>\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\"></th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"column-header table-column-header\">\n {{column.label}}\n </th>\n </tr>\n </thead>\n <tbody *ngIf=\"columns() as columnsList\">\n <ng-container *cdkVirtualFor=\"let groupItem of groupedRows();\n trackBy: trackByGroupItemFn;\n let i = index;\n let first=first\">\n <tr\n *ngIf=\"groupItem.type === 'header' && groups().length > 1\"\n class=\"group-header\"\n (click)=\"toggleGroupExpansion(groupItem.group?.id || '')\"\n >\n \n <td class=\"checkbox-column\" style=\"border: none;\">\n {{ groupItem.group?.isExpanded ? '\u25BC' : '\u25B6' }}\n </td>\n \n <td [attr.colspan]=\"2\" style=\"border: none;\">\n <span class=\"group-title\">\n {{ groupItem.group?.title }}\n </span>\n <span class=\"group-row-count\">\n ({{ groupItem.group?.currentLoadedRows || 0 }}/{{ groupItem.group?.totalRowCount || 0 }})\n </span>\n </td>\n </tr>\n <tr *ngIf=\"groupItem.type === 'table-header' && groups().length > 1\" style=\"background:#fafafa\">\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isGroupSelected(groupItem.group?.id || '')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleGroupSelection($event, groupItem.group?.id || '')\"\n >\n </th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn;let i =index\"\n style=\"text-align: center;\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"true\"\n [columnConfig]=\"column\"\n [columnDraggable]=\"i\"\n class=\"column-header\">\n <div class=\"column-drag-handle\"></div>\n {{column.label}} {{column.symbol}}\n </th>\n </tr>\n <tr\n *ngIf=\"groupItem.type === 'row' && groupItem.group?.isExpanded\"\n class=\"row-item\"\n [attr.data-row-id]=\"groupItem.row?.entity_id\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n >\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isRowSelected(groupItem.row?.entity_id)\"\n (change)=\"toggleRowSelection($event, groupItem.row)\"\n >\n </td>\n }\n <td #cell *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"data-cell\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n [matTooltipClass]=\"'error-message'\"\n [matTooltip]=\"datacell.error()?'Error: ' + datacell.error():''\"\n matTooltipPosition=\"below\"\n >\n <div class=\"cell-content\">\n <data-cell\n #datacell \n [td]=cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"groupItem.row?.[column.name] || ''\"\n [column]=\"column\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [drillable]=\"column.enableDrilldown || false\"\n [id]=\"i + '_' + column.name\"\n [eruGridStore]=\"gridStore\"\n ></data-cell>\n </div>\n </td>\n </tr>\n\n <tr\n *ngIf=\"groupItem.type === 'ghost-loading' && groupItem.group?.isExpanded\"\n class=\"ghost-loading-row\"\n [style.height.px]=\"30\"\n [style.minHeight.px]=\"30\"\n [style.maxHeight.px]=\"30\"\n >\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\"></th>\n }\n <td *ngFor=\"let column of columns(); trackBy: trackByColumnFn\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"ghost-cell-container\"\n >\n <div class=\"ghost-cell\"></div>\n </td>\n </tr>\n\n <tr\n *ngIf=\"groupItem.type === 'row-place-holder'\"\n class=\"group-separator\"\n >\n <td [attr.colspan]=\"groupSeperatorColSpan()\" class=\"separator-cell\"></td>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </div>\n </cdk-virtual-scroll-viewport>\n </ng-container> \n}\n</div>\n\n <!-- Pivot Table Header Template -->\n <ng-template #pivotTableHead>\n <thead>\n @if (hasNestedHeaders()) {\n <ng-container >\n @for (headerRow of getHeaderRows(); track headerRow; let rowIndex = $index) {\n <tr class=\"pivot-header pivot-header-container\" \n [class.pivot-header-level]=\"'level-' + rowIndex\">\n @for (header of headerRow; track trackByHeaderFn($index, header); let colIndex = $index) {\n <th\n [attr.colspan]=\"header.colspan\"\n [attr.rowspan]=\"header.rowspan\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable') && header.level === 0\"\n class=\"column-header pivot-column-header nested-header\"\n [class.row-dimension-header]=\"isRowDimensionHeader(header)\"\n [class.column-dimension-header]=\"!isRowDimensionHeader(header)\"\n [class.expanded]=\"header.isExpanded\"\n [class.collapsed]=\"!header.isExpanded\"\n [class.sticky-column]=\"isStickyColumn(header.name, colIndex)\"\n [style.position]=\"isStickyColumn(header.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(header.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(header.name, colIndex) ? 100 : 1\"\n style=\"min-height: 40px; height: auto; padding: 8px 6px;\">\n <div class=\"header-content\">\n \n <data-cell\n [fieldSize]=\"header.field_size\"\n [columnDatatype]=\"header.dataType\"\n [columnName]=\"header.name\"\n [value]=\"header.label\"\n [column]=\"header\"\n [frozenGrandTotalCell]=\"true\"\n [drillable]=\"header.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + $index + '_' + header.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n <!-- <span class=\"header-label header-wrap-text\">{{header.label}}</span> -->\n <!-- <button *ngIf=\"!isRowDimensionHeader(header)\" \n class=\"collapse-toggle-btn\"\n [title]=\"header.isExpanded ? 'Collapse group' : 'Expand group'\"\n (click)=\"toggleColumnGroup(header.groupKey)\"\n type=\"button\">\n <span class=\"collapse-icon\">+</span>\n </button> -->\n </div>\n </th>\n }\n </tr>\n }\n </ng-container>\n } @else {\n <!-- Simple header fallback -->\n <ng-container>\n <tr class=\"pivot-header\" [class.freeze-header-enabled]=\"freezeHeader()\">\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <th [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [columnConfig]=\"column\"\n class=\"column-header pivot-column-header\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 100 : 1\"\n style = \"min-height: 40px;height: auto;padding: 8px 6px;position: relative;left: 0px;z-index: 1\">\n {{column.label}}\n </th>\n }\n </tr>\n </ng-container>\n }\n \n </thead>\n</ng-template>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #pivotColGroup>\n <colgroup>\n @for (column of getLeafColumns(); track trackByColumnFn($index, column)) {\n <col [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n </colgroup>\n</ng-template>\n\n<ng-template #pivotGrandTotal>\n<tbody class=\"pivot-tbody\">\n @for (pivotRow of gridStore.pivotGrandTotalData(); track trackByPivotRowFn($index, pivotRow); let i = $index) {\n <tr \n class=\"pivot-row grand-total-row\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\"\n [attr.data-pivot-row]=\"i\">\n <!-- <td colspan=\"20\">{{pivotRow | json}}</td> -->\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td\n [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\" \n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\"\n [style.height.px]=\"50\"\n [attr.xx]=\"i\"> \n <div class=\"cell-content pivot-cell-content\">\n <data-cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\"\n [column]=\"column\"\n [frozenGrandTotalCell]=\"true\"\n [drillable]=\"column.enableDrilldown || false\"\n [mode]=\"mode()\"\n [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\"\n [eruGridStore]=\"gridStore\">\n </data-cell>\n </div>\n </td>\n }\n </tr>\n}\n</tbody>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%;height:100%;font-family:var(--grid-font-family);--grid-primary: #6750a4;--grid-on-primary: #ffffff;--grid-surface: #fef7ff;--grid-surface-variant: #e7e0ec;--grid-surface-container: #f3edf7;--grid-surface-container-high: #ede7f0;--grid-on-surface: #1d1b20;--grid-on-surface-variant: #49454f;--grid-outline: #79757f;--grid-outline-variant: #cac4d0;--grid-error: #ba1a1a;--grid-error-container: #ffdad6;--grid-font-family: \"Poppins\", \"Roboto\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--grid-font-size-body: 12px;--grid-font-size-caption: 12px !important;--grid-line-height-body: 1;--grid-aggregation-text-align: right;--grid-number-text-align: right;--grid-spacing-xxs: 2px;--grid-spacing-xs: 4px;--grid-spacing-sm: 8px;--grid-spacing-md: 16px;--grid-spacing-lg: 24px;--grid-border-radius: 4px;--grid-elevation-1: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 1px 3px 1px rgba(0, 0, 0, .15);--grid-elevation-2: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 2px 6px 2px rgba(0, 0, 0, .15)}.incremental-row-container{padding:10px;width:100%;height:100%;min-height:var(--table-min-height, 400px);max-height:none;overflow:auto;position:relative;background-color:var(--grid-surface);border-radius:var(--grid-border-radius);box-shadow:var(--grid-elevation-1);font-family:var(--grid-font-family)}.viewport{overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface);scrollbar-gutter:stable}.viewport.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.table-viewport{background-color:var(--grid-surface);height:auto;min-height:var(--table-min-height, 300px);max-height:80vh;overflow-x:auto;overflow-y:auto}.pivot-viewport{min-height:var(--table-min-height, 300px);overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface)}.pivot-viewport .cdk-virtual-scroll-content-wrapper{width:auto;height:auto}.table-wrapper{min-width:100%;overflow-x:visible}.incremental-row-container .eru-grid-table,.eru-grid-table{width:100%!important;border-collapse:separate;border-spacing:0;table-layout:fixed!important;background-color:var(--grid-surface);color:var(--grid-on-surface);font-size:var(--grid-font-size-body);line-height:var(--grid-line-height-body)}.eru-grid-table th,.eru-grid-table td{text-align:left;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;background-color:var(--grid-surface);color:var(--grid-on-surface);min-width:0;max-width:100%!important;box-sizing:border-box;position:relative}.eru-grid-table th:hover,.eru-grid-table td:hover{background-color:var(--grid-surface-variant)}.eru-grid-table thead{background-color:var(--grid-surface-container);transform:translateZ(0);will-change:transform;backface-visibility:hidden}.eru-grid-table thead.freeze-header-enabled{box-shadow:0 2px 4px #0000001a;border-bottom:2px solid var(--grid-outline)}.eru-grid-table thead th{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-weight:500;font-size:var(--grid-font-size-caption)}.checkbox-column{width:50px;min-width:50px;max-width:50px;text-align:center;border:1px solid var(--grid-outline);background-color:var(--grid-surface-container)}.checkbox-column input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--grid-primary);border-radius:var(--grid-border-radius)}.checkbox-column input[type=checkbox]:focus{outline:2px solid var(--grid-primary);outline-offset:2px}.group-header{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-size:var(--grid-font-size-caption);font-weight:500;border-bottom:1px solid var(--grid-outline);cursor:pointer;transition:background-color .2s ease}.group-header:hover{background-color:var(--grid-surface-container-high)}.group-header .group-title{font-weight:600;color:var(--grid-primary)}.group-header .group-row-count{color:var(--grid-on-surface-variant);font-size:var(--grid-font-size-caption);margin-left:var(--grid-spacing-sm)}.row-item{border:1px solid var(--grid-outline);background-color:var(--grid-surface);transition:background-color .2s ease,box-shadow .2s ease}.row-item:hover{background-color:var(--grid-surface-variant);box-shadow:var(--grid-elevation-1)}.table-column-header{padding:12px 8px}.column-header{font-weight:500;text-align:center!important;font-size:var(--grid-font-size-caption, 12px);position:relative;-webkit-user-select:none;user-select:none;background-color:var(--grid-surface-container);color:var(--grid-on-surface)}.column-header:hover{background-color:var(--grid-surface-container-high)}.column-drag-handle{position:absolute;left:0;top:0;bottom:0;width:12px;cursor:grab;opacity:0;transition:opacity .2s ease,background-color .2s ease;z-index:2;display:flex;align-items:center;justify-content:center;border-right:1px solid transparent}.column-drag-handle:after{content:\"\\22ee\\22ee\";font-size:14px;color:var(--grid-on-surface-variant);transform:rotate(90deg)}.column-drag-handle:hover{background-color:var(--grid-surface-container-high);border-right-color:var(--grid-outline)}.column-header:hover .column-drag-handle{opacity:1}.column-drag-handle:active{cursor:grabbing}.dragging{opacity:1;background-color:var(--grid-surface-container);box-shadow:var(--grid-elevation-2)}.drag-over{background-color:var(--grid-surface-container);border-color:var(--grid-primary)}.data-cell{background-color:var(--grid-surface);color:var(--grid-on-surface);font-size:var(--grid-font-size-body)}.cell-content{align-items:center}.cell-content .mdc-text-field{padding:0px var(--grid-spacing-xxs)!important}.cell-display-text{align-items:center;padding:0px var(--grid-spacing-xs)}.ghost-loading-row{background-color:transparent}.ghost-cell-container{padding:var(--grid-spacing-sm)}.ghost-cell{height:20px;width:100%;background-color:var(--grid-surface-container);animation:pulse 1.5s ease-in-out infinite;border-radius:var(--grid-border-radius)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.column-resizer{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;background-color:transparent;transition:background-color .2s ease}.column-resizer:hover{background-color:var(--grid-primary)}.group-separator{height:var(--grid-spacing-sm);background-color:var(--grid-surface-variant)}.group-separator .separator-cell{background-color:var(--grid-surface-variant);border:none;height:var(--grid-spacing-sm)}.error-state{background-color:var(--grid-error-container);color:var(--grid-error);border-color:var(--grid-error)}.error-message{background-color:var(--grid-error);color:#fff;padding:var(--grid-spacing-sm);border-radius:var(--grid-border-radius);font-size:var(--grid-font-size-caption)}.incremental-row-container .eru-grid-table tbody,.incremental-row-container .eru-grid-table{position:relative}.incremental-row-container .eru-grid-table.show-column-lines{border-right:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-top:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table:not(.show-column-lines){border:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table thead:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:calc(var(--grid-outline-width, 1px) * 2);background-color:var(--grid-outline, #e0e0e0);pointer-events:none;z-index:10}.incremental-row-container .eru-grid-table.show-column-lines thead th{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-column-lines tbody td{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-row-lines thead th{border-left:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-row-lines tbody td{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}@media (max-width: 768px){.incremental-row-container{height:600px}.eru-grid-table th,.eru-grid-table td{font-size:var(--grid-font-size-caption)}.checkbox-column{width:40px;min-width:40px;max-width:40px}}@media (prefers-contrast: high){.eru-grid-table th,.eru-grid-table td{border-width:2px}.row-item:hover{border-width:2px;border-color:var(--grid-primary)}}@media (prefers-reduced-motion: reduce){.row-item,.column-drag-handle,.ghost-cell{transition:none;animation:none}}.pivot-table .nested-header{text-align:center;font-weight:600;background:var(--grid-surface-container)}.pivot-table .nested-header.row-dimension-header{background:var(--grid-surface-container);font-weight:600}.pivot-table .pivot-header-leafcols{padding:0;margin:0;height:0}.pivot-table .pivot-header-level.level-0 .nested-header{font-size:14px;padding:12px 8px}.pivot-table .pivot-header-level.level-1 .nested-header{font-size:13px;padding:10px 6px}.pivot-table .pivot-header-level.level-2 .nested-header{font-size:12px;padding:8px 4px}.pivot-table .nested-header:hover{background:var(--grid-surface-variant);color:var(--grid-primary);transition:all .2s ease}.pivot-table .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-table .pivot-cell-content{display:flex;justify-content:center;align-items:center;min-height:38px}.pivot-table .rowspan-cell{vertical-align:middle}.pivot-table .rowspan-cell .pivot-cell-content{height:100%}.pivot-mode .incremental-row-container{display:flex;flex-direction:column;height:auto;max-height:85vh;overflow:auto}.pivot-mode .h-shell{position:relative;width:calc(100% - var(--scrollbar-width, 17px))!important;top:0;z-index:1;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .h-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell{position:relative;bottom:50px;flex-shrink:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .gt-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell table{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.pivot-mode .gt-shell.adjust-bottom-vs{bottom:66px!important}.pivot-mode .gt-shell.adjust-bottom:not(.adjust-bottom-vs){bottom:calc(66px - var(--scrollbar-width, 17px))!important}.pivot-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .header-shell::-webkit-scrollbar{display:none}.pivot-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.pivot-mode .header-shell .eru-grid-table{margin-bottom:0;width:100%;table-layout:fixed}.pivot-mode .header-shell .eru-grid-table thead{background:var(--grid-surface-container)}.pivot-mode .header-shell .eru-grid-table thead th{background:var(--grid-surface-container);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .header-shell .eru-grid-table thead th.sticky-column{position:sticky;background:var(--grid-surface-container);z-index:111}.pivot-mode .header-shell .eru-grid-table tbody td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-container{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.pivot-mode .pivot-table{width:auto!important;min-width:100%!important;table-layout:fixed!important;width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important}.pivot-mode .pivot-table td,.pivot-mode .pivot-table th{box-sizing:border-box!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-table *{max-width:var(--col-width)!important;box-sizing:border-box!important}.pivot-mode .pivot-table colgroup{width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex-basis:var(--col-width)!important;flex:0 0 var(--col-width)!important}.pivot-mode .pivot-table table{width:100%!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important}.pivot-mode .pivot-table[style*=--table-total-width]{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:0 0 var(--col-width)!important;flex-basis:var(--col-width)!important;flex-grow:0!important;flex-shrink:0!important;overflow:hidden!important}.pivot-mode .pivot-table tbody td,.pivot-mode .pivot-table thead th{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.pivot-mode .pivot-table .cell-content,.pivot-mode .pivot-table data-cell{width:100%!important;max-width:100%!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;display:block!important}.pivot-mode .pivot-table table{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-tbody tr.pivot-row{min-height:50px!important;height:50px!important}.pivot-mode .pivot-tbody tr.pivot-row:hover{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-tbody tr.pivot-row:nth-child(2n){background-color:#00000005}.pivot-mode .pivot-tbody tr.pivot-row td{min-height:50px!important;height:50px!important;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content{min-height:48px;display:flex;align-items:center;justify-content:center}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content data-cell{width:100%;min-height:46px;display:flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0}.pivot-mode .pivot-cell{vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-mode .pivot-cell .cell-content{display:flex;justify-content:center;align-items:center;min-height:40px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:0}.pivot-mode .pivot-table .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.pivot-mode .pivot-table .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .subtotal-row td:first-child{color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row td.aggregated-value{font-weight:500;color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.pivot-mode .pivot-table .subtotal-bold td{font-weight:600!important;font-style:normal!important}.pivot-mode .pivot-table .subtotal-bold td.aggregated-value{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td{font-style:italic!important}.pivot-mode .pivot-table .subtotal-italic td:first-child{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.pivot-mode .pivot-table .subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted td.aggregated-value{font-weight:500!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted:hover,.pivot-mode .pivot-table .subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-row{background-color:var(--grid-surface-container-high)!important;font-weight:700;font-size:var(--grid-font-size-body)}.pivot-mode .pivot-table .grand-total-row td{background-color:var(--grid-surface-container-high)!important;color:var(--grid-on-surface)}.pivot-mode .pivot-table .grand-total-row td:first-child{font-style:normal;font-weight:800;color:var(--grid-primary)}.pivot-mode .pivot-table .grand-total-row td.aggregated-value{font-weight:500;color:var(--grid-primary);font-family:Roboto Mono,monospace}.pivot-mode .pivot-table .grand-total-row:hover,.pivot-mode .pivot-table .grand-total-row:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-bold td{font-weight:700!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-bold td.aggregated-value{font-weight:700!important}.pivot-mode .pivot-table .grand-total-italic td,.pivot-mode .pivot-table .grand-total-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted{background-color:var(--grid-primary)!important;box-shadow:var(--grid-elevation-2)!important}.pivot-mode .pivot-table .grand-total-highlighted td{background-color:var(--grid-primary)!important;color:var(--grid-on-primary)!important;font-weight:500!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-highlighted td.aggregated-value{color:var(--grid-on-primary)!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted:hover,.pivot-mode .pivot-table .grand-total-highlighted:hover td{background-color:var(--grid-primary)!important}.pivot-mode .pivot-table .collapsible-header{position:relative}.pivot-mode .pivot-table .collapsible-header .header-content{display:flex;align-items:center;justify-content:space-between;gap:var(--grid-spacing-xs);padding:var(--grid-spacing-xs) var(--grid-spacing-sm)}.pivot-mode .pivot-table .collapsible-header .header-label{flex:1;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn{background:none;border:none;cursor:pointer;padding:var(--grid-spacing-xxs);margin:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:var(--grid-border-radius);color:var(--grid-on-surface-variant);transition:all .2s ease;font-size:12px;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:hover{background-color:var(--grid-surface-container);color:var(--grid-primary);transform:scale(1.1)}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:focus{outline:2px solid var(--grid-primary);outline-offset:1px}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn .collapse-icon{display:block;line-height:1;font-family:monospace;font-size:14px}.pivot-mode .pivot-table .collapsible-header.expanded .collapse-toggle-btn .collapse-icon{color:var(--grid-primary)}.pivot-mode .pivot-table .collapsible-header.collapsed{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .header-label{font-style:italic;color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .collapse-toggle-btn .collapse-icon{color:var(--grid-outline)}.pivot-mode .pivot-table .collapsible-header:hover{background-color:var(--grid-surface-container)}.pivot-mode .pivot-table .collapsible-header:hover .header-label{color:var(--grid-on-surface)}.pivot-mode .pivot-table .pivot-single-table{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden;min-height:var(--table-min-height)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container{flex-shrink:0;background:var(--grid-surface)!important;overflow-x:auto;overflow-y:hidden;min-height:100px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table{width:auto;min-width:100%;height:auto!important;min-height:100px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th{background:var(--grid-surface-container)!important;padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:40px!important;height:auto!important;position:relative;visibility:visible!important;color:var(--grid-on-surface)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:101!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container{flex:1;overflow:auto;min-height:300px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-viewport{height:100%!important;width:100%!important;overflow-x:auto!important;overflow-y:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table{width:auto;min-width:100%;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td{padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:32px!important;height:auto!important;background:var(--grid-surface)!important;color:var(--grid-on-surface)!important;visibility:visible!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td.sticky-column,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:100!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr{height:auto!important;min-height:50px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr.pivot-row,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr.pivot-row{visibility:visible!important;display:table-row!important}.pivot-mode .pivot-table .collapsed-column-group{background-color:var(--grid-surface-container);border-left:3px solid var(--grid-primary)}.pivot-mode .pivot-table .collapsed-column-group:hover{background-color:var(--grid-surface-container-high)}.pivot-row.subtotal-row{background-color:var(--grid-surface-variant);font-weight:500}.pivot-row.subtotal-row.subtotal-bold{font-weight:500}.pivot-row.subtotal-row.subtotal-italic{font-style:italic}.pivot-row.subtotal-row.subtotal-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.grand-total-row{background-color:var(--grid-surface-container);font-weight:600}.pivot-row.grand-total-row.grand-total-bold{font-weight:800}.pivot-row.grand-total-row.grand-total-italic{font-style:italic}.pivot-row.grand-total-row.grand-total-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.first-visible-row{background-color:#6750a41a!important;position:relative}.pivot-row.first-visible-row:before{content:\"\\1f441\\fe0f First Visible\";position:absolute;top:-20px;left:0;background:var(--grid-primary);color:var(--grid-on-primary);padding:2px 6px;font-size:10px;border-radius:2px;z-index:1000}.header-wrap-text{white-space:pre-wrap;word-break:auto-phrase}\n"] }]
|
|
6439
5771
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { viewport: [{
|
|
6440
5772
|
type: ViewChild,
|
|
6441
5773
|
args: [CdkVirtualScrollViewport]
|