@fuentis/phoenix-ui 0.0.9-alpha.638 → 0.0.9-alpha.640
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.
|
@@ -2056,7 +2056,13 @@ class TableCaptionComponent {
|
|
|
2056
2056
|
}
|
|
2057
2057
|
// Normalize filters (backward compatible) before building form
|
|
2058
2058
|
const normalizedFilters = this.normalizeFilters(this.filters);
|
|
2059
|
-
|
|
2059
|
+
// Key the rebuild signature on the storage identity (FILTER_KEY), not just
|
|
2060
|
+
// the table key. Sibling tabs that share the same filter columns (e.g. IT
|
|
2061
|
+
// Systems vs Virtualization) but persist under different stateKeys must
|
|
2062
|
+
// rebuild — and thus re-restore — when switched between while the caption
|
|
2063
|
+
// instance is reused; otherwise the reused form keeps the previous tab's
|
|
2064
|
+
// values and the persisted filter looks lost until a full reload.
|
|
2065
|
+
const signature = this.buildSignature(this.FILTER_KEY, normalizedFilters);
|
|
2060
2066
|
if (signature !== this.lastSignature) {
|
|
2061
2067
|
this.lastSignature = signature;
|
|
2062
2068
|
this.buildFiltersForm(normalizedFilters);
|
|
@@ -2119,8 +2125,9 @@ class TableCaptionComponent {
|
|
|
2119
2125
|
const raw = this.filtersForm.getRawValue();
|
|
2120
2126
|
const payload = this.normalizeOutgoingPayload(raw, filtersCfg);
|
|
2121
2127
|
this.applyFiltersEvent.emit(payload);
|
|
2128
|
+
// Initial/restore emit — save if there's something, but never DELETE here.
|
|
2122
2129
|
if (hasFilterConfig)
|
|
2123
|
-
this.persistState(payload, this.FILTER_KEY);
|
|
2130
|
+
this.persistState(payload, this.FILTER_KEY, false);
|
|
2124
2131
|
});
|
|
2125
2132
|
}
|
|
2126
2133
|
/**
|
|
@@ -2147,11 +2154,19 @@ class TableCaptionComponent {
|
|
|
2147
2154
|
}
|
|
2148
2155
|
buildSignature(tableKey, filtersCfg) {
|
|
2149
2156
|
const keys = (filtersCfg ?? [])
|
|
2150
|
-
.map((f) =>
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2157
|
+
.map((f) => {
|
|
2158
|
+
// Range bounds are data-derived and can change without the key set
|
|
2159
|
+
// changing; fold them into the signature so the form rebuilds when
|
|
2160
|
+
// the min/max move.
|
|
2161
|
+
if (f.type === 'range')
|
|
2162
|
+
return `${f.key}:${f.min}-${f.max}`;
|
|
2163
|
+
// Options arrive after the data loads. Fold their presence in so the
|
|
2164
|
+
// form rebuilds — and re-restores against real options — once they're
|
|
2165
|
+
// available, instead of staying with the value dropped on the first
|
|
2166
|
+
// (option-less) build.
|
|
2167
|
+
const hasOptions = Array.isArray(f.options) && f.options.length > 0;
|
|
2168
|
+
return `${f.key}${hasOptions ? ':o' : ''}`;
|
|
2169
|
+
})
|
|
2155
2170
|
.join('|');
|
|
2156
2171
|
return `${tableKey ?? 'table'}::${keys}`;
|
|
2157
2172
|
}
|
|
@@ -2176,7 +2191,8 @@ class TableCaptionComponent {
|
|
|
2176
2191
|
if (Object.keys(patch).length > 0) {
|
|
2177
2192
|
this.filtersForm.patchValue(patch, { emitEvent: true });
|
|
2178
2193
|
const payload = this.normalizeOutgoingPayload(this.filtersForm.getRawValue(), cfg);
|
|
2179
|
-
|
|
2194
|
+
// Programmatic valid-values sync — update, but never delete.
|
|
2195
|
+
this.persistState(payload, this.FILTER_KEY, false);
|
|
2180
2196
|
}
|
|
2181
2197
|
}
|
|
2182
2198
|
normalizeMultiInitial(selected) {
|
|
@@ -2388,10 +2404,11 @@ class TableCaptionComponent {
|
|
|
2388
2404
|
}
|
|
2389
2405
|
}
|
|
2390
2406
|
this.filtersForm.patchValue(patch, { emitEvent: false });
|
|
2391
|
-
// Persist the pruned state so stale (non-existent) values don't linger in
|
|
2407
|
+
// Persist the pruned state so stale (non-existent) values don't linger in
|
|
2408
|
+
// storage — but never DELETE here (empty after pruning ≠ user cleared).
|
|
2392
2409
|
if (changed) {
|
|
2393
2410
|
const payload = this.normalizeOutgoingPayload(this.filtersForm.getRawValue(), cfg);
|
|
2394
|
-
this.persistState(payload, this.FILTER_KEY);
|
|
2411
|
+
this.persistState(payload, this.FILTER_KEY, false);
|
|
2395
2412
|
}
|
|
2396
2413
|
}
|
|
2397
2414
|
catch {
|
|
@@ -2495,16 +2512,23 @@ class TableCaptionComponent {
|
|
|
2495
2512
|
localStorage.removeItem(this.FILTER_KEY);
|
|
2496
2513
|
this.filtersPopover?.hide();
|
|
2497
2514
|
}
|
|
2498
|
-
persistState(state, key) {
|
|
2515
|
+
persistState(state, key, allowDelete = true) {
|
|
2499
2516
|
const isEmpty = state == null ||
|
|
2500
2517
|
(Array.isArray(state) && state.length === 0) ||
|
|
2501
2518
|
(typeof state === 'object' &&
|
|
2502
2519
|
!Array.isArray(state) &&
|
|
2503
2520
|
Object.keys(state).length === 0);
|
|
2504
|
-
if (isEmpty)
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2521
|
+
if (isEmpty) {
|
|
2522
|
+
// Only a USER-initiated clear (valueChanges) may delete a saved filter.
|
|
2523
|
+
// Programmatic emits (initial rebuild, valid-values pruning, restore
|
|
2524
|
+
// pruning) pass allowDelete=false, so a transient empty form — e.g. a
|
|
2525
|
+
// caption rebuilt before its options loaded, which drops the restored
|
|
2526
|
+
// value — never wipes a perfectly good persisted filter.
|
|
2527
|
+
if (allowDelete)
|
|
2528
|
+
localStorage.removeItem(key);
|
|
2529
|
+
return;
|
|
2530
|
+
}
|
|
2531
|
+
localStorage.setItem(key, JSON.stringify(state));
|
|
2508
2532
|
}
|
|
2509
2533
|
getOptionLabelField(control) {
|
|
2510
2534
|
return (control?.optionLabel ?? 'label');
|