@praxisui/metadata-editor 8.0.0-beta.31 → 8.0.0-beta.33
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.
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Injectable, inject, Component, Input, ViewEncapsulation, EventEmitter, DestroyRef, Output, signal, ENVIRONMENT_INITIALIZER } from '@angular/core';
|
|
3
|
-
import * as
|
|
3
|
+
import * as i1 from '@angular/forms';
|
|
4
4
|
import { FormControl, FormGroup, ReactiveFormsModule, FormArray, FormBuilder, FormsModule } from '@angular/forms';
|
|
5
5
|
import * as i3 from '@angular/common';
|
|
6
6
|
import { CommonModule } from '@angular/common';
|
|
7
7
|
import { DynamicFieldLoaderDirective } from '@praxisui/dynamic-fields';
|
|
8
|
-
import * as i2$
|
|
8
|
+
import * as i2$1 from '@praxisui/core';
|
|
9
9
|
import { FieldControlType, PraxisIconDirective, providePraxisI18n, PraxisI18nService, INLINE_FILTER_CONTROL_TYPES, resolveInlineFilterControlType, normalizeControlTypeToken, ComponentMetadataRegistry } from '@praxisui/core';
|
|
10
10
|
import * as i5 from '@angular/material/expansion';
|
|
11
11
|
import { MatExpansionModule } from '@angular/material/expansion';
|
|
12
12
|
import * as i6 from '@angular/material/icon';
|
|
13
13
|
import { MatIconModule } from '@angular/material/icon';
|
|
14
|
-
import * as
|
|
14
|
+
import * as i4 from '@angular/material/button';
|
|
15
15
|
import { MatButtonModule } from '@angular/material/button';
|
|
16
|
-
import * as i1 from '@angular/material/dialog';
|
|
16
|
+
import * as i1$1 from '@angular/material/dialog';
|
|
17
17
|
import { MatDialogRef, MatDialogModule } from '@angular/material/dialog';
|
|
18
18
|
import * as i8 from '@angular/material/tooltip';
|
|
19
19
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
20
|
-
import * as i2
|
|
20
|
+
import * as i2 from '@angular/material/list';
|
|
21
21
|
import { MatListModule } from '@angular/material/list';
|
|
22
22
|
import { SETTINGS_PANEL_DATA } from '@praxisui/settings-panel';
|
|
23
23
|
import { BehaviorSubject } from 'rxjs';
|
|
24
24
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
25
|
-
import * as
|
|
25
|
+
import * as i6$1 from '@angular/material/input';
|
|
26
26
|
import { MatInputModule } from '@angular/material/input';
|
|
27
27
|
import { MatChipsModule } from '@angular/material/chips';
|
|
28
28
|
import { MatDividerModule } from '@angular/material/divider';
|
|
29
|
-
import * as
|
|
29
|
+
import * as i7 from '@angular/material/select';
|
|
30
30
|
import { MatSelectModule } from '@angular/material/select';
|
|
31
|
-
import * as
|
|
31
|
+
import * as i8$1 from '@angular/material/checkbox';
|
|
32
32
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
33
|
-
import * as
|
|
33
|
+
import * as i10 from '@angular/material/menu';
|
|
34
34
|
import { MatMenuModule } from '@angular/material/menu';
|
|
35
|
-
import * as
|
|
35
|
+
import * as i11 from '@angular/material/autocomplete';
|
|
36
36
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
|
37
|
-
import * as
|
|
37
|
+
import * as i12 from '@angular/cdk/scrolling';
|
|
38
38
|
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
39
39
|
|
|
40
40
|
class ConfigRegistryService {
|
|
@@ -51,10 +51,10 @@ class ConfigRegistryService {
|
|
|
51
51
|
count: props.length,
|
|
52
52
|
}));
|
|
53
53
|
}
|
|
54
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
55
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
54
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ConfigRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
55
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ConfigRegistryService, providedIn: 'root' });
|
|
56
56
|
}
|
|
57
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
57
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ConfigRegistryService, decorators: [{
|
|
58
58
|
type: Injectable,
|
|
59
59
|
args: [{ providedIn: 'root' }]
|
|
60
60
|
}] });
|
|
@@ -69,10 +69,10 @@ class ContextValidatorRegistryService {
|
|
|
69
69
|
get(controlType) {
|
|
70
70
|
return this.map.get(controlType) ?? [];
|
|
71
71
|
}
|
|
72
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
73
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
72
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ContextValidatorRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
73
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ContextValidatorRegistryService, providedIn: 'root' });
|
|
74
74
|
}
|
|
75
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
75
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ContextValidatorRegistryService, decorators: [{
|
|
76
76
|
type: Injectable,
|
|
77
77
|
args: [{ providedIn: 'root' }]
|
|
78
78
|
}] });
|
|
@@ -182,10 +182,10 @@ class SchemaNormalizerService {
|
|
|
182
182
|
getByPath(obj, path) {
|
|
183
183
|
return path.split('.').reduce((acc, key) => (acc == null ? acc : acc[key]), obj);
|
|
184
184
|
}
|
|
185
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
186
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
185
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SchemaNormalizerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
186
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SchemaNormalizerService, providedIn: 'root' });
|
|
187
187
|
}
|
|
188
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
188
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SchemaNormalizerService, decorators: [{
|
|
189
189
|
type: Injectable,
|
|
190
190
|
args: [{ providedIn: 'root' }]
|
|
191
191
|
}] });
|
|
@@ -276,13 +276,13 @@ class DynamicFormFactoryService {
|
|
|
276
276
|
}
|
|
277
277
|
return result;
|
|
278
278
|
}
|
|
279
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
280
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
279
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormFactoryService, deps: [{ token: i1.FormBuilder }, { token: ContextValidatorRegistryService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
280
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormFactoryService, providedIn: 'root' });
|
|
281
281
|
}
|
|
282
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
282
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormFactoryService, decorators: [{
|
|
283
283
|
type: Injectable,
|
|
284
284
|
args: [{ providedIn: 'root' }]
|
|
285
|
-
}], ctorParameters: () => [{ type:
|
|
285
|
+
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: ContextValidatorRegistryService }] });
|
|
286
286
|
|
|
287
287
|
class EditorComponentRegistryService {
|
|
288
288
|
registry = new Map();
|
|
@@ -305,10 +305,10 @@ class EditorComponentRegistryService {
|
|
|
305
305
|
isRegistered(editorType) {
|
|
306
306
|
return this.registry.has(editorType);
|
|
307
307
|
}
|
|
308
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
309
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
308
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EditorComponentRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
309
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EditorComponentRegistryService, providedIn: 'root' });
|
|
310
310
|
}
|
|
311
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
311
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EditorComponentRegistryService, decorators: [{
|
|
312
312
|
type: Injectable,
|
|
313
313
|
args: [{ providedIn: 'root' }]
|
|
314
314
|
}] });
|
|
@@ -349,8 +349,8 @@ class RegexHelpDialogComponent {
|
|
|
349
349
|
choose(pattern) {
|
|
350
350
|
this.dialogRef.close(pattern);
|
|
351
351
|
}
|
|
352
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
353
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
352
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: RegexHelpDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
353
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: RegexHelpDialogComponent, isStandalone: true, selector: "praxis-regex-help-dialog", ngImport: i0, template: `
|
|
354
354
|
<h2 mat-dialog-title>Modelos de Expressões Regulares</h2>
|
|
355
355
|
<div mat-dialog-content>
|
|
356
356
|
<p>Selecione um dos modelos abaixo para preencher o campo ou use como base:</p>
|
|
@@ -371,14 +371,14 @@ class RegexHelpDialogComponent {
|
|
|
371
371
|
<div mat-dialog-actions>
|
|
372
372
|
<button class="mat-mdc-button mdc-button" mat-dialog-close>Fechar</button>
|
|
373
373
|
</div>
|
|
374
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type:
|
|
374
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: i2.MatListItemLine, selector: "[matListItemLine]" }, { kind: "directive", type: i2.MatListItemTitle, selector: "[matListItemTitle]" }, { kind: "ngmodule", type: MatButtonModule }] });
|
|
375
375
|
}
|
|
376
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
376
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: RegexHelpDialogComponent, decorators: [{
|
|
377
377
|
type: Component,
|
|
378
378
|
args: [{
|
|
379
379
|
selector: 'praxis-regex-help-dialog',
|
|
380
380
|
standalone: true,
|
|
381
|
-
imports: [
|
|
381
|
+
imports: [MatDialogModule, MatListModule, MatButtonModule],
|
|
382
382
|
template: `
|
|
383
383
|
<h2 mat-dialog-title>Modelos de Expressões Regulares</h2>
|
|
384
384
|
<div mat-dialog-content>
|
|
@@ -684,79 +684,87 @@ class DynamicEditorRendererComponent {
|
|
|
684
684
|
this.form?.markAsDirty();
|
|
685
685
|
}
|
|
686
686
|
}
|
|
687
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
688
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
687
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicEditorRendererComponent, deps: [{ token: i1$1.MatDialog }, { token: i2$1.IconPickerService }], target: i0.ɵɵFactoryTarget.Component });
|
|
688
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicEditorRendererComponent, isStandalone: true, selector: "praxis-dynamic-editor-renderer", inputs: { properties: "properties", form: "form" }, usesOnChanges: true, ngImport: i0, template: `
|
|
689
689
|
<ng-template #item let-field="field" let-index="index" let-content="content">
|
|
690
690
|
<div class="editor-item" [attr.data-control-type]="field.controlType">
|
|
691
691
|
<ng-container [ngTemplateOutlet]="content"></ng-container>
|
|
692
|
-
|
|
692
|
+
|
|
693
693
|
<div class="actions-container">
|
|
694
694
|
<!-- Botão de ajuda para regex -->
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
695
|
+
@if (field.name === 'pattern') {
|
|
696
|
+
<button
|
|
697
|
+
type="button"
|
|
698
|
+
mat-icon-button
|
|
699
|
+
class="regex-help-btn decorator-btn"
|
|
700
|
+
(click)="openRegexHelp()"
|
|
701
|
+
aria-label="Exemplos de regex"
|
|
702
|
+
matTooltip="Exemplos de regex"
|
|
703
|
+
>
|
|
704
|
+
<mat-icon [praxisIcon]="'search'"></mat-icon>
|
|
705
|
+
</button>
|
|
706
|
+
}
|
|
706
707
|
<!-- Botão para escolher ícone (prefix/suffix) -->
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
708
|
+
@if (isIconField(field.name)) {
|
|
709
|
+
<button
|
|
710
|
+
type="button"
|
|
711
|
+
mat-icon-button
|
|
712
|
+
class="icon-picker-btn decorator-btn"
|
|
713
|
+
(click)="openIconPicker(field.name)"
|
|
714
|
+
aria-label="Escolher ícone"
|
|
715
|
+
matTooltip="Escolher ícone"
|
|
716
|
+
>
|
|
717
|
+
<mat-icon [praxisIcon]="'apps'"></mat-icon>
|
|
718
|
+
</button>
|
|
719
|
+
}
|
|
718
720
|
<!-- Botão de ajuda (fallback quando suffix não é aplicado) -->
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
721
|
+
@if (field.hint && !useHelpSuffix(field)) {
|
|
722
|
+
<button
|
|
723
|
+
type="button"
|
|
724
|
+
mat-icon-button
|
|
725
|
+
class="hint-btn decorator-btn"
|
|
726
|
+
[class.has-icon-picker]="isIconField(field.name)"
|
|
727
|
+
[matTooltip]="field.hint"
|
|
728
|
+
aria-label="Ajuda"
|
|
729
|
+
>
|
|
730
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
731
|
+
</button>
|
|
732
|
+
}
|
|
730
733
|
</div>
|
|
731
734
|
</div>
|
|
732
735
|
</ng-template>
|
|
733
|
-
|
|
736
|
+
|
|
734
737
|
<div class="editor-surface">
|
|
735
738
|
<mat-accordion class="section-accordion" multi>
|
|
736
|
-
|
|
737
|
-
<mat-expansion-panel
|
|
738
|
-
<mat-panel-
|
|
739
|
-
<
|
|
740
|
-
<
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
739
|
+
@for (g of groupOrder; track g) {
|
|
740
|
+
<mat-expansion-panel class="section-card">
|
|
741
|
+
<mat-expansion-panel-header class="section-header">
|
|
742
|
+
<mat-panel-title>
|
|
743
|
+
<span class="section-title">
|
|
744
|
+
<mat-icon class="section-icon" [praxisIcon]="groupIcon(g)"></mat-icon>
|
|
745
|
+
{{ g }}
|
|
746
|
+
</span>
|
|
747
|
+
</mat-panel-title>
|
|
748
|
+
</mat-expansion-panel-header>
|
|
749
|
+
@for (row of groupRows[g]; track row) {
|
|
750
|
+
<div class="editor-row" [ngClass]="rowClass(row)">
|
|
751
|
+
@if (ready) {
|
|
752
|
+
<ng-container
|
|
753
|
+
dynamicFieldLoader
|
|
754
|
+
[fields]="row"
|
|
755
|
+
[formGroup]="form"
|
|
756
|
+
[itemTemplate]="item">
|
|
757
|
+
</ng-container>
|
|
758
|
+
}
|
|
759
|
+
</div>
|
|
760
|
+
}
|
|
761
|
+
</mat-expansion-panel>
|
|
762
|
+
}
|
|
755
763
|
</mat-accordion>
|
|
756
764
|
</div>
|
|
757
|
-
|
|
765
|
+
`, isInline: true, styles: [":host{display:block}.editor-surface{padding:8px 0 2px;border-radius:12px;background:transparent}.section-accordion{display:block}.section-card{margin:6px 0 8px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant);overflow:hidden}.section-card.mat-expanded{border-color:var(--md-sys-color-primary);box-shadow:0 2px 10px #0000000d}.section-card .mat-expansion-panel-body{background:var(--md-sys-color-surface-container-low)}.section-header{background:var(--md-sys-color-surface-container-low);border-bottom:1px solid var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium));padding:2px 8px;min-height:32px;display:flex;align-items:center;color:var(--md-sys-color-on-surface)}.section-header .mat-expansion-panel-header-title,.section-header .mat-expansion-panel-header-description{display:flex;align-items:center;color:var(--md-sys-color-on-surface)}.section-title{display:inline-flex;align-items:center;gap:6px;font-weight:600;letter-spacing:.2px;color:var(--md-sys-color-on-surface);font-size:.9rem;line-height:1.2}.section-icon{color:var(--md-sys-color-primary, var(--md-sys-color-primary, #3f51b5));opacity:.9}.editor-row{display:flex;gap:12px;align-items:flex-start;flex-wrap:wrap;margin-bottom:8px}.editor-row>praxis-field-shell{flex:1 1 100%;min-width:280px}.editor-row praxis-field-shell .mat-mdc-form-field{width:100%;margin-bottom:8px}.editor-row.row-inline>praxis-field-shell{flex:0 0 auto}.editor-row.row-2>praxis-field-shell{flex:1 1 calc(50% - 12px);min-width:260px}.editor-row.row-3>praxis-field-shell{flex:1 1 calc(33.333% - 12px);min-width:220px}.editor-row>praxis-field-shell[data-field-name=controlType],.editor-row>praxis-field-shell[data-field-name=label],.editor-row>praxis-field-shell[data-field-name=placeholder]{flex:1 1 calc(50% - 12px);min-width:300px}praxis-field-shell[data-field-name=label] .mdc-floating-label,praxis-field-shell[data-field-name=placeholder] .mdc-floating-label{font-weight:600}.editor-row>praxis-field-shell[data-field-name=prefix],.editor-row>praxis-field-shell[data-field-name=suffix]{flex:0 0 200px;min-width:160px}.editor-row>praxis-field-shell[data-field-name=prefixIcon],.editor-row>praxis-field-shell[data-field-name=suffixIcon],.editor-row>praxis-field-shell[data-field-name=prefixIconColor],.editor-row>praxis-field-shell[data-field-name=suffixIconColor]{flex:1 1 auto;min-width:160px}.editor-item{display:flex;align-items:flex-start;gap:4px}.editor-item>ng-container,.editor-item>praxis-field-shell{flex:1;min-width:0}.actions-container{display:flex;align-items:center;gap:0;margin-top:12px;flex-shrink:0}.decorator-btn{position:static;color:var(--md-sys-color-primary, #3f51b5);opacity:.6;transform:scale(.8);width:32px;height:32px;line-height:32px;padding:0}.decorator-btn:hover{opacity:1}.icon-picker-btn,.hint-btn,.hint-btn.has-icon-picker{right:auto}.editor-row .mat-mdc-form-field-subscript-wrapper mat-hint{display:none!important}.editor-row .mat-mdc-form-field-subscript-wrapper mat-error{display:block!important}praxis-field-shell[data-field-name=showCharCount] .mdc-switch{transform:scale(1.05)}praxis-field-shell[data-field-name=showCharCount] .mat-mdc-slide-toggle{font-weight:600}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-hint{display:flex;align-items:center;gap:8px;background:var(--md-sys-color-tertiary-container);border:1px solid var(--md-sys-color-tertiary);color:var(--md-sys-color-on-tertiary-container);padding:8px 10px;border-radius:6px;line-height:1.3;white-space:normal}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-hint:before{content:\"\\26a0\\fe0f\";display:inline-block}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-subscript-wrapper{margin-top:6px;margin-bottom:10px;min-height:auto}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field{margin-bottom:16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick", "canvasFocus"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i5.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i5.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i5.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i5.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatDialogModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
758
766
|
}
|
|
759
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
767
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicEditorRendererComponent, decorators: [{
|
|
760
768
|
type: Component,
|
|
761
769
|
args: [{ selector: 'praxis-dynamic-editor-renderer', standalone: true, imports: [
|
|
762
770
|
CommonModule,
|
|
@@ -772,73 +780,81 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
772
780
|
<ng-template #item let-field="field" let-index="index" let-content="content">
|
|
773
781
|
<div class="editor-item" [attr.data-control-type]="field.controlType">
|
|
774
782
|
<ng-container [ngTemplateOutlet]="content"></ng-container>
|
|
775
|
-
|
|
783
|
+
|
|
776
784
|
<div class="actions-container">
|
|
777
785
|
<!-- Botão de ajuda para regex -->
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
786
|
+
@if (field.name === 'pattern') {
|
|
787
|
+
<button
|
|
788
|
+
type="button"
|
|
789
|
+
mat-icon-button
|
|
790
|
+
class="regex-help-btn decorator-btn"
|
|
791
|
+
(click)="openRegexHelp()"
|
|
792
|
+
aria-label="Exemplos de regex"
|
|
793
|
+
matTooltip="Exemplos de regex"
|
|
794
|
+
>
|
|
795
|
+
<mat-icon [praxisIcon]="'search'"></mat-icon>
|
|
796
|
+
</button>
|
|
797
|
+
}
|
|
789
798
|
<!-- Botão para escolher ícone (prefix/suffix) -->
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
799
|
+
@if (isIconField(field.name)) {
|
|
800
|
+
<button
|
|
801
|
+
type="button"
|
|
802
|
+
mat-icon-button
|
|
803
|
+
class="icon-picker-btn decorator-btn"
|
|
804
|
+
(click)="openIconPicker(field.name)"
|
|
805
|
+
aria-label="Escolher ícone"
|
|
806
|
+
matTooltip="Escolher ícone"
|
|
807
|
+
>
|
|
808
|
+
<mat-icon [praxisIcon]="'apps'"></mat-icon>
|
|
809
|
+
</button>
|
|
810
|
+
}
|
|
801
811
|
<!-- Botão de ajuda (fallback quando suffix não é aplicado) -->
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
812
|
+
@if (field.hint && !useHelpSuffix(field)) {
|
|
813
|
+
<button
|
|
814
|
+
type="button"
|
|
815
|
+
mat-icon-button
|
|
816
|
+
class="hint-btn decorator-btn"
|
|
817
|
+
[class.has-icon-picker]="isIconField(field.name)"
|
|
818
|
+
[matTooltip]="field.hint"
|
|
819
|
+
aria-label="Ajuda"
|
|
820
|
+
>
|
|
821
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
822
|
+
</button>
|
|
823
|
+
}
|
|
813
824
|
</div>
|
|
814
825
|
</div>
|
|
815
826
|
</ng-template>
|
|
816
|
-
|
|
827
|
+
|
|
817
828
|
<div class="editor-surface">
|
|
818
829
|
<mat-accordion class="section-accordion" multi>
|
|
819
|
-
|
|
820
|
-
<mat-expansion-panel
|
|
821
|
-
<mat-panel-
|
|
822
|
-
<
|
|
823
|
-
<
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
830
|
+
@for (g of groupOrder; track g) {
|
|
831
|
+
<mat-expansion-panel class="section-card">
|
|
832
|
+
<mat-expansion-panel-header class="section-header">
|
|
833
|
+
<mat-panel-title>
|
|
834
|
+
<span class="section-title">
|
|
835
|
+
<mat-icon class="section-icon" [praxisIcon]="groupIcon(g)"></mat-icon>
|
|
836
|
+
{{ g }}
|
|
837
|
+
</span>
|
|
838
|
+
</mat-panel-title>
|
|
839
|
+
</mat-expansion-panel-header>
|
|
840
|
+
@for (row of groupRows[g]; track row) {
|
|
841
|
+
<div class="editor-row" [ngClass]="rowClass(row)">
|
|
842
|
+
@if (ready) {
|
|
843
|
+
<ng-container
|
|
844
|
+
dynamicFieldLoader
|
|
845
|
+
[fields]="row"
|
|
846
|
+
[formGroup]="form"
|
|
847
|
+
[itemTemplate]="item">
|
|
848
|
+
</ng-container>
|
|
849
|
+
}
|
|
850
|
+
</div>
|
|
851
|
+
}
|
|
852
|
+
</mat-expansion-panel>
|
|
853
|
+
}
|
|
838
854
|
</mat-accordion>
|
|
839
855
|
</div>
|
|
840
|
-
|
|
841
|
-
}], ctorParameters: () => [{ type: i1.MatDialog }, { type: i2$
|
|
856
|
+
`, styles: [":host{display:block}.editor-surface{padding:8px 0 2px;border-radius:12px;background:transparent}.section-accordion{display:block}.section-card{margin:6px 0 8px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant);overflow:hidden}.section-card.mat-expanded{border-color:var(--md-sys-color-primary);box-shadow:0 2px 10px #0000000d}.section-card .mat-expansion-panel-body{background:var(--md-sys-color-surface-container-low)}.section-header{background:var(--md-sys-color-surface-container-low);border-bottom:1px solid var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium));padding:2px 8px;min-height:32px;display:flex;align-items:center;color:var(--md-sys-color-on-surface)}.section-header .mat-expansion-panel-header-title,.section-header .mat-expansion-panel-header-description{display:flex;align-items:center;color:var(--md-sys-color-on-surface)}.section-title{display:inline-flex;align-items:center;gap:6px;font-weight:600;letter-spacing:.2px;color:var(--md-sys-color-on-surface);font-size:.9rem;line-height:1.2}.section-icon{color:var(--md-sys-color-primary, var(--md-sys-color-primary, #3f51b5));opacity:.9}.editor-row{display:flex;gap:12px;align-items:flex-start;flex-wrap:wrap;margin-bottom:8px}.editor-row>praxis-field-shell{flex:1 1 100%;min-width:280px}.editor-row praxis-field-shell .mat-mdc-form-field{width:100%;margin-bottom:8px}.editor-row.row-inline>praxis-field-shell{flex:0 0 auto}.editor-row.row-2>praxis-field-shell{flex:1 1 calc(50% - 12px);min-width:260px}.editor-row.row-3>praxis-field-shell{flex:1 1 calc(33.333% - 12px);min-width:220px}.editor-row>praxis-field-shell[data-field-name=controlType],.editor-row>praxis-field-shell[data-field-name=label],.editor-row>praxis-field-shell[data-field-name=placeholder]{flex:1 1 calc(50% - 12px);min-width:300px}praxis-field-shell[data-field-name=label] .mdc-floating-label,praxis-field-shell[data-field-name=placeholder] .mdc-floating-label{font-weight:600}.editor-row>praxis-field-shell[data-field-name=prefix],.editor-row>praxis-field-shell[data-field-name=suffix]{flex:0 0 200px;min-width:160px}.editor-row>praxis-field-shell[data-field-name=prefixIcon],.editor-row>praxis-field-shell[data-field-name=suffixIcon],.editor-row>praxis-field-shell[data-field-name=prefixIconColor],.editor-row>praxis-field-shell[data-field-name=suffixIconColor]{flex:1 1 auto;min-width:160px}.editor-item{display:flex;align-items:flex-start;gap:4px}.editor-item>ng-container,.editor-item>praxis-field-shell{flex:1;min-width:0}.actions-container{display:flex;align-items:center;gap:0;margin-top:12px;flex-shrink:0}.decorator-btn{position:static;color:var(--md-sys-color-primary, #3f51b5);opacity:.6;transform:scale(.8);width:32px;height:32px;line-height:32px;padding:0}.decorator-btn:hover{opacity:1}.icon-picker-btn,.hint-btn,.hint-btn.has-icon-picker{right:auto}.editor-row .mat-mdc-form-field-subscript-wrapper mat-hint{display:none!important}.editor-row .mat-mdc-form-field-subscript-wrapper mat-error{display:block!important}praxis-field-shell[data-field-name=showCharCount] .mdc-switch{transform:scale(1.05)}praxis-field-shell[data-field-name=showCharCount] .mat-mdc-slide-toggle{font-weight:600}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-hint{display:flex;align-items:center;gap:8px;background:var(--md-sys-color-tertiary-container);border:1px solid var(--md-sys-color-tertiary);color:var(--md-sys-color-on-tertiary-container);padding:8px 10px;border-radius:6px;line-height:1.3;white-space:normal}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-hint:before{content:\"\\26a0\\fe0f\";display:inline-block}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-subscript-wrapper{margin-top:6px;margin-bottom:10px;min-height:auto}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field{margin-bottom:16px}\n"] }]
|
|
857
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: i2$1.IconPickerService }], propDecorators: { properties: [{
|
|
842
858
|
type: Input
|
|
843
859
|
}], form: [{
|
|
844
860
|
type: Input
|
|
@@ -1447,13 +1463,13 @@ class ArrayItemSchemaFieldsEditorComponent {
|
|
|
1447
1463
|
escapeRegExp(value) {
|
|
1448
1464
|
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1449
1465
|
}
|
|
1450
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1451
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1466
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ArrayItemSchemaFieldsEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1467
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ArrayItemSchemaFieldsEditorComponent, isStandalone: true, selector: "praxis-array-item-schema-fields-editor", inputs: { control: "control", arrayControl: "arrayControl" }, providers: [providePraxisMetadataEditorI18n()], usesOnChanges: true, ngImport: i0, template: `
|
|
1452
1468
|
<section
|
|
1453
1469
|
class="array-fields-editor"
|
|
1454
1470
|
[attr.data-schema-source]="schemaSourceState"
|
|
1455
1471
|
[attr.aria-label]="text('praxis.metadataEditor.arrayFields.section', 'Subcampos da cole\u00e7\u00e3o')"
|
|
1456
|
-
|
|
1472
|
+
>
|
|
1457
1473
|
<header class="array-fields-editor__header">
|
|
1458
1474
|
<div>
|
|
1459
1475
|
<h3>{{ text('praxis.metadataEditor.arrayFields.title', 'Subcampos') }}</h3>
|
|
@@ -1465,104 +1481,106 @@ class ArrayItemSchemaFieldsEditorComponent {
|
|
|
1465
1481
|
{{ text('praxis.metadataEditor.arrayFields.add', 'Adicionar subcampo') }}
|
|
1466
1482
|
</button>
|
|
1467
1483
|
</header>
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1484
|
+
|
|
1485
|
+
@if (duplicateNames.length) {
|
|
1486
|
+
<div
|
|
1487
|
+
class="array-fields-editor__warning"
|
|
1488
|
+
role="alert"
|
|
1489
|
+
>
|
|
1490
|
+
{{
|
|
1475
1491
|
text(
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1492
|
+
'praxis.metadataEditor.arrayFields.duplicateNames',
|
|
1493
|
+
undefined,
|
|
1494
|
+
'Existem nomes duplicados: {{names}}',
|
|
1495
|
+
{ names: duplicateNames.join(', ') }
|
|
1480
1496
|
)
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
*ngIf="formArray.length === 0"
|
|
1487
|
-
>
|
|
1488
|
-
{{ text('praxis.metadataEditor.arrayFields.empty', 'Nenhum subcampo local configurado.') }}
|
|
1489
|
-
</div>
|
|
1490
|
-
|
|
1491
|
-
<div class="array-fields-editor__list" [formGroup]="form">
|
|
1497
|
+
}}
|
|
1498
|
+
</div>
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
@if (formArray.length === 0) {
|
|
1492
1502
|
<div
|
|
1493
|
-
class="array-fields-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
>
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
[attr.aria-describedby]="nameErrorDescribedBy(i)"
|
|
1505
|
-
/>
|
|
1506
|
-
<span
|
|
1507
|
-
class="array-fields-editor__field-error"
|
|
1508
|
-
*ngIf="nameErrorMessage(i) as nameError"
|
|
1509
|
-
[id]="nameErrorId(i)"
|
|
1510
|
-
>
|
|
1511
|
-
{{ nameError }}
|
|
1512
|
-
</span>
|
|
1513
|
-
</label>
|
|
1514
|
-
|
|
1515
|
-
<label>
|
|
1516
|
-
<span>{{ text('praxis.metadataEditor.arrayFields.label', 'Label') }}</span>
|
|
1517
|
-
<input type="text" formControlName="label" />
|
|
1518
|
-
</label>
|
|
1519
|
-
|
|
1520
|
-
<label>
|
|
1521
|
-
<span>{{ text('praxis.metadataEditor.arrayFields.controlType', 'Controle') }}</span>
|
|
1522
|
-
<select formControlName="controlType">
|
|
1523
|
-
<option *ngFor="let option of controlTypeOptions" [value]="option">
|
|
1524
|
-
{{ controlTypeLabel(option) }}
|
|
1525
|
-
</option>
|
|
1526
|
-
</select>
|
|
1527
|
-
</label>
|
|
1528
|
-
|
|
1529
|
-
<label class="array-fields-editor__check">
|
|
1530
|
-
<input type="checkbox" formControlName="required" />
|
|
1531
|
-
<span>{{ text('praxis.metadataEditor.arrayFields.required', 'Obrigat\u00f3rio') }}</span>
|
|
1532
|
-
</label>
|
|
1533
|
-
|
|
1534
|
-
<div class="array-fields-editor__actions">
|
|
1535
|
-
<button type="button" (click)="moveField(i, -1)" [disabled]="i === 0">
|
|
1536
|
-
{{ text('praxis.metadataEditor.arrayFields.moveUp', 'Subir') }}
|
|
1537
|
-
</button>
|
|
1538
|
-
<button type="button" (click)="moveField(i, 1)" [disabled]="i === formArray.length - 1">
|
|
1539
|
-
{{ text('praxis.metadataEditor.arrayFields.moveDown', 'Descer') }}
|
|
1540
|
-
</button>
|
|
1541
|
-
<button type="button" (click)="duplicateField(i)">
|
|
1542
|
-
{{ text('praxis.metadataEditor.arrayFields.duplicate', 'Duplicar') }}
|
|
1543
|
-
</button>
|
|
1544
|
-
<button
|
|
1545
|
-
type="button"
|
|
1546
|
-
(click)="removeField(i)"
|
|
1547
|
-
[disabled]="isReferenced(row.get('name')?.value)"
|
|
1548
|
-
[title]="removeTitle(row.get('name')?.value)"
|
|
1503
|
+
class="array-fields-editor__empty"
|
|
1504
|
+
>
|
|
1505
|
+
{{ text('praxis.metadataEditor.arrayFields.empty', 'Nenhum subcampo local configurado.') }}
|
|
1506
|
+
</div>
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
<div class="array-fields-editor__list" [formGroup]="form">
|
|
1510
|
+
@for (row of rows; track row; let i = $index) {
|
|
1511
|
+
<div
|
|
1512
|
+
class="array-fields-editor__row"
|
|
1513
|
+
[formGroup]="row"
|
|
1549
1514
|
>
|
|
1550
|
-
|
|
1551
|
-
|
|
1515
|
+
<label>
|
|
1516
|
+
<span>{{ text('praxis.metadataEditor.arrayFields.name', 'Nome') }}</span>
|
|
1517
|
+
<input
|
|
1518
|
+
type="text"
|
|
1519
|
+
formControlName="name"
|
|
1520
|
+
(blur)="onNameBlur(i)"
|
|
1521
|
+
[attr.aria-invalid]="isNameInvalid(i) ? 'true' : null"
|
|
1522
|
+
[attr.aria-describedby]="nameErrorDescribedBy(i)"
|
|
1523
|
+
/>
|
|
1524
|
+
@if (nameErrorMessage(i); as nameError) {
|
|
1525
|
+
<span
|
|
1526
|
+
class="array-fields-editor__field-error"
|
|
1527
|
+
[id]="nameErrorId(i)"
|
|
1528
|
+
>
|
|
1529
|
+
{{ nameError }}
|
|
1530
|
+
</span>
|
|
1531
|
+
}
|
|
1532
|
+
</label>
|
|
1533
|
+
<label>
|
|
1534
|
+
<span>{{ text('praxis.metadataEditor.arrayFields.label', 'Label') }}</span>
|
|
1535
|
+
<input type="text" formControlName="label" />
|
|
1536
|
+
</label>
|
|
1537
|
+
<label>
|
|
1538
|
+
<span>{{ text('praxis.metadataEditor.arrayFields.controlType', 'Controle') }}</span>
|
|
1539
|
+
<select formControlName="controlType">
|
|
1540
|
+
@for (option of controlTypeOptions; track option) {
|
|
1541
|
+
<option [value]="option">
|
|
1542
|
+
{{ controlTypeLabel(option) }}
|
|
1543
|
+
</option>
|
|
1544
|
+
}
|
|
1545
|
+
</select>
|
|
1546
|
+
</label>
|
|
1547
|
+
<label class="array-fields-editor__check">
|
|
1548
|
+
<input type="checkbox" formControlName="required" />
|
|
1549
|
+
<span>{{ text('praxis.metadataEditor.arrayFields.required', 'Obrigat\u00f3rio') }}</span>
|
|
1550
|
+
</label>
|
|
1551
|
+
<div class="array-fields-editor__actions">
|
|
1552
|
+
<button type="button" (click)="moveField(i, -1)" [disabled]="i === 0">
|
|
1553
|
+
{{ text('praxis.metadataEditor.arrayFields.moveUp', 'Subir') }}
|
|
1554
|
+
</button>
|
|
1555
|
+
<button type="button" (click)="moveField(i, 1)" [disabled]="i === formArray.length - 1">
|
|
1556
|
+
{{ text('praxis.metadataEditor.arrayFields.moveDown', 'Descer') }}
|
|
1557
|
+
</button>
|
|
1558
|
+
<button type="button" (click)="duplicateField(i)">
|
|
1559
|
+
{{ text('praxis.metadataEditor.arrayFields.duplicate', 'Duplicar') }}
|
|
1560
|
+
</button>
|
|
1561
|
+
<button
|
|
1562
|
+
type="button"
|
|
1563
|
+
(click)="removeField(i)"
|
|
1564
|
+
[disabled]="isReferenced(row.get('name')?.value)"
|
|
1565
|
+
[title]="removeTitle(row.get('name')?.value)"
|
|
1566
|
+
>
|
|
1567
|
+
{{ text('praxis.metadataEditor.arrayFields.remove', 'Remover') }}
|
|
1568
|
+
</button>
|
|
1569
|
+
</div>
|
|
1552
1570
|
</div>
|
|
1553
|
-
|
|
1571
|
+
}
|
|
1554
1572
|
</div>
|
|
1555
1573
|
</section>
|
|
1556
|
-
|
|
1574
|
+
`, isInline: true, styles: [":host{display:block}.array-fields-editor{display:block;margin:10px 0 2px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface)}.array-fields-editor__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:12px}.array-fields-editor__header h3{margin:0 0 4px;font-size:1rem;line-height:1.25}.array-fields-editor__header p,.array-fields-editor__empty{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:.875rem;line-height:1.35}.array-fields-editor__primary,.array-fields-editor button{border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer;min-height:32px;padding:5px 10px}.array-fields-editor__primary{border-color:var(--md-sys-color-primary);color:var(--md-sys-color-primary);font-weight:600;white-space:nowrap}.array-fields-editor button:disabled{cursor:not-allowed;opacity:.55}.array-fields-editor__warning{margin:8px 0 12px;padding:8px 10px;border:1px solid var(--md-sys-color-error);border-radius:6px;color:var(--md-sys-color-error);background:var(--md-sys-color-error-container)}.array-fields-editor__list{display:grid;gap:10px}.array-fields-editor__row{display:grid;grid-template-columns:minmax(140px,1fr) minmax(160px,1.2fr) minmax(140px,.9fr) auto;gap:10px;align-items:end;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}.array-fields-editor label{display:grid;gap:4px;font-size:.8rem;font-weight:600}.array-fields-editor input[type=text],.array-fields-editor select{box-sizing:border-box;width:100%;min-height:34px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:5px 8px}.array-fields-editor input[aria-invalid=true]{border-color:var(--md-sys-color-error)}.array-fields-editor__field-error{color:var(--md-sys-color-error);font-size:.75rem;font-weight:500;line-height:1.3}.array-fields-editor__check{display:flex!important;align-items:center;gap:6px;min-height:34px}.array-fields-editor__actions{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:6px}@media(max-width:720px){.array-fields-editor__header,.array-fields-editor__row{display:grid;grid-template-columns:1fr}.array-fields-editor__primary{width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
|
|
1557
1575
|
}
|
|
1558
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1576
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ArrayItemSchemaFieldsEditorComponent, decorators: [{
|
|
1559
1577
|
type: Component,
|
|
1560
|
-
args: [{ selector: 'praxis-array-item-schema-fields-editor', standalone: true, imports: [
|
|
1578
|
+
args: [{ selector: 'praxis-array-item-schema-fields-editor', standalone: true, imports: [ReactiveFormsModule], providers: [providePraxisMetadataEditorI18n()], template: `
|
|
1561
1579
|
<section
|
|
1562
1580
|
class="array-fields-editor"
|
|
1563
1581
|
[attr.data-schema-source]="schemaSourceState"
|
|
1564
1582
|
[attr.aria-label]="text('praxis.metadataEditor.arrayFields.section', 'Subcampos da cole\u00e7\u00e3o')"
|
|
1565
|
-
|
|
1583
|
+
>
|
|
1566
1584
|
<header class="array-fields-editor__header">
|
|
1567
1585
|
<div>
|
|
1568
1586
|
<h3>{{ text('praxis.metadataEditor.arrayFields.title', 'Subcampos') }}</h3>
|
|
@@ -1574,95 +1592,97 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
1574
1592
|
{{ text('praxis.metadataEditor.arrayFields.add', 'Adicionar subcampo') }}
|
|
1575
1593
|
</button>
|
|
1576
1594
|
</header>
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1595
|
+
|
|
1596
|
+
@if (duplicateNames.length) {
|
|
1597
|
+
<div
|
|
1598
|
+
class="array-fields-editor__warning"
|
|
1599
|
+
role="alert"
|
|
1600
|
+
>
|
|
1601
|
+
{{
|
|
1584
1602
|
text(
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1603
|
+
'praxis.metadataEditor.arrayFields.duplicateNames',
|
|
1604
|
+
undefined,
|
|
1605
|
+
'Existem nomes duplicados: {{names}}',
|
|
1606
|
+
{ names: duplicateNames.join(', ') }
|
|
1589
1607
|
)
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
*ngIf="formArray.length === 0"
|
|
1596
|
-
>
|
|
1597
|
-
{{ text('praxis.metadataEditor.arrayFields.empty', 'Nenhum subcampo local configurado.') }}
|
|
1598
|
-
</div>
|
|
1599
|
-
|
|
1600
|
-
<div class="array-fields-editor__list" [formGroup]="form">
|
|
1608
|
+
}}
|
|
1609
|
+
</div>
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
@if (formArray.length === 0) {
|
|
1601
1613
|
<div
|
|
1602
|
-
class="array-fields-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
>
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
[attr.aria-describedby]="nameErrorDescribedBy(i)"
|
|
1614
|
-
/>
|
|
1615
|
-
<span
|
|
1616
|
-
class="array-fields-editor__field-error"
|
|
1617
|
-
*ngIf="nameErrorMessage(i) as nameError"
|
|
1618
|
-
[id]="nameErrorId(i)"
|
|
1619
|
-
>
|
|
1620
|
-
{{ nameError }}
|
|
1621
|
-
</span>
|
|
1622
|
-
</label>
|
|
1623
|
-
|
|
1624
|
-
<label>
|
|
1625
|
-
<span>{{ text('praxis.metadataEditor.arrayFields.label', 'Label') }}</span>
|
|
1626
|
-
<input type="text" formControlName="label" />
|
|
1627
|
-
</label>
|
|
1628
|
-
|
|
1629
|
-
<label>
|
|
1630
|
-
<span>{{ text('praxis.metadataEditor.arrayFields.controlType', 'Controle') }}</span>
|
|
1631
|
-
<select formControlName="controlType">
|
|
1632
|
-
<option *ngFor="let option of controlTypeOptions" [value]="option">
|
|
1633
|
-
{{ controlTypeLabel(option) }}
|
|
1634
|
-
</option>
|
|
1635
|
-
</select>
|
|
1636
|
-
</label>
|
|
1637
|
-
|
|
1638
|
-
<label class="array-fields-editor__check">
|
|
1639
|
-
<input type="checkbox" formControlName="required" />
|
|
1640
|
-
<span>{{ text('praxis.metadataEditor.arrayFields.required', 'Obrigat\u00f3rio') }}</span>
|
|
1641
|
-
</label>
|
|
1642
|
-
|
|
1643
|
-
<div class="array-fields-editor__actions">
|
|
1644
|
-
<button type="button" (click)="moveField(i, -1)" [disabled]="i === 0">
|
|
1645
|
-
{{ text('praxis.metadataEditor.arrayFields.moveUp', 'Subir') }}
|
|
1646
|
-
</button>
|
|
1647
|
-
<button type="button" (click)="moveField(i, 1)" [disabled]="i === formArray.length - 1">
|
|
1648
|
-
{{ text('praxis.metadataEditor.arrayFields.moveDown', 'Descer') }}
|
|
1649
|
-
</button>
|
|
1650
|
-
<button type="button" (click)="duplicateField(i)">
|
|
1651
|
-
{{ text('praxis.metadataEditor.arrayFields.duplicate', 'Duplicar') }}
|
|
1652
|
-
</button>
|
|
1653
|
-
<button
|
|
1654
|
-
type="button"
|
|
1655
|
-
(click)="removeField(i)"
|
|
1656
|
-
[disabled]="isReferenced(row.get('name')?.value)"
|
|
1657
|
-
[title]="removeTitle(row.get('name')?.value)"
|
|
1614
|
+
class="array-fields-editor__empty"
|
|
1615
|
+
>
|
|
1616
|
+
{{ text('praxis.metadataEditor.arrayFields.empty', 'Nenhum subcampo local configurado.') }}
|
|
1617
|
+
</div>
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
<div class="array-fields-editor__list" [formGroup]="form">
|
|
1621
|
+
@for (row of rows; track row; let i = $index) {
|
|
1622
|
+
<div
|
|
1623
|
+
class="array-fields-editor__row"
|
|
1624
|
+
[formGroup]="row"
|
|
1658
1625
|
>
|
|
1659
|
-
|
|
1660
|
-
|
|
1626
|
+
<label>
|
|
1627
|
+
<span>{{ text('praxis.metadataEditor.arrayFields.name', 'Nome') }}</span>
|
|
1628
|
+
<input
|
|
1629
|
+
type="text"
|
|
1630
|
+
formControlName="name"
|
|
1631
|
+
(blur)="onNameBlur(i)"
|
|
1632
|
+
[attr.aria-invalid]="isNameInvalid(i) ? 'true' : null"
|
|
1633
|
+
[attr.aria-describedby]="nameErrorDescribedBy(i)"
|
|
1634
|
+
/>
|
|
1635
|
+
@if (nameErrorMessage(i); as nameError) {
|
|
1636
|
+
<span
|
|
1637
|
+
class="array-fields-editor__field-error"
|
|
1638
|
+
[id]="nameErrorId(i)"
|
|
1639
|
+
>
|
|
1640
|
+
{{ nameError }}
|
|
1641
|
+
</span>
|
|
1642
|
+
}
|
|
1643
|
+
</label>
|
|
1644
|
+
<label>
|
|
1645
|
+
<span>{{ text('praxis.metadataEditor.arrayFields.label', 'Label') }}</span>
|
|
1646
|
+
<input type="text" formControlName="label" />
|
|
1647
|
+
</label>
|
|
1648
|
+
<label>
|
|
1649
|
+
<span>{{ text('praxis.metadataEditor.arrayFields.controlType', 'Controle') }}</span>
|
|
1650
|
+
<select formControlName="controlType">
|
|
1651
|
+
@for (option of controlTypeOptions; track option) {
|
|
1652
|
+
<option [value]="option">
|
|
1653
|
+
{{ controlTypeLabel(option) }}
|
|
1654
|
+
</option>
|
|
1655
|
+
}
|
|
1656
|
+
</select>
|
|
1657
|
+
</label>
|
|
1658
|
+
<label class="array-fields-editor__check">
|
|
1659
|
+
<input type="checkbox" formControlName="required" />
|
|
1660
|
+
<span>{{ text('praxis.metadataEditor.arrayFields.required', 'Obrigat\u00f3rio') }}</span>
|
|
1661
|
+
</label>
|
|
1662
|
+
<div class="array-fields-editor__actions">
|
|
1663
|
+
<button type="button" (click)="moveField(i, -1)" [disabled]="i === 0">
|
|
1664
|
+
{{ text('praxis.metadataEditor.arrayFields.moveUp', 'Subir') }}
|
|
1665
|
+
</button>
|
|
1666
|
+
<button type="button" (click)="moveField(i, 1)" [disabled]="i === formArray.length - 1">
|
|
1667
|
+
{{ text('praxis.metadataEditor.arrayFields.moveDown', 'Descer') }}
|
|
1668
|
+
</button>
|
|
1669
|
+
<button type="button" (click)="duplicateField(i)">
|
|
1670
|
+
{{ text('praxis.metadataEditor.arrayFields.duplicate', 'Duplicar') }}
|
|
1671
|
+
</button>
|
|
1672
|
+
<button
|
|
1673
|
+
type="button"
|
|
1674
|
+
(click)="removeField(i)"
|
|
1675
|
+
[disabled]="isReferenced(row.get('name')?.value)"
|
|
1676
|
+
[title]="removeTitle(row.get('name')?.value)"
|
|
1677
|
+
>
|
|
1678
|
+
{{ text('praxis.metadataEditor.arrayFields.remove', 'Remover') }}
|
|
1679
|
+
</button>
|
|
1680
|
+
</div>
|
|
1661
1681
|
</div>
|
|
1662
|
-
|
|
1682
|
+
}
|
|
1663
1683
|
</div>
|
|
1664
1684
|
</section>
|
|
1665
|
-
|
|
1685
|
+
`, styles: [":host{display:block}.array-fields-editor{display:block;margin:10px 0 2px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface)}.array-fields-editor__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:12px}.array-fields-editor__header h3{margin:0 0 4px;font-size:1rem;line-height:1.25}.array-fields-editor__header p,.array-fields-editor__empty{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:.875rem;line-height:1.35}.array-fields-editor__primary,.array-fields-editor button{border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer;min-height:32px;padding:5px 10px}.array-fields-editor__primary{border-color:var(--md-sys-color-primary);color:var(--md-sys-color-primary);font-weight:600;white-space:nowrap}.array-fields-editor button:disabled{cursor:not-allowed;opacity:.55}.array-fields-editor__warning{margin:8px 0 12px;padding:8px 10px;border:1px solid var(--md-sys-color-error);border-radius:6px;color:var(--md-sys-color-error);background:var(--md-sys-color-error-container)}.array-fields-editor__list{display:grid;gap:10px}.array-fields-editor__row{display:grid;grid-template-columns:minmax(140px,1fr) minmax(160px,1.2fr) minmax(140px,.9fr) auto;gap:10px;align-items:end;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}.array-fields-editor label{display:grid;gap:4px;font-size:.8rem;font-weight:600}.array-fields-editor input[type=text],.array-fields-editor select{box-sizing:border-box;width:100%;min-height:34px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);padding:5px 8px}.array-fields-editor input[aria-invalid=true]{border-color:var(--md-sys-color-error)}.array-fields-editor__field-error{color:var(--md-sys-color-error);font-size:.75rem;font-weight:500;line-height:1.3}.array-fields-editor__check{display:flex!important;align-items:center;gap:6px;min-height:34px}.array-fields-editor__actions{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:6px}@media(max-width:720px){.array-fields-editor__header,.array-fields-editor__row{display:grid;grid-template-columns:1fr}.array-fields-editor__primary{width:100%}}\n"] }]
|
|
1666
1686
|
}], propDecorators: { control: [{
|
|
1667
1687
|
type: Input
|
|
1668
1688
|
}], arrayControl: [{
|
|
@@ -8274,47 +8294,50 @@ class FieldMetadataEditorComponent {
|
|
|
8274
8294
|
}
|
|
8275
8295
|
control.setErrors(Object.keys(errors).length ? errors : null);
|
|
8276
8296
|
}
|
|
8277
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8278
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
8279
|
-
|
|
8280
|
-
<
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8297
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FieldMetadataEditorComponent, deps: [{ token: ConfigRegistryService }, { token: SchemaNormalizerService }, { token: DynamicFormFactoryService }, { token: ContextValidatorRegistryService }], target: i0.ɵɵFactoryTarget.Component });
|
|
8298
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: FieldMetadataEditorComponent, isStandalone: true, selector: "praxis-field-metadata-editor", inputs: { controlType: "controlType", seed: "seed" }, outputs: { applied: "applied", cancel: "cancel" }, ngImport: i0, template: `
|
|
8299
|
+
@if (form) {
|
|
8300
|
+
<div class="p-3">
|
|
8301
|
+
<praxis-dynamic-editor-renderer
|
|
8302
|
+
[properties]="renderedProps"
|
|
8303
|
+
[form]="form"
|
|
8304
|
+
></praxis-dynamic-editor-renderer>
|
|
8305
|
+
@if (isArrayEditor) {
|
|
8306
|
+
<praxis-array-item-schema-fields-editor
|
|
8307
|
+
[control]="form.get('array.itemSchema.fields')"
|
|
8308
|
+
[arrayControl]="form.get('array')"
|
|
8309
|
+
></praxis-array-item-schema-fields-editor>
|
|
8310
|
+
}
|
|
8311
|
+
</div>
|
|
8312
|
+
}
|
|
8313
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: DynamicEditorRendererComponent, selector: "praxis-dynamic-editor-renderer", inputs: ["properties", "form"] }, { kind: "component", type: ArrayItemSchemaFieldsEditorComponent, selector: "praxis-array-item-schema-fields-editor", inputs: ["control", "arrayControl"] }] });
|
|
8292
8314
|
}
|
|
8293
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8315
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FieldMetadataEditorComponent, decorators: [{
|
|
8294
8316
|
type: Component,
|
|
8295
8317
|
args: [{
|
|
8296
8318
|
selector: 'praxis-field-metadata-editor',
|
|
8297
8319
|
standalone: true,
|
|
8298
8320
|
imports: [
|
|
8299
|
-
CommonModule,
|
|
8300
8321
|
ReactiveFormsModule,
|
|
8301
8322
|
DynamicEditorRendererComponent,
|
|
8302
|
-
ArrayItemSchemaFieldsEditorComponent
|
|
8323
|
+
ArrayItemSchemaFieldsEditorComponent
|
|
8303
8324
|
],
|
|
8304
8325
|
template: `
|
|
8305
|
-
|
|
8306
|
-
<
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8326
|
+
@if (form) {
|
|
8327
|
+
<div class="p-3">
|
|
8328
|
+
<praxis-dynamic-editor-renderer
|
|
8329
|
+
[properties]="renderedProps"
|
|
8330
|
+
[form]="form"
|
|
8331
|
+
></praxis-dynamic-editor-renderer>
|
|
8332
|
+
@if (isArrayEditor) {
|
|
8333
|
+
<praxis-array-item-schema-fields-editor
|
|
8334
|
+
[control]="form.get('array.itemSchema.fields')"
|
|
8335
|
+
[arrayControl]="form.get('array')"
|
|
8336
|
+
></praxis-array-item-schema-fields-editor>
|
|
8337
|
+
}
|
|
8338
|
+
</div>
|
|
8339
|
+
}
|
|
8340
|
+
`,
|
|
8318
8341
|
}]
|
|
8319
8342
|
}], ctorParameters: () => [{ type: ConfigRegistryService }, { type: SchemaNormalizerService }, { type: DynamicFormFactoryService }, { type: ContextValidatorRegistryService }], propDecorators: { controlType: [{
|
|
8320
8343
|
type: Input
|
|
@@ -8381,10 +8404,10 @@ class CascadeRulesService {
|
|
|
8381
8404
|
dependencyValuePath: rule.dependencyValuePath || inferredValueKey || 'id',
|
|
8382
8405
|
};
|
|
8383
8406
|
}
|
|
8384
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8385
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
8407
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CascadeRulesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
8408
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CascadeRulesService, providedIn: 'root' });
|
|
8386
8409
|
}
|
|
8387
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8410
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CascadeRulesService, decorators: [{
|
|
8388
8411
|
type: Injectable,
|
|
8389
8412
|
args: [{ providedIn: 'root' }]
|
|
8390
8413
|
}] });
|
|
@@ -8398,10 +8421,10 @@ class CascadeManagerTabComponent {
|
|
|
8398
8421
|
searchTerm = '';
|
|
8399
8422
|
searchTimer = null;
|
|
8400
8423
|
searchValue = '';
|
|
8401
|
-
rules = signal(new Map(), ...(ngDevMode ? [{ debugName: "rules" }] : []));
|
|
8402
|
-
selectedFieldSig = signal(null, ...(ngDevMode ? [{ debugName: "selectedFieldSig" }] : []));
|
|
8424
|
+
rules = signal(new Map(), ...(ngDevMode ? [{ debugName: "rules" }] : /* istanbul ignore next */ []));
|
|
8425
|
+
selectedFieldSig = signal(null, ...(ngDevMode ? [{ debugName: "selectedFieldSig" }] : /* istanbul ignore next */ []));
|
|
8403
8426
|
// Inline editor state (MVP)
|
|
8404
|
-
editing = signal(false, ...(ngDevMode ? [{ debugName: "editing" }] : []));
|
|
8427
|
+
editing = signal(false, ...(ngDevMode ? [{ debugName: "editing" }] : /* istanbul ignore next */ []));
|
|
8405
8428
|
editDepList = [];
|
|
8406
8429
|
editEnable = true;
|
|
8407
8430
|
editReset = false;
|
|
@@ -8753,8 +8776,8 @@ class CascadeManagerTabComponent {
|
|
|
8753
8776
|
}
|
|
8754
8777
|
return [...new Set(suggestions)];
|
|
8755
8778
|
}
|
|
8756
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8757
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
8779
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CascadeManagerTabComponent, deps: [{ token: CascadeRulesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
8780
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: CascadeManagerTabComponent, isStandalone: true, selector: "praxis-cascade-manager-tab", inputs: { fields: "fields", connections: "connections" }, outputs: { apply: "apply", cancel: "cancel" }, usesOnChanges: true, ngImport: i0, template: `
|
|
8758
8781
|
<div class="cm-root">
|
|
8759
8782
|
<!-- Left: Fields list -->
|
|
8760
8783
|
<div class="cm-left">
|
|
@@ -8762,276 +8785,301 @@ class CascadeManagerTabComponent {
|
|
|
8762
8785
|
<mat-label>Buscar campos</mat-label>
|
|
8763
8786
|
<input matInput [ngModel]="searchTerm" (ngModelChange)="onSearchChange($event)">
|
|
8764
8787
|
</mat-form-field>
|
|
8765
|
-
|
|
8788
|
+
@if (fields.length <= 50) {
|
|
8766
8789
|
<div>
|
|
8767
|
-
|
|
8768
|
-
<div>
|
|
8769
|
-
<div>
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
8790
|
+
@for (f of filteredFields(); track f) {
|
|
8791
|
+
<div (click)="selectField(f.name)" class="field-item" [class.selected]="f.name===selectedField()" tabindex="0" (keydown)="onFieldKeydown($event, f.name)">
|
|
8792
|
+
<div>
|
|
8793
|
+
<div>{{ labelFor(f.name) }}</div>
|
|
8794
|
+
<small style="opacity:.7">{{ f.name }}</small>
|
|
8795
|
+
</div>
|
|
8796
|
+
@if (hasRule(f.name)) {
|
|
8797
|
+
<div class="rule-badges">
|
|
8798
|
+
@if (isCascadeEnabled(f.name)) {
|
|
8799
|
+
<span class="rule-badge b-active">Ativo</span>
|
|
8800
|
+
}
|
|
8801
|
+
@if (loadOnChange(f.name)==='manual') {
|
|
8802
|
+
<span class="rule-badge b-manual">Manual</span>
|
|
8803
|
+
}
|
|
8804
|
+
@if (loadOnChange(f.name)==='immediate') {
|
|
8805
|
+
<span class="rule-badge b-immediate">Immediate</span>
|
|
8806
|
+
}
|
|
8807
|
+
</div>
|
|
8808
|
+
}
|
|
8776
8809
|
</div>
|
|
8777
|
-
|
|
8810
|
+
}
|
|
8778
8811
|
</div>
|
|
8779
|
-
|
|
8780
|
-
<ng-template #vscroll>
|
|
8812
|
+
} @else {
|
|
8781
8813
|
<cdk-virtual-scroll-viewport itemSize="44" style="height: calc(100vh - 240px)">
|
|
8782
8814
|
<div *cdkVirtualFor="let f of filteredFields()" (click)="selectField(f.name)" class="field-item" [class.selected]="f.name===selectedField()" tabindex="0" (keydown)="onFieldKeydown($event, f.name)">
|
|
8783
8815
|
<div>
|
|
8784
8816
|
<div>{{ labelFor(f.name) }}</div>
|
|
8785
8817
|
<small style="opacity:.7">{{ f.name }}</small>
|
|
8786
8818
|
</div>
|
|
8787
|
-
|
|
8788
|
-
<
|
|
8789
|
-
|
|
8790
|
-
|
|
8791
|
-
|
|
8819
|
+
@if (hasRule(f.name)) {
|
|
8820
|
+
<div class="rule-badges">
|
|
8821
|
+
@if (isCascadeEnabled(f.name)) {
|
|
8822
|
+
<span class="rule-badge b-active">Ativo</span>
|
|
8823
|
+
}
|
|
8824
|
+
@if (loadOnChange(f.name)==='manual') {
|
|
8825
|
+
<span class="rule-badge b-manual">Manual</span>
|
|
8826
|
+
}
|
|
8827
|
+
@if (loadOnChange(f.name)==='immediate') {
|
|
8828
|
+
<span class="rule-badge b-immediate">Immediate</span>
|
|
8829
|
+
}
|
|
8830
|
+
</div>
|
|
8831
|
+
}
|
|
8792
8832
|
</div>
|
|
8793
8833
|
</cdk-virtual-scroll-viewport>
|
|
8794
|
-
|
|
8834
|
+
}
|
|
8795
8835
|
</div>
|
|
8796
|
-
|
|
8836
|
+
|
|
8797
8837
|
<!-- Right: Rules for selected field -->
|
|
8798
|
-
|
|
8799
|
-
<div class="cm-
|
|
8800
|
-
<div>
|
|
8801
|
-
<h3 style="margin:0">{{ labelFor(sel) }}</h3>
|
|
8802
|
-
<div style="opacity:.7">{{ sel }}</div>
|
|
8803
|
-
</div>
|
|
8804
|
-
<div>
|
|
8805
|
-
<button mat-stroked-button color="primary" (click)="exportRules()" style="margin-right:8px">Exportar</button>
|
|
8806
|
-
<button mat-stroked-button (click)="toggleImport()" style="margin-right:8px">Importar</button>
|
|
8807
|
-
<button mat-flat-button color="primary" [matMenuTriggerFor]="addMenu" [disabled]="editing()">Adicionar</button>
|
|
8808
|
-
<mat-menu #addMenu="matMenu">
|
|
8809
|
-
<button mat-menu-item (click)="startEdit(sel)"><mat-icon [praxisIcon]="'add'"></mat-icon><span>Em branco</span></button>
|
|
8810
|
-
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota → Destino (id)</span></button>
|
|
8811
|
-
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino-propriedade')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota + Destino → Propriedade (ids)</span></button>
|
|
8812
|
-
</mat-menu>
|
|
8813
|
-
</div>
|
|
8814
|
-
</div>
|
|
8815
|
-
|
|
8816
|
-
<!-- Conflict banner (connections) -->
|
|
8817
|
-
<div class="banner" *ngIf="hasConflict(sel)">
|
|
8818
|
-
<mat-icon [praxisIcon]="'link_off'"></mat-icon>
|
|
8819
|
-
<div>
|
|
8820
|
-
Connections atualizam este campo (filterCriteria). Considere desativar a cascata nativa ou usar ‘manual’.
|
|
8821
|
-
</div>
|
|
8822
|
-
<span class="spacer"></span>
|
|
8823
|
-
<button mat-stroked-button color="primary" (click)="quickSet(sel,'disable')">Desativar</button>
|
|
8824
|
-
<button mat-stroked-button color="accent" (click)="quickSet(sel,'manual')">Definir manual</button>
|
|
8825
|
-
</div>
|
|
8826
|
-
|
|
8827
|
-
<div *ngIf="importMode" class="import-panel">
|
|
8828
|
-
<div style="display:flex; gap:8px; align-items:center; margin-bottom:8px"><mat-icon [praxisIcon]="'upload'"></mat-icon><strong>Importar regras (JSON)</strong></div>
|
|
8829
|
-
<textarea matInput rows="6" class="full" [(ngModel)]="importJson" placeholder='{ "campo": { "dependencyFields": ["dep"], ... } }'></textarea>
|
|
8830
|
-
<div style="display:flex; gap:8px; justify-content:flex-end; padding-top:8px">
|
|
8831
|
-
<button mat-stroked-button (click)="toggleImport()">Cancelar</button>
|
|
8832
|
-
<button mat-flat-button color="primary" (click)="applyImport()">Aplicar</button>
|
|
8833
|
-
</div>
|
|
8834
|
-
</div>
|
|
8835
|
-
|
|
8836
|
-
<div *ngIf="!ruleFor(sel)">
|
|
8837
|
-
<div class="rules-empty">Nenhuma cascata configurada. Clique em “Adicionar” para montar a dependência.</div>
|
|
8838
|
-
</div>
|
|
8839
|
-
<div *ngIf="ruleFor(sel) as rule">
|
|
8840
|
-
<div class="rule-row">
|
|
8838
|
+
@if (selectedField(); as sel) {
|
|
8839
|
+
<div class="cm-right">
|
|
8840
|
+
<div class="cm-header">
|
|
8841
8841
|
<div>
|
|
8842
|
-
<
|
|
8843
|
-
<div style="opacity:.7">
|
|
8842
|
+
<h3 style="margin:0">{{ labelFor(sel) }}</h3>
|
|
8843
|
+
<div style="opacity:.7">{{ sel }}</div>
|
|
8844
8844
|
</div>
|
|
8845
|
-
<div
|
|
8846
|
-
<button mat-
|
|
8847
|
-
<button mat-
|
|
8848
|
-
<button mat-
|
|
8845
|
+
<div>
|
|
8846
|
+
<button mat-stroked-button color="primary" (click)="exportRules()" style="margin-right:8px">Exportar</button>
|
|
8847
|
+
<button mat-stroked-button (click)="toggleImport()" style="margin-right:8px">Importar</button>
|
|
8848
|
+
<button mat-flat-button color="primary" [matMenuTriggerFor]="addMenu" [disabled]="editing()">Adicionar</button>
|
|
8849
|
+
<mat-menu #addMenu="matMenu">
|
|
8850
|
+
<button mat-menu-item (click)="startEdit(sel)"><mat-icon [praxisIcon]="'add'"></mat-icon><span>Em branco</span></button>
|
|
8851
|
+
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota → Destino (id)</span></button>
|
|
8852
|
+
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino-propriedade')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota + Destino → Propriedade (ids)</span></button>
|
|
8853
|
+
</mat-menu>
|
|
8849
8854
|
</div>
|
|
8850
8855
|
</div>
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8856
|
+
<!-- Conflict banner (connections) -->
|
|
8857
|
+
@if (hasConflict(sel)) {
|
|
8858
|
+
<div class="banner">
|
|
8859
|
+
<mat-icon [praxisIcon]="'link_off'"></mat-icon>
|
|
8860
|
+
<div>
|
|
8861
|
+
Connections atualizam este campo (filterCriteria). Considere desativar a cascata nativa ou usar ‘manual’.
|
|
8862
|
+
</div>
|
|
8863
|
+
<span class="spacer"></span>
|
|
8864
|
+
<button mat-stroked-button color="primary" (click)="quickSet(sel,'disable')">Desativar</button>
|
|
8865
|
+
<button mat-stroked-button color="accent" (click)="quickSet(sel,'manual')">Definir manual</button>
|
|
8866
|
+
</div>
|
|
8867
|
+
}
|
|
8868
|
+
@if (importMode) {
|
|
8869
|
+
<div class="import-panel">
|
|
8870
|
+
<div style="display:flex; gap:8px; align-items:center; margin-bottom:8px"><mat-icon [praxisIcon]="'upload'"></mat-icon><strong>Importar regras (JSON)</strong></div>
|
|
8871
|
+
<textarea matInput rows="6" class="full" [(ngModel)]="importJson" placeholder='{ "campo": { "dependencyFields": ["dep"], ... } }'></textarea>
|
|
8872
|
+
<div style="display:flex; gap:8px; justify-content:flex-end; padding-top:8px">
|
|
8873
|
+
<button mat-stroked-button (click)="toggleImport()">Cancelar</button>
|
|
8874
|
+
<button mat-flat-button color="primary" (click)="applyImport()">Aplicar</button>
|
|
8875
|
+
</div>
|
|
8876
|
+
</div>
|
|
8877
|
+
}
|
|
8878
|
+
@if (!ruleFor(sel)) {
|
|
8857
8879
|
<div>
|
|
8858
|
-
<div>
|
|
8859
|
-
<small style="color: var(--md-sys-color-on-surface-variant);">Defina dependentes, quando recarregar e como mapear filtros</small>
|
|
8880
|
+
<div class="rules-empty">Nenhuma cascata configurada. Clique em “Adicionar” para montar a dependência.</div>
|
|
8860
8881
|
</div>
|
|
8861
|
-
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
8869
|
-
|
|
8882
|
+
}
|
|
8883
|
+
@if (ruleFor(sel); as rule) {
|
|
8884
|
+
<div>
|
|
8885
|
+
<div class="rule-row">
|
|
8886
|
+
<div>
|
|
8887
|
+
<div><strong>Dependentes:</strong> {{ rule.dependencyFields.join(', ') || '—' }}</div>
|
|
8888
|
+
<div style="opacity:.7">Load on change: {{ rule.dependencyLoadOnChange || 'respectLoadOn' }} | Merge: {{ rule.dependencyMergeStrategy || 'merge' }}</div>
|
|
8889
|
+
</div>
|
|
8890
|
+
<div class="rule-actions">
|
|
8891
|
+
<button mat-icon-button matTooltip="Editar" (click)="startEdit(sel)"><mat-icon [praxisIcon]="'edit'"></mat-icon></button>
|
|
8892
|
+
<button mat-icon-button matTooltip="Duplicar" disabled><mat-icon [praxisIcon]="'content_copy'"></mat-icon></button>
|
|
8893
|
+
<button mat-icon-button matTooltip="Remover" (click)="remove(sel)"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
8894
|
+
</div>
|
|
8895
|
+
</div>
|
|
8896
|
+
</div>
|
|
8897
|
+
}
|
|
8898
|
+
<!-- Editor com seções (sem acordeão duplo) -->
|
|
8899
|
+
<div class="panel-surface">
|
|
8900
|
+
<div class="panel-header" style="padding: 12px 16px; border-bottom: 1px solid var(--md-sys-color-outline-variant);">
|
|
8901
|
+
<mat-icon [praxisIcon]="'rule'"></mat-icon>
|
|
8902
|
+
<div>
|
|
8903
|
+
<div>Cascata do campo</div>
|
|
8904
|
+
<small style="color: var(--md-sys-color-on-surface-variant);">Defina dependentes, quando recarregar e como mapear filtros</small>
|
|
8905
|
+
</div>
|
|
8906
|
+
</div>
|
|
8907
|
+
<div class="panel-stack">
|
|
8908
|
+
<!-- Básico -->
|
|
8909
|
+
<mat-expansion-panel [expanded]="true" class="stack-panel">
|
|
8910
|
+
<mat-expansion-panel-header>
|
|
8911
|
+
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'tune'"></mat-icon> Básico</mat-panel-title>
|
|
8912
|
+
</mat-expansion-panel-header>
|
|
8913
|
+
<div class="form-grid">
|
|
8914
|
+
<div class="form-row">
|
|
8915
|
+
<mat-form-field appearance="outline" class="full">
|
|
8916
|
+
<mat-label>Campos dependentes</mat-label>
|
|
8917
|
+
<mat-select multiple [(ngModel)]="editDepList" (ngModelChange)="onDepListChange()">
|
|
8918
|
+
@for (f of availableDependencyFields(); track f) {
|
|
8919
|
+
<mat-option [value]="f.name">
|
|
8920
|
+
{{ labelFor(f.name) }} ({{ f.name }})
|
|
8921
|
+
</mat-option>
|
|
8922
|
+
}
|
|
8923
|
+
</mat-select>
|
|
8924
|
+
<button
|
|
8925
|
+
mat-icon-button
|
|
8926
|
+
matSuffix
|
|
8927
|
+
class="help-icon-button"
|
|
8928
|
+
type="button"
|
|
8929
|
+
[matTooltip]="'Selecione os campos que controlam este valor'"
|
|
8930
|
+
matTooltipPosition="above"
|
|
8931
|
+
>
|
|
8932
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
8933
|
+
</button>
|
|
8934
|
+
</mat-form-field>
|
|
8935
|
+
</div>
|
|
8936
|
+
<div class="form-row">
|
|
8937
|
+
<mat-checkbox [(ngModel)]="editEnable">Ativar cascata nativa</mat-checkbox>
|
|
8938
|
+
<mat-checkbox [(ngModel)]="editReset">Resetar ao mudar</mat-checkbox>
|
|
8939
|
+
</div>
|
|
8940
|
+
</div>
|
|
8941
|
+
</mat-expansion-panel>
|
|
8942
|
+
<!-- Execução -->
|
|
8943
|
+
<mat-expansion-panel class="stack-panel">
|
|
8944
|
+
<mat-expansion-panel-header>
|
|
8945
|
+
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'schedule'"></mat-icon> Execução</mat-panel-title>
|
|
8946
|
+
</mat-expansion-panel-header>
|
|
8870
8947
|
<div class="form-row">
|
|
8871
|
-
|
|
8872
|
-
|
|
8873
|
-
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
|
|
8877
|
-
|
|
8948
|
+
<mat-form-field appearance="outline">
|
|
8949
|
+
<mat-label>Carregar ao mudar</mat-label>
|
|
8950
|
+
<mat-select [(ngModel)]="editLoadOn">
|
|
8951
|
+
<mat-option value="respectLoadOn">Respeitar loadOn</mat-option>
|
|
8952
|
+
<mat-option value="immediate">Imediato</mat-option>
|
|
8953
|
+
<mat-option value="manual">Manual</mat-option>
|
|
8954
|
+
</mat-select>
|
|
8955
|
+
</mat-form-field>
|
|
8956
|
+
<mat-form-field appearance="outline">
|
|
8957
|
+
<mat-label>Merge de filtros</mat-label>
|
|
8958
|
+
<mat-select [(ngModel)]="editMerge">
|
|
8959
|
+
<mat-option value="merge">merge (padrão)</mat-option>
|
|
8960
|
+
<mat-option value="replace">replace</mat-option>
|
|
8961
|
+
</mat-select>
|
|
8962
|
+
</mat-form-field>
|
|
8963
|
+
<mat-form-field appearance="outline">
|
|
8964
|
+
<mat-label>Atraso (ms)</mat-label>
|
|
8965
|
+
<input matInput type="number" [(ngModel)]="editDebounce">
|
|
8966
|
+
</mat-form-field>
|
|
8967
|
+
</div>
|
|
8968
|
+
</mat-expansion-panel>
|
|
8969
|
+
<!-- Extração de valor -->
|
|
8970
|
+
<mat-expansion-panel class="stack-panel">
|
|
8971
|
+
<mat-expansion-panel-header>
|
|
8972
|
+
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'call_split'"></mat-icon> Extração de valor</mat-panel-title>
|
|
8973
|
+
</mat-expansion-panel-header>
|
|
8974
|
+
<div class="form-row">
|
|
8975
|
+
<mat-form-field appearance="outline" class="full">
|
|
8976
|
+
<mat-label>ValuePath padrão</mat-label>
|
|
8977
|
+
<input matInput [(ngModel)]="editValuePath" placeholder="id">
|
|
8878
8978
|
<button
|
|
8879
8979
|
mat-icon-button
|
|
8880
8980
|
matSuffix
|
|
8881
8981
|
class="help-icon-button"
|
|
8882
8982
|
type="button"
|
|
8883
|
-
[matTooltip]="'
|
|
8983
|
+
[matTooltip]="'Preenchido automaticamente a partir de optionValueKey() ou \\'id\\''"
|
|
8884
8984
|
matTooltipPosition="above"
|
|
8885
|
-
|
|
8985
|
+
>
|
|
8886
8986
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
8887
8987
|
</button>
|
|
8888
|
-
|
|
8889
|
-
</div>
|
|
8890
|
-
<div class="form-row">
|
|
8891
|
-
<mat-checkbox [(ngModel)]="editEnable">Ativar cascata nativa</mat-checkbox>
|
|
8892
|
-
<mat-checkbox [(ngModel)]="editReset">Resetar ao mudar</mat-checkbox>
|
|
8988
|
+
</mat-form-field>
|
|
8893
8989
|
</div>
|
|
8894
|
-
</
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
8903
|
-
|
|
8904
|
-
|
|
8905
|
-
|
|
8906
|
-
|
|
8907
|
-
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
>
|
|
8979
|
-
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
8980
|
-
</button>
|
|
8981
|
-
</mat-form-field>
|
|
8982
|
-
</td>
|
|
8983
|
-
<td>
|
|
8984
|
-
<mat-form-field appearance="outline" class="full">
|
|
8985
|
-
<mat-label>ValuePath</mat-label>
|
|
8986
|
-
<input matInput [(ngModel)]="row.valuePath" [matAutocomplete]="autoValue" [placeholder]="editValuePath||'id'">
|
|
8987
|
-
<mat-autocomplete #autoValue="matAutocomplete">
|
|
8988
|
-
<mat-option *ngFor="let opt of getValuePathSuggestions(row.dep)" [value]="opt">{{ opt }}</mat-option>
|
|
8989
|
-
</mat-autocomplete>
|
|
8990
|
-
<button
|
|
8991
|
-
mat-icon-button
|
|
8992
|
-
matSuffix
|
|
8993
|
-
class="help-icon-button"
|
|
8994
|
-
type="button"
|
|
8995
|
-
[matTooltip]="'Opcional'"
|
|
8996
|
-
matTooltipPosition="above"
|
|
8997
|
-
>
|
|
8998
|
-
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
8999
|
-
</button>
|
|
9000
|
-
</mat-form-field>
|
|
9001
|
-
</td>
|
|
9002
|
-
</tr>
|
|
9003
|
-
</tbody>
|
|
9004
|
-
</table>
|
|
9005
|
-
<ng-template #noMap>
|
|
9006
|
-
<div class="rules-empty">Defina dependentes para sugerir o mapeamento.</div>
|
|
9007
|
-
</ng-template>
|
|
9008
|
-
</mat-expansion-panel>
|
|
9009
|
-
|
|
9010
|
-
<!-- Preview -->
|
|
9011
|
-
<mat-expansion-panel class="stack-panel">
|
|
9012
|
-
<mat-expansion-panel-header>
|
|
9013
|
-
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'visibility'"></mat-icon> Preview</mat-panel-title>
|
|
9014
|
-
</mat-expansion-panel-header>
|
|
9015
|
-
<pre class="preview-box">{{ buildPreview() }}</pre>
|
|
9016
|
-
<div style="display:flex; justify-content:flex-end; padding-top:6px">
|
|
9017
|
-
<button mat-stroked-button (click)="copyPreview()">Copiar</button>
|
|
9018
|
-
</div>
|
|
9019
|
-
</mat-expansion-panel>
|
|
9020
|
-
</div>
|
|
9021
|
-
|
|
9022
|
-
<div style="display:flex; gap:8px; justify-content:flex-end; padding:8px 12px;">
|
|
9023
|
-
<button mat-stroked-button (click)="cancelEdit()">Cancelar</button>
|
|
9024
|
-
<button mat-flat-button color="primary" (click)="saveEdit(sel)">Salvar</button>
|
|
8990
|
+
</mat-expansion-panel>
|
|
8991
|
+
<!-- Mapeamento de filtros (tabela) -->
|
|
8992
|
+
<mat-expansion-panel class="stack-panel">
|
|
8993
|
+
<mat-expansion-panel-header>
|
|
8994
|
+
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'filter_alt'"></mat-icon> Mapeamento de filtros</mat-panel-title>
|
|
8995
|
+
</mat-expansion-panel-header>
|
|
8996
|
+
@if (editMapRows.length) {
|
|
8997
|
+
<table class="map-table">
|
|
8998
|
+
<thead>
|
|
8999
|
+
<tr>
|
|
9000
|
+
<th>Dependente</th>
|
|
9001
|
+
<th>Chave (dot‑path)</th>
|
|
9002
|
+
<th>ValuePath (opcional)</th>
|
|
9003
|
+
</tr>
|
|
9004
|
+
</thead>
|
|
9005
|
+
<tbody>
|
|
9006
|
+
@for (row of editMapRows; track row; let i = $index) {
|
|
9007
|
+
<tr>
|
|
9008
|
+
<td>{{ row.dep }}</td>
|
|
9009
|
+
<td>
|
|
9010
|
+
<mat-form-field appearance="outline" class="full">
|
|
9011
|
+
<mat-label>Chave</mat-label>
|
|
9012
|
+
<input matInput [(ngModel)]="row.key" [matAutocomplete]="autoKey" [placeholder]="row.dep">
|
|
9013
|
+
<mat-autocomplete #autoKey="matAutocomplete">
|
|
9014
|
+
@for (opt of getKeySuggestions(row.dep); track opt) {
|
|
9015
|
+
<mat-option [value]="opt">{{ opt }}</mat-option>
|
|
9016
|
+
}
|
|
9017
|
+
</mat-autocomplete>
|
|
9018
|
+
<button
|
|
9019
|
+
mat-icon-button
|
|
9020
|
+
matSuffix
|
|
9021
|
+
class="help-icon-button"
|
|
9022
|
+
type="button"
|
|
9023
|
+
[matTooltip]="'Use dot-notation (e.g. ' + row.dep + '.id) for nested objects'"
|
|
9024
|
+
matTooltipPosition="above"
|
|
9025
|
+
>
|
|
9026
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
9027
|
+
</button>
|
|
9028
|
+
</mat-form-field>
|
|
9029
|
+
</td>
|
|
9030
|
+
<td>
|
|
9031
|
+
<mat-form-field appearance="outline" class="full">
|
|
9032
|
+
<mat-label>ValuePath</mat-label>
|
|
9033
|
+
<input matInput [(ngModel)]="row.valuePath" [matAutocomplete]="autoValue" [placeholder]="editValuePath||'id'">
|
|
9034
|
+
<mat-autocomplete #autoValue="matAutocomplete">
|
|
9035
|
+
@for (opt of getValuePathSuggestions(row.dep); track opt) {
|
|
9036
|
+
<mat-option [value]="opt">{{ opt }}</mat-option>
|
|
9037
|
+
}
|
|
9038
|
+
</mat-autocomplete>
|
|
9039
|
+
<button
|
|
9040
|
+
mat-icon-button
|
|
9041
|
+
matSuffix
|
|
9042
|
+
class="help-icon-button"
|
|
9043
|
+
type="button"
|
|
9044
|
+
[matTooltip]="'Opcional'"
|
|
9045
|
+
matTooltipPosition="above"
|
|
9046
|
+
>
|
|
9047
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
9048
|
+
</button>
|
|
9049
|
+
</mat-form-field>
|
|
9050
|
+
</td>
|
|
9051
|
+
</tr>
|
|
9052
|
+
}
|
|
9053
|
+
</tbody>
|
|
9054
|
+
</table>
|
|
9055
|
+
} @else {
|
|
9056
|
+
<div class="rules-empty">Defina dependentes para sugerir o mapeamento.</div>
|
|
9057
|
+
}
|
|
9058
|
+
</mat-expansion-panel>
|
|
9059
|
+
<!-- Preview -->
|
|
9060
|
+
<mat-expansion-panel class="stack-panel">
|
|
9061
|
+
<mat-expansion-panel-header>
|
|
9062
|
+
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'visibility'"></mat-icon> Preview</mat-panel-title>
|
|
9063
|
+
</mat-expansion-panel-header>
|
|
9064
|
+
<pre class="preview-box">{{ buildPreview() }}</pre>
|
|
9065
|
+
<div style="display:flex; justify-content:flex-end; padding-top:6px">
|
|
9066
|
+
<button mat-stroked-button (click)="copyPreview()">Copiar</button>
|
|
9067
|
+
</div>
|
|
9068
|
+
</mat-expansion-panel>
|
|
9069
|
+
</div>
|
|
9070
|
+
<div style="display:flex; gap:8px; justify-content:flex-end; padding:8px 12px;">
|
|
9071
|
+
<button mat-stroked-button (click)="cancelEdit()">Cancelar</button>
|
|
9072
|
+
<button mat-flat-button color="primary" (click)="saveEdit(sel)">Salvar</button>
|
|
9073
|
+
</div>
|
|
9025
9074
|
</div>
|
|
9026
9075
|
</div>
|
|
9027
|
-
|
|
9076
|
+
}
|
|
9028
9077
|
</div>
|
|
9029
|
-
`, isInline: true, styles: [":host{display:block}.cm-root{display:grid;grid-template-columns:320px 1fr;gap:16px;min-height:420px}.cm-left{border-right:1px solid var(--md-sys-color-outline-variant);padding-right:8px}.cm-search{width:100%;margin-bottom:8px}.cm-right{padding-left:8px}.field-item{display:flex;align-items:center;justify-content:space-between;padding:8px 6px;cursor:pointer;border-radius:10px;transition:background .12s ease,border .12s ease;border:1px solid transparent}.field-item:hover{background:var(--md-sys-color-surface-container-high)}.field-item.selected{background:var(--md-sys-color-surface-container-highest);border-color:var(--md-sys-color-outline-variant)}.rule-badges{display:inline-flex;gap:6px}.rule-badge{font-size:11px;padding:2px 8px;border-radius:999px;font-weight:600}.b-active{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.b-manual{background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant)}.b-immediate{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.b-conflict{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.cm-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.rules-empty{opacity:.8;font-style:italic;padding:8px 0;color:var(--md-sys-color-on-surface-variant)}.rule-row{display:grid;grid-template-columns:1fr auto;align-items:center;padding:10px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant)}.rule-actions button{margin-left:4px}.banner{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container);padding:10px 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;margin-bottom:10px;display:flex;gap:8px;align-items:center}.import-panel{background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:10px;margin-bottom:10px}.full{width:100%}.form-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.form-grid{display:grid;gap:12px;padding:8px 0}.map-table{width:100%;border-collapse:collapse}.map-table th,.map-table td{padding:8px;border-bottom:1px dashed var(--md-sys-color-outline-variant)}.kbd{font-family:monospace;background:var(--md-sys-color-surface-container-highest);padding:0 6px;border-radius:4px;color:var(--md-sys-color-on-surface-variant)}.panel-surface{background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;box-shadow:var(--md-sys-elevation-level1, none);margin-bottom:12px}.panel-stack{display:grid;gap:12px;margin:12px 0}.stack-panel{background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;box-shadow:var(--md-sys-elevation-level1, none)}.stack-panel .mat-expansion-panel-content{padding:0 16px 12px}.panel-header{display:flex;align-items:center;gap:8px}.preview-box{background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:8px;color:var(--md-sys-color-on-surface)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5$1.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: "component", type: i5$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i7.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i8$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i8$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i5.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i5.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i5.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i11.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i11.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i11.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i12.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i12.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i13.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i13.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i13.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
|
|
9078
|
+
`, isInline: true, styles: [":host{display:block}.cm-root{display:grid;grid-template-columns:320px 1fr;gap:16px;min-height:420px}.cm-left{border-right:1px solid var(--md-sys-color-outline-variant);padding-right:8px}.cm-search{width:100%;margin-bottom:8px}.cm-right{padding-left:8px}.field-item{display:flex;align-items:center;justify-content:space-between;padding:8px 6px;cursor:pointer;border-radius:10px;transition:background .12s ease,border .12s ease;border:1px solid transparent}.field-item:hover{background:var(--md-sys-color-surface-container-high)}.field-item.selected{background:var(--md-sys-color-surface-container-highest);border-color:var(--md-sys-color-outline-variant)}.rule-badges{display:inline-flex;gap:6px}.rule-badge{font-size:11px;padding:2px 8px;border-radius:999px;font-weight:600}.b-active{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.b-manual{background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant)}.b-immediate{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.b-conflict{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.cm-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.rules-empty{opacity:.8;font-style:italic;padding:8px 0;color:var(--md-sys-color-on-surface-variant)}.rule-row{display:grid;grid-template-columns:1fr auto;align-items:center;padding:10px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant)}.rule-actions button{margin-left:4px}.banner{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container);padding:10px 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;margin-bottom:10px;display:flex;gap:8px;align-items:center}.import-panel{background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:10px;margin-bottom:10px}.full{width:100%}.form-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.form-grid{display:grid;gap:12px;padding:8px 0}.map-table{width:100%;border-collapse:collapse}.map-table th,.map-table td{padding:8px;border-bottom:1px dashed var(--md-sys-color-outline-variant)}.kbd{font-family:monospace;background:var(--md-sys-color-surface-container-highest);padding:0 6px;border-radius:4px;color:var(--md-sys-color-on-surface-variant)}.panel-surface{background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;box-shadow:var(--md-sys-elevation-level1, none);margin-bottom:12px}.panel-stack{display:grid;gap:12px;margin:12px 0}.stack-panel{background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;box-shadow:var(--md-sys-elevation-level1, none)}.stack-panel .mat-expansion-panel-content{padding:0 16px 12px}.panel-header{display:flex;align-items:center;gap:8px}.preview-box{background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:8px;color:var(--md-sys-color-on-surface)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: "component", type: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i7.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i8$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i5.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i5.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i5.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i10.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i10.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i10.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i11.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i11.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i12.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i12.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i12.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
|
|
9030
9079
|
}
|
|
9031
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
9080
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CascadeManagerTabComponent, decorators: [{
|
|
9032
9081
|
type: Component,
|
|
9033
9082
|
args: [{ selector: 'praxis-cascade-manager-tab', standalone: true, imports: [
|
|
9034
|
-
CommonModule,
|
|
9035
9083
|
ReactiveFormsModule,
|
|
9036
9084
|
FormsModule,
|
|
9037
9085
|
MatIconModule,
|
|
@@ -9047,7 +9095,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
9047
9095
|
MatMenuModule,
|
|
9048
9096
|
MatAutocompleteModule,
|
|
9049
9097
|
ScrollingModule,
|
|
9050
|
-
PraxisIconDirective
|
|
9098
|
+
PraxisIconDirective
|
|
9051
9099
|
], template: `
|
|
9052
9100
|
<div class="cm-root">
|
|
9053
9101
|
<!-- Left: Fields list -->
|
|
@@ -9056,271 +9104,297 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
9056
9104
|
<mat-label>Buscar campos</mat-label>
|
|
9057
9105
|
<input matInput [ngModel]="searchTerm" (ngModelChange)="onSearchChange($event)">
|
|
9058
9106
|
</mat-form-field>
|
|
9059
|
-
|
|
9107
|
+
@if (fields.length <= 50) {
|
|
9060
9108
|
<div>
|
|
9061
|
-
|
|
9062
|
-
<div>
|
|
9063
|
-
<div>
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9109
|
+
@for (f of filteredFields(); track f) {
|
|
9110
|
+
<div (click)="selectField(f.name)" class="field-item" [class.selected]="f.name===selectedField()" tabindex="0" (keydown)="onFieldKeydown($event, f.name)">
|
|
9111
|
+
<div>
|
|
9112
|
+
<div>{{ labelFor(f.name) }}</div>
|
|
9113
|
+
<small style="opacity:.7">{{ f.name }}</small>
|
|
9114
|
+
</div>
|
|
9115
|
+
@if (hasRule(f.name)) {
|
|
9116
|
+
<div class="rule-badges">
|
|
9117
|
+
@if (isCascadeEnabled(f.name)) {
|
|
9118
|
+
<span class="rule-badge b-active">Ativo</span>
|
|
9119
|
+
}
|
|
9120
|
+
@if (loadOnChange(f.name)==='manual') {
|
|
9121
|
+
<span class="rule-badge b-manual">Manual</span>
|
|
9122
|
+
}
|
|
9123
|
+
@if (loadOnChange(f.name)==='immediate') {
|
|
9124
|
+
<span class="rule-badge b-immediate">Immediate</span>
|
|
9125
|
+
}
|
|
9126
|
+
</div>
|
|
9127
|
+
}
|
|
9070
9128
|
</div>
|
|
9071
|
-
|
|
9129
|
+
}
|
|
9072
9130
|
</div>
|
|
9073
|
-
|
|
9074
|
-
<ng-template #vscroll>
|
|
9131
|
+
} @else {
|
|
9075
9132
|
<cdk-virtual-scroll-viewport itemSize="44" style="height: calc(100vh - 240px)">
|
|
9076
9133
|
<div *cdkVirtualFor="let f of filteredFields()" (click)="selectField(f.name)" class="field-item" [class.selected]="f.name===selectedField()" tabindex="0" (keydown)="onFieldKeydown($event, f.name)">
|
|
9077
9134
|
<div>
|
|
9078
9135
|
<div>{{ labelFor(f.name) }}</div>
|
|
9079
9136
|
<small style="opacity:.7">{{ f.name }}</small>
|
|
9080
9137
|
</div>
|
|
9081
|
-
|
|
9082
|
-
<
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
|
|
9138
|
+
@if (hasRule(f.name)) {
|
|
9139
|
+
<div class="rule-badges">
|
|
9140
|
+
@if (isCascadeEnabled(f.name)) {
|
|
9141
|
+
<span class="rule-badge b-active">Ativo</span>
|
|
9142
|
+
}
|
|
9143
|
+
@if (loadOnChange(f.name)==='manual') {
|
|
9144
|
+
<span class="rule-badge b-manual">Manual</span>
|
|
9145
|
+
}
|
|
9146
|
+
@if (loadOnChange(f.name)==='immediate') {
|
|
9147
|
+
<span class="rule-badge b-immediate">Immediate</span>
|
|
9148
|
+
}
|
|
9149
|
+
</div>
|
|
9150
|
+
}
|
|
9086
9151
|
</div>
|
|
9087
9152
|
</cdk-virtual-scroll-viewport>
|
|
9088
|
-
|
|
9153
|
+
}
|
|
9089
9154
|
</div>
|
|
9090
|
-
|
|
9155
|
+
|
|
9091
9156
|
<!-- Right: Rules for selected field -->
|
|
9092
|
-
|
|
9093
|
-
<div class="cm-
|
|
9094
|
-
<div>
|
|
9095
|
-
<h3 style="margin:0">{{ labelFor(sel) }}</h3>
|
|
9096
|
-
<div style="opacity:.7">{{ sel }}</div>
|
|
9097
|
-
</div>
|
|
9098
|
-
<div>
|
|
9099
|
-
<button mat-stroked-button color="primary" (click)="exportRules()" style="margin-right:8px">Exportar</button>
|
|
9100
|
-
<button mat-stroked-button (click)="toggleImport()" style="margin-right:8px">Importar</button>
|
|
9101
|
-
<button mat-flat-button color="primary" [matMenuTriggerFor]="addMenu" [disabled]="editing()">Adicionar</button>
|
|
9102
|
-
<mat-menu #addMenu="matMenu">
|
|
9103
|
-
<button mat-menu-item (click)="startEdit(sel)"><mat-icon [praxisIcon]="'add'"></mat-icon><span>Em branco</span></button>
|
|
9104
|
-
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota → Destino (id)</span></button>
|
|
9105
|
-
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino-propriedade')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota + Destino → Propriedade (ids)</span></button>
|
|
9106
|
-
</mat-menu>
|
|
9107
|
-
</div>
|
|
9108
|
-
</div>
|
|
9109
|
-
|
|
9110
|
-
<!-- Conflict banner (connections) -->
|
|
9111
|
-
<div class="banner" *ngIf="hasConflict(sel)">
|
|
9112
|
-
<mat-icon [praxisIcon]="'link_off'"></mat-icon>
|
|
9113
|
-
<div>
|
|
9114
|
-
Connections atualizam este campo (filterCriteria). Considere desativar a cascata nativa ou usar ‘manual’.
|
|
9115
|
-
</div>
|
|
9116
|
-
<span class="spacer"></span>
|
|
9117
|
-
<button mat-stroked-button color="primary" (click)="quickSet(sel,'disable')">Desativar</button>
|
|
9118
|
-
<button mat-stroked-button color="accent" (click)="quickSet(sel,'manual')">Definir manual</button>
|
|
9119
|
-
</div>
|
|
9120
|
-
|
|
9121
|
-
<div *ngIf="importMode" class="import-panel">
|
|
9122
|
-
<div style="display:flex; gap:8px; align-items:center; margin-bottom:8px"><mat-icon [praxisIcon]="'upload'"></mat-icon><strong>Importar regras (JSON)</strong></div>
|
|
9123
|
-
<textarea matInput rows="6" class="full" [(ngModel)]="importJson" placeholder='{ "campo": { "dependencyFields": ["dep"], ... } }'></textarea>
|
|
9124
|
-
<div style="display:flex; gap:8px; justify-content:flex-end; padding-top:8px">
|
|
9125
|
-
<button mat-stroked-button (click)="toggleImport()">Cancelar</button>
|
|
9126
|
-
<button mat-flat-button color="primary" (click)="applyImport()">Aplicar</button>
|
|
9127
|
-
</div>
|
|
9128
|
-
</div>
|
|
9129
|
-
|
|
9130
|
-
<div *ngIf="!ruleFor(sel)">
|
|
9131
|
-
<div class="rules-empty">Nenhuma cascata configurada. Clique em “Adicionar” para montar a dependência.</div>
|
|
9132
|
-
</div>
|
|
9133
|
-
<div *ngIf="ruleFor(sel) as rule">
|
|
9134
|
-
<div class="rule-row">
|
|
9157
|
+
@if (selectedField(); as sel) {
|
|
9158
|
+
<div class="cm-right">
|
|
9159
|
+
<div class="cm-header">
|
|
9135
9160
|
<div>
|
|
9136
|
-
<
|
|
9137
|
-
<div style="opacity:.7">
|
|
9161
|
+
<h3 style="margin:0">{{ labelFor(sel) }}</h3>
|
|
9162
|
+
<div style="opacity:.7">{{ sel }}</div>
|
|
9138
9163
|
</div>
|
|
9139
|
-
<div
|
|
9140
|
-
<button mat-
|
|
9141
|
-
<button mat-
|
|
9142
|
-
<button mat-
|
|
9164
|
+
<div>
|
|
9165
|
+
<button mat-stroked-button color="primary" (click)="exportRules()" style="margin-right:8px">Exportar</button>
|
|
9166
|
+
<button mat-stroked-button (click)="toggleImport()" style="margin-right:8px">Importar</button>
|
|
9167
|
+
<button mat-flat-button color="primary" [matMenuTriggerFor]="addMenu" [disabled]="editing()">Adicionar</button>
|
|
9168
|
+
<mat-menu #addMenu="matMenu">
|
|
9169
|
+
<button mat-menu-item (click)="startEdit(sel)"><mat-icon [praxisIcon]="'add'"></mat-icon><span>Em branco</span></button>
|
|
9170
|
+
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota → Destino (id)</span></button>
|
|
9171
|
+
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino-propriedade')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota + Destino → Propriedade (ids)</span></button>
|
|
9172
|
+
</mat-menu>
|
|
9143
9173
|
</div>
|
|
9144
9174
|
</div>
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9175
|
+
<!-- Conflict banner (connections) -->
|
|
9176
|
+
@if (hasConflict(sel)) {
|
|
9177
|
+
<div class="banner">
|
|
9178
|
+
<mat-icon [praxisIcon]="'link_off'"></mat-icon>
|
|
9179
|
+
<div>
|
|
9180
|
+
Connections atualizam este campo (filterCriteria). Considere desativar a cascata nativa ou usar ‘manual’.
|
|
9181
|
+
</div>
|
|
9182
|
+
<span class="spacer"></span>
|
|
9183
|
+
<button mat-stroked-button color="primary" (click)="quickSet(sel,'disable')">Desativar</button>
|
|
9184
|
+
<button mat-stroked-button color="accent" (click)="quickSet(sel,'manual')">Definir manual</button>
|
|
9185
|
+
</div>
|
|
9186
|
+
}
|
|
9187
|
+
@if (importMode) {
|
|
9188
|
+
<div class="import-panel">
|
|
9189
|
+
<div style="display:flex; gap:8px; align-items:center; margin-bottom:8px"><mat-icon [praxisIcon]="'upload'"></mat-icon><strong>Importar regras (JSON)</strong></div>
|
|
9190
|
+
<textarea matInput rows="6" class="full" [(ngModel)]="importJson" placeholder='{ "campo": { "dependencyFields": ["dep"], ... } }'></textarea>
|
|
9191
|
+
<div style="display:flex; gap:8px; justify-content:flex-end; padding-top:8px">
|
|
9192
|
+
<button mat-stroked-button (click)="toggleImport()">Cancelar</button>
|
|
9193
|
+
<button mat-flat-button color="primary" (click)="applyImport()">Aplicar</button>
|
|
9194
|
+
</div>
|
|
9195
|
+
</div>
|
|
9196
|
+
}
|
|
9197
|
+
@if (!ruleFor(sel)) {
|
|
9151
9198
|
<div>
|
|
9152
|
-
<div>
|
|
9153
|
-
<small style="color: var(--md-sys-color-on-surface-variant);">Defina dependentes, quando recarregar e como mapear filtros</small>
|
|
9199
|
+
<div class="rules-empty">Nenhuma cascata configurada. Clique em “Adicionar” para montar a dependência.</div>
|
|
9154
9200
|
</div>
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9201
|
+
}
|
|
9202
|
+
@if (ruleFor(sel); as rule) {
|
|
9203
|
+
<div>
|
|
9204
|
+
<div class="rule-row">
|
|
9205
|
+
<div>
|
|
9206
|
+
<div><strong>Dependentes:</strong> {{ rule.dependencyFields.join(', ') || '—' }}</div>
|
|
9207
|
+
<div style="opacity:.7">Load on change: {{ rule.dependencyLoadOnChange || 'respectLoadOn' }} | Merge: {{ rule.dependencyMergeStrategy || 'merge' }}</div>
|
|
9208
|
+
</div>
|
|
9209
|
+
<div class="rule-actions">
|
|
9210
|
+
<button mat-icon-button matTooltip="Editar" (click)="startEdit(sel)"><mat-icon [praxisIcon]="'edit'"></mat-icon></button>
|
|
9211
|
+
<button mat-icon-button matTooltip="Duplicar" disabled><mat-icon [praxisIcon]="'content_copy'"></mat-icon></button>
|
|
9212
|
+
<button mat-icon-button matTooltip="Remover" (click)="remove(sel)"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
9213
|
+
</div>
|
|
9214
|
+
</div>
|
|
9215
|
+
</div>
|
|
9216
|
+
}
|
|
9217
|
+
<!-- Editor com seções (sem acordeão duplo) -->
|
|
9218
|
+
<div class="panel-surface">
|
|
9219
|
+
<div class="panel-header" style="padding: 12px 16px; border-bottom: 1px solid var(--md-sys-color-outline-variant);">
|
|
9220
|
+
<mat-icon [praxisIcon]="'rule'"></mat-icon>
|
|
9221
|
+
<div>
|
|
9222
|
+
<div>Cascata do campo</div>
|
|
9223
|
+
<small style="color: var(--md-sys-color-on-surface-variant);">Defina dependentes, quando recarregar e como mapear filtros</small>
|
|
9224
|
+
</div>
|
|
9225
|
+
</div>
|
|
9226
|
+
<div class="panel-stack">
|
|
9227
|
+
<!-- Básico -->
|
|
9228
|
+
<mat-expansion-panel [expanded]="true" class="stack-panel">
|
|
9229
|
+
<mat-expansion-panel-header>
|
|
9230
|
+
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'tune'"></mat-icon> Básico</mat-panel-title>
|
|
9231
|
+
</mat-expansion-panel-header>
|
|
9232
|
+
<div class="form-grid">
|
|
9233
|
+
<div class="form-row">
|
|
9234
|
+
<mat-form-field appearance="outline" class="full">
|
|
9235
|
+
<mat-label>Campos dependentes</mat-label>
|
|
9236
|
+
<mat-select multiple [(ngModel)]="editDepList" (ngModelChange)="onDepListChange()">
|
|
9237
|
+
@for (f of availableDependencyFields(); track f) {
|
|
9238
|
+
<mat-option [value]="f.name">
|
|
9239
|
+
{{ labelFor(f.name) }} ({{ f.name }})
|
|
9240
|
+
</mat-option>
|
|
9241
|
+
}
|
|
9242
|
+
</mat-select>
|
|
9243
|
+
<button
|
|
9244
|
+
mat-icon-button
|
|
9245
|
+
matSuffix
|
|
9246
|
+
class="help-icon-button"
|
|
9247
|
+
type="button"
|
|
9248
|
+
[matTooltip]="'Selecione os campos que controlam este valor'"
|
|
9249
|
+
matTooltipPosition="above"
|
|
9250
|
+
>
|
|
9251
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
9252
|
+
</button>
|
|
9253
|
+
</mat-form-field>
|
|
9254
|
+
</div>
|
|
9255
|
+
<div class="form-row">
|
|
9256
|
+
<mat-checkbox [(ngModel)]="editEnable">Ativar cascata nativa</mat-checkbox>
|
|
9257
|
+
<mat-checkbox [(ngModel)]="editReset">Resetar ao mudar</mat-checkbox>
|
|
9258
|
+
</div>
|
|
9259
|
+
</div>
|
|
9260
|
+
</mat-expansion-panel>
|
|
9261
|
+
<!-- Execução -->
|
|
9262
|
+
<mat-expansion-panel class="stack-panel">
|
|
9263
|
+
<mat-expansion-panel-header>
|
|
9264
|
+
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'schedule'"></mat-icon> Execução</mat-panel-title>
|
|
9265
|
+
</mat-expansion-panel-header>
|
|
9266
|
+
<div class="form-row">
|
|
9267
|
+
<mat-form-field appearance="outline">
|
|
9268
|
+
<mat-label>Carregar ao mudar</mat-label>
|
|
9269
|
+
<mat-select [(ngModel)]="editLoadOn">
|
|
9270
|
+
<mat-option value="respectLoadOn">Respeitar loadOn</mat-option>
|
|
9271
|
+
<mat-option value="immediate">Imediato</mat-option>
|
|
9272
|
+
<mat-option value="manual">Manual</mat-option>
|
|
9273
|
+
</mat-select>
|
|
9274
|
+
</mat-form-field>
|
|
9275
|
+
<mat-form-field appearance="outline">
|
|
9276
|
+
<mat-label>Merge de filtros</mat-label>
|
|
9277
|
+
<mat-select [(ngModel)]="editMerge">
|
|
9278
|
+
<mat-option value="merge">merge (padrão)</mat-option>
|
|
9279
|
+
<mat-option value="replace">replace</mat-option>
|
|
9280
|
+
</mat-select>
|
|
9281
|
+
</mat-form-field>
|
|
9282
|
+
<mat-form-field appearance="outline">
|
|
9283
|
+
<mat-label>Atraso (ms)</mat-label>
|
|
9284
|
+
<input matInput type="number" [(ngModel)]="editDebounce">
|
|
9285
|
+
</mat-form-field>
|
|
9286
|
+
</div>
|
|
9287
|
+
</mat-expansion-panel>
|
|
9288
|
+
<!-- Extração de valor -->
|
|
9289
|
+
<mat-expansion-panel class="stack-panel">
|
|
9290
|
+
<mat-expansion-panel-header>
|
|
9291
|
+
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'call_split'"></mat-icon> Extração de valor</mat-panel-title>
|
|
9292
|
+
</mat-expansion-panel-header>
|
|
9164
9293
|
<div class="form-row">
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
<mat-option *ngFor="let f of availableDependencyFields()" [value]="f.name">
|
|
9169
|
-
{{ labelFor(f.name) }} ({{ f.name }})
|
|
9170
|
-
</mat-option>
|
|
9171
|
-
</mat-select>
|
|
9294
|
+
<mat-form-field appearance="outline" class="full">
|
|
9295
|
+
<mat-label>ValuePath padrão</mat-label>
|
|
9296
|
+
<input matInput [(ngModel)]="editValuePath" placeholder="id">
|
|
9172
9297
|
<button
|
|
9173
9298
|
mat-icon-button
|
|
9174
9299
|
matSuffix
|
|
9175
9300
|
class="help-icon-button"
|
|
9176
9301
|
type="button"
|
|
9177
|
-
[matTooltip]="'
|
|
9302
|
+
[matTooltip]="'Preenchido automaticamente a partir de optionValueKey() ou \\'id\\''"
|
|
9178
9303
|
matTooltipPosition="above"
|
|
9179
|
-
|
|
9304
|
+
>
|
|
9180
9305
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
9181
9306
|
</button>
|
|
9182
|
-
|
|
9183
|
-
</div>
|
|
9184
|
-
<div class="form-row">
|
|
9185
|
-
<mat-checkbox [(ngModel)]="editEnable">Ativar cascata nativa</mat-checkbox>
|
|
9186
|
-
<mat-checkbox [(ngModel)]="editReset">Resetar ao mudar</mat-checkbox>
|
|
9307
|
+
</mat-form-field>
|
|
9187
9308
|
</div>
|
|
9188
|
-
</
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9210
|
-
|
|
9211
|
-
|
|
9212
|
-
|
|
9213
|
-
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9261
|
-
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
|
|
9265
|
-
|
|
9266
|
-
|
|
9267
|
-
|
|
9268
|
-
|
|
9269
|
-
|
|
9270
|
-
|
|
9271
|
-
|
|
9272
|
-
>
|
|
9273
|
-
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
9274
|
-
</button>
|
|
9275
|
-
</mat-form-field>
|
|
9276
|
-
</td>
|
|
9277
|
-
<td>
|
|
9278
|
-
<mat-form-field appearance="outline" class="full">
|
|
9279
|
-
<mat-label>ValuePath</mat-label>
|
|
9280
|
-
<input matInput [(ngModel)]="row.valuePath" [matAutocomplete]="autoValue" [placeholder]="editValuePath||'id'">
|
|
9281
|
-
<mat-autocomplete #autoValue="matAutocomplete">
|
|
9282
|
-
<mat-option *ngFor="let opt of getValuePathSuggestions(row.dep)" [value]="opt">{{ opt }}</mat-option>
|
|
9283
|
-
</mat-autocomplete>
|
|
9284
|
-
<button
|
|
9285
|
-
mat-icon-button
|
|
9286
|
-
matSuffix
|
|
9287
|
-
class="help-icon-button"
|
|
9288
|
-
type="button"
|
|
9289
|
-
[matTooltip]="'Opcional'"
|
|
9290
|
-
matTooltipPosition="above"
|
|
9291
|
-
>
|
|
9292
|
-
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
9293
|
-
</button>
|
|
9294
|
-
</mat-form-field>
|
|
9295
|
-
</td>
|
|
9296
|
-
</tr>
|
|
9297
|
-
</tbody>
|
|
9298
|
-
</table>
|
|
9299
|
-
<ng-template #noMap>
|
|
9300
|
-
<div class="rules-empty">Defina dependentes para sugerir o mapeamento.</div>
|
|
9301
|
-
</ng-template>
|
|
9302
|
-
</mat-expansion-panel>
|
|
9303
|
-
|
|
9304
|
-
<!-- Preview -->
|
|
9305
|
-
<mat-expansion-panel class="stack-panel">
|
|
9306
|
-
<mat-expansion-panel-header>
|
|
9307
|
-
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'visibility'"></mat-icon> Preview</mat-panel-title>
|
|
9308
|
-
</mat-expansion-panel-header>
|
|
9309
|
-
<pre class="preview-box">{{ buildPreview() }}</pre>
|
|
9310
|
-
<div style="display:flex; justify-content:flex-end; padding-top:6px">
|
|
9311
|
-
<button mat-stroked-button (click)="copyPreview()">Copiar</button>
|
|
9312
|
-
</div>
|
|
9313
|
-
</mat-expansion-panel>
|
|
9314
|
-
</div>
|
|
9315
|
-
|
|
9316
|
-
<div style="display:flex; gap:8px; justify-content:flex-end; padding:8px 12px;">
|
|
9317
|
-
<button mat-stroked-button (click)="cancelEdit()">Cancelar</button>
|
|
9318
|
-
<button mat-flat-button color="primary" (click)="saveEdit(sel)">Salvar</button>
|
|
9309
|
+
</mat-expansion-panel>
|
|
9310
|
+
<!-- Mapeamento de filtros (tabela) -->
|
|
9311
|
+
<mat-expansion-panel class="stack-panel">
|
|
9312
|
+
<mat-expansion-panel-header>
|
|
9313
|
+
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'filter_alt'"></mat-icon> Mapeamento de filtros</mat-panel-title>
|
|
9314
|
+
</mat-expansion-panel-header>
|
|
9315
|
+
@if (editMapRows.length) {
|
|
9316
|
+
<table class="map-table">
|
|
9317
|
+
<thead>
|
|
9318
|
+
<tr>
|
|
9319
|
+
<th>Dependente</th>
|
|
9320
|
+
<th>Chave (dot‑path)</th>
|
|
9321
|
+
<th>ValuePath (opcional)</th>
|
|
9322
|
+
</tr>
|
|
9323
|
+
</thead>
|
|
9324
|
+
<tbody>
|
|
9325
|
+
@for (row of editMapRows; track row; let i = $index) {
|
|
9326
|
+
<tr>
|
|
9327
|
+
<td>{{ row.dep }}</td>
|
|
9328
|
+
<td>
|
|
9329
|
+
<mat-form-field appearance="outline" class="full">
|
|
9330
|
+
<mat-label>Chave</mat-label>
|
|
9331
|
+
<input matInput [(ngModel)]="row.key" [matAutocomplete]="autoKey" [placeholder]="row.dep">
|
|
9332
|
+
<mat-autocomplete #autoKey="matAutocomplete">
|
|
9333
|
+
@for (opt of getKeySuggestions(row.dep); track opt) {
|
|
9334
|
+
<mat-option [value]="opt">{{ opt }}</mat-option>
|
|
9335
|
+
}
|
|
9336
|
+
</mat-autocomplete>
|
|
9337
|
+
<button
|
|
9338
|
+
mat-icon-button
|
|
9339
|
+
matSuffix
|
|
9340
|
+
class="help-icon-button"
|
|
9341
|
+
type="button"
|
|
9342
|
+
[matTooltip]="'Use dot-notation (e.g. ' + row.dep + '.id) for nested objects'"
|
|
9343
|
+
matTooltipPosition="above"
|
|
9344
|
+
>
|
|
9345
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
9346
|
+
</button>
|
|
9347
|
+
</mat-form-field>
|
|
9348
|
+
</td>
|
|
9349
|
+
<td>
|
|
9350
|
+
<mat-form-field appearance="outline" class="full">
|
|
9351
|
+
<mat-label>ValuePath</mat-label>
|
|
9352
|
+
<input matInput [(ngModel)]="row.valuePath" [matAutocomplete]="autoValue" [placeholder]="editValuePath||'id'">
|
|
9353
|
+
<mat-autocomplete #autoValue="matAutocomplete">
|
|
9354
|
+
@for (opt of getValuePathSuggestions(row.dep); track opt) {
|
|
9355
|
+
<mat-option [value]="opt">{{ opt }}</mat-option>
|
|
9356
|
+
}
|
|
9357
|
+
</mat-autocomplete>
|
|
9358
|
+
<button
|
|
9359
|
+
mat-icon-button
|
|
9360
|
+
matSuffix
|
|
9361
|
+
class="help-icon-button"
|
|
9362
|
+
type="button"
|
|
9363
|
+
[matTooltip]="'Opcional'"
|
|
9364
|
+
matTooltipPosition="above"
|
|
9365
|
+
>
|
|
9366
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
9367
|
+
</button>
|
|
9368
|
+
</mat-form-field>
|
|
9369
|
+
</td>
|
|
9370
|
+
</tr>
|
|
9371
|
+
}
|
|
9372
|
+
</tbody>
|
|
9373
|
+
</table>
|
|
9374
|
+
} @else {
|
|
9375
|
+
<div class="rules-empty">Defina dependentes para sugerir o mapeamento.</div>
|
|
9376
|
+
}
|
|
9377
|
+
</mat-expansion-panel>
|
|
9378
|
+
<!-- Preview -->
|
|
9379
|
+
<mat-expansion-panel class="stack-panel">
|
|
9380
|
+
<mat-expansion-panel-header>
|
|
9381
|
+
<mat-panel-title class="panel-header"><mat-icon [praxisIcon]="'visibility'"></mat-icon> Preview</mat-panel-title>
|
|
9382
|
+
</mat-expansion-panel-header>
|
|
9383
|
+
<pre class="preview-box">{{ buildPreview() }}</pre>
|
|
9384
|
+
<div style="display:flex; justify-content:flex-end; padding-top:6px">
|
|
9385
|
+
<button mat-stroked-button (click)="copyPreview()">Copiar</button>
|
|
9386
|
+
</div>
|
|
9387
|
+
</mat-expansion-panel>
|
|
9388
|
+
</div>
|
|
9389
|
+
<div style="display:flex; gap:8px; justify-content:flex-end; padding:8px 12px;">
|
|
9390
|
+
<button mat-stroked-button (click)="cancelEdit()">Cancelar</button>
|
|
9391
|
+
<button mat-flat-button color="primary" (click)="saveEdit(sel)">Salvar</button>
|
|
9392
|
+
</div>
|
|
9319
9393
|
</div>
|
|
9320
9394
|
</div>
|
|
9321
|
-
|
|
9395
|
+
}
|
|
9322
9396
|
</div>
|
|
9323
|
-
|
|
9397
|
+
`, styles: [":host{display:block}.cm-root{display:grid;grid-template-columns:320px 1fr;gap:16px;min-height:420px}.cm-left{border-right:1px solid var(--md-sys-color-outline-variant);padding-right:8px}.cm-search{width:100%;margin-bottom:8px}.cm-right{padding-left:8px}.field-item{display:flex;align-items:center;justify-content:space-between;padding:8px 6px;cursor:pointer;border-radius:10px;transition:background .12s ease,border .12s ease;border:1px solid transparent}.field-item:hover{background:var(--md-sys-color-surface-container-high)}.field-item.selected{background:var(--md-sys-color-surface-container-highest);border-color:var(--md-sys-color-outline-variant)}.rule-badges{display:inline-flex;gap:6px}.rule-badge{font-size:11px;padding:2px 8px;border-radius:999px;font-weight:600}.b-active{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.b-manual{background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant)}.b-immediate{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.b-conflict{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.cm-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.rules-empty{opacity:.8;font-style:italic;padding:8px 0;color:var(--md-sys-color-on-surface-variant)}.rule-row{display:grid;grid-template-columns:1fr auto;align-items:center;padding:10px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant)}.rule-actions button{margin-left:4px}.banner{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container);padding:10px 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;margin-bottom:10px;display:flex;gap:8px;align-items:center}.import-panel{background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:10px;margin-bottom:10px}.full{width:100%}.form-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.form-grid{display:grid;gap:12px;padding:8px 0}.map-table{width:100%;border-collapse:collapse}.map-table th,.map-table td{padding:8px;border-bottom:1px dashed var(--md-sys-color-outline-variant)}.kbd{font-family:monospace;background:var(--md-sys-color-surface-container-highest);padding:0 6px;border-radius:4px;color:var(--md-sys-color-on-surface-variant)}.panel-surface{background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;box-shadow:var(--md-sys-elevation-level1, none);margin-bottom:12px}.panel-stack{display:grid;gap:12px;margin:12px 0}.stack-panel{background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;box-shadow:var(--md-sys-elevation-level1, none)}.stack-panel .mat-expansion-panel-content{padding:0 16px 12px}.panel-header{display:flex;align-items:center;gap:8px}.preview-box{background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:8px;color:var(--md-sys-color-on-surface)}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}\n"] }]
|
|
9324
9398
|
}], ctorParameters: () => [{ type: CascadeRulesService }], propDecorators: { fields: [{
|
|
9325
9399
|
type: Input
|
|
9326
9400
|
}], connections: [{
|