@praxisui/core 10.0.0-rc.15 → 10.0.0-rc.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/ai/component-registry.json +2 -2
- package/fesm2022/praxisui-core.mjs +277 -48
- package/package.json +1 -1
- package/types/praxisui-core.d.ts +21 -2
package/README.md
CHANGED
|
@@ -93,6 +93,15 @@ backend B7 acceptance is complete.
|
|
|
93
93
|
|
|
94
94
|
`GovernedColorPaletteService` is the canonical Angular client for color-palette projections published by Praxis Config. Published palettes carry a stable `familyKey`, an explicit `variant` identity and token-level `displayName`/`aliases`; incomplete legacy projections are rejected before caching. The service supports list/read/capabilities/preview, exact `list(familyKey)` queries, tenant/environment-isolated caching, conditional ETag revalidation and deterministic `version`/`etag` pins. Consumers may use names and aliases for presentation and discovery only: `paletteKey` and `tokenId` remain the persisted identities, and local metadata must not become a second source of governance. `GovernedColorTokenSelection` carries the exact palette/version/ETag/token observation beside the existing CSS-string field value; applications persist it only through an explicit domain field or mapping.
|
|
95
95
|
|
|
96
|
+
## Declarative Page DataSources (`page.dataSources`)
|
|
97
|
+
|
|
98
|
+
`WidgetPageDefinition.dataSources` and `WidgetPageDataSourceRuntimeService` allow dynamic pages and dashboards to fetch backend KPIs, group-by aggregations, and time-series metrics without imperative host `HttpClient` orchestration:
|
|
99
|
+
|
|
100
|
+
- **Endpoint resolution (`endpointKey` + `resourcePath`)**: resolves URLs through the `API_URL` token using `endpointKey` (falling back to `'default'`) so multi-service enterprise hosts route each DataSource to its target microservice.
|
|
101
|
+
- **Transform presets & JsonLogic**: supports `{ kind: 'path', path }`, `{ kind: 'group-by-map', mappings, totalField }` (initializing declared keys with `0` for sparse buckets), `{ kind: 'timeseries-last', mappings }`, or arbitrary JsonLogic expressions.
|
|
102
|
+
- **Transient state overlay (`targetStatePath`)**: merges resolved payloads into a non-persisted runtime overlay over `page.state.values[targetStatePath]` and coalesces concurrent emissions via microtask batching before re-evaluating `page.state.derived` and `composition.links`. Live runtime payloads never dirty `authoredPageDefinition` or trigger `autoPersist` writes.
|
|
103
|
+
- **Resilience & visibility-aware polling**: `errorPolicy` (`'fallback' | 'silent' | 'propagate'`) applies `fallbackValue` only before the first successful response so transient network errors during polling (`refreshIntervalMs`) never overwrite live data with static fallbacks. Subsequent poll ticks pause while `document.visibilityState === 'hidden'` and resume immediately on `visibilitychange`.
|
|
104
|
+
|
|
96
105
|
## LLM Recommendation Guide
|
|
97
106
|
|
|
98
107
|
- `BUILTIN_WIDGET_SHELL_PRESETS` is the canonical catalog for reusable shell
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-14T22:05:37.957Z",
|
|
4
4
|
"packageName": "@praxisui/core",
|
|
5
|
-
"packageVersion": "10.0.0-rc.
|
|
5
|
+
"packageVersion": "10.0.0-rc.17",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 4,
|
|
@@ -5532,8 +5532,28 @@ class GenericCrudService {
|
|
|
5532
5532
|
.post(url, entity, {
|
|
5533
5533
|
headers: composeHeadersWithVersion(entry),
|
|
5534
5534
|
context: options?.httpContext,
|
|
5535
|
+
observe: 'response',
|
|
5535
5536
|
})
|
|
5536
|
-
.pipe(
|
|
5537
|
+
.pipe(map((response) => {
|
|
5538
|
+
const isHttpResponse = response &&
|
|
5539
|
+
typeof response === 'object' &&
|
|
5540
|
+
'body' in response &&
|
|
5541
|
+
'headers' in response;
|
|
5542
|
+
if (!isHttpResponse) {
|
|
5543
|
+
return response;
|
|
5544
|
+
}
|
|
5545
|
+
const idField = this._lastResourceMeta.idField || 'id';
|
|
5546
|
+
const createdId = response.body?.data?.[idField] ??
|
|
5547
|
+
response.body?.data?.id;
|
|
5548
|
+
if (createdId !== undefined && createdId !== null) {
|
|
5549
|
+
const versionKey = this.resourceVersionKey(createdId, options);
|
|
5550
|
+
return this.captureResourceVersion(versionKey, response);
|
|
5551
|
+
}
|
|
5552
|
+
if (!response.body) {
|
|
5553
|
+
throw new Error('Resource response body is empty.');
|
|
5554
|
+
}
|
|
5555
|
+
return response.body;
|
|
5556
|
+
}), catchError(this.handleError));
|
|
5537
5557
|
}
|
|
5538
5558
|
/**
|
|
5539
5559
|
* Atualiza um registro existente.
|
|
@@ -5558,6 +5578,26 @@ class GenericCrudService {
|
|
|
5558
5578
|
update(id, entity, options) {
|
|
5559
5579
|
return this.updateResponse(id, entity, options).pipe(map((r) => r.data));
|
|
5560
5580
|
}
|
|
5581
|
+
getResourceVersion(id, options) {
|
|
5582
|
+
if (id === undefined || id === null || !this.configured) {
|
|
5583
|
+
return null;
|
|
5584
|
+
}
|
|
5585
|
+
const versionKey = this.resourceVersionKey(id, options);
|
|
5586
|
+
return this._resourceEtags.get(versionKey) ?? null;
|
|
5587
|
+
}
|
|
5588
|
+
setResourceVersion(id, etag, options) {
|
|
5589
|
+
if (id === undefined || id === null || !this.configured) {
|
|
5590
|
+
return;
|
|
5591
|
+
}
|
|
5592
|
+
const versionKey = this.resourceVersionKey(id, options);
|
|
5593
|
+
const formatted = this.normalizeEtagToken(etag);
|
|
5594
|
+
if (formatted) {
|
|
5595
|
+
this._resourceEtags.set(versionKey, formatted);
|
|
5596
|
+
}
|
|
5597
|
+
else {
|
|
5598
|
+
this._resourceEtags.delete(versionKey);
|
|
5599
|
+
}
|
|
5600
|
+
}
|
|
5561
5601
|
updateResponse(id, entity, options) {
|
|
5562
5602
|
if (id === undefined || id === null)
|
|
5563
5603
|
throw new Error(this.errorMessages.emptyId);
|
|
@@ -5568,10 +5608,12 @@ class GenericCrudService {
|
|
|
5568
5608
|
const url = this.getEndpointUrl('update', id, options?.parentPath, options?.endpointKey);
|
|
5569
5609
|
const versionKey = this.resourceVersionKey(id, options);
|
|
5570
5610
|
let headers = composeHeadersWithVersion(entry);
|
|
5571
|
-
const etag = this._resourceEtags.get(versionKey)
|
|
5611
|
+
const etag = this._resourceEtags.get(versionKey) ||
|
|
5612
|
+
this.normalizeEtagToken(entity?.resourceVersion) ||
|
|
5613
|
+
null;
|
|
5572
5614
|
if (etag) {
|
|
5573
5615
|
headers = (headers instanceof HttpHeaders ? headers : new HttpHeaders(headers))
|
|
5574
|
-
.set('If-Match', etag);
|
|
5616
|
+
.set('If-Match', this.ensureEtagFormat(etag));
|
|
5575
5617
|
}
|
|
5576
5618
|
return this.http
|
|
5577
5619
|
.put(url, entity, {
|
|
@@ -5594,7 +5636,9 @@ class GenericCrudService {
|
|
|
5594
5636
|
return [buildApiUrl(entry), tenant, environment, this.resourcePath, options?.parentPath ?? '', String(id)].join('|');
|
|
5595
5637
|
}
|
|
5596
5638
|
captureResourceVersion(key, response) {
|
|
5597
|
-
const etag = response.headers
|
|
5639
|
+
const etag = this.normalizeEtagToken(response.headers?.get('ETag')) ||
|
|
5640
|
+
this.normalizeEtagToken(response.body?.data?.resourceVersion) ||
|
|
5641
|
+
null;
|
|
5598
5642
|
if (etag) {
|
|
5599
5643
|
this._resourceEtags.set(key, etag);
|
|
5600
5644
|
}
|
|
@@ -5603,6 +5647,26 @@ class GenericCrudService {
|
|
|
5603
5647
|
}
|
|
5604
5648
|
return response.body;
|
|
5605
5649
|
}
|
|
5650
|
+
normalizeEtagToken(etag) {
|
|
5651
|
+
if (typeof etag !== 'string' && typeof etag !== 'number') {
|
|
5652
|
+
return null;
|
|
5653
|
+
}
|
|
5654
|
+
const trimmed = String(etag).trim();
|
|
5655
|
+
if (!trimmed) {
|
|
5656
|
+
return null;
|
|
5657
|
+
}
|
|
5658
|
+
const inner = trimmed.replace(/^(?:W\/)?"|"$/g, '').trim();
|
|
5659
|
+
if (!inner) {
|
|
5660
|
+
return null;
|
|
5661
|
+
}
|
|
5662
|
+
return this.ensureEtagFormat(trimmed);
|
|
5663
|
+
}
|
|
5664
|
+
ensureEtagFormat(etag) {
|
|
5665
|
+
if (/^(?:W\/)?".+"$/.test(etag)) {
|
|
5666
|
+
return etag;
|
|
5667
|
+
}
|
|
5668
|
+
return `"${etag.replace(/^"|"$/g, '')}"`;
|
|
5669
|
+
}
|
|
5606
5670
|
/**
|
|
5607
5671
|
* Remove um registro pelo ID.
|
|
5608
5672
|
*
|
|
@@ -5631,6 +5695,7 @@ class GenericCrudService {
|
|
|
5631
5695
|
this.ensureConfigured();
|
|
5632
5696
|
const entry = this.resolveEndpointEntry(options?.endpointKey);
|
|
5633
5697
|
const url = this.getEndpointUrl('delete', id, options?.parentPath, options?.endpointKey);
|
|
5698
|
+
const versionKey = this.resourceVersionKey(id, options);
|
|
5634
5699
|
debugCrudService('[CRUD:Service] delete:request', {
|
|
5635
5700
|
url,
|
|
5636
5701
|
id,
|
|
@@ -5642,7 +5707,7 @@ class GenericCrudService {
|
|
|
5642
5707
|
headers: composeHeadersWithVersion(entry),
|
|
5643
5708
|
context: options?.httpContext,
|
|
5644
5709
|
})
|
|
5645
|
-
.pipe(catchError(this.handleError));
|
|
5710
|
+
.pipe(tap(() => this._resourceEtags.delete(versionKey)), catchError(this.handleError));
|
|
5646
5711
|
}
|
|
5647
5712
|
/**
|
|
5648
5713
|
* Realiza exclusão de múltiplos registros sequencialmente.
|
|
@@ -13237,6 +13302,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
13237
13302
|
type: Optional
|
|
13238
13303
|
}] }] });
|
|
13239
13304
|
|
|
13305
|
+
const DEFAULT_FRAMEWORK_VERSION_MESSAGES = new Set([
|
|
13306
|
+
'resource version is stale.',
|
|
13307
|
+
'resource version is required.',
|
|
13308
|
+
'the resource changed after it was read. reload it before deciding whether to retry.',
|
|
13309
|
+
'the resource changed after it was read. reload and try again.',
|
|
13310
|
+
'this operation requires a current resource version in if-match.',
|
|
13311
|
+
]);
|
|
13240
13312
|
/**
|
|
13241
13313
|
* Maps HTTP or network errors to user-friendly messages.
|
|
13242
13314
|
* This service centralizes error messaging so UI components don't
|
|
@@ -13258,14 +13330,19 @@ class ErrorMessageService {
|
|
|
13258
13330
|
? this.normalizeDetails(payload?.['errors'])
|
|
13259
13331
|
: [];
|
|
13260
13332
|
if (details.length) {
|
|
13333
|
+
const topMessage = this.textValue(payload?.['message']);
|
|
13334
|
+
const resolvedTopMessage = this.resolveVersionPreconditionCopy(details[0].code, topMessage ?? details[0].message, status);
|
|
13261
13335
|
return {
|
|
13262
|
-
message:
|
|
13336
|
+
message: resolvedTopMessage,
|
|
13263
13337
|
details,
|
|
13264
13338
|
};
|
|
13265
13339
|
}
|
|
13266
13340
|
const publicMessage = this.textValue(payload?.['message']);
|
|
13267
13341
|
if (publicMessage && isPublicClientError) {
|
|
13268
|
-
return {
|
|
13342
|
+
return {
|
|
13343
|
+
message: this.resolveVersionPreconditionCopy(undefined, publicMessage, status),
|
|
13344
|
+
details: [],
|
|
13345
|
+
};
|
|
13269
13346
|
}
|
|
13270
13347
|
return { message: this.fallbackMessage(status), details: [] };
|
|
13271
13348
|
}
|
|
@@ -13283,6 +13360,12 @@ class ErrorMessageService {
|
|
|
13283
13360
|
if (status !== undefined && status >= 500) {
|
|
13284
13361
|
return this.tx('global.submitError.server', 'Erro interno no servidor. Tente novamente mais tarde.');
|
|
13285
13362
|
}
|
|
13363
|
+
if (status === 412) {
|
|
13364
|
+
return this.staleResourceVersionMessage();
|
|
13365
|
+
}
|
|
13366
|
+
if (status === 428) {
|
|
13367
|
+
return this.resourceVersionRequiredMessage();
|
|
13368
|
+
}
|
|
13286
13369
|
if (status === 400 || status === 422) {
|
|
13287
13370
|
return this.tx('global.submitError.invalidData', 'Dados inválidos ou inconsistentes. Verifique os campos e tente novamente.');
|
|
13288
13371
|
}
|
|
@@ -13293,17 +13376,40 @@ class ErrorMessageService {
|
|
|
13293
13376
|
return [];
|
|
13294
13377
|
return value.flatMap((item) => {
|
|
13295
13378
|
const detail = this.objectValue(item);
|
|
13296
|
-
const
|
|
13297
|
-
if (!
|
|
13379
|
+
const rawMessage = this.textValue(detail?.['message']) ?? this.textValue(detail?.['detail']);
|
|
13380
|
+
if (!rawMessage)
|
|
13298
13381
|
return [];
|
|
13382
|
+
const code = this.textValue(detail?.['code']);
|
|
13383
|
+
const message = this.resolveVersionPreconditionCopy(code, rawMessage, undefined);
|
|
13299
13384
|
return [{
|
|
13300
13385
|
message,
|
|
13301
|
-
code
|
|
13386
|
+
code,
|
|
13302
13387
|
target: this.textValue(detail?.['target']),
|
|
13303
13388
|
category: this.textValue(detail?.['category']),
|
|
13304
13389
|
}];
|
|
13305
13390
|
});
|
|
13306
13391
|
}
|
|
13392
|
+
resolveVersionPreconditionCopy(code, candidateMessage, status) {
|
|
13393
|
+
const normalizedCode = String(code ?? '').trim().toUpperCase();
|
|
13394
|
+
const isDefaultFrameworkCopy = DEFAULT_FRAMEWORK_VERSION_MESSAGES.has(candidateMessage.trim().toLowerCase());
|
|
13395
|
+
if ((normalizedCode === 'STALE_RESOURCE_VERSION' || status === 412) &&
|
|
13396
|
+
isDefaultFrameworkCopy) {
|
|
13397
|
+
return this.staleResourceVersionMessage();
|
|
13398
|
+
}
|
|
13399
|
+
if ((normalizedCode === 'RESOURCE_VERSION_REQUIRED' ||
|
|
13400
|
+
normalizedCode === 'MISSING_IF_MATCH' ||
|
|
13401
|
+
status === 428) &&
|
|
13402
|
+
isDefaultFrameworkCopy) {
|
|
13403
|
+
return this.resourceVersionRequiredMessage();
|
|
13404
|
+
}
|
|
13405
|
+
return candidateMessage;
|
|
13406
|
+
}
|
|
13407
|
+
staleResourceVersionMessage() {
|
|
13408
|
+
return this.tx('global.submitError.staleResourceVersion', 'Este registro foi alterado após a leitura. Recarregue os dados e revise antes de tentar salvar novamente.');
|
|
13409
|
+
}
|
|
13410
|
+
resourceVersionRequiredMessage() {
|
|
13411
|
+
return this.tx('global.submitError.resourceVersionRequired', 'A versão atual do registro é obrigatória para confirmar esta alteração. Recarregue o registro e tente novamente.');
|
|
13412
|
+
}
|
|
13307
13413
|
objectValue(value) {
|
|
13308
13414
|
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
13309
13415
|
? value
|
|
@@ -39980,7 +40086,7 @@ class WidgetPageDataSourceRuntimeService {
|
|
|
39980
40086
|
/**
|
|
39981
40087
|
* Constrói a URL canônica completa para o resourcePath declarado no dataSource.
|
|
39982
40088
|
*/
|
|
39983
|
-
resolveUrl(resourcePath) {
|
|
40089
|
+
resolveUrl(resourcePath, endpointKey) {
|
|
39984
40090
|
const trimmed = (resourcePath || '').trim();
|
|
39985
40091
|
if (!trimmed)
|
|
39986
40092
|
return '';
|
|
@@ -39989,7 +40095,10 @@ class WidgetPageDataSourceRuntimeService {
|
|
|
39989
40095
|
}
|
|
39990
40096
|
let base = '';
|
|
39991
40097
|
if (this.apiUrlConfig) {
|
|
39992
|
-
const
|
|
40098
|
+
const key = (endpointKey || 'default').trim() || 'default';
|
|
40099
|
+
const entry = this.apiUrlConfig[key] ||
|
|
40100
|
+
this.apiUrlConfig['default'] ||
|
|
40101
|
+
Object.values(this.apiUrlConfig)[0];
|
|
39993
40102
|
if (entry) {
|
|
39994
40103
|
base = buildApiUrl(entry);
|
|
39995
40104
|
}
|
|
@@ -40008,7 +40117,7 @@ class WidgetPageDataSourceRuntimeService {
|
|
|
40008
40117
|
if (!this.http) {
|
|
40009
40118
|
return of(dataSource.fallbackValue ?? null);
|
|
40010
40119
|
}
|
|
40011
|
-
const url = this.resolveUrl(dataSource.resourcePath);
|
|
40120
|
+
const url = this.resolveUrl(dataSource.resourcePath, dataSource.endpointKey);
|
|
40012
40121
|
if (!url) {
|
|
40013
40122
|
return of(dataSource.fallbackValue ?? null);
|
|
40014
40123
|
}
|
|
@@ -40032,7 +40141,8 @@ class WidgetPageDataSourceRuntimeService {
|
|
|
40032
40141
|
if (!this.http) {
|
|
40033
40142
|
return of(dataSource.fallbackValue ?? null);
|
|
40034
40143
|
}
|
|
40035
|
-
const url = resolvedUrl ??
|
|
40144
|
+
const url = resolvedUrl ??
|
|
40145
|
+
this.resolveUrl(dataSource.resourcePath, dataSource.endpointKey);
|
|
40036
40146
|
if (!url) {
|
|
40037
40147
|
return of(dataSource.fallbackValue ?? null);
|
|
40038
40148
|
}
|
|
@@ -40064,28 +40174,65 @@ class WidgetPageDataSourceRuntimeService {
|
|
|
40064
40174
|
}
|
|
40065
40175
|
return request$.pipe(map((res) => this.transformPayload(res, dataSource)));
|
|
40066
40176
|
}
|
|
40177
|
+
/**
|
|
40178
|
+
* Normaliza `page.dataSources` aceitando tanto o formato canônico em Array quanto Object Map indexado por id.
|
|
40179
|
+
*/
|
|
40180
|
+
normalizeDataSources(dataSources) {
|
|
40181
|
+
if (!dataSources || typeof dataSources !== 'object') {
|
|
40182
|
+
return [];
|
|
40183
|
+
}
|
|
40184
|
+
if (Array.isArray(dataSources)) {
|
|
40185
|
+
return dataSources.filter((item) => !!item &&
|
|
40186
|
+
typeof item === 'object' &&
|
|
40187
|
+
!Array.isArray(item) &&
|
|
40188
|
+
typeof item.id === 'string' &&
|
|
40189
|
+
item.id.trim().length > 0 &&
|
|
40190
|
+
typeof item.resourcePath === 'string' &&
|
|
40191
|
+
item.resourcePath.trim().length > 0);
|
|
40192
|
+
}
|
|
40193
|
+
return Object.entries(dataSources)
|
|
40194
|
+
.filter(([key, item]) => key.trim().length > 0 &&
|
|
40195
|
+
!!item &&
|
|
40196
|
+
typeof item === 'object' &&
|
|
40197
|
+
!Array.isArray(item) &&
|
|
40198
|
+
typeof item.resourcePath === 'string' &&
|
|
40199
|
+
item.resourcePath.trim().length > 0)
|
|
40200
|
+
.map(([key, item]) => {
|
|
40201
|
+
const candidateId = item.id;
|
|
40202
|
+
return {
|
|
40203
|
+
...item,
|
|
40204
|
+
id: typeof candidateId === 'string' && candidateId.trim().length > 0
|
|
40205
|
+
? candidateId.trim()
|
|
40206
|
+
: key.trim(),
|
|
40207
|
+
};
|
|
40208
|
+
});
|
|
40209
|
+
}
|
|
40067
40210
|
/**
|
|
40068
40211
|
* Inicia a orquestração reativa de todos os DataSources declarados em uma página dinâmica.
|
|
40069
40212
|
* Retorna uma função de teardown que cancela todas as requisições em voo e timers de polling.
|
|
40070
40213
|
*/
|
|
40071
40214
|
startDataSources(dataSources, onUpdate, onDiagnostic) {
|
|
40072
|
-
|
|
40215
|
+
const normalizedDataSources = this.normalizeDataSources(dataSources);
|
|
40216
|
+
if (!normalizedDataSources.length) {
|
|
40073
40217
|
return () => { };
|
|
40074
40218
|
}
|
|
40075
40219
|
const destroy$ = new Subject();
|
|
40076
|
-
|
|
40220
|
+
const visibilityCallbacks = [];
|
|
40221
|
+
for (const ds of normalizedDataSources) {
|
|
40077
40222
|
if (ds.autoFetch === false) {
|
|
40078
40223
|
continue;
|
|
40079
40224
|
}
|
|
40080
40225
|
const targetPath = ds.targetStatePath || ds.id;
|
|
40081
40226
|
const intervalMs = ds.refreshIntervalMs ?? 0;
|
|
40082
40227
|
let hasSucceededOnce = false;
|
|
40228
|
+
let skippedWhileHidden = false;
|
|
40083
40229
|
onDiagnostic?.({
|
|
40084
40230
|
dataSourceId: ds.id,
|
|
40085
40231
|
status: 'loading',
|
|
40086
40232
|
});
|
|
40087
40233
|
const runSingleFetch$ = () => this.executeRawRequest(ds).pipe(map((value) => {
|
|
40088
40234
|
hasSucceededOnce = true;
|
|
40235
|
+
skippedWhileHidden = false;
|
|
40089
40236
|
const now = new Date().toISOString();
|
|
40090
40237
|
onDiagnostic?.({
|
|
40091
40238
|
dataSourceId: ds.id,
|
|
@@ -40120,16 +40267,43 @@ class WidgetPageDataSourceRuntimeService {
|
|
|
40120
40267
|
}));
|
|
40121
40268
|
const stream$ = intervalMs > 0
|
|
40122
40269
|
? timer(0, intervalMs).pipe(takeUntil(destroy$), switchMap(() => {
|
|
40123
|
-
if (
|
|
40270
|
+
if (hasSucceededOnce &&
|
|
40271
|
+
typeof document !== 'undefined' &&
|
|
40124
40272
|
document.visibilityState === 'hidden') {
|
|
40273
|
+
skippedWhileHidden = true;
|
|
40125
40274
|
return EMPTY;
|
|
40126
40275
|
}
|
|
40127
40276
|
return runSingleFetch$();
|
|
40128
40277
|
}))
|
|
40129
40278
|
: runSingleFetch$().pipe(takeUntil(destroy$));
|
|
40130
40279
|
stream$.subscribe();
|
|
40280
|
+
if (intervalMs > 0) {
|
|
40281
|
+
visibilityCallbacks.push(() => {
|
|
40282
|
+
if (skippedWhileHidden) {
|
|
40283
|
+
skippedWhileHidden = false;
|
|
40284
|
+
runSingleFetch$().pipe(takeUntil(destroy$)).subscribe();
|
|
40285
|
+
}
|
|
40286
|
+
});
|
|
40287
|
+
}
|
|
40288
|
+
}
|
|
40289
|
+
const onVisibilityChange = () => {
|
|
40290
|
+
if (typeof document !== 'undefined' && document.visibilityState === 'visible') {
|
|
40291
|
+
for (const cb of visibilityCallbacks) {
|
|
40292
|
+
cb();
|
|
40293
|
+
}
|
|
40294
|
+
}
|
|
40295
|
+
};
|
|
40296
|
+
if (visibilityCallbacks.length > 0 &&
|
|
40297
|
+
typeof document !== 'undefined' &&
|
|
40298
|
+
typeof document.addEventListener === 'function') {
|
|
40299
|
+
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
40131
40300
|
}
|
|
40132
40301
|
return () => {
|
|
40302
|
+
if (visibilityCallbacks.length > 0 &&
|
|
40303
|
+
typeof document !== 'undefined' &&
|
|
40304
|
+
typeof document.removeEventListener === 'function') {
|
|
40305
|
+
document.removeEventListener('visibilitychange', onVisibilityChange);
|
|
40306
|
+
}
|
|
40133
40307
|
destroy$.next();
|
|
40134
40308
|
destroy$.complete();
|
|
40135
40309
|
};
|
|
@@ -45716,6 +45890,7 @@ class DynamicWidgetPageComponent {
|
|
|
45716
45890
|
pendingDataSourceUpdates = [];
|
|
45717
45891
|
isCoalescingDataSourceUpdates = false;
|
|
45718
45892
|
dataSourceRuntimeOverlay = new Map();
|
|
45893
|
+
dataSourceDiagnostics = new Map();
|
|
45719
45894
|
nestedWidgetAccessor = new NestedWidgetConfigAccessor();
|
|
45720
45895
|
settingsPanel = inject(SETTINGS_PANEL_BRIDGE, {
|
|
45721
45896
|
optional: true,
|
|
@@ -45807,6 +45982,7 @@ class DynamicWidgetPageComponent {
|
|
|
45807
45982
|
this.pendingDataSourceUpdates = [];
|
|
45808
45983
|
this.isCoalescingDataSourceUpdates = false;
|
|
45809
45984
|
this.dataSourceRuntimeOverlay.clear();
|
|
45985
|
+
this.dataSourceDiagnostics.clear();
|
|
45810
45986
|
this.persistenceGeneration++;
|
|
45811
45987
|
this.persistenceLoad?.unsubscribe();
|
|
45812
45988
|
this.persistenceMutation?.unsubscribe();
|
|
@@ -45891,6 +46067,9 @@ class DynamicWidgetPageComponent {
|
|
|
45891
46067
|
this.getDataSourcesSignature(this.pageDefinition?.dataSources) !==
|
|
45892
46068
|
this.currentDataSourcesSignature) {
|
|
45893
46069
|
this.dataSourceRuntimeOverlay.clear();
|
|
46070
|
+
this.dataSourceDiagnostics.clear();
|
|
46071
|
+
this.pendingDataSourceUpdates = [];
|
|
46072
|
+
this.currentDataSourcesSignature = null;
|
|
45894
46073
|
}
|
|
45895
46074
|
this.pageRuntime = this.buildStateRuntime(this.pageDefinition?.state, this.pageDefinition?.context);
|
|
45896
46075
|
this.pageState = this.pageRuntime.state;
|
|
@@ -45992,13 +46171,21 @@ class DynamicWidgetPageComponent {
|
|
|
45992
46171
|
const state = this.stateFromCompositionSnapshot(pageWithPatchedInputs.state, cycle.snapshot.state.primaryValues);
|
|
45993
46172
|
const runtimeStatePaths = Array.from(new Set((cycle.snapshot.state.changedPaths || []).filter((path) => typeof path === 'string')));
|
|
45994
46173
|
const updatedPrimaryStatePaths = runtimeStatePaths.filter((path) => !this.areStateValuesEqual(this.conn.extractByPath(this.stateRuntime.normalizeState(page.state).values || {}, path), this.conn.extractByPath(state.values || {}, path)));
|
|
46174
|
+
for (const changedPath of updatedPrimaryStatePaths) {
|
|
46175
|
+
this.dataSourceRuntimeOverlay.delete(changedPath);
|
|
46176
|
+
}
|
|
46177
|
+
const nextRuntime = this.buildStateRuntime(state, pageWithPatchedInputs.context);
|
|
45995
46178
|
let widgets = this.cloneWidgets(pageWithPatchedInputs.widgets || []);
|
|
45996
46179
|
const directDelivery = this.applyCompositionWidgetDeliveries(widgets, cycle);
|
|
45997
46180
|
widgets = directDelivery.widgets;
|
|
45998
|
-
const
|
|
46181
|
+
const effectiveCompositionState = {
|
|
46182
|
+
...cycle.snapshot.state,
|
|
46183
|
+
primaryValues: this.cloneStateValues(nextRuntime.primaryValues),
|
|
46184
|
+
derivedValues: this.cloneStateValues(nextRuntime.derivedValues),
|
|
46185
|
+
};
|
|
46186
|
+
const projectedWidgets = this.projectPersistentCompositionStateInputs(widgets, effectiveCompositionState, cycle.snapshot.generatedAt);
|
|
45999
46187
|
const stateProjectionChanged = !this.areStateValuesEqual(widgets, projectedWidgets);
|
|
46000
46188
|
widgets = projectedWidgets;
|
|
46001
|
-
const nextRuntime = this.buildStateRuntime(state, pageWithPatchedInputs.context);
|
|
46002
46189
|
if (this.isTransientOnlyCompositionCycle(cycle) &&
|
|
46003
46190
|
!updatedPrimaryStatePaths.length &&
|
|
46004
46191
|
!directDelivery.changed &&
|
|
@@ -46214,9 +46401,8 @@ class DynamicWidgetPageComponent {
|
|
|
46214
46401
|
};
|
|
46215
46402
|
}
|
|
46216
46403
|
getDataSourcesSignature(dataSources) {
|
|
46217
|
-
|
|
46218
|
-
|
|
46219
|
-
: null;
|
|
46404
|
+
const normalized = this.dataSourceRuntime.normalizeDataSources(dataSources);
|
|
46405
|
+
return normalized.length > 0 ? JSON.stringify(normalized) : null;
|
|
46220
46406
|
}
|
|
46221
46407
|
bootstrapCompositionAdapter(page) {
|
|
46222
46408
|
if (!page) {
|
|
@@ -46826,12 +47012,16 @@ class DynamicWidgetPageComponent {
|
|
|
46826
47012
|
return { page };
|
|
46827
47013
|
}
|
|
46828
47014
|
const state = this.stateFromCompositionSnapshot(page.state, cycle.snapshot.state.primaryValues);
|
|
47015
|
+
const runtime = this.buildStateRuntime(state, page.context);
|
|
46829
47016
|
let widgets = this.cloneWidgets(page.widgets || []);
|
|
46830
47017
|
widgets = this.applyCompositionWidgetDeliveries(widgets, cycle).widgets;
|
|
46831
47018
|
if (this.compositionDefinition) {
|
|
46832
|
-
widgets = this.projectPersistentCompositionStateInputs(widgets,
|
|
47019
|
+
widgets = this.projectPersistentCompositionStateInputs(widgets, {
|
|
47020
|
+
...cycle.snapshot.state,
|
|
47021
|
+
primaryValues: this.cloneStateValues(runtime.primaryValues),
|
|
47022
|
+
derivedValues: this.cloneStateValues(runtime.derivedValues),
|
|
47023
|
+
}, cycle.snapshot.generatedAt);
|
|
46833
47024
|
}
|
|
46834
|
-
const runtime = this.buildStateRuntime(state, page.context);
|
|
46835
47025
|
return {
|
|
46836
47026
|
page: { ...page, widgets, state },
|
|
46837
47027
|
runtime,
|
|
@@ -46948,10 +47138,14 @@ class DynamicWidgetPageComponent {
|
|
|
46948
47138
|
return;
|
|
46949
47139
|
}
|
|
46950
47140
|
const state = this.stateFromCompositionSnapshot(page.state, cycle.snapshot.state.primaryValues);
|
|
47141
|
+
const runtime = this.buildStateRuntime(state, page.context);
|
|
46951
47142
|
let widgets = this.cloneWidgets(page.widgets || []);
|
|
46952
47143
|
widgets = this.applyCompositionWidgetDeliveries(widgets, cycle).widgets;
|
|
46953
|
-
widgets = this.projectPersistentCompositionStateInputs(widgets,
|
|
46954
|
-
|
|
47144
|
+
widgets = this.projectPersistentCompositionStateInputs(widgets, {
|
|
47145
|
+
...cycle.snapshot.state,
|
|
47146
|
+
primaryValues: this.cloneStateValues(runtime.primaryValues),
|
|
47147
|
+
derivedValues: this.cloneStateValues(runtime.derivedValues),
|
|
47148
|
+
}, cycle.snapshot.generatedAt);
|
|
46955
47149
|
this.applyPageUpdate({ ...page, widgets, state }, true, runtime, false, true, false);
|
|
46956
47150
|
}
|
|
46957
47151
|
matchesRuntimeSourceRef(endpoint, sourceRef) {
|
|
@@ -48623,15 +48817,22 @@ class DynamicWidgetPageComponent {
|
|
|
48623
48817
|
themePreset: themePreset || undefined,
|
|
48624
48818
|
}, persist);
|
|
48625
48819
|
}
|
|
48626
|
-
applyAuthoringPageUpdate(next, persist = true, runtime
|
|
48820
|
+
applyAuthoringPageUpdate(next, persist = true, runtime, syncCompositionAdapter = true, skipStateWidgetProjection = false, emitUnchangedCanonicalPage = true) {
|
|
48627
48821
|
this.applyPageUpdate(next, persist, runtime, syncCompositionAdapter, skipStateWidgetProjection, emitUnchangedCanonicalPage);
|
|
48628
48822
|
if (this.authoredPageDefinition) {
|
|
48629
48823
|
this.pageAuthoringChange.emit(this.clonePageDefinition(this.authoredPageDefinition));
|
|
48630
48824
|
}
|
|
48631
48825
|
}
|
|
48632
|
-
applyPageUpdate(next, persist = true, runtime
|
|
48826
|
+
applyPageUpdate(next, persist = true, runtime, syncCompositionAdapter = true, skipStateWidgetProjection = false, emitUnchangedCanonicalPage = true) {
|
|
48633
48827
|
this.assertNoLegacyConnections(next);
|
|
48634
|
-
|
|
48828
|
+
if (this.getDataSourcesSignature(next.dataSources) !==
|
|
48829
|
+
this.currentDataSourcesSignature) {
|
|
48830
|
+
this.dataSourceRuntimeOverlay.clear();
|
|
48831
|
+
this.dataSourceDiagnostics.clear();
|
|
48832
|
+
this.pendingDataSourceUpdates = [];
|
|
48833
|
+
}
|
|
48834
|
+
const effectiveRuntime = runtime ?? this.buildStateRuntime(next.state, next.context);
|
|
48835
|
+
const normalized = { ...next, state: effectiveRuntime.state };
|
|
48635
48836
|
const normalizedWidgets = this.applyEditShellActions(normalized.widgets || []);
|
|
48636
48837
|
const bootstrapSnapshot = syncCompositionAdapter
|
|
48637
48838
|
? this.bootstrapCompositionAdapter(normalized)
|
|
@@ -48639,14 +48840,14 @@ class DynamicWidgetPageComponent {
|
|
|
48639
48840
|
const stateBoundWidgets = skipStateWidgetProjection
|
|
48640
48841
|
? normalizedWidgets
|
|
48641
48842
|
: bootstrapSnapshot
|
|
48642
|
-
? this.applyBootstrapCompositionHydration(normalizedWidgets, bootstrapSnapshot,
|
|
48843
|
+
? this.applyBootstrapCompositionHydration(normalizedWidgets, bootstrapSnapshot, effectiveRuntime)
|
|
48643
48844
|
: this.compositionDefinition
|
|
48644
48845
|
? this.compositionRuntime.projectStateWidgetInputs(this.compositionDefinition, {
|
|
48645
48846
|
widgets: normalizedWidgets,
|
|
48646
48847
|
state: {
|
|
48647
|
-
primaryValues: this.cloneStateValues(
|
|
48648
|
-
derivedValues: this.cloneStateValues(
|
|
48649
|
-
transientValues:
|
|
48848
|
+
primaryValues: this.cloneStateValues(effectiveRuntime.primaryValues),
|
|
48849
|
+
derivedValues: this.cloneStateValues(effectiveRuntime.derivedValues),
|
|
48850
|
+
transientValues: this.cloneStateValues(this.compositionRuntime.getSnapshot().state.transientValues),
|
|
48650
48851
|
changedPaths: [],
|
|
48651
48852
|
diagnostics: [],
|
|
48652
48853
|
},
|
|
@@ -48658,9 +48859,9 @@ class DynamicWidgetPageComponent {
|
|
|
48658
48859
|
});
|
|
48659
48860
|
this.pageDefinition = hydrated;
|
|
48660
48861
|
this.page = hydrated;
|
|
48661
|
-
this.pageState =
|
|
48662
|
-
this.pageRuntime =
|
|
48663
|
-
this.applyResponsivePresentation(hydrated, hydrated?.widgets || stateBoundWidgets,
|
|
48862
|
+
this.pageState = effectiveRuntime.state;
|
|
48863
|
+
this.pageRuntime = effectiveRuntime;
|
|
48864
|
+
this.applyResponsivePresentation(hydrated, hydrated?.widgets || stateBoundWidgets, effectiveRuntime);
|
|
48664
48865
|
this.restartDataSources(hydrated);
|
|
48665
48866
|
if (this.widgetEventBus) {
|
|
48666
48867
|
this.wiringSubscription?.unsubscribe();
|
|
@@ -48676,7 +48877,7 @@ class DynamicWidgetPageComponent {
|
|
|
48676
48877
|
if (authoredPageChanged || emitUnchangedCanonicalPage) {
|
|
48677
48878
|
this.pageChange.emit(canonicalPage);
|
|
48678
48879
|
}
|
|
48679
|
-
this.reportStateDiagnostics(
|
|
48880
|
+
this.reportStateDiagnostics(effectiveRuntime.diagnostics);
|
|
48680
48881
|
if (authoredPageChanged &&
|
|
48681
48882
|
persist &&
|
|
48682
48883
|
this.autoPersist &&
|
|
@@ -48730,7 +48931,7 @@ class DynamicWidgetPageComponent {
|
|
|
48730
48931
|
state: {
|
|
48731
48932
|
primaryValues: this.cloneStateValues(nextRuntime.primaryValues),
|
|
48732
48933
|
derivedValues: this.cloneStateValues(nextRuntime.derivedValues),
|
|
48733
|
-
transientValues:
|
|
48934
|
+
transientValues: this.cloneStateValues(this.compositionRuntime.getSnapshot().state.transientValues),
|
|
48734
48935
|
changedPaths: updates.map((u) => u.targetStatePath),
|
|
48735
48936
|
diagnostics: [],
|
|
48736
48937
|
},
|
|
@@ -48747,6 +48948,17 @@ class DynamicWidgetPageComponent {
|
|
|
48747
48948
|
this.reportStateDiagnostics(nextRuntime.diagnostics);
|
|
48748
48949
|
this.changeDetector.markForCheck();
|
|
48749
48950
|
}
|
|
48951
|
+
handleDataSourceDiagnostic(diagnostic) {
|
|
48952
|
+
if (this.destroyed) {
|
|
48953
|
+
return;
|
|
48954
|
+
}
|
|
48955
|
+
this.dataSourceDiagnostics.set(diagnostic.dataSourceId, diagnostic);
|
|
48956
|
+
if (diagnostic.status === 'error') {
|
|
48957
|
+
this.reportStateDiagnostics([
|
|
48958
|
+
`DataSource "${diagnostic.dataSourceId}" failed: ${diagnostic.error || 'unknown error'}`,
|
|
48959
|
+
]);
|
|
48960
|
+
}
|
|
48961
|
+
}
|
|
48750
48962
|
restartDataSources(page) {
|
|
48751
48963
|
const dataSources = page?.dataSources;
|
|
48752
48964
|
const signature = this.getDataSourcesSignature(dataSources);
|
|
@@ -48755,12 +48967,15 @@ class DynamicWidgetPageComponent {
|
|
|
48755
48967
|
}
|
|
48756
48968
|
this.currentDataSourcesSignature = signature;
|
|
48757
48969
|
this.dataSourceRuntimeOverlay.clear();
|
|
48970
|
+
this.dataSourceDiagnostics.clear();
|
|
48971
|
+
this.pendingDataSourceUpdates = [];
|
|
48758
48972
|
this.dataSourceTeardown?.();
|
|
48759
48973
|
this.dataSourceTeardown = undefined;
|
|
48760
|
-
|
|
48974
|
+
const normalizedDataSources = this.dataSourceRuntime.normalizeDataSources(dataSources);
|
|
48975
|
+
if (normalizedDataSources.length === 0) {
|
|
48761
48976
|
return;
|
|
48762
48977
|
}
|
|
48763
|
-
this.dataSourceTeardown = this.dataSourceRuntime.startDataSources(
|
|
48978
|
+
this.dataSourceTeardown = this.dataSourceRuntime.startDataSources(normalizedDataSources, (update) => this.handleDataSourceUpdate(update), (diagnostic) => this.handleDataSourceDiagnostic(diagnostic));
|
|
48764
48979
|
}
|
|
48765
48980
|
applyLayout(layout, grouping, deviceLayoutColumnsSelected = false) {
|
|
48766
48981
|
this.layout = layout;
|
|
@@ -49102,7 +49317,11 @@ class DynamicWidgetPageComponent {
|
|
|
49102
49317
|
}
|
|
49103
49318
|
return this.compositionRuntime.projectStateWidgetInputs(this.compositionDefinition, {
|
|
49104
49319
|
widgets,
|
|
49105
|
-
state:
|
|
49320
|
+
state: {
|
|
49321
|
+
...snapshot.state,
|
|
49322
|
+
primaryValues: this.cloneStateValues(this.pageRuntime.primaryValues),
|
|
49323
|
+
derivedValues: this.cloneStateValues(this.pageRuntime.derivedValues),
|
|
49324
|
+
},
|
|
49106
49325
|
now: snapshot.generatedAt,
|
|
49107
49326
|
}).widgets;
|
|
49108
49327
|
}
|
|
@@ -51240,7 +51459,13 @@ class DynamicWidgetPageComponent {
|
|
|
51240
51459
|
cloned.layout = { ...page.layout };
|
|
51241
51460
|
}
|
|
51242
51461
|
if (page.grouping) {
|
|
51243
|
-
cloned.grouping =
|
|
51462
|
+
cloned.grouping = this.cloneStateValues(page.grouping);
|
|
51463
|
+
}
|
|
51464
|
+
if (page.dataSources) {
|
|
51465
|
+
cloned.dataSources = this.cloneStateValues(page.dataSources);
|
|
51466
|
+
}
|
|
51467
|
+
if (page.composition) {
|
|
51468
|
+
cloned.composition = this.cloneStateValues(page.composition);
|
|
51244
51469
|
}
|
|
51245
51470
|
if (page.canvas) {
|
|
51246
51471
|
cloned.canvas = {
|
|
@@ -51251,16 +51476,20 @@ class DynamicWidgetPageComponent {
|
|
|
51251
51476
|
};
|
|
51252
51477
|
}
|
|
51253
51478
|
if (page.context) {
|
|
51254
|
-
cloned.context =
|
|
51479
|
+
cloned.context = this.cloneStateValues(page.context);
|
|
51255
51480
|
}
|
|
51256
51481
|
if (page.state) {
|
|
51257
51482
|
const stateObj = {
|
|
51258
|
-
values: page.state.values
|
|
51483
|
+
values: page.state.values
|
|
51484
|
+
? this.cloneStateValues(page.state.values)
|
|
51485
|
+
: {},
|
|
51259
51486
|
};
|
|
51260
|
-
if (page.state.schema !== undefined)
|
|
51261
|
-
stateObj.schema = page.state.schema;
|
|
51262
|
-
|
|
51263
|
-
|
|
51487
|
+
if (page.state.schema !== undefined) {
|
|
51488
|
+
stateObj.schema = this.cloneStateValues(page.state.schema);
|
|
51489
|
+
}
|
|
51490
|
+
if (page.state.derived !== undefined) {
|
|
51491
|
+
stateObj.derived = this.cloneStateValues(page.state.derived);
|
|
51492
|
+
}
|
|
51264
51493
|
cloned.state = stateObj;
|
|
51265
51494
|
}
|
|
51266
51495
|
return cloned;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/core",
|
|
3
|
-
"version": "10.0.0-rc.
|
|
3
|
+
"version": "10.0.0-rc.17",
|
|
4
4
|
"description": "Core library for Praxis UI Workspace: types, tokens, services and utilities shared across @praxisui/* packages.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/cdk": "^21.0.0",
|
package/types/praxisui-core.d.ts
CHANGED
|
@@ -6363,9 +6363,13 @@ declare class GenericCrudService<T, ID extends string | number = string | number
|
|
|
6363
6363
|
* @returns Observable com a entidade atualizada.
|
|
6364
6364
|
*/
|
|
6365
6365
|
update(id: ID, entity: T, options?: CrudOperationOptions): Observable<T>;
|
|
6366
|
+
getResourceVersion(id: ID, options?: CrudOperationOptions): string | null;
|
|
6367
|
+
setResourceVersion(id: ID, etag: string | null | undefined, options?: CrudOperationOptions): void;
|
|
6366
6368
|
updateResponse(id: ID, entity: T, options?: CrudOperationOptions): Observable<RestApiResponse<T>>;
|
|
6367
6369
|
private resourceVersionKey;
|
|
6368
6370
|
private captureResourceVersion;
|
|
6371
|
+
private normalizeEtagToken;
|
|
6372
|
+
private ensureEtagFormat;
|
|
6369
6373
|
/**
|
|
6370
6374
|
* Remove um registro pelo ID.
|
|
6371
6375
|
*
|
|
@@ -10840,6 +10844,9 @@ declare class ErrorMessageService {
|
|
|
10840
10844
|
getSubmitErrorMessage(error: unknown): string;
|
|
10841
10845
|
private fallbackMessage;
|
|
10842
10846
|
private normalizeDetails;
|
|
10847
|
+
private resolveVersionPreconditionCopy;
|
|
10848
|
+
private staleResourceVersionMessage;
|
|
10849
|
+
private resourceVersionRequiredMessage;
|
|
10843
10850
|
private objectValue;
|
|
10844
10851
|
private textValue;
|
|
10845
10852
|
private numberValue;
|
|
@@ -16232,6 +16239,8 @@ interface WidgetPageDataSourceDefinition {
|
|
|
16232
16239
|
kind?: WidgetPageDataSourceKind;
|
|
16233
16240
|
/** Caminho do recurso canônico no backend Praxis (ex: 'human-resources/funcionarios/stats/group-by'). */
|
|
16234
16241
|
resourcePath: string;
|
|
16242
|
+
/** Chave opcional do endpoint configurado em API_URL (padrão: 'default'). */
|
|
16243
|
+
endpointKey?: string;
|
|
16235
16244
|
/** Método HTTP utilizado (padrão: 'POST' para endpoints /stats, 'GET' para recursos padrão). */
|
|
16236
16245
|
method?: WidgetPageDataSourceMethod;
|
|
16237
16246
|
/** Parâmetros de consulta (query params para GET ou corpo da requisição para POST de analytics). */
|
|
@@ -18246,17 +18255,25 @@ declare class WidgetPageDataSourceRuntimeService {
|
|
|
18246
18255
|
/**
|
|
18247
18256
|
* Constrói a URL canônica completa para o resourcePath declarado no dataSource.
|
|
18248
18257
|
*/
|
|
18249
|
-
resolveUrl(resourcePath: string): string;
|
|
18258
|
+
resolveUrl(resourcePath: string, endpointKey?: string): string;
|
|
18250
18259
|
/**
|
|
18251
18260
|
* Executa uma única consulta para um DataSource e retorna o resultado transformado.
|
|
18252
18261
|
*/
|
|
18253
18262
|
fetchDataSource(dataSource: WidgetPageDataSourceDefinition): Observable<unknown>;
|
|
18254
18263
|
private executeRawRequest;
|
|
18264
|
+
/**
|
|
18265
|
+
* Normaliza `page.dataSources` aceitando tanto o formato canônico em Array quanto Object Map indexado por id.
|
|
18266
|
+
*/
|
|
18267
|
+
normalizeDataSources(dataSources: WidgetPageDataSourceDefinition[] | Record<string, Omit<WidgetPageDataSourceDefinition, 'id'> & {
|
|
18268
|
+
id?: string;
|
|
18269
|
+
}> | undefined | null): WidgetPageDataSourceDefinition[];
|
|
18255
18270
|
/**
|
|
18256
18271
|
* Inicia a orquestração reativa de todos os DataSources declarados em uma página dinâmica.
|
|
18257
18272
|
* Retorna uma função de teardown que cancela todas as requisições em voo e timers de polling.
|
|
18258
18273
|
*/
|
|
18259
|
-
startDataSources(dataSources: WidgetPageDataSourceDefinition[] |
|
|
18274
|
+
startDataSources(dataSources: WidgetPageDataSourceDefinition[] | Record<string, Omit<WidgetPageDataSourceDefinition, 'id'> & {
|
|
18275
|
+
id?: string;
|
|
18276
|
+
}> | undefined, onUpdate: (event: WidgetPageDataSourceUpdateEvent) => void, onDiagnostic?: (diagnostic: WidgetPageDataSourceDiagnostic) => void): () => void;
|
|
18260
18277
|
/**
|
|
18261
18278
|
* Transforma a resposta bruta do backend aplicando envelope canônico ou JsonLogic.
|
|
18262
18279
|
*/
|
|
@@ -18776,6 +18793,7 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
|
|
|
18776
18793
|
private pendingDataSourceUpdates;
|
|
18777
18794
|
private isCoalescingDataSourceUpdates;
|
|
18778
18795
|
private readonly dataSourceRuntimeOverlay;
|
|
18796
|
+
private readonly dataSourceDiagnostics;
|
|
18779
18797
|
private readonly nestedWidgetAccessor;
|
|
18780
18798
|
private readonly settingsPanel;
|
|
18781
18799
|
private readonly defaultShellEditor;
|
|
@@ -19007,6 +19025,7 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
|
|
|
19007
19025
|
private applyPageUpdate;
|
|
19008
19026
|
private handleDataSourceUpdate;
|
|
19009
19027
|
private flushPendingDataSourceUpdates;
|
|
19028
|
+
private handleDataSourceDiagnostic;
|
|
19010
19029
|
private restartDataSources;
|
|
19011
19030
|
private applyLayout;
|
|
19012
19031
|
private applyCanvasLayout;
|