@praxisui/crud 9.0.4-rc.24 → 9.0.4-rc.26
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 +8 -0
- package/ai/component-registry.json +18 -6
- package/fesm2022/praxisui-crud.mjs +120 -28
- package/package.json +7 -7
- package/types/praxisui-crud-drawer-adapter.d.ts +3 -1
- package/types/praxisui-crud.d.ts +12 -1
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ import { PraxisCrudComponent, CrudMetadata } from '@praxisui/crud';
|
|
|
43
43
|
<praxis-crud
|
|
44
44
|
crudId="employees-crud"
|
|
45
45
|
[metadata]="metadata"
|
|
46
|
+
tableConfigPersistenceStrategy="input-first"
|
|
46
47
|
[context]="context"
|
|
47
48
|
[enableCustomization]="true"
|
|
48
49
|
(afterSave)="reloadSummary()"
|
|
@@ -92,6 +93,7 @@ export class EmployeesCrudComponent {
|
|
|
92
93
|
- `metadata`: `CrudMetadata | string`
|
|
93
94
|
- `crudId`: stable instance id
|
|
94
95
|
- `componentInstanceId`: optional host-level instance id
|
|
96
|
+
- `tableConfigPersistenceStrategy`: controls persistence precedence for the internal table. Keep `local-first` for user-owned workspaces, use `input-first` for an authoritative governed contract, and use `volatile` for previews that must neither read nor write stored preferences.
|
|
95
97
|
- `context`: host/runtime context passed into table and form flows
|
|
96
98
|
- `enableCustomization`: enables the package authoring surface
|
|
97
99
|
- `authoringCapability`: optionally requires the exact capability from `EnterpriseRuntimeContext.capabilities` before authoring controls, the CRUD editor, and its internal table authoring are available. This is a UX gate; governed persistence must enforce the same policy server-side.
|
|
@@ -194,6 +196,12 @@ outside the request schema and are never added to the update payload. Custom
|
|
|
194
196
|
drawer adapters receive the same `resourceIdentity` context and retain their own
|
|
195
197
|
presentation responsibility.
|
|
196
198
|
|
|
199
|
+
Related operations also receive `contextIdentity` when the governed surface
|
|
200
|
+
publishes `context.operation.taskScope`. The default host labels it as “Related
|
|
201
|
+
to” and keeps it distinct from the current child record. Both identities stay
|
|
202
|
+
outside dynamic-form inputs and submit payloads; capabilities and HATEOAS remain
|
|
203
|
+
the authority for whether the operation may execute.
|
|
204
|
+
|
|
197
205
|
Route mode has a different lifecycle because `@praxisui/crud` does not own the
|
|
198
206
|
destination component. Routed edit hosts must load the entity through the
|
|
199
207
|
canonical read contract and materialize identity from its response schema. Do
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-08-
|
|
3
|
+
"generatedAt": "2026-08-04T22:30:51.687Z",
|
|
4
4
|
"packageName": "@praxisui/crud",
|
|
5
|
-
"packageVersion": "9.0.4-rc.
|
|
5
|
+
"packageVersion": "9.0.4-rc.26",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 2,
|
|
@@ -29,6 +29,13 @@
|
|
|
29
29
|
"required": false,
|
|
30
30
|
"description": "Identificador opcional para múltiplas instâncias na mesma rota."
|
|
31
31
|
},
|
|
32
|
+
{
|
|
33
|
+
"name": "tableConfigPersistenceStrategy",
|
|
34
|
+
"type": "'local-first' | 'input-first' | 'volatile'",
|
|
35
|
+
"required": false,
|
|
36
|
+
"description": "Política da tabela interna. Use input-first para contratos governados autoritativos e volatile para previews que não devem ler nem gravar preferências locais.",
|
|
37
|
+
"default": "local-first"
|
|
38
|
+
},
|
|
32
39
|
{
|
|
33
40
|
"name": "context",
|
|
34
41
|
"type": "Record<string, unknown>",
|
|
@@ -5015,6 +5022,11 @@
|
|
|
5015
5022
|
"type": "string",
|
|
5016
5023
|
"description": "Optional stable host instance id for multiple CRUD widgets on the same route."
|
|
5017
5024
|
},
|
|
5025
|
+
{
|
|
5026
|
+
"name": "tableConfigPersistenceStrategy",
|
|
5027
|
+
"type": "'local-first' | 'input-first' | 'volatile'",
|
|
5028
|
+
"description": "Persistence precedence forwarded to the internal Praxis Table. Governed previews should use input-first or volatile explicitly."
|
|
5029
|
+
},
|
|
5018
5030
|
{
|
|
5019
5031
|
"name": "context",
|
|
5020
5032
|
"type": "Record<string, unknown>",
|
|
@@ -7206,9 +7218,9 @@
|
|
|
7206
7218
|
{
|
|
7207
7219
|
"chunkIndex": 0,
|
|
7208
7220
|
"chunkKind": "summary",
|
|
7209
|
-
"content": "Component ID: praxis-crud\nSelector: praxis-crud\nFriendly Name: Praxis CRUD\nDescription: Tabela com operações de CRUD via metadados.\nLib/Package: @praxisui/crud\nTags: widget, crud, configurable, hasWizard, stable\nInputs:\n - metadata (CrudMetadata | string)\n - crudId (string)\n - componentInstanceId (string)\n - context (Record<string, unknown>)\n - metadata.queryContext (PraxisDataQueryContext | null)\n - metadata.resource.schemaPath (string | null)\n - metadata.resource.title (string | null)\n - metadata.resource.formTitle (string | null)\n - metadata.filterCriteria (Record<string, unknown> | null)\n - metadata.form (FormConfig)\n - metadata.actions[].form (CrudActionFormContract)\n - enableCustomization (boolean)\n - authoringCapability (string | null)\nOutputs:\n - afterOpen ({ mode: FormOpenMode; action: string })\n - afterClose (void)\n - afterSave ({ id: string | number; data: unknown })\n - afterDelete ({ id: string | number })\n - rowClick ({ row: unknown; index: number })\n - selectionChange (unknown)\n - error (unknown)\n - configureRequested (void)\n - crudAuthoringDocumentApplied (CrudAuthoringWidgetPersistenceEvent)\n - crudAuthoringDocumentSaved (CrudAuthoringWidgetPersistenceEvent)\n",
|
|
7221
|
+
"content": "Component ID: praxis-crud\nSelector: praxis-crud\nFriendly Name: Praxis CRUD\nDescription: Tabela com operações de CRUD via metadados.\nLib/Package: @praxisui/crud\nTags: widget, crud, configurable, hasWizard, stable\nInputs:\n - metadata (CrudMetadata | string)\n - crudId (string)\n - componentInstanceId (string)\n - tableConfigPersistenceStrategy ('local-first' | 'input-first' | 'volatile')\n - context (Record<string, unknown>)\n - metadata.queryContext (PraxisDataQueryContext | null)\n - metadata.resource.schemaPath (string | null)\n - metadata.resource.title (string | null)\n - metadata.resource.formTitle (string | null)\n - metadata.filterCriteria (Record<string, unknown> | null)\n - metadata.form (FormConfig)\n - metadata.actions[].form (CrudActionFormContract)\n - enableCustomization (boolean)\n - authoringCapability (string | null)\nOutputs:\n - afterOpen ({ mode: FormOpenMode; action: string })\n - afterClose (void)\n - afterSave ({ id: string | number; data: unknown })\n - afterDelete ({ id: string | number })\n - rowClick ({ row: unknown; index: number })\n - selectionChange (unknown)\n - error (unknown)\n - configureRequested (void)\n - crudAuthoringDocumentApplied (CrudAuthoringWidgetPersistenceEvent)\n - crudAuthoringDocumentSaved (CrudAuthoringWidgetPersistenceEvent)\n",
|
|
7210
7222
|
"sourcePointer": "projects/praxis-crud/src/lib/praxis-crud.metadata.ts",
|
|
7211
|
-
"contentHash": "
|
|
7223
|
+
"contentHash": "a9d744b92ff6f475de4d870e57bc963200a7b68688a8ea5159cc02496a8967be",
|
|
7212
7224
|
"sourceKind": "component_definition",
|
|
7213
7225
|
"sourceId": "praxis-crud",
|
|
7214
7226
|
"corpusVersion": "1.0.0"
|
|
@@ -7436,9 +7448,9 @@
|
|
|
7436
7448
|
{
|
|
7437
7449
|
"chunkIndex": 23,
|
|
7438
7450
|
"chunkKind": "authoring_manifest",
|
|
7439
|
-
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"runtimeInputs\",\"runtimeInputs\":[{\"name\":\"metadata\",\"type\":\"CrudMetadata | string\",\"description\":\"Canonical CRUD metadata or serialized metadata document.\"},{\"name\":\"crudId\",\"type\":\"string\",\"description\":\"Stable CRUD instance id used for table/form identity and persistence.\"},{\"name\":\"componentInstanceId\",\"type\":\"string\",\"description\":\"Optional stable host instance id for multiple CRUD widgets on the same route.\"},{\"name\":\"context\",\"type\":\"Record<string, unknown>\",\"description\":\"Opaque host context used for authoring seeds and launcher inputs.\"},{\"name\":\"enableCustomization\",\"type\":\"boolean\",\"description\":\"Explicit host opt-in for CRUD authoring surfaces.\"},{\"name\":\"authoringCapability\",\"type\":\"string | null\",\"description\":\"Public runtime capability required before CRUD and delegated table authoring can open.\"},{\"name\":\"afterOpen\",\"type\":\"{ mode: FormOpenMode; action: string }\",\"description\":\"Emitted after a CRUD action opens.\"},{\"name\":\"afterSave\",\"type\":\"{ id: string | number; data: unknown }\",\"description\":\"Emitted after save; CRUD refetches the list.\"},{\"name\":\"afterDelete\",\"type\":\"{ id: string | number }\",\"description\":\"Emitted after delete; CRUD refetches the list.\"}]}",
|
|
7451
|
+
"content": "{\"schemaVersion\":\"1.0.0\",\"manifestVersion\":\"1.0.0\",\"componentId\":\"praxis-crud\",\"ownerPackage\":\"@praxisui/crud\",\"configSchemaId\":\"CrudMetadata\",\"chunkSection\":\"runtimeInputs\",\"runtimeInputs\":[{\"name\":\"metadata\",\"type\":\"CrudMetadata | string\",\"description\":\"Canonical CRUD metadata or serialized metadata document.\"},{\"name\":\"crudId\",\"type\":\"string\",\"description\":\"Stable CRUD instance id used for table/form identity and persistence.\"},{\"name\":\"componentInstanceId\",\"type\":\"string\",\"description\":\"Optional stable host instance id for multiple CRUD widgets on the same route.\"},{\"name\":\"tableConfigPersistenceStrategy\",\"type\":\"'local-first' | 'input-first' | 'volatile'\",\"description\":\"Persistence precedence forwarded to the internal Praxis Table. Governed previews should use input-first or volatile explicitly.\"},{\"name\":\"context\",\"type\":\"Record<string, unknown>\",\"description\":\"Opaque host context used for authoring seeds and launcher inputs.\"},{\"name\":\"enableCustomization\",\"type\":\"boolean\",\"description\":\"Explicit host opt-in for CRUD authoring surfaces.\"},{\"name\":\"authoringCapability\",\"type\":\"string | null\",\"description\":\"Public runtime capability required before CRUD and delegated table authoring can open.\"},{\"name\":\"afterOpen\",\"type\":\"{ mode: FormOpenMode; action: string }\",\"description\":\"Emitted after a CRUD action opens.\"},{\"name\":\"afterSave\",\"type\":\"{ id: string | number; data: unknown }\",\"description\":\"Emitted after save; CRUD refetches the list.\"},{\"name\":\"afterDelete\",\"type\":\"{ id: string | number }\",\"description\":\"Emitted after delete; CRUD refetches the list.\"}]}",
|
|
7440
7452
|
"sourcePointer": "projects/praxis-crud/src/lib/ai/praxis-crud-authoring-manifest.ts",
|
|
7441
|
-
"contentHash": "
|
|
7453
|
+
"contentHash": "068b8503236aa70e0543cc63c791a5c9cb192983b3e369285bb44732b3b646d8",
|
|
7442
7454
|
"sourceKind": "component_definition",
|
|
7443
7455
|
"sourceId": "praxis-crud",
|
|
7444
7456
|
"corpusVersion": "1.0.0"
|
|
@@ -6,7 +6,7 @@ import { Router, ActivatedRoute, RouterLink } from '@angular/router';
|
|
|
6
6
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
7
7
|
import { firstValueFrom, BehaviorSubject, Subscription } from 'rxjs';
|
|
8
8
|
import * as i2$1 from '@praxisui/core';
|
|
9
|
-
import { ASYNC_CONFIG_STORAGE, GlobalConfigService, CrudOperationResolutionService, fillUndefined, SETTINGS_PANEL_DATA, PraxisI18nService, PraxisIconDirective, providePraxisI18nConfig, createDefaultTableConfig, EnterpriseRuntimeContextService, GLOBAL_SURFACE_SERVICE, SurfaceOutletRegistryService, ComponentKeyService, ResourceDiscoveryService, ResourceActionOpenAdapterService, ResourceSurfaceOpenAdapterService, translateUnavailableWorkflowMessage, EmptyStateCardComponent, RESOURCE_DISCOVERY_I18N_CONFIG, PraxisIconButtonComponent, PraxisResourceIdentityComponent, GenericCrudService, ComponentMetadataRegistry } from '@praxisui/core';
|
|
9
|
+
import { ASYNC_CONFIG_STORAGE, GlobalConfigService, CrudOperationResolutionService, fillUndefined, SETTINGS_PANEL_DATA, PraxisI18nService, PraxisIconDirective, providePraxisI18nConfig, createDefaultTableConfig, EnterpriseRuntimeContextService, GLOBAL_SURFACE_SERVICE, SurfaceOutletRegistryService, ComponentKeyService, ResourceDiscoveryService, ResourceActionOpenAdapterService, ResourceSurfaceOpenAdapterService, normalizeSurfaceOperationContext, translateUnavailableWorkflowMessage, EmptyStateCardComponent, RESOURCE_DISCOVERY_I18N_CONFIG, PraxisIconButtonComponent, PraxisResourceIdentityComponent, GenericCrudService, ComponentMetadataRegistry } from '@praxisui/core';
|
|
10
10
|
import { SettingsPanelService } from '@praxisui/settings-panel';
|
|
11
11
|
import { PraxisTableInlineAuthoringEditorComponent, PraxisTable } from '@praxisui/table';
|
|
12
12
|
import { ConfirmDialogComponent } from '@praxisui/dynamic-fields';
|
|
@@ -141,15 +141,17 @@ class CrudLauncherService {
|
|
|
141
141
|
row[idField] !== undefined) {
|
|
142
142
|
inputs[idField] = row[idField];
|
|
143
143
|
}
|
|
144
|
-
const resourceIdentity = actionForLaunch.action === 'edit'
|
|
144
|
+
const resourceIdentity = actionForLaunch.action === 'edit' || actionForLaunch.action === 'view'
|
|
145
145
|
? runtime?.resourceIdentity ?? null
|
|
146
146
|
: null;
|
|
147
|
+
const contextIdentity = runtime?.contextIdentity ?? null;
|
|
147
148
|
if (mode === 'drawer' && this.drawerAdapter) {
|
|
148
149
|
await Promise.resolve(this.drawerAdapter.open({
|
|
149
150
|
action: actionForLaunch,
|
|
150
151
|
metadata: merged.metadata,
|
|
151
152
|
inputs,
|
|
152
153
|
resourceIdentity,
|
|
154
|
+
contextIdentity,
|
|
153
155
|
onClose: drawerCallbacks?.onClose,
|
|
154
156
|
onResult: drawerCallbacks?.onResult,
|
|
155
157
|
}));
|
|
@@ -212,6 +214,7 @@ class CrudLauncherService {
|
|
|
212
214
|
presentation: drawerMode ? 'drawer' : 'modal',
|
|
213
215
|
dialogPosition,
|
|
214
216
|
resourceIdentity,
|
|
217
|
+
contextIdentity,
|
|
215
218
|
},
|
|
216
219
|
});
|
|
217
220
|
if (drawerMode) {
|
|
@@ -911,6 +914,8 @@ const PRAXIS_CRUD_RUNTIME_I18N_CONFIG = {
|
|
|
911
914
|
'crud.actions.opening': 'Abrindo {action}…',
|
|
912
915
|
'crud.surface.openFailed': 'Não foi possível abrir {title}. Tente novamente ou confirme se esse recurso continua disponível.',
|
|
913
916
|
'crud.dialog.recordContextLabel': 'Registro em edição',
|
|
917
|
+
'crud.dialog.viewRecordContextLabel': 'Registro em consulta',
|
|
918
|
+
'crud.dialog.relatedContextLabel': 'Vinculado a',
|
|
914
919
|
'crud.delete.confirmMessage': 'Esta ação não pode ser desfeita. Deseja continuar?',
|
|
915
920
|
'crud.delete.cancel': 'Cancelar',
|
|
916
921
|
},
|
|
@@ -932,6 +937,8 @@ const PRAXIS_CRUD_RUNTIME_I18N_CONFIG = {
|
|
|
932
937
|
'crud.actions.opening': 'Opening {action}…',
|
|
933
938
|
'crud.surface.openFailed': 'Could not open {title}. Try again or confirm that this resource is still available.',
|
|
934
939
|
'crud.dialog.recordContextLabel': 'Record being edited',
|
|
940
|
+
'crud.dialog.viewRecordContextLabel': 'Record being viewed',
|
|
941
|
+
'crud.dialog.relatedContextLabel': 'Related to',
|
|
935
942
|
'crud.delete.confirmMessage': 'This action cannot be undone. Do you want to continue?',
|
|
936
943
|
'crud.delete.cancel': 'Cancel',
|
|
937
944
|
},
|
|
@@ -3660,6 +3667,8 @@ class PraxisCrudComponent {
|
|
|
3660
3667
|
metadata;
|
|
3661
3668
|
crudId;
|
|
3662
3669
|
componentInstanceId;
|
|
3670
|
+
/** Controls whether the CRUD's internal table trusts host input or stored user configuration. */
|
|
3671
|
+
tableConfigPersistenceStrategy = 'local-first';
|
|
3663
3672
|
context;
|
|
3664
3673
|
enableCustomization = false;
|
|
3665
3674
|
/** Capability publica exigida para authoring governado do CRUD e da tabela interna. */
|
|
@@ -3863,6 +3872,7 @@ class PraxisCrudComponent {
|
|
|
3863
3872
|
action: this.normalizeCrudActionName(actionMeta?.action ?? normalizedAction),
|
|
3864
3873
|
};
|
|
3865
3874
|
const resourceIdentity = runtimeEvent?.resourceIdentity ?? null;
|
|
3875
|
+
const contextIdentity = this.resolveTaskScopeIdentity();
|
|
3866
3876
|
const handledByDuplicateDraft = await this.tryHandleCanonicalDuplicateDraftAction(effectiveAction, contextualRow);
|
|
3867
3877
|
if (handledByDuplicateDraft) {
|
|
3868
3878
|
return;
|
|
@@ -3911,6 +3921,7 @@ class PraxisCrudComponent {
|
|
|
3911
3921
|
: this.collectionCapabilities,
|
|
3912
3922
|
links: this.resolveCrudRuntimeLinks(effectiveAction.action, contextualRow),
|
|
3913
3923
|
resourceIdentity,
|
|
3924
|
+
contextIdentity,
|
|
3914
3925
|
});
|
|
3915
3926
|
this.afterOpen.emit({ mode, action: effectiveAction.action });
|
|
3916
3927
|
if (mode === 'drawer') {
|
|
@@ -3946,6 +3957,10 @@ class PraxisCrudComponent {
|
|
|
3946
3957
|
this.openingActionLabel.set(null);
|
|
3947
3958
|
}
|
|
3948
3959
|
}
|
|
3960
|
+
resolveTaskScopeIdentity() {
|
|
3961
|
+
const operation = normalizeSurfaceOperationContext(this.context?.['operation']);
|
|
3962
|
+
return operation?.taskScope?.identity ?? null;
|
|
3963
|
+
}
|
|
3949
3964
|
getOpeningActionStatus(actionLabel) {
|
|
3950
3965
|
return this.txWithParams('crud.actions.opening', 'Abrindo {action}…', { action: actionLabel });
|
|
3951
3966
|
}
|
|
@@ -5234,7 +5249,7 @@ class PraxisCrudComponent {
|
|
|
5234
5249
|
return Object.entries(params).reduce((current, [name, value]) => current.split(`{${name}}`).join(value), text);
|
|
5235
5250
|
}
|
|
5236
5251
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisCrudComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5237
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisCrudComponent, isStandalone: true, selector: "praxis-crud", inputs: { metadata: "metadata", crudId: "crudId", componentInstanceId: "componentInstanceId", context: "context", enableCustomization: "enableCustomization", authoringCapability: "authoringCapability" }, outputs: { configureRequested: "configureRequested", afterOpen: "afterOpen", afterClose: "afterClose", afterSave: "afterSave", afterDelete: "afterDelete", error: "error", rowClick: "rowClick", selectionChange: "selectionChange", tableRuntimeConfigChange: "tableRuntimeConfigChange", crudAuthoringDocumentApplied: "crudAuthoringDocumentApplied", crudAuthoringDocumentSaved: "crudAuthoringDocumentSaved" }, providers: [
|
|
5252
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisCrudComponent, isStandalone: true, selector: "praxis-crud", inputs: { metadata: "metadata", crudId: "crudId", componentInstanceId: "componentInstanceId", tableConfigPersistenceStrategy: "tableConfigPersistenceStrategy", context: "context", enableCustomization: "enableCustomization", authoringCapability: "authoringCapability" }, outputs: { configureRequested: "configureRequested", afterOpen: "afterOpen", afterClose: "afterClose", afterSave: "afterSave", afterDelete: "afterDelete", error: "error", rowClick: "rowClick", selectionChange: "selectionChange", tableRuntimeConfigChange: "tableRuntimeConfigChange", crudAuthoringDocumentApplied: "crudAuthoringDocumentApplied", crudAuthoringDocumentSaved: "crudAuthoringDocumentSaved" }, providers: [
|
|
5238
5253
|
providePraxisI18nConfig(RESOURCE_DISCOVERY_I18N_CONFIG),
|
|
5239
5254
|
providePraxisI18nConfig(PRAXIS_CRUD_RUNTIME_I18N_CONFIG),
|
|
5240
5255
|
], viewQueries: [{ propertyName: "table", first: true, predicate: PraxisTable, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
@@ -5253,6 +5268,7 @@ class PraxisCrudComponent {
|
|
|
5253
5268
|
[queryContext]="tableQueryContext"
|
|
5254
5269
|
[filterCriteria]="tableFilterCriteria"
|
|
5255
5270
|
[tableId]="crudId || 'default'"
|
|
5271
|
+
[configPersistenceStrategy]="tableConfigPersistenceStrategy"
|
|
5256
5272
|
[crudContext]="tableCrudContext"
|
|
5257
5273
|
[enableCustomization]="enableCustomization"
|
|
5258
5274
|
[authoringCapability]="authoringCapability"
|
|
@@ -5300,6 +5316,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5300
5316
|
[queryContext]="tableQueryContext"
|
|
5301
5317
|
[filterCriteria]="tableFilterCriteria"
|
|
5302
5318
|
[tableId]="crudId || 'default'"
|
|
5319
|
+
[configPersistenceStrategy]="tableConfigPersistenceStrategy"
|
|
5303
5320
|
[crudContext]="tableCrudContext"
|
|
5304
5321
|
[enableCustomization]="enableCustomization"
|
|
5305
5322
|
[authoringCapability]="authoringCapability"
|
|
@@ -5333,6 +5350,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5333
5350
|
args: [{ required: true }]
|
|
5334
5351
|
}], componentInstanceId: [{
|
|
5335
5352
|
type: Input
|
|
5353
|
+
}], tableConfigPersistenceStrategy: [{
|
|
5354
|
+
type: Input
|
|
5336
5355
|
}], context: [{
|
|
5337
5356
|
type: Input
|
|
5338
5357
|
}], enableCustomization: [{
|
|
@@ -5408,6 +5427,7 @@ class DynamicFormDialogHostComponent {
|
|
|
5408
5427
|
resourceId;
|
|
5409
5428
|
initialValue;
|
|
5410
5429
|
resourceIdentity = null;
|
|
5430
|
+
contextIdentity = null;
|
|
5411
5431
|
schemaUrl;
|
|
5412
5432
|
submitUrl;
|
|
5413
5433
|
submitMethod;
|
|
@@ -5427,6 +5447,8 @@ class DynamicFormDialogHostComponent {
|
|
|
5427
5447
|
maximizeLabel: 'Maximizar',
|
|
5428
5448
|
restoreLabel: 'Restaurar',
|
|
5429
5449
|
recordContextLabel: translateCrudRuntimeText(this.i18n, 'crud.dialog.recordContextLabel', 'Registro em edição'),
|
|
5450
|
+
viewRecordContextLabel: translateCrudRuntimeText(this.i18n, 'crud.dialog.viewRecordContextLabel', 'Registro em consulta'),
|
|
5451
|
+
relatedContextLabel: translateCrudRuntimeText(this.i18n, 'crud.dialog.relatedContextLabel', 'Vinculado a'),
|
|
5430
5452
|
discardTitle: 'Descartar alterações?',
|
|
5431
5453
|
discardMessage: 'Você tem alterações não salvas. Deseja fechar assim mesmo?',
|
|
5432
5454
|
discardConfirm: 'Descartar',
|
|
@@ -5477,9 +5499,12 @@ class DynamicFormDialogHostComponent {
|
|
|
5477
5499
|
this.apiUrlEntry = this.data.inputs?.['apiUrlEntry'] ?? null;
|
|
5478
5500
|
const act = this.data.action?.action;
|
|
5479
5501
|
this.mode = act === 'edit' ? 'edit' : act === 'view' ? 'view' : 'create';
|
|
5480
|
-
this.resourceIdentity = this.mode
|
|
5502
|
+
this.resourceIdentity = this.mode !== 'create' && this.data.resourceIdentity
|
|
5481
5503
|
? this.data.resourceIdentity
|
|
5482
5504
|
: null;
|
|
5505
|
+
this.contextIdentity = this.data.contextIdentity
|
|
5506
|
+
? this.data.contextIdentity
|
|
5507
|
+
: null;
|
|
5483
5508
|
this.formConfig = this.resolveFormConfig();
|
|
5484
5509
|
this.layoutPolicy = this.resolveLayoutPolicy();
|
|
5485
5510
|
this.formActions = this.resolveFormActions();
|
|
@@ -5515,6 +5540,32 @@ class DynamicFormDialogHostComponent {
|
|
|
5515
5540
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
5516
5541
|
.subscribe(() => this.saveState());
|
|
5517
5542
|
}
|
|
5543
|
+
get resourceIdentityLabel() {
|
|
5544
|
+
return this.mode === 'view'
|
|
5545
|
+
? this.texts['viewRecordContextLabel']
|
|
5546
|
+
: this.texts['recordContextLabel'];
|
|
5547
|
+
}
|
|
5548
|
+
get showContextIdentity() {
|
|
5549
|
+
return !!this.contextIdentity && !this.sameIdentity(this.contextIdentity, this.resourceIdentity);
|
|
5550
|
+
}
|
|
5551
|
+
sameIdentity(left, right) {
|
|
5552
|
+
if (!left || !right)
|
|
5553
|
+
return false;
|
|
5554
|
+
const leftKey = left.key;
|
|
5555
|
+
const rightKey = right.key;
|
|
5556
|
+
const leftLabel = this.identityLabel(left);
|
|
5557
|
+
const rightLabel = this.identityLabel(right);
|
|
5558
|
+
if (leftKey && rightKey) {
|
|
5559
|
+
return leftKey.field === rightKey.field
|
|
5560
|
+
&& String(leftKey.value) === String(rightKey.value)
|
|
5561
|
+
&& !!leftLabel
|
|
5562
|
+
&& leftLabel === rightLabel;
|
|
5563
|
+
}
|
|
5564
|
+
return !!leftLabel && leftLabel === rightLabel;
|
|
5565
|
+
}
|
|
5566
|
+
identityLabel(identity) {
|
|
5567
|
+
return String(identity.displayLabel || identity.title?.value || '').trim();
|
|
5568
|
+
}
|
|
5518
5569
|
extractInitialValue(inputs) {
|
|
5519
5570
|
if (!inputs || typeof inputs !== 'object') {
|
|
5520
5571
|
return null;
|
|
@@ -5858,17 +5909,34 @@ class DynamicFormDialogHostComponent {
|
|
|
5858
5909
|
aria-labelledby="crudDialogTitle"
|
|
5859
5910
|
[attr.aria-describedby]="dialogSubtitle ? 'crudDialogDescription' : null"
|
|
5860
5911
|
>
|
|
5861
|
-
@if (resourceIdentity) {
|
|
5862
|
-
<div class="crud-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5912
|
+
@if (showContextIdentity || resourceIdentity) {
|
|
5913
|
+
<div class="crud-operation-context" data-testid="crud-operation-context">
|
|
5914
|
+
@if (showContextIdentity) {
|
|
5915
|
+
<div class="crud-resource-identity" data-testid="crud-context-identity">
|
|
5916
|
+
<span class="crud-resource-identity__label" aria-hidden="true">
|
|
5917
|
+
{{ texts.relatedContextLabel }}
|
|
5918
|
+
</span>
|
|
5919
|
+
<praxis-resource-identity
|
|
5920
|
+
[identity]="contextIdentity"
|
|
5921
|
+
density="compact"
|
|
5922
|
+
[showKeyLabel]="true"
|
|
5923
|
+
[ariaLabel]="texts.relatedContextLabel"
|
|
5924
|
+
></praxis-resource-identity>
|
|
5925
|
+
</div>
|
|
5926
|
+
}
|
|
5927
|
+
@if (resourceIdentity) {
|
|
5928
|
+
<div class="crud-resource-identity" data-testid="crud-resource-identity">
|
|
5929
|
+
<span class="crud-resource-identity__label" aria-hidden="true">
|
|
5930
|
+
{{ resourceIdentityLabel }}
|
|
5931
|
+
</span>
|
|
5932
|
+
<praxis-resource-identity
|
|
5933
|
+
[identity]="resourceIdentity"
|
|
5934
|
+
density="compact"
|
|
5935
|
+
[showKeyLabel]="true"
|
|
5936
|
+
[ariaLabel]="resourceIdentityLabel"
|
|
5937
|
+
></praxis-resource-identity>
|
|
5938
|
+
</div>
|
|
5939
|
+
}
|
|
5872
5940
|
</div>
|
|
5873
5941
|
}
|
|
5874
5942
|
<praxis-dynamic-form
|
|
@@ -5892,7 +5960,7 @@ class DynamicFormDialogHostComponent {
|
|
|
5892
5960
|
(formCancel)="onCancel()"
|
|
5893
5961
|
></praxis-dynamic-form>
|
|
5894
5962
|
</mat-dialog-content>
|
|
5895
|
-
`, isInline: true, styles: ["praxis-dynamic-form-dialog-host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}praxis-dynamic-form-dialog-host[data-density=compact]{--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}praxis-dynamic-form-dialog-host .dialog-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--dlg-pad);min-height:var(--dlg-header-h);padding:10px var(--dlg-pad);margin:0;background:var(--md-sys-color-surface-container-high);border-bottom:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-heading{display:grid;min-width:0;gap:2px}praxis-dynamic-form-dialog-host .dialog-title-icon{display:inline-grid;flex:0 0 auto;width:36px;height:36px;place-items:center;border-radius:10px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}praxis-dynamic-form-dialog-host .dialog-title-icon mat-icon{width:22px;height:22px;font-size:22px}praxis-dynamic-form-dialog-host .dialog-subtitle{display:-webkit-box;overflow:hidden;color:var(--md-sys-color-on-surface-variant);font-size:.82rem;font-weight:400;line-height:1.35;-webkit-box-orient:vertical;-webkit-line-clamp:2}praxis-dynamic-form-dialog-host .spacer{flex:1}praxis-dynamic-form-dialog-host .dialog-content{flex:1 1 auto;overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}praxis-dynamic-form-dialog-host .crud-
|
|
5963
|
+
`, isInline: true, styles: ["praxis-dynamic-form-dialog-host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}praxis-dynamic-form-dialog-host[data-density=compact]{--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}praxis-dynamic-form-dialog-host .dialog-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--dlg-pad);min-height:var(--dlg-header-h);padding:10px var(--dlg-pad);margin:0;background:var(--md-sys-color-surface-container-high);border-bottom:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-heading{display:grid;min-width:0;gap:2px}praxis-dynamic-form-dialog-host .dialog-title-icon{display:inline-grid;flex:0 0 auto;width:36px;height:36px;place-items:center;border-radius:10px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}praxis-dynamic-form-dialog-host .dialog-title-icon mat-icon{width:22px;height:22px;font-size:22px}praxis-dynamic-form-dialog-host .dialog-subtitle{display:-webkit-box;overflow:hidden;color:var(--md-sys-color-on-surface-variant);font-size:.82rem;font-weight:400;line-height:1.35;-webkit-box-orient:vertical;-webkit-line-clamp:2}praxis-dynamic-form-dialog-host .spacer{flex:1}praxis-dynamic-form-dialog-host .dialog-content{flex:1 1 auto;overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}praxis-dynamic-form-dialog-host .crud-operation-context{position:sticky;top:0;z-index:1;display:grid;gap:.75rem;margin-block-end:var(--dlg-pad);padding-block:.5rem .75rem;background:var(--pfx-form-surface, var(--md-sys-color-surface));border-bottom:1px solid var(--md-sys-color-outline-variant)}praxis-dynamic-form-dialog-host .crud-resource-identity{display:grid;gap:.25rem;min-width:0}praxis-dynamic-form-dialog-host .crud-resource-identity__label{color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typescale-label-medium, 500 .75rem/1rem inherit)}praxis-dynamic-form-dialog-host.praxis-drawer{--dlg-header-h: 72px;width:100%;min-width:0;max-width:100vw;height:100dvh;background:var(--pfx-form-surface, var(--md-sys-color-surface));color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-header{background:color-mix(in srgb,var(--md-sys-color-surface-container-high, var(--md-sys-color-surface)),transparent 4%)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content{max-height:none;min-height:0;padding:clamp(12px,2.4vw,24px)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button:hover{color:var(--md-sys-color-primary)}praxis-dynamic-form-dialog-host .dialog-footer{position:sticky;bottom:0;z-index:1;padding:var(--dlg-pad)}.pfx-blur-backdrop{background-color:var(--pfx-backdrop, rgba(15, 23, 42, .42))!important;backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%)}.pfx-transparent-backdrop{background-color:transparent!important}.cdk-overlay-pane.pfx-dialog-pane{overflow:hidden;transition:width .2s ease,height .2s ease,margin .2s ease}.cdk-overlay-pane.pfx-dialog-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane .mdc-dialog__surface{display:flex;flex-direction:column;width:100%;min-width:0;height:100%;max-height:inherit;overflow:hidden;background:var(--pfx-form-surface, var(--md-sys-color-surface))!important;border:1px solid var(--pfx-form-stroke, var(--md-sys-color-outline-variant))!important}.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mdc-dialog__surface{backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cdk-overlay-pane.pfx-drawer-pane{margin:0!important;border-radius:0!important;box-shadow:var(--md-sys-elevation-level3, 0 24px 80px rgba(15, 23, 42, .28)),0 0 0 1px color-mix(in srgb,var(--md-sys-color-outline, #64748b) 24%,transparent)}.cdk-overlay-pane.pfx-drawer-pane.pfx-drawer-maximized{margin:var(--pfx-drawer-edge-gap, 8px)!important}.cdk-overlay-pane.pfx-drawer-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-drawer-pane .mdc-dialog__surface{min-width:0!important;border-radius:0!important}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisResourceIdentityComponent, selector: "praxis-resource-identity", inputs: ["identity", "emptyTitle", "density", "showMetadataLabels", "showKeyLabel", "ariaLabel"] }, { kind: "component", type: PraxisDynamicForm, selector: "praxis-dynamic-form", inputs: ["resourcePath", "resourceId", "initialValue", "editorialContext", "mode", "config", "actions", "schemaSource", "schemaUrl", "readUrl", "submitUrl", "submitMethod", "submitIdempotencyKey", "submitCorrelationId", "submitResourceVersion", "responseSchemaUrl", "apiEndpointKey", "apiUrlEntry", "enableCustomization", "showAiAssistant", "formId", "componentInstanceId", "configPersistenceStrategy", "layout", "generatedLayoutPreset", "layoutPolicy", "backConfig", "hooks", "removeEmptyContainersOnSave", "reactiveValidation", "reactiveValidationDebounceMs", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "readonlyModeGlobal", "disabledModeGlobal", "presentationModeGlobal", "visibleGlobal", "fieldIconPolicy", "domainRules", "customEndpoints"], outputs: ["formSubmit", "formCancel", "formReset", "configChange", "configPatchChange", "formReady", "valueChange", "syncCompleted", "initializationError", "loadingStateChange", "enableCustomizationChange", "customAction", "actionConfirmation", "schemaStatusChange", "fieldRenderError", "ruleDiagnosticsChange"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
5896
5964
|
}
|
|
5897
5965
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormDialogHostComponent, decorators: [{
|
|
5898
5966
|
type: Component,
|
|
@@ -5953,17 +6021,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5953
6021
|
aria-labelledby="crudDialogTitle"
|
|
5954
6022
|
[attr.aria-describedby]="dialogSubtitle ? 'crudDialogDescription' : null"
|
|
5955
6023
|
>
|
|
5956
|
-
@if (resourceIdentity) {
|
|
5957
|
-
<div class="crud-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
6024
|
+
@if (showContextIdentity || resourceIdentity) {
|
|
6025
|
+
<div class="crud-operation-context" data-testid="crud-operation-context">
|
|
6026
|
+
@if (showContextIdentity) {
|
|
6027
|
+
<div class="crud-resource-identity" data-testid="crud-context-identity">
|
|
6028
|
+
<span class="crud-resource-identity__label" aria-hidden="true">
|
|
6029
|
+
{{ texts.relatedContextLabel }}
|
|
6030
|
+
</span>
|
|
6031
|
+
<praxis-resource-identity
|
|
6032
|
+
[identity]="contextIdentity"
|
|
6033
|
+
density="compact"
|
|
6034
|
+
[showKeyLabel]="true"
|
|
6035
|
+
[ariaLabel]="texts.relatedContextLabel"
|
|
6036
|
+
></praxis-resource-identity>
|
|
6037
|
+
</div>
|
|
6038
|
+
}
|
|
6039
|
+
@if (resourceIdentity) {
|
|
6040
|
+
<div class="crud-resource-identity" data-testid="crud-resource-identity">
|
|
6041
|
+
<span class="crud-resource-identity__label" aria-hidden="true">
|
|
6042
|
+
{{ resourceIdentityLabel }}
|
|
6043
|
+
</span>
|
|
6044
|
+
<praxis-resource-identity
|
|
6045
|
+
[identity]="resourceIdentity"
|
|
6046
|
+
density="compact"
|
|
6047
|
+
[showKeyLabel]="true"
|
|
6048
|
+
[ariaLabel]="resourceIdentityLabel"
|
|
6049
|
+
></praxis-resource-identity>
|
|
6050
|
+
</div>
|
|
6051
|
+
}
|
|
5967
6052
|
</div>
|
|
5968
6053
|
}
|
|
5969
6054
|
<praxis-dynamic-form
|
|
@@ -5987,7 +6072,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5987
6072
|
(formCancel)="onCancel()"
|
|
5988
6073
|
></praxis-dynamic-form>
|
|
5989
6074
|
</mat-dialog-content>
|
|
5990
|
-
`, styles: ["praxis-dynamic-form-dialog-host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}praxis-dynamic-form-dialog-host[data-density=compact]{--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}praxis-dynamic-form-dialog-host .dialog-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--dlg-pad);min-height:var(--dlg-header-h);padding:10px var(--dlg-pad);margin:0;background:var(--md-sys-color-surface-container-high);border-bottom:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-heading{display:grid;min-width:0;gap:2px}praxis-dynamic-form-dialog-host .dialog-title-icon{display:inline-grid;flex:0 0 auto;width:36px;height:36px;place-items:center;border-radius:10px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}praxis-dynamic-form-dialog-host .dialog-title-icon mat-icon{width:22px;height:22px;font-size:22px}praxis-dynamic-form-dialog-host .dialog-subtitle{display:-webkit-box;overflow:hidden;color:var(--md-sys-color-on-surface-variant);font-size:.82rem;font-weight:400;line-height:1.35;-webkit-box-orient:vertical;-webkit-line-clamp:2}praxis-dynamic-form-dialog-host .spacer{flex:1}praxis-dynamic-form-dialog-host .dialog-content{flex:1 1 auto;overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}praxis-dynamic-form-dialog-host .crud-
|
|
6075
|
+
`, styles: ["praxis-dynamic-form-dialog-host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}praxis-dynamic-form-dialog-host[data-density=compact]{--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}praxis-dynamic-form-dialog-host .dialog-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--dlg-pad);min-height:var(--dlg-header-h);padding:10px var(--dlg-pad);margin:0;background:var(--md-sys-color-surface-container-high);border-bottom:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-heading{display:grid;min-width:0;gap:2px}praxis-dynamic-form-dialog-host .dialog-title-icon{display:inline-grid;flex:0 0 auto;width:36px;height:36px;place-items:center;border-radius:10px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}praxis-dynamic-form-dialog-host .dialog-title-icon mat-icon{width:22px;height:22px;font-size:22px}praxis-dynamic-form-dialog-host .dialog-subtitle{display:-webkit-box;overflow:hidden;color:var(--md-sys-color-on-surface-variant);font-size:.82rem;font-weight:400;line-height:1.35;-webkit-box-orient:vertical;-webkit-line-clamp:2}praxis-dynamic-form-dialog-host .spacer{flex:1}praxis-dynamic-form-dialog-host .dialog-content{flex:1 1 auto;overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}praxis-dynamic-form-dialog-host .crud-operation-context{position:sticky;top:0;z-index:1;display:grid;gap:.75rem;margin-block-end:var(--dlg-pad);padding-block:.5rem .75rem;background:var(--pfx-form-surface, var(--md-sys-color-surface));border-bottom:1px solid var(--md-sys-color-outline-variant)}praxis-dynamic-form-dialog-host .crud-resource-identity{display:grid;gap:.25rem;min-width:0}praxis-dynamic-form-dialog-host .crud-resource-identity__label{color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typescale-label-medium, 500 .75rem/1rem inherit)}praxis-dynamic-form-dialog-host.praxis-drawer{--dlg-header-h: 72px;width:100%;min-width:0;max-width:100vw;height:100dvh;background:var(--pfx-form-surface, var(--md-sys-color-surface));color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-header{background:color-mix(in srgb,var(--md-sys-color-surface-container-high, var(--md-sys-color-surface)),transparent 4%)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content{max-height:none;min-height:0;padding:clamp(12px,2.4vw,24px)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button:hover{color:var(--md-sys-color-primary)}praxis-dynamic-form-dialog-host .dialog-footer{position:sticky;bottom:0;z-index:1;padding:var(--dlg-pad)}.pfx-blur-backdrop{background-color:var(--pfx-backdrop, rgba(15, 23, 42, .42))!important;backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%)}.pfx-transparent-backdrop{background-color:transparent!important}.cdk-overlay-pane.pfx-dialog-pane{overflow:hidden;transition:width .2s ease,height .2s ease,margin .2s ease}.cdk-overlay-pane.pfx-dialog-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane .mdc-dialog__surface{display:flex;flex-direction:column;width:100%;min-width:0;height:100%;max-height:inherit;overflow:hidden;background:var(--pfx-form-surface, var(--md-sys-color-surface))!important;border:1px solid var(--pfx-form-stroke, var(--md-sys-color-outline-variant))!important}.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mdc-dialog__surface{backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cdk-overlay-pane.pfx-drawer-pane{margin:0!important;border-radius:0!important;box-shadow:var(--md-sys-elevation-level3, 0 24px 80px rgba(15, 23, 42, .28)),0 0 0 1px color-mix(in srgb,var(--md-sys-color-outline, #64748b) 24%,transparent)}.cdk-overlay-pane.pfx-drawer-pane.pfx-drawer-maximized{margin:var(--pfx-drawer-edge-gap, 8px)!important}.cdk-overlay-pane.pfx-drawer-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-drawer-pane .mdc-dialog__surface{min-width:0!important;border-radius:0!important}\n"] }]
|
|
5991
6076
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
5992
6077
|
type: Inject,
|
|
5993
6078
|
args: [MatDialogRef]
|
|
@@ -6226,6 +6311,12 @@ const PRAXIS_CRUD_COMPONENT_METADATA = {
|
|
|
6226
6311
|
type: 'string',
|
|
6227
6312
|
description: 'Identificador opcional para múltiplas instâncias na mesma rota.',
|
|
6228
6313
|
},
|
|
6314
|
+
{
|
|
6315
|
+
name: 'tableConfigPersistenceStrategy',
|
|
6316
|
+
type: "'local-first' | 'input-first' | 'volatile'",
|
|
6317
|
+
default: 'local-first',
|
|
6318
|
+
description: 'Política da tabela interna. Use input-first para contratos governados autoritativos e volatile para previews que não devem ler nem gravar preferências locais.',
|
|
6319
|
+
},
|
|
6229
6320
|
{
|
|
6230
6321
|
name: 'context',
|
|
6231
6322
|
type: 'Record<string, unknown>',
|
|
@@ -6801,6 +6892,7 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
6801
6892
|
{ name: 'metadata', type: 'CrudMetadata | string', description: 'Canonical CRUD metadata or serialized metadata document.' },
|
|
6802
6893
|
{ name: 'crudId', type: 'string', description: 'Stable CRUD instance id used for table/form identity and persistence.' },
|
|
6803
6894
|
{ name: 'componentInstanceId', type: 'string', description: 'Optional stable host instance id for multiple CRUD widgets on the same route.' },
|
|
6895
|
+
{ name: 'tableConfigPersistenceStrategy', type: "'local-first' | 'input-first' | 'volatile'", description: 'Persistence precedence forwarded to the internal Praxis Table. Governed previews should use input-first or volatile explicitly.' },
|
|
6804
6896
|
{ name: 'context', type: 'Record<string, unknown>', description: 'Opaque host context used for authoring seeds and launcher inputs.' },
|
|
6805
6897
|
{ name: 'enableCustomization', type: 'boolean', description: 'Explicit host opt-in for CRUD authoring surfaces.' },
|
|
6806
6898
|
{ name: 'authoringCapability', type: 'string | null', description: 'Public runtime capability required before CRUD and delegated table authoring can open.' },
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/crud",
|
|
3
|
-
"version": "9.0.4-rc.
|
|
3
|
+
"version": "9.0.4-rc.26",
|
|
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": "^9.0.4-rc.
|
|
9
|
-
"@praxisui/table": "^9.0.4-rc.
|
|
10
|
-
"@praxisui/core": "^9.0.4-rc.
|
|
11
|
-
"@praxisui/dynamic-fields": "^9.0.4-rc.
|
|
12
|
-
"@praxisui/settings-panel": "^9.0.4-rc.
|
|
8
|
+
"@praxisui/dynamic-form": "^9.0.4-rc.26",
|
|
9
|
+
"@praxisui/table": "^9.0.4-rc.26",
|
|
10
|
+
"@praxisui/core": "^9.0.4-rc.26",
|
|
11
|
+
"@praxisui/dynamic-fields": "^9.0.4-rc.26",
|
|
12
|
+
"@praxisui/settings-panel": "^9.0.4-rc.26",
|
|
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": "^9.0.4-rc.
|
|
17
|
+
"@praxisui/ai": "^9.0.4-rc.26",
|
|
18
18
|
"rxjs": "~7.8.0"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
@@ -55,8 +55,10 @@ interface CrudDrawerOpenConfig {
|
|
|
55
55
|
action: CrudAction;
|
|
56
56
|
metadata: CrudMetadata;
|
|
57
57
|
inputs: Record<string, unknown>;
|
|
58
|
-
/** Read-only record context for
|
|
58
|
+
/** Read-only record context for existing-record drawers. It is never part of form inputs or submit payloads. */
|
|
59
59
|
resourceIdentity?: MaterializedResourceIdentity | null;
|
|
60
|
+
/** Read-only task scope for related operations. It is never part of form inputs or submit payloads. */
|
|
61
|
+
contextIdentity?: MaterializedResourceIdentity | null;
|
|
60
62
|
/**
|
|
61
63
|
* Notifica fechamento do drawer (cancelamento/fechamento externo/resultado finalizado).
|
|
62
64
|
*/
|
package/types/praxisui-crud.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { NgZone, OnChanges, EventEmitter, SimpleChanges, OnInit, Provider, After
|
|
|
3
3
|
import * as _praxisui_core from '@praxisui/core';
|
|
4
4
|
import { RowAction, ToolbarAction, ApiEndpoint, ApiUrlEntry, DynamicFormLayoutPolicy, BackConfig, TableConfig, PraxisDataQueryContext, FormConfig, ResourceActionCatalogItem, ResourceSurfaceCatalogItem, MaterializedResourceIdentity, LoadingState, RestApiLinks, ResourceCapabilitySnapshot, GenericCrudService, AsyncConfigStorage, ComponentDocMeta, AiCapabilityCatalog, AiCapability, AiCapabilityCategory, AiValueKind, ComponentAuthoringManifest, SettingsValueProvider } from '@praxisui/core';
|
|
5
5
|
export { BackConfig } from '@praxisui/core';
|
|
6
|
+
import { TableConfigPersistenceStrategy } from '@praxisui/table';
|
|
6
7
|
import { MatDialogConfig, MatDialogRef, MatDialog } from '@angular/material/dialog';
|
|
7
8
|
export { MAT_DIALOG_DATA as DIALOG_DATA } from '@angular/material/dialog';
|
|
8
9
|
import { ComponentType } from '@angular/cdk/portal';
|
|
@@ -170,6 +171,8 @@ declare class PraxisCrudComponent implements OnChanges {
|
|
|
170
171
|
metadata: CrudMetadata | string;
|
|
171
172
|
crudId: string;
|
|
172
173
|
componentInstanceId?: string;
|
|
174
|
+
/** Controls whether the CRUD's internal table trusts host input or stored user configuration. */
|
|
175
|
+
tableConfigPersistenceStrategy: TableConfigPersistenceStrategy;
|
|
173
176
|
context?: Record<string, unknown>;
|
|
174
177
|
enableCustomization: boolean;
|
|
175
178
|
/** Capability publica exigida para authoring governado do CRUD e da tabela interna. */
|
|
@@ -245,6 +248,7 @@ declare class PraxisCrudComponent implements OnChanges {
|
|
|
245
248
|
onToolbarAction(event: CrudActionRuntimeEvent): Promise<void>;
|
|
246
249
|
ngOnChanges(changes: SimpleChanges): void;
|
|
247
250
|
onAction(action: string, row?: Record<string, unknown>, runtimeEvent?: CrudActionRuntimeEvent): Promise<void>;
|
|
251
|
+
private resolveTaskScopeIdentity;
|
|
248
252
|
getOpeningActionStatus(actionLabel: string): string;
|
|
249
253
|
private resolveOpeningActionLabel;
|
|
250
254
|
private hasExplicitOpenBinding;
|
|
@@ -332,7 +336,7 @@ declare class PraxisCrudComponent implements OnChanges {
|
|
|
332
336
|
private txWithParams;
|
|
333
337
|
private interpolateTranslationParams;
|
|
334
338
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PraxisCrudComponent, never>;
|
|
335
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PraxisCrudComponent, "praxis-crud", never, { "metadata": { "alias": "metadata"; "required": true; }; "crudId": { "alias": "crudId"; "required": true; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; }; "context": { "alias": "context"; "required": false; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; }; "authoringCapability": { "alias": "authoringCapability"; "required": false; }; }, { "configureRequested": "configureRequested"; "afterOpen": "afterOpen"; "afterClose": "afterClose"; "afterSave": "afterSave"; "afterDelete": "afterDelete"; "error": "error"; "rowClick": "rowClick"; "selectionChange": "selectionChange"; "tableRuntimeConfigChange": "tableRuntimeConfigChange"; "crudAuthoringDocumentApplied": "crudAuthoringDocumentApplied"; "crudAuthoringDocumentSaved": "crudAuthoringDocumentSaved"; }, never, never, true, never>;
|
|
339
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PraxisCrudComponent, "praxis-crud", never, { "metadata": { "alias": "metadata"; "required": true; }; "crudId": { "alias": "crudId"; "required": true; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; }; "tableConfigPersistenceStrategy": { "alias": "tableConfigPersistenceStrategy"; "required": false; }; "context": { "alias": "context"; "required": false; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; }; "authoringCapability": { "alias": "authoringCapability"; "required": false; }; }, { "configureRequested": "configureRequested"; "afterOpen": "afterOpen"; "afterClose": "afterClose"; "afterSave": "afterSave"; "afterDelete": "afterDelete"; "error": "error"; "rowClick": "rowClick"; "selectionChange": "selectionChange"; "tableRuntimeConfigChange": "tableRuntimeConfigChange"; "crudAuthoringDocumentApplied": "crudAuthoringDocumentApplied"; "crudAuthoringDocumentSaved": "crudAuthoringDocumentSaved"; }, never, never, true, never>;
|
|
336
340
|
}
|
|
337
341
|
|
|
338
342
|
type CrudDrawerResultType = 'save' | 'delete' | 'close';
|
|
@@ -356,6 +360,7 @@ declare class CrudLauncherService {
|
|
|
356
360
|
capabilities?: ResourceCapabilitySnapshot | null;
|
|
357
361
|
links?: RestApiLinks | null;
|
|
358
362
|
resourceIdentity?: MaterializedResourceIdentity | null;
|
|
363
|
+
contextIdentity?: MaterializedResourceIdentity | null;
|
|
359
364
|
}): Promise<{
|
|
360
365
|
mode: FormOpenMode;
|
|
361
366
|
ref?: DialogRef<any>;
|
|
@@ -411,6 +416,7 @@ declare class DynamicFormDialogHostComponent implements OnInit {
|
|
|
411
416
|
resourceId?: string | number;
|
|
412
417
|
initialValue?: Record<string, unknown> | null;
|
|
413
418
|
resourceIdentity: MaterializedResourceIdentity | null;
|
|
419
|
+
contextIdentity: MaterializedResourceIdentity | null;
|
|
414
420
|
schemaUrl?: string | null;
|
|
415
421
|
submitUrl?: string | null;
|
|
416
422
|
submitMethod?: string | null;
|
|
@@ -425,6 +431,10 @@ declare class DynamicFormDialogHostComponent implements OnInit {
|
|
|
425
431
|
private idField;
|
|
426
432
|
texts: Record<string, string>;
|
|
427
433
|
constructor(dialogRef: DialogRef<DynamicFormDialogHostComponent>, data: any, dialogService: DialogService, crud: GenericCrudService<any>, configStorage: AsyncConfigStorage);
|
|
434
|
+
get resourceIdentityLabel(): string;
|
|
435
|
+
get showContextIdentity(): boolean;
|
|
436
|
+
private sameIdentity;
|
|
437
|
+
private identityLabel;
|
|
428
438
|
private extractInitialValue;
|
|
429
439
|
private resolveFormConfig;
|
|
430
440
|
get dialogTitle(): string;
|
|
@@ -685,6 +695,7 @@ interface PraxisCrudWidgetEditorInputs {
|
|
|
685
695
|
metadata?: CrudMetadata | string | null;
|
|
686
696
|
crudId?: string;
|
|
687
697
|
componentInstanceId?: string;
|
|
698
|
+
tableConfigPersistenceStrategy?: TableConfigPersistenceStrategy;
|
|
688
699
|
context?: Record<string, unknown>;
|
|
689
700
|
enableCustomization?: boolean;
|
|
690
701
|
authoringCapability?: string | null;
|