@praxisui/crud 10.0.0-rc.16 → 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 +3 -1
- package/ai/component-registry.json +2 -2
- package/fesm2022/praxisui-crud.mjs +73 -20
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -365,7 +365,9 @@ and materializes them in the contextual bulk selection toolbar:
|
|
|
365
365
|
executions until terminal state (`COMPLETED`, `COMPLETED_WITH_ERRORS`,
|
|
366
366
|
`CANCELLED`, `STOPPED`, `RECONCILIATION_REQUIRED`), aggregates all rejection
|
|
367
367
|
categories (`denied`, `invalid`, `conflict`, `notProcessed`, `unknown`),
|
|
368
|
-
clears table selection
|
|
368
|
+
clears table selection on full success or deselects only confirmed items on
|
|
369
|
+
partial outcomes so rejected/unprocessed rows remain selected across
|
|
370
|
+
`persistOnDataUpdate: true` table refreshes, and re-fetches capabilities
|
|
369
371
|
when `refresh.capabilities === true`.
|
|
370
372
|
|
|
371
373
|
Unavailable bulk operations (`availability.allowed === false`) remain visible
|
|
@@ -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/crud",
|
|
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": 2,
|
|
@@ -522,6 +522,7 @@ class PraxisBulkOperationDialogComponent {
|
|
|
522
522
|
this.dialogRef.close({
|
|
523
523
|
success: isSuccess,
|
|
524
524
|
execution: exec,
|
|
525
|
+
results: this.executionItems(),
|
|
525
526
|
});
|
|
526
527
|
}
|
|
527
528
|
onCancel() {
|
|
@@ -1771,6 +1772,7 @@ class PraxisBulkEditDialogComponent {
|
|
|
1771
1772
|
this.dialogRef.close({
|
|
1772
1773
|
success: isSuccess,
|
|
1773
1774
|
execution: exec,
|
|
1775
|
+
results: this.executionItems(),
|
|
1774
1776
|
});
|
|
1775
1777
|
}
|
|
1776
1778
|
onCancel() {
|
|
@@ -7227,8 +7229,21 @@ class PraxisCrudComponent {
|
|
|
7227
7229
|
this.openingActionLabel.set(this.resolveOpeningActionLabel(action, event));
|
|
7228
7230
|
try {
|
|
7229
7231
|
let resolvedBulk = this.resolveSyncBulkExecutionContractForAction(action, normalizedAction, configAction, crudAction, tableBulkAction);
|
|
7230
|
-
if (!resolvedBulk.contract
|
|
7231
|
-
resolvedBulk
|
|
7232
|
+
if ((!resolvedBulk.contract ||
|
|
7233
|
+
(!resolvedBulk.catalogAction &&
|
|
7234
|
+
resolvedBulk.contract.mode === 'DOMAIN_COMMAND' &&
|
|
7235
|
+
!configAction?.requestSchemaId &&
|
|
7236
|
+
!configAction?.commandParameterDescriptors &&
|
|
7237
|
+
!crudAction?.requestSchemaId)) &&
|
|
7238
|
+
this.tableCollectionLinks &&
|
|
7239
|
+
(!crudAction || !this.hasExplicitOpenBinding(crudAction))) {
|
|
7240
|
+
const asyncBulk = await this.resolveAsyncDiscoveredBulkContractForAction(action, normalizedAction);
|
|
7241
|
+
if (asyncBulk.contract || asyncBulk.catalogAction) {
|
|
7242
|
+
resolvedBulk = {
|
|
7243
|
+
contract: resolvedBulk.contract ?? asyncBulk.contract,
|
|
7244
|
+
catalogAction: resolvedBulk.catalogAction ?? asyncBulk.catalogAction,
|
|
7245
|
+
};
|
|
7246
|
+
}
|
|
7232
7247
|
}
|
|
7233
7248
|
const bulkContract = resolvedBulk.contract;
|
|
7234
7249
|
const discoveredCatalogAction = resolvedBulk.catalogAction;
|
|
@@ -7239,14 +7254,22 @@ class PraxisCrudComponent {
|
|
|
7239
7254
|
this.snack.open(`A seleção atual (${selectedCount} itens) excede o limite máximo permitido (${maxTargets} itens por lote).`, undefined, { duration: 4000 });
|
|
7240
7255
|
return;
|
|
7241
7256
|
}
|
|
7242
|
-
const
|
|
7257
|
+
const resourceVersionPrecondition = discoveredCatalogAction?.execution?.preconditions?.resourceVersion ??
|
|
7258
|
+
configAction?.execution?.preconditions?.resourceVersion ??
|
|
7259
|
+
crudAction?.execution?.preconditions?.resourceVersion ??
|
|
7260
|
+
bulkContract?.preconditions?.resourceVersion;
|
|
7261
|
+
const requiresResourceVersion = resourceVersionPrecondition !== 'NONE';
|
|
7243
7262
|
const targets = Array.isArray(rawTargets) && rawTargets.length > 0
|
|
7244
7263
|
? rawTargets
|
|
7245
|
-
: await this.resolveBulkTargetsFromRows(rows, requiresResourceVersion);
|
|
7264
|
+
: await this.resolveBulkTargetsFromRows(rows, requiresResourceVersion, resourcePath);
|
|
7246
7265
|
if (!targets.length) {
|
|
7247
7266
|
this.snack.open('Nenhum registro selecionado para a operação em lote.', undefined, { duration: 3000 });
|
|
7248
7267
|
return;
|
|
7249
7268
|
}
|
|
7269
|
+
const refreshPolicy = discoveredCatalogAction?.execution?.refresh ??
|
|
7270
|
+
configAction?.execution?.refresh ??
|
|
7271
|
+
crudAction?.execution?.refresh ??
|
|
7272
|
+
bulkContract?.refresh;
|
|
7250
7273
|
const columns = this.table?.config?.columns?.length
|
|
7251
7274
|
? this.table.config.columns
|
|
7252
7275
|
: this.effectiveTableConfig?.columns;
|
|
@@ -7277,7 +7300,7 @@ class PraxisCrudComponent {
|
|
|
7277
7300
|
.afterClosed()
|
|
7278
7301
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
7279
7302
|
.subscribe((res) => {
|
|
7280
|
-
this.handleBulkDialogResult(res,
|
|
7303
|
+
this.handleBulkDialogResult(res, refreshPolicy, 'Atualização em lote concluída com sucesso.');
|
|
7281
7304
|
});
|
|
7282
7305
|
return;
|
|
7283
7306
|
}
|
|
@@ -7314,7 +7337,7 @@ class PraxisCrudComponent {
|
|
|
7314
7337
|
.afterClosed()
|
|
7315
7338
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
7316
7339
|
.subscribe((res) => {
|
|
7317
|
-
this.handleBulkDialogResult(res,
|
|
7340
|
+
this.handleBulkDialogResult(res, refreshPolicy, 'Operação em lote executada com sucesso.');
|
|
7318
7341
|
});
|
|
7319
7342
|
return;
|
|
7320
7343
|
}
|
|
@@ -7331,6 +7354,15 @@ class PraxisCrudComponent {
|
|
|
7331
7354
|
}
|
|
7332
7355
|
handleBulkDialogResult(res, refreshPolicy, defaultSuccessMessage) {
|
|
7333
7356
|
const exec = res?.execution;
|
|
7357
|
+
const confirmedIds = Array.isArray(res?.results)
|
|
7358
|
+
? new Set(res.results
|
|
7359
|
+
.filter((item) => (item?.status === 'CONFIRMED' ||
|
|
7360
|
+
item?.status === 'UNCHANGED' ||
|
|
7361
|
+
item?.outcome === 'CONFIRMED' ||
|
|
7362
|
+
item?.outcome === 'UNCHANGED') &&
|
|
7363
|
+
item?.id != null)
|
|
7364
|
+
.map((item) => String(item.id)))
|
|
7365
|
+
: undefined;
|
|
7334
7366
|
if (exec && exec.status) {
|
|
7335
7367
|
const status = exec.status;
|
|
7336
7368
|
const confirmed = exec.totals?.['confirmed'] ?? 0;
|
|
@@ -7345,13 +7377,13 @@ class PraxisCrudComponent {
|
|
|
7345
7377
|
return;
|
|
7346
7378
|
}
|
|
7347
7379
|
if (status === 'COMPLETED_WITH_ERRORS' || (status === 'COMPLETED' && rejected > 0)) {
|
|
7348
|
-
this.handleBulkExecutionCompleted(refreshPolicy, false);
|
|
7380
|
+
this.handleBulkExecutionCompleted(refreshPolicy, false, confirmedIds);
|
|
7349
7381
|
this.snack.open(`Operação em lote concluída parcialmente (${confirmed} efetivado(s), ${rejected} com restrição).`, undefined, { duration: 4000 });
|
|
7350
7382
|
return;
|
|
7351
7383
|
}
|
|
7352
7384
|
if (status === 'CANCELLED') {
|
|
7353
7385
|
if (confirmed > 0) {
|
|
7354
|
-
this.handleBulkExecutionCompleted(refreshPolicy, false);
|
|
7386
|
+
this.handleBulkExecutionCompleted(refreshPolicy, false, confirmedIds);
|
|
7355
7387
|
}
|
|
7356
7388
|
this.snack.open(confirmed > 0
|
|
7357
7389
|
? `Execução em lote cancelada após efetivar ${confirmed} registro(s).`
|
|
@@ -7360,7 +7392,7 @@ class PraxisCrudComponent {
|
|
|
7360
7392
|
}
|
|
7361
7393
|
if (status === 'STOPPED' || status === 'RECONCILIATION_REQUIRED') {
|
|
7362
7394
|
if (confirmed > 0 || status === 'RECONCILIATION_REQUIRED') {
|
|
7363
|
-
this.handleBulkExecutionCompleted(refreshPolicy, false);
|
|
7395
|
+
this.handleBulkExecutionCompleted(refreshPolicy, false, confirmedIds);
|
|
7364
7396
|
}
|
|
7365
7397
|
this.snack.open(status === 'RECONCILIATION_REQUIRED'
|
|
7366
7398
|
? 'Execução em lote exige reconciliação. Verifique os diagnósticos.'
|
|
@@ -7373,7 +7405,7 @@ class PraxisCrudComponent {
|
|
|
7373
7405
|
this.snack.open(defaultSuccessMessage, undefined, { duration: 3000 });
|
|
7374
7406
|
}
|
|
7375
7407
|
}
|
|
7376
|
-
handleBulkExecutionCompleted(refreshPolicy, clearSelection = true) {
|
|
7408
|
+
handleBulkExecutionCompleted(refreshPolicy, clearSelection = true, confirmedIds) {
|
|
7377
7409
|
if (clearSelection) {
|
|
7378
7410
|
try {
|
|
7379
7411
|
this.table?.clearSelection?.();
|
|
@@ -7383,6 +7415,23 @@ class PraxisCrudComponent {
|
|
|
7383
7415
|
// Best-effort table selection cleanup
|
|
7384
7416
|
}
|
|
7385
7417
|
}
|
|
7418
|
+
else if (confirmedIds && confirmedIds.size > 0) {
|
|
7419
|
+
try {
|
|
7420
|
+
const selectionModel = this.table?.selection;
|
|
7421
|
+
if (selectionModel && Array.isArray(selectionModel.selected)) {
|
|
7422
|
+
const rowsToDeselect = selectionModel.selected.filter((row) => {
|
|
7423
|
+
const id = this.resolveRowResourceId(row);
|
|
7424
|
+
return id != null && confirmedIds.has(String(id));
|
|
7425
|
+
});
|
|
7426
|
+
if (rowsToDeselect.length > 0 && typeof selectionModel.deselect === 'function') {
|
|
7427
|
+
selectionModel.deselect(...rowsToDeselect);
|
|
7428
|
+
}
|
|
7429
|
+
}
|
|
7430
|
+
}
|
|
7431
|
+
catch {
|
|
7432
|
+
// Best-effort partial selection reconciliation
|
|
7433
|
+
}
|
|
7434
|
+
}
|
|
7386
7435
|
if (refreshPolicy?.collection !== false) {
|
|
7387
7436
|
this.refreshTable();
|
|
7388
7437
|
}
|
|
@@ -7447,12 +7496,6 @@ class PraxisCrudComponent {
|
|
|
7447
7496
|
return results;
|
|
7448
7497
|
}
|
|
7449
7498
|
resolveSyncBulkExecutionContractForAction(action, normalizedAction, configAction, crudAction, tableBulkAction) {
|
|
7450
|
-
const direct = configAction?.execution?.bulk ||
|
|
7451
|
-
crudAction?.execution?.bulk ||
|
|
7452
|
-
tableBulkAction?.execution?.bulk;
|
|
7453
|
-
if (direct) {
|
|
7454
|
-
return { contract: direct };
|
|
7455
|
-
}
|
|
7456
7499
|
const matchKey = (candidate) => {
|
|
7457
7500
|
const id = String(candidate?.id || candidate?.action || candidate?.operationId || '').trim();
|
|
7458
7501
|
const norm = this.normalizeCrudActionName(id).toLowerCase();
|
|
@@ -7461,8 +7504,12 @@ class PraxisCrudComponent {
|
|
|
7461
7504
|
String(candidate?.operationId || '').trim() === action);
|
|
7462
7505
|
};
|
|
7463
7506
|
const capAction = (this.collectionCapabilities?.actions || []).find((a) => matchKey(a) && a.execution?.bulk);
|
|
7464
|
-
|
|
7465
|
-
|
|
7507
|
+
const direct = configAction?.execution?.bulk ||
|
|
7508
|
+
crudAction?.execution?.bulk ||
|
|
7509
|
+
tableBulkAction?.execution?.bulk ||
|
|
7510
|
+
capAction?.execution?.bulk;
|
|
7511
|
+
if (direct) {
|
|
7512
|
+
return { contract: direct, ...(capAction ? { catalogAction: capAction } : {}) };
|
|
7466
7513
|
}
|
|
7467
7514
|
const capOp = Object.values(this.collectionCapabilities?.operations || {}).find((op) => matchKey(op) && op?.bulk);
|
|
7468
7515
|
if (capOp?.bulk) {
|
|
@@ -9022,7 +9069,7 @@ class PraxisCrudComponent {
|
|
|
9022
9069
|
allowSelectAll: prevSelection?.allowSelectAll ?? true,
|
|
9023
9070
|
checkboxPosition: prevSelection?.checkboxPosition || 'start',
|
|
9024
9071
|
persistSelection: prevSelection?.persistSelection ?? true,
|
|
9025
|
-
persistOnDataUpdate: prevSelection?.persistOnDataUpdate ??
|
|
9072
|
+
persistOnDataUpdate: prevSelection?.persistOnDataUpdate ?? true,
|
|
9026
9073
|
};
|
|
9027
9074
|
}
|
|
9028
9075
|
changed = true;
|
|
@@ -9339,6 +9386,12 @@ class PraxisCrudComponent {
|
|
|
9339
9386
|
items.push({
|
|
9340
9387
|
id: action.id,
|
|
9341
9388
|
label: action.title || action.id,
|
|
9389
|
+
title: action.title || action.id,
|
|
9390
|
+
description: action.description,
|
|
9391
|
+
operationId: action.operationId,
|
|
9392
|
+
requestSchemaId: action.requestSchemaId,
|
|
9393
|
+
requestSchemaUrl: action.requestSchemaUrl,
|
|
9394
|
+
commandParameterDescriptors: action.commandParameterDescriptors,
|
|
9342
9395
|
icon: action.icon || (action.execution?.bulk?.mode === 'UNIFORM_UPDATE' ? 'edit_note' : 'playlist_add_check'),
|
|
9343
9396
|
action: action.id,
|
|
9344
9397
|
requiresSelection: true,
|
|
@@ -9346,7 +9399,7 @@ class PraxisCrudComponent {
|
|
|
9346
9399
|
tooltip: !available
|
|
9347
9400
|
? translateUnavailableWorkflowMessage(this.i18n, capabilities.operations?.[action.id]?.availability || action.availability) || action.description
|
|
9348
9401
|
: action.description,
|
|
9349
|
-
execution:
|
|
9402
|
+
execution: action.execution,
|
|
9350
9403
|
});
|
|
9351
9404
|
}
|
|
9352
9405
|
for (const [opKey, op] of Object.entries(capabilities.operations || {})) {
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/crud",
|
|
3
|
-
"version": "10.0.0-rc.
|
|
3
|
+
"version": "10.0.0-rc.17",
|
|
4
4
|
"description": "CRUD building blocks for Praxis UI: integrates dynamic forms and tables with unified configuration and services.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
7
7
|
"@angular/core": "^21.0.0",
|
|
8
|
-
"@praxisui/dynamic-form": "^10.0.0-rc.
|
|
9
|
-
"@praxisui/table": "^10.0.0-rc.
|
|
10
|
-
"@praxisui/core": "^10.0.0-rc.
|
|
11
|
-
"@praxisui/dynamic-fields": "^10.0.0-rc.
|
|
12
|
-
"@praxisui/settings-panel": "^10.0.0-rc.
|
|
8
|
+
"@praxisui/dynamic-form": "^10.0.0-rc.17",
|
|
9
|
+
"@praxisui/table": "^10.0.0-rc.17",
|
|
10
|
+
"@praxisui/core": "^10.0.0-rc.17",
|
|
11
|
+
"@praxisui/dynamic-fields": "^10.0.0-rc.17",
|
|
12
|
+
"@praxisui/settings-panel": "^10.0.0-rc.17",
|
|
13
13
|
"@angular/cdk": "^21.0.0",
|
|
14
14
|
"@angular/forms": "^21.0.0",
|
|
15
15
|
"@angular/material": "^21.0.0",
|
|
16
16
|
"@angular/router": "^21.0.0",
|
|
17
|
-
"@praxisui/ai": "^10.0.0-rc.
|
|
17
|
+
"@praxisui/ai": "^10.0.0-rc.17",
|
|
18
18
|
"rxjs": "~7.8.0"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|