@praxisui/crud 1.0.0-beta.5 → 1.0.0-beta.52
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 +103 -2
- package/drawer-adapter/index.d.ts +81 -0
- package/drawer-adapter/package.json +3 -0
- package/fesm2022/praxisui-crud-drawer-adapter.mjs +18 -0
- package/fesm2022/praxisui-crud-drawer-adapter.mjs.map +1 -0
- package/fesm2022/praxisui-crud.mjs +520 -145
- package/fesm2022/praxisui-crud.mjs.map +1 -1
- package/index.d.ts +65 -18
- package/package.json +13 -9
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, InjectionToken, inject, EventEmitter, ViewChild, Output, Input, Component,
|
|
2
|
+
import { Injectable, InjectionToken, inject, EventEmitter, DestroyRef, ViewChild, Output, Input, Component, Inject, ENVIRONMENT_INITIALIZER } from '@angular/core';
|
|
3
|
+
import { Router, ActivatedRoute, RouterLink } from '@angular/router';
|
|
3
4
|
import { PraxisTable } from '@praxisui/table';
|
|
4
|
-
import {
|
|
5
|
+
import { firstValueFrom } from 'rxjs';
|
|
5
6
|
import * as i1 from '@angular/material/dialog';
|
|
6
7
|
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
7
8
|
export { MAT_DIALOG_DATA as DIALOG_DATA } from '@angular/material/dialog';
|
|
8
9
|
import * as i2 from '@praxisui/core';
|
|
9
|
-
import {
|
|
10
|
+
import { ASYNC_CONFIG_STORAGE, GlobalConfigService, fillUndefined, createDefaultTableConfig, ComponentKeyService, EmptyStateCardComponent, PraxisIconDirective, GenericCrudService, ComponentMetadataRegistry } from '@praxisui/core';
|
|
10
11
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
11
12
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
12
13
|
import * as i1$1 from '@angular/common';
|
|
@@ -17,7 +18,7 @@ import * as i5 from '@angular/material/icon';
|
|
|
17
18
|
import { MatIconModule } from '@angular/material/icon';
|
|
18
19
|
import { PraxisDynamicForm } from '@praxisui/dynamic-form';
|
|
19
20
|
import { ConfirmDialogComponent } from '@praxisui/dynamic-fields';
|
|
20
|
-
import { filter } from 'rxjs/operators';
|
|
21
|
+
import { filter, take } from 'rxjs/operators';
|
|
21
22
|
|
|
22
23
|
class DialogService {
|
|
23
24
|
matDialog;
|
|
@@ -33,20 +34,28 @@ class DialogService {
|
|
|
33
34
|
const component = await loader();
|
|
34
35
|
return this.zone.run(() => this.matDialog.open(component, config));
|
|
35
36
|
}
|
|
36
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.
|
|
37
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.
|
|
37
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DialogService, deps: [{ token: i1.MatDialog }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
38
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DialogService, providedIn: 'root' });
|
|
38
39
|
}
|
|
39
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.
|
|
40
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DialogService, decorators: [{
|
|
40
41
|
type: Injectable,
|
|
41
42
|
args: [{ providedIn: 'root' }]
|
|
42
43
|
}], ctorParameters: () => [{ type: i1.MatDialog }, { type: i0.NgZone }] });
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
function getCrudDrawerAdapterToken() {
|
|
46
|
+
const registryKey = '__PAX_CRUD_DRAWER_ADAPTER_TOKEN__';
|
|
47
|
+
const globalRegistry = globalThis;
|
|
48
|
+
if (!globalRegistry[registryKey]) {
|
|
49
|
+
globalRegistry[registryKey] = new InjectionToken('CRUD_DRAWER_ADAPTER');
|
|
50
|
+
}
|
|
51
|
+
return globalRegistry[registryKey];
|
|
52
|
+
}
|
|
53
|
+
const CRUD_DRAWER_ADAPTER = getCrudDrawerAdapterToken();
|
|
45
54
|
|
|
46
55
|
class CrudLauncherService {
|
|
47
56
|
router = inject(Router);
|
|
48
57
|
dialog = inject(DialogService);
|
|
49
|
-
storage = inject(
|
|
58
|
+
storage = inject(ASYNC_CONFIG_STORAGE);
|
|
50
59
|
global = inject(GlobalConfigService);
|
|
51
60
|
drawerAdapter = (() => {
|
|
52
61
|
try {
|
|
@@ -56,9 +65,9 @@ class CrudLauncherService {
|
|
|
56
65
|
return undefined;
|
|
57
66
|
}
|
|
58
67
|
})();
|
|
59
|
-
async launch(action, row, metadata) {
|
|
68
|
+
async launch(action, row, metadata, componentKeyId, drawerCallbacks) {
|
|
60
69
|
// Carregar overrides de CRUD (se houver) e mesclar em uma cópia local
|
|
61
|
-
const merged = this.mergeCrudOverrides(metadata, action);
|
|
70
|
+
const merged = await this.mergeCrudOverrides(metadata, action, componentKeyId || undefined);
|
|
62
71
|
const mode = this.resolveOpenMode(merged.action, merged.metadata);
|
|
63
72
|
console.debug('[CRUD:Launcher] mode=', mode, 'action=', action);
|
|
64
73
|
if (mode === 'route') {
|
|
@@ -75,7 +84,13 @@ class CrudLauncherService {
|
|
|
75
84
|
if (row && inputs[idField] === undefined && row[idField] !== undefined) {
|
|
76
85
|
inputs[idField] = row[idField];
|
|
77
86
|
}
|
|
78
|
-
await Promise.resolve(this.drawerAdapter.open({
|
|
87
|
+
await Promise.resolve(this.drawerAdapter.open({
|
|
88
|
+
action: merged.action,
|
|
89
|
+
metadata: merged.metadata,
|
|
90
|
+
inputs,
|
|
91
|
+
onClose: drawerCallbacks?.onClose,
|
|
92
|
+
onResult: drawerCallbacks?.onResult,
|
|
93
|
+
}));
|
|
79
94
|
return { mode };
|
|
80
95
|
}
|
|
81
96
|
if (!merged.action.formId) {
|
|
@@ -195,13 +210,18 @@ class CrudLauncherService {
|
|
|
195
210
|
});
|
|
196
211
|
return inputs;
|
|
197
212
|
}
|
|
198
|
-
mergeCrudOverrides(metadata, action) {
|
|
213
|
+
async mergeCrudOverrides(metadata, action, componentKeyId) {
|
|
199
214
|
try {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
215
|
+
if (!componentKeyId)
|
|
216
|
+
return { metadata, action };
|
|
217
|
+
const key = `crud-overrides:${componentKeyId}`;
|
|
218
|
+
let saved = null;
|
|
219
|
+
try {
|
|
220
|
+
saved = await firstValueFrom(this.storage.loadConfig(key));
|
|
221
|
+
}
|
|
222
|
+
catch { }
|
|
223
|
+
const overDefaults = saved?.defaults || {};
|
|
224
|
+
const overActions = saved?.actions || {};
|
|
205
225
|
// Merge defaults (shallow for defaults, shallow for modal/back)
|
|
206
226
|
let mergedDefaults = {
|
|
207
227
|
...(metadata.defaults || {}),
|
|
@@ -237,21 +257,29 @@ class CrudLauncherService {
|
|
|
237
257
|
return { metadata, action };
|
|
238
258
|
}
|
|
239
259
|
}
|
|
240
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.
|
|
241
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.
|
|
260
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudLauncherService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
261
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudLauncherService, providedIn: 'root' });
|
|
242
262
|
}
|
|
243
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.
|
|
263
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudLauncherService, decorators: [{
|
|
244
264
|
type: Injectable,
|
|
245
265
|
args: [{ providedIn: 'root' }]
|
|
246
266
|
}] });
|
|
247
267
|
|
|
248
|
-
function assertCrudMetadata(meta) {
|
|
268
|
+
function assertCrudMetadata(meta, options = {}) {
|
|
269
|
+
if (meta.component !== 'praxis-crud') {
|
|
270
|
+
throw new Error('Invalid component type for CRUD metadata');
|
|
271
|
+
}
|
|
272
|
+
if (!meta.table) {
|
|
273
|
+
throw new Error('Table config not provided for CRUD metadata');
|
|
274
|
+
}
|
|
249
275
|
meta.actions?.forEach((action) => {
|
|
250
276
|
const mode = action.openMode ?? meta.defaults?.openMode ?? 'route';
|
|
251
|
-
if (mode === 'route' && !action.route) {
|
|
277
|
+
if (!options.allowDeferredActionBindings && mode === 'route' && !action.route) {
|
|
252
278
|
throw new Error(`Route not provided for action ${action.action}`);
|
|
253
279
|
}
|
|
254
|
-
if (
|
|
280
|
+
if (!options.allowDeferredActionBindings &&
|
|
281
|
+
(mode === 'modal' || mode === 'drawer') &&
|
|
282
|
+
!action.formId) {
|
|
255
283
|
throw new Error(`formId not provided for action ${action.action}`);
|
|
256
284
|
}
|
|
257
285
|
action.params?.forEach((p) => {
|
|
@@ -263,10 +291,12 @@ function assertCrudMetadata(meta) {
|
|
|
263
291
|
}
|
|
264
292
|
|
|
265
293
|
class PraxisCrudComponent {
|
|
266
|
-
/** Habilita visual de debug para alinhamento/layouot */
|
|
267
|
-
debugLayout = false;
|
|
268
294
|
/** JSON inline ou chave/URL resolvida pelo MetadataResolver */
|
|
269
295
|
metadata;
|
|
296
|
+
/** Identificador obrigatório do CRUD (base para tabela/formulário) */
|
|
297
|
+
crudId;
|
|
298
|
+
/** Identificador opcional para instâncias múltiplas */
|
|
299
|
+
componentInstanceId;
|
|
270
300
|
context;
|
|
271
301
|
/** Encaminha o modo de edição de layout para a tabela interna */
|
|
272
302
|
editModeEnabled = false;
|
|
@@ -280,10 +310,27 @@ class PraxisCrudComponent {
|
|
|
280
310
|
resolvedMetadata;
|
|
281
311
|
/** Configuração efetiva da tabela com melhorias automáticas (ex.: botão Adicionar). */
|
|
282
312
|
effectiveTableConfig;
|
|
313
|
+
/** Config passado ao PraxisTable — sempre definido (fallback seguro). */
|
|
314
|
+
tableConfigForBinding = createDefaultTableConfig();
|
|
283
315
|
launcher = inject(CrudLauncherService);
|
|
316
|
+
destroyRef = inject(DestroyRef);
|
|
284
317
|
table;
|
|
285
|
-
storage = inject(
|
|
318
|
+
storage = inject(ASYNC_CONFIG_STORAGE);
|
|
286
319
|
snack = inject(MatSnackBar);
|
|
320
|
+
global = (() => { try {
|
|
321
|
+
return inject(GlobalConfigService);
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
return undefined;
|
|
325
|
+
} })();
|
|
326
|
+
componentKeys = inject(ComponentKeyService);
|
|
327
|
+
route = (() => { try {
|
|
328
|
+
return inject(ActivatedRoute);
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
return undefined;
|
|
332
|
+
} })();
|
|
333
|
+
warnedMissingId = false;
|
|
287
334
|
/**
|
|
288
335
|
* Stable CRUD context passed to PraxisTable.
|
|
289
336
|
* Previously this was created via a getter, producing a new object each CD tick
|
|
@@ -292,9 +339,11 @@ class PraxisCrudComponent {
|
|
|
292
339
|
tableCrudContext;
|
|
293
340
|
onResetPreferences() {
|
|
294
341
|
try {
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
342
|
+
const keyId = this.componentKeyId();
|
|
343
|
+
if (!keyId)
|
|
344
|
+
return;
|
|
345
|
+
const key = `crud-overrides:${keyId}`;
|
|
346
|
+
void firstValueFrom(this.storage.clearConfig(key)).catch(() => { });
|
|
298
347
|
this.snack.open('Overrides de CRUD redefinidos', undefined, { duration: 2000 });
|
|
299
348
|
}
|
|
300
349
|
catch { }
|
|
@@ -302,12 +351,21 @@ class PraxisCrudComponent {
|
|
|
302
351
|
ngOnChanges(changes) {
|
|
303
352
|
if (changes['metadata']) {
|
|
304
353
|
try {
|
|
305
|
-
this.
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
354
|
+
const parsed = typeof this.metadata === 'string'
|
|
355
|
+
? JSON.parse(this.metadata)
|
|
356
|
+
: this.metadata;
|
|
357
|
+
this.resolvedMetadata = parsed;
|
|
358
|
+
// Runtime metadata must stay structurally valid, but route/formId can be
|
|
359
|
+
// completed later by launcher overrides, defaults or host policy.
|
|
360
|
+
assertCrudMetadata(this.resolvedMetadata, {
|
|
361
|
+
allowDeferredActionBindings: true,
|
|
362
|
+
});
|
|
310
363
|
this.effectiveTableConfig = this.buildEffectiveTableConfig(this.resolvedMetadata);
|
|
364
|
+
// Evitar passar undefined para [config], o que sobrescreve o default do PraxisTable
|
|
365
|
+
this.tableConfigForBinding =
|
|
366
|
+
this.effectiveTableConfig ||
|
|
367
|
+
(this.resolvedMetadata.table ??
|
|
368
|
+
createDefaultTableConfig());
|
|
311
369
|
// Build a stable table context when metadata changes
|
|
312
370
|
this.tableCrudContext = this.buildTableCrudContext(this.resolvedMetadata);
|
|
313
371
|
}
|
|
@@ -338,13 +396,39 @@ class PraxisCrudComponent {
|
|
|
338
396
|
}
|
|
339
397
|
}
|
|
340
398
|
const effectiveAction = (actionMeta || { action });
|
|
341
|
-
|
|
399
|
+
let drawerCloseEmitted = false;
|
|
400
|
+
const emitDrawerClose = () => {
|
|
401
|
+
if (drawerCloseEmitted)
|
|
402
|
+
return;
|
|
403
|
+
drawerCloseEmitted = true;
|
|
404
|
+
this.afterClose.emit();
|
|
405
|
+
};
|
|
406
|
+
const { mode, ref } = await this.launcher.launch(effectiveAction, row, this.resolvedMetadata, this.componentKeyId(), {
|
|
407
|
+
onClose: () => {
|
|
408
|
+
emitDrawerClose();
|
|
409
|
+
},
|
|
410
|
+
onResult: (result) => {
|
|
411
|
+
emitDrawerClose();
|
|
412
|
+
const data = (result?.data || {});
|
|
413
|
+
const idField = this.getIdField();
|
|
414
|
+
if (result?.type === 'save') {
|
|
415
|
+
const id = data?.[idField];
|
|
416
|
+
this.afterSave.emit({ id, data });
|
|
417
|
+
this.refreshTable();
|
|
418
|
+
}
|
|
419
|
+
if (result?.type === 'delete') {
|
|
420
|
+
const id = data?.[idField];
|
|
421
|
+
this.afterDelete.emit({ id });
|
|
422
|
+
this.refreshTable();
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
});
|
|
342
426
|
this.afterOpen.emit({ mode, action: effectiveAction.action });
|
|
343
427
|
if (ref) {
|
|
344
428
|
const idField = this.getIdField();
|
|
345
429
|
ref
|
|
346
430
|
.afterClosed()
|
|
347
|
-
.pipe(takeUntilDestroyed())
|
|
431
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
348
432
|
.subscribe((result) => {
|
|
349
433
|
this.afterClose.emit();
|
|
350
434
|
if (result?.type === 'save') {
|
|
@@ -369,6 +453,24 @@ class PraxisCrudComponent {
|
|
|
369
453
|
refreshTable() {
|
|
370
454
|
this.table.refetch();
|
|
371
455
|
}
|
|
456
|
+
resolveResourcePath(meta) {
|
|
457
|
+
return (meta?.resource?.path ||
|
|
458
|
+
meta?.table?.resourcePath ||
|
|
459
|
+
'').trim();
|
|
460
|
+
}
|
|
461
|
+
resolveLocalData(meta) {
|
|
462
|
+
const localData = meta?.data;
|
|
463
|
+
return Array.isArray(localData) ? localData : null;
|
|
464
|
+
}
|
|
465
|
+
resolveTableData(meta) {
|
|
466
|
+
if (this.resolveResourcePath(meta).length > 0) {
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
return this.resolveLocalData(meta);
|
|
470
|
+
}
|
|
471
|
+
shouldRenderTable(meta) {
|
|
472
|
+
return this.resolveResourcePath(meta).length > 0 || Array.isArray(meta?.data);
|
|
473
|
+
}
|
|
372
474
|
getIdField() {
|
|
373
475
|
return this.resolvedMetadata?.resource?.idField || 'id';
|
|
374
476
|
}
|
|
@@ -383,45 +485,77 @@ class PraxisCrudComponent {
|
|
|
383
485
|
*/
|
|
384
486
|
buildEffectiveTableConfig(meta) {
|
|
385
487
|
const base = meta.table;
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
488
|
+
// Clonar base ou criar default para permitir injeção de melhorias
|
|
489
|
+
const cfg = base
|
|
490
|
+
? JSON.parse(JSON.stringify(base))
|
|
491
|
+
: createDefaultTableConfig();
|
|
492
|
+
let changed = false;
|
|
390
493
|
const ensureToolbar = () => {
|
|
391
494
|
if (!cfg.toolbar) {
|
|
392
495
|
cfg.toolbar = { visible: true, position: 'top' };
|
|
393
496
|
}
|
|
394
497
|
return cfg.toolbar;
|
|
395
498
|
};
|
|
396
|
-
//
|
|
499
|
+
// 1) Toolbar: injetar ação "Adicionar" se metadata declara create/add e toolbar não tiver
|
|
397
500
|
const hasToolbarAdd = (cfg.toolbar?.actions || []).some((a) => this.isAddLike(a));
|
|
398
|
-
// Procurar mapeamento de ação "adicionar/criar" nos metadados do CRUD
|
|
399
501
|
const addAction = (meta.actions || []).find((a) => this.isAddLike(a));
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
502
|
+
if (addAction) {
|
|
503
|
+
if (hasToolbarAdd) {
|
|
504
|
+
const tb = ensureToolbar();
|
|
505
|
+
tb.visible = true; // garantir visibilidade
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
const tb = ensureToolbar();
|
|
509
|
+
tb.visible = true;
|
|
510
|
+
if (!tb.actions)
|
|
511
|
+
tb.actions = [];
|
|
512
|
+
const injected = {
|
|
513
|
+
id: addAction.id || 'add',
|
|
514
|
+
label: addAction.label || 'Adicionar',
|
|
515
|
+
icon: addAction.icon || 'add',
|
|
516
|
+
type: 'button',
|
|
517
|
+
color: 'primary',
|
|
518
|
+
position: 'end',
|
|
519
|
+
action: addAction.action || 'add',
|
|
520
|
+
};
|
|
521
|
+
tb.actions.push(injected);
|
|
522
|
+
}
|
|
523
|
+
changed = true;
|
|
403
524
|
}
|
|
404
|
-
//
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
525
|
+
// 2) Row actions automáticas (apenas quando host não definiu explicitamente)
|
|
526
|
+
const hostDefinedRow = !!(base && base.actions && base.actions.row);
|
|
527
|
+
const crudDefaults = this.global.get('crud.defaults') || {};
|
|
528
|
+
const autoRow = crudDefaults.autoRowActions !== false; // default true
|
|
529
|
+
if (!hostDefinedRow && autoRow) {
|
|
530
|
+
const acts = (meta.actions || []);
|
|
531
|
+
const hasView = acts.some((a) => String(a.action).toLowerCase() === 'view');
|
|
532
|
+
const hasEdit = acts.some((a) => String(a.action).toLowerCase() === 'edit');
|
|
533
|
+
const includeDelete = !!crudDefaults.includeDeleteInRow && acts.some((a) => String(a.action).toLowerCase() === 'delete');
|
|
534
|
+
const rowActions = [];
|
|
535
|
+
if (hasView)
|
|
536
|
+
rowActions.push({ id: 'view', label: 'Ver', icon: 'visibility', action: 'view', tooltip: 'Ver' });
|
|
537
|
+
if (hasEdit)
|
|
538
|
+
rowActions.push({ id: 'edit', label: 'Editar', icon: 'edit', action: 'edit', tooltip: 'Editar' });
|
|
539
|
+
if (includeDelete)
|
|
540
|
+
rowActions.push({ id: 'delete', label: 'Excluir', icon: 'delete', action: 'delete', tooltip: 'Excluir' });
|
|
541
|
+
if (rowActions.length) {
|
|
542
|
+
cfg.actions = cfg.actions || {};
|
|
543
|
+
cfg.actions.row = {
|
|
544
|
+
enabled: true,
|
|
545
|
+
position: 'end',
|
|
546
|
+
width: cfg.actions?.row?.width || '120px',
|
|
547
|
+
display: crudDefaults.rowActionsDisplay || 'icons',
|
|
548
|
+
trigger: cfg.actions?.row?.trigger || 'hover',
|
|
549
|
+
actions: rowActions,
|
|
550
|
+
header: { label: cfg.actions?.row?.header?.label || '' },
|
|
551
|
+
};
|
|
552
|
+
changed = true;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
// Se nada foi alterado e havia base, não retornar para preservar semântica anterior
|
|
556
|
+
if (!changed) {
|
|
557
|
+
return base ? undefined : cfg;
|
|
409
558
|
}
|
|
410
|
-
// Injetar ação na toolbar
|
|
411
|
-
const tb = ensureToolbar();
|
|
412
|
-
tb.visible = true;
|
|
413
|
-
if (!tb.actions)
|
|
414
|
-
tb.actions = [];
|
|
415
|
-
const injected = {
|
|
416
|
-
id: addAction.id || 'add',
|
|
417
|
-
label: addAction.label || 'Adicionar',
|
|
418
|
-
icon: addAction.icon || 'add',
|
|
419
|
-
type: 'button',
|
|
420
|
-
color: 'primary',
|
|
421
|
-
position: 'end',
|
|
422
|
-
action: addAction.action || 'add',
|
|
423
|
-
};
|
|
424
|
-
tb.actions.push(injected);
|
|
425
559
|
return cfg;
|
|
426
560
|
}
|
|
427
561
|
/** Heurística leve para identificar ações do tipo "adicionar/criar" */
|
|
@@ -451,8 +585,9 @@ class PraxisCrudComponent {
|
|
|
451
585
|
? meta.actions
|
|
452
586
|
: [{ action: 'create' }, { action: 'view' }, { action: 'edit' }];
|
|
453
587
|
return {
|
|
454
|
-
tableId:
|
|
455
|
-
|
|
588
|
+
tableId: this.crudId || 'default',
|
|
589
|
+
componentKeyId: this.componentKeyId() || undefined,
|
|
590
|
+
resourcePath: this.resolveResourcePath(meta) || undefined,
|
|
456
591
|
defaults: meta.defaults,
|
|
457
592
|
actions: baseActions.map((a) => ({
|
|
458
593
|
action: a.action,
|
|
@@ -464,68 +599,90 @@ class PraxisCrudComponent {
|
|
|
464
599
|
idField: meta.resource?.idField || 'id',
|
|
465
600
|
};
|
|
466
601
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
602
|
+
componentKeyId() {
|
|
603
|
+
const key = this.componentKeys.buildComponentId({
|
|
604
|
+
componentType: 'praxis-crud',
|
|
605
|
+
componentId: this.crudId,
|
|
606
|
+
instanceKey: this.componentInstanceId,
|
|
607
|
+
componentRef: this,
|
|
608
|
+
route: this.route,
|
|
609
|
+
requireComponentId: true,
|
|
610
|
+
});
|
|
611
|
+
if (!key)
|
|
612
|
+
this.warnMissingId();
|
|
613
|
+
return key;
|
|
614
|
+
}
|
|
615
|
+
warnMissingId() {
|
|
616
|
+
if (this.warnedMissingId)
|
|
617
|
+
return;
|
|
618
|
+
this.warnedMissingId = true;
|
|
619
|
+
console.warn('[PraxisCrud] crudId is required for config persistence.');
|
|
620
|
+
}
|
|
621
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisCrudComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
622
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisCrudComponent, isStandalone: true, selector: "praxis-crud", inputs: { metadata: "metadata", crudId: "crudId", componentInstanceId: "componentInstanceId", context: "context", editModeEnabled: "editModeEnabled" }, outputs: { configureRequested: "configureRequested", afterOpen: "afterOpen", afterClose: "afterClose", afterSave: "afterSave", afterDelete: "afterDelete", error: "error" }, viewQueries: [{ propertyName: "table", first: true, predicate: PraxisTable, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
623
|
+
@if (shouldRenderTable(resolvedMetadata)) {
|
|
470
624
|
<praxis-table
|
|
471
|
-
[config]="
|
|
472
|
-
[resourcePath]="resolvedMetadata
|
|
473
|
-
[
|
|
625
|
+
[config]="tableConfigForBinding"
|
|
626
|
+
[resourcePath]="resolveResourcePath(resolvedMetadata)"
|
|
627
|
+
[data]="resolveTableData(resolvedMetadata)"
|
|
628
|
+
[tableId]="crudId || 'default'"
|
|
474
629
|
[crudContext]="tableCrudContext"
|
|
475
630
|
[editModeEnabled]="editModeEnabled"
|
|
476
631
|
(rowAction)="onAction($event.action, $event.row)"
|
|
477
632
|
(toolbarAction)="onAction($event.action)"
|
|
478
633
|
(reset)="onResetPreferences()"
|
|
479
|
-
[debugLayout]="debugLayout"
|
|
480
634
|
></praxis-table>
|
|
481
635
|
} @else {
|
|
482
636
|
@if (editModeEnabled) {
|
|
483
637
|
<praxis-empty-state-card
|
|
484
638
|
icon="table_rows"
|
|
485
639
|
[title]="'Conecte o CRUD a um recurso'"
|
|
486
|
-
[description]="'Informe os metadados (resourcePath / schema) para habilitar a tabela e ações.'"
|
|
640
|
+
[description]="'Informe os metadados (resourcePath / schema) ou forneça metadata.data para habilitar a tabela e ações.'"
|
|
487
641
|
[primaryAction]="{ label: 'Configurar metadados', icon: 'bolt', action: onConfigureRequested.bind(this) }"
|
|
488
642
|
/>
|
|
489
643
|
}
|
|
490
644
|
}
|
|
491
|
-
`, isInline: true, dependencies: [{ kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "
|
|
645
|
+
`, isInline: true, dependencies: [{ kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "dslFunctionRegistry", "editModeEnabled", "dense"], outputs: ["rowClick", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "columnReorder", "columnReorderAttempt", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "metadataChange", "loadingStateChange"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }] });
|
|
492
646
|
}
|
|
493
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.
|
|
647
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisCrudComponent, decorators: [{
|
|
494
648
|
type: Component,
|
|
495
649
|
args: [{
|
|
496
650
|
selector: 'praxis-crud',
|
|
497
651
|
standalone: true,
|
|
498
652
|
imports: [PraxisTable, EmptyStateCardComponent],
|
|
499
653
|
template: `
|
|
500
|
-
@if (
|
|
654
|
+
@if (shouldRenderTable(resolvedMetadata)) {
|
|
501
655
|
<praxis-table
|
|
502
|
-
[config]="
|
|
503
|
-
[resourcePath]="resolvedMetadata
|
|
504
|
-
[
|
|
656
|
+
[config]="tableConfigForBinding"
|
|
657
|
+
[resourcePath]="resolveResourcePath(resolvedMetadata)"
|
|
658
|
+
[data]="resolveTableData(resolvedMetadata)"
|
|
659
|
+
[tableId]="crudId || 'default'"
|
|
505
660
|
[crudContext]="tableCrudContext"
|
|
506
661
|
[editModeEnabled]="editModeEnabled"
|
|
507
662
|
(rowAction)="onAction($event.action, $event.row)"
|
|
508
663
|
(toolbarAction)="onAction($event.action)"
|
|
509
664
|
(reset)="onResetPreferences()"
|
|
510
|
-
[debugLayout]="debugLayout"
|
|
511
665
|
></praxis-table>
|
|
512
666
|
} @else {
|
|
513
667
|
@if (editModeEnabled) {
|
|
514
668
|
<praxis-empty-state-card
|
|
515
669
|
icon="table_rows"
|
|
516
670
|
[title]="'Conecte o CRUD a um recurso'"
|
|
517
|
-
[description]="'Informe os metadados (resourcePath / schema) para habilitar a tabela e ações.'"
|
|
671
|
+
[description]="'Informe os metadados (resourcePath / schema) ou forneça metadata.data para habilitar a tabela e ações.'"
|
|
518
672
|
[primaryAction]="{ label: 'Configurar metadados', icon: 'bolt', action: onConfigureRequested.bind(this) }"
|
|
519
673
|
/>
|
|
520
674
|
}
|
|
521
675
|
}
|
|
522
676
|
`,
|
|
523
677
|
}]
|
|
524
|
-
}], propDecorators: {
|
|
525
|
-
type: Input
|
|
526
|
-
}], metadata: [{
|
|
678
|
+
}], propDecorators: { metadata: [{
|
|
527
679
|
type: Input,
|
|
528
680
|
args: [{ required: true }]
|
|
681
|
+
}], crudId: [{
|
|
682
|
+
type: Input,
|
|
683
|
+
args: [{ required: true }]
|
|
684
|
+
}], componentInstanceId: [{
|
|
685
|
+
type: Input
|
|
529
686
|
}], context: [{
|
|
530
687
|
type: Input
|
|
531
688
|
}], editModeEnabled: [{
|
|
@@ -559,6 +716,7 @@ class DynamicFormDialogHostComponent {
|
|
|
559
716
|
initialSize = {};
|
|
560
717
|
rememberState = false;
|
|
561
718
|
stateKey;
|
|
719
|
+
backDefaults = {};
|
|
562
720
|
destroyRef = inject(DestroyRef);
|
|
563
721
|
resourcePath;
|
|
564
722
|
resourceId;
|
|
@@ -610,10 +768,8 @@ class DynamicFormDialogHostComponent {
|
|
|
610
768
|
this.mode = act === 'edit' ? 'edit' : act === 'view' ? 'view' : 'create';
|
|
611
769
|
// Back config: defaults from metadata/action, overridden by saved per-form config
|
|
612
770
|
const defaults = (this.data.action?.back || this.data.metadata?.defaults?.back) || {};
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
: null;
|
|
616
|
-
this.backConfig = { ...defaults, ...(saved || {}) };
|
|
771
|
+
this.backDefaults = defaults;
|
|
772
|
+
this.backConfig = { ...defaults };
|
|
617
773
|
console.debug('[CRUD:Host] constructed', {
|
|
618
774
|
action: this.data?.action,
|
|
619
775
|
resourcePath: this.resourcePath,
|
|
@@ -644,34 +800,25 @@ class DynamicFormDialogHostComponent {
|
|
|
644
800
|
}
|
|
645
801
|
ngOnInit() {
|
|
646
802
|
// Carregar estado salvo (se habilitado)
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
height: saved?.height ?? this.modal.height,
|
|
653
|
-
};
|
|
654
|
-
console.debug('[CRUD:Host] ngOnInit', {
|
|
655
|
-
initialSize: this.initialSize,
|
|
656
|
-
startMaximized: this.modal.startMaximized,
|
|
657
|
-
fullscreenBreakpoint: this.modal.fullscreenBreakpoint,
|
|
658
|
-
});
|
|
659
|
-
let shouldMax = false;
|
|
660
|
-
if (saved && typeof saved.maximized === 'boolean') {
|
|
661
|
-
shouldMax = !!saved.maximized;
|
|
803
|
+
if (this.rememberState && this.stateKey) {
|
|
804
|
+
this.configStorage
|
|
805
|
+
.loadConfig(this.stateKey)
|
|
806
|
+
.pipe(take(1))
|
|
807
|
+
.subscribe((saved) => this.applySavedState(saved || null));
|
|
662
808
|
}
|
|
663
809
|
else {
|
|
664
|
-
|
|
665
|
-
this.modal.startMaximized ||
|
|
666
|
-
(this.modal.fullscreenBreakpoint &&
|
|
667
|
-
window.innerWidth <= this.modal.fullscreenBreakpoint);
|
|
810
|
+
this.applySavedState(null);
|
|
668
811
|
}
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
812
|
+
// Carregar override de back config se houver formId
|
|
813
|
+
if (this.data.action?.formId) {
|
|
814
|
+
this.configStorage
|
|
815
|
+
.loadConfig(`crud-back:${this.data.action.formId}`)
|
|
816
|
+
.pipe(take(1))
|
|
817
|
+
.subscribe((saved) => {
|
|
818
|
+
if (saved && typeof saved === 'object') {
|
|
819
|
+
this.backConfig = { ...this.backDefaults, ...saved };
|
|
820
|
+
}
|
|
821
|
+
});
|
|
675
822
|
}
|
|
676
823
|
}
|
|
677
824
|
onSave(result) {
|
|
@@ -695,6 +842,7 @@ class DynamicFormDialogHostComponent {
|
|
|
695
842
|
cancelText: this.texts.discardCancel,
|
|
696
843
|
type: 'warning',
|
|
697
844
|
},
|
|
845
|
+
autoFocus: false,
|
|
698
846
|
});
|
|
699
847
|
ref
|
|
700
848
|
.afterClosed()
|
|
@@ -731,15 +879,46 @@ class DynamicFormDialogHostComponent {
|
|
|
731
879
|
const style = pane ? getComputedStyle(pane) : null;
|
|
732
880
|
const currentWidth = style?.width || this.initialSize.width;
|
|
733
881
|
const currentHeight = style?.height || this.initialSize.height;
|
|
734
|
-
this.configStorage
|
|
882
|
+
this.configStorage
|
|
883
|
+
.saveConfig(this.stateKey, {
|
|
735
884
|
maximized: this.maximized,
|
|
736
885
|
width: currentWidth,
|
|
737
886
|
height: currentHeight,
|
|
887
|
+
})
|
|
888
|
+
.pipe(take(1))
|
|
889
|
+
.subscribe({ error: () => { } });
|
|
890
|
+
}
|
|
891
|
+
applySavedState(saved) {
|
|
892
|
+
this.initialSize = {
|
|
893
|
+
width: saved?.width ?? this.modal.width,
|
|
894
|
+
height: saved?.height ?? this.modal.height,
|
|
895
|
+
};
|
|
896
|
+
console.debug('[CRUD:Host] ngOnInit', {
|
|
897
|
+
initialSize: this.initialSize,
|
|
898
|
+
startMaximized: this.modal.startMaximized,
|
|
899
|
+
fullscreenBreakpoint: this.modal.fullscreenBreakpoint,
|
|
738
900
|
});
|
|
901
|
+
let shouldMax = false;
|
|
902
|
+
if (saved && typeof saved.maximized === 'boolean') {
|
|
903
|
+
shouldMax = !!saved.maximized;
|
|
904
|
+
}
|
|
905
|
+
else {
|
|
906
|
+
shouldMax =
|
|
907
|
+
this.modal.startMaximized ||
|
|
908
|
+
(this.modal.fullscreenBreakpoint &&
|
|
909
|
+
window.innerWidth <= this.modal.fullscreenBreakpoint);
|
|
910
|
+
}
|
|
911
|
+
if (shouldMax) {
|
|
912
|
+
this.toggleMaximize(true);
|
|
913
|
+
}
|
|
914
|
+
else if (this.initialSize.width || this.initialSize.height) {
|
|
915
|
+
this.dialogRef.updateSize(this.initialSize.width, this.initialSize.height);
|
|
916
|
+
this.dialogRef.updatePosition();
|
|
917
|
+
}
|
|
739
918
|
}
|
|
740
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.
|
|
741
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.
|
|
742
|
-
<div class="dialog-header">
|
|
919
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicFormDialogHostComponent, deps: [{ token: MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: DialogService }, { token: i2.GenericCrudService }, { token: ASYNC_CONFIG_STORAGE }], target: i0.ɵɵFactoryTarget.Component });
|
|
920
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", 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: `
|
|
921
|
+
<div mat-dialog-title class="dialog-header">
|
|
743
922
|
<h2 id="crudDialogTitle" class="dialog-title">
|
|
744
923
|
{{ data.action?.label || texts.title }}
|
|
745
924
|
</h2>
|
|
@@ -749,13 +928,9 @@ class DynamicFormDialogHostComponent {
|
|
|
749
928
|
mat-icon-button
|
|
750
929
|
type="button"
|
|
751
930
|
(click)="toggleMaximize()"
|
|
752
|
-
[attr.aria-label]="
|
|
753
|
-
maximized ? texts.restoreLabel : texts.maximizeLabel
|
|
754
|
-
"
|
|
931
|
+
[attr.aria-label]="maximized ? texts.restoreLabel : texts.maximizeLabel"
|
|
755
932
|
>
|
|
756
|
-
<mat-icon>
|
|
757
|
-
maximized ? 'close_fullscreen' : 'open_in_full'
|
|
758
|
-
}}</mat-icon>
|
|
933
|
+
<mat-icon [praxisIcon]="maximized ? 'close_fullscreen' : 'open_in_full'"></mat-icon>
|
|
759
934
|
</button>
|
|
760
935
|
}
|
|
761
936
|
<button
|
|
@@ -778,14 +953,15 @@ class DynamicFormDialogHostComponent {
|
|
|
778
953
|
[resourcePath]="resourcePath"
|
|
779
954
|
[resourceId]="resourceId"
|
|
780
955
|
[mode]="mode"
|
|
956
|
+
[presentationModeGlobal]="mode === 'view' ? true : null"
|
|
781
957
|
[backConfig]="backConfig"
|
|
782
958
|
(formSubmit)="onSave($event)"
|
|
783
959
|
(formCancel)="onCancel()"
|
|
784
960
|
></praxis-dynamic-form>
|
|
785
961
|
</mat-dialog-content>
|
|
786
|
-
`, isInline: true, styles: [":host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}:host([data-density=\"compact\"]){--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}.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);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)}.dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}.spacer{flex:1}.dialog-content{overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}.dialog-header button.mat-icon-button{color:var(--md-sys-color-on-surface-variant)}.dialog-header button.mat-icon-button:hover{color:var(--md-sys-color-primary);background:
|
|
962
|
+
`, isInline: true, styles: [":host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}:host([data-density=\"compact\"]){--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}.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)}.dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}.spacer{flex:1}.dialog-content{overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}.dialog-header button.mat-icon-button{color:var(--md-sys-color-on-surface-variant)}.dialog-header button.mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}.dialog-footer{position:sticky;bottom:0;z-index:1;padding:var(--dlg-pad)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.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", "mode", "config", "schemaSource", "editModeEnabled", "formId", "componentInstanceId", "layout", "backConfig", "hooks", "removeEmptyContainersOnSave", "reactiveValidation", "reactiveValidationDebounceMs", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "readonlyModeGlobal", "disabledModeGlobal", "presentationModeGlobal", "visibleGlobal", "customEndpoints"], outputs: ["formSubmit", "formCancel", "formReset", "configChange", "formReady", "valueChange", "syncCompleted", "initializationError", "loadingStateChange", "editModeEnabledChange", "customAction", "actionConfirmation", "schemaStatusChange", "fieldRenderError"] }] });
|
|
787
963
|
}
|
|
788
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.
|
|
964
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicFormDialogHostComponent, decorators: [{
|
|
789
965
|
type: Component,
|
|
790
966
|
args: [{ selector: 'praxis-dynamic-form-dialog-host', standalone: true, imports: [
|
|
791
967
|
CommonModule,
|
|
@@ -798,7 +974,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
798
974
|
class: 'praxis-dialog',
|
|
799
975
|
'[attr.data-density]': 'modal.density || "default"',
|
|
800
976
|
}, template: `
|
|
801
|
-
<div class="dialog-header">
|
|
977
|
+
<div mat-dialog-title class="dialog-header">
|
|
802
978
|
<h2 id="crudDialogTitle" class="dialog-title">
|
|
803
979
|
{{ data.action?.label || texts.title }}
|
|
804
980
|
</h2>
|
|
@@ -808,13 +984,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
808
984
|
mat-icon-button
|
|
809
985
|
type="button"
|
|
810
986
|
(click)="toggleMaximize()"
|
|
811
|
-
[attr.aria-label]="
|
|
812
|
-
maximized ? texts.restoreLabel : texts.maximizeLabel
|
|
813
|
-
"
|
|
987
|
+
[attr.aria-label]="maximized ? texts.restoreLabel : texts.maximizeLabel"
|
|
814
988
|
>
|
|
815
|
-
<mat-icon>
|
|
816
|
-
maximized ? 'close_fullscreen' : 'open_in_full'
|
|
817
|
-
}}</mat-icon>
|
|
989
|
+
<mat-icon [praxisIcon]="maximized ? 'close_fullscreen' : 'open_in_full'"></mat-icon>
|
|
818
990
|
</button>
|
|
819
991
|
}
|
|
820
992
|
<button
|
|
@@ -837,12 +1009,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
837
1009
|
[resourcePath]="resourcePath"
|
|
838
1010
|
[resourceId]="resourceId"
|
|
839
1011
|
[mode]="mode"
|
|
1012
|
+
[presentationModeGlobal]="mode === 'view' ? true : null"
|
|
840
1013
|
[backConfig]="backConfig"
|
|
841
1014
|
(formSubmit)="onSave($event)"
|
|
842
1015
|
(formCancel)="onCancel()"
|
|
843
1016
|
></praxis-dynamic-form>
|
|
844
1017
|
</mat-dialog-content>
|
|
845
|
-
`, styles: [":host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}:host([data-density=\"compact\"]){--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}.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);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)}.dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}.spacer{flex:1}.dialog-content{overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}.dialog-header button.mat-icon-button{color:var(--md-sys-color-on-surface-variant)}.dialog-header button.mat-icon-button:hover{color:var(--md-sys-color-primary);background:
|
|
1018
|
+
`, styles: [":host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}:host([data-density=\"compact\"]){--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}.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)}.dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}.spacer{flex:1}.dialog-content{overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}.dialog-header button.mat-icon-button{color:var(--md-sys-color-on-surface-variant)}.dialog-header button.mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}.dialog-footer{position:sticky;bottom:0;z-index:1;padding:var(--dlg-pad)}\n"] }]
|
|
846
1019
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
847
1020
|
type: Inject,
|
|
848
1021
|
args: [MatDialogRef]
|
|
@@ -851,7 +1024,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
851
1024
|
args: [MAT_DIALOG_DATA]
|
|
852
1025
|
}] }, { type: DialogService }, { type: i2.GenericCrudService }, { type: undefined, decorators: [{
|
|
853
1026
|
type: Inject,
|
|
854
|
-
args: [
|
|
1027
|
+
args: [ASYNC_CONFIG_STORAGE]
|
|
855
1028
|
}] }], propDecorators: { formComp: [{
|
|
856
1029
|
type: ViewChild,
|
|
857
1030
|
args: [PraxisDynamicForm]
|
|
@@ -874,12 +1047,22 @@ const PRAXIS_CRUD_COMPONENT_METADATA = {
|
|
|
874
1047
|
{
|
|
875
1048
|
name: 'metadata',
|
|
876
1049
|
type: 'CrudMetadata | string',
|
|
877
|
-
description: 'Metadados de configuração do CRUD',
|
|
1050
|
+
description: 'Metadados de configuração do CRUD (fonte remota via resource.path ou local via metadata.data).',
|
|
1051
|
+
},
|
|
1052
|
+
{
|
|
1053
|
+
name: 'crudId',
|
|
1054
|
+
type: 'string',
|
|
1055
|
+
description: 'Identificador do CRUD (base para tabela/formulário e persistência)',
|
|
1056
|
+
},
|
|
1057
|
+
{
|
|
1058
|
+
name: 'componentInstanceId',
|
|
1059
|
+
type: 'string',
|
|
1060
|
+
description: 'Identificador opcional para múltiplas instâncias na mesma rota',
|
|
878
1061
|
},
|
|
879
1062
|
{
|
|
880
1063
|
name: 'context',
|
|
881
1064
|
type: 'Record<string, unknown>',
|
|
882
|
-
description: 'Contexto
|
|
1065
|
+
description: 'Contexto opaco do host. A implementacao atual o expõe como Input, mas nao o consome no launcher nem no tableCrudContext.',
|
|
883
1066
|
},
|
|
884
1067
|
{
|
|
885
1068
|
name: 'editModeEnabled',
|
|
@@ -916,6 +1099,108 @@ const PRAXIS_CRUD_COMPONENT_METADATA = {
|
|
|
916
1099
|
description: 'Emitido quando CTA de configuração é acionado em modo edição',
|
|
917
1100
|
},
|
|
918
1101
|
],
|
|
1102
|
+
actions: [
|
|
1103
|
+
{
|
|
1104
|
+
id: 'create',
|
|
1105
|
+
label: 'Criar',
|
|
1106
|
+
icon: 'add',
|
|
1107
|
+
description: 'Emite evento ao abrir fluxo de criação',
|
|
1108
|
+
emit: 'afterOpen',
|
|
1109
|
+
payloadSchema: {
|
|
1110
|
+
type: 'object',
|
|
1111
|
+
properties: {
|
|
1112
|
+
action: { type: 'string', description: 'Ação executada' },
|
|
1113
|
+
mode: { type: 'string', description: 'Modo de abertura' },
|
|
1114
|
+
},
|
|
1115
|
+
required: ['action', 'mode'],
|
|
1116
|
+
example: { action: 'create', mode: 'route' },
|
|
1117
|
+
},
|
|
1118
|
+
scope: 'toolbar',
|
|
1119
|
+
},
|
|
1120
|
+
{
|
|
1121
|
+
id: 'view',
|
|
1122
|
+
label: 'Visualizar',
|
|
1123
|
+
icon: 'visibility',
|
|
1124
|
+
description: 'Emite evento ao abrir fluxo de visualização',
|
|
1125
|
+
emit: 'afterOpen',
|
|
1126
|
+
payloadSchema: {
|
|
1127
|
+
type: 'object',
|
|
1128
|
+
properties: {
|
|
1129
|
+
action: { type: 'string', description: 'Ação executada' },
|
|
1130
|
+
mode: { type: 'string', description: 'Modo de abertura' },
|
|
1131
|
+
},
|
|
1132
|
+
required: ['action', 'mode'],
|
|
1133
|
+
example: { action: 'view', mode: 'modal' },
|
|
1134
|
+
},
|
|
1135
|
+
scope: 'context',
|
|
1136
|
+
},
|
|
1137
|
+
{
|
|
1138
|
+
id: 'edit',
|
|
1139
|
+
label: 'Editar',
|
|
1140
|
+
icon: 'edit',
|
|
1141
|
+
description: 'Emite evento ao abrir fluxo de edição',
|
|
1142
|
+
emit: 'afterOpen',
|
|
1143
|
+
payloadSchema: {
|
|
1144
|
+
type: 'object',
|
|
1145
|
+
properties: {
|
|
1146
|
+
action: { type: 'string', description: 'Ação executada' },
|
|
1147
|
+
mode: { type: 'string', description: 'Modo de abertura' },
|
|
1148
|
+
},
|
|
1149
|
+
required: ['action', 'mode'],
|
|
1150
|
+
example: { action: 'edit', mode: 'drawer' },
|
|
1151
|
+
},
|
|
1152
|
+
scope: 'context',
|
|
1153
|
+
},
|
|
1154
|
+
{
|
|
1155
|
+
id: 'delete',
|
|
1156
|
+
label: 'Excluir',
|
|
1157
|
+
icon: 'delete',
|
|
1158
|
+
description: 'Emite evento após exclusão',
|
|
1159
|
+
emit: 'afterDelete',
|
|
1160
|
+
payloadSchema: {
|
|
1161
|
+
type: 'object',
|
|
1162
|
+
properties: {
|
|
1163
|
+
id: { type: 'string | number', description: 'ID do registro (string ou number)' },
|
|
1164
|
+
},
|
|
1165
|
+
required: ['id'],
|
|
1166
|
+
example: { id: '123' },
|
|
1167
|
+
},
|
|
1168
|
+
scope: 'context',
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
id: 'save',
|
|
1172
|
+
label: 'Salvar',
|
|
1173
|
+
icon: 'save',
|
|
1174
|
+
description: 'Emite evento após salvar',
|
|
1175
|
+
emit: 'afterSave',
|
|
1176
|
+
payloadSchema: {
|
|
1177
|
+
type: 'object',
|
|
1178
|
+
properties: {
|
|
1179
|
+
id: { type: 'string | number', description: 'ID do registro (string ou number)' },
|
|
1180
|
+
data: { type: 'object', description: 'Dados salvos' },
|
|
1181
|
+
},
|
|
1182
|
+
required: ['id', 'data'],
|
|
1183
|
+
example: { id: '123', data: {} },
|
|
1184
|
+
},
|
|
1185
|
+
scope: 'shell',
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1188
|
+
id: 'close',
|
|
1189
|
+
label: 'Fechar',
|
|
1190
|
+
icon: 'close',
|
|
1191
|
+
description: 'Emite evento ao fechar o diálogo',
|
|
1192
|
+
emit: 'afterClose',
|
|
1193
|
+
scope: 'shell',
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
id: 'configure',
|
|
1197
|
+
label: 'Configurar',
|
|
1198
|
+
icon: 'tune',
|
|
1199
|
+
description: 'Emite evento ao abrir configuração',
|
|
1200
|
+
emit: 'configureRequested',
|
|
1201
|
+
scope: 'shell',
|
|
1202
|
+
},
|
|
1203
|
+
],
|
|
919
1204
|
tags: ['widget', 'crud', 'configurable', 'hasWizard', 'stable'],
|
|
920
1205
|
lib: '@praxisui/crud',
|
|
921
1206
|
};
|
|
@@ -939,8 +1224,8 @@ class CrudPageHeaderComponent {
|
|
|
939
1224
|
sticky = true;
|
|
940
1225
|
divider = true;
|
|
941
1226
|
returnTo;
|
|
942
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.
|
|
943
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.
|
|
1227
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudPageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1228
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: CrudPageHeaderComponent, isStandalone: true, selector: "praxis-crud-page-header", inputs: { title: "title", backLabel: "backLabel", showBack: "showBack", variant: "variant", sticky: "sticky", divider: "divider", returnTo: "returnTo" }, ngImport: i0, template: `
|
|
944
1229
|
<header
|
|
945
1230
|
class="crud-header"
|
|
946
1231
|
[class.sticky]="sticky"
|
|
@@ -966,9 +1251,9 @@ class CrudPageHeaderComponent {
|
|
|
966
1251
|
<ng-content></ng-content>
|
|
967
1252
|
</div>
|
|
968
1253
|
</header>
|
|
969
|
-
`, isInline: true, styles: [".crud-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 0;background:var(--md-sys-color-surface
|
|
1254
|
+
`, isInline: true, styles: [".crud-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 0;background:var(--md-sys-color-surface)}.crud-header.sticky{position:sticky;top:0;z-index:10;-webkit-backdrop-filter:saturate(110%);backdrop-filter:saturate(110%)}.crud-header.with-divider{border-bottom:1px solid var(--md-sys-color-outline-variant)}.left{display:flex;align-items:center;gap:8px;min-width:0}.right{display:flex;align-items:center;gap:8px}.title{margin:0;font-weight:600;color:var(--md-sys-color-on-surface, currentColor);font:var(--mdc-typography-title-large, 600 20px/28px system-ui);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.back-btn{display:inline-flex;align-items:center;gap:6px;text-decoration:none}.back-btn .mat-mdc-button{padding-left:0}.back-btn mat-icon{color:var(--md-sys-color-on-surface-variant, currentColor)}.back-btn .label{color:var(--md-sys-color-on-surface-variant, currentColor)}.back-btn.ghost{border-radius:20px;padding:4px 8px}.back-btn.ghost:hover{background:var(--md-sys-color-primary-container)}.back-btn.tonal{border-radius:20px;padding:4px 10px;background:var(--md-sys-color-surface-container);box-shadow:inset 0 0 0 1px var(--md-sys-color-outline-variant)}.back-btn.tonal:hover{background:var(--md-sys-color-primary-container)}.back-btn.outlined{border-radius:20px;padding:4px 10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.back-btn.outlined:hover{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}@media(max-width:599px){.label.hide-on-narrow{display:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
|
|
970
1255
|
}
|
|
971
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.
|
|
1256
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: CrudPageHeaderComponent, decorators: [{
|
|
972
1257
|
type: Component,
|
|
973
1258
|
args: [{ selector: 'praxis-crud-page-header', standalone: true, imports: [CommonModule, RouterLink, MatButtonModule, MatIconModule, PraxisIconDirective], template: `
|
|
974
1259
|
<header
|
|
@@ -996,7 +1281,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
996
1281
|
<ng-content></ng-content>
|
|
997
1282
|
</div>
|
|
998
1283
|
</header>
|
|
999
|
-
`, styles: [".crud-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 0;background:var(--md-sys-color-surface
|
|
1284
|
+
`, styles: [".crud-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 0;background:var(--md-sys-color-surface)}.crud-header.sticky{position:sticky;top:0;z-index:10;-webkit-backdrop-filter:saturate(110%);backdrop-filter:saturate(110%)}.crud-header.with-divider{border-bottom:1px solid var(--md-sys-color-outline-variant)}.left{display:flex;align-items:center;gap:8px;min-width:0}.right{display:flex;align-items:center;gap:8px}.title{margin:0;font-weight:600;color:var(--md-sys-color-on-surface, currentColor);font:var(--mdc-typography-title-large, 600 20px/28px system-ui);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.back-btn{display:inline-flex;align-items:center;gap:6px;text-decoration:none}.back-btn .mat-mdc-button{padding-left:0}.back-btn mat-icon{color:var(--md-sys-color-on-surface-variant, currentColor)}.back-btn .label{color:var(--md-sys-color-on-surface-variant, currentColor)}.back-btn.ghost{border-radius:20px;padding:4px 8px}.back-btn.ghost:hover{background:var(--md-sys-color-primary-container)}.back-btn.tonal{border-radius:20px;padding:4px 10px;background:var(--md-sys-color-surface-container);box-shadow:inset 0 0 0 1px var(--md-sys-color-outline-variant)}.back-btn.tonal:hover{background:var(--md-sys-color-primary-container)}.back-btn.outlined{border-radius:20px;padding:4px 10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.back-btn.outlined:hover{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}@media(max-width:599px){.label.hide-on-narrow{display:none}}\n"] }]
|
|
1000
1285
|
}], propDecorators: { title: [{
|
|
1001
1286
|
type: Input
|
|
1002
1287
|
}], backLabel: [{
|
|
@@ -1013,6 +1298,96 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1013
1298
|
type: Input
|
|
1014
1299
|
}] } });
|
|
1015
1300
|
|
|
1301
|
+
/**
|
|
1302
|
+
* Capabilities catalog for CrudMetadata (Praxis CRUD).
|
|
1303
|
+
*/
|
|
1304
|
+
const ENUMS = {
|
|
1305
|
+
openMode: ['route', 'modal', 'drawer'],
|
|
1306
|
+
paramTarget: ['routeParam', 'query', 'input'],
|
|
1307
|
+
headerVariant: ['ghost', 'tonal', 'outlined'],
|
|
1308
|
+
toolbarActionType: ['button', 'icon', 'fab', 'menu'],
|
|
1309
|
+
toolbarActionAppearance: ['filled', 'outlined', 'elevated', 'text', 'tonal'],
|
|
1310
|
+
toolbarActionPosition: ['start', 'end'],
|
|
1311
|
+
backStrategy: ['auto', 'close', 'navigate'],
|
|
1312
|
+
};
|
|
1313
|
+
const CRUD_AI_CAPABILITIES = {
|
|
1314
|
+
version: 'v1.0',
|
|
1315
|
+
enums: ENUMS,
|
|
1316
|
+
targets: ['praxis-crud', 'crud-view', 'generic-crud'],
|
|
1317
|
+
notes: [
|
|
1318
|
+
'CrudMetadata agrega TableConfig e FormConfig; use os catalogos de tabela e formulario para detalhes.',
|
|
1319
|
+
'actions[] herda campos de RowAction e ToolbarAction; combine com openMode/route/formId quando aplicavel.',
|
|
1320
|
+
],
|
|
1321
|
+
capabilities: [
|
|
1322
|
+
// --- Metadata root ---
|
|
1323
|
+
{
|
|
1324
|
+
path: 'component',
|
|
1325
|
+
category: 'meta',
|
|
1326
|
+
valueKind: 'enum',
|
|
1327
|
+
allowedValues: ['praxis-crud'],
|
|
1328
|
+
description: 'Identificador fixo do componente.',
|
|
1329
|
+
critical: true,
|
|
1330
|
+
},
|
|
1331
|
+
// --- Resource ---
|
|
1332
|
+
{ path: 'resource', category: 'resource', valueKind: 'object', description: 'Recurso principal do CRUD.' },
|
|
1333
|
+
{ path: 'resource.path', category: 'resource', valueKind: 'string', description: 'Endpoint base do recurso.' },
|
|
1334
|
+
{ path: 'resource.idField', category: 'resource', valueKind: 'string', description: 'Campo identificador do recurso.' },
|
|
1335
|
+
{ path: 'resource.endpointKey', category: 'resource', valueKind: 'string', description: 'Chave de endpoint (ApiEndpoint).' },
|
|
1336
|
+
// --- Table / Form ---
|
|
1337
|
+
{ path: 'table', category: 'table', valueKind: 'object', description: 'TableConfig completo (usar catalogo de tabela).' },
|
|
1338
|
+
{ path: 'form', category: 'form', valueKind: 'object', description: 'FormConfig completo (usar catalogo de formulario).' },
|
|
1339
|
+
// --- Defaults ---
|
|
1340
|
+
{ path: 'defaults', category: 'defaults', valueKind: 'object', description: 'Defaults aplicados a acoes e UI.' },
|
|
1341
|
+
{ path: 'defaults.openMode', category: 'defaults', valueKind: 'enum', allowedValues: ENUMS.openMode, description: 'Modo padrao de abertura (route/modal/drawer).' },
|
|
1342
|
+
{ path: 'defaults.modal', category: 'defaults', valueKind: 'object', description: 'Config de dialog (DialogConfig).' },
|
|
1343
|
+
{ path: 'defaults.back', category: 'navigation', valueKind: 'object', description: 'Config de retorno (BackConfig).' },
|
|
1344
|
+
{ path: 'defaults.back.strategy', category: 'navigation', valueKind: 'enum', allowedValues: ENUMS.backStrategy, description: 'Estrategia de retorno.' },
|
|
1345
|
+
{ path: 'defaults.back.returnTo', category: 'navigation', valueKind: 'string', description: 'Rota de retorno quando strategy=navigate.' },
|
|
1346
|
+
{ path: 'defaults.back.confirmOnDirty', category: 'navigation', valueKind: 'boolean', description: 'Confirmar ao sair com alteracoes.' },
|
|
1347
|
+
{ path: 'defaults.header', category: 'defaults', valueKind: 'object', description: 'Config do header do CRUD.' },
|
|
1348
|
+
{ path: 'defaults.header.showBack', category: 'defaults', valueKind: 'boolean', description: 'Exibir botao voltar.' },
|
|
1349
|
+
{ path: 'defaults.header.backLabel', category: 'defaults', valueKind: 'string', description: 'Label do botao voltar.' },
|
|
1350
|
+
{ path: 'defaults.header.variant', category: 'defaults', valueKind: 'enum', allowedValues: ENUMS.headerVariant, description: 'Variante visual do header.' },
|
|
1351
|
+
{ path: 'defaults.header.sticky', category: 'defaults', valueKind: 'boolean', description: 'Header fixo.' },
|
|
1352
|
+
{ path: 'defaults.header.breadcrumbs', category: 'defaults', valueKind: 'boolean', description: 'Exibir breadcrumbs.' },
|
|
1353
|
+
{ path: 'defaults.header.divider', category: 'defaults', valueKind: 'boolean', description: 'Exibir divisor no header.' },
|
|
1354
|
+
// --- Actions ---
|
|
1355
|
+
{ path: 'actions', category: 'actions', valueKind: 'array', description: 'Acoes disponiveis no CRUD.' },
|
|
1356
|
+
{ path: 'actions[].id', category: 'actions', valueKind: 'string', description: 'ID da acao (RowAction/ToolbarAction).' },
|
|
1357
|
+
{ path: 'actions[].label', category: 'actions', valueKind: 'string', description: 'Label da acao.' },
|
|
1358
|
+
{ path: 'actions[].icon', category: 'actions', valueKind: 'string', description: 'Icone da acao.' },
|
|
1359
|
+
{ path: 'actions[].color', category: 'actions', valueKind: 'string', description: 'Cor da acao.' },
|
|
1360
|
+
{ path: 'actions[].disabled', category: 'actions', valueKind: 'boolean', description: 'Acao desabilitada.' },
|
|
1361
|
+
{ path: 'actions[].action', category: 'actions', valueKind: 'string', description: 'Nome da acao emitida.' },
|
|
1362
|
+
{ path: 'actions[].tooltip', category: 'actions', valueKind: 'string', description: 'Tooltip da acao.' },
|
|
1363
|
+
{ path: 'actions[].requiresConfirmation', category: 'actions', valueKind: 'boolean', description: 'Exige confirmacao.' },
|
|
1364
|
+
{ path: 'actions[].visibleWhen', category: 'actions', valueKind: 'expression', description: 'Condicao de visibilidade (RowAction/ToolbarAction).' },
|
|
1365
|
+
{ path: 'actions[].separator', category: 'actions', valueKind: 'boolean', description: 'Separador apos a acao (RowAction).' },
|
|
1366
|
+
{ path: 'actions[].autoDelete', category: 'actions', valueKind: 'boolean', description: 'Habilita auto delete (RowAction).' },
|
|
1367
|
+
{ path: 'actions[].deleteEndpoint', category: 'actions', valueKind: 'string', description: 'Endpoint custom para delete (RowAction).' },
|
|
1368
|
+
{ path: 'actions[].type', category: 'actions', valueKind: 'enum', allowedValues: ENUMS.toolbarActionType, description: 'Tipo de acao (ToolbarAction).' },
|
|
1369
|
+
{ path: 'actions[].appearance', category: 'actions', valueKind: 'enum', allowedValues: ENUMS.toolbarActionAppearance, description: 'Aparencia do botao (ToolbarAction).' },
|
|
1370
|
+
{ path: 'actions[].position', category: 'actions', valueKind: 'enum', allowedValues: ENUMS.toolbarActionPosition, description: 'Posicao da acao (ToolbarAction).' },
|
|
1371
|
+
{ path: 'actions[].order', category: 'actions', valueKind: 'number', description: 'Ordem de exibicao (ToolbarAction).' },
|
|
1372
|
+
{ path: 'actions[].shortcut', category: 'actions', valueKind: 'string', description: 'Atalho de teclado (ToolbarAction).' },
|
|
1373
|
+
{ path: 'actions[].children', category: 'actions', valueKind: 'array', description: 'Sub-acoes (menu).' },
|
|
1374
|
+
{ path: 'actions[].openMode', category: 'actions', valueKind: 'enum', allowedValues: ENUMS.openMode, description: 'Modo de abertura da acao.' },
|
|
1375
|
+
{ path: 'actions[].route', category: 'actions', valueKind: 'string', description: 'Rota para openMode=route.' },
|
|
1376
|
+
{ path: 'actions[].formId', category: 'actions', valueKind: 'string', description: 'FormId canonico para modal/drawer; se ausente, o host precisa resolve-lo por override por acao antes da abertura.' },
|
|
1377
|
+
{ path: 'actions[].params', category: 'actions', valueKind: 'array', description: 'Mapeamento de parametros.' },
|
|
1378
|
+
{ path: 'actions[].params[].from', category: 'actions', valueKind: 'string', description: 'Origem do parametro.' },
|
|
1379
|
+
{ path: 'actions[].params[].to', category: 'actions', valueKind: 'enum', allowedValues: ENUMS.paramTarget, description: 'Destino do parametro.' },
|
|
1380
|
+
{ path: 'actions[].params[].name', category: 'actions', valueKind: 'string', description: 'Nome do parametro no destino.' },
|
|
1381
|
+
{ path: 'actions[].back', category: 'navigation', valueKind: 'object', description: 'BackConfig por acao.' },
|
|
1382
|
+
{ path: 'actions[].back.strategy', category: 'navigation', valueKind: 'enum', allowedValues: ENUMS.backStrategy },
|
|
1383
|
+
{ path: 'actions[].back.returnTo', category: 'navigation', valueKind: 'string' },
|
|
1384
|
+
{ path: 'actions[].back.confirmOnDirty', category: 'navigation', valueKind: 'boolean' },
|
|
1385
|
+
// --- i18n ---
|
|
1386
|
+
{ path: 'i18n', category: 'i18n', valueKind: 'object', description: 'Mensagens i18n do CRUD.' },
|
|
1387
|
+
{ path: 'i18n.crudDialog', category: 'i18n', valueKind: 'object', description: 'Mapa de textos do dialog.' },
|
|
1388
|
+
],
|
|
1389
|
+
};
|
|
1390
|
+
|
|
1016
1391
|
/*
|
|
1017
1392
|
* Public API Surface of praxis-crud
|
|
1018
1393
|
*/
|
|
@@ -1021,5 +1396,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1021
1396
|
* Generated bundle index. Do not edit.
|
|
1022
1397
|
*/
|
|
1023
1398
|
|
|
1024
|
-
export {
|
|
1399
|
+
export { CRUD_AI_CAPABILITIES, CrudLauncherService, CrudPageHeaderComponent, DialogService, DynamicFormDialogHostComponent, PRAXIS_CRUD_COMPONENT_METADATA, PraxisCrudComponent, assertCrudMetadata, providePraxisCrudMetadata };
|
|
1025
1400
|
//# sourceMappingURL=praxisui-crud.mjs.map
|