@praxisui/page-builder 4.0.0-beta.0 → 6.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/fesm2022/praxisui-page-builder.mjs +722 -95
- package/index.d.ts +5 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -36,9 +36,11 @@ Peer dependencies (Angular v20):
|
|
|
36
36
|
Este pacote expoe o shell ativo do builder canonico de pagina dinamica:
|
|
37
37
|
- `ComponentPaletteDialogComponent` para adicionar widgets a pagina.
|
|
38
38
|
- `FloatingToolbarComponent` e `TileToolbarComponent` para acoes rapidas de add/save/preview/configuracao.
|
|
39
|
+
- visualizador inicial de conexoes somente leitura para inspecao de `composition.links`.
|
|
39
40
|
- `WidgetShellEditorComponent` e `DynamicPageConfigEditorComponent` para authoring de shell/canvas sem redefinir a semantica canonica de composicao.
|
|
40
41
|
|
|
41
42
|
Conexoes continuam pertencendo ao contrato `WidgetPageDefinition`, mas a criacao/manutencao delas nesta fase deve acontecer por JSON/configuracao canonica e nao por builder/graph/editor visual legado.
|
|
43
|
+
O viewer ativo nesta fase existe apenas para inspecao contextual do contrato canonico e nao para editar links inline.
|
|
42
44
|
|
|
43
45
|
## AI Capabilities Registration
|
|
44
46
|
|
|
@@ -122,14 +124,14 @@ O builder canonico expoe authoring de shell/palette sobre `praxis-dynamic-page`.
|
|
|
122
124
|
</praxis-dynamic-page-builder>
|
|
123
125
|
```
|
|
124
126
|
|
|
125
|
-
`page` e um `WidgetPageDefinition` (do `@praxisui/core`) contendo `widgets` e opcionalmente `
|
|
127
|
+
`page` e um `WidgetPageDefinition` (do `@praxisui/core`) contendo `widgets` e opcionalmente `composition.links`. O envelope `composition` e o caminho `composition.links` formam a superficie canonica persistida para wiring da pagina, com `condition` em Json Logic e `policy` para comportamento operacional.
|
|
126
128
|
|
|
127
129
|
## Widget Shell (Dashboard Cards)
|
|
128
130
|
|
|
129
131
|
Cada widget pode declarar um `shell` para renderizar um card padronizado com cabecalho rico, acoes de contexto e controles de janela (expandir/recolher).
|
|
130
132
|
|
|
131
133
|
Quando uma acao e clicada, o shell:
|
|
132
|
-
- dispara um evento para o page-builder (`emit`, ou `shell:<id>` por padrao) para uso em `
|
|
134
|
+
- dispara um evento para o page-builder (`emit`, ou `shell:<id>` por padrao) para uso em `composition.links`;
|
|
133
135
|
- tenta despachar a acao para o componente interno via metodo `handleShellAction(action)`.
|
|
134
136
|
|
|
135
137
|
### Presets visuais (global)
|
|
@@ -157,7 +159,8 @@ this.settingsPanel.open({
|
|
|
157
159
|
|
|
158
160
|
## Dicas
|
|
159
161
|
|
|
160
|
-
- Trate `
|
|
162
|
+
- Trate `composition.links` como parte do contrato canonico salvo no JSON da pagina.
|
|
163
|
+
- Use `composition.links[].condition` para guardas semanticas em Json Logic e `composition.links[].policy` para debounce/distinct/missing-value.
|
|
161
164
|
- Quando precisar revisar ligacoes, prefira inspecao textual/versionada do contrato e do runtime, nao um editor visual legado.
|
|
162
165
|
|
|
163
166
|
## API (resumo)
|
|
@@ -11,9 +11,9 @@ import { MatIconModule } from '@angular/material/icon';
|
|
|
11
11
|
import * as i2$2 from '@praxisui/core';
|
|
12
12
|
import { PraxisIconDirective, BUILTIN_SHELL_PRESETS, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, providePraxisI18n, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, PraxisI18nService, generateId, SETTINGS_PANEL_BRIDGE, DynamicWidgetPageComponent, DYNAMIC_PAGE_SHELL_EDITOR } from '@praxisui/core';
|
|
13
13
|
export { WidgetShellComponent } from '@praxisui/core';
|
|
14
|
-
import * as
|
|
14
|
+
import * as i4 from '@angular/material/tooltip';
|
|
15
15
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
16
|
-
import * as i3$
|
|
16
|
+
import * as i3$1 from '@angular/material/form-field';
|
|
17
17
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
18
18
|
import * as i9 from '@angular/material/input';
|
|
19
19
|
import { MatInputModule } from '@angular/material/input';
|
|
@@ -119,7 +119,7 @@ class TileToolbarComponent {
|
|
|
119
119
|
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
120
120
|
</button>
|
|
121
121
|
</div>
|
|
122
|
-
`, isInline: true, styles: [":host{position:absolute;inset:0;pointer-events:none}.pdx-tile-toolbar{position:absolute;right:6px;top:-18px;display:flex;gap:6px;z-index:5;opacity:0;transition:opacity .12s ease-in-out;pointer-events:auto;background:var(--md-sys-color-surface-container-low);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border-radius:999px;padding:4px;box-shadow:var(--mat-elevation-level3)}.pdx-tile-toolbar.always-visible{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type:
|
|
122
|
+
`, isInline: true, styles: [":host{position:absolute;inset:0;pointer-events:none}.pdx-tile-toolbar{position:absolute;right:6px;top:-18px;display:flex;gap:6px;z-index:5;opacity:0;transition:opacity .12s ease-in-out;pointer-events:auto;background:var(--md-sys-color-surface-container-low);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border-radius:999px;padding:4px;box-shadow:var(--mat-elevation-level3)}.pdx-tile-toolbar.always-visible{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
123
123
|
}
|
|
124
124
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TileToolbarComponent, decorators: [{
|
|
125
125
|
type: Component,
|
|
@@ -211,7 +211,7 @@ class FloatingToolbarComponent {
|
|
|
211
211
|
<ng-content select="[pdx-toolbar-extra]"></ng-content>
|
|
212
212
|
</div>
|
|
213
213
|
</div>
|
|
214
|
-
`, isInline: true, styles: [":host{position:absolute;inset:0;pointer-events:none}.pdx-floating-toolbar{position:absolute;right:16px;bottom:16px;display:flex;gap:8px;align-items:center;pointer-events:auto}.pdx-actions{display:flex;gap:8px}.pdx-fab{box-shadow:var(--mat-elevation-level4)}@media(max-width:720px){.pdx-actions{gap:6px}.pdx-floating-toolbar{right:12px;bottom:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type:
|
|
214
|
+
`, isInline: true, styles: [":host{position:absolute;inset:0;pointer-events:none}.pdx-floating-toolbar{position:absolute;right:16px;bottom:16px;display:flex;gap:8px;align-items:center;pointer-events:auto}.pdx-actions{display:flex;gap:8px}.pdx-fab{box-shadow:var(--mat-elevation-level4)}@media(max-width:720px){.pdx-actions{gap:6px}.pdx-floating-toolbar{right:12px;bottom:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
215
215
|
}
|
|
216
216
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FloatingToolbarComponent, decorators: [{
|
|
217
217
|
type: Component,
|
|
@@ -1516,7 +1516,7 @@ class WidgetShellEditorComponent {
|
|
|
1516
1516
|
<div class="shell-empty">Nenhuma ação configurada.</div>
|
|
1517
1517
|
</ng-template>
|
|
1518
1518
|
</div>
|
|
1519
|
-
`, isInline: true, styles: [".shell-editor{display:grid;gap:12px;padding:16px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.shell-head{display:flex;align-items:center;gap:12px}.shell-title{font-weight:600}.shell-subtitle{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-section{font-weight:600;margin-top:8px}.shell-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:1fr auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100%}.shell-preview{border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;padding:12px}.shell-preview-card{background:var(--pdx-shell-card-bg, var(--md-sys-color-surface));border:1px solid var(--pdx-shell-card-border, var(--md-sys-color-outline-variant));border-radius:var(--pdx-shell-card-radius, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.shell-preview-card.no-shell{background:transparent;border:none;box-shadow:none}.shell-preview-card.expanded{box-shadow:var(--pdx-shell-card-shadow, 0 16px 34px rgba(0,0,0,.32));transform:scale(1.01)}.shell-preview-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.shell-preview-title{display:flex;align-items:center;gap:10px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.shell-preview-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.shell-preview-text{min-width:0}.shell-preview-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-actions{display:flex;align-items:center;gap:6px}.pdx-preview-text{padding:0 8px}.pdx-preview-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-preview-label{font-size:12px;font-weight:500}.shell-preview-body{padding:var(--pdx-shell-body-padding, 10px 12px 12px 12px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit);font-size:12px}.shell-preview-body.hidden{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5.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: MatDividerModule }, { kind: "component", type: i6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$
|
|
1519
|
+
`, isInline: true, styles: [".shell-editor{display:grid;gap:12px;padding:16px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.shell-head{display:flex;align-items:center;gap:12px}.shell-title{font-weight:600}.shell-subtitle{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-section{font-weight:600;margin-top:8px}.shell-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:1fr auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100%}.shell-preview{border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;padding:12px}.shell-preview-card{background:var(--pdx-shell-card-bg, var(--md-sys-color-surface));border:1px solid var(--pdx-shell-card-border, var(--md-sys-color-outline-variant));border-radius:var(--pdx-shell-card-radius, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.shell-preview-card.no-shell{background:transparent;border:none;box-shadow:none}.shell-preview-card.expanded{box-shadow:var(--pdx-shell-card-shadow, 0 16px 34px rgba(0,0,0,.32));transform:scale(1.01)}.shell-preview-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.shell-preview-title{display:flex;align-items:center;gap:10px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.shell-preview-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.shell-preview-text{min-width:0}.shell-preview-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-actions{display:flex;align-items:center;gap:6px}.pdx-preview-text{padding:0 8px}.pdx-preview-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-preview-label{font-size:12px;font-weight:500}.shell-preview-body{padding:var(--pdx-shell-body-padding, 10px 12px 12px 12px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit);font-size:12px}.shell-preview-body.hidden{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5.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: MatDividerModule }, { kind: "component", type: i6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i9.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: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$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: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1520
1520
|
}
|
|
1521
1521
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: WidgetShellEditorComponent, decorators: [{
|
|
1522
1522
|
type: Component,
|
|
@@ -2101,7 +2101,7 @@ class DynamicPageConfigEditorComponent {
|
|
|
2101
2101
|
<mat-tab label="Estado da Pagina"><mat-form-field appearance="outline" class="wide"><mat-label>State (JSON)</mat-label><textarea matInput rows="14" [formControl]="stateControl"></textarea></mat-form-field></mat-tab>
|
|
2102
2102
|
</mat-tab-group>
|
|
2103
2103
|
</div>
|
|
2104
|
-
`, isInline: true, styles: [".editor,.panel{display:grid;gap:16px}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.card{display:grid;gap:12px;padding:16px;border:1px solid #d8e0ea;border-radius:16px;background:#fbfcfe}.wide{grid-column:1/-1}.hint{color:#5b6472;font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.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$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$
|
|
2104
|
+
`, isInline: true, styles: [".editor,.panel{display:grid;gap:16px}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.card{display:grid;gap:12px;padding:16px;border:1px solid #d8e0ea;border-radius:16px;background:#fbfcfe}.wide{grid-column:1/-1}.hint{color:#5b6472;font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.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$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i9.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: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$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: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2105
2105
|
}
|
|
2106
2106
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicPageConfigEditorComponent, decorators: [{
|
|
2107
2107
|
type: Component,
|
|
@@ -2236,7 +2236,7 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
2236
2236
|
'praxis.pageBuilder.editor.state.compute': 'Compute',
|
|
2237
2237
|
'praxis.pageBuilder.editor.state.compute.operator': 'Operator',
|
|
2238
2238
|
'praxis.pageBuilder.editor.state.compute.template': 'Template',
|
|
2239
|
-
'praxis.pageBuilder.editor.state.compute.expr': '
|
|
2239
|
+
'praxis.pageBuilder.editor.state.compute.expr': 'Json Logic',
|
|
2240
2240
|
'praxis.pageBuilder.editor.state.compute.transformer': 'Transformer',
|
|
2241
2241
|
'praxis.pageBuilder.editor.state.dependsOn': 'DependsOn (comma-separated)',
|
|
2242
2242
|
'praxis.pageBuilder.editor.state.sourcePath': 'Source path',
|
|
@@ -2245,7 +2245,7 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
2245
2245
|
'praxis.pageBuilder.editor.state.template': 'Template',
|
|
2246
2246
|
'praxis.pageBuilder.editor.state.templateJson': 'Template (JSON)',
|
|
2247
2247
|
'praxis.pageBuilder.editor.state.templateNull': 'The template will return null.',
|
|
2248
|
-
'praxis.pageBuilder.editor.state.expression': '
|
|
2248
|
+
'praxis.pageBuilder.editor.state.expression': 'Json Logic',
|
|
2249
2249
|
'praxis.pageBuilder.editor.state.transformer': 'Transformer',
|
|
2250
2250
|
'praxis.pageBuilder.editor.state.optionsJson': 'Options (JSON)',
|
|
2251
2251
|
'praxis.pageBuilder.editor.apply': 'Apply',
|
|
@@ -2262,6 +2262,44 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
2262
2262
|
'praxis.pageBuilder.editor.hints.schemaInitial': 'Define the initial value of this state path. This helps the page start in a consistent state even before remote connections and data.',
|
|
2263
2263
|
'praxis.pageBuilder.editor.hints.templateJson': 'JSON templates are useful to generate complete derived objects, such as texts, summary cards or shell settings.',
|
|
2264
2264
|
'praxis.pageBuilder.editor.hints.transformerOptions': 'Pass the registered transformer options here. Prefer lean JSON with only the parameters actually used by the runtime.',
|
|
2265
|
+
'praxis.pageBuilder.connections.toggle': 'Inspect connections',
|
|
2266
|
+
'praxis.pageBuilder.connections.toggleAria': 'Inspect connections',
|
|
2267
|
+
'praxis.pageBuilder.connections.title': 'Connections',
|
|
2268
|
+
'praxis.pageBuilder.connections.subtitle': 'Inspect the canonical composition links without editing the page document.',
|
|
2269
|
+
'praxis.pageBuilder.connections.panelAria': 'Connections viewer',
|
|
2270
|
+
'praxis.pageBuilder.connections.summary.widgets': 'Widgets',
|
|
2271
|
+
'praxis.pageBuilder.connections.summary.links': 'Links',
|
|
2272
|
+
'praxis.pageBuilder.connections.summary.conditions': 'With condition',
|
|
2273
|
+
'praxis.pageBuilder.connections.summary.diagnostics': 'Diagnostics',
|
|
2274
|
+
'praxis.pageBuilder.connections.filters.title': 'Filters',
|
|
2275
|
+
'praxis.pageBuilder.connections.filters.all': 'All',
|
|
2276
|
+
'praxis.pageBuilder.connections.filters.condition': 'Condition',
|
|
2277
|
+
'praxis.pageBuilder.connections.filters.transform': 'Transform',
|
|
2278
|
+
'praxis.pageBuilder.connections.filters.policy': 'Policy',
|
|
2279
|
+
'praxis.pageBuilder.connections.filters.diagnostic': 'Diagnostic',
|
|
2280
|
+
'praxis.pageBuilder.connections.widgets.title': 'Widgets',
|
|
2281
|
+
'praxis.pageBuilder.connections.widgets.selected': 'Selected widget',
|
|
2282
|
+
'praxis.pageBuilder.connections.widgets.incoming': 'In',
|
|
2283
|
+
'praxis.pageBuilder.connections.widgets.outgoing': 'Out',
|
|
2284
|
+
'praxis.pageBuilder.connections.links.title': 'Links',
|
|
2285
|
+
'praxis.pageBuilder.connections.badges.condition': 'Condition',
|
|
2286
|
+
'praxis.pageBuilder.connections.badges.transform': 'Transform',
|
|
2287
|
+
'praxis.pageBuilder.connections.badges.policy': 'Policy',
|
|
2288
|
+
'praxis.pageBuilder.connections.badges.diagnostic': 'Diagnostic',
|
|
2289
|
+
'praxis.pageBuilder.connections.actions.focusSource': 'Focus source',
|
|
2290
|
+
'praxis.pageBuilder.connections.actions.focusTarget': 'Focus target',
|
|
2291
|
+
'praxis.pageBuilder.connections.actions.openPageSettings': 'Open page settings',
|
|
2292
|
+
'praxis.pageBuilder.connections.details.title': 'Selected link',
|
|
2293
|
+
'praxis.pageBuilder.connections.details.widgetId': 'Widget',
|
|
2294
|
+
'praxis.pageBuilder.connections.details.componentType': 'Component',
|
|
2295
|
+
'praxis.pageBuilder.connections.details.intent': 'Intent',
|
|
2296
|
+
'praxis.pageBuilder.connections.details.from': 'From',
|
|
2297
|
+
'praxis.pageBuilder.connections.details.to': 'To',
|
|
2298
|
+
'praxis.pageBuilder.connections.details.condition': 'Condition',
|
|
2299
|
+
'praxis.pageBuilder.connections.details.transform': 'Transform',
|
|
2300
|
+
'praxis.pageBuilder.connections.details.policy': 'Policy',
|
|
2301
|
+
'praxis.pageBuilder.connections.details.diagnostics': 'Diagnostics',
|
|
2302
|
+
'praxis.pageBuilder.connections.palette.insertComponent': 'Insert component',
|
|
2265
2303
|
};
|
|
2266
2304
|
|
|
2267
2305
|
const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
@@ -2361,7 +2399,7 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
2361
2399
|
'praxis.pageBuilder.editor.state.compute': 'Computar',
|
|
2362
2400
|
'praxis.pageBuilder.editor.state.compute.operator': 'Operador',
|
|
2363
2401
|
'praxis.pageBuilder.editor.state.compute.template': 'Modelo (Template)',
|
|
2364
|
-
'praxis.pageBuilder.editor.state.compute.expr': '
|
|
2402
|
+
'praxis.pageBuilder.editor.state.compute.expr': 'Json Logic',
|
|
2365
2403
|
'praxis.pageBuilder.editor.state.compute.transformer': 'Transformador',
|
|
2366
2404
|
'praxis.pageBuilder.editor.state.dependsOn': 'Depende de (vírgula)',
|
|
2367
2405
|
'praxis.pageBuilder.editor.state.sourcePath': 'Caminho de origem',
|
|
@@ -2370,7 +2408,7 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
2370
2408
|
'praxis.pageBuilder.editor.state.template': 'Modelo (Template)',
|
|
2371
2409
|
'praxis.pageBuilder.editor.state.templateJson': 'Modelo (JSON)',
|
|
2372
2410
|
'praxis.pageBuilder.editor.state.templateNull': 'O modelo retornará nulo (null).',
|
|
2373
|
-
'praxis.pageBuilder.editor.state.expression': '
|
|
2411
|
+
'praxis.pageBuilder.editor.state.expression': 'Json Logic',
|
|
2374
2412
|
'praxis.pageBuilder.editor.state.transformer': 'Transformador',
|
|
2375
2413
|
'praxis.pageBuilder.editor.state.optionsJson': 'Opções (JSON)',
|
|
2376
2414
|
'praxis.pageBuilder.editor.apply': 'Aplicar',
|
|
@@ -2387,6 +2425,44 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
2387
2425
|
'praxis.pageBuilder.editor.hints.schemaInitial': 'Defina o valor inicial desse caminho de estado. Isso ajuda a página a nascer em um estado consistente mesmo antes de conexões e dados remotos.',
|
|
2388
2426
|
'praxis.pageBuilder.editor.hints.templateJson': 'Modelos em JSON são úteis para gerar objetos derivados completos, como textos, cartões de resumo ou configurações de shell.',
|
|
2389
2427
|
'praxis.pageBuilder.editor.hints.transformerOptions': 'Passe aqui as opções do transformador registrado. Prefira JSON enxuto com os parâmetros realmente usados pelo runtime.',
|
|
2428
|
+
'praxis.pageBuilder.connections.toggle': 'Inspecionar conexões',
|
|
2429
|
+
'praxis.pageBuilder.connections.toggleAria': 'Inspecionar conexões',
|
|
2430
|
+
'praxis.pageBuilder.connections.title': 'Conexões',
|
|
2431
|
+
'praxis.pageBuilder.connections.subtitle': 'Inspecione os links canônicos da composição sem editar o documento da página.',
|
|
2432
|
+
'praxis.pageBuilder.connections.panelAria': 'Visualizador de conexões',
|
|
2433
|
+
'praxis.pageBuilder.connections.summary.widgets': 'Widgets',
|
|
2434
|
+
'praxis.pageBuilder.connections.summary.links': 'Links',
|
|
2435
|
+
'praxis.pageBuilder.connections.summary.conditions': 'Com condição',
|
|
2436
|
+
'praxis.pageBuilder.connections.summary.diagnostics': 'Diagnósticos',
|
|
2437
|
+
'praxis.pageBuilder.connections.filters.title': 'Filtros',
|
|
2438
|
+
'praxis.pageBuilder.connections.filters.all': 'Todos',
|
|
2439
|
+
'praxis.pageBuilder.connections.filters.condition': 'Condition',
|
|
2440
|
+
'praxis.pageBuilder.connections.filters.transform': 'Transform',
|
|
2441
|
+
'praxis.pageBuilder.connections.filters.policy': 'Policy',
|
|
2442
|
+
'praxis.pageBuilder.connections.filters.diagnostic': 'Diagnostic',
|
|
2443
|
+
'praxis.pageBuilder.connections.widgets.title': 'Widgets',
|
|
2444
|
+
'praxis.pageBuilder.connections.widgets.selected': 'Widget selecionado',
|
|
2445
|
+
'praxis.pageBuilder.connections.widgets.incoming': 'Entrada',
|
|
2446
|
+
'praxis.pageBuilder.connections.widgets.outgoing': 'Saída',
|
|
2447
|
+
'praxis.pageBuilder.connections.links.title': 'Links',
|
|
2448
|
+
'praxis.pageBuilder.connections.badges.condition': 'Condition',
|
|
2449
|
+
'praxis.pageBuilder.connections.badges.transform': 'Transform',
|
|
2450
|
+
'praxis.pageBuilder.connections.badges.policy': 'Policy',
|
|
2451
|
+
'praxis.pageBuilder.connections.badges.diagnostic': 'Diagnostic',
|
|
2452
|
+
'praxis.pageBuilder.connections.actions.focusSource': 'Focar origem',
|
|
2453
|
+
'praxis.pageBuilder.connections.actions.focusTarget': 'Focar destino',
|
|
2454
|
+
'praxis.pageBuilder.connections.actions.openPageSettings': 'Abrir configurações da página',
|
|
2455
|
+
'praxis.pageBuilder.connections.details.title': 'Link selecionado',
|
|
2456
|
+
'praxis.pageBuilder.connections.details.widgetId': 'Widget',
|
|
2457
|
+
'praxis.pageBuilder.connections.details.componentType': 'Componente',
|
|
2458
|
+
'praxis.pageBuilder.connections.details.intent': 'Intent',
|
|
2459
|
+
'praxis.pageBuilder.connections.details.from': 'Origem',
|
|
2460
|
+
'praxis.pageBuilder.connections.details.to': 'Destino',
|
|
2461
|
+
'praxis.pageBuilder.connections.details.condition': 'Condition',
|
|
2462
|
+
'praxis.pageBuilder.connections.details.transform': 'Transform',
|
|
2463
|
+
'praxis.pageBuilder.connections.details.policy': 'Policy',
|
|
2464
|
+
'praxis.pageBuilder.connections.details.diagnostics': 'Diagnostics',
|
|
2465
|
+
'praxis.pageBuilder.connections.palette.insertComponent': 'Inserir componente',
|
|
2390
2466
|
};
|
|
2391
2467
|
|
|
2392
2468
|
function createPraxisPageBuilderI18nConfig(options = {}) {
|
|
@@ -2925,7 +3001,9 @@ class PageConfigEditorComponent {
|
|
|
2925
3001
|
}),
|
|
2926
3002
|
sourcePath: new FormControl(sourcePath, { nonNullable: true }),
|
|
2927
3003
|
keysCsv: new FormControl(keysCsv, { nonNullable: true }),
|
|
2928
|
-
expression: new FormControl(compute?.kind === '
|
|
3004
|
+
expression: new FormControl(compute?.kind === 'json-logic'
|
|
3005
|
+
? JSON.stringify(compute.expression ?? {}, null, 2)
|
|
3006
|
+
: '', { nonNullable: true }),
|
|
2929
3007
|
transformerId: new FormControl(compute?.kind === 'transformer' ? compute.transformerId || '' : '', { nonNullable: true }),
|
|
2930
3008
|
options: new FormControl(compute?.kind === 'transformer'
|
|
2931
3009
|
? JSON.stringify(compute.options || {}, null, 2)
|
|
@@ -3007,8 +3085,13 @@ class PageConfigEditorComponent {
|
|
|
3007
3085
|
return null;
|
|
3008
3086
|
compute = { kind: 'template', value: templateValue.value };
|
|
3009
3087
|
}
|
|
3010
|
-
else if (computeKind === '
|
|
3011
|
-
|
|
3088
|
+
else if (computeKind === 'json-logic') {
|
|
3089
|
+
const expression = this.parseJson(group.controls.expression.value, {});
|
|
3090
|
+
if (expression === null
|
|
3091
|
+
|| (typeof expression === 'object' && !Array.isArray(expression) && Object.keys(expression).length === 0)) {
|
|
3092
|
+
return null;
|
|
3093
|
+
}
|
|
3094
|
+
compute = { kind: 'json-logic', expression };
|
|
3012
3095
|
}
|
|
3013
3096
|
else if (computeKind === 'transformer') {
|
|
3014
3097
|
const options = this.parseJson(group.controls.options.value, {});
|
|
@@ -3769,7 +3852,7 @@ class PageConfigEditorComponent {
|
|
|
3769
3852
|
<mat-select formControlName="computeKind">
|
|
3770
3853
|
<mat-option value="operator">{{ tx('editor.state.compute.operator', 'Operator') }}</mat-option>
|
|
3771
3854
|
<mat-option value="template">{{ tx('editor.state.compute.template', 'Template') }}</mat-option>
|
|
3772
|
-
<mat-option value="
|
|
3855
|
+
<mat-option value="json-logic">{{ tx('editor.state.compute.expr', 'Json Logic') }}</mat-option>
|
|
3773
3856
|
<mat-option value="transformer">{{ tx('editor.state.compute.transformer', 'Transformer') }}</mat-option>
|
|
3774
3857
|
</mat-select>
|
|
3775
3858
|
</mat-form-field>
|
|
@@ -3839,10 +3922,10 @@ class PageConfigEditorComponent {
|
|
|
3839
3922
|
</mat-form-field>
|
|
3840
3923
|
}
|
|
3841
3924
|
}
|
|
3842
|
-
@if (group.controls.computeKind.value === '
|
|
3925
|
+
@if (group.controls.computeKind.value === 'json-logic') {
|
|
3843
3926
|
<mat-form-field appearance="outline" class="span-3">
|
|
3844
|
-
<mat-label>{{ tx('editor.state.expression', '
|
|
3845
|
-
<
|
|
3927
|
+
<mat-label>{{ tx('editor.state.expression', 'Json Logic') }}</mat-label>
|
|
3928
|
+
<textarea matInput rows="4" formControlName="expression"></textarea>
|
|
3846
3929
|
</mat-form-field>
|
|
3847
3930
|
}
|
|
3848
3931
|
@if (group.controls.computeKind.value === 'transformer') {
|
|
@@ -3881,7 +3964,7 @@ class PageConfigEditorComponent {
|
|
|
3881
3964
|
</div>
|
|
3882
3965
|
}
|
|
3883
3966
|
</div>
|
|
3884
|
-
`, isInline: true, styles: [".page-config{display:grid;gap:12px;padding:16px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.page-head{display:flex;align-items:flex-start;gap:12px}.page-head__copy{display:grid;gap:4px}.page-title{font-weight:600;font-size:18px;line-height:1.2}.page-subtitle{max-width:72ch;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.spacer{flex:1}.page-summary{display:flex;flex-wrap:wrap;gap:8px}.page-tabs{border-radius:16px;overflow:hidden;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent)}.page-tabs ::ng-deep .mdc-tab{min-width:120px}.page-tabs ::ng-deep .mdc-tab__text-label{font-size:13px;font-weight:600}.page-tab-panel{display:grid;gap:12px;padding:16px 4px 4px}.page-chip{display:inline-flex;align-items:center;gap:8px;min-height:36px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 88%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:500}.page-chip mat-icon{width:18px;height:18px;font-size:18px}.page-chip--accent{border-color:color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 30%,transparent)}.page-chip--warning{border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 35%,transparent)}.page-identity{display:grid;gap:4px;padding:12px 14px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 70%,transparent);font-size:13px;color:var(--md-sys-color-on-surface-variant)}.page-section{font-weight:600;margin-top:8px}.page-section-help{margin-top:-4px;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.grid-form{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.state-grid{display:grid;gap:16px}.state-values,.state-group{padding:14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:14px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-surface-container-low) 92%,transparent),transparent),var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface))}.state-group{display:grid;gap:12px}.state-group-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-group-title{font-weight:600}.state-group-help{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-list{display:grid;gap:12px}.state-card{display:grid;gap:12px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 80%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container) 84%,transparent)}.state-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-card-title{font-weight:600}.state-card-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.span-2{grid-column:span 2}.span-3{grid-column:1 / -1}.state-empty{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-operator-hint{display:flex;align-items:center;gap:8px;min-height:48px;padding:0 12px;border-radius:12px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-secondary-container) 35%,transparent)}.state-operator-hint mat-icon{color:var(--md-sys-color-secondary)}.page-actions{display:flex;justify-content:flex-end}.page-error{color:var(--md-sys-color-error);font-size:13px}.page-config .mat-mdc-form-field{width:100%;--mdc-outlined-text-field-container-height: 48px;--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-outline);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-error-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-focus-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-hover-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-label-text-color: var(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-supporting-text-color: var(--md-sys-color-on-surface-variant)}.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}@media(max-width:720px){.span-2,.span-3{grid-column:auto}.page-head{flex-direction:column}.state-group-head{align-items:stretch;flex-direction:column}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i9.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: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$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: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3967
|
+
`, isInline: true, styles: [".page-config{display:grid;gap:12px;padding:16px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.page-head{display:flex;align-items:flex-start;gap:12px}.page-head__copy{display:grid;gap:4px}.page-title{font-weight:600;font-size:18px;line-height:1.2}.page-subtitle{max-width:72ch;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.spacer{flex:1}.page-summary{display:flex;flex-wrap:wrap;gap:8px}.page-tabs{border-radius:16px;overflow:hidden;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent)}.page-tabs ::ng-deep .mdc-tab{min-width:120px}.page-tabs ::ng-deep .mdc-tab__text-label{font-size:13px;font-weight:600}.page-tab-panel{display:grid;gap:12px;padding:16px 4px 4px}.page-chip{display:inline-flex;align-items:center;gap:8px;min-height:36px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 88%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:500}.page-chip mat-icon{width:18px;height:18px;font-size:18px}.page-chip--accent{border-color:color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 30%,transparent)}.page-chip--warning{border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 35%,transparent)}.page-identity{display:grid;gap:4px;padding:12px 14px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 70%,transparent);font-size:13px;color:var(--md-sys-color-on-surface-variant)}.page-section{font-weight:600;margin-top:8px}.page-section-help{margin-top:-4px;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.grid-form{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.state-grid{display:grid;gap:16px}.state-values,.state-group{padding:14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:14px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-surface-container-low) 92%,transparent),transparent),var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface))}.state-group{display:grid;gap:12px}.state-group-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-group-title{font-weight:600}.state-group-help{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-list{display:grid;gap:12px}.state-card{display:grid;gap:12px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 80%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container) 84%,transparent)}.state-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-card-title{font-weight:600}.state-card-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.span-2{grid-column:span 2}.span-3{grid-column:1 / -1}.state-empty{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-operator-hint{display:flex;align-items:center;gap:8px;min-height:48px;padding:0 12px;border-radius:12px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-secondary-container) 35%,transparent)}.state-operator-hint mat-icon{color:var(--md-sys-color-secondary)}.page-actions{display:flex;justify-content:flex-end}.page-error{color:var(--md-sys-color-error);font-size:13px}.page-config .mat-mdc-form-field{width:100%;--mdc-outlined-text-field-container-height: 48px;--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-outline);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-error-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-focus-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-hover-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-label-text-color: var(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-supporting-text-color: var(--md-sys-color-on-surface-variant)}.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}@media(max-width:720px){.span-2,.span-3{grid-column:auto}.page-head{flex-direction:column}.state-group-head{align-items:stretch;flex-direction:column}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i9.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: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$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: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3885
3968
|
}
|
|
3886
3969
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PageConfigEditorComponent, decorators: [{
|
|
3887
3970
|
type: Component,
|
|
@@ -4401,7 +4484,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
4401
4484
|
<mat-select formControlName="computeKind">
|
|
4402
4485
|
<mat-option value="operator">{{ tx('editor.state.compute.operator', 'Operator') }}</mat-option>
|
|
4403
4486
|
<mat-option value="template">{{ tx('editor.state.compute.template', 'Template') }}</mat-option>
|
|
4404
|
-
<mat-option value="
|
|
4487
|
+
<mat-option value="json-logic">{{ tx('editor.state.compute.expr', 'Json Logic') }}</mat-option>
|
|
4405
4488
|
<mat-option value="transformer">{{ tx('editor.state.compute.transformer', 'Transformer') }}</mat-option>
|
|
4406
4489
|
</mat-select>
|
|
4407
4490
|
</mat-form-field>
|
|
@@ -4471,10 +4554,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
4471
4554
|
</mat-form-field>
|
|
4472
4555
|
}
|
|
4473
4556
|
}
|
|
4474
|
-
@if (group.controls.computeKind.value === '
|
|
4557
|
+
@if (group.controls.computeKind.value === 'json-logic') {
|
|
4475
4558
|
<mat-form-field appearance="outline" class="span-3">
|
|
4476
|
-
<mat-label>{{ tx('editor.state.expression', '
|
|
4477
|
-
<
|
|
4559
|
+
<mat-label>{{ tx('editor.state.expression', 'Json Logic') }}</mat-label>
|
|
4560
|
+
<textarea matInput rows="4" formControlName="expression"></textarea>
|
|
4478
4561
|
</mat-form-field>
|
|
4479
4562
|
}
|
|
4480
4563
|
@if (group.controls.computeKind.value === 'transformer') {
|
|
@@ -4530,8 +4613,9 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
|
|
|
4530
4613
|
'praxis-dynamic-page-builder',
|
|
4531
4614
|
],
|
|
4532
4615
|
notes: [
|
|
4533
|
-
'page segue o modelo canonico WidgetPageDefinition (widgets,
|
|
4616
|
+
'page segue o modelo canonico WidgetPageDefinition (widgets, composition.links, context e state opcional).',
|
|
4534
4617
|
'Canvas e o modelo espacial canonico da pagina quando houver posicionamento explicito.',
|
|
4618
|
+
'Taxonomia editorial: condition usa Json Logic canonico; transform usa pipeline declarativo; policy cobre apenas comportamento operacional.',
|
|
4535
4619
|
'Payloads legados de layout ainda podem ser ingeridos, mas sao normalizados para canvas e nao devem ser reemitidos.',
|
|
4536
4620
|
'pageIdentity identifica o escopo de persistencia e nao pertence ao objeto page.',
|
|
4537
4621
|
],
|
|
@@ -4573,23 +4657,17 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
|
|
|
4573
4657
|
{ path: 'page.widgets[].definition.id', category: 'widgets', valueKind: 'string', description: 'ID do componente registrado.' },
|
|
4574
4658
|
{ path: 'page.widgets[].definition.inputs', category: 'widgets', valueKind: 'object', description: 'Inputs do componente.' },
|
|
4575
4659
|
{ path: 'page.widgets[].definition.bindingOrder', category: 'widgets', valueKind: 'array', description: 'Ordem de aplicacao dos inputs.' },
|
|
4576
|
-
{ path: 'page.
|
|
4577
|
-
{ path: 'page.
|
|
4578
|
-
{ path: 'page.
|
|
4579
|
-
{ path: 'page.
|
|
4580
|
-
{ path: 'page.
|
|
4581
|
-
{ path: 'page.
|
|
4582
|
-
{ path: 'page.
|
|
4583
|
-
{ path: 'page.
|
|
4584
|
-
{ path: 'page.
|
|
4585
|
-
{ path: 'page.
|
|
4586
|
-
{ path: 'page.
|
|
4587
|
-
{ path: 'page.connections[].set', category: 'connections', valueKind: 'object', description: 'Overrides fixos aplicados ao destino.' },
|
|
4588
|
-
{ path: 'page.connections[].meta', category: 'connections', valueKind: 'object', description: 'Metadados opcionais para operadores de runtime.' },
|
|
4589
|
-
{ path: 'page.connections[].meta.filterExpr', category: 'connections', valueKind: 'expression', description: 'Expressao de filtro para eventos.' },
|
|
4590
|
-
{ path: 'page.connections[].meta.debounceMs', category: 'connections', valueKind: 'number', description: 'Debounce em milissegundos.' },
|
|
4591
|
-
{ path: 'page.connections[].meta.distinct', category: 'connections', valueKind: 'boolean', description: 'Emite apenas quando valor mudar.' },
|
|
4592
|
-
{ path: 'page.connections[].meta.distinctBy', category: 'connections', valueKind: 'expression', description: 'Chave para comparacao distinct.' },
|
|
4660
|
+
{ path: 'page.composition', category: 'connections', valueKind: 'object', description: 'Envelope canonico da composicao persistida.' },
|
|
4661
|
+
{ path: 'page.composition.version', category: 'connections', valueKind: 'string', description: 'Versao do envelope de composicao.' },
|
|
4662
|
+
{ path: 'page.composition.links', category: 'connections', valueKind: 'array', description: 'Links canonicos entre widgets e estado.' },
|
|
4663
|
+
{ path: 'page.composition.links[].id', category: 'connections', valueKind: 'string', description: 'Identificador estavel do link.' },
|
|
4664
|
+
{ path: 'page.composition.links[].from', category: 'connections', valueKind: 'object', description: 'Endpoint de origem do link.' },
|
|
4665
|
+
{ path: 'page.composition.links[].to', category: 'connections', valueKind: 'object', description: 'Endpoint de destino do link.' },
|
|
4666
|
+
{ path: 'page.composition.links[].intent', category: 'connections', valueKind: 'string', description: 'Intencao semantica do link.' },
|
|
4667
|
+
{ path: 'page.composition.links[].transform', category: 'connections', valueKind: 'object', description: 'Pipeline de transformacao do link.' },
|
|
4668
|
+
{ path: 'page.composition.links[].condition', category: 'connections', valueKind: 'expression', description: 'Guarda semantica opcional do link, expressa como um unico AST Json Logic canonico.' },
|
|
4669
|
+
{ path: 'page.composition.links[].policy', category: 'connections', valueKind: 'object', description: 'Politicas operacionais opcionais do link, separadas da condition semantica.' },
|
|
4670
|
+
{ path: 'page.composition.links[].metadata', category: 'connections', valueKind: 'object', description: 'Metadados opcionais do link.' },
|
|
4593
4671
|
{ path: 'page.context', category: 'context', valueKind: 'object', description: 'Contexto da pagina (compartilhado por widgets).' },
|
|
4594
4672
|
],
|
|
4595
4673
|
};
|
|
@@ -4747,9 +4825,501 @@ function providePageBuilderWidgetAiCatalogs() {
|
|
|
4747
4825
|
};
|
|
4748
4826
|
}
|
|
4749
4827
|
|
|
4828
|
+
function buildConnectionsViewerModel(page) {
|
|
4829
|
+
const widgets = page?.widgets ?? [];
|
|
4830
|
+
const links = page?.composition?.links ?? [];
|
|
4831
|
+
const counts = new Map();
|
|
4832
|
+
for (const widget of widgets) {
|
|
4833
|
+
counts.set(widget.key, { incoming: 0, outgoing: 0 });
|
|
4834
|
+
}
|
|
4835
|
+
const edges = links.map((link) => {
|
|
4836
|
+
const fromWidgetId = link.from.kind === 'component-port' ? link.from.ref.widget : null;
|
|
4837
|
+
const toWidgetId = link.to.kind === 'component-port' ? link.to.ref.widget : null;
|
|
4838
|
+
const toStatePath = link.to.kind === 'state' ? link.to.ref.path : null;
|
|
4839
|
+
const diagnosticReasons = [];
|
|
4840
|
+
if (fromWidgetId && !counts.has(fromWidgetId)) {
|
|
4841
|
+
diagnosticReasons.push('missing-source-widget');
|
|
4842
|
+
}
|
|
4843
|
+
if (toWidgetId && !counts.has(toWidgetId)) {
|
|
4844
|
+
diagnosticReasons.push('missing-target-widget');
|
|
4845
|
+
}
|
|
4846
|
+
if (fromWidgetId) {
|
|
4847
|
+
const current = counts.get(fromWidgetId) ?? { incoming: 0, outgoing: 0 };
|
|
4848
|
+
current.outgoing += 1;
|
|
4849
|
+
counts.set(fromWidgetId, current);
|
|
4850
|
+
}
|
|
4851
|
+
if (toWidgetId) {
|
|
4852
|
+
const current = counts.get(toWidgetId) ?? { incoming: 0, outgoing: 0 };
|
|
4853
|
+
current.incoming += 1;
|
|
4854
|
+
counts.set(toWidgetId, current);
|
|
4855
|
+
}
|
|
4856
|
+
return {
|
|
4857
|
+
id: link.id,
|
|
4858
|
+
fromKind: link.from.kind,
|
|
4859
|
+
fromWidgetId,
|
|
4860
|
+
fromPort: link.from.kind === 'component-port' ? link.from.ref.port : null,
|
|
4861
|
+
toKind: link.to.kind,
|
|
4862
|
+
toWidgetId,
|
|
4863
|
+
toPort: link.to.kind === 'component-port' ? link.to.ref.port : null,
|
|
4864
|
+
toStatePath,
|
|
4865
|
+
intent: link.intent,
|
|
4866
|
+
hasCondition: !!link.condition,
|
|
4867
|
+
hasTransform: !!link.transform?.steps?.length,
|
|
4868
|
+
hasPolicy: !!link.policy && Object.keys(link.policy).length > 0,
|
|
4869
|
+
hasDiagnostics: diagnosticReasons.length > 0,
|
|
4870
|
+
diagnosticReasons,
|
|
4871
|
+
link,
|
|
4872
|
+
};
|
|
4873
|
+
});
|
|
4874
|
+
const nodes = widgets.map((widget) => {
|
|
4875
|
+
const counter = counts.get(widget.key) ?? { incoming: 0, outgoing: 0 };
|
|
4876
|
+
return {
|
|
4877
|
+
widgetId: widget.key,
|
|
4878
|
+
componentType: widget.definition?.id ?? 'unknown',
|
|
4879
|
+
incomingCount: counter.incoming,
|
|
4880
|
+
outgoingCount: counter.outgoing,
|
|
4881
|
+
};
|
|
4882
|
+
});
|
|
4883
|
+
return {
|
|
4884
|
+
nodes,
|
|
4885
|
+
edges,
|
|
4886
|
+
totalLinks: edges.length,
|
|
4887
|
+
conditionLinks: edges.filter((edge) => edge.hasCondition).length,
|
|
4888
|
+
transformLinks: edges.filter((edge) => edge.hasTransform).length,
|
|
4889
|
+
policyLinks: edges.filter((edge) => edge.hasPolicy).length,
|
|
4890
|
+
diagnosticLinks: edges.filter((edge) => edge.hasDiagnostics).length,
|
|
4891
|
+
};
|
|
4892
|
+
}
|
|
4893
|
+
|
|
4894
|
+
class ConnectionsViewerPanelComponent {
|
|
4895
|
+
i18n = inject(PraxisI18nService);
|
|
4896
|
+
open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
4897
|
+
page = input(undefined, ...(ngDevMode ? [{ debugName: "page" }] : []));
|
|
4898
|
+
focusWidget = output();
|
|
4899
|
+
openPageSettings = output();
|
|
4900
|
+
filters = [
|
|
4901
|
+
{ id: 'all', label: this.tx('connections.filters.all', 'All') },
|
|
4902
|
+
{ id: 'condition', label: this.tx('connections.filters.condition', 'Condition') },
|
|
4903
|
+
{ id: 'transform', label: this.tx('connections.filters.transform', 'Transform') },
|
|
4904
|
+
{ id: 'policy', label: this.tx('connections.filters.policy', 'Policy') },
|
|
4905
|
+
{ id: 'diagnostic', label: this.tx('connections.filters.diagnostic', 'Diagnostic') },
|
|
4906
|
+
];
|
|
4907
|
+
activeFilter = signal('all', ...(ngDevMode ? [{ debugName: "activeFilter" }] : []));
|
|
4908
|
+
selectedWidgetId = signal(null, ...(ngDevMode ? [{ debugName: "selectedWidgetId" }] : []));
|
|
4909
|
+
selectedLinkId = signal(null, ...(ngDevMode ? [{ debugName: "selectedLinkId" }] : []));
|
|
4910
|
+
model = computed(() => buildConnectionsViewerModel(this.page()), ...(ngDevMode ? [{ debugName: "model" }] : []));
|
|
4911
|
+
selectedNode = computed(() => this.model().nodes.find((node) => node.widgetId === this.selectedWidgetId()) ?? null, ...(ngDevMode ? [{ debugName: "selectedNode" }] : []));
|
|
4912
|
+
visibleEdges = computed(() => {
|
|
4913
|
+
const widgetId = this.selectedWidgetId();
|
|
4914
|
+
const filter = this.activeFilter();
|
|
4915
|
+
let edges = this.model().edges;
|
|
4916
|
+
if (widgetId) {
|
|
4917
|
+
edges = edges.filter((edge) => edge.fromWidgetId === widgetId || edge.toWidgetId === widgetId);
|
|
4918
|
+
}
|
|
4919
|
+
if (filter === 'condition') {
|
|
4920
|
+
edges = edges.filter((edge) => edge.hasCondition);
|
|
4921
|
+
}
|
|
4922
|
+
else if (filter === 'transform') {
|
|
4923
|
+
edges = edges.filter((edge) => edge.hasTransform);
|
|
4924
|
+
}
|
|
4925
|
+
else if (filter === 'policy') {
|
|
4926
|
+
edges = edges.filter((edge) => edge.hasPolicy);
|
|
4927
|
+
}
|
|
4928
|
+
else if (filter === 'diagnostic') {
|
|
4929
|
+
edges = edges.filter((edge) => edge.hasDiagnostics);
|
|
4930
|
+
}
|
|
4931
|
+
return edges;
|
|
4932
|
+
}, ...(ngDevMode ? [{ debugName: "visibleEdges" }] : []));
|
|
4933
|
+
selectedEdge = computed(() => this.model().edges.find((edge) => edge.id === this.selectedLinkId()) ?? null, ...(ngDevMode ? [{ debugName: "selectedEdge" }] : []));
|
|
4934
|
+
selectWidget(node) {
|
|
4935
|
+
this.selectedWidgetId.update((current) => (current === node.widgetId ? null : node.widgetId));
|
|
4936
|
+
this.selectedLinkId.set(null);
|
|
4937
|
+
}
|
|
4938
|
+
selectLink(edge) {
|
|
4939
|
+
this.selectedLinkId.update((current) => (current === edge.id ? null : edge.id));
|
|
4940
|
+
}
|
|
4941
|
+
setFilter(filter) {
|
|
4942
|
+
this.activeFilter.set(filter);
|
|
4943
|
+
this.selectedLinkId.set(null);
|
|
4944
|
+
}
|
|
4945
|
+
describeEdge(edge) {
|
|
4946
|
+
return `${this.describeSource(edge)} -> ${this.describeTarget(edge)}`;
|
|
4947
|
+
}
|
|
4948
|
+
describeSource(edge) {
|
|
4949
|
+
if (edge.fromKind === 'component-port') {
|
|
4950
|
+
return `${edge.fromWidgetId}.${edge.fromPort}`;
|
|
4951
|
+
}
|
|
4952
|
+
return edge.fromKind;
|
|
4953
|
+
}
|
|
4954
|
+
describeTarget(edge) {
|
|
4955
|
+
if (edge.toKind === 'component-port') {
|
|
4956
|
+
return `${edge.toWidgetId}.${edge.toPort}`;
|
|
4957
|
+
}
|
|
4958
|
+
return `state.${edge.toStatePath}`;
|
|
4959
|
+
}
|
|
4960
|
+
tx(key, fallback) {
|
|
4961
|
+
return resolvePraxisPageBuilderText(this.i18n, key, fallback);
|
|
4962
|
+
}
|
|
4963
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ConnectionsViewerPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4964
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.17", type: ConnectionsViewerPanelComponent, isStandalone: true, selector: "praxis-connections-viewer-panel", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { focusWidget: "focusWidget", openPageSettings: "openPageSettings" }, providers: [providePraxisPageBuilderI18n()], ngImport: i0, template: `
|
|
4965
|
+
<aside
|
|
4966
|
+
*ngIf="open()"
|
|
4967
|
+
class="connections-panel"
|
|
4968
|
+
data-testid="page-builder-connections-panel"
|
|
4969
|
+
[attr.aria-label]="tx('connections.panelAria', 'Connections viewer')"
|
|
4970
|
+
>
|
|
4971
|
+
<div class="connections-panel__header">
|
|
4972
|
+
<div class="connections-panel__title">{{ tx('connections.title', 'Connections') }}</div>
|
|
4973
|
+
<div class="connections-panel__subtitle">
|
|
4974
|
+
{{ tx('connections.subtitle', 'Inspect the canonical composition links without editing the page document.') }}
|
|
4975
|
+
</div>
|
|
4976
|
+
</div>
|
|
4977
|
+
|
|
4978
|
+
<div class="connections-panel__summary">
|
|
4979
|
+
<div class="connections-panel__metric">
|
|
4980
|
+
<span>{{ tx('connections.summary.widgets', 'Widgets') }}</span>
|
|
4981
|
+
<strong>{{ model().nodes.length }}</strong>
|
|
4982
|
+
</div>
|
|
4983
|
+
<div class="connections-panel__metric">
|
|
4984
|
+
<span>{{ tx('connections.summary.links', 'Links') }}</span>
|
|
4985
|
+
<strong>{{ model().totalLinks }}</strong>
|
|
4986
|
+
</div>
|
|
4987
|
+
<div class="connections-panel__metric">
|
|
4988
|
+
<span>{{ tx('connections.summary.conditions', 'With condition') }}</span>
|
|
4989
|
+
<strong>{{ model().conditionLinks }}</strong>
|
|
4990
|
+
</div>
|
|
4991
|
+
<div class="connections-panel__metric">
|
|
4992
|
+
<span>{{ tx('connections.summary.diagnostics', 'Diagnostics') }}</span>
|
|
4993
|
+
<strong>{{ model().diagnosticLinks }}</strong>
|
|
4994
|
+
</div>
|
|
4995
|
+
</div>
|
|
4996
|
+
|
|
4997
|
+
<section class="connections-panel__section">
|
|
4998
|
+
<div class="connections-panel__section-title">{{ tx('connections.filters.title', 'Filters') }}</div>
|
|
4999
|
+
<div class="connections-panel__filters">
|
|
5000
|
+
<button
|
|
5001
|
+
*ngFor="let filter of filters"
|
|
5002
|
+
type="button"
|
|
5003
|
+
class="connections-panel__filter"
|
|
5004
|
+
[class.connections-panel__filter--active]="activeFilter() === filter.id"
|
|
5005
|
+
[attr.data-testid]="'page-builder-connections-filter-' + filter.id"
|
|
5006
|
+
(click)="setFilter(filter.id)"
|
|
5007
|
+
>
|
|
5008
|
+
{{ filter.label }}
|
|
5009
|
+
</button>
|
|
5010
|
+
</div>
|
|
5011
|
+
</section>
|
|
5012
|
+
|
|
5013
|
+
<section class="connections-panel__section">
|
|
5014
|
+
<div class="connections-panel__section-title">{{ tx('connections.widgets.title', 'Widgets') }}</div>
|
|
5015
|
+
<button
|
|
5016
|
+
*ngFor="let node of model().nodes"
|
|
5017
|
+
type="button"
|
|
5018
|
+
[attr.data-testid]="'page-builder-connections-widget-' + node.widgetId"
|
|
5019
|
+
class="connections-panel__item"
|
|
5020
|
+
[class.connections-panel__item--active]="selectedWidgetId() === node.widgetId"
|
|
5021
|
+
(click)="selectWidget(node)"
|
|
5022
|
+
>
|
|
5023
|
+
<div class="connections-panel__item-title">{{ node.widgetId }}</div>
|
|
5024
|
+
<div class="connections-panel__item-copy">{{ node.componentType }}</div>
|
|
5025
|
+
<div class="connections-panel__item-meta">
|
|
5026
|
+
{{ tx('connections.widgets.incoming', 'In') }} {{ node.incomingCount }}
|
|
5027
|
+
|
|
|
5028
|
+
{{ tx('connections.widgets.outgoing', 'Out') }} {{ node.outgoingCount }}
|
|
5029
|
+
</div>
|
|
5030
|
+
</button>
|
|
5031
|
+
</section>
|
|
5032
|
+
|
|
5033
|
+
<section class="connections-panel__section" *ngIf="selectedNode() as node">
|
|
5034
|
+
<div class="connections-panel__section-title">{{ tx('connections.widgets.selected', 'Selected widget') }}</div>
|
|
5035
|
+
<div class="connections-panel__details-row" data-testid="page-builder-connections-selected-widget">
|
|
5036
|
+
<span>{{ tx('connections.details.widgetId', 'Widget') }}</span>
|
|
5037
|
+
<strong>{{ node.widgetId }}</strong>
|
|
5038
|
+
</div>
|
|
5039
|
+
<div class="connections-panel__details-row">
|
|
5040
|
+
<span>{{ tx('connections.details.componentType', 'Component') }}</span>
|
|
5041
|
+
<strong>{{ node.componentType }}</strong>
|
|
5042
|
+
</div>
|
|
5043
|
+
</section>
|
|
5044
|
+
|
|
5045
|
+
<section class="connections-panel__section">
|
|
5046
|
+
<div class="connections-panel__section-title">{{ tx('connections.links.title', 'Links') }}</div>
|
|
5047
|
+
<button
|
|
5048
|
+
*ngFor="let edge of visibleEdges()"
|
|
5049
|
+
type="button"
|
|
5050
|
+
[attr.data-testid]="'page-builder-connections-link-' + edge.id"
|
|
5051
|
+
class="connections-panel__item"
|
|
5052
|
+
[class.connections-panel__item--active]="selectedLinkId() === edge.id"
|
|
5053
|
+
(click)="selectLink(edge)"
|
|
5054
|
+
>
|
|
5055
|
+
<div class="connections-panel__item-title">{{ edge.id }}</div>
|
|
5056
|
+
<div class="connections-panel__item-copy">{{ describeEdge(edge) }}</div>
|
|
5057
|
+
<div class="connections-panel__badges">
|
|
5058
|
+
<span class="connections-panel__badge" *ngIf="edge.hasCondition">
|
|
5059
|
+
{{ tx('connections.badges.condition', 'Condition') }}
|
|
5060
|
+
</span>
|
|
5061
|
+
<span class="connections-panel__badge" *ngIf="edge.hasTransform">
|
|
5062
|
+
{{ tx('connections.badges.transform', 'Transform') }}
|
|
5063
|
+
</span>
|
|
5064
|
+
<span class="connections-panel__badge" *ngIf="edge.hasPolicy">
|
|
5065
|
+
{{ tx('connections.badges.policy', 'Policy') }}
|
|
5066
|
+
</span>
|
|
5067
|
+
<span class="connections-panel__badge connections-panel__badge--warning" *ngIf="edge.hasDiagnostics">
|
|
5068
|
+
{{ tx('connections.badges.diagnostic', 'Diagnostic') }}
|
|
5069
|
+
</span>
|
|
5070
|
+
</div>
|
|
5071
|
+
</button>
|
|
5072
|
+
</section>
|
|
5073
|
+
|
|
5074
|
+
<section
|
|
5075
|
+
class="connections-panel__section"
|
|
5076
|
+
*ngIf="selectedEdge() as edge"
|
|
5077
|
+
data-testid="page-builder-connections-link-details"
|
|
5078
|
+
>
|
|
5079
|
+
<div class="connections-panel__section-title">{{ tx('connections.details.title', 'Selected link') }}</div>
|
|
5080
|
+
<div class="connections-panel__details-row">
|
|
5081
|
+
<span>{{ tx('connections.details.intent', 'Intent') }}</span>
|
|
5082
|
+
<strong>{{ edge.intent }}</strong>
|
|
5083
|
+
</div>
|
|
5084
|
+
<div class="connections-panel__details-row">
|
|
5085
|
+
<span>{{ tx('connections.details.from', 'From') }}</span>
|
|
5086
|
+
<strong>{{ describeSource(edge) }}</strong>
|
|
5087
|
+
</div>
|
|
5088
|
+
<div class="connections-panel__details-row">
|
|
5089
|
+
<span>{{ tx('connections.details.to', 'To') }}</span>
|
|
5090
|
+
<strong>{{ describeTarget(edge) }}</strong>
|
|
5091
|
+
</div>
|
|
5092
|
+
<div class="connections-panel__actions">
|
|
5093
|
+
<button
|
|
5094
|
+
*ngIf="edge.fromWidgetId"
|
|
5095
|
+
type="button"
|
|
5096
|
+
class="connections-panel__action"
|
|
5097
|
+
data-testid="page-builder-connections-focus-source"
|
|
5098
|
+
(click)="focusWidget.emit(edge.fromWidgetId)"
|
|
5099
|
+
>
|
|
5100
|
+
{{ tx('connections.actions.focusSource', 'Focus source') }}
|
|
5101
|
+
</button>
|
|
5102
|
+
<button
|
|
5103
|
+
*ngIf="edge.toWidgetId"
|
|
5104
|
+
type="button"
|
|
5105
|
+
class="connections-panel__action"
|
|
5106
|
+
data-testid="page-builder-connections-focus-target"
|
|
5107
|
+
(click)="focusWidget.emit(edge.toWidgetId)"
|
|
5108
|
+
>
|
|
5109
|
+
{{ tx('connections.actions.focusTarget', 'Focus target') }}
|
|
5110
|
+
</button>
|
|
5111
|
+
<button
|
|
5112
|
+
type="button"
|
|
5113
|
+
class="connections-panel__action"
|
|
5114
|
+
data-testid="page-builder-connections-open-page-settings"
|
|
5115
|
+
(click)="openPageSettings.emit()"
|
|
5116
|
+
>
|
|
5117
|
+
{{ tx('connections.actions.openPageSettings', 'Open page settings') }}
|
|
5118
|
+
</button>
|
|
5119
|
+
</div>
|
|
5120
|
+
<div class="connections-panel__details-block" *ngIf="edge.link.condition">
|
|
5121
|
+
<div class="connections-panel__details-label">{{ tx('connections.details.condition', 'Condition') }}</div>
|
|
5122
|
+
<pre>{{ edge.link.condition | json }}</pre>
|
|
5123
|
+
</div>
|
|
5124
|
+
<div class="connections-panel__details-block" *ngIf="edge.link.transform?.steps?.length">
|
|
5125
|
+
<div class="connections-panel__details-label">{{ tx('connections.details.transform', 'Transform') }}</div>
|
|
5126
|
+
<pre>{{ edge.link.transform | json }}</pre>
|
|
5127
|
+
</div>
|
|
5128
|
+
<div class="connections-panel__details-block" *ngIf="edge.link.policy">
|
|
5129
|
+
<div class="connections-panel__details-label">{{ tx('connections.details.policy', 'Policy') }}</div>
|
|
5130
|
+
<pre>{{ edge.link.policy | json }}</pre>
|
|
5131
|
+
</div>
|
|
5132
|
+
<div class="connections-panel__details-block" *ngIf="edge.hasDiagnostics">
|
|
5133
|
+
<div class="connections-panel__details-label">{{ tx('connections.details.diagnostics', 'Diagnostics') }}</div>
|
|
5134
|
+
<pre>{{ edge.diagnosticReasons | json }}</pre>
|
|
5135
|
+
</div>
|
|
5136
|
+
</section>
|
|
5137
|
+
</aside>
|
|
5138
|
+
`, isInline: true, styles: [":host{position:absolute;inset-block:16px;inset-inline-end:16px;z-index:4;pointer-events:none}.connections-panel{width:min(420px,calc(100vw - 32px));max-height:calc(100vh - 32px);overflow:auto;padding:16px;border-radius:18px;background:#fffffffa;border:1px solid rgba(15,23,42,.08);box-shadow:0 20px 44px #0f172a2e;pointer-events:auto;display:grid;gap:16px}.connections-panel__header,.connections-panel__summary,.connections-panel__section{display:grid;gap:10px}.connections-panel__title{font-size:1rem;font-weight:700;color:#0f172a}.connections-panel__subtitle,.connections-panel__item-copy,.connections-panel__item-meta,.connections-panel__details-row span,.connections-panel__details-label{color:#475569;font-size:.86rem}.connections-panel__summary{grid-template-columns:repeat(4,minmax(0,1fr))}.connections-panel__metric{padding:12px;border-radius:12px;background:#f8fafc;border:1px solid #e2e8f0;display:grid;gap:4px}.connections-panel__metric strong,.connections-panel__details-row strong{color:#0f172a;font-size:.92rem}.connections-panel__section-title{font-size:.78rem;text-transform:uppercase;letter-spacing:.08em;color:#64748b;font-weight:700}.connections-panel__item{text-align:start;padding:12px;border-radius:12px;border:1px solid #e2e8f0;background:#fff;display:grid;gap:6px;cursor:pointer}.connections-panel__item--active{border-color:#2563eb;box-shadow:0 0 0 1px #2563eb1f;background:#eff6ff}.connections-panel__item-title{font-weight:700;color:#0f172a;word-break:break-word}.connections-panel__badges{display:flex;flex-wrap:wrap;gap:6px}.connections-panel__filters,.connections-panel__actions{display:flex;gap:8px;flex-wrap:wrap}.connections-panel__filter{border:1px solid #cbd5e1;background:#fff;color:#334155;border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connections-panel__filter--active{border-color:#2563eb;background:#dbeafe;color:#1d4ed8}.connections-panel__action{border:1px solid #cbd5e1;background:#fff;color:#334155;border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connections-panel__action:hover{border-color:#2563eb;color:#1d4ed8}.connections-panel__badge{padding:3px 8px;border-radius:999px;background:#dbeafe;color:#1d4ed8;font-size:.75rem;font-weight:700}.connections-panel__badge--warning{background:#fef3c7;color:#b45309}.connections-panel__details-row,.connections-panel__details-block{display:grid;gap:6px}pre{margin:0;padding:12px;border-radius:12px;background:#0f172a;color:#e2e8f0;overflow:auto;font-size:.75rem}@media(max-width:900px){:host{inset:auto 12px 88px}.connections-panel{width:auto;max-height:min(60vh,520px)}.connections-panel__summary{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2$1.JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5139
|
+
}
|
|
5140
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ConnectionsViewerPanelComponent, decorators: [{
|
|
5141
|
+
type: Component,
|
|
5142
|
+
args: [{ selector: 'praxis-connections-viewer-panel', standalone: true, imports: [CommonModule], providers: [providePraxisPageBuilderI18n()], template: `
|
|
5143
|
+
<aside
|
|
5144
|
+
*ngIf="open()"
|
|
5145
|
+
class="connections-panel"
|
|
5146
|
+
data-testid="page-builder-connections-panel"
|
|
5147
|
+
[attr.aria-label]="tx('connections.panelAria', 'Connections viewer')"
|
|
5148
|
+
>
|
|
5149
|
+
<div class="connections-panel__header">
|
|
5150
|
+
<div class="connections-panel__title">{{ tx('connections.title', 'Connections') }}</div>
|
|
5151
|
+
<div class="connections-panel__subtitle">
|
|
5152
|
+
{{ tx('connections.subtitle', 'Inspect the canonical composition links without editing the page document.') }}
|
|
5153
|
+
</div>
|
|
5154
|
+
</div>
|
|
5155
|
+
|
|
5156
|
+
<div class="connections-panel__summary">
|
|
5157
|
+
<div class="connections-panel__metric">
|
|
5158
|
+
<span>{{ tx('connections.summary.widgets', 'Widgets') }}</span>
|
|
5159
|
+
<strong>{{ model().nodes.length }}</strong>
|
|
5160
|
+
</div>
|
|
5161
|
+
<div class="connections-panel__metric">
|
|
5162
|
+
<span>{{ tx('connections.summary.links', 'Links') }}</span>
|
|
5163
|
+
<strong>{{ model().totalLinks }}</strong>
|
|
5164
|
+
</div>
|
|
5165
|
+
<div class="connections-panel__metric">
|
|
5166
|
+
<span>{{ tx('connections.summary.conditions', 'With condition') }}</span>
|
|
5167
|
+
<strong>{{ model().conditionLinks }}</strong>
|
|
5168
|
+
</div>
|
|
5169
|
+
<div class="connections-panel__metric">
|
|
5170
|
+
<span>{{ tx('connections.summary.diagnostics', 'Diagnostics') }}</span>
|
|
5171
|
+
<strong>{{ model().diagnosticLinks }}</strong>
|
|
5172
|
+
</div>
|
|
5173
|
+
</div>
|
|
5174
|
+
|
|
5175
|
+
<section class="connections-panel__section">
|
|
5176
|
+
<div class="connections-panel__section-title">{{ tx('connections.filters.title', 'Filters') }}</div>
|
|
5177
|
+
<div class="connections-panel__filters">
|
|
5178
|
+
<button
|
|
5179
|
+
*ngFor="let filter of filters"
|
|
5180
|
+
type="button"
|
|
5181
|
+
class="connections-panel__filter"
|
|
5182
|
+
[class.connections-panel__filter--active]="activeFilter() === filter.id"
|
|
5183
|
+
[attr.data-testid]="'page-builder-connections-filter-' + filter.id"
|
|
5184
|
+
(click)="setFilter(filter.id)"
|
|
5185
|
+
>
|
|
5186
|
+
{{ filter.label }}
|
|
5187
|
+
</button>
|
|
5188
|
+
</div>
|
|
5189
|
+
</section>
|
|
5190
|
+
|
|
5191
|
+
<section class="connections-panel__section">
|
|
5192
|
+
<div class="connections-panel__section-title">{{ tx('connections.widgets.title', 'Widgets') }}</div>
|
|
5193
|
+
<button
|
|
5194
|
+
*ngFor="let node of model().nodes"
|
|
5195
|
+
type="button"
|
|
5196
|
+
[attr.data-testid]="'page-builder-connections-widget-' + node.widgetId"
|
|
5197
|
+
class="connections-panel__item"
|
|
5198
|
+
[class.connections-panel__item--active]="selectedWidgetId() === node.widgetId"
|
|
5199
|
+
(click)="selectWidget(node)"
|
|
5200
|
+
>
|
|
5201
|
+
<div class="connections-panel__item-title">{{ node.widgetId }}</div>
|
|
5202
|
+
<div class="connections-panel__item-copy">{{ node.componentType }}</div>
|
|
5203
|
+
<div class="connections-panel__item-meta">
|
|
5204
|
+
{{ tx('connections.widgets.incoming', 'In') }} {{ node.incomingCount }}
|
|
5205
|
+
|
|
|
5206
|
+
{{ tx('connections.widgets.outgoing', 'Out') }} {{ node.outgoingCount }}
|
|
5207
|
+
</div>
|
|
5208
|
+
</button>
|
|
5209
|
+
</section>
|
|
5210
|
+
|
|
5211
|
+
<section class="connections-panel__section" *ngIf="selectedNode() as node">
|
|
5212
|
+
<div class="connections-panel__section-title">{{ tx('connections.widgets.selected', 'Selected widget') }}</div>
|
|
5213
|
+
<div class="connections-panel__details-row" data-testid="page-builder-connections-selected-widget">
|
|
5214
|
+
<span>{{ tx('connections.details.widgetId', 'Widget') }}</span>
|
|
5215
|
+
<strong>{{ node.widgetId }}</strong>
|
|
5216
|
+
</div>
|
|
5217
|
+
<div class="connections-panel__details-row">
|
|
5218
|
+
<span>{{ tx('connections.details.componentType', 'Component') }}</span>
|
|
5219
|
+
<strong>{{ node.componentType }}</strong>
|
|
5220
|
+
</div>
|
|
5221
|
+
</section>
|
|
5222
|
+
|
|
5223
|
+
<section class="connections-panel__section">
|
|
5224
|
+
<div class="connections-panel__section-title">{{ tx('connections.links.title', 'Links') }}</div>
|
|
5225
|
+
<button
|
|
5226
|
+
*ngFor="let edge of visibleEdges()"
|
|
5227
|
+
type="button"
|
|
5228
|
+
[attr.data-testid]="'page-builder-connections-link-' + edge.id"
|
|
5229
|
+
class="connections-panel__item"
|
|
5230
|
+
[class.connections-panel__item--active]="selectedLinkId() === edge.id"
|
|
5231
|
+
(click)="selectLink(edge)"
|
|
5232
|
+
>
|
|
5233
|
+
<div class="connections-panel__item-title">{{ edge.id }}</div>
|
|
5234
|
+
<div class="connections-panel__item-copy">{{ describeEdge(edge) }}</div>
|
|
5235
|
+
<div class="connections-panel__badges">
|
|
5236
|
+
<span class="connections-panel__badge" *ngIf="edge.hasCondition">
|
|
5237
|
+
{{ tx('connections.badges.condition', 'Condition') }}
|
|
5238
|
+
</span>
|
|
5239
|
+
<span class="connections-panel__badge" *ngIf="edge.hasTransform">
|
|
5240
|
+
{{ tx('connections.badges.transform', 'Transform') }}
|
|
5241
|
+
</span>
|
|
5242
|
+
<span class="connections-panel__badge" *ngIf="edge.hasPolicy">
|
|
5243
|
+
{{ tx('connections.badges.policy', 'Policy') }}
|
|
5244
|
+
</span>
|
|
5245
|
+
<span class="connections-panel__badge connections-panel__badge--warning" *ngIf="edge.hasDiagnostics">
|
|
5246
|
+
{{ tx('connections.badges.diagnostic', 'Diagnostic') }}
|
|
5247
|
+
</span>
|
|
5248
|
+
</div>
|
|
5249
|
+
</button>
|
|
5250
|
+
</section>
|
|
5251
|
+
|
|
5252
|
+
<section
|
|
5253
|
+
class="connections-panel__section"
|
|
5254
|
+
*ngIf="selectedEdge() as edge"
|
|
5255
|
+
data-testid="page-builder-connections-link-details"
|
|
5256
|
+
>
|
|
5257
|
+
<div class="connections-panel__section-title">{{ tx('connections.details.title', 'Selected link') }}</div>
|
|
5258
|
+
<div class="connections-panel__details-row">
|
|
5259
|
+
<span>{{ tx('connections.details.intent', 'Intent') }}</span>
|
|
5260
|
+
<strong>{{ edge.intent }}</strong>
|
|
5261
|
+
</div>
|
|
5262
|
+
<div class="connections-panel__details-row">
|
|
5263
|
+
<span>{{ tx('connections.details.from', 'From') }}</span>
|
|
5264
|
+
<strong>{{ describeSource(edge) }}</strong>
|
|
5265
|
+
</div>
|
|
5266
|
+
<div class="connections-panel__details-row">
|
|
5267
|
+
<span>{{ tx('connections.details.to', 'To') }}</span>
|
|
5268
|
+
<strong>{{ describeTarget(edge) }}</strong>
|
|
5269
|
+
</div>
|
|
5270
|
+
<div class="connections-panel__actions">
|
|
5271
|
+
<button
|
|
5272
|
+
*ngIf="edge.fromWidgetId"
|
|
5273
|
+
type="button"
|
|
5274
|
+
class="connections-panel__action"
|
|
5275
|
+
data-testid="page-builder-connections-focus-source"
|
|
5276
|
+
(click)="focusWidget.emit(edge.fromWidgetId)"
|
|
5277
|
+
>
|
|
5278
|
+
{{ tx('connections.actions.focusSource', 'Focus source') }}
|
|
5279
|
+
</button>
|
|
5280
|
+
<button
|
|
5281
|
+
*ngIf="edge.toWidgetId"
|
|
5282
|
+
type="button"
|
|
5283
|
+
class="connections-panel__action"
|
|
5284
|
+
data-testid="page-builder-connections-focus-target"
|
|
5285
|
+
(click)="focusWidget.emit(edge.toWidgetId)"
|
|
5286
|
+
>
|
|
5287
|
+
{{ tx('connections.actions.focusTarget', 'Focus target') }}
|
|
5288
|
+
</button>
|
|
5289
|
+
<button
|
|
5290
|
+
type="button"
|
|
5291
|
+
class="connections-panel__action"
|
|
5292
|
+
data-testid="page-builder-connections-open-page-settings"
|
|
5293
|
+
(click)="openPageSettings.emit()"
|
|
5294
|
+
>
|
|
5295
|
+
{{ tx('connections.actions.openPageSettings', 'Open page settings') }}
|
|
5296
|
+
</button>
|
|
5297
|
+
</div>
|
|
5298
|
+
<div class="connections-panel__details-block" *ngIf="edge.link.condition">
|
|
5299
|
+
<div class="connections-panel__details-label">{{ tx('connections.details.condition', 'Condition') }}</div>
|
|
5300
|
+
<pre>{{ edge.link.condition | json }}</pre>
|
|
5301
|
+
</div>
|
|
5302
|
+
<div class="connections-panel__details-block" *ngIf="edge.link.transform?.steps?.length">
|
|
5303
|
+
<div class="connections-panel__details-label">{{ tx('connections.details.transform', 'Transform') }}</div>
|
|
5304
|
+
<pre>{{ edge.link.transform | json }}</pre>
|
|
5305
|
+
</div>
|
|
5306
|
+
<div class="connections-panel__details-block" *ngIf="edge.link.policy">
|
|
5307
|
+
<div class="connections-panel__details-label">{{ tx('connections.details.policy', 'Policy') }}</div>
|
|
5308
|
+
<pre>{{ edge.link.policy | json }}</pre>
|
|
5309
|
+
</div>
|
|
5310
|
+
<div class="connections-panel__details-block" *ngIf="edge.hasDiagnostics">
|
|
5311
|
+
<div class="connections-panel__details-label">{{ tx('connections.details.diagnostics', 'Diagnostics') }}</div>
|
|
5312
|
+
<pre>{{ edge.diagnosticReasons | json }}</pre>
|
|
5313
|
+
</div>
|
|
5314
|
+
</section>
|
|
5315
|
+
</aside>
|
|
5316
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{position:absolute;inset-block:16px;inset-inline-end:16px;z-index:4;pointer-events:none}.connections-panel{width:min(420px,calc(100vw - 32px));max-height:calc(100vh - 32px);overflow:auto;padding:16px;border-radius:18px;background:#fffffffa;border:1px solid rgba(15,23,42,.08);box-shadow:0 20px 44px #0f172a2e;pointer-events:auto;display:grid;gap:16px}.connections-panel__header,.connections-panel__summary,.connections-panel__section{display:grid;gap:10px}.connections-panel__title{font-size:1rem;font-weight:700;color:#0f172a}.connections-panel__subtitle,.connections-panel__item-copy,.connections-panel__item-meta,.connections-panel__details-row span,.connections-panel__details-label{color:#475569;font-size:.86rem}.connections-panel__summary{grid-template-columns:repeat(4,minmax(0,1fr))}.connections-panel__metric{padding:12px;border-radius:12px;background:#f8fafc;border:1px solid #e2e8f0;display:grid;gap:4px}.connections-panel__metric strong,.connections-panel__details-row strong{color:#0f172a;font-size:.92rem}.connections-panel__section-title{font-size:.78rem;text-transform:uppercase;letter-spacing:.08em;color:#64748b;font-weight:700}.connections-panel__item{text-align:start;padding:12px;border-radius:12px;border:1px solid #e2e8f0;background:#fff;display:grid;gap:6px;cursor:pointer}.connections-panel__item--active{border-color:#2563eb;box-shadow:0 0 0 1px #2563eb1f;background:#eff6ff}.connections-panel__item-title{font-weight:700;color:#0f172a;word-break:break-word}.connections-panel__badges{display:flex;flex-wrap:wrap;gap:6px}.connections-panel__filters,.connections-panel__actions{display:flex;gap:8px;flex-wrap:wrap}.connections-panel__filter{border:1px solid #cbd5e1;background:#fff;color:#334155;border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connections-panel__filter--active{border-color:#2563eb;background:#dbeafe;color:#1d4ed8}.connections-panel__action{border:1px solid #cbd5e1;background:#fff;color:#334155;border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connections-panel__action:hover{border-color:#2563eb;color:#1d4ed8}.connections-panel__badge{padding:3px 8px;border-radius:999px;background:#dbeafe;color:#1d4ed8;font-size:.75rem;font-weight:700}.connections-panel__badge--warning{background:#fef3c7;color:#b45309}.connections-panel__details-row,.connections-panel__details-block{display:grid;gap:6px}pre{margin:0;padding:12px;border-radius:12px;background:#0f172a;color:#e2e8f0;overflow:auto;font-size:.75rem}@media(max-width:900px){:host{inset:auto 12px 88px}.connections-panel{width:auto;max-height:min(60vh,520px)}.connections-panel__summary{grid-template-columns:1fr}}\n"] }]
|
|
5317
|
+
}], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }], focusWidget: [{ type: i0.Output, args: ["focusWidget"] }], openPageSettings: [{ type: i0.Output, args: ["openPageSettings"] }] } });
|
|
5318
|
+
|
|
4750
5319
|
class DynamicPageBuilderComponent {
|
|
4751
5320
|
dialog;
|
|
4752
5321
|
settingsPanel;
|
|
5322
|
+
i18n = inject(PraxisI18nService);
|
|
4753
5323
|
runtime;
|
|
4754
5324
|
page;
|
|
4755
5325
|
context = null;
|
|
@@ -4761,6 +5331,7 @@ class DynamicPageBuilderComponent {
|
|
|
4761
5331
|
pageEditorComponent = DynamicPageConfigEditorComponent;
|
|
4762
5332
|
pageChange = new EventEmitter();
|
|
4763
5333
|
currentPage = signal({ widgets: [] }, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
|
|
5334
|
+
connectionsViewerOpen = signal(false, ...(ngDevMode ? [{ debugName: "connectionsViewerOpen" }] : []));
|
|
4764
5335
|
previewMode = false;
|
|
4765
5336
|
constructor(dialog, settingsPanel) {
|
|
4766
5337
|
this.dialog = dialog;
|
|
@@ -4781,11 +5352,17 @@ class DynamicPageBuilderComponent {
|
|
|
4781
5352
|
}
|
|
4782
5353
|
togglePreview() {
|
|
4783
5354
|
this.previewMode = !this.previewMode;
|
|
5355
|
+
if (this.previewMode) {
|
|
5356
|
+
this.connectionsViewerOpen.set(false);
|
|
5357
|
+
}
|
|
5358
|
+
}
|
|
5359
|
+
toggleConnectionsViewer() {
|
|
5360
|
+
this.connectionsViewerOpen.update((current) => !current);
|
|
4784
5361
|
}
|
|
4785
5362
|
onAddComponent() {
|
|
4786
5363
|
const ref = this.dialog.open(ComponentPaletteDialogComponent, {
|
|
4787
5364
|
width: '720px',
|
|
4788
|
-
data: { title: '
|
|
5365
|
+
data: { title: this.tx('connections.palette.insertComponent', 'Insert component') },
|
|
4789
5366
|
});
|
|
4790
5367
|
ref.afterClosed().subscribe((type) => {
|
|
4791
5368
|
if (type)
|
|
@@ -4825,6 +5402,11 @@ class DynamicPageBuilderComponent {
|
|
|
4825
5402
|
this.currentPage.set(cloned);
|
|
4826
5403
|
this.pageChange.emit(cloned);
|
|
4827
5404
|
}
|
|
5405
|
+
focusCanvasWidget(widgetKey) {
|
|
5406
|
+
if (!widgetKey)
|
|
5407
|
+
return;
|
|
5408
|
+
this.runtime?.selectCanvasWidget(widgetKey);
|
|
5409
|
+
}
|
|
4828
5410
|
parsePage(input) {
|
|
4829
5411
|
if (!input)
|
|
4830
5412
|
return undefined;
|
|
@@ -4841,73 +5423,118 @@ class DynamicPageBuilderComponent {
|
|
|
4841
5423
|
clonePage(page) {
|
|
4842
5424
|
return JSON.parse(JSON.stringify(page));
|
|
4843
5425
|
}
|
|
5426
|
+
tx(key, fallback) {
|
|
5427
|
+
return resolvePraxisPageBuilderText(this.i18n, key, fallback);
|
|
5428
|
+
}
|
|
4844
5429
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicPageBuilderComponent, deps: [{ token: i1.MatDialog }, { token: SETTINGS_PANEL_BRIDGE, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
4845
5430
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: DynamicPageBuilderComponent, isStandalone: true, selector: "praxis-dynamic-page-builder", inputs: { page: "page", context: "context", strictValidation: "strictValidation", enableCustomization: "enableCustomization", showSettingsButton: "showSettingsButton", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", pageEditorComponent: "pageEditorComponent" }, outputs: { pageChange: "pageChange" }, providers: [
|
|
5431
|
+
providePraxisPageBuilderI18n(),
|
|
4846
5432
|
{ provide: DYNAMIC_PAGE_SHELL_EDITOR, useValue: WidgetShellEditorComponent },
|
|
4847
5433
|
], viewQueries: [{ propertyName: "runtime", first: true, predicate: ["runtime"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
4848
|
-
<
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
5434
|
+
<div class="builder-shell">
|
|
5435
|
+
<praxis-dynamic-page
|
|
5436
|
+
#runtime
|
|
5437
|
+
[page]="currentPage()"
|
|
5438
|
+
[context]="context"
|
|
5439
|
+
[strictValidation]="strictValidation"
|
|
5440
|
+
[enableCustomization]="showSettings()"
|
|
5441
|
+
[showPageSettingsButton]="false"
|
|
5442
|
+
[pageIdentity]="pageIdentity"
|
|
5443
|
+
[componentInstanceId]="componentInstanceId"
|
|
5444
|
+
[pageEditorComponent]="pageEditorComponent"
|
|
5445
|
+
(pageChange)="onRuntimePageChange($event)"
|
|
5446
|
+
/>
|
|
5447
|
+
|
|
5448
|
+
<praxis-connections-viewer-panel
|
|
5449
|
+
[open]="showSettings() && connectionsViewerOpen()"
|
|
5450
|
+
[page]="currentPage()"
|
|
5451
|
+
(focusWidget)="focusCanvasWidget($event)"
|
|
5452
|
+
(openPageSettings)="openPageSettings()"
|
|
5453
|
+
/>
|
|
4860
5454
|
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
5455
|
+
<praxis-floating-toolbar
|
|
5456
|
+
[visible]="showSettings()"
|
|
5457
|
+
[canUndo]="false"
|
|
5458
|
+
[canRedo]="false"
|
|
5459
|
+
(add)="onAddComponent()"
|
|
5460
|
+
(settings)="openPageSettings()"
|
|
5461
|
+
(save)="saveCurrentPage()"
|
|
5462
|
+
(preview)="togglePreview()"
|
|
5463
|
+
>
|
|
5464
|
+
<button
|
|
5465
|
+
pdx-toolbar-extra
|
|
5466
|
+
mat-mini-fab
|
|
5467
|
+
type="button"
|
|
5468
|
+
[attr.data-testid]="'page-builder-connections-toggle'"
|
|
5469
|
+
[matTooltip]="tx('connections.toggle', 'Inspect connections')"
|
|
5470
|
+
[attr.aria-label]="tx('connections.toggleAria', 'Inspect connections')"
|
|
5471
|
+
(click)="toggleConnectionsViewer()"
|
|
5472
|
+
>
|
|
5473
|
+
<mat-icon [praxisIcon]="'hub'"></mat-icon>
|
|
5474
|
+
</button>
|
|
5475
|
+
</praxis-floating-toolbar>
|
|
5476
|
+
</div>
|
|
5477
|
+
`, isInline: true, styles: [":host,.builder-shell{display:block;position:relative;min-height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: DynamicWidgetPageComponent, selector: "praxis-dynamic-page", inputs: ["page", "context", "strictValidation", "enableCustomization", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId"], outputs: ["pageChange", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionsViewerPanelComponent, selector: "praxis-connections-viewer-panel", inputs: ["open", "page"], outputs: ["focusWidget", "openPageSettings"] }] });
|
|
4871
5478
|
}
|
|
4872
5479
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicPageBuilderComponent, decorators: [{
|
|
4873
5480
|
type: Component,
|
|
4874
|
-
args: [{
|
|
4875
|
-
selector: 'praxis-dynamic-page-builder',
|
|
4876
|
-
standalone: true,
|
|
4877
|
-
imports: [
|
|
5481
|
+
args: [{ selector: 'praxis-dynamic-page-builder', standalone: true, imports: [
|
|
4878
5482
|
CommonModule,
|
|
5483
|
+
MatButtonModule,
|
|
5484
|
+
MatIconModule,
|
|
5485
|
+
MatTooltipModule,
|
|
5486
|
+
PraxisIconDirective,
|
|
4879
5487
|
DynamicWidgetPageComponent,
|
|
4880
5488
|
FloatingToolbarComponent,
|
|
4881
|
-
|
|
4882
|
-
],
|
|
4883
|
-
|
|
5489
|
+
ConnectionsViewerPanelComponent,
|
|
5490
|
+
], providers: [
|
|
5491
|
+
providePraxisPageBuilderI18n(),
|
|
4884
5492
|
{ provide: DYNAMIC_PAGE_SHELL_EDITOR, useValue: WidgetShellEditorComponent },
|
|
4885
|
-
],
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
5493
|
+
], template: `
|
|
5494
|
+
<div class="builder-shell">
|
|
5495
|
+
<praxis-dynamic-page
|
|
5496
|
+
#runtime
|
|
5497
|
+
[page]="currentPage()"
|
|
5498
|
+
[context]="context"
|
|
5499
|
+
[strictValidation]="strictValidation"
|
|
5500
|
+
[enableCustomization]="showSettings()"
|
|
5501
|
+
[showPageSettingsButton]="false"
|
|
5502
|
+
[pageIdentity]="pageIdentity"
|
|
5503
|
+
[componentInstanceId]="componentInstanceId"
|
|
5504
|
+
[pageEditorComponent]="pageEditorComponent"
|
|
5505
|
+
(pageChange)="onRuntimePageChange($event)"
|
|
5506
|
+
/>
|
|
4899
5507
|
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
5508
|
+
<praxis-connections-viewer-panel
|
|
5509
|
+
[open]="showSettings() && connectionsViewerOpen()"
|
|
5510
|
+
[page]="currentPage()"
|
|
5511
|
+
(focusWidget)="focusCanvasWidget($event)"
|
|
5512
|
+
(openPageSettings)="openPageSettings()"
|
|
5513
|
+
/>
|
|
5514
|
+
|
|
5515
|
+
<praxis-floating-toolbar
|
|
5516
|
+
[visible]="showSettings()"
|
|
5517
|
+
[canUndo]="false"
|
|
5518
|
+
[canRedo]="false"
|
|
5519
|
+
(add)="onAddComponent()"
|
|
5520
|
+
(settings)="openPageSettings()"
|
|
5521
|
+
(save)="saveCurrentPage()"
|
|
5522
|
+
(preview)="togglePreview()"
|
|
5523
|
+
>
|
|
5524
|
+
<button
|
|
5525
|
+
pdx-toolbar-extra
|
|
5526
|
+
mat-mini-fab
|
|
5527
|
+
type="button"
|
|
5528
|
+
[attr.data-testid]="'page-builder-connections-toggle'"
|
|
5529
|
+
[matTooltip]="tx('connections.toggle', 'Inspect connections')"
|
|
5530
|
+
[attr.aria-label]="tx('connections.toggleAria', 'Inspect connections')"
|
|
5531
|
+
(click)="toggleConnectionsViewer()"
|
|
5532
|
+
>
|
|
5533
|
+
<mat-icon [praxisIcon]="'hub'"></mat-icon>
|
|
5534
|
+
</button>
|
|
5535
|
+
</praxis-floating-toolbar>
|
|
5536
|
+
</div>
|
|
5537
|
+
`, styles: [":host,.builder-shell{display:block;position:relative;min-height:100%}\n"] }]
|
|
4911
5538
|
}], ctorParameters: () => [{ type: i1.MatDialog }, { type: undefined, decorators: [{
|
|
4912
5539
|
type: Optional
|
|
4913
5540
|
}, {
|
package/index.d.ts
CHANGED
|
@@ -599,6 +599,7 @@ declare function providePageBuilderWidgetAiCatalogs(): Provider;
|
|
|
599
599
|
declare class DynamicPageBuilderComponent implements OnChanges {
|
|
600
600
|
private dialog;
|
|
601
601
|
private settingsPanel;
|
|
602
|
+
private readonly i18n;
|
|
602
603
|
runtime?: DynamicWidgetPageComponent;
|
|
603
604
|
page?: WidgetPageDefinition | string;
|
|
604
605
|
context?: Record<string, unknown> | null;
|
|
@@ -610,18 +611,22 @@ declare class DynamicPageBuilderComponent implements OnChanges {
|
|
|
610
611
|
pageEditorComponent: Type<any> | undefined;
|
|
611
612
|
pageChange: EventEmitter<WidgetPageDefinition>;
|
|
612
613
|
readonly currentPage: i0.WritableSignal<WidgetPageDefinition>;
|
|
614
|
+
readonly connectionsViewerOpen: i0.WritableSignal<boolean>;
|
|
613
615
|
private previewMode;
|
|
614
616
|
constructor(dialog: MatDialog, settingsPanel: SettingsPanelBridge | null);
|
|
615
617
|
ngOnChanges(changes: SimpleChanges): void;
|
|
616
618
|
showSettings(): boolean;
|
|
617
619
|
onRuntimePageChange(next: WidgetPageDefinition): void;
|
|
618
620
|
togglePreview(): void;
|
|
621
|
+
toggleConnectionsViewer(): void;
|
|
619
622
|
onAddComponent(): void;
|
|
620
623
|
addWidget(type: string): void;
|
|
621
624
|
openPageSettings(): void;
|
|
622
625
|
saveCurrentPage(): void;
|
|
626
|
+
focusCanvasWidget(widgetKey: string): void;
|
|
623
627
|
private parsePage;
|
|
624
628
|
private clonePage;
|
|
629
|
+
tx(key: string, fallback: string): string;
|
|
625
630
|
static ɵfac: i0.ɵɵFactoryDeclaration<DynamicPageBuilderComponent, [null, { optional: true; }]>;
|
|
626
631
|
static ɵcmp: i0.ɵɵComponentDeclaration<DynamicPageBuilderComponent, "praxis-dynamic-page-builder", never, { "page": { "alias": "page"; "required": false; }; "context": { "alias": "context"; "required": false; }; "strictValidation": { "alias": "strictValidation"; "required": false; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; }; "showSettingsButton": { "alias": "showSettingsButton"; "required": false; }; "pageIdentity": { "alias": "pageIdentity"; "required": false; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; }; "pageEditorComponent": { "alias": "pageEditorComponent"; "required": false; }; }, { "pageChange": "pageChange"; }, never, never, true, never>;
|
|
627
632
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/page-builder",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0-beta.0",
|
|
4
4
|
"description": "Page and widget builder utilities for Praxis UI (grid, dynamic widgets, editors).",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^20.0.0",
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"@angular/forms": "^20.0.0",
|
|
9
9
|
"@angular/cdk": "^20.0.0",
|
|
10
10
|
"@angular/material": "^20.0.0",
|
|
11
|
-
"@praxisui/core": "^
|
|
12
|
-
"@praxisui/settings-panel": "^
|
|
11
|
+
"@praxisui/core": "^6.0.0-beta.0",
|
|
12
|
+
"@praxisui/settings-panel": "^6.0.0-beta.0"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"tslib": "^2.3.0"
|