@praxisui/crud 9.0.4-rc.23 → 9.0.4-rc.25
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
CHANGED
|
@@ -194,6 +194,12 @@ outside the request schema and are never added to the update payload. Custom
|
|
|
194
194
|
drawer adapters receive the same `resourceIdentity` context and retain their own
|
|
195
195
|
presentation responsibility.
|
|
196
196
|
|
|
197
|
+
Related operations also receive `contextIdentity` when the governed surface
|
|
198
|
+
publishes `context.operation.taskScope`. The default host labels it as “Related
|
|
199
|
+
to” and keeps it distinct from the current child record. Both identities stay
|
|
200
|
+
outside dynamic-form inputs and submit payloads; capabilities and HATEOAS remain
|
|
201
|
+
the authority for whether the operation may execute.
|
|
202
|
+
|
|
197
203
|
Route mode has a different lifecycle because `@praxisui/crud` does not own the
|
|
198
204
|
destination component. Routed edit hosts must load the entity through the
|
|
199
205
|
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-04T21:23:28.566Z",
|
|
4
4
|
"packageName": "@praxisui/crud",
|
|
5
|
-
"packageVersion": "9.0.4-rc.
|
|
5
|
+
"packageVersion": "9.0.4-rc.25",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 2,
|
|
@@ -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
|
},
|
|
@@ -3863,6 +3870,7 @@ class PraxisCrudComponent {
|
|
|
3863
3870
|
action: this.normalizeCrudActionName(actionMeta?.action ?? normalizedAction),
|
|
3864
3871
|
};
|
|
3865
3872
|
const resourceIdentity = runtimeEvent?.resourceIdentity ?? null;
|
|
3873
|
+
const contextIdentity = this.resolveTaskScopeIdentity();
|
|
3866
3874
|
const handledByDuplicateDraft = await this.tryHandleCanonicalDuplicateDraftAction(effectiveAction, contextualRow);
|
|
3867
3875
|
if (handledByDuplicateDraft) {
|
|
3868
3876
|
return;
|
|
@@ -3911,6 +3919,7 @@ class PraxisCrudComponent {
|
|
|
3911
3919
|
: this.collectionCapabilities,
|
|
3912
3920
|
links: this.resolveCrudRuntimeLinks(effectiveAction.action, contextualRow),
|
|
3913
3921
|
resourceIdentity,
|
|
3922
|
+
contextIdentity,
|
|
3914
3923
|
});
|
|
3915
3924
|
this.afterOpen.emit({ mode, action: effectiveAction.action });
|
|
3916
3925
|
if (mode === 'drawer') {
|
|
@@ -3946,6 +3955,10 @@ class PraxisCrudComponent {
|
|
|
3946
3955
|
this.openingActionLabel.set(null);
|
|
3947
3956
|
}
|
|
3948
3957
|
}
|
|
3958
|
+
resolveTaskScopeIdentity() {
|
|
3959
|
+
const operation = normalizeSurfaceOperationContext(this.context?.['operation']);
|
|
3960
|
+
return operation?.taskScope?.identity ?? null;
|
|
3961
|
+
}
|
|
3949
3962
|
getOpeningActionStatus(actionLabel) {
|
|
3950
3963
|
return this.txWithParams('crud.actions.opening', 'Abrindo {action}…', { action: actionLabel });
|
|
3951
3964
|
}
|
|
@@ -5408,6 +5421,7 @@ class DynamicFormDialogHostComponent {
|
|
|
5408
5421
|
resourceId;
|
|
5409
5422
|
initialValue;
|
|
5410
5423
|
resourceIdentity = null;
|
|
5424
|
+
contextIdentity = null;
|
|
5411
5425
|
schemaUrl;
|
|
5412
5426
|
submitUrl;
|
|
5413
5427
|
submitMethod;
|
|
@@ -5427,6 +5441,8 @@ class DynamicFormDialogHostComponent {
|
|
|
5427
5441
|
maximizeLabel: 'Maximizar',
|
|
5428
5442
|
restoreLabel: 'Restaurar',
|
|
5429
5443
|
recordContextLabel: translateCrudRuntimeText(this.i18n, 'crud.dialog.recordContextLabel', 'Registro em edição'),
|
|
5444
|
+
viewRecordContextLabel: translateCrudRuntimeText(this.i18n, 'crud.dialog.viewRecordContextLabel', 'Registro em consulta'),
|
|
5445
|
+
relatedContextLabel: translateCrudRuntimeText(this.i18n, 'crud.dialog.relatedContextLabel', 'Vinculado a'),
|
|
5430
5446
|
discardTitle: 'Descartar alterações?',
|
|
5431
5447
|
discardMessage: 'Você tem alterações não salvas. Deseja fechar assim mesmo?',
|
|
5432
5448
|
discardConfirm: 'Descartar',
|
|
@@ -5477,9 +5493,12 @@ class DynamicFormDialogHostComponent {
|
|
|
5477
5493
|
this.apiUrlEntry = this.data.inputs?.['apiUrlEntry'] ?? null;
|
|
5478
5494
|
const act = this.data.action?.action;
|
|
5479
5495
|
this.mode = act === 'edit' ? 'edit' : act === 'view' ? 'view' : 'create';
|
|
5480
|
-
this.resourceIdentity = this.mode
|
|
5496
|
+
this.resourceIdentity = this.mode !== 'create' && this.data.resourceIdentity
|
|
5481
5497
|
? this.data.resourceIdentity
|
|
5482
5498
|
: null;
|
|
5499
|
+
this.contextIdentity = this.data.contextIdentity
|
|
5500
|
+
? this.data.contextIdentity
|
|
5501
|
+
: null;
|
|
5483
5502
|
this.formConfig = this.resolveFormConfig();
|
|
5484
5503
|
this.layoutPolicy = this.resolveLayoutPolicy();
|
|
5485
5504
|
this.formActions = this.resolveFormActions();
|
|
@@ -5515,6 +5534,32 @@ class DynamicFormDialogHostComponent {
|
|
|
5515
5534
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
5516
5535
|
.subscribe(() => this.saveState());
|
|
5517
5536
|
}
|
|
5537
|
+
get resourceIdentityLabel() {
|
|
5538
|
+
return this.mode === 'view'
|
|
5539
|
+
? this.texts['viewRecordContextLabel']
|
|
5540
|
+
: this.texts['recordContextLabel'];
|
|
5541
|
+
}
|
|
5542
|
+
get showContextIdentity() {
|
|
5543
|
+
return !!this.contextIdentity && !this.sameIdentity(this.contextIdentity, this.resourceIdentity);
|
|
5544
|
+
}
|
|
5545
|
+
sameIdentity(left, right) {
|
|
5546
|
+
if (!left || !right)
|
|
5547
|
+
return false;
|
|
5548
|
+
const leftKey = left.key;
|
|
5549
|
+
const rightKey = right.key;
|
|
5550
|
+
const leftLabel = this.identityLabel(left);
|
|
5551
|
+
const rightLabel = this.identityLabel(right);
|
|
5552
|
+
if (leftKey && rightKey) {
|
|
5553
|
+
return leftKey.field === rightKey.field
|
|
5554
|
+
&& String(leftKey.value) === String(rightKey.value)
|
|
5555
|
+
&& !!leftLabel
|
|
5556
|
+
&& leftLabel === rightLabel;
|
|
5557
|
+
}
|
|
5558
|
+
return !!leftLabel && leftLabel === rightLabel;
|
|
5559
|
+
}
|
|
5560
|
+
identityLabel(identity) {
|
|
5561
|
+
return String(identity.displayLabel || identity.title?.value || '').trim();
|
|
5562
|
+
}
|
|
5518
5563
|
extractInitialValue(inputs) {
|
|
5519
5564
|
if (!inputs || typeof inputs !== 'object') {
|
|
5520
5565
|
return null;
|
|
@@ -5858,17 +5903,34 @@ class DynamicFormDialogHostComponent {
|
|
|
5858
5903
|
aria-labelledby="crudDialogTitle"
|
|
5859
5904
|
[attr.aria-describedby]="dialogSubtitle ? 'crudDialogDescription' : null"
|
|
5860
5905
|
>
|
|
5861
|
-
@if (resourceIdentity) {
|
|
5862
|
-
<div class="crud-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5906
|
+
@if (showContextIdentity || resourceIdentity) {
|
|
5907
|
+
<div class="crud-operation-context" data-testid="crud-operation-context">
|
|
5908
|
+
@if (showContextIdentity) {
|
|
5909
|
+
<div class="crud-resource-identity" data-testid="crud-context-identity">
|
|
5910
|
+
<span class="crud-resource-identity__label" aria-hidden="true">
|
|
5911
|
+
{{ texts.relatedContextLabel }}
|
|
5912
|
+
</span>
|
|
5913
|
+
<praxis-resource-identity
|
|
5914
|
+
[identity]="contextIdentity"
|
|
5915
|
+
density="compact"
|
|
5916
|
+
[showKeyLabel]="true"
|
|
5917
|
+
[ariaLabel]="texts.relatedContextLabel"
|
|
5918
|
+
></praxis-resource-identity>
|
|
5919
|
+
</div>
|
|
5920
|
+
}
|
|
5921
|
+
@if (resourceIdentity) {
|
|
5922
|
+
<div class="crud-resource-identity" data-testid="crud-resource-identity">
|
|
5923
|
+
<span class="crud-resource-identity__label" aria-hidden="true">
|
|
5924
|
+
{{ resourceIdentityLabel }}
|
|
5925
|
+
</span>
|
|
5926
|
+
<praxis-resource-identity
|
|
5927
|
+
[identity]="resourceIdentity"
|
|
5928
|
+
density="compact"
|
|
5929
|
+
[showKeyLabel]="true"
|
|
5930
|
+
[ariaLabel]="resourceIdentityLabel"
|
|
5931
|
+
></praxis-resource-identity>
|
|
5932
|
+
</div>
|
|
5933
|
+
}
|
|
5872
5934
|
</div>
|
|
5873
5935
|
}
|
|
5874
5936
|
<praxis-dynamic-form
|
|
@@ -5892,7 +5954,7 @@ class DynamicFormDialogHostComponent {
|
|
|
5892
5954
|
(formCancel)="onCancel()"
|
|
5893
5955
|
></praxis-dynamic-form>
|
|
5894
5956
|
</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-
|
|
5957
|
+
`, 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
5958
|
}
|
|
5897
5959
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormDialogHostComponent, decorators: [{
|
|
5898
5960
|
type: Component,
|
|
@@ -5953,17 +6015,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5953
6015
|
aria-labelledby="crudDialogTitle"
|
|
5954
6016
|
[attr.aria-describedby]="dialogSubtitle ? 'crudDialogDescription' : null"
|
|
5955
6017
|
>
|
|
5956
|
-
@if (resourceIdentity) {
|
|
5957
|
-
<div class="crud-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
6018
|
+
@if (showContextIdentity || resourceIdentity) {
|
|
6019
|
+
<div class="crud-operation-context" data-testid="crud-operation-context">
|
|
6020
|
+
@if (showContextIdentity) {
|
|
6021
|
+
<div class="crud-resource-identity" data-testid="crud-context-identity">
|
|
6022
|
+
<span class="crud-resource-identity__label" aria-hidden="true">
|
|
6023
|
+
{{ texts.relatedContextLabel }}
|
|
6024
|
+
</span>
|
|
6025
|
+
<praxis-resource-identity
|
|
6026
|
+
[identity]="contextIdentity"
|
|
6027
|
+
density="compact"
|
|
6028
|
+
[showKeyLabel]="true"
|
|
6029
|
+
[ariaLabel]="texts.relatedContextLabel"
|
|
6030
|
+
></praxis-resource-identity>
|
|
6031
|
+
</div>
|
|
6032
|
+
}
|
|
6033
|
+
@if (resourceIdentity) {
|
|
6034
|
+
<div class="crud-resource-identity" data-testid="crud-resource-identity">
|
|
6035
|
+
<span class="crud-resource-identity__label" aria-hidden="true">
|
|
6036
|
+
{{ resourceIdentityLabel }}
|
|
6037
|
+
</span>
|
|
6038
|
+
<praxis-resource-identity
|
|
6039
|
+
[identity]="resourceIdentity"
|
|
6040
|
+
density="compact"
|
|
6041
|
+
[showKeyLabel]="true"
|
|
6042
|
+
[ariaLabel]="resourceIdentityLabel"
|
|
6043
|
+
></praxis-resource-identity>
|
|
6044
|
+
</div>
|
|
6045
|
+
}
|
|
5967
6046
|
</div>
|
|
5968
6047
|
}
|
|
5969
6048
|
<praxis-dynamic-form
|
|
@@ -5987,7 +6066,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5987
6066
|
(formCancel)="onCancel()"
|
|
5988
6067
|
></praxis-dynamic-form>
|
|
5989
6068
|
</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-
|
|
6069
|
+
`, 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
6070
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
5992
6071
|
type: Inject,
|
|
5993
6072
|
args: [MatDialogRef]
|
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.25",
|
|
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.25",
|
|
9
|
+
"@praxisui/table": "^9.0.4-rc.25",
|
|
10
|
+
"@praxisui/core": "^9.0.4-rc.25",
|
|
11
|
+
"@praxisui/dynamic-fields": "^9.0.4-rc.25",
|
|
12
|
+
"@praxisui/settings-panel": "^9.0.4-rc.25",
|
|
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.25",
|
|
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
|
@@ -245,6 +245,7 @@ declare class PraxisCrudComponent implements OnChanges {
|
|
|
245
245
|
onToolbarAction(event: CrudActionRuntimeEvent): Promise<void>;
|
|
246
246
|
ngOnChanges(changes: SimpleChanges): void;
|
|
247
247
|
onAction(action: string, row?: Record<string, unknown>, runtimeEvent?: CrudActionRuntimeEvent): Promise<void>;
|
|
248
|
+
private resolveTaskScopeIdentity;
|
|
248
249
|
getOpeningActionStatus(actionLabel: string): string;
|
|
249
250
|
private resolveOpeningActionLabel;
|
|
250
251
|
private hasExplicitOpenBinding;
|
|
@@ -356,6 +357,7 @@ declare class CrudLauncherService {
|
|
|
356
357
|
capabilities?: ResourceCapabilitySnapshot | null;
|
|
357
358
|
links?: RestApiLinks | null;
|
|
358
359
|
resourceIdentity?: MaterializedResourceIdentity | null;
|
|
360
|
+
contextIdentity?: MaterializedResourceIdentity | null;
|
|
359
361
|
}): Promise<{
|
|
360
362
|
mode: FormOpenMode;
|
|
361
363
|
ref?: DialogRef<any>;
|
|
@@ -411,6 +413,7 @@ declare class DynamicFormDialogHostComponent implements OnInit {
|
|
|
411
413
|
resourceId?: string | number;
|
|
412
414
|
initialValue?: Record<string, unknown> | null;
|
|
413
415
|
resourceIdentity: MaterializedResourceIdentity | null;
|
|
416
|
+
contextIdentity: MaterializedResourceIdentity | null;
|
|
414
417
|
schemaUrl?: string | null;
|
|
415
418
|
submitUrl?: string | null;
|
|
416
419
|
submitMethod?: string | null;
|
|
@@ -425,6 +428,10 @@ declare class DynamicFormDialogHostComponent implements OnInit {
|
|
|
425
428
|
private idField;
|
|
426
429
|
texts: Record<string, string>;
|
|
427
430
|
constructor(dialogRef: DialogRef<DynamicFormDialogHostComponent>, data: any, dialogService: DialogService, crud: GenericCrudService<any>, configStorage: AsyncConfigStorage);
|
|
431
|
+
get resourceIdentityLabel(): string;
|
|
432
|
+
get showContextIdentity(): boolean;
|
|
433
|
+
private sameIdentity;
|
|
434
|
+
private identityLabel;
|
|
428
435
|
private extractInitialValue;
|
|
429
436
|
private resolveFormConfig;
|
|
430
437
|
get dialogTitle(): string;
|