eru-grid 0.0.54 → 0.0.55
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 +117 -26
- package/fesm2022/eru-grid.mjs.map +1 -1
- package/package.json +1 -1
- package/types/eru-grid.d.ts +34 -2
package/fesm2022/eru-grid.mjs
CHANGED
|
@@ -194,9 +194,23 @@ const SELF_COLOURED_DATATYPES = new Set(['status', 'priority', 'tag', 'progress'
|
|
|
194
194
|
*/
|
|
195
195
|
const ACTION_COLUMN_MIN_WIDTH = 56;
|
|
196
196
|
const SEEDED_FIELD_KEYS = [
|
|
197
|
-
'dynamic_number', 'display_number_as', 'symbol_field', 'date_format',
|
|
197
|
+
'dynamic_number', 'display_number_as', 'symbol_field', 'date_format',
|
|
198
198
|
'storage_name', 'folder_name', 'default_upload',
|
|
199
199
|
];
|
|
200
|
+
/**
|
|
201
|
+
* Keys the model seeds only until the design panel overrides them EXPLICITLY,
|
|
202
|
+
* tracked by a companion flag rather than by "does the column hold a value".
|
|
203
|
+
*
|
|
204
|
+
* `label` is the case that forced this: it is in SEEDED_FIELD_KEYS' spirit —
|
|
205
|
+
* the model's label is the default and a grid may shorten it — but a column
|
|
206
|
+
* never arrives without one, so the seeded test ("column already has a value,
|
|
207
|
+
* leave it alone") was true from the first render and the model's label never
|
|
208
|
+
* reached a mapped column. A query-derived column kept showing its raw result
|
|
209
|
+
* key as the heading.
|
|
210
|
+
*/
|
|
211
|
+
const EXPLICITLY_OVERRIDDEN_FIELD_KEYS = {
|
|
212
|
+
label: 'label_overridden',
|
|
213
|
+
};
|
|
200
214
|
/**
|
|
201
215
|
* Datatype aliases the data model emits that mean an existing DataTypes value.
|
|
202
216
|
*
|
|
@@ -4077,33 +4091,34 @@ class EruGridStore {
|
|
|
4077
4091
|
}
|
|
4078
4092
|
return this.rows();
|
|
4079
4093
|
}, ...(ngDevMode ? [{ debugName: "displayData" }] : []));
|
|
4094
|
+
// The frozen grand total is the row the transform appended (or prepended) to
|
|
4095
|
+
// the pivot data, so it is only there when the transform actually produced
|
|
4096
|
+
// one. It skips totalling an empty result, so `data` can be [] with the
|
|
4097
|
+
// grand-total config still on; indexing it then yields undefined and the
|
|
4098
|
+
// frozen-row template renders a row that has no `_rowKey`. Read the row
|
|
4099
|
+
// positionally but keep it only when it really is the grand total.
|
|
4100
|
+
frozenGrandTotalRow = computed(() => {
|
|
4101
|
+
if (!this.isPivotMode() || !this.pivotResult())
|
|
4102
|
+
return null;
|
|
4103
|
+
const config = this.configuration().config;
|
|
4104
|
+
if (!config?.enableGrandTotal || !config?.freezeGrandTotal)
|
|
4105
|
+
return null;
|
|
4106
|
+
const data = this.pivotResult().data;
|
|
4107
|
+
const row = config?.grandTotalPosition === 'before' ? data[0] : data[data.length - 1];
|
|
4108
|
+
return row?._isGrandTotal ? row : null;
|
|
4109
|
+
}, ...(ngDevMode ? [{ debugName: "frozenGrandTotalRow" }] : []));
|
|
4080
4110
|
// Type-safe accessors for specific modes
|
|
4081
4111
|
pivotGrandTotalData = computed(() => {
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
if (this.configuration().config?.enableGrandTotal) {
|
|
4085
|
-
if (this.configuration().config?.freezeGrandTotal) {
|
|
4086
|
-
if (this.configuration().config?.grandTotalPosition === 'before') {
|
|
4087
|
-
pd = [this.pivotResult().data[0]];
|
|
4088
|
-
}
|
|
4089
|
-
else {
|
|
4090
|
-
pd = [this.pivotResult().data[this.pivotResult().data.length - 1]];
|
|
4091
|
-
}
|
|
4092
|
-
}
|
|
4093
|
-
}
|
|
4094
|
-
}
|
|
4095
|
-
return pd;
|
|
4112
|
+
const row = this.frozenGrandTotalRow();
|
|
4113
|
+
return row ? [row] : [];
|
|
4096
4114
|
}, ...(ngDevMode ? [{ debugName: "pivotGrandTotalData" }] : []));
|
|
4097
4115
|
// Type-safe accessors for specific modes
|
|
4098
4116
|
pivotDisplayData = computed(() => {
|
|
4099
4117
|
if (this.isPivotMode() && this.pivotResult()) {
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
else {
|
|
4105
|
-
return this.pivotResult().data;
|
|
4106
|
-
}
|
|
4118
|
+
// Only drop the leading row when it is the frozen grand total that the
|
|
4119
|
+
// header renders separately, never a real data row.
|
|
4120
|
+
if (this.frozenGrandTotalRow() && this.configuration().config?.grandTotalPosition === 'before') {
|
|
4121
|
+
return this.pivotResult().data.slice(1);
|
|
4107
4122
|
}
|
|
4108
4123
|
return this.pivotResult().data;
|
|
4109
4124
|
}
|
|
@@ -4502,6 +4517,56 @@ class EruGridStore {
|
|
|
4502
4517
|
const rows = this.rows().map(row => row.entity_id === rowId ? { ...row, ...updates } : row);
|
|
4503
4518
|
this._rows.set(rows);
|
|
4504
4519
|
}
|
|
4520
|
+
/**
|
|
4521
|
+
* Merge field values into the record with this id, wherever the grid is
|
|
4522
|
+
* holding it — the flat row list AND the per-group buckets a board fills.
|
|
4523
|
+
*
|
|
4524
|
+
* For a consumer that edits a record somewhere else on the page and needs the
|
|
4525
|
+
* grid to agree without refetching. `updateRow` is not enough on two counts:
|
|
4526
|
+
* it only looks at `_rows`, so a grouped/board grid keeps the stale copy, and
|
|
4527
|
+
* it replaces top-level row keys rather than merging into `entity_data`,
|
|
4528
|
+
* where an entity-backed row keeps its fields.
|
|
4529
|
+
*
|
|
4530
|
+
* Unknown ids are ignored, so a caller can announce a change blindly.
|
|
4531
|
+
*/
|
|
4532
|
+
patchRecord(entityId, fields) {
|
|
4533
|
+
if (!entityId || !fields)
|
|
4534
|
+
return;
|
|
4535
|
+
const entries = Object.entries(fields);
|
|
4536
|
+
if (entries.length === 0)
|
|
4537
|
+
return;
|
|
4538
|
+
const patch = (row) => {
|
|
4539
|
+
if (!row || row.entity_id !== entityId)
|
|
4540
|
+
return row;
|
|
4541
|
+
const next = { ...row };
|
|
4542
|
+
if (next.entity_data && typeof next.entity_data === 'object') {
|
|
4543
|
+
next.entity_data = { ...next.entity_data, ...fields };
|
|
4544
|
+
}
|
|
4545
|
+
// An array-sourced row carries its fields at the top level instead. Only
|
|
4546
|
+
// keys the row already has are touched, so this never invents columns.
|
|
4547
|
+
for (const [key, value] of entries) {
|
|
4548
|
+
if (key !== 'entity_data' && Object.prototype.hasOwnProperty.call(next, key)) {
|
|
4549
|
+
next[key] = value;
|
|
4550
|
+
}
|
|
4551
|
+
}
|
|
4552
|
+
return next;
|
|
4553
|
+
};
|
|
4554
|
+
const holdsRecord = (rows) => rows.some(row => row?.entity_id === entityId);
|
|
4555
|
+
if (holdsRecord(this._rows())) {
|
|
4556
|
+
this._rows.set(this._rows().map(patch));
|
|
4557
|
+
}
|
|
4558
|
+
this._groupRows.update(current => {
|
|
4559
|
+
let touched = false;
|
|
4560
|
+
const next = new Map(current);
|
|
4561
|
+
current.forEach((rows, groupId) => {
|
|
4562
|
+
if (!holdsRecord(rows))
|
|
4563
|
+
return;
|
|
4564
|
+
next.set(groupId, rows.map(patch));
|
|
4565
|
+
touched = true;
|
|
4566
|
+
});
|
|
4567
|
+
return touched ? next : current;
|
|
4568
|
+
});
|
|
4569
|
+
}
|
|
4505
4570
|
// Selection methods
|
|
4506
4571
|
selectRow(rowId) {
|
|
4507
4572
|
const selectedRowIds = new Set(this.selectedRowIds());
|
|
@@ -13756,9 +13821,13 @@ class ColumnDesignPanelComponent {
|
|
|
13756
13821
|
* drift apart: a key that is inherited is always locked, and vice versa.
|
|
13757
13822
|
*
|
|
13758
13823
|
* SEEDED_FIELD_KEYS are the exception the resolver makes too: the model seeds
|
|
13759
|
-
* them, this grid may then override them, so they stay editable here.
|
|
13824
|
+
* them, this grid may then override them, so they stay editable here. So are
|
|
13825
|
+
* EXPLICITLY_OVERRIDDEN_FIELD_KEYS, seeded the same way but tracked by a flag
|
|
13826
|
+
* — `label` among them, which must stay typeable for the flag to ever be set.
|
|
13760
13827
|
*/
|
|
13761
|
-
static INHERITED_KEYS = new Set(INHERITED_FIELD_KEYS.filter(k => !SEEDED_FIELD_KEYS.includes(k) &&
|
|
13828
|
+
static INHERITED_KEYS = new Set(INHERITED_FIELD_KEYS.filter(k => !SEEDED_FIELD_KEYS.includes(k) &&
|
|
13829
|
+
!EXPLICITLY_OVERRIDDEN_FIELD_KEYS[k] &&
|
|
13830
|
+
k !== 'datatype'));
|
|
13762
13831
|
isInherited(key) {
|
|
13763
13832
|
return this.isEntityMapped() && ColumnDesignPanelComponent.INHERITED_KEYS.has(key);
|
|
13764
13833
|
}
|
|
@@ -14045,6 +14114,20 @@ class ColumnDesignPanelComponent {
|
|
|
14045
14114
|
this.gridStore.updateColumnMeta(name, { [key]: value });
|
|
14046
14115
|
}
|
|
14047
14116
|
onText(key, value) {
|
|
14117
|
+
// A typed heading is the author's, and stops the mapped field's label from
|
|
14118
|
+
// seeding it on the next resolve; clearing the box hands the column back to
|
|
14119
|
+
// the data model rather than pinning it to an empty header.
|
|
14120
|
+
const flag = EXPLICITLY_OVERRIDDEN_FIELD_KEYS[key];
|
|
14121
|
+
if (flag) {
|
|
14122
|
+
const name = this.gridStore.selectedDesignColumn();
|
|
14123
|
+
if (!name)
|
|
14124
|
+
return;
|
|
14125
|
+
const typed = String(value ?? '').trim();
|
|
14126
|
+
this.gridStore.updateColumnMeta(name, typed
|
|
14127
|
+
? { [key]: value, [flag]: true }
|
|
14128
|
+
: { [key]: null, [flag]: null });
|
|
14129
|
+
return;
|
|
14130
|
+
}
|
|
14048
14131
|
this.patch(key, value);
|
|
14049
14132
|
}
|
|
14050
14133
|
onNumber(key, value) {
|
|
@@ -15789,7 +15872,7 @@ class EruGridComponent {
|
|
|
15789
15872
|
}
|
|
15790
15873
|
}
|
|
15791
15874
|
trackByPivotRowFn(index, pivotRow) {
|
|
15792
|
-
return pivotRow
|
|
15875
|
+
return pivotRow?._rowKey || `pivot-row-${index}`;
|
|
15793
15876
|
}
|
|
15794
15877
|
trackByRowFn(index, row) {
|
|
15795
15878
|
// Use both entity_id and index to ensure uniqueness even with duplicate entity_ids
|
|
@@ -16121,6 +16204,11 @@ class EruGridComponent {
|
|
|
16121
16204
|
* including an explicit `false` on a checkbox — wins from then on. Without the
|
|
16122
16205
|
* column in hand there is no way to tell "not set" from "set to the opposite",
|
|
16123
16206
|
* so an override was overwritten on every resolve.
|
|
16207
|
+
*
|
|
16208
|
+
* EXPLICITLY_OVERRIDDEN_FIELD_KEYS work the same way but ask a companion flag
|
|
16209
|
+
* instead, for keys a column always holds a value for — `label`, whose
|
|
16210
|
+
* "already set" was true from the first render, so the model's label never
|
|
16211
|
+
* won and a mapped column kept its raw result key as the heading.
|
|
16124
16212
|
*/
|
|
16125
16213
|
buildMappedColumnPatch(meta, col) {
|
|
16126
16214
|
const patch = {};
|
|
@@ -16132,6 +16220,9 @@ class EruGridComponent {
|
|
|
16132
16220
|
continue;
|
|
16133
16221
|
if (seeded.has(k) && !isUnset(col?.[k]))
|
|
16134
16222
|
continue;
|
|
16223
|
+
const overrideFlag = EXPLICITLY_OVERRIDDEN_FIELD_KEYS[k];
|
|
16224
|
+
if (overrideFlag && col?.[overrideFlag])
|
|
16225
|
+
continue;
|
|
16135
16226
|
patch[k] = v;
|
|
16136
16227
|
}
|
|
16137
16228
|
// setColumns() stores the canonical datatype ('r_status' -> 'status'), so a
|
|
@@ -17033,5 +17124,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
17033
17124
|
* Generated bundle index. Do not edit.
|
|
17034
17125
|
*/
|
|
17035
17126
|
|
|
17036
|
-
export { ACTION_COLUMN_MIN_WIDTH, AttachmentComponent, CELL_RULE_OPERATORS, CheckboxComponent, ChipListComponent, ColumnConstraintsService, CompositeComponent, CurrencyComponent, CustomVirtualScrollStrategy, DATA_TYPES, DATETIME_FORMATS, DATE_FORMATS, DateComponent, DatetimeComponent, DurationComponent, EmailComponent, EruGridComponent, EruGridService, EruGridStore, GRID_COLOR_TOKENS, INHERITED_FIELD_KEYS, LocationComponent, MATERIAL_MODULES, MATERIAL_PROVIDERS, MONTH_SHORT_NAMES, NumberComponent, NumericInputDirective, PRESENTATION_DATATYPES, PRESET_CONFIG_DEFAULTS, PRESET_MANAGED_FIELDS, PeopleComponent, PhoneComponent, PriorityComponent, ProgressComponent, RatingComponent, SEEDED_FIELD_KEYS, SELF_COLOURED_DATATYPES, SelectComponent, StatusComponent, TagComponent, TextareaComponent, TextboxComponent, ThemeService, ThemeToggleComponent, WebsiteComponent, abbreviateNumber, abbreviationScaleFor, cellRuleBarPercent, cellRuleMatches, cellRuleToCss, cellStatAlias, cellTextStyleToCss, collectColumnStatRequests, columnCellRules, composeColorValue, effectiveValueDatatype, evaluateRowCondition, formatCellValue, formatDateTimeWithPattern, formatDateWithPattern, formatNumberValue, hasOwnCellRules, matchCellRule, matchColorRange, normalizeCellRender, normalizeDatatype, normalizeDateFormat, normalizeDateTimeFormat, parseCellDate, parseCellDateTime, parseColorValue, parseDateWithPattern, readRowValue, resolveColumnRules, resolveRowValue, resolveStatValue, rowSelectionKey, statusPillColors, tagPillColors, toDateOnlyString, toDateTimeString };
|
|
17127
|
+
export { ACTION_COLUMN_MIN_WIDTH, AttachmentComponent, CELL_RULE_OPERATORS, CheckboxComponent, ChipListComponent, ColumnConstraintsService, CompositeComponent, CurrencyComponent, CustomVirtualScrollStrategy, DATA_TYPES, DATETIME_FORMATS, DATE_FORMATS, DateComponent, DatetimeComponent, DurationComponent, EXPLICITLY_OVERRIDDEN_FIELD_KEYS, EmailComponent, EruGridComponent, EruGridService, EruGridStore, GRID_COLOR_TOKENS, INHERITED_FIELD_KEYS, LocationComponent, MATERIAL_MODULES, MATERIAL_PROVIDERS, MONTH_SHORT_NAMES, NumberComponent, NumericInputDirective, PRESENTATION_DATATYPES, PRESET_CONFIG_DEFAULTS, PRESET_MANAGED_FIELDS, PeopleComponent, PhoneComponent, PriorityComponent, ProgressComponent, RatingComponent, SEEDED_FIELD_KEYS, SELF_COLOURED_DATATYPES, SelectComponent, StatusComponent, TagComponent, TextareaComponent, TextboxComponent, ThemeService, ThemeToggleComponent, WebsiteComponent, abbreviateNumber, abbreviationScaleFor, cellRuleBarPercent, cellRuleMatches, cellRuleToCss, cellStatAlias, cellTextStyleToCss, collectColumnStatRequests, columnCellRules, composeColorValue, effectiveValueDatatype, evaluateRowCondition, formatCellValue, formatDateTimeWithPattern, formatDateWithPattern, formatNumberValue, hasOwnCellRules, matchCellRule, matchColorRange, normalizeCellRender, normalizeDatatype, normalizeDateFormat, normalizeDateTimeFormat, parseCellDate, parseCellDateTime, parseColorValue, parseDateWithPattern, readRowValue, resolveColumnRules, resolveRowValue, resolveStatValue, rowSelectionKey, statusPillColors, tagPillColors, toDateOnlyString, toDateTimeString };
|
|
17037
17128
|
//# sourceMappingURL=eru-grid.mjs.map
|