@praxisui/core 10.0.0-rc.15 → 10.0.0-rc.16
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/ai/component-registry.json +2 -2
- package/fesm2022/praxisui-core.mjs +213 -31
- package/package.json +1 -1
- package/types/praxisui-core.d.ts +12 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-14T20:20:10.826Z",
|
|
4
4
|
"packageName": "@praxisui/core",
|
|
5
|
-
"packageVersion": "10.0.0-rc.
|
|
5
|
+
"packageVersion": "10.0.0-rc.16",
|
|
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
|
}
|
|
@@ -40073,6 +40183,7 @@ class WidgetPageDataSourceRuntimeService {
|
|
|
40073
40183
|
return () => { };
|
|
40074
40184
|
}
|
|
40075
40185
|
const destroy$ = new Subject();
|
|
40186
|
+
const visibilityCallbacks = [];
|
|
40076
40187
|
for (const ds of dataSources) {
|
|
40077
40188
|
if (ds.autoFetch === false) {
|
|
40078
40189
|
continue;
|
|
@@ -40080,12 +40191,14 @@ class WidgetPageDataSourceRuntimeService {
|
|
|
40080
40191
|
const targetPath = ds.targetStatePath || ds.id;
|
|
40081
40192
|
const intervalMs = ds.refreshIntervalMs ?? 0;
|
|
40082
40193
|
let hasSucceededOnce = false;
|
|
40194
|
+
let skippedWhileHidden = false;
|
|
40083
40195
|
onDiagnostic?.({
|
|
40084
40196
|
dataSourceId: ds.id,
|
|
40085
40197
|
status: 'loading',
|
|
40086
40198
|
});
|
|
40087
40199
|
const runSingleFetch$ = () => this.executeRawRequest(ds).pipe(map((value) => {
|
|
40088
40200
|
hasSucceededOnce = true;
|
|
40201
|
+
skippedWhileHidden = false;
|
|
40089
40202
|
const now = new Date().toISOString();
|
|
40090
40203
|
onDiagnostic?.({
|
|
40091
40204
|
dataSourceId: ds.id,
|
|
@@ -40120,16 +40233,43 @@ class WidgetPageDataSourceRuntimeService {
|
|
|
40120
40233
|
}));
|
|
40121
40234
|
const stream$ = intervalMs > 0
|
|
40122
40235
|
? timer(0, intervalMs).pipe(takeUntil(destroy$), switchMap(() => {
|
|
40123
|
-
if (
|
|
40236
|
+
if (hasSucceededOnce &&
|
|
40237
|
+
typeof document !== 'undefined' &&
|
|
40124
40238
|
document.visibilityState === 'hidden') {
|
|
40239
|
+
skippedWhileHidden = true;
|
|
40125
40240
|
return EMPTY;
|
|
40126
40241
|
}
|
|
40127
40242
|
return runSingleFetch$();
|
|
40128
40243
|
}))
|
|
40129
40244
|
: runSingleFetch$().pipe(takeUntil(destroy$));
|
|
40130
40245
|
stream$.subscribe();
|
|
40246
|
+
if (intervalMs > 0) {
|
|
40247
|
+
visibilityCallbacks.push(() => {
|
|
40248
|
+
if (skippedWhileHidden) {
|
|
40249
|
+
skippedWhileHidden = false;
|
|
40250
|
+
runSingleFetch$().pipe(takeUntil(destroy$)).subscribe();
|
|
40251
|
+
}
|
|
40252
|
+
});
|
|
40253
|
+
}
|
|
40254
|
+
}
|
|
40255
|
+
const onVisibilityChange = () => {
|
|
40256
|
+
if (typeof document !== 'undefined' && document.visibilityState === 'visible') {
|
|
40257
|
+
for (const cb of visibilityCallbacks) {
|
|
40258
|
+
cb();
|
|
40259
|
+
}
|
|
40260
|
+
}
|
|
40261
|
+
};
|
|
40262
|
+
if (visibilityCallbacks.length > 0 &&
|
|
40263
|
+
typeof document !== 'undefined' &&
|
|
40264
|
+
typeof document.addEventListener === 'function') {
|
|
40265
|
+
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
40131
40266
|
}
|
|
40132
40267
|
return () => {
|
|
40268
|
+
if (visibilityCallbacks.length > 0 &&
|
|
40269
|
+
typeof document !== 'undefined' &&
|
|
40270
|
+
typeof document.removeEventListener === 'function') {
|
|
40271
|
+
document.removeEventListener('visibilitychange', onVisibilityChange);
|
|
40272
|
+
}
|
|
40133
40273
|
destroy$.next();
|
|
40134
40274
|
destroy$.complete();
|
|
40135
40275
|
};
|
|
@@ -45716,6 +45856,7 @@ class DynamicWidgetPageComponent {
|
|
|
45716
45856
|
pendingDataSourceUpdates = [];
|
|
45717
45857
|
isCoalescingDataSourceUpdates = false;
|
|
45718
45858
|
dataSourceRuntimeOverlay = new Map();
|
|
45859
|
+
dataSourceDiagnostics = new Map();
|
|
45719
45860
|
nestedWidgetAccessor = new NestedWidgetConfigAccessor();
|
|
45720
45861
|
settingsPanel = inject(SETTINGS_PANEL_BRIDGE, {
|
|
45721
45862
|
optional: true,
|
|
@@ -45807,6 +45948,7 @@ class DynamicWidgetPageComponent {
|
|
|
45807
45948
|
this.pendingDataSourceUpdates = [];
|
|
45808
45949
|
this.isCoalescingDataSourceUpdates = false;
|
|
45809
45950
|
this.dataSourceRuntimeOverlay.clear();
|
|
45951
|
+
this.dataSourceDiagnostics.clear();
|
|
45810
45952
|
this.persistenceGeneration++;
|
|
45811
45953
|
this.persistenceLoad?.unsubscribe();
|
|
45812
45954
|
this.persistenceMutation?.unsubscribe();
|
|
@@ -45891,6 +46033,8 @@ class DynamicWidgetPageComponent {
|
|
|
45891
46033
|
this.getDataSourcesSignature(this.pageDefinition?.dataSources) !==
|
|
45892
46034
|
this.currentDataSourcesSignature) {
|
|
45893
46035
|
this.dataSourceRuntimeOverlay.clear();
|
|
46036
|
+
this.dataSourceDiagnostics.clear();
|
|
46037
|
+
this.currentDataSourcesSignature = null;
|
|
45894
46038
|
}
|
|
45895
46039
|
this.pageRuntime = this.buildStateRuntime(this.pageDefinition?.state, this.pageDefinition?.context);
|
|
45896
46040
|
this.pageState = this.pageRuntime.state;
|
|
@@ -45992,13 +46136,21 @@ class DynamicWidgetPageComponent {
|
|
|
45992
46136
|
const state = this.stateFromCompositionSnapshot(pageWithPatchedInputs.state, cycle.snapshot.state.primaryValues);
|
|
45993
46137
|
const runtimeStatePaths = Array.from(new Set((cycle.snapshot.state.changedPaths || []).filter((path) => typeof path === 'string')));
|
|
45994
46138
|
const updatedPrimaryStatePaths = runtimeStatePaths.filter((path) => !this.areStateValuesEqual(this.conn.extractByPath(this.stateRuntime.normalizeState(page.state).values || {}, path), this.conn.extractByPath(state.values || {}, path)));
|
|
46139
|
+
for (const changedPath of updatedPrimaryStatePaths) {
|
|
46140
|
+
this.dataSourceRuntimeOverlay.delete(changedPath);
|
|
46141
|
+
}
|
|
46142
|
+
const nextRuntime = this.buildStateRuntime(state, pageWithPatchedInputs.context);
|
|
45995
46143
|
let widgets = this.cloneWidgets(pageWithPatchedInputs.widgets || []);
|
|
45996
46144
|
const directDelivery = this.applyCompositionWidgetDeliveries(widgets, cycle);
|
|
45997
46145
|
widgets = directDelivery.widgets;
|
|
45998
|
-
const
|
|
46146
|
+
const effectiveCompositionState = {
|
|
46147
|
+
...cycle.snapshot.state,
|
|
46148
|
+
primaryValues: this.cloneStateValues(nextRuntime.primaryValues),
|
|
46149
|
+
derivedValues: this.cloneStateValues(nextRuntime.derivedValues),
|
|
46150
|
+
};
|
|
46151
|
+
const projectedWidgets = this.projectPersistentCompositionStateInputs(widgets, effectiveCompositionState, cycle.snapshot.generatedAt);
|
|
45999
46152
|
const stateProjectionChanged = !this.areStateValuesEqual(widgets, projectedWidgets);
|
|
46000
46153
|
widgets = projectedWidgets;
|
|
46001
|
-
const nextRuntime = this.buildStateRuntime(state, pageWithPatchedInputs.context);
|
|
46002
46154
|
if (this.isTransientOnlyCompositionCycle(cycle) &&
|
|
46003
46155
|
!updatedPrimaryStatePaths.length &&
|
|
46004
46156
|
!directDelivery.changed &&
|
|
@@ -46826,12 +46978,16 @@ class DynamicWidgetPageComponent {
|
|
|
46826
46978
|
return { page };
|
|
46827
46979
|
}
|
|
46828
46980
|
const state = this.stateFromCompositionSnapshot(page.state, cycle.snapshot.state.primaryValues);
|
|
46981
|
+
const runtime = this.buildStateRuntime(state, page.context);
|
|
46829
46982
|
let widgets = this.cloneWidgets(page.widgets || []);
|
|
46830
46983
|
widgets = this.applyCompositionWidgetDeliveries(widgets, cycle).widgets;
|
|
46831
46984
|
if (this.compositionDefinition) {
|
|
46832
|
-
widgets = this.projectPersistentCompositionStateInputs(widgets,
|
|
46985
|
+
widgets = this.projectPersistentCompositionStateInputs(widgets, {
|
|
46986
|
+
...cycle.snapshot.state,
|
|
46987
|
+
primaryValues: this.cloneStateValues(runtime.primaryValues),
|
|
46988
|
+
derivedValues: this.cloneStateValues(runtime.derivedValues),
|
|
46989
|
+
}, cycle.snapshot.generatedAt);
|
|
46833
46990
|
}
|
|
46834
|
-
const runtime = this.buildStateRuntime(state, page.context);
|
|
46835
46991
|
return {
|
|
46836
46992
|
page: { ...page, widgets, state },
|
|
46837
46993
|
runtime,
|
|
@@ -46948,10 +47104,14 @@ class DynamicWidgetPageComponent {
|
|
|
46948
47104
|
return;
|
|
46949
47105
|
}
|
|
46950
47106
|
const state = this.stateFromCompositionSnapshot(page.state, cycle.snapshot.state.primaryValues);
|
|
47107
|
+
const runtime = this.buildStateRuntime(state, page.context);
|
|
46951
47108
|
let widgets = this.cloneWidgets(page.widgets || []);
|
|
46952
47109
|
widgets = this.applyCompositionWidgetDeliveries(widgets, cycle).widgets;
|
|
46953
|
-
widgets = this.projectPersistentCompositionStateInputs(widgets,
|
|
46954
|
-
|
|
47110
|
+
widgets = this.projectPersistentCompositionStateInputs(widgets, {
|
|
47111
|
+
...cycle.snapshot.state,
|
|
47112
|
+
primaryValues: this.cloneStateValues(runtime.primaryValues),
|
|
47113
|
+
derivedValues: this.cloneStateValues(runtime.derivedValues),
|
|
47114
|
+
}, cycle.snapshot.generatedAt);
|
|
46955
47115
|
this.applyPageUpdate({ ...page, widgets, state }, true, runtime, false, true, false);
|
|
46956
47116
|
}
|
|
46957
47117
|
matchesRuntimeSourceRef(endpoint, sourceRef) {
|
|
@@ -48646,7 +48806,7 @@ class DynamicWidgetPageComponent {
|
|
|
48646
48806
|
state: {
|
|
48647
48807
|
primaryValues: this.cloneStateValues(runtime.primaryValues),
|
|
48648
48808
|
derivedValues: this.cloneStateValues(runtime.derivedValues),
|
|
48649
|
-
transientValues:
|
|
48809
|
+
transientValues: this.cloneStateValues(this.compositionRuntime.getSnapshot().state.transientValues),
|
|
48650
48810
|
changedPaths: [],
|
|
48651
48811
|
diagnostics: [],
|
|
48652
48812
|
},
|
|
@@ -48730,7 +48890,7 @@ class DynamicWidgetPageComponent {
|
|
|
48730
48890
|
state: {
|
|
48731
48891
|
primaryValues: this.cloneStateValues(nextRuntime.primaryValues),
|
|
48732
48892
|
derivedValues: this.cloneStateValues(nextRuntime.derivedValues),
|
|
48733
|
-
transientValues:
|
|
48893
|
+
transientValues: this.cloneStateValues(this.compositionRuntime.getSnapshot().state.transientValues),
|
|
48734
48894
|
changedPaths: updates.map((u) => u.targetStatePath),
|
|
48735
48895
|
diagnostics: [],
|
|
48736
48896
|
},
|
|
@@ -48747,6 +48907,17 @@ class DynamicWidgetPageComponent {
|
|
|
48747
48907
|
this.reportStateDiagnostics(nextRuntime.diagnostics);
|
|
48748
48908
|
this.changeDetector.markForCheck();
|
|
48749
48909
|
}
|
|
48910
|
+
handleDataSourceDiagnostic(diagnostic) {
|
|
48911
|
+
if (this.destroyed) {
|
|
48912
|
+
return;
|
|
48913
|
+
}
|
|
48914
|
+
this.dataSourceDiagnostics.set(diagnostic.dataSourceId, diagnostic);
|
|
48915
|
+
if (diagnostic.status === 'error') {
|
|
48916
|
+
this.reportStateDiagnostics([
|
|
48917
|
+
`DataSource "${diagnostic.dataSourceId}" failed: ${diagnostic.error || 'unknown error'}`,
|
|
48918
|
+
]);
|
|
48919
|
+
}
|
|
48920
|
+
}
|
|
48750
48921
|
restartDataSources(page) {
|
|
48751
48922
|
const dataSources = page?.dataSources;
|
|
48752
48923
|
const signature = this.getDataSourcesSignature(dataSources);
|
|
@@ -48755,12 +48926,13 @@ class DynamicWidgetPageComponent {
|
|
|
48755
48926
|
}
|
|
48756
48927
|
this.currentDataSourcesSignature = signature;
|
|
48757
48928
|
this.dataSourceRuntimeOverlay.clear();
|
|
48929
|
+
this.dataSourceDiagnostics.clear();
|
|
48758
48930
|
this.dataSourceTeardown?.();
|
|
48759
48931
|
this.dataSourceTeardown = undefined;
|
|
48760
48932
|
if (!dataSources || dataSources.length === 0) {
|
|
48761
48933
|
return;
|
|
48762
48934
|
}
|
|
48763
|
-
this.dataSourceTeardown = this.dataSourceRuntime.startDataSources(dataSources, (update) => this.handleDataSourceUpdate(update));
|
|
48935
|
+
this.dataSourceTeardown = this.dataSourceRuntime.startDataSources(dataSources, (update) => this.handleDataSourceUpdate(update), (diagnostic) => this.handleDataSourceDiagnostic(diagnostic));
|
|
48764
48936
|
}
|
|
48765
48937
|
applyLayout(layout, grouping, deviceLayoutColumnsSelected = false) {
|
|
48766
48938
|
this.layout = layout;
|
|
@@ -51240,7 +51412,13 @@ class DynamicWidgetPageComponent {
|
|
|
51240
51412
|
cloned.layout = { ...page.layout };
|
|
51241
51413
|
}
|
|
51242
51414
|
if (page.grouping) {
|
|
51243
|
-
cloned.grouping =
|
|
51415
|
+
cloned.grouping = this.cloneStateValues(page.grouping);
|
|
51416
|
+
}
|
|
51417
|
+
if (page.dataSources) {
|
|
51418
|
+
cloned.dataSources = this.cloneStateValues(page.dataSources);
|
|
51419
|
+
}
|
|
51420
|
+
if (page.composition) {
|
|
51421
|
+
cloned.composition = this.cloneStateValues(page.composition);
|
|
51244
51422
|
}
|
|
51245
51423
|
if (page.canvas) {
|
|
51246
51424
|
cloned.canvas = {
|
|
@@ -51251,16 +51429,20 @@ class DynamicWidgetPageComponent {
|
|
|
51251
51429
|
};
|
|
51252
51430
|
}
|
|
51253
51431
|
if (page.context) {
|
|
51254
|
-
cloned.context =
|
|
51432
|
+
cloned.context = this.cloneStateValues(page.context);
|
|
51255
51433
|
}
|
|
51256
51434
|
if (page.state) {
|
|
51257
51435
|
const stateObj = {
|
|
51258
|
-
values: page.state.values
|
|
51436
|
+
values: page.state.values
|
|
51437
|
+
? this.cloneStateValues(page.state.values)
|
|
51438
|
+
: {},
|
|
51259
51439
|
};
|
|
51260
|
-
if (page.state.schema !== undefined)
|
|
51261
|
-
stateObj.schema = page.state.schema;
|
|
51262
|
-
|
|
51263
|
-
|
|
51440
|
+
if (page.state.schema !== undefined) {
|
|
51441
|
+
stateObj.schema = this.cloneStateValues(page.state.schema);
|
|
51442
|
+
}
|
|
51443
|
+
if (page.state.derived !== undefined) {
|
|
51444
|
+
stateObj.derived = this.cloneStateValues(page.state.derived);
|
|
51445
|
+
}
|
|
51264
51446
|
cloned.state = stateObj;
|
|
51265
51447
|
}
|
|
51266
51448
|
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.16",
|
|
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,7 +18255,7 @@ 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
|
*/
|
|
@@ -18776,6 +18785,7 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
|
|
|
18776
18785
|
private pendingDataSourceUpdates;
|
|
18777
18786
|
private isCoalescingDataSourceUpdates;
|
|
18778
18787
|
private readonly dataSourceRuntimeOverlay;
|
|
18788
|
+
private readonly dataSourceDiagnostics;
|
|
18779
18789
|
private readonly nestedWidgetAccessor;
|
|
18780
18790
|
private readonly settingsPanel;
|
|
18781
18791
|
private readonly defaultShellEditor;
|
|
@@ -19007,6 +19017,7 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
|
|
|
19007
19017
|
private applyPageUpdate;
|
|
19008
19018
|
private handleDataSourceUpdate;
|
|
19009
19019
|
private flushPendingDataSourceUpdates;
|
|
19020
|
+
private handleDataSourceDiagnostic;
|
|
19010
19021
|
private restartDataSources;
|
|
19011
19022
|
private applyLayout;
|
|
19012
19023
|
private applyCanvasLayout;
|