@praxisui/page-builder 10.0.0-rc.13 → 10.0.0-rc.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-14T16:04:24.084Z",
|
|
4
4
|
"packageName": "@praxisui/page-builder",
|
|
5
|
-
"packageVersion": "10.0.0-rc.
|
|
5
|
+
"packageVersion": "10.0.0-rc.15",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 1,
|
|
@@ -14567,11 +14567,17 @@ const DERIVED_OPERATORS = ['merge-objects', 'pick', 'omit'];
|
|
|
14567
14567
|
const MERGE_STRATEGIES = ['replace', 'merge', 'append', 'remove-keys'];
|
|
14568
14568
|
const VALUE_MODES = ['json', 'string', 'number', 'boolean', 'null'];
|
|
14569
14569
|
const GROUPING_KINDS = ['section', 'tabs', 'hero', 'rail'];
|
|
14570
|
+
const DATA_SOURCE_KINDS = ['remote-resource', 'stats-query', 'raw-http'];
|
|
14571
|
+
const DATA_SOURCE_METHODS = ['GET', 'POST'];
|
|
14572
|
+
const DATA_SOURCE_ERROR_POLICIES = ['fallback', 'silent', 'propagate'];
|
|
14570
14573
|
class PageConfigEditorComponent {
|
|
14571
14574
|
derivedOperators = DERIVED_OPERATORS;
|
|
14572
14575
|
mergeStrategies = MERGE_STRATEGIES;
|
|
14573
14576
|
valueModes = VALUE_MODES;
|
|
14574
14577
|
groupingKinds = GROUPING_KINDS;
|
|
14578
|
+
dataSourceKinds = DATA_SOURCE_KINDS;
|
|
14579
|
+
dataSourceMethods = DATA_SOURCE_METHODS;
|
|
14580
|
+
dataSourceErrorPolicies = DATA_SOURCE_ERROR_POLICIES;
|
|
14575
14581
|
layoutPresetEntries = Object.values(BUILTIN_PAGE_LAYOUT_PRESETS);
|
|
14576
14582
|
themePresetEntries = Object.values(BUILTIN_PAGE_THEME_PRESETS);
|
|
14577
14583
|
page = input(null, ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
|
|
@@ -14595,6 +14601,7 @@ class PageConfigEditorComponent {
|
|
|
14595
14601
|
groupingNodes = new FormArray([]);
|
|
14596
14602
|
schemaNodes = new FormArray([]);
|
|
14597
14603
|
derivedNodes = new FormArray([]);
|
|
14604
|
+
dataSourceNodes = new FormArray([]);
|
|
14598
14605
|
deviceDesktopForm = this.createDeviceLayoutForm();
|
|
14599
14606
|
deviceTabletForm = this.createDeviceLayoutForm();
|
|
14600
14607
|
deviceMobileForm = this.createDeviceLayoutForm();
|
|
@@ -14789,6 +14796,14 @@ class PageConfigEditorComponent {
|
|
|
14789
14796
|
.pipe(takeUntilDestroyed())
|
|
14790
14797
|
.subscribe(() => {
|
|
14791
14798
|
this.stateError.set(null);
|
|
14799
|
+
this.syncDataSourceNodesFromControl();
|
|
14800
|
+
this.refreshPanelState();
|
|
14801
|
+
});
|
|
14802
|
+
this.dataSourceNodes.valueChanges
|
|
14803
|
+
.pipe(takeUntilDestroyed())
|
|
14804
|
+
.subscribe(() => {
|
|
14805
|
+
this.stateError.set(null);
|
|
14806
|
+
this.syncDataSourcesControlFromNodes();
|
|
14792
14807
|
this.refreshPanelState();
|
|
14793
14808
|
});
|
|
14794
14809
|
this.schemaNodes.valueChanges
|
|
@@ -14825,6 +14840,12 @@ class PageConfigEditorComponent {
|
|
|
14825
14840
|
removeDerivedNode(index) {
|
|
14826
14841
|
this.derivedNodes.removeAt(index);
|
|
14827
14842
|
}
|
|
14843
|
+
addDataSourceNode(seed) {
|
|
14844
|
+
this.dataSourceNodes.push(this.createDataSourceNodeGroup(seed));
|
|
14845
|
+
}
|
|
14846
|
+
removeDataSourceNode(index) {
|
|
14847
|
+
this.dataSourceNodes.removeAt(index);
|
|
14848
|
+
}
|
|
14828
14849
|
addGroupingNode(seed) {
|
|
14829
14850
|
this.groupingNodes.push(this.createGroupingNodeGroup(seed));
|
|
14830
14851
|
}
|
|
@@ -15049,19 +15070,143 @@ class PageConfigEditorComponent {
|
|
|
15049
15070
|
this.replaceDerivedNodes(normalized.derived);
|
|
15050
15071
|
}
|
|
15051
15072
|
hydrateDataSourcesEditor(dataSources) {
|
|
15073
|
+
const normalized = this.normalizeDataSourcesArray(dataSources);
|
|
15052
15074
|
const hasEntries = Array.isArray(dataSources)
|
|
15053
15075
|
? dataSources.length > 0
|
|
15054
15076
|
: !!(dataSources && Object.keys(dataSources).length);
|
|
15055
15077
|
const nextJson = hasEntries
|
|
15056
15078
|
? JSON.stringify(dataSources, null, 2)
|
|
15057
15079
|
: '';
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
|
|
15061
|
-
|
|
15080
|
+
this.lastDataSources = nextJson;
|
|
15081
|
+
this.dataSourcesControl.setValue(nextJson, { emitEvent: false });
|
|
15082
|
+
this.replaceDataSourceNodes(normalized);
|
|
15083
|
+
this.stateError.set(null);
|
|
15084
|
+
}
|
|
15085
|
+
normalizeDataSourcesArray(dataSources) {
|
|
15086
|
+
if (!dataSources)
|
|
15087
|
+
return [];
|
|
15088
|
+
if (Array.isArray(dataSources))
|
|
15089
|
+
return dataSources;
|
|
15090
|
+
if (typeof dataSources === 'object') {
|
|
15091
|
+
return Object.entries(dataSources).map(([id, def]) => ({
|
|
15092
|
+
...def,
|
|
15093
|
+
id: def?.id || id,
|
|
15094
|
+
}));
|
|
15095
|
+
}
|
|
15096
|
+
return [];
|
|
15097
|
+
}
|
|
15098
|
+
replaceDataSourceNodes(dataSources) {
|
|
15099
|
+
this.dataSourceNodes.clear({ emitEvent: false });
|
|
15100
|
+
for (const item of dataSources || []) {
|
|
15101
|
+
this.dataSourceNodes.push(this.createDataSourceNodeGroup(item), { emitEvent: false });
|
|
15102
|
+
}
|
|
15103
|
+
}
|
|
15104
|
+
createDataSourceNodeGroup(seed) {
|
|
15105
|
+
return new FormGroup({
|
|
15106
|
+
id: new FormControl(seed?.id || '', { nonNullable: true, validators: [Validators.required] }),
|
|
15107
|
+
kind: new FormControl(seed?.kind || '', { nonNullable: true }),
|
|
15108
|
+
resourcePath: new FormControl(seed?.resourcePath || '', { nonNullable: true, validators: [Validators.required] }),
|
|
15109
|
+
method: new FormControl(seed?.method || '', { nonNullable: true }),
|
|
15110
|
+
targetStatePath: new FormControl(seed?.targetStatePath || '', { nonNullable: true }),
|
|
15111
|
+
errorPolicy: new FormControl(seed?.errorPolicy || '', { nonNullable: true }),
|
|
15112
|
+
refreshIntervalMs: new FormControl(seed?.refreshIntervalMs ?? null),
|
|
15113
|
+
autoFetch: new FormControl(typeof seed?.autoFetch === 'boolean' ? String(seed.autoFetch) : '', { nonNullable: true }),
|
|
15114
|
+
queryJson: new FormControl(seed?.query !== undefined ? JSON.stringify(seed.query, null, 2) : '', { nonNullable: true }),
|
|
15115
|
+
transformJson: new FormControl(seed?.transform !== undefined ? JSON.stringify(seed.transform, null, 2) : '', { nonNullable: true }),
|
|
15116
|
+
fallbackJson: new FormControl(seed?.fallbackValue !== undefined ? JSON.stringify(seed.fallbackValue, null, 2) : '', { nonNullable: true }),
|
|
15117
|
+
description: new FormControl(seed?.description || '', { nonNullable: true }),
|
|
15118
|
+
});
|
|
15119
|
+
}
|
|
15120
|
+
syncDataSourceNodesFromControl() {
|
|
15121
|
+
const raw = this.dataSourcesControl.value.trim();
|
|
15122
|
+
if (!raw) {
|
|
15123
|
+
this.replaceDataSourceNodes([]);
|
|
15124
|
+
return;
|
|
15062
15125
|
}
|
|
15126
|
+
const parsed = this.parseJson(raw, null);
|
|
15127
|
+
if (parsed && typeof parsed === 'object') {
|
|
15128
|
+
this.replaceDataSourceNodes(this.normalizeDataSourcesArray(parsed));
|
|
15129
|
+
}
|
|
15130
|
+
}
|
|
15131
|
+
syncDataSourcesControlFromNodes() {
|
|
15132
|
+
const built = this.buildDataSourcesFromNodes();
|
|
15133
|
+
if (built === null)
|
|
15134
|
+
return;
|
|
15135
|
+
const json = built.length ? JSON.stringify(built, null, 2) : '';
|
|
15136
|
+
this.lastDataSources = json;
|
|
15137
|
+
this.dataSourcesControl.setValue(json, { emitEvent: false });
|
|
15138
|
+
}
|
|
15139
|
+
buildDataSourcesFromNodes() {
|
|
15140
|
+
const list = [];
|
|
15141
|
+
for (const group of this.dataSourceNodes.controls) {
|
|
15142
|
+
const id = group.controls.id.value.trim();
|
|
15143
|
+
const resourcePath = group.controls.resourcePath.value.trim();
|
|
15144
|
+
if (!id || !resourcePath)
|
|
15145
|
+
continue;
|
|
15146
|
+
const node = { id, resourcePath };
|
|
15147
|
+
const kind = group.controls.kind.value.trim();
|
|
15148
|
+
const method = group.controls.method.value.trim();
|
|
15149
|
+
const targetStatePath = group.controls.targetStatePath.value.trim();
|
|
15150
|
+
const errorPolicy = group.controls.errorPolicy.value.trim();
|
|
15151
|
+
const refreshIntervalMs = group.controls.refreshIntervalMs.value;
|
|
15152
|
+
const autoFetch = group.controls.autoFetch.value.trim();
|
|
15153
|
+
const queryRaw = group.controls.queryJson.value.trim();
|
|
15154
|
+
const transformRaw = group.controls.transformJson.value.trim();
|
|
15155
|
+
const fallbackRaw = group.controls.fallbackJson.value.trim();
|
|
15156
|
+
const description = group.controls.description.value.trim();
|
|
15157
|
+
if (kind)
|
|
15158
|
+
node.kind = kind;
|
|
15159
|
+
if (method)
|
|
15160
|
+
node.method = method;
|
|
15161
|
+
if (targetStatePath)
|
|
15162
|
+
node.targetStatePath = targetStatePath;
|
|
15163
|
+
if (errorPolicy)
|
|
15164
|
+
node.errorPolicy = errorPolicy;
|
|
15165
|
+
if (refreshIntervalMs !== null && refreshIntervalMs !== undefined && !Number.isNaN(Number(refreshIntervalMs))) {
|
|
15166
|
+
node.refreshIntervalMs = Number(refreshIntervalMs);
|
|
15167
|
+
}
|
|
15168
|
+
if (autoFetch === 'true')
|
|
15169
|
+
node.autoFetch = true;
|
|
15170
|
+
if (autoFetch === 'false')
|
|
15171
|
+
node.autoFetch = false;
|
|
15172
|
+
if (queryRaw) {
|
|
15173
|
+
const parsedQuery = this.parseJson(queryRaw, {});
|
|
15174
|
+
if (parsedQuery === null || typeof parsedQuery !== 'object' || Array.isArray(parsedQuery))
|
|
15175
|
+
return null;
|
|
15176
|
+
node.query = parsedQuery;
|
|
15177
|
+
}
|
|
15178
|
+
if (transformRaw) {
|
|
15179
|
+
const parsedTransform = this.parseJson(transformRaw, {});
|
|
15180
|
+
if (parsedTransform === null)
|
|
15181
|
+
return null;
|
|
15182
|
+
node.transform = parsedTransform;
|
|
15183
|
+
}
|
|
15184
|
+
if (fallbackRaw) {
|
|
15185
|
+
try {
|
|
15186
|
+
node.fallbackValue = JSON.parse(fallbackRaw);
|
|
15187
|
+
}
|
|
15188
|
+
catch {
|
|
15189
|
+
return null;
|
|
15190
|
+
}
|
|
15191
|
+
}
|
|
15192
|
+
if (description)
|
|
15193
|
+
node.description = description;
|
|
15194
|
+
list.push(node);
|
|
15195
|
+
}
|
|
15196
|
+
return list;
|
|
15063
15197
|
}
|
|
15064
15198
|
buildDataSources() {
|
|
15199
|
+
if (this.dataSourceNodes.length > 0) {
|
|
15200
|
+
const fromNodes = this.buildDataSourcesFromNodes();
|
|
15201
|
+
if (fromNodes === null)
|
|
15202
|
+
return null;
|
|
15203
|
+
if (fromNodes.length > 0) {
|
|
15204
|
+
const json = JSON.stringify(fromNodes, null, 2);
|
|
15205
|
+
this.lastDataSources = json;
|
|
15206
|
+
this.dataSourcesControl.setValue(json, { emitEvent: false });
|
|
15207
|
+
return fromNodes;
|
|
15208
|
+
}
|
|
15209
|
+
}
|
|
15065
15210
|
const raw = this.dataSourcesControl.value.trim();
|
|
15066
15211
|
if (!raw)
|
|
15067
15212
|
return undefined;
|
|
@@ -16056,12 +16201,85 @@ class PageConfigEditorComponent {
|
|
|
16056
16201
|
}
|
|
16057
16202
|
</div>
|
|
16058
16203
|
</div>
|
|
16059
|
-
|
|
16060
|
-
|
|
16061
|
-
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
|
|
16204
|
+
|
|
16205
|
+
<div class="state-group">
|
|
16206
|
+
<div class="state-group-head">
|
|
16207
|
+
<div class="state-group-title">{{ tx('editor.state.dataSourcesTitle', 'Declarative Data Sources') }}</div>
|
|
16208
|
+
<button mat-stroked-button type="button" (click)="addDataSourceNode()">
|
|
16209
|
+
<mat-icon>add</mat-icon>
|
|
16210
|
+
{{ tx('editor.state.addDataSource', 'Add data source') }}
|
|
16211
|
+
</button>
|
|
16212
|
+
</div>
|
|
16213
|
+
<div class="state-group-help">{{ tx('editor.state.dataSourcesCopy', 'Bind HTTP or resource endpoints directly into page state paths with reactive parameters.') }}</div>
|
|
16214
|
+
@if (!dataSourceNodes.length) {
|
|
16215
|
+
<div class="state-empty">{{ tx('editor.state.emptyDataSources', 'No declarative data sources configured.') }}</div>
|
|
16216
|
+
}
|
|
16217
|
+
<div class="state-list">
|
|
16218
|
+
@for (group of dataSourceNodes.controls; track $index) {
|
|
16219
|
+
<div class="state-card" [formGroup]="group">
|
|
16220
|
+
<div class="state-card-head">
|
|
16221
|
+
<div class="state-card-title">{{ tx('editor.state.dataSourceN', 'Data source {{index}}').replace('{{index}}', '' + ($index + 1)) }}</div>
|
|
16222
|
+
<button praxisIconButton="delete" size="compact" type="button" (click)="removeDataSourceNode($index)" [attr.aria-label]="tx('editor.state.removeDataSourceAria', 'Remove data source')"></button>
|
|
16223
|
+
</div>
|
|
16224
|
+
<div class="state-card-grid">
|
|
16225
|
+
<mat-form-field appearance="outline">
|
|
16226
|
+
<mat-label>{{ tx('editor.state.dataSourceId', 'ID') }}</mat-label>
|
|
16227
|
+
<input matInput formControlName="id" />
|
|
16228
|
+
</mat-form-field>
|
|
16229
|
+
<mat-form-field appearance="outline">
|
|
16230
|
+
<mat-label>{{ tx('editor.state.dataSourceKind', 'Kind') }}</mat-label>
|
|
16231
|
+
<mat-select formControlName="kind">
|
|
16232
|
+
<mat-option value="">{{ tx('editor.common.default', 'Default') }}</mat-option>
|
|
16233
|
+
@for (kind of dataSourceKinds; track kind) {
|
|
16234
|
+
<mat-option [value]="kind">{{ kind }}</mat-option>
|
|
16235
|
+
}
|
|
16236
|
+
</mat-select>
|
|
16237
|
+
</mat-form-field>
|
|
16238
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16239
|
+
<mat-label>{{ tx('editor.state.resourcePath', 'Resource path') }}</mat-label>
|
|
16240
|
+
<input matInput formControlName="resourcePath" />
|
|
16241
|
+
</mat-form-field>
|
|
16242
|
+
<mat-form-field appearance="outline">
|
|
16243
|
+
<mat-label>{{ tx('editor.state.method', 'HTTP method') }}</mat-label>
|
|
16244
|
+
<mat-select formControlName="method">
|
|
16245
|
+
<mat-option value="">{{ tx('editor.common.auto', 'Auto') }}</mat-option>
|
|
16246
|
+
@for (method of dataSourceMethods; track method) {
|
|
16247
|
+
<mat-option [value]="method">{{ method }}</mat-option>
|
|
16248
|
+
}
|
|
16249
|
+
</mat-select>
|
|
16250
|
+
</mat-form-field>
|
|
16251
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16252
|
+
<mat-label>{{ tx('editor.state.targetStatePath', 'Target state path') }}</mat-label>
|
|
16253
|
+
<input matInput formControlName="targetStatePath" />
|
|
16254
|
+
</mat-form-field>
|
|
16255
|
+
<mat-form-field appearance="outline">
|
|
16256
|
+
<mat-label>{{ tx('editor.state.errorPolicy', 'Error policy') }}</mat-label>
|
|
16257
|
+
<mat-select formControlName="errorPolicy">
|
|
16258
|
+
<mat-option value="">{{ tx('editor.common.default', 'Default') }}</mat-option>
|
|
16259
|
+
@for (policy of dataSourceErrorPolicies; track policy) {
|
|
16260
|
+
<mat-option [value]="policy">{{ policy }}</mat-option>
|
|
16261
|
+
}
|
|
16262
|
+
</mat-select>
|
|
16263
|
+
</mat-form-field>
|
|
16264
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16265
|
+
<mat-label>{{ tx('editor.state.queryJson', 'Query (JSON)') }}</mat-label>
|
|
16266
|
+
<textarea matInput rows="3" formControlName="queryJson"></textarea>
|
|
16267
|
+
</mat-form-field>
|
|
16268
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16269
|
+
<mat-label>{{ tx('editor.state.transformJson', 'Transform (JSON)') }}</mat-label>
|
|
16270
|
+
<textarea matInput rows="3" formControlName="transformJson"></textarea>
|
|
16271
|
+
</mat-form-field>
|
|
16272
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16273
|
+
<mat-label>{{ tx('editor.state.fallbackJson', 'Fallback value (JSON)') }}</mat-label>
|
|
16274
|
+
<textarea matInput rows="3" formControlName="fallbackJson"></textarea>
|
|
16275
|
+
</mat-form-field>
|
|
16276
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16277
|
+
<mat-label>{{ tx('editor.state.description', 'Description') }}</mat-label>
|
|
16278
|
+
<input matInput formControlName="description" />
|
|
16279
|
+
</mat-form-field>
|
|
16280
|
+
</div>
|
|
16281
|
+
</div>
|
|
16282
|
+
}
|
|
16065
16283
|
</div>
|
|
16066
16284
|
<mat-form-field appearance="outline" class="page-context">
|
|
16067
16285
|
<mat-label>{{ tx('editor.state.dataSourcesJson', 'page.dataSources (JSON)') }}</mat-label>
|
|
@@ -16672,12 +16890,85 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
16672
16890
|
}
|
|
16673
16891
|
</div>
|
|
16674
16892
|
</div>
|
|
16675
|
-
|
|
16676
|
-
|
|
16677
|
-
|
|
16678
|
-
|
|
16679
|
-
|
|
16680
|
-
|
|
16893
|
+
|
|
16894
|
+
<div class="state-group">
|
|
16895
|
+
<div class="state-group-head">
|
|
16896
|
+
<div class="state-group-title">{{ tx('editor.state.dataSourcesTitle', 'Declarative Data Sources') }}</div>
|
|
16897
|
+
<button mat-stroked-button type="button" (click)="addDataSourceNode()">
|
|
16898
|
+
<mat-icon>add</mat-icon>
|
|
16899
|
+
{{ tx('editor.state.addDataSource', 'Add data source') }}
|
|
16900
|
+
</button>
|
|
16901
|
+
</div>
|
|
16902
|
+
<div class="state-group-help">{{ tx('editor.state.dataSourcesCopy', 'Bind HTTP or resource endpoints directly into page state paths with reactive parameters.') }}</div>
|
|
16903
|
+
@if (!dataSourceNodes.length) {
|
|
16904
|
+
<div class="state-empty">{{ tx('editor.state.emptyDataSources', 'No declarative data sources configured.') }}</div>
|
|
16905
|
+
}
|
|
16906
|
+
<div class="state-list">
|
|
16907
|
+
@for (group of dataSourceNodes.controls; track $index) {
|
|
16908
|
+
<div class="state-card" [formGroup]="group">
|
|
16909
|
+
<div class="state-card-head">
|
|
16910
|
+
<div class="state-card-title">{{ tx('editor.state.dataSourceN', 'Data source {{index}}').replace('{{index}}', '' + ($index + 1)) }}</div>
|
|
16911
|
+
<button praxisIconButton="delete" size="compact" type="button" (click)="removeDataSourceNode($index)" [attr.aria-label]="tx('editor.state.removeDataSourceAria', 'Remove data source')"></button>
|
|
16912
|
+
</div>
|
|
16913
|
+
<div class="state-card-grid">
|
|
16914
|
+
<mat-form-field appearance="outline">
|
|
16915
|
+
<mat-label>{{ tx('editor.state.dataSourceId', 'ID') }}</mat-label>
|
|
16916
|
+
<input matInput formControlName="id" />
|
|
16917
|
+
</mat-form-field>
|
|
16918
|
+
<mat-form-field appearance="outline">
|
|
16919
|
+
<mat-label>{{ tx('editor.state.dataSourceKind', 'Kind') }}</mat-label>
|
|
16920
|
+
<mat-select formControlName="kind">
|
|
16921
|
+
<mat-option value="">{{ tx('editor.common.default', 'Default') }}</mat-option>
|
|
16922
|
+
@for (kind of dataSourceKinds; track kind) {
|
|
16923
|
+
<mat-option [value]="kind">{{ kind }}</mat-option>
|
|
16924
|
+
}
|
|
16925
|
+
</mat-select>
|
|
16926
|
+
</mat-form-field>
|
|
16927
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16928
|
+
<mat-label>{{ tx('editor.state.resourcePath', 'Resource path') }}</mat-label>
|
|
16929
|
+
<input matInput formControlName="resourcePath" />
|
|
16930
|
+
</mat-form-field>
|
|
16931
|
+
<mat-form-field appearance="outline">
|
|
16932
|
+
<mat-label>{{ tx('editor.state.method', 'HTTP method') }}</mat-label>
|
|
16933
|
+
<mat-select formControlName="method">
|
|
16934
|
+
<mat-option value="">{{ tx('editor.common.auto', 'Auto') }}</mat-option>
|
|
16935
|
+
@for (method of dataSourceMethods; track method) {
|
|
16936
|
+
<mat-option [value]="method">{{ method }}</mat-option>
|
|
16937
|
+
}
|
|
16938
|
+
</mat-select>
|
|
16939
|
+
</mat-form-field>
|
|
16940
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16941
|
+
<mat-label>{{ tx('editor.state.targetStatePath', 'Target state path') }}</mat-label>
|
|
16942
|
+
<input matInput formControlName="targetStatePath" />
|
|
16943
|
+
</mat-form-field>
|
|
16944
|
+
<mat-form-field appearance="outline">
|
|
16945
|
+
<mat-label>{{ tx('editor.state.errorPolicy', 'Error policy') }}</mat-label>
|
|
16946
|
+
<mat-select formControlName="errorPolicy">
|
|
16947
|
+
<mat-option value="">{{ tx('editor.common.default', 'Default') }}</mat-option>
|
|
16948
|
+
@for (policy of dataSourceErrorPolicies; track policy) {
|
|
16949
|
+
<mat-option [value]="policy">{{ policy }}</mat-option>
|
|
16950
|
+
}
|
|
16951
|
+
</mat-select>
|
|
16952
|
+
</mat-form-field>
|
|
16953
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16954
|
+
<mat-label>{{ tx('editor.state.queryJson', 'Query (JSON)') }}</mat-label>
|
|
16955
|
+
<textarea matInput rows="3" formControlName="queryJson"></textarea>
|
|
16956
|
+
</mat-form-field>
|
|
16957
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16958
|
+
<mat-label>{{ tx('editor.state.transformJson', 'Transform (JSON)') }}</mat-label>
|
|
16959
|
+
<textarea matInput rows="3" formControlName="transformJson"></textarea>
|
|
16960
|
+
</mat-form-field>
|
|
16961
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16962
|
+
<mat-label>{{ tx('editor.state.fallbackJson', 'Fallback value (JSON)') }}</mat-label>
|
|
16963
|
+
<textarea matInput rows="3" formControlName="fallbackJson"></textarea>
|
|
16964
|
+
</mat-form-field>
|
|
16965
|
+
<mat-form-field appearance="outline" class="span-2">
|
|
16966
|
+
<mat-label>{{ tx('editor.state.description', 'Description') }}</mat-label>
|
|
16967
|
+
<input matInput formControlName="description" />
|
|
16968
|
+
</mat-form-field>
|
|
16969
|
+
</div>
|
|
16970
|
+
</div>
|
|
16971
|
+
}
|
|
16681
16972
|
</div>
|
|
16682
16973
|
<mat-form-field appearance="outline" class="page-context">
|
|
16683
16974
|
<mat-label>{{ tx('editor.state.dataSourcesJson', 'page.dataSources (JSON)') }}</mat-label>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/page-builder",
|
|
3
|
-
"version": "10.0.0-rc.
|
|
3
|
+
"version": "10.0.0-rc.15",
|
|
4
4
|
"description": "Page and widget builder utilities for Praxis UI (grid, dynamic widgets, editors).",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
"@angular/forms": "^21.0.0",
|
|
9
9
|
"@angular/cdk": "^21.0.0",
|
|
10
10
|
"@angular/material": "^21.0.0",
|
|
11
|
-
"@praxisui/ai": "^10.0.0-rc.
|
|
12
|
-
"@praxisui/core": "^10.0.0-rc.
|
|
13
|
-
"@praxisui/settings-panel": "^10.0.0-rc.
|
|
11
|
+
"@praxisui/ai": "^10.0.0-rc.15",
|
|
12
|
+
"@praxisui/core": "^10.0.0-rc.15",
|
|
13
|
+
"@praxisui/settings-panel": "^10.0.0-rc.15",
|
|
14
14
|
"rxjs": "~7.8.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
@@ -2,7 +2,7 @@ import { MatDialogRef, MatDialog } from '@angular/material/dialog';
|
|
|
2
2
|
import * as _angular_core from '@angular/core';
|
|
3
3
|
import { EventEmitter, OnInit, WritableSignal, InjectionToken, Provider, OnChanges, OnDestroy, Type, SimpleChanges } from '@angular/core';
|
|
4
4
|
import * as _praxisui_core from '@praxisui/core';
|
|
5
|
-
import { ComponentDocMeta, WidgetShellConfig, ComponentMetadataRegistry, PraxisI18nService, SettingsEditorSection, EndpointRef, PraxisTextValue, WidgetShellPresetCategory, CompositionLink, WidgetShellAction, WidgetPageAuthoringCapabilities, PortContract, ComponentPortPathSegment, LinkIntent, WidgetPageDefinition, SurfaceOpenActionEditorComponent, TransformKind, TransformPipeline, SurfaceOpenPayload, WidgetPageDeviceKind, SettingsValueProvider as SettingsValueProvider$1, WidgetShellPresetDefinition, WidgetPageCanvasLayout, WidgetPageGroupingDefinition, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, PageIdentity, WidgetStateNode, WidgetDerivedStateNode, AiCapability, AiCapabilityCategory, AiCapabilityCatalog, AiValueKind, WidgetPageDeviceLayouts, WidgetPageSlotAssignments, WidgetPageStateInput, WidgetInstance, TransformOutputHint, TransformSemanticKind, ConfigAuthoringSource, DomainKnowledgeChangeSetRequest, DomainKnowledgeChangeSet, DomainKnowledgeChangeSetTimelineResponse, DomainKnowledgeChangeSetFilters, DomainKnowledgeValidationResponse, DomainKnowledgeStatusTransitionRequest, DomainRuleIntakeRequest, DomainRuleIntakeResponse, DomainRuleDefinitionRequest, DomainRuleDefinition, DomainRuleSimulationRequest, DomainRuleSimulationResponse, DomainRuleStatusTransitionRequest, DomainRulePublicationRequest, DomainRulePublicationResponse, DomainRuleMaterializationFilters, DomainRuleMaterialization, DomainRuleTimelineResponse, PraxisRuntimeComponentObservationEnvelope, ComponentContextPack, ComponentAuthoringManifest, DiagnosticRecord, NestedPortCatalogRegistry, CompositionValidatorService, ApiUrlEntry, DynamicWidgetPageComponent, ConfigDocument, WidgetPagePersistenceState, WidgetEventEnvelope, ObservabilityAgenticTurnMetrics, SettingsPanelBridge, ObservabilityAgenticTurnMetricBucket, RichTimelineItem } from '@praxisui/core';
|
|
5
|
+
import { ComponentDocMeta, WidgetShellConfig, ComponentMetadataRegistry, PraxisI18nService, SettingsEditorSection, EndpointRef, PraxisTextValue, WidgetShellPresetCategory, CompositionLink, WidgetShellAction, WidgetPageAuthoringCapabilities, PortContract, ComponentPortPathSegment, LinkIntent, WidgetPageDefinition, SurfaceOpenActionEditorComponent, TransformKind, TransformPipeline, SurfaceOpenPayload, WidgetPageDeviceKind, SettingsValueProvider as SettingsValueProvider$1, WidgetShellPresetDefinition, WidgetPageCanvasLayout, WidgetPageGroupingDefinition, WidgetPageDataSourceKind, WidgetPageDataSourceMethod, WidgetPageDataSourceErrorPolicy, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, PageIdentity, WidgetStateNode, WidgetDerivedStateNode, WidgetPageDataSourceDefinition, AiCapability, AiCapabilityCategory, AiCapabilityCatalog, AiValueKind, WidgetPageDeviceLayouts, WidgetPageSlotAssignments, WidgetPageStateInput, WidgetInstance, TransformOutputHint, TransformSemanticKind, ConfigAuthoringSource, DomainKnowledgeChangeSetRequest, DomainKnowledgeChangeSet, DomainKnowledgeChangeSetTimelineResponse, DomainKnowledgeChangeSetFilters, DomainKnowledgeValidationResponse, DomainKnowledgeStatusTransitionRequest, DomainRuleIntakeRequest, DomainRuleIntakeResponse, DomainRuleDefinitionRequest, DomainRuleDefinition, DomainRuleSimulationRequest, DomainRuleSimulationResponse, DomainRuleStatusTransitionRequest, DomainRulePublicationRequest, DomainRulePublicationResponse, DomainRuleMaterializationFilters, DomainRuleMaterialization, DomainRuleTimelineResponse, PraxisRuntimeComponentObservationEnvelope, ComponentContextPack, ComponentAuthoringManifest, DiagnosticRecord, NestedPortCatalogRegistry, CompositionValidatorService, ApiUrlEntry, DynamicWidgetPageComponent, ConfigDocument, WidgetPagePersistenceState, WidgetEventEnvelope, ObservabilityAgenticTurnMetrics, SettingsPanelBridge, ObservabilityAgenticTurnMetricBucket, RichTimelineItem } from '@praxisui/core';
|
|
6
6
|
import * as rxjs from 'rxjs';
|
|
7
7
|
import { BehaviorSubject, Observable } from 'rxjs';
|
|
8
8
|
import { FormGroup, FormControl, FormArray, AbstractControl } from '@angular/forms';
|
|
@@ -1409,11 +1409,28 @@ type GroupingNodeGroup = FormGroup<{
|
|
|
1409
1409
|
side: FormControl<string>;
|
|
1410
1410
|
tabsJson: FormControl<string>;
|
|
1411
1411
|
}>;
|
|
1412
|
+
type DataSourceNodeGroup = FormGroup<{
|
|
1413
|
+
id: FormControl<string>;
|
|
1414
|
+
kind: FormControl<string>;
|
|
1415
|
+
resourcePath: FormControl<string>;
|
|
1416
|
+
method: FormControl<string>;
|
|
1417
|
+
targetStatePath: FormControl<string>;
|
|
1418
|
+
errorPolicy: FormControl<string>;
|
|
1419
|
+
refreshIntervalMs: FormControl<number | null>;
|
|
1420
|
+
autoFetch: FormControl<string>;
|
|
1421
|
+
queryJson: FormControl<string>;
|
|
1422
|
+
transformJson: FormControl<string>;
|
|
1423
|
+
fallbackJson: FormControl<string>;
|
|
1424
|
+
description: FormControl<string>;
|
|
1425
|
+
}>;
|
|
1412
1426
|
declare class PageConfigEditorComponent implements SettingsValueProvider$1 {
|
|
1413
1427
|
protected readonly derivedOperators: readonly ["merge-objects", "pick", "omit"];
|
|
1414
1428
|
protected readonly mergeStrategies: readonly ["replace", "merge", "append", "remove-keys"];
|
|
1415
1429
|
protected readonly valueModes: readonly ["json", "string", "number", "boolean", "null"];
|
|
1416
1430
|
protected readonly groupingKinds: readonly ["section", "tabs", "hero", "rail"];
|
|
1431
|
+
protected readonly dataSourceKinds: WidgetPageDataSourceKind[];
|
|
1432
|
+
protected readonly dataSourceMethods: WidgetPageDataSourceMethod[];
|
|
1433
|
+
protected readonly dataSourceErrorPolicies: WidgetPageDataSourceErrorPolicy[];
|
|
1417
1434
|
protected readonly layoutPresetEntries: Array<(typeof BUILTIN_PAGE_LAYOUT_PRESETS)[string]>;
|
|
1418
1435
|
protected readonly themePresetEntries: Array<(typeof BUILTIN_PAGE_THEME_PRESETS)[string]>;
|
|
1419
1436
|
readonly page: _angular_core.InputSignal<string | PageDefinition | null>;
|
|
@@ -1437,6 +1454,7 @@ declare class PageConfigEditorComponent implements SettingsValueProvider$1 {
|
|
|
1437
1454
|
readonly groupingNodes: FormArray<GroupingNodeGroup>;
|
|
1438
1455
|
readonly schemaNodes: FormArray<SchemaNodeGroup>;
|
|
1439
1456
|
readonly derivedNodes: FormArray<DerivedNodeGroup>;
|
|
1457
|
+
readonly dataSourceNodes: FormArray<DataSourceNodeGroup>;
|
|
1440
1458
|
readonly deviceDesktopForm: FormGroup<{
|
|
1441
1459
|
orientation: FormControl<string>;
|
|
1442
1460
|
columns: FormControl<number | null>;
|
|
@@ -1519,6 +1537,8 @@ declare class PageConfigEditorComponent implements SettingsValueProvider$1 {
|
|
|
1519
1537
|
config?: WidgetDerivedStateNode;
|
|
1520
1538
|
}): void;
|
|
1521
1539
|
removeDerivedNode(index: number): void;
|
|
1540
|
+
addDataSourceNode(seed?: WidgetPageDataSourceDefinition): void;
|
|
1541
|
+
removeDataSourceNode(index: number): void;
|
|
1522
1542
|
addGroupingNode(seed?: WidgetPageGroupingDefinition): void;
|
|
1523
1543
|
removeGroupingNode(index: number): void;
|
|
1524
1544
|
setActiveTab(tab: EditorTabId): void;
|
|
@@ -1536,6 +1556,12 @@ declare class PageConfigEditorComponent implements SettingsValueProvider$1 {
|
|
|
1536
1556
|
private buildDeviceLayoutVariant;
|
|
1537
1557
|
private hydrateStateEditor;
|
|
1538
1558
|
private hydrateDataSourcesEditor;
|
|
1559
|
+
private normalizeDataSourcesArray;
|
|
1560
|
+
private replaceDataSourceNodes;
|
|
1561
|
+
private createDataSourceNodeGroup;
|
|
1562
|
+
private syncDataSourceNodesFromControl;
|
|
1563
|
+
private syncDataSourcesControlFromNodes;
|
|
1564
|
+
private buildDataSourcesFromNodes;
|
|
1539
1565
|
private buildDataSources;
|
|
1540
1566
|
private replaceSchemaNodes;
|
|
1541
1567
|
private replaceDerivedNodes;
|