@praxisui/crud 9.0.0-beta.4 → 9.0.0-beta.41
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 +1 -1
- package/ai/component-registry.json +3604 -0
- package/fesm2022/praxisui-crud.mjs +124 -48
- package/package.json +12 -8
- package/types/praxisui-crud.d.ts +8 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, InjectionToken, inject, input, signal, computed, effect, ChangeDetectionStrategy, Component, EventEmitter, DestroyRef, ChangeDetectorRef, Injector, ViewChild, Output, Input, Inject, ENVIRONMENT_INITIALIZER } from '@angular/core';
|
|
2
|
+
import { Injectable, InjectionToken, inject, input, signal, computed, effect, ChangeDetectionStrategy, Component, EventEmitter, DestroyRef, ChangeDetectorRef, Injector, ViewChild, Output, Input, Inject, ViewEncapsulation, ENVIRONMENT_INITIALIZER } from '@angular/core';
|
|
3
3
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
4
|
import { HttpClient } from '@angular/common/http';
|
|
5
5
|
import { Router, ActivatedRoute, RouterLink } from '@angular/router';
|
|
@@ -10,6 +10,7 @@ import { ASYNC_CONFIG_STORAGE, GlobalConfigService, CrudOperationResolutionServi
|
|
|
10
10
|
import { SettingsPanelService } from '@praxisui/settings-panel';
|
|
11
11
|
import { PraxisTableInlineAuthoringEditorComponent, PraxisTable } from '@praxisui/table';
|
|
12
12
|
import { ConfirmDialogComponent } from '@praxisui/dynamic-fields';
|
|
13
|
+
import { take, filter } from 'rxjs/operators';
|
|
13
14
|
import * as i1 from '@angular/material/dialog';
|
|
14
15
|
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
15
16
|
export { MAT_DIALOG_DATA as DIALOG_DATA } from '@angular/material/dialog';
|
|
@@ -34,7 +35,6 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
|
|
34
35
|
import * as i10 from '@angular/material/tabs';
|
|
35
36
|
import { MatTabsModule } from '@angular/material/tabs';
|
|
36
37
|
import { PraxisDynamicForm } from '@praxisui/dynamic-form';
|
|
37
|
-
import { filter, take } from 'rxjs/operators';
|
|
38
38
|
|
|
39
39
|
class DialogService {
|
|
40
40
|
matDialog;
|
|
@@ -95,22 +95,6 @@ class CrudLauncherService {
|
|
|
95
95
|
await this.router.navigateByUrl(url);
|
|
96
96
|
return { mode };
|
|
97
97
|
}
|
|
98
|
-
if (mode === 'drawer' && this.drawerAdapter) {
|
|
99
|
-
const actionForLaunch = this.resolveActionForLaunch(merged.action, merged.metadata);
|
|
100
|
-
const inputs = this.mapInputs(actionForLaunch, row, merged.metadata, runtime);
|
|
101
|
-
const idField = merged.metadata.resource?.idField ?? 'id';
|
|
102
|
-
if (row && inputs[idField] === undefined && row[idField] !== undefined) {
|
|
103
|
-
inputs[idField] = row[idField];
|
|
104
|
-
}
|
|
105
|
-
await Promise.resolve(this.drawerAdapter.open({
|
|
106
|
-
action: actionForLaunch,
|
|
107
|
-
metadata: merged.metadata,
|
|
108
|
-
inputs,
|
|
109
|
-
onClose: drawerCallbacks?.onClose,
|
|
110
|
-
onResult: drawerCallbacks?.onResult,
|
|
111
|
-
}));
|
|
112
|
-
return { mode };
|
|
113
|
-
}
|
|
114
98
|
const actionForLaunch = this.resolveActionForLaunch(merged.action, merged.metadata);
|
|
115
99
|
if (!actionForLaunch.formId) {
|
|
116
100
|
throw new Error(`formId not provided for action ${actionForLaunch.action}`);
|
|
@@ -123,6 +107,16 @@ class CrudLauncherService {
|
|
|
123
107
|
row[idField] !== undefined) {
|
|
124
108
|
inputs[idField] = row[idField];
|
|
125
109
|
}
|
|
110
|
+
if (mode === 'drawer' && this.drawerAdapter) {
|
|
111
|
+
await Promise.resolve(this.drawerAdapter.open({
|
|
112
|
+
action: actionForLaunch,
|
|
113
|
+
metadata: merged.metadata,
|
|
114
|
+
inputs,
|
|
115
|
+
onClose: drawerCallbacks?.onClose,
|
|
116
|
+
onResult: drawerCallbacks?.onResult,
|
|
117
|
+
}));
|
|
118
|
+
return { mode };
|
|
119
|
+
}
|
|
126
120
|
const modalCfg = { ...(merged.metadata.defaults?.modal || {}) };
|
|
127
121
|
console.debug('[CRUD:Launcher] opening dialog with:', {
|
|
128
122
|
action: merged.action.action,
|
|
@@ -131,10 +125,8 @@ class CrudLauncherService {
|
|
|
131
125
|
modalCfg,
|
|
132
126
|
resourcePath: merged.metadata.resource?.path ?? merged.metadata.table?.resourcePath,
|
|
133
127
|
});
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
panelClasses.push(modalCfg.panelClass);
|
|
137
|
-
}
|
|
128
|
+
const drawerMode = mode === 'drawer';
|
|
129
|
+
const panelClasses = mergeClassList(['pfx-dialog-pane', drawerMode ? 'pfx-drawer-pane' : 'pfx-dialog-frosted'], modalCfg.panelClass);
|
|
138
130
|
// Backdrop style presets
|
|
139
131
|
const backdropClasses = [];
|
|
140
132
|
const style = modalCfg.backdropStyle;
|
|
@@ -147,20 +139,44 @@ class CrudLauncherService {
|
|
|
147
139
|
else if (style === 'transparent') {
|
|
148
140
|
backdropClasses.push('pfx-transparent-backdrop');
|
|
149
141
|
}
|
|
150
|
-
|
|
151
|
-
backdropClasses.push(modalCfg.backdropClass);
|
|
152
|
-
}
|
|
142
|
+
const mergedBackdropClasses = mergeClassList(backdropClasses, modalCfg.backdropClass);
|
|
153
143
|
const ref = await this.dialog.openAsync(() => Promise.resolve().then(function () { return dynamicFormDialogHost_component; }).then((m) => m.DynamicFormDialogHostComponent), {
|
|
154
144
|
...modalCfg,
|
|
155
145
|
panelClass: panelClasses,
|
|
156
|
-
backdropClass:
|
|
146
|
+
backdropClass: mergedBackdropClasses,
|
|
157
147
|
autoFocus: modalCfg.autoFocus ?? true,
|
|
158
148
|
restoreFocus: modalCfg.restoreFocus ?? true,
|
|
159
|
-
minWidth: '360px',
|
|
160
|
-
|
|
149
|
+
minWidth: drawerMode ? (modalCfg.minWidth ?? '0') : '360px',
|
|
150
|
+
width: drawerMode ? (modalCfg.width ?? 'min(560px, 100vw)') : modalCfg.width,
|
|
151
|
+
height: drawerMode ? (modalCfg.height ?? '100dvh') : modalCfg.height,
|
|
152
|
+
maxWidth: drawerMode ? (modalCfg.maxWidth ?? '100vw') : '95vw',
|
|
153
|
+
maxHeight: drawerMode ? (modalCfg.maxHeight ?? '100dvh') : modalCfg.maxHeight,
|
|
154
|
+
position: drawerMode ? (modalCfg.position ?? { right: '0', top: '0' }) : modalCfg.position,
|
|
161
155
|
ariaLabelledBy: 'crudDialogTitle',
|
|
162
|
-
data: {
|
|
156
|
+
data: {
|
|
157
|
+
action: actionForLaunch,
|
|
158
|
+
row,
|
|
159
|
+
metadata: merged.metadata,
|
|
160
|
+
inputs,
|
|
161
|
+
presentation: drawerMode ? 'drawer' : 'modal',
|
|
162
|
+
},
|
|
163
163
|
});
|
|
164
|
+
if (drawerMode) {
|
|
165
|
+
ref
|
|
166
|
+
.afterClosed()
|
|
167
|
+
.pipe(take(1))
|
|
168
|
+
.subscribe((closedValue) => {
|
|
169
|
+
const result = toCrudDrawerResult(closedValue);
|
|
170
|
+
drawerCallbacks?.onClose?.();
|
|
171
|
+
if (result?.type) {
|
|
172
|
+
drawerCallbacks?.onResult?.(result);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
drawerCallbacks?.onResult?.({ type: 'close' });
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
return { mode, ref };
|
|
179
|
+
}
|
|
164
180
|
return { mode, ref };
|
|
165
181
|
}
|
|
166
182
|
resolveOpenMode(action, metadata) {
|
|
@@ -248,6 +264,9 @@ class CrudLauncherService {
|
|
|
248
264
|
if (resolved.apiUrlEntry != null) {
|
|
249
265
|
inputs['apiUrlEntry'] = resolved.apiUrlEntry;
|
|
250
266
|
}
|
|
267
|
+
if (resolved.layoutPolicy != null) {
|
|
268
|
+
inputs['layoutPolicy'] = resolved.layoutPolicy;
|
|
269
|
+
}
|
|
251
270
|
if (action.form?.initialValue != null) {
|
|
252
271
|
inputs['initialValue'] = action.form.initialValue;
|
|
253
272
|
}
|
|
@@ -274,15 +293,18 @@ class CrudLauncherService {
|
|
|
274
293
|
submitMethod: action.form?.submitMethod ?? null,
|
|
275
294
|
apiEndpointKey: action.form?.apiEndpointKey ?? null,
|
|
276
295
|
apiUrlEntry: action.form?.apiUrlEntry ?? null,
|
|
296
|
+
layoutPolicy: action.form?.layoutPolicy ?? null,
|
|
277
297
|
};
|
|
278
298
|
}
|
|
279
299
|
if (!this.isCanonicalCrudAction(action.action)) {
|
|
280
300
|
return {
|
|
281
301
|
apiEndpointKey: action.form?.apiEndpointKey ?? null,
|
|
282
302
|
apiUrlEntry: action.form?.apiUrlEntry ?? null,
|
|
303
|
+
layoutPolicy: action.form?.layoutPolicy ?? null,
|
|
283
304
|
};
|
|
284
305
|
}
|
|
285
306
|
const resourcePath = String(metadata.resource?.path ?? metadata.table?.resourcePath ?? '').trim();
|
|
307
|
+
const schemaResourcePath = String(metadata.resource?.schemaPath || '').trim() || null;
|
|
286
308
|
if (!resourcePath) {
|
|
287
309
|
return {
|
|
288
310
|
apiEndpointKey: action.form?.apiEndpointKey ?? null,
|
|
@@ -294,6 +316,7 @@ class CrudLauncherService {
|
|
|
294
316
|
const resolved = this.operationResolver.resolve({
|
|
295
317
|
operation: action.action,
|
|
296
318
|
resourcePath,
|
|
319
|
+
schemaResourcePath,
|
|
297
320
|
resourceId: resourceId ?? null,
|
|
298
321
|
capabilities: runtime?.capabilities ?? null,
|
|
299
322
|
links: runtime?.links ?? null,
|
|
@@ -301,14 +324,15 @@ class CrudLauncherService {
|
|
|
301
324
|
endpointKey: action.form?.apiEndpointKey ??
|
|
302
325
|
metadata.resource?.endpointKey ??
|
|
303
326
|
undefined,
|
|
304
|
-
apiUrlEntry: action.form?.apiUrlEntry ?? null,
|
|
327
|
+
apiUrlEntry: action.form?.apiUrlEntry ?? metadata.resource?.apiUrlEntry ?? null,
|
|
305
328
|
});
|
|
306
329
|
return {
|
|
307
330
|
schemaUrl: resolved?.schemaUrl ?? null,
|
|
308
331
|
submitUrl: resolved?.submitUrl ?? null,
|
|
309
332
|
submitMethod: resolved?.submitMethod ?? null,
|
|
310
333
|
apiEndpointKey: action.form?.apiEndpointKey ?? metadata.resource?.endpointKey ?? null,
|
|
311
|
-
apiUrlEntry: action.form?.apiUrlEntry ?? null,
|
|
334
|
+
apiUrlEntry: action.form?.apiUrlEntry ?? metadata.resource?.apiUrlEntry ?? null,
|
|
335
|
+
layoutPolicy: action.form?.layoutPolicy ?? null,
|
|
312
336
|
};
|
|
313
337
|
}
|
|
314
338
|
resolveRuntimeContract(action, row, metadata, runtime) {
|
|
@@ -392,6 +416,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
392
416
|
type: Injectable,
|
|
393
417
|
args: [{ providedIn: 'root' }]
|
|
394
418
|
}] });
|
|
419
|
+
function mergeClassList(base, extra) {
|
|
420
|
+
if (!extra) {
|
|
421
|
+
return base;
|
|
422
|
+
}
|
|
423
|
+
if (typeof extra === 'string') {
|
|
424
|
+
return [...base, extra];
|
|
425
|
+
}
|
|
426
|
+
if (Array.isArray(extra)) {
|
|
427
|
+
return [...base, ...extra];
|
|
428
|
+
}
|
|
429
|
+
return [
|
|
430
|
+
...base,
|
|
431
|
+
...Object.keys(extra).filter((className) => !!extra[className]),
|
|
432
|
+
];
|
|
433
|
+
}
|
|
434
|
+
function toCrudDrawerResult(value) {
|
|
435
|
+
if (!value || typeof value !== 'object') {
|
|
436
|
+
return undefined;
|
|
437
|
+
}
|
|
438
|
+
const result = value;
|
|
439
|
+
return result.type === 'save' || result.type === 'delete' || result.type === 'close'
|
|
440
|
+
? result
|
|
441
|
+
: undefined;
|
|
442
|
+
}
|
|
395
443
|
|
|
396
444
|
const DOCUMENT_KIND = 'praxis.crud.editor';
|
|
397
445
|
const DOCUMENT_VERSION = 1;
|
|
@@ -3656,6 +3704,9 @@ class PraxisCrudComponent {
|
|
|
3656
3704
|
links: this.resolveCrudRuntimeLinks(effectiveAction.action, row),
|
|
3657
3705
|
});
|
|
3658
3706
|
this.afterOpen.emit({ mode, action: effectiveAction.action });
|
|
3707
|
+
if (mode === 'drawer') {
|
|
3708
|
+
return;
|
|
3709
|
+
}
|
|
3659
3710
|
if (!ref) {
|
|
3660
3711
|
return;
|
|
3661
3712
|
}
|
|
@@ -3999,7 +4050,7 @@ class PraxisCrudComponent {
|
|
|
3999
4050
|
const providedAction = this.resolveProvidedWorkflowAction(normalizedAction, runtimeEvent?.actionConfig);
|
|
4000
4051
|
const catalog = providedAction ? null : await this.resolveDiscoveredActionCatalog(row);
|
|
4001
4052
|
const discoveredAction = providedAction || this.selectDiscoveredWorkflowAction(normalizedAction, catalog?.actions || []);
|
|
4002
|
-
const resourcePath = String(this.resolveResourcePath(this.resolvedMetadata) ||
|
|
4053
|
+
const resourcePath = String(catalog?.resourcePath || this.resolveResourcePath(this.resolvedMetadata) || '').trim();
|
|
4003
4054
|
if (!discoveredAction || !resourcePath) {
|
|
4004
4055
|
return false;
|
|
4005
4056
|
}
|
|
@@ -4657,7 +4708,7 @@ class PraxisCrudComponent {
|
|
|
4657
4708
|
/>
|
|
4658
4709
|
}
|
|
4659
4710
|
}
|
|
4660
|
-
`, isInline: true, styles: [":host{display:block;width:100%;min-width:0;max-width:100%}\n"], dependencies: [{ kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "dense"], outputs: ["rowClick", "widgetEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }] });
|
|
4711
|
+
`, isInline: true, styles: [":host{display:block;width:100%;min-width:0;max-width:100%}\n"], dependencies: [{ kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "dense"], outputs: ["rowClick", "widgetEvent", "resourceEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "columnResize", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }] });
|
|
4661
4712
|
}
|
|
4662
4713
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisCrudComponent, decorators: [{
|
|
4663
4714
|
type: Component,
|
|
@@ -4742,6 +4793,7 @@ class DynamicFormDialogHostComponent {
|
|
|
4742
4793
|
configStorage;
|
|
4743
4794
|
formComp;
|
|
4744
4795
|
modal = {};
|
|
4796
|
+
presentation = 'modal';
|
|
4745
4797
|
maximized = false;
|
|
4746
4798
|
initialSize = {};
|
|
4747
4799
|
rememberState = false;
|
|
@@ -4756,6 +4808,7 @@ class DynamicFormDialogHostComponent {
|
|
|
4756
4808
|
submitMethod;
|
|
4757
4809
|
apiEndpointKey;
|
|
4758
4810
|
apiUrlEntry;
|
|
4811
|
+
layoutPolicy;
|
|
4759
4812
|
formActions;
|
|
4760
4813
|
mode = 'create';
|
|
4761
4814
|
backConfig;
|
|
@@ -4778,6 +4831,7 @@ class DynamicFormDialogHostComponent {
|
|
|
4778
4831
|
this.crud = crud;
|
|
4779
4832
|
this.configStorage = configStorage;
|
|
4780
4833
|
this.dialogRef.disableClose = true;
|
|
4834
|
+
this.presentation = this.data.presentation === 'drawer' ? 'drawer' : 'modal';
|
|
4781
4835
|
// i18n
|
|
4782
4836
|
this.texts = {
|
|
4783
4837
|
...this.texts,
|
|
@@ -4812,6 +4866,7 @@ class DynamicFormDialogHostComponent {
|
|
|
4812
4866
|
this.apiUrlEntry = this.data.inputs?.['apiUrlEntry'] ?? null;
|
|
4813
4867
|
const act = this.data.action?.action;
|
|
4814
4868
|
this.mode = act === 'edit' ? 'edit' : act === 'view' ? 'view' : 'create';
|
|
4869
|
+
this.layoutPolicy = this.resolveLayoutPolicy();
|
|
4815
4870
|
this.formActions = this.resolveFormActions();
|
|
4816
4871
|
// Back config: defaults from metadata/action, overridden by saved per-form config
|
|
4817
4872
|
const defaults = (this.data.action?.back || this.data.metadata?.defaults?.back) || {};
|
|
@@ -4857,6 +4912,7 @@ class DynamicFormDialogHostComponent {
|
|
|
4857
4912
|
'apiEndpointKey',
|
|
4858
4913
|
'apiUrlEntry',
|
|
4859
4914
|
'initialValue',
|
|
4915
|
+
'layoutPolicy',
|
|
4860
4916
|
]);
|
|
4861
4917
|
const explicit = inputs['initialValue'] && typeof inputs['initialValue'] === 'object'
|
|
4862
4918
|
? { ...inputs['initialValue'] }
|
|
@@ -4890,6 +4946,15 @@ class DynamicFormDialogHostComponent {
|
|
|
4890
4946
|
},
|
|
4891
4947
|
};
|
|
4892
4948
|
}
|
|
4949
|
+
resolveLayoutPolicy() {
|
|
4950
|
+
const explicit = this.data.inputs?.['layoutPolicy'] ??
|
|
4951
|
+
this.data.action?.form?.layoutPolicy ??
|
|
4952
|
+
this.data.action?.layoutPolicy;
|
|
4953
|
+
if (explicit && typeof explicit === 'object') {
|
|
4954
|
+
return explicit;
|
|
4955
|
+
}
|
|
4956
|
+
return null;
|
|
4957
|
+
}
|
|
4893
4958
|
resolveSubmitLabel() {
|
|
4894
4959
|
const action = this.data.action ?? {};
|
|
4895
4960
|
const explicit = stringOrUndefined(action.form?.submitLabel ??
|
|
@@ -4962,10 +5027,10 @@ class DynamicFormDialogHostComponent {
|
|
|
4962
5027
|
ref
|
|
4963
5028
|
.afterClosed()
|
|
4964
5029
|
.pipe(filter((confirmed) => !!confirmed), takeUntilDestroyed(this.destroyRef))
|
|
4965
|
-
.subscribe(() => this.dialogRef.close());
|
|
5030
|
+
.subscribe(() => this.dialogRef.close({ type: 'close' }));
|
|
4966
5031
|
}
|
|
4967
5032
|
else {
|
|
4968
|
-
this.dialogRef.close();
|
|
5033
|
+
this.dialogRef.close({ type: 'close' });
|
|
4969
5034
|
}
|
|
4970
5035
|
}
|
|
4971
5036
|
toggleMaximize(initial = false) {
|
|
@@ -5032,7 +5097,7 @@ class DynamicFormDialogHostComponent {
|
|
|
5032
5097
|
}
|
|
5033
5098
|
}
|
|
5034
5099
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormDialogHostComponent, deps: [{ token: MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: DialogService }, { token: i2$1.GenericCrudService }, { token: ASYNC_CONFIG_STORAGE }], target: i0.ɵɵFactoryTarget.Component });
|
|
5035
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicFormDialogHostComponent, isStandalone: true, selector: "praxis-dynamic-form-dialog-host", host: { properties: { "attr.data-density": "modal.density || \"default\"" }, classAttribute: "praxis-dialog" }, providers: [GenericCrudService], viewQueries: [{ propertyName: "formComp", first: true, predicate: PraxisDynamicForm, descendants: true }], ngImport: i0, template: `
|
|
5100
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicFormDialogHostComponent, isStandalone: true, selector: "praxis-dynamic-form-dialog-host", host: { properties: { "attr.data-density": "modal.density || \"default\"", "attr.data-presentation": "presentation", "class.praxis-drawer": "presentation === \"drawer\"" }, classAttribute: "praxis-dialog" }, providers: [GenericCrudService], viewQueries: [{ propertyName: "formComp", first: true, predicate: PraxisDynamicForm, descendants: true }], ngImport: i0, template: `
|
|
5036
5101
|
<div mat-dialog-title class="dialog-header">
|
|
5037
5102
|
<h2 id="crudDialogTitle" class="dialog-title">
|
|
5038
5103
|
{{ data.action?.label || texts.title }}
|
|
@@ -5074,6 +5139,7 @@ class DynamicFormDialogHostComponent {
|
|
|
5074
5139
|
[submitMethod]="submitMethod"
|
|
5075
5140
|
[apiEndpointKey]="apiEndpointKey"
|
|
5076
5141
|
[apiUrlEntry]="apiUrlEntry"
|
|
5142
|
+
[layoutPolicy]="layoutPolicy"
|
|
5077
5143
|
[presentationModeGlobal]="mode === 'view' ? true : null"
|
|
5078
5144
|
[backConfig]="backConfig"
|
|
5079
5145
|
[actions]="formActions"
|
|
@@ -5081,7 +5147,7 @@ class DynamicFormDialogHostComponent {
|
|
|
5081
5147
|
(formCancel)="onCancel()"
|
|
5082
5148
|
></praxis-dynamic-form>
|
|
5083
5149
|
</mat-dialog-content>
|
|
5084
|
-
`, isInline: true, styles: ["
|
|
5150
|
+
`, 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);padding:0 var(--dlg-pad);height:var(--dlg-header-h);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 .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.praxis-drawer{--dlg-header-h: 64px;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.mat-icon-button{color:var(--md-sys-color-on-surface-variant)}praxis-dynamic-form-dialog-host .dialog-header button.mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}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%;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 .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-drawer-pane .mdc-dialog__surface{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: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisDynamicForm, selector: "praxis-dynamic-form", inputs: ["resourcePath", "resourceId", "initialValue", "editorialContext", "mode", "config", "actions", "schemaSource", "schemaUrl", "readUrl", "submitUrl", "submitMethod", "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 });
|
|
5085
5151
|
}
|
|
5086
5152
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormDialogHostComponent, decorators: [{
|
|
5087
5153
|
type: Component,
|
|
@@ -5091,9 +5157,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5091
5157
|
MatIconModule,
|
|
5092
5158
|
PraxisIconDirective,
|
|
5093
5159
|
PraxisDynamicForm
|
|
5094
|
-
], providers: [GenericCrudService], host: {
|
|
5160
|
+
], encapsulation: ViewEncapsulation.None, providers: [GenericCrudService], host: {
|
|
5095
5161
|
class: 'praxis-dialog',
|
|
5096
5162
|
'[attr.data-density]': 'modal.density || "default"',
|
|
5163
|
+
'[attr.data-presentation]': 'presentation',
|
|
5164
|
+
'[class.praxis-drawer]': 'presentation === "drawer"',
|
|
5097
5165
|
}, template: `
|
|
5098
5166
|
<div mat-dialog-title class="dialog-header">
|
|
5099
5167
|
<h2 id="crudDialogTitle" class="dialog-title">
|
|
@@ -5136,6 +5204,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5136
5204
|
[submitMethod]="submitMethod"
|
|
5137
5205
|
[apiEndpointKey]="apiEndpointKey"
|
|
5138
5206
|
[apiUrlEntry]="apiUrlEntry"
|
|
5207
|
+
[layoutPolicy]="layoutPolicy"
|
|
5139
5208
|
[presentationModeGlobal]="mode === 'view' ? true : null"
|
|
5140
5209
|
[backConfig]="backConfig"
|
|
5141
5210
|
[actions]="formActions"
|
|
@@ -5143,7 +5212,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5143
5212
|
(formCancel)="onCancel()"
|
|
5144
5213
|
></praxis-dynamic-form>
|
|
5145
5214
|
</mat-dialog-content>
|
|
5146
|
-
`, styles: ["
|
|
5215
|
+
`, 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);padding:0 var(--dlg-pad);height:var(--dlg-header-h);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 .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.praxis-drawer{--dlg-header-h: 64px;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.mat-icon-button{color:var(--md-sys-color-on-surface-variant)}praxis-dynamic-form-dialog-host .dialog-header button.mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}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%;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 .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-drawer-pane .mdc-dialog__surface{border-radius:0!important}\n"] }]
|
|
5147
5216
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
5148
5217
|
type: Inject,
|
|
5149
5218
|
args: [MatDialogRef]
|
|
@@ -5325,6 +5394,11 @@ const PRAXIS_CRUD_COMPONENT_METADATA = {
|
|
|
5325
5394
|
type: 'PraxisDataQueryContext | null',
|
|
5326
5395
|
description: 'Contexto semântico de consulta encaminhado para a tabela interna do CRUD. Preferir este contrato para novo authoring remoto.',
|
|
5327
5396
|
},
|
|
5397
|
+
{
|
|
5398
|
+
name: 'metadata.resource.schemaPath',
|
|
5399
|
+
type: 'string | null',
|
|
5400
|
+
description: 'Template canonico opcional usado apenas para resolver /schemas/filtered quando resource.path precisa ser um alvo operacional concreto.',
|
|
5401
|
+
},
|
|
5328
5402
|
{
|
|
5329
5403
|
name: 'metadata.filterCriteria',
|
|
5330
5404
|
type: 'Record<string, unknown> | null',
|
|
@@ -5699,6 +5773,7 @@ const CRUD_AI_CAPABILITIES = {
|
|
|
5699
5773
|
{ path: 'actions[].params[].to', category: 'actions', valueKind: 'enum', allowedValues: ENUMS.paramTarget, description: 'Destino do parametro.' },
|
|
5700
5774
|
{ path: 'actions[].params[].name', category: 'actions', valueKind: 'string', description: 'Nome do parametro no destino.' },
|
|
5701
5775
|
{ path: 'actions[].form.initialValue', category: 'actions', valueKind: 'object', description: 'Seed fixo do formulario injetado em inputs.initialValue antes da abertura.' },
|
|
5776
|
+
{ path: 'actions[].form.layoutPolicy', category: 'actions', valueKind: 'object', description: 'Politica schema-driven opt-in encaminhada ao Dynamic Form para materializar detalhe ou command form sem FormConfig.sections local; deve acompanhar schemaUrl compativel, especialmente schemaType=request para comandos.' },
|
|
5702
5777
|
{ path: 'actions[].back', category: 'navigation', valueKind: 'object', description: 'BackConfig por acao.' },
|
|
5703
5778
|
{ path: 'actions[].back.strategy', category: 'navigation', valueKind: 'enum', allowedValues: ENUMS.backStrategy, description: 'Estrategia de retorno da acao (auto, close, navigate).' },
|
|
5704
5779
|
{ path: 'actions[].back.returnTo', category: 'navigation', valueKind: 'string', description: 'Rota ou destino usado quando a estrategia de retorno for navigate.' },
|
|
@@ -5736,6 +5811,7 @@ const surfaceConfigureSchema = {
|
|
|
5736
5811
|
submitMethod: { enum: ['post', 'put', 'patch', 'delete'] },
|
|
5737
5812
|
apiEndpointKey: { type: 'string' },
|
|
5738
5813
|
initialValue: { type: 'object' },
|
|
5814
|
+
layoutPolicy: { type: 'object' },
|
|
5739
5815
|
},
|
|
5740
5816
|
},
|
|
5741
5817
|
params: {
|
|
@@ -5854,7 +5930,7 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
5854
5930
|
{ name: 'afterDelete', type: '{ id: string | number }', description: 'Emitted after delete; CRUD refetches the list.' },
|
|
5855
5931
|
],
|
|
5856
5932
|
editableTargets: [
|
|
5857
|
-
{ kind: 'resourceBinding', resolver: 'crud-resource-by-path-or-key', description: 'Resource path/key, id field, endpoint key and query context owned by CRUD orchestration.' },
|
|
5933
|
+
{ kind: 'resourceBinding', resolver: 'crud-resource-by-path-or-key', description: 'Resource path/key, optional schema path template, id field, endpoint key and query context owned by CRUD orchestration.' },
|
|
5858
5934
|
{ kind: 'listSurface', resolver: 'crud-list-surface', description: 'CRUD-hosted list surface and table delegation boundary.' },
|
|
5859
5935
|
{ kind: 'createSurface', resolver: 'crud-action-by-id:create', description: 'Create action open mode, route/form binding and launcher inputs.' },
|
|
5860
5936
|
{ kind: 'editSurface', resolver: 'crud-action-by-id:edit', description: 'Edit action open mode, route/form binding and launcher inputs.' },
|
|
@@ -5877,13 +5953,13 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
5877
5953
|
effects: [{ kind: 'compile-domain-patch', handler: 'crud-resource-bind', handlerContract: {
|
|
5878
5954
|
reads: ['CrudMetadata.resource', 'api_metadata', 'ResourceDiscoveryService', 'GET /{resource}/capabilities'],
|
|
5879
5955
|
writes: ['CrudMetadata.resource', 'CrudMetadata.queryContext', 'PraxisCrudComponent.tableCrudContext'],
|
|
5880
|
-
identityKeys: ['resourcePath', 'resourceKey'],
|
|
5956
|
+
identityKeys: ['resourcePath', 'resourceKey', 'schemaPath'],
|
|
5881
5957
|
inputSchema: resourceBindSchema,
|
|
5882
5958
|
failureModes: ['resource-not-found', 'schema-url-not-canonical', 'capabilities-unavailable', 'id-field-missing'],
|
|
5883
|
-
description: 'Binds CRUD to a canonical resource and validates it against api_metadata/resource capabilities before runtime use.',
|
|
5959
|
+
description: 'Binds CRUD to a canonical resource and validates it against api_metadata/resource capabilities before runtime use. Use CrudMetadata.resource.schemaPath when schema discovery must use a templated path while resource.path targets a concrete nested collection.',
|
|
5884
5960
|
} }],
|
|
5885
5961
|
validators: ['resource-exists-in-api-metadata', 'resource-path-canonical', 'resource-key-stable', 'id-field-known', 'resource-capabilities-resolvable'],
|
|
5886
|
-
affectedPaths: ['resource.path', 'resource.idField', 'resource.endpointKey', 'queryContext', 'filterCriteria'],
|
|
5962
|
+
affectedPaths: ['resource.path', 'resource.schemaPath', 'resource.idField', 'resource.endpointKey', 'resource.apiUrlEntry', 'queryContext', 'filterCriteria'],
|
|
5887
5963
|
submissionImpact: 'affects-remote-binding',
|
|
5888
5964
|
preconditions: ['crud-metadata-loaded', 'api-metadata-available'],
|
|
5889
5965
|
},
|
|
@@ -6017,14 +6093,14 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
6017
6093
|
target: { kind: 'dialogHost', resolver: 'crud-dialog-host-defaults', ambiguityPolicy: 'fail', required: true },
|
|
6018
6094
|
inputSchema: dialogHostSchema,
|
|
6019
6095
|
effects: [{ kind: 'compile-domain-patch', handler: 'crud-dialog-host-set', handlerContract: {
|
|
6020
|
-
reads: ['CrudMetadata.defaults', 'CrudLauncherService.resolveOpenMode', 'DialogService', 'CRUD_DRAWER_ADAPTER'],
|
|
6096
|
+
reads: ['CrudMetadata.defaults', 'CrudLauncherService.resolveOpenMode', 'DialogService', 'DynamicFormDialogHostComponent', 'CRUD_DRAWER_ADAPTER'],
|
|
6021
6097
|
writes: ['CrudMetadata.defaults.openMode', 'CrudMetadata.defaults.modal', 'CrudMetadata.defaults.back'],
|
|
6022
6098
|
identityKeys: ['crudId'],
|
|
6023
6099
|
inputSchema: dialogHostSchema,
|
|
6024
|
-
failureModes: ['open-mode-unsupported', 'drawer-
|
|
6025
|
-
description: 'Configures CRUD-owned route/modal/drawer defaults consumed by the launcher
|
|
6100
|
+
failureModes: ['open-mode-unsupported', 'drawer-runtime-unavailable', 'modal-size-invalid', 'back-policy-invalid'],
|
|
6101
|
+
description: 'Configures CRUD-owned route/modal/drawer defaults consumed by the launcher, default dialog-backed drawer runtime and optional host drawer adapter.',
|
|
6026
6102
|
} }],
|
|
6027
|
-
validators: ['open-mode-supported', 'modal-size-valid', 'drawer-
|
|
6103
|
+
validators: ['open-mode-supported', 'modal-size-valid', 'drawer-runtime-available', 'back-policy-valid', 'settings-panel-shell-compatible'],
|
|
6028
6104
|
affectedPaths: ['defaults.openMode', 'defaults.modal', 'defaults.back'],
|
|
6029
6105
|
submissionImpact: 'config-only',
|
|
6030
6106
|
preconditions: ['crud-metadata-loaded'],
|
|
@@ -6100,7 +6176,7 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
6100
6176
|
{ validatorId: 'permissions-delete-valid', level: 'error', code: 'CRUD_DELETE_PERMISSION_VALID', description: 'Delete permission cannot bypass resource capabilities or confirmation policy.' },
|
|
6101
6177
|
{ validatorId: 'open-mode-supported', level: 'error', code: 'CRUD_OPEN_MODE_SUPPORTED', description: 'Open mode must be route, modal or drawer.' },
|
|
6102
6178
|
{ validatorId: 'modal-size-valid', level: 'error', code: 'CRUD_MODAL_SIZE_VALID', description: 'Modal sizing defaults must be valid DialogConfig values.' },
|
|
6103
|
-
{ validatorId: 'drawer-
|
|
6179
|
+
{ validatorId: 'drawer-runtime-available', level: 'error', code: 'CRUD_DRAWER_RUNTIME_AVAILABLE', description: 'Drawer open mode uses the default dialog-backed drawer runtime with CRUD-owned chrome, responsive right-panel sizing, Escape/backdrop handling and semantic close/save results; a host drawer adapter is optional only for shell-specific presentation.' },
|
|
6104
6180
|
{ validatorId: 'back-policy-valid', level: 'error', code: 'CRUD_BACK_POLICY_VALID', description: 'Back policy must be valid for route/modal/drawer behavior.' },
|
|
6105
6181
|
{ validatorId: 'settings-panel-shell-compatible', level: 'warning', code: 'CRUD_SETTINGS_PANEL_COMPATIBLE', description: 'Authoring shell must preserve apply/save/reset semantics.' },
|
|
6106
6182
|
{ validatorId: 'action-permission-supported', level: 'error', code: 'CRUD_ACTION_PERMISSION_SUPPORTED', description: 'Action permissions must map to supported resource capabilities.' },
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/crud",
|
|
3
|
-
"version": "9.0.0-beta.
|
|
3
|
+
"version": "9.0.0-beta.41",
|
|
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.0-beta.
|
|
9
|
-
"@praxisui/table": "^9.0.0-beta.
|
|
10
|
-
"@praxisui/core": "^9.0.0-beta.
|
|
11
|
-
"@praxisui/dynamic-fields": "^9.0.0-beta.
|
|
12
|
-
"@praxisui/settings-panel": "^9.0.0-beta.
|
|
8
|
+
"@praxisui/dynamic-form": "^9.0.0-beta.41",
|
|
9
|
+
"@praxisui/table": "^9.0.0-beta.41",
|
|
10
|
+
"@praxisui/core": "^9.0.0-beta.41",
|
|
11
|
+
"@praxisui/dynamic-fields": "^9.0.0-beta.41",
|
|
12
|
+
"@praxisui/settings-panel": "^9.0.0-beta.41",
|
|
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.0-beta.
|
|
17
|
+
"@praxisui/ai": "^9.0.0-beta.41",
|
|
18
18
|
"rxjs": "~7.8.0"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"keywords": [
|
|
29
29
|
"angular",
|
|
30
30
|
"praxisui",
|
|
31
|
+
"praxis",
|
|
31
32
|
"crud",
|
|
32
33
|
"admin",
|
|
33
34
|
"backoffice",
|
|
@@ -48,7 +49,10 @@
|
|
|
48
49
|
"./drawer-adapter": {
|
|
49
50
|
"types": "./types/praxisui-crud-drawer-adapter.d.ts",
|
|
50
51
|
"default": "./fesm2022/praxisui-crud-drawer-adapter.mjs"
|
|
52
|
+
},
|
|
53
|
+
"./ai/component-registry.json": {
|
|
54
|
+
"default": "./ai/component-registry.json"
|
|
51
55
|
}
|
|
52
56
|
},
|
|
53
57
|
"type": "module"
|
|
54
|
-
}
|
|
58
|
+
}
|
package/types/praxisui-crud.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _praxisui_core from '@praxisui/core';
|
|
2
|
-
import { RowAction, ToolbarAction, ApiEndpoint, ApiUrlEntry, BackConfig, TableConfig, PraxisDataQueryContext, FormConfig, ResourceActionCatalogItem, ResourceSurfaceCatalogItem, LoadingState, RestApiLinks, ResourceCapabilitySnapshot, GenericCrudService, AsyncConfigStorage, ComponentDocMeta, AiCapabilityCatalog, AiCapability, AiCapabilityCategory, AiValueKind, ComponentAuthoringManifest, SettingsValueProvider } from '@praxisui/core';
|
|
2
|
+
import { RowAction, ToolbarAction, ApiEndpoint, ApiUrlEntry, DynamicFormLayoutPolicy, BackConfig, TableConfig, PraxisDataQueryContext, FormConfig, ResourceActionCatalogItem, ResourceSurfaceCatalogItem, LoadingState, RestApiLinks, ResourceCapabilitySnapshot, GenericCrudService, AsyncConfigStorage, ComponentDocMeta, AiCapabilityCatalog, AiCapability, AiCapabilityCategory, AiValueKind, ComponentAuthoringManifest, SettingsValueProvider } from '@praxisui/core';
|
|
3
3
|
export { BackConfig } from '@praxisui/core';
|
|
4
4
|
import * as _angular_core from '@angular/core';
|
|
5
5
|
import { NgZone, OnChanges, EventEmitter, SimpleChanges, OnInit, Provider, AfterViewInit, OnDestroy } from '@angular/core';
|
|
@@ -53,6 +53,7 @@ interface CrudActionFormContract {
|
|
|
53
53
|
apiEndpointKey?: ApiEndpoint | string | null;
|
|
54
54
|
apiUrlEntry?: ApiUrlEntry | null;
|
|
55
55
|
initialValue?: Record<string, unknown> | null;
|
|
56
|
+
layoutPolicy?: DynamicFormLayoutPolicy | null;
|
|
56
57
|
}
|
|
57
58
|
type CrudActionResolutionMode = 'inferred' | 'explicit';
|
|
58
59
|
type CrudAction = (RowAction | ToolbarAction) & {
|
|
@@ -72,8 +73,10 @@ interface CrudDefaults {
|
|
|
72
73
|
}
|
|
73
74
|
interface CrudResource {
|
|
74
75
|
path: string;
|
|
76
|
+
schemaPath?: string | null;
|
|
75
77
|
idField?: string | number;
|
|
76
78
|
endpointKey?: ApiEndpoint;
|
|
79
|
+
apiUrlEntry?: ApiUrlEntry | null;
|
|
77
80
|
}
|
|
78
81
|
interface CrudMetadata {
|
|
79
82
|
component: 'praxis-crud';
|
|
@@ -316,6 +319,7 @@ declare class CrudLauncherService {
|
|
|
316
319
|
submitMethod?: string | null;
|
|
317
320
|
apiEndpointKey?: unknown;
|
|
318
321
|
apiUrlEntry?: unknown;
|
|
322
|
+
layoutPolicy?: unknown;
|
|
319
323
|
};
|
|
320
324
|
private buildInferredFormId;
|
|
321
325
|
private isCanonicalCrudAction;
|
|
@@ -333,6 +337,7 @@ declare class DynamicFormDialogHostComponent implements OnInit {
|
|
|
333
337
|
private configStorage;
|
|
334
338
|
formComp?: PraxisDynamicForm;
|
|
335
339
|
modal: any;
|
|
340
|
+
presentation: 'modal' | 'drawer';
|
|
336
341
|
maximized: boolean;
|
|
337
342
|
private initialSize;
|
|
338
343
|
private rememberState;
|
|
@@ -347,6 +352,7 @@ declare class DynamicFormDialogHostComponent implements OnInit {
|
|
|
347
352
|
submitMethod?: string | null;
|
|
348
353
|
apiEndpointKey?: ApiEndpoint | string | null;
|
|
349
354
|
apiUrlEntry?: ApiUrlEntry | null;
|
|
355
|
+
layoutPolicy?: DynamicFormLayoutPolicy | null;
|
|
350
356
|
formActions?: FormConfig['actions'];
|
|
351
357
|
mode: 'create' | 'edit' | 'view';
|
|
352
358
|
backConfig?: BackConfig;
|
|
@@ -355,6 +361,7 @@ declare class DynamicFormDialogHostComponent implements OnInit {
|
|
|
355
361
|
constructor(dialogRef: DialogRef<DynamicFormDialogHostComponent>, data: any, dialogService: DialogService, crud: GenericCrudService<any>, configStorage: AsyncConfigStorage);
|
|
356
362
|
private extractInitialValue;
|
|
357
363
|
private resolveFormActions;
|
|
364
|
+
private resolveLayoutPolicy;
|
|
358
365
|
private resolveSubmitLabel;
|
|
359
366
|
ngOnInit(): void;
|
|
360
367
|
onSave(result: unknown): void;
|