@memberjunction/ng-query-viewer 6.2.0-edge.0 → 6.2.0-edge.2
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/dist/lib/query-data-grid/models/query-grid-types.d.ts +10 -0
- package/dist/lib/query-data-grid/models/query-grid-types.d.ts.map +1 -1
- package/dist/lib/query-data-grid/models/query-grid-types.js +26 -6
- package/dist/lib/query-data-grid/models/query-grid-types.js.map +1 -1
- package/dist/lib/query-data-grid/query-data-grid.component.d.ts.map +1 -1
- package/dist/lib/query-data-grid/query-data-grid.component.js +19 -11
- package/dist/lib/query-data-grid/query-data-grid.component.js.map +1 -1
- package/dist/lib/query-pivot/query-pivot.component.d.ts +144 -0
- package/dist/lib/query-pivot/query-pivot.component.d.ts.map +1 -0
- package/dist/lib/query-pivot/query-pivot.component.js +434 -0
- package/dist/lib/query-pivot/query-pivot.component.js.map +1 -0
- package/dist/lib/query-pivot/query-pivot.compute.d.ts +36 -0
- package/dist/lib/query-pivot/query-pivot.compute.d.ts.map +1 -0
- package/dist/lib/query-pivot/query-pivot.compute.js +324 -0
- package/dist/lib/query-pivot/query-pivot.compute.js.map +1 -0
- package/dist/lib/query-pivot/query-pivot.types.d.ts +74 -0
- package/dist/lib/query-pivot/query-pivot.types.d.ts.map +1 -0
- package/dist/lib/query-pivot/query-pivot.types.js +2 -0
- package/dist/lib/query-pivot/query-pivot.types.js.map +1 -0
- package/dist/lib/query-row-detail/query-row-detail.component.d.ts +26 -0
- package/dist/lib/query-row-detail/query-row-detail.component.d.ts.map +1 -1
- package/dist/lib/query-row-detail/query-row-detail.component.js +79 -23
- package/dist/lib/query-row-detail/query-row-detail.component.js.map +1 -1
- package/dist/lib/query-viewer/query-viewer.component.js +5 -5
- package/dist/lib/query-viewer/query-viewer.component.js.map +1 -1
- package/dist/lib/query-viewer.module.d.ts +11 -10
- package/dist/lib/query-viewer.module.d.ts.map +1 -1
- package/dist/lib/query-viewer.module.js +9 -4
- package/dist/lib/query-viewer.module.js.map +1 -1
- package/dist/public-api.d.ts +3 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +4 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +14 -14
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a numeric measure value according to the specified format style.
|
|
3
|
+
* Null and undefined values always render as an em dash ('—').
|
|
4
|
+
*/
|
|
5
|
+
export function FormatMeasureValue(value, format, currencyCode = 'USD') {
|
|
6
|
+
if (value === null || value === undefined || isNaN(value)) {
|
|
7
|
+
return '—';
|
|
8
|
+
}
|
|
9
|
+
switch (format) {
|
|
10
|
+
case 'currency':
|
|
11
|
+
return formatCurrencyAmount(value, currencyCode);
|
|
12
|
+
case 'number':
|
|
13
|
+
return value.toLocaleString('en-US', {
|
|
14
|
+
minimumFractionDigits: Number.isInteger(value) ? 0 : 2,
|
|
15
|
+
maximumFractionDigits: 2
|
|
16
|
+
});
|
|
17
|
+
case 'percent':
|
|
18
|
+
return `${value.toLocaleString('en-US', {
|
|
19
|
+
minimumFractionDigits: 1,
|
|
20
|
+
maximumFractionDigits: 1
|
|
21
|
+
})}%`;
|
|
22
|
+
case 'duration':
|
|
23
|
+
return FormatDuration(value);
|
|
24
|
+
default:
|
|
25
|
+
return String(value);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Formats an amount in the given ISO 4217 currency. A code Intl does not recognise is shown beside
|
|
30
|
+
* the number rather than silently re-labelled as dollars.
|
|
31
|
+
*/
|
|
32
|
+
function formatCurrencyAmount(value, currencyCode) {
|
|
33
|
+
try {
|
|
34
|
+
const format = new Intl.NumberFormat('en-US', {
|
|
35
|
+
style: 'currency',
|
|
36
|
+
currency: currencyCode,
|
|
37
|
+
minimumFractionDigits: 2,
|
|
38
|
+
maximumFractionDigits: 2
|
|
39
|
+
});
|
|
40
|
+
// A real but sub-cent amount is not "$0.00": that reads as free, and free is what an
|
|
41
|
+
// unpriced value (rendered '—') is easily mistaken for. A negative one keeps its sign in
|
|
42
|
+
// front of the magnitude ("-<$0.01"), since "<-$0.01" would be false.
|
|
43
|
+
if (value !== 0 && Math.abs(value) < 0.005) {
|
|
44
|
+
return `${value < 0 ? '-' : ''}<${format.format(0.01)}`;
|
|
45
|
+
}
|
|
46
|
+
return format.format(value);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return `${value.toFixed(2)} ${currencyCode}`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Formats a duration in milliseconds into a concise readable unit (ms, s, m s).
|
|
54
|
+
*/
|
|
55
|
+
export function FormatDuration(ms) {
|
|
56
|
+
if (ms < 1000) {
|
|
57
|
+
return `${Math.round(ms)}ms`;
|
|
58
|
+
}
|
|
59
|
+
if (ms < 60000) {
|
|
60
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
61
|
+
}
|
|
62
|
+
const minutes = Math.floor(ms / 60000);
|
|
63
|
+
const seconds = Math.round((ms % 60000) / 1000);
|
|
64
|
+
return `${minutes}m ${seconds}s`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Formats a comparison delta percentage with sign prefix and em dash fallback.
|
|
68
|
+
*/
|
|
69
|
+
export function FormatDelta(deltaPercent) {
|
|
70
|
+
if (deltaPercent === null || deltaPercent === undefined || isNaN(deltaPercent)) {
|
|
71
|
+
return '—';
|
|
72
|
+
}
|
|
73
|
+
const prefix = deltaPercent > 0 ? '+' : '';
|
|
74
|
+
return `${prefix}${deltaPercent.toFixed(1)}%`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Parses a date/time string, reading an ISO date-time that carries no offset as UTC. `new Date()`
|
|
78
|
+
* reads such a string as LOCAL time, and the buckets below are UTC — so in UTC+10 a
|
|
79
|
+
* `2026-09-24T00:00:00` day bucket would land on the 23rd.
|
|
80
|
+
*/
|
|
81
|
+
function parseAsUtc(text) {
|
|
82
|
+
const trimmed = text.trim();
|
|
83
|
+
const offsetLessDateTime = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/;
|
|
84
|
+
return new Date(offsetLessDateTime.test(trimmed) ? `${trimmed.replace(' ', 'T')}Z` : trimmed);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Buckets a date/time value into the given time grain (hour or day).
|
|
88
|
+
*/
|
|
89
|
+
export function BucketTimestamp(value, grain) {
|
|
90
|
+
if (value === null || value === undefined || value === '') {
|
|
91
|
+
return '—';
|
|
92
|
+
}
|
|
93
|
+
const date = value instanceof Date ? value : parseAsUtc(String(value));
|
|
94
|
+
if (isNaN(date.getTime())) {
|
|
95
|
+
return String(value);
|
|
96
|
+
}
|
|
97
|
+
const year = date.getUTCFullYear();
|
|
98
|
+
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
|
99
|
+
const day = String(date.getUTCDate()).padStart(2, '0');
|
|
100
|
+
if (grain === 'day') {
|
|
101
|
+
return `${year}-${month}-${day}`;
|
|
102
|
+
}
|
|
103
|
+
const hour = String(date.getUTCHours()).padStart(2, '0');
|
|
104
|
+
return `${year}-${month}-${day} ${hour}:00`;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Computes an aggregate over an array of numeric values, ignoring nulls.
|
|
108
|
+
* If all values are null/undefined/NaN, returns null.
|
|
109
|
+
*
|
|
110
|
+
* NOTE: For 'count' aggregation, this returns the count of non-null values
|
|
111
|
+
* for the measure column in this group (matching SQL COUNT(column) semantics).
|
|
112
|
+
*/
|
|
113
|
+
export function AggregateValues(values, aggregation = 'sum') {
|
|
114
|
+
// Numeric strings are converted, not trusted: some drivers (PostgreSQL's NUMERIC) return
|
|
115
|
+
// decimals as strings, and summing those as-is would concatenate them ("5" + "3" = "53").
|
|
116
|
+
const valid = values
|
|
117
|
+
.map(v => (typeof v === 'string' && v.trim() !== '' ? Number(v) : v))
|
|
118
|
+
.filter((v) => typeof v === 'number' && !isNaN(v));
|
|
119
|
+
if (valid.length === 0) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
switch (aggregation) {
|
|
123
|
+
case 'sum':
|
|
124
|
+
return valid.reduce((acc, curr) => acc + curr, 0);
|
|
125
|
+
case 'avg':
|
|
126
|
+
return valid.reduce((acc, curr) => acc + curr, 0) / valid.length;
|
|
127
|
+
case 'min':
|
|
128
|
+
return Math.min(...valid);
|
|
129
|
+
case 'max':
|
|
130
|
+
return Math.max(...valid);
|
|
131
|
+
case 'count':
|
|
132
|
+
return valid.length;
|
|
133
|
+
default:
|
|
134
|
+
return valid.reduce((acc, curr) => acc + curr, 0);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Computes percentage delta between current and previous values.
|
|
139
|
+
*/
|
|
140
|
+
export function ComputeDeltaPercent(current, previous) {
|
|
141
|
+
if (current === null || previous === null || previous === 0) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return ((current - previous) / previous) * 100;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Helper to build a standard QueryGridColumnConfig.
|
|
148
|
+
*/
|
|
149
|
+
function createGridColumn(field, title, order, align = 'left', sqlBaseType = 'nvarchar') {
|
|
150
|
+
return {
|
|
151
|
+
field,
|
|
152
|
+
title,
|
|
153
|
+
order,
|
|
154
|
+
align,
|
|
155
|
+
sqlBaseType,
|
|
156
|
+
sqlFullType: sqlBaseType,
|
|
157
|
+
visible: true,
|
|
158
|
+
sortable: true,
|
|
159
|
+
resizable: true,
|
|
160
|
+
reorderable: true,
|
|
161
|
+
isEntityLink: false,
|
|
162
|
+
pinned: null
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Builds the group key string and dimension values object for a raw data row.
|
|
167
|
+
*/
|
|
168
|
+
function extractGroupKey(row, dimensions, timeColumn, grain) {
|
|
169
|
+
const dimensionValues = {};
|
|
170
|
+
const keyParts = [];
|
|
171
|
+
for (const dim of dimensions) {
|
|
172
|
+
const val = row[dim];
|
|
173
|
+
dimensionValues[dim] = val ?? '—';
|
|
174
|
+
keyParts.push(`${dim}:${String(val ?? '—')}`);
|
|
175
|
+
}
|
|
176
|
+
if (timeColumn && grain) {
|
|
177
|
+
const bucketed = BucketTimestamp(row[timeColumn], grain);
|
|
178
|
+
dimensionValues[timeColumn] = bucketed;
|
|
179
|
+
keyParts.push(`${timeColumn}:${bucketed}`);
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
groupKey: keyParts.join('|'),
|
|
183
|
+
dimensionValues
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The columns rows are grouped by: the configured dimensions plus any measure's CurrencyColumn, so a
|
|
188
|
+
* currency measure is never aggregated across currencies.
|
|
189
|
+
*/
|
|
190
|
+
function effectiveDimensions(config) {
|
|
191
|
+
const dims = [...config.DimensionColumns];
|
|
192
|
+
for (const measure of config.MeasureColumns) {
|
|
193
|
+
if (measure.Format === 'currency' && measure.CurrencyColumn && !dims.includes(measure.CurrencyColumn)) {
|
|
194
|
+
dims.push(measure.CurrencyColumn);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return dims;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Determines whether a given row is in the previous/comparison period.
|
|
201
|
+
*/
|
|
202
|
+
function isRowInPreviousPeriod(row, periodColumn) {
|
|
203
|
+
if (!periodColumn || !(periodColumn in row)) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
const val = row[periodColumn];
|
|
207
|
+
if (typeof val === 'boolean') {
|
|
208
|
+
return val;
|
|
209
|
+
}
|
|
210
|
+
const str = String(val ?? '').toLowerCase();
|
|
211
|
+
return str === 'previous' || str === 'prev' || str === 'prior' || str === 'comparison' || str === '1' || str === 'true';
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Groups raw query rows by dimension keys.
|
|
215
|
+
*/
|
|
216
|
+
function groupRows(rows, config) {
|
|
217
|
+
const groups = new Map();
|
|
218
|
+
for (const row of rows) {
|
|
219
|
+
const { groupKey, dimensionValues } = extractGroupKey(row, effectiveDimensions(config), config.TimeColumn, config.Grain);
|
|
220
|
+
let group = groups.get(groupKey);
|
|
221
|
+
if (!group) {
|
|
222
|
+
group = { dimensionValues, currentRows: [], prevRows: [] };
|
|
223
|
+
groups.set(groupKey, group);
|
|
224
|
+
}
|
|
225
|
+
if (config.ComparisonWindow && isRowInPreviousPeriod(row, config.ComparisonPeriodColumn)) {
|
|
226
|
+
group.prevRows.push(row);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
group.currentRows.push(row);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return groups;
|
|
233
|
+
}
|
|
234
|
+
/** The currency a group's amounts are in: its CurrencyColumn value, or USD when none is configured. */
|
|
235
|
+
function currencyForGroup(dimensionValues, measure) {
|
|
236
|
+
if (!measure.CurrencyColumn) {
|
|
237
|
+
return 'USD';
|
|
238
|
+
}
|
|
239
|
+
const code = dimensionValues[measure.CurrencyColumn];
|
|
240
|
+
return typeof code === 'string' && code.length === 3 ? code.toUpperCase() : 'USD';
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Computes measures for a single group with comparison window support.
|
|
244
|
+
*/
|
|
245
|
+
function computeGroupMeasures(group, measureCols, comparisonWindow) {
|
|
246
|
+
const result = {};
|
|
247
|
+
for (const measure of measureCols) {
|
|
248
|
+
const currency = currencyForGroup(group.dimensionValues, measure);
|
|
249
|
+
const currentVals = group.currentRows.map(r => r[measure.Key]);
|
|
250
|
+
const currentAgg = AggregateValues(currentVals, measure.Aggregation);
|
|
251
|
+
result[measure.Key] = FormatMeasureValue(currentAgg, measure.Format, currency);
|
|
252
|
+
result[`${measure.Key}_raw`] = currentAgg;
|
|
253
|
+
if (comparisonWindow) {
|
|
254
|
+
const prevVals = group.prevRows.map(r => r[measure.Key]);
|
|
255
|
+
const prevAgg = AggregateValues(prevVals, measure.Aggregation);
|
|
256
|
+
const deltaPercent = ComputeDeltaPercent(currentAgg, prevAgg);
|
|
257
|
+
const diff = currentAgg !== null && prevAgg !== null ? currentAgg - prevAgg : null;
|
|
258
|
+
result[`${measure.Key}_prev`] = FormatMeasureValue(prevAgg, measure.Format, currency);
|
|
259
|
+
result[`${measure.Key}_prev_raw`] = prevAgg;
|
|
260
|
+
result[`${measure.Key}_delta`] = FormatDelta(deltaPercent);
|
|
261
|
+
result[`${measure.Key}_delta_raw`] = diff;
|
|
262
|
+
result[`${measure.Key}_delta_percent`] = deltaPercent;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Builds the grid column configurations for dimensions and measures.
|
|
269
|
+
*/
|
|
270
|
+
function buildGridColumns(config) {
|
|
271
|
+
const columns = [];
|
|
272
|
+
let order = 0;
|
|
273
|
+
const labels = config.ColumnLabels ?? {};
|
|
274
|
+
const hidden = new Set(config.HiddenColumns ?? []);
|
|
275
|
+
for (const dim of effectiveDimensions(config)) {
|
|
276
|
+
const column = createGridColumn(dim, labels[dim] ?? dim, order++, 'left', 'nvarchar');
|
|
277
|
+
column.visible = !hidden.has(dim);
|
|
278
|
+
columns.push(column);
|
|
279
|
+
}
|
|
280
|
+
if (config.TimeColumn && config.Grain) {
|
|
281
|
+
const timeHeader = labels[config.TimeColumn]
|
|
282
|
+
?? (config.Grain === 'hour' ? `${config.TimeColumn} (Hour)` : `${config.TimeColumn} (Day)`);
|
|
283
|
+
columns.push(createGridColumn(config.TimeColumn, timeHeader, order++, 'left', 'nvarchar'));
|
|
284
|
+
}
|
|
285
|
+
for (const measure of config.MeasureColumns) {
|
|
286
|
+
const baseType = measure.Format === 'currency' ? 'money' : (measure.Format === 'number' ? 'decimal' : 'nvarchar');
|
|
287
|
+
columns.push(createGridColumn(measure.Key, measure.Label, order++, 'right', baseType));
|
|
288
|
+
if (config.ComparisonWindow) {
|
|
289
|
+
columns.push(createGridColumn(`${measure.Key}_prev`, `${measure.Label} (Prev)`, order++, 'right', baseType));
|
|
290
|
+
columns.push(createGridColumn(`${measure.Key}_delta`, `${measure.Label} Δ`, order++, 'right', 'nvarchar'));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return columns;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Pure pivot function: aggregates query rows by dimensions, applies measure aggregations,
|
|
297
|
+
* computes comparison deltas, formats null values as em dashes ('—'), and builds grid column defs.
|
|
298
|
+
*/
|
|
299
|
+
export function ComputePivot(rows, config) {
|
|
300
|
+
if (!rows || rows.length === 0) {
|
|
301
|
+
return {
|
|
302
|
+
Rows: [],
|
|
303
|
+
ColumnConfigs: buildGridColumns(config),
|
|
304
|
+
TotalInputRows: 0,
|
|
305
|
+
GroupedRowCount: 0
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
const groups = groupRows(rows, config);
|
|
309
|
+
const outputRows = [];
|
|
310
|
+
for (const group of groups.values()) {
|
|
311
|
+
const measureValues = computeGroupMeasures(group, config.MeasureColumns, !!config.ComparisonWindow);
|
|
312
|
+
outputRows.push({
|
|
313
|
+
...group.dimensionValues,
|
|
314
|
+
...measureValues
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
return {
|
|
318
|
+
Rows: outputRows,
|
|
319
|
+
ColumnConfigs: buildGridColumns(config),
|
|
320
|
+
TotalInputRows: rows.length,
|
|
321
|
+
GroupedRowCount: outputRows.length
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=query-pivot.compute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-pivot.compute.js","sourceRoot":"","sources":["../../../src/lib/query-pivot/query-pivot.compute.ts"],"names":[],"mappings":"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","sourcesContent":["import { QueryGridColumnConfig } from '../query-data-grid/models/query-grid-types';\nimport {\n PivotAggregationType,\n PivotMeasureColumn,\n PivotMeasureFormat,\n PivotResult,\n PivotTimeGrain,\n QueryPivotConfig\n} from './query-pivot.types';\n\n/**\n * Formats a numeric measure value according to the specified format style.\n * Null and undefined values always render as an em dash ('—').\n */\nexport function FormatMeasureValue(value: number | null | undefined, format: PivotMeasureFormat, currencyCode: string = 'USD'): string {\n if (value === null || value === undefined || isNaN(value)) {\n return '—';\n }\n\n switch (format) {\n case 'currency':\n return formatCurrencyAmount(value, currencyCode);\n\n case 'number':\n return value.toLocaleString('en-US', {\n minimumFractionDigits: Number.isInteger(value) ? 0 : 2,\n maximumFractionDigits: 2\n });\n\n case 'percent':\n return `${value.toLocaleString('en-US', {\n minimumFractionDigits: 1,\n maximumFractionDigits: 1\n })}%`;\n\n case 'duration':\n return FormatDuration(value);\n\n default:\n return String(value);\n }\n}\n\n/**\n * Formats an amount in the given ISO 4217 currency. A code Intl does not recognise is shown beside\n * the number rather than silently re-labelled as dollars.\n */\nfunction formatCurrencyAmount(value: number, currencyCode: string): string {\n try {\n const format = new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2\n });\n // A real but sub-cent amount is not \"$0.00\": that reads as free, and free is what an\n // unpriced value (rendered '—') is easily mistaken for. A negative one keeps its sign in\n // front of the magnitude (\"-<$0.01\"), since \"<-$0.01\" would be false.\n if (value !== 0 && Math.abs(value) < 0.005) {\n return `${value < 0 ? '-' : ''}<${format.format(0.01)}`;\n }\n return format.format(value);\n } catch {\n return `${value.toFixed(2)} ${currencyCode}`;\n }\n}\n\n/**\n * Formats a duration in milliseconds into a concise readable unit (ms, s, m s).\n */\nexport function FormatDuration(ms: number): string {\n if (ms < 1000) {\n return `${Math.round(ms)}ms`;\n }\n if (ms < 60000) {\n return `${(ms / 1000).toFixed(2)}s`;\n }\n const minutes = Math.floor(ms / 60000);\n const seconds = Math.round((ms % 60000) / 1000);\n return `${minutes}m ${seconds}s`;\n}\n\n/**\n * Formats a comparison delta percentage with sign prefix and em dash fallback.\n */\nexport function FormatDelta(deltaPercent: number | null | undefined): string {\n if (deltaPercent === null || deltaPercent === undefined || isNaN(deltaPercent)) {\n return '—';\n }\n const prefix = deltaPercent > 0 ? '+' : '';\n return `${prefix}${deltaPercent.toFixed(1)}%`;\n}\n\n/**\n * Parses a date/time string, reading an ISO date-time that carries no offset as UTC. `new Date()`\n * reads such a string as LOCAL time, and the buckets below are UTC — so in UTC+10 a\n * `2026-09-24T00:00:00` day bucket would land on the 23rd.\n */\nfunction parseAsUtc(text: string): Date {\n const trimmed = text.trim();\n const offsetLessDateTime = /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?$/;\n return new Date(offsetLessDateTime.test(trimmed) ? `${trimmed.replace(' ', 'T')}Z` : trimmed);\n}\n\n/**\n * Buckets a date/time value into the given time grain (hour or day).\n */\nexport function BucketTimestamp(value: unknown, grain: PivotTimeGrain): string {\n if (value === null || value === undefined || value === '') {\n return '—';\n }\n\n const date = value instanceof Date ? value : parseAsUtc(String(value));\n if (isNaN(date.getTime())) {\n return String(value);\n }\n\n const year = date.getUTCFullYear();\n const month = String(date.getUTCMonth() + 1).padStart(2, '0');\n const day = String(date.getUTCDate()).padStart(2, '0');\n\n if (grain === 'day') {\n return `${year}-${month}-${day}`;\n }\n\n const hour = String(date.getUTCHours()).padStart(2, '0');\n return `${year}-${month}-${day} ${hour}:00`;\n}\n\n/**\n * Computes an aggregate over an array of numeric values, ignoring nulls.\n * If all values are null/undefined/NaN, returns null.\n *\n * NOTE: For 'count' aggregation, this returns the count of non-null values\n * for the measure column in this group (matching SQL COUNT(column) semantics).\n */\nexport function AggregateValues(\n values: (number | null | undefined)[],\n aggregation: PivotAggregationType = 'sum'\n): number | null {\n // Numeric strings are converted, not trusted: some drivers (PostgreSQL's NUMERIC) return\n // decimals as strings, and summing those as-is would concatenate them (\"5\" + \"3\" = \"53\").\n const valid = (values as unknown[])\n .map(v => (typeof v === 'string' && v.trim() !== '' ? Number(v) : v))\n .filter((v): v is number => typeof v === 'number' && !isNaN(v));\n if (valid.length === 0) {\n return null;\n }\n\n switch (aggregation) {\n case 'sum':\n return valid.reduce((acc, curr) => acc + curr, 0);\n\n case 'avg':\n return valid.reduce((acc, curr) => acc + curr, 0) / valid.length;\n\n case 'min':\n return Math.min(...valid);\n\n case 'max':\n return Math.max(...valid);\n\n case 'count':\n return valid.length;\n\n default:\n return valid.reduce((acc, curr) => acc + curr, 0);\n }\n}\n\n/**\n * Computes percentage delta between current and previous values.\n */\nexport function ComputeDeltaPercent(current: number | null, previous: number | null): number | null {\n if (current === null || previous === null || previous === 0) {\n return null;\n }\n return ((current - previous) / previous) * 100;\n}\n\n/**\n * Helper to build a standard QueryGridColumnConfig.\n */\nfunction createGridColumn(\n field: string,\n title: string,\n order: number,\n align: 'left' | 'center' | 'right' = 'left',\n sqlBaseType: string = 'nvarchar'\n): QueryGridColumnConfig {\n return {\n field,\n title,\n order,\n align,\n sqlBaseType,\n sqlFullType: sqlBaseType,\n visible: true,\n sortable: true,\n resizable: true,\n reorderable: true,\n isEntityLink: false,\n pinned: null\n };\n}\n\n/**\n * Builds the group key string and dimension values object for a raw data row.\n */\nfunction extractGroupKey(\n row: Record<string, unknown>,\n dimensions: string[],\n timeColumn?: string | null,\n grain?: PivotTimeGrain | null\n): { groupKey: string; dimensionValues: Record<string, unknown> } {\n const dimensionValues: Record<string, unknown> = {};\n const keyParts: string[] = [];\n\n for (const dim of dimensions) {\n const val = row[dim];\n dimensionValues[dim] = val ?? '—';\n keyParts.push(`${dim}:${String(val ?? '—')}`);\n }\n\n if (timeColumn && grain) {\n const bucketed = BucketTimestamp(row[timeColumn], grain);\n dimensionValues[timeColumn] = bucketed;\n keyParts.push(`${timeColumn}:${bucketed}`);\n }\n\n return {\n groupKey: keyParts.join('|'),\n dimensionValues\n };\n}\n\n/**\n * The columns rows are grouped by: the configured dimensions plus any measure's CurrencyColumn, so a\n * currency measure is never aggregated across currencies.\n */\nfunction effectiveDimensions(config: QueryPivotConfig): string[] {\n const dims = [...config.DimensionColumns];\n for (const measure of config.MeasureColumns) {\n if (measure.Format === 'currency' && measure.CurrencyColumn && !dims.includes(measure.CurrencyColumn)) {\n dims.push(measure.CurrencyColumn);\n }\n }\n return dims;\n}\n\n/**\n * Determines whether a given row is in the previous/comparison period.\n */\nfunction isRowInPreviousPeriod(\n row: Record<string, unknown>,\n periodColumn?: string | null\n): boolean {\n if (!periodColumn || !(periodColumn in row)) {\n return false;\n }\n const val = row[periodColumn];\n if (typeof val === 'boolean') {\n return val;\n }\n const str = String(val ?? '').toLowerCase();\n return str === 'previous' || str === 'prev' || str === 'prior' || str === 'comparison' || str === '1' || str === 'true';\n}\n\n/**\n * Groups raw query rows by dimension keys.\n */\nfunction groupRows(\n rows: Record<string, unknown>[],\n config: QueryPivotConfig\n): Map<string, { dimensionValues: Record<string, unknown>; currentRows: Record<string, unknown>[]; prevRows: Record<string, unknown>[] }> {\n const groups = new Map<\n string,\n { dimensionValues: Record<string, unknown>; currentRows: Record<string, unknown>[]; prevRows: Record<string, unknown>[] }\n >();\n\n for (const row of rows) {\n const { groupKey, dimensionValues } = extractGroupKey(\n row,\n effectiveDimensions(config),\n config.TimeColumn,\n config.Grain\n );\n\n let group = groups.get(groupKey);\n if (!group) {\n group = { dimensionValues, currentRows: [], prevRows: [] };\n groups.set(groupKey, group);\n }\n\n if (config.ComparisonWindow && isRowInPreviousPeriod(row, config.ComparisonPeriodColumn)) {\n group.prevRows.push(row);\n } else {\n group.currentRows.push(row);\n }\n }\n\n return groups;\n}\n\n/** The currency a group's amounts are in: its CurrencyColumn value, or USD when none is configured. */\nfunction currencyForGroup(dimensionValues: Record<string, unknown>, measure: PivotMeasureColumn): string {\n if (!measure.CurrencyColumn) {\n return 'USD';\n }\n const code = dimensionValues[measure.CurrencyColumn];\n return typeof code === 'string' && code.length === 3 ? code.toUpperCase() : 'USD';\n}\n\n/**\n * Computes measures for a single group with comparison window support.\n */\nfunction computeGroupMeasures(\n group: { dimensionValues: Record<string, unknown>; currentRows: Record<string, unknown>[]; prevRows: Record<string, unknown>[] },\n measureCols: PivotMeasureColumn[],\n comparisonWindow: boolean\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const measure of measureCols) {\n const currency = currencyForGroup(group.dimensionValues, measure);\n const currentVals = group.currentRows.map(r => r[measure.Key] as number | null | undefined);\n const currentAgg = AggregateValues(currentVals, measure.Aggregation);\n\n result[measure.Key] = FormatMeasureValue(currentAgg, measure.Format, currency);\n result[`${measure.Key}_raw`] = currentAgg;\n\n if (comparisonWindow) {\n const prevVals = group.prevRows.map(r => r[measure.Key] as number | null | undefined);\n const prevAgg = AggregateValues(prevVals, measure.Aggregation);\n const deltaPercent = ComputeDeltaPercent(currentAgg, prevAgg);\n const diff = currentAgg !== null && prevAgg !== null ? currentAgg - prevAgg : null;\n\n result[`${measure.Key}_prev`] = FormatMeasureValue(prevAgg, measure.Format, currency);\n result[`${measure.Key}_prev_raw`] = prevAgg;\n result[`${measure.Key}_delta`] = FormatDelta(deltaPercent);\n result[`${measure.Key}_delta_raw`] = diff;\n result[`${measure.Key}_delta_percent`] = deltaPercent;\n }\n }\n\n return result;\n}\n\n/**\n * Builds the grid column configurations for dimensions and measures.\n */\nfunction buildGridColumns(\n config: QueryPivotConfig\n): QueryGridColumnConfig[] {\n const columns: QueryGridColumnConfig[] = [];\n let order = 0;\n\n const labels = config.ColumnLabels ?? {};\n const hidden = new Set(config.HiddenColumns ?? []);\n for (const dim of effectiveDimensions(config)) {\n const column = createGridColumn(dim, labels[dim] ?? dim, order++, 'left', 'nvarchar');\n column.visible = !hidden.has(dim);\n columns.push(column);\n }\n\n if (config.TimeColumn && config.Grain) {\n const timeHeader = labels[config.TimeColumn]\n ?? (config.Grain === 'hour' ? `${config.TimeColumn} (Hour)` : `${config.TimeColumn} (Day)`);\n columns.push(createGridColumn(config.TimeColumn, timeHeader, order++, 'left', 'nvarchar'));\n }\n\n for (const measure of config.MeasureColumns) {\n const baseType = measure.Format === 'currency' ? 'money' : (measure.Format === 'number' ? 'decimal' : 'nvarchar');\n columns.push(createGridColumn(measure.Key, measure.Label, order++, 'right', baseType));\n\n if (config.ComparisonWindow) {\n columns.push(createGridColumn(`${measure.Key}_prev`, `${measure.Label} (Prev)`, order++, 'right', baseType));\n columns.push(createGridColumn(`${measure.Key}_delta`, `${measure.Label} Δ`, order++, 'right', 'nvarchar'));\n }\n }\n\n return columns;\n}\n\n/**\n * Pure pivot function: aggregates query rows by dimensions, applies measure aggregations,\n * computes comparison deltas, formats null values as em dashes ('—'), and builds grid column defs.\n */\nexport function ComputePivot(\n rows: Record<string, unknown>[],\n config: QueryPivotConfig\n): PivotResult {\n if (!rows || rows.length === 0) {\n return {\n Rows: [],\n ColumnConfigs: buildGridColumns(config),\n TotalInputRows: 0,\n GroupedRowCount: 0\n };\n }\n\n const groups = groupRows(rows, config);\n const outputRows: Record<string, unknown>[] = [];\n\n for (const group of groups.values()) {\n const measureValues = computeGroupMeasures(group, config.MeasureColumns, !!config.ComparisonWindow);\n outputRows.push({\n ...group.dimensionValues,\n ...measureValues\n });\n }\n\n return {\n Rows: outputRows,\n ColumnConfigs: buildGridColumns(config),\n TotalInputRows: rows.length,\n GroupedRowCount: outputRows.length\n };\n}\n"]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { QueryGridColumnConfig } from '../query-data-grid/models/query-grid-types';
|
|
2
|
+
/**
|
|
3
|
+
* Supported display formatting styles for pivot measures.
|
|
4
|
+
*/
|
|
5
|
+
export type PivotMeasureFormat = 'currency' | 'number' | 'percent' | 'duration';
|
|
6
|
+
/**
|
|
7
|
+
* Supported aggregation functions for pivot measures.
|
|
8
|
+
*/
|
|
9
|
+
export type PivotAggregationType = 'sum' | 'avg' | 'min' | 'max' | 'count';
|
|
10
|
+
/**
|
|
11
|
+
* Time grain options for date/time bucketing.
|
|
12
|
+
*/
|
|
13
|
+
export type PivotTimeGrain = 'hour' | 'day';
|
|
14
|
+
/**
|
|
15
|
+
* Configuration for a single measure column in a pivot operation.
|
|
16
|
+
*/
|
|
17
|
+
export interface PivotMeasureColumn {
|
|
18
|
+
/** The field name/key from the raw query dataset */
|
|
19
|
+
Key: string;
|
|
20
|
+
/** The column header label to display */
|
|
21
|
+
Label: string;
|
|
22
|
+
/** Format style for rendering the aggregated value */
|
|
23
|
+
Format: PivotMeasureFormat;
|
|
24
|
+
/** Aggregation function to apply (defaults to 'sum') */
|
|
25
|
+
Aggregation?: PivotAggregationType;
|
|
26
|
+
/**
|
|
27
|
+
* For a `'currency'` measure: the row column holding each amount's ISO 4217 currency code.
|
|
28
|
+
* The pivot also groups by this column, so amounts in different currencies are never summed
|
|
29
|
+
* into one figure, and each group is formatted in its own currency. Omit for single-currency
|
|
30
|
+
* data, which is then formatted as USD.
|
|
31
|
+
*/
|
|
32
|
+
CurrencyColumn?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Full configuration for computing a pivot table over query rows.
|
|
36
|
+
*/
|
|
37
|
+
export interface QueryPivotConfig {
|
|
38
|
+
/** Columns to group rows by */
|
|
39
|
+
DimensionColumns: string[];
|
|
40
|
+
/** Measures to aggregate per group */
|
|
41
|
+
MeasureColumns: PivotMeasureColumn[];
|
|
42
|
+
/** Optional date/time column to bucket */
|
|
43
|
+
TimeColumn?: string | null;
|
|
44
|
+
/** Time grain for the timeColumn (e.g., 'hour' or 'day') */
|
|
45
|
+
Grain?: PivotTimeGrain | null;
|
|
46
|
+
/** Whether to calculate comparison window deltas */
|
|
47
|
+
ComparisonWindow?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Optional column name indicating whether a row belongs to the current or comparison period.
|
|
50
|
+
* When not supplied but ComparisonWindow is true, rows are split across available time intervals.
|
|
51
|
+
*/
|
|
52
|
+
ComparisonPeriodColumn?: string | null;
|
|
53
|
+
/** Header titles for dimension/time columns, keyed by column; unlisted columns show their key. */
|
|
54
|
+
ColumnLabels?: Record<string, string>;
|
|
55
|
+
/**
|
|
56
|
+
* Dimension columns that take part in grouping but are not displayed — e.g. group by an ID and
|
|
57
|
+
* its display name, show only the name, and still have the ID on each output row.
|
|
58
|
+
*/
|
|
59
|
+
HiddenColumns?: string[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Computed result of a query pivot operation.
|
|
63
|
+
*/
|
|
64
|
+
export interface PivotResult {
|
|
65
|
+
/** The aggregated rows ready for tabular grid display */
|
|
66
|
+
Rows: Record<string, unknown>[];
|
|
67
|
+
/** Column definitions configured with appropriate alignment and headers */
|
|
68
|
+
ColumnConfigs: QueryGridColumnConfig[];
|
|
69
|
+
/** Total number of raw input rows processed */
|
|
70
|
+
TotalInputRows: number;
|
|
71
|
+
/** Total number of grouped output rows generated */
|
|
72
|
+
GroupedRowCount: number;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=query-pivot.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-pivot.types.d.ts","sourceRoot":"","sources":["../../../src/lib/query-pivot/query-pivot.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAEnF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;AAEhF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;AAE3E;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,MAAM,EAAE,kBAAkB,CAAC;IAC3B,wDAAwD;IACxD,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,+BAA+B;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,sCAAsC;IACtC,cAAc,EAAE,kBAAkB,EAAE,CAAC;IACrC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,4DAA4D;IAC5D,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,kGAAkG;IAClG,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAChC,2EAA2E;IAC3E,aAAa,EAAE,qBAAqB,EAAE,CAAC;IACvC,+CAA+C;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,eAAe,EAAE,MAAM,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-pivot.types.js","sourceRoot":"","sources":["../../../src/lib/query-pivot/query-pivot.types.ts"],"names":[],"mappings":"","sourcesContent":["import { QueryGridColumnConfig } from '../query-data-grid/models/query-grid-types';\n\n/**\n * Supported display formatting styles for pivot measures.\n */\nexport type PivotMeasureFormat = 'currency' | 'number' | 'percent' | 'duration';\n\n/**\n * Supported aggregation functions for pivot measures.\n */\nexport type PivotAggregationType = 'sum' | 'avg' | 'min' | 'max' | 'count';\n\n/**\n * Time grain options for date/time bucketing.\n */\nexport type PivotTimeGrain = 'hour' | 'day';\n\n/**\n * Configuration for a single measure column in a pivot operation.\n */\nexport interface PivotMeasureColumn {\n /** The field name/key from the raw query dataset */\n Key: string;\n /** The column header label to display */\n Label: string;\n /** Format style for rendering the aggregated value */\n Format: PivotMeasureFormat;\n /** Aggregation function to apply (defaults to 'sum') */\n Aggregation?: PivotAggregationType;\n /**\n * For a `'currency'` measure: the row column holding each amount's ISO 4217 currency code.\n * The pivot also groups by this column, so amounts in different currencies are never summed\n * into one figure, and each group is formatted in its own currency. Omit for single-currency\n * data, which is then formatted as USD.\n */\n CurrencyColumn?: string;\n}\n\n/**\n * Full configuration for computing a pivot table over query rows.\n */\nexport interface QueryPivotConfig {\n /** Columns to group rows by */\n DimensionColumns: string[];\n /** Measures to aggregate per group */\n MeasureColumns: PivotMeasureColumn[];\n /** Optional date/time column to bucket */\n TimeColumn?: string | null;\n /** Time grain for the timeColumn (e.g., 'hour' or 'day') */\n Grain?: PivotTimeGrain | null;\n /** Whether to calculate comparison window deltas */\n ComparisonWindow?: boolean;\n /**\n * Optional column name indicating whether a row belongs to the current or comparison period.\n * When not supplied but ComparisonWindow is true, rows are split across available time intervals.\n */\n ComparisonPeriodColumn?: string | null;\n /** Header titles for dimension/time columns, keyed by column; unlisted columns show their key. */\n ColumnLabels?: Record<string, string>;\n /**\n * Dimension columns that take part in grouping but are not displayed — e.g. group by an ID and\n * its display name, show only the name, and still have the ID on each output row.\n */\n HiddenColumns?: string[];\n}\n\n/**\n * Computed result of a query pivot operation.\n */\nexport interface PivotResult {\n /** The aggregated rows ready for tabular grid display */\n Rows: Record<string, unknown>[];\n /** Column definitions configured with appropriate alignment and headers */\n ColumnConfigs: QueryGridColumnConfig[];\n /** Total number of raw input rows processed */\n TotalInputRows: number;\n /** Total number of grouped output rows generated */\n GroupedRowCount: number;\n}\n"]}
|
|
@@ -63,15 +63,35 @@ export declare class QueryRowDetailComponent implements OnInit, OnDestroy {
|
|
|
63
63
|
private buildDetailFields;
|
|
64
64
|
private buildDetailField;
|
|
65
65
|
private formatValue;
|
|
66
|
+
OnClose(): void;
|
|
67
|
+
/** @deprecated Use {@link OnClose}. */
|
|
66
68
|
onClose(): void;
|
|
69
|
+
OnEntityLinkClick(field: DetailField): void;
|
|
70
|
+
/** @deprecated Use {@link OnEntityLinkClick}. */
|
|
67
71
|
onEntityLinkClick(field: DetailField): void;
|
|
72
|
+
OnNavigatePrev(): void;
|
|
73
|
+
/** @deprecated Use {@link OnNavigatePrev}. */
|
|
68
74
|
onNavigatePrev(): void;
|
|
75
|
+
OnNavigateNext(): void;
|
|
76
|
+
/** @deprecated Use {@link OnNavigateNext}. */
|
|
69
77
|
onNavigateNext(): void;
|
|
78
|
+
ToggleFieldExpand(field: DetailField): void;
|
|
79
|
+
/** @deprecated Use {@link ToggleFieldExpand}. */
|
|
70
80
|
toggleFieldExpand(field: DetailField): void;
|
|
81
|
+
CopyValue(field: DetailField): void;
|
|
82
|
+
/** @deprecated Use {@link CopyValue}. */
|
|
71
83
|
copyValue(field: DetailField): void;
|
|
84
|
+
CopyRowAsJson(): void;
|
|
85
|
+
/** @deprecated Use {@link CopyRowAsJson}. */
|
|
72
86
|
copyRowAsJson(): void;
|
|
87
|
+
IsJson(value: string): boolean;
|
|
88
|
+
/** @deprecated Use {@link IsJson}. */
|
|
73
89
|
isJson(value: string): boolean;
|
|
90
|
+
FormatJson(value: string): string;
|
|
91
|
+
/** @deprecated Use {@link FormatJson}. */
|
|
74
92
|
formatJson(value: string): string;
|
|
93
|
+
OnResizeStart(event: MouseEvent): void;
|
|
94
|
+
/** @deprecated Use {@link OnResizeStart}. */
|
|
75
95
|
onResizeStart(event: MouseEvent): void;
|
|
76
96
|
onMouseMove(event: MouseEvent): void;
|
|
77
97
|
onMouseUp(): void;
|
|
@@ -79,14 +99,20 @@ export declare class QueryRowDetailComponent implements OnInit, OnDestroy {
|
|
|
79
99
|
private persistPanelWidth;
|
|
80
100
|
private loadHideEmptyFieldsPreference;
|
|
81
101
|
private persistHideEmptyFieldsPreference;
|
|
102
|
+
ToggleHideEmptyFields(): void;
|
|
103
|
+
/** @deprecated Use {@link ToggleHideEmptyFields}. */
|
|
82
104
|
toggleHideEmptyFields(): void;
|
|
83
105
|
/**
|
|
84
106
|
* Returns visible fields based on HideEmptyFields setting
|
|
85
107
|
*/
|
|
108
|
+
GetVisibleFields(fields: DetailField[]): DetailField[];
|
|
109
|
+
/** @deprecated Use {@link GetVisibleFields}. */
|
|
86
110
|
getVisibleFields(fields: DetailField[]): DetailField[];
|
|
87
111
|
/**
|
|
88
112
|
* Returns count of empty fields for display
|
|
89
113
|
*/
|
|
114
|
+
GetEmptyFieldCount(fields: DetailField[]): number;
|
|
115
|
+
/** @deprecated Use {@link GetEmptyFieldCount}. */
|
|
90
116
|
getEmptyFieldCount(fields: DetailField[]): number;
|
|
91
117
|
onKeyDown(event: KeyboardEvent): void;
|
|
92
118
|
static ɵfac: i0.ɵɵFactoryDeclaration<QueryRowDetailComponent, never>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-row-detail.component.d.ts","sourceRoot":"","sources":["../../../src/lib/query-row-detail/query-row-detail.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,YAAY,EACZ,MAAM,EACN,SAAS,EACT,iBAAiB,EAEjB,UAAU,EAEb,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"query-row-detail.component.d.ts","sourceRoot":"","sources":["../../../src/lib/query-row-detail/query-row-detail.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,YAAY,EACZ,MAAM,EACN,SAAS,EACT,iBAAiB,EAEjB,UAAU,EAEb,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;;AAEnF;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,UAAU,WAAW;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;CACvB;AAYD;;;GAGG;AACH,qBAkBa,uBAAwB,YAAW,MAAM,EAAE,SAAS;IA2DzD,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,UAAU;IAvDtB,OAAO,CAAC,QAAQ,CAAwC;IACxD,IACI,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EAKhD;IACD,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE5C;IAED,OAAO,CAAC,QAAQ,CAA+B;IAC/C,IACI,OAAO,CAAC,KAAK,EAAE,qBAAqB,EAAE,EAKzC;IACD,IAAI,OAAO,IAAI,qBAAqB,EAAE,CAErC;IAEQ,SAAS,EAAE,qBAAqB,GAAG,IAAI,CAAQ;IAC/C,OAAO,EAAE,OAAO,CAAS;IACzB,QAAQ,EAAE,MAAM,CAAK;IACrB,SAAS,EAAE,MAAM,CAAK;IAMrB,KAAK,qBAA4B;IACjC,eAAe,yCAAgD;IAC/D,WAAW,gCAAuC;IAMrD,gBAAgB,EAAE,WAAW,EAAE,CAAM;IACrC,gBAAgB,EAAE,WAAW,EAAE,CAAM;IACrC,aAAa,EAAE,WAAW,EAAE,CAAM;IAClC,UAAU,EAAE,MAAM,CAAO;IACzB,UAAU,EAAE,OAAO,CAAS;IAC5B,eAAe,EAAE,OAAO,CAAQ;IAEvC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,mBAAmB,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAO;IACvB,OAAO,CAAC,QAAQ,CAAO;gBAGX,GAAG,EAAE,iBAAiB,EACtB,UAAU,EAAE,UAAU;IAWlC,QAAQ,IAAI,IAAI;IAKhB,WAAW,IAAI,IAAI;IASnB,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,WAAW;IAkFZ,OAAO,IAAI,IAAI;IAItB,uCAAuC;IAChC,OAAO,IAAI,IAAI;IAIf,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAUlD,iDAAiD;IAC1C,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAI3C,cAAc,IAAI,IAAI;IAI7B,8CAA8C;IACvC,cAAc,IAAI,IAAI;IAItB,cAAc,IAAI,IAAI;IAI7B,8CAA8C;IACvC,cAAc,IAAI,IAAI;IAItB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAKlD,iDAAiD;IAC1C,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAI3C,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAK1C,yCAAyC;IAClC,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAInC,aAAa,IAAI,IAAI;IAO5B,6CAA6C;IACtC,aAAa,IAAI,IAAI;IAIrB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAOrC,sCAAsC;IAC/B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAI9B,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAQxC,0CAA0C;IACnC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAQjC,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAO7C,6CAA6C;IACtC,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAK7C,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAYpC,SAAS,IAAI,IAAI;IAajB,OAAO,CAAC,kBAAkB;YAcZ,iBAAiB;IAQ/B,OAAO,CAAC,6BAA6B;YAWvB,gCAAgC;IAQvC,qBAAqB,IAAI,IAAI;IAMpC,qDAAqD;IAC9C,qBAAqB,IAAI,IAAI;IAIpC;;OAEG;IACI,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE;IAO7D,gDAAgD;IACzC,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE;IAI7D;;OAEG;IACI,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM;IAIxD,kDAAkD;IAC3C,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM;IASxD,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;yCA3b5B,uBAAuB;2CAAvB,uBAAuB;CA0cnC"}
|