@praxisui/page-builder 8.0.0-beta.92 → 8.0.0-beta.94
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.
|
@@ -14307,13 +14307,14 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
14307
14307
|
};
|
|
14308
14308
|
}
|
|
14309
14309
|
const status = this.decorateDashboardReviewStatus(this.context.describePreviewStatus(preview), intentResolution, preview);
|
|
14310
|
+
const reviewCanApply = this.reviewCanApply(intentResolution, preview);
|
|
14310
14311
|
return {
|
|
14311
14312
|
state: 'review',
|
|
14312
14313
|
phase: 'review',
|
|
14313
14314
|
assistantMessage: status,
|
|
14314
|
-
quickReplies: this.
|
|
14315
|
-
canApply:
|
|
14316
|
-
statusText: this.reviewStatusText(status,
|
|
14315
|
+
quickReplies: this.reviewQuickReplies([], intentResolution, preview),
|
|
14316
|
+
canApply: reviewCanApply,
|
|
14317
|
+
statusText: this.reviewStatusText(status, reviewCanApply),
|
|
14317
14318
|
errorText: '',
|
|
14318
14319
|
preview,
|
|
14319
14320
|
diagnostics: this.buildTurnDiagnostics(intentResolution, preview),
|
|
@@ -14445,8 +14446,848 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
14445
14446
|
currentPageSummary: {},
|
|
14446
14447
|
contextHints,
|
|
14447
14448
|
};
|
|
14449
|
+
const localDashboardRepair = this.buildLocalDashboardRepairPreview(prompt, contextHints, intentResolution);
|
|
14450
|
+
if (localDashboardRepair) {
|
|
14451
|
+
return this.applyDashboardRepairPreview(localDashboardRepair, intentResolution);
|
|
14452
|
+
}
|
|
14448
14453
|
return this.completeExecutableStreamPreview(request, prompt, intentResolution, undefined);
|
|
14449
14454
|
}
|
|
14455
|
+
async applyDashboardRepairPreview(preview, intentResolution) {
|
|
14456
|
+
const applied = await this.context.applyLocalPreview(preview);
|
|
14457
|
+
if (!applied.success) {
|
|
14458
|
+
const message = applied.error || this.context.tx('agentic.errors.applyLocal', 'Preview could not be applied.');
|
|
14459
|
+
return {
|
|
14460
|
+
state: 'error',
|
|
14461
|
+
phase: 'preview',
|
|
14462
|
+
assistantMessage: message,
|
|
14463
|
+
canApply: false,
|
|
14464
|
+
statusText: '',
|
|
14465
|
+
errorText: message,
|
|
14466
|
+
preview: null,
|
|
14467
|
+
diagnostics: this.buildTurnDiagnostics(intentResolution, preview),
|
|
14468
|
+
};
|
|
14469
|
+
}
|
|
14470
|
+
const status = this.decorateDashboardReviewStatus(this.context.describePreviewStatus(preview), intentResolution, preview);
|
|
14471
|
+
const reviewCanApply = this.reviewCanApply(intentResolution, preview);
|
|
14472
|
+
return {
|
|
14473
|
+
state: 'review',
|
|
14474
|
+
phase: 'review',
|
|
14475
|
+
assistantMessage: status,
|
|
14476
|
+
quickReplies: this.reviewQuickReplies([], intentResolution, preview),
|
|
14477
|
+
canApply: reviewCanApply,
|
|
14478
|
+
statusText: this.reviewStatusText(status, reviewCanApply),
|
|
14479
|
+
errorText: '',
|
|
14480
|
+
preview,
|
|
14481
|
+
diagnostics: this.buildTurnDiagnostics(intentResolution, preview),
|
|
14482
|
+
};
|
|
14483
|
+
}
|
|
14484
|
+
buildLocalDashboardRepairPreview(prompt, contextHints, intentResolution) {
|
|
14485
|
+
const changeKind = intentResolution.changeKind
|
|
14486
|
+
|| this.readString(contextHints, 'changeKind')
|
|
14487
|
+
|| this.dashboardQualityChangeKindFromActionText(prompt)
|
|
14488
|
+
|| '';
|
|
14489
|
+
if (this.readString(contextHints, 'kind') !== 'dashboard-repair-action' && !changeKind) {
|
|
14490
|
+
return null;
|
|
14491
|
+
}
|
|
14492
|
+
if (![
|
|
14493
|
+
'add_dashboard_kpis',
|
|
14494
|
+
'bind_dashboard_kpis',
|
|
14495
|
+
'add_dashboard_chart',
|
|
14496
|
+
'add_dashboard_surfaces',
|
|
14497
|
+
'connect_dashboard_widgets',
|
|
14498
|
+
].includes(changeKind)) {
|
|
14499
|
+
return null;
|
|
14500
|
+
}
|
|
14501
|
+
const page = this.dashboardRepairBasePage(contextHints);
|
|
14502
|
+
if (!page) {
|
|
14503
|
+
return null;
|
|
14504
|
+
}
|
|
14505
|
+
const repairLog = [];
|
|
14506
|
+
if (changeKind === 'add_dashboard_kpis' || changeKind === 'bind_dashboard_kpis') {
|
|
14507
|
+
this.repairDashboardKpis(page, contextHints, repairLog);
|
|
14508
|
+
}
|
|
14509
|
+
if (changeKind === 'add_dashboard_chart') {
|
|
14510
|
+
this.repairDashboardChart(page, contextHints, repairLog);
|
|
14511
|
+
this.repairDashboardConnections(page, repairLog);
|
|
14512
|
+
}
|
|
14513
|
+
if (changeKind === 'add_dashboard_surfaces') {
|
|
14514
|
+
this.repairDashboardSurfaces(page, contextHints, repairLog);
|
|
14515
|
+
}
|
|
14516
|
+
if (changeKind === 'connect_dashboard_widgets') {
|
|
14517
|
+
this.repairDashboardConnections(page, repairLog);
|
|
14518
|
+
}
|
|
14519
|
+
if (!repairLog.length) {
|
|
14520
|
+
return null;
|
|
14521
|
+
}
|
|
14522
|
+
return {
|
|
14523
|
+
valid: true,
|
|
14524
|
+
failureCodes: [],
|
|
14525
|
+
warnings: [],
|
|
14526
|
+
minimalFormPlan: {},
|
|
14527
|
+
compiledFormPatch: {
|
|
14528
|
+
patch: { page: page },
|
|
14529
|
+
diagnostics: {
|
|
14530
|
+
dashboardQualityRepair: {
|
|
14531
|
+
schemaVersion: 'praxis-dashboard-quality-repair.v1',
|
|
14532
|
+
source: 'dashboard-quality-gate',
|
|
14533
|
+
mode: 'local-deterministic-repair',
|
|
14534
|
+
changeKind,
|
|
14535
|
+
prompt,
|
|
14536
|
+
actions: repairLog,
|
|
14537
|
+
},
|
|
14538
|
+
},
|
|
14539
|
+
},
|
|
14540
|
+
diagnostics: {
|
|
14541
|
+
dashboardQualityRepair: {
|
|
14542
|
+
schemaVersion: 'praxis-dashboard-quality-repair.v1',
|
|
14543
|
+
source: 'dashboard-quality-gate',
|
|
14544
|
+
mode: 'local-deterministic-repair',
|
|
14545
|
+
changeKind,
|
|
14546
|
+
actions: repairLog,
|
|
14547
|
+
},
|
|
14548
|
+
},
|
|
14549
|
+
};
|
|
14550
|
+
}
|
|
14551
|
+
dashboardRepairBasePage(contextHints) {
|
|
14552
|
+
const materializedPage = this.cloneJsonObject(this.toJsonObject(contextHints['materializedPage']));
|
|
14553
|
+
if (this.hasDashboardSnapshotWidgets(materializedPage)) {
|
|
14554
|
+
return materializedPage;
|
|
14555
|
+
}
|
|
14556
|
+
const currentPage = this.cloneJsonObject(this.toJsonObject(this.context.currentPage()));
|
|
14557
|
+
if (this.hasDashboardSnapshotWidgets(currentPage)) {
|
|
14558
|
+
return currentPage;
|
|
14559
|
+
}
|
|
14560
|
+
const plan = this.toJsonObject(contextHints['uiCompositionPlan']);
|
|
14561
|
+
const pageFromPlan = this.pageFromUiCompositionPlan(plan);
|
|
14562
|
+
return this.hasDashboardSnapshotWidgets(pageFromPlan) ? pageFromPlan : null;
|
|
14563
|
+
}
|
|
14564
|
+
pageFromUiCompositionPlan(plan) {
|
|
14565
|
+
if (!plan) {
|
|
14566
|
+
return null;
|
|
14567
|
+
}
|
|
14568
|
+
const widgets = this.arrayFromUnknown(plan['widgets'])
|
|
14569
|
+
.map((widget) => this.toJsonObject(widget))
|
|
14570
|
+
.filter((widget) => !!widget)
|
|
14571
|
+
.map((widget) => ({
|
|
14572
|
+
key: this.readString(widget, 'key') ?? this.readString(widget, 'id') ?? 'dashboard-widget',
|
|
14573
|
+
...(this.toJsonObject(widget['shell']) ? { shell: this.cloneJsonObject(this.toJsonObject(widget['shell'])) } : {}),
|
|
14574
|
+
...(this.readString(widget, 'className') ? { className: this.readString(widget, 'className') } : {}),
|
|
14575
|
+
definition: {
|
|
14576
|
+
id: this.readString(widget, 'componentId') ?? this.readString(widget, 'type') ?? 'praxis-rich-content',
|
|
14577
|
+
bindingOrder: this.arrayFromUnknown(widget['bindingOrder']).map((item) => `${item}`),
|
|
14578
|
+
inputs: this.cloneJsonObject(this.toJsonObject(widget['inputs'])) ?? {},
|
|
14579
|
+
},
|
|
14580
|
+
}));
|
|
14581
|
+
const links = this.arrayFromUnknown(plan['bindings'])
|
|
14582
|
+
.map((binding) => this.toJsonObject(binding))
|
|
14583
|
+
.filter((binding) => !!binding)
|
|
14584
|
+
.map((binding) => this.pageCompositionLinkFromBinding(binding))
|
|
14585
|
+
.filter((link) => !!link);
|
|
14586
|
+
return {
|
|
14587
|
+
title: this.readString(plan, 'title') ?? 'Dashboard',
|
|
14588
|
+
layoutPreset: this.readString(plan, 'layoutPreset'),
|
|
14589
|
+
themePreset: this.readString(plan, 'themePreset'),
|
|
14590
|
+
canvas: this.cloneJsonObject(this.toJsonObject(plan['canvas'])),
|
|
14591
|
+
state: this.cloneJsonObject(this.toJsonObject(plan['state'])),
|
|
14592
|
+
widgets,
|
|
14593
|
+
...(links.length ? { composition: { version: '1.0.0', links } } : {}),
|
|
14594
|
+
};
|
|
14595
|
+
}
|
|
14596
|
+
pageCompositionLinkFromBinding(binding) {
|
|
14597
|
+
const from = this.pageCompositionEndpointFromPlanEndpoint(this.toJsonObject(binding['from']));
|
|
14598
|
+
const to = this.pageCompositionEndpointFromPlanEndpoint(this.toJsonObject(binding['to']));
|
|
14599
|
+
if (!from || !to) {
|
|
14600
|
+
return null;
|
|
14601
|
+
}
|
|
14602
|
+
return {
|
|
14603
|
+
id: this.readString(binding, 'id') ?? `${JSON.stringify(from)}->${JSON.stringify(to)}`,
|
|
14604
|
+
intent: this.readString(binding, 'intent') ?? 'filter',
|
|
14605
|
+
from,
|
|
14606
|
+
to,
|
|
14607
|
+
...(this.toJsonObject(binding['transform']) ? { transform: this.cloneJsonObject(this.toJsonObject(binding['transform'])) } : {}),
|
|
14608
|
+
};
|
|
14609
|
+
}
|
|
14610
|
+
pageCompositionEndpointFromPlanEndpoint(endpoint) {
|
|
14611
|
+
if (!endpoint) {
|
|
14612
|
+
return null;
|
|
14613
|
+
}
|
|
14614
|
+
const kind = this.readString(endpoint, 'kind');
|
|
14615
|
+
if (kind === 'component-port') {
|
|
14616
|
+
return {
|
|
14617
|
+
kind,
|
|
14618
|
+
ref: {
|
|
14619
|
+
widget: this.readString(endpoint, 'widget'),
|
|
14620
|
+
port: this.readString(endpoint, 'port'),
|
|
14621
|
+
direction: this.readString(endpoint, 'direction'),
|
|
14622
|
+
componentType: this.readString(endpoint, 'componentType'),
|
|
14623
|
+
nestedPath: this.cloneJsonObject(this.toJsonObject(endpoint['nestedPath'])),
|
|
14624
|
+
},
|
|
14625
|
+
};
|
|
14626
|
+
}
|
|
14627
|
+
if (kind === 'global-action') {
|
|
14628
|
+
return {
|
|
14629
|
+
kind,
|
|
14630
|
+
ref: {
|
|
14631
|
+
actionId: this.readString(endpoint, 'actionId') ?? this.readString(this.toJsonObject(endpoint['ref']) ?? {}, 'actionId'),
|
|
14632
|
+
payload: this.cloneJsonObject(this.toJsonObject(endpoint['payload'])),
|
|
14633
|
+
},
|
|
14634
|
+
};
|
|
14635
|
+
}
|
|
14636
|
+
if (kind === 'state') {
|
|
14637
|
+
return {
|
|
14638
|
+
kind,
|
|
14639
|
+
ref: {
|
|
14640
|
+
path: this.readString(endpoint, 'path'),
|
|
14641
|
+
},
|
|
14642
|
+
};
|
|
14643
|
+
}
|
|
14644
|
+
return null;
|
|
14645
|
+
}
|
|
14646
|
+
repairDashboardKpis(page, contextHints, repairLog) {
|
|
14647
|
+
const widgets = this.dashboardPageWidgets(page);
|
|
14648
|
+
const detailKey = this.dashboardDetailWidgetKey(page) ?? this.dashboardDetailWidgetKeyFromRepairContext(contextHints);
|
|
14649
|
+
let repaired = false;
|
|
14650
|
+
for (const widget of widgets) {
|
|
14651
|
+
const componentId = this.dashboardWidgetComponentId(widget);
|
|
14652
|
+
const inputs = this.dashboardWidgetInputs(widget);
|
|
14653
|
+
if (!this.isDashboardKpiWidget(componentId, widget, inputs, this.toJsonObject(widget['shell']))) {
|
|
14654
|
+
continue;
|
|
14655
|
+
}
|
|
14656
|
+
const document = this.toJsonObject(inputs['document']);
|
|
14657
|
+
if (!document) {
|
|
14658
|
+
continue;
|
|
14659
|
+
}
|
|
14660
|
+
const kpiKey = this.dashboardWidgetKey(widget);
|
|
14661
|
+
repaired = this.repairRichContentKpiDocument(document) || repaired;
|
|
14662
|
+
const context = this.dashboardKpiInitialContext(inputs['context']);
|
|
14663
|
+
this.setDashboardWidgetInputs(widget, {
|
|
14664
|
+
...inputs,
|
|
14665
|
+
context,
|
|
14666
|
+
document,
|
|
14667
|
+
});
|
|
14668
|
+
this.ensureDashboardWidgetBindingOrder(widget, ['document', 'context']);
|
|
14669
|
+
if (detailKey && this.ensureDashboardKpiContextLinks(page, detailKey, kpiKey)) {
|
|
14670
|
+
repaired = true;
|
|
14671
|
+
}
|
|
14672
|
+
}
|
|
14673
|
+
if (!repaired) {
|
|
14674
|
+
const resourcePath = this.dashboardRepairResourcePath(contextHints);
|
|
14675
|
+
const kpiKey = this.uniqueDashboardWidgetKey(page, 'dashboard-kpis');
|
|
14676
|
+
const kpiWidget = {
|
|
14677
|
+
key: kpiKey,
|
|
14678
|
+
shell: {
|
|
14679
|
+
kind: 'dashboard-card',
|
|
14680
|
+
title: 'Indicadores',
|
|
14681
|
+
subtitle: 'Metricas dinamicas do recurso selecionado',
|
|
14682
|
+
},
|
|
14683
|
+
definition: {
|
|
14684
|
+
id: 'praxis-rich-content',
|
|
14685
|
+
bindingOrder: ['document', 'context', 'resourcePath', 'queryContext'],
|
|
14686
|
+
inputs: {
|
|
14687
|
+
resourcePath,
|
|
14688
|
+
queryContext: { filters: {} },
|
|
14689
|
+
context: this.dashboardKpiInitialContext(),
|
|
14690
|
+
document: this.buildDashboardKpiDocument(),
|
|
14691
|
+
},
|
|
14692
|
+
},
|
|
14693
|
+
};
|
|
14694
|
+
this.insertDashboardWidget(page, kpiWidget, 1);
|
|
14695
|
+
if (detailKey) {
|
|
14696
|
+
this.ensureDashboardKpiContextLinks(page, detailKey, kpiKey);
|
|
14697
|
+
}
|
|
14698
|
+
repaired = true;
|
|
14699
|
+
}
|
|
14700
|
+
if (repaired) {
|
|
14701
|
+
repairLog.push('dashboard-kpis-bound');
|
|
14702
|
+
}
|
|
14703
|
+
}
|
|
14704
|
+
repairRichContentKpiDocument(document) {
|
|
14705
|
+
let repaired = false;
|
|
14706
|
+
for (const node of this.arrayFromUnknown(document['nodes'])) {
|
|
14707
|
+
repaired = this.repairRichContentKpiNode(this.toJsonObject(node)) || repaired;
|
|
14708
|
+
}
|
|
14709
|
+
return repaired;
|
|
14710
|
+
}
|
|
14711
|
+
repairRichContentKpiNode(node) {
|
|
14712
|
+
if (!node) {
|
|
14713
|
+
return false;
|
|
14714
|
+
}
|
|
14715
|
+
let repaired = false;
|
|
14716
|
+
const type = this.readString(node, 'type')?.toLowerCase();
|
|
14717
|
+
if (type === 'metric' || type === 'stat' || type === 'statitem' || type === 'stat-item') {
|
|
14718
|
+
repaired = this.bindKpiNode(node) || repaired;
|
|
14719
|
+
}
|
|
14720
|
+
if (type === 'statgroup' || type === 'stat-group') {
|
|
14721
|
+
if (this.dashboardKpiStatGroupNeedsCanonicalItems(node)) {
|
|
14722
|
+
node['items'] = this.buildDashboardKpiItems();
|
|
14723
|
+
repaired = true;
|
|
14724
|
+
}
|
|
14725
|
+
for (const item of this.arrayFromUnknown(node['items'])) {
|
|
14726
|
+
repaired = this.bindKpiNode(this.toJsonObject(item)) || repaired;
|
|
14727
|
+
}
|
|
14728
|
+
}
|
|
14729
|
+
for (const key of ['nodes', 'items', 'children', 'content']) {
|
|
14730
|
+
for (const child of this.arrayFromUnknown(node[key])) {
|
|
14731
|
+
repaired = this.repairRichContentKpiNode(this.toJsonObject(child)) || repaired;
|
|
14732
|
+
}
|
|
14733
|
+
}
|
|
14734
|
+
return repaired;
|
|
14735
|
+
}
|
|
14736
|
+
dashboardKpiStatGroupNeedsCanonicalItems(node) {
|
|
14737
|
+
const items = this.arrayFromUnknown(node['items'])
|
|
14738
|
+
.map((item) => this.toJsonObject(item))
|
|
14739
|
+
.filter((item) => !!item);
|
|
14740
|
+
if (!items.length) {
|
|
14741
|
+
return true;
|
|
14742
|
+
}
|
|
14743
|
+
const canonicalLabels = new Set(['total filtrado', 'itens na pagina', 'status da consulta']);
|
|
14744
|
+
const hasOnlyResolvableLabels = items.every((item) => canonicalLabels.has(this.normalizeText(this.readString(item, 'label') ?? this.readString(item, 'title') ?? '')));
|
|
14745
|
+
if (hasOnlyResolvableLabels) {
|
|
14746
|
+
return false;
|
|
14747
|
+
}
|
|
14748
|
+
return items.some((item) => !!this.readString(item, 'valuePath')
|
|
14749
|
+
|| !this.readString(item, 'valueExpr')
|
|
14750
|
+
|| ['-', '--', 'n/a'].includes((this.readString(item, 'value') || '').toLowerCase()));
|
|
14751
|
+
}
|
|
14752
|
+
bindKpiNode(node) {
|
|
14753
|
+
if (!node) {
|
|
14754
|
+
return false;
|
|
14755
|
+
}
|
|
14756
|
+
const value = this.readString(node, 'value')?.trim() ?? '';
|
|
14757
|
+
const hasRuntimeExpression = !!this.readString(node, 'valueExpr');
|
|
14758
|
+
if (hasRuntimeExpression && value !== '-' && value !== '--' && value.toLowerCase() !== 'n/a') {
|
|
14759
|
+
return false;
|
|
14760
|
+
}
|
|
14761
|
+
if (!hasRuntimeExpression && value && value !== '-' && value !== '--' && value.toLowerCase() !== 'n/a') {
|
|
14762
|
+
return false;
|
|
14763
|
+
}
|
|
14764
|
+
const label = this.readString(node, 'label') ?? this.readString(node, 'title') ?? '';
|
|
14765
|
+
node['valueExpr'] = this.dashboardKpiValueExpression(label);
|
|
14766
|
+
delete node['valuePath'];
|
|
14767
|
+
delete node['valueTemplate'];
|
|
14768
|
+
delete node['value'];
|
|
14769
|
+
node['format'] = node['format'] ?? 'integer';
|
|
14770
|
+
node['captionExpr'] = this.dashboardKpiCaptionExpression(label);
|
|
14771
|
+
delete node['caption'];
|
|
14772
|
+
return true;
|
|
14773
|
+
}
|
|
14774
|
+
dashboardKpiValueExpression(label) {
|
|
14775
|
+
const normalized = this.normalizeText(label);
|
|
14776
|
+
if (normalized.includes('pagina') || normalized.includes('carregad')) {
|
|
14777
|
+
return '${loadedItemsCount}';
|
|
14778
|
+
}
|
|
14779
|
+
if (normalized.includes('status')) {
|
|
14780
|
+
return '${statusLabel}';
|
|
14781
|
+
}
|
|
14782
|
+
return '${totalItems}';
|
|
14783
|
+
}
|
|
14784
|
+
dashboardKpiCaptionExpression(label) {
|
|
14785
|
+
const normalized = this.normalizeText(label);
|
|
14786
|
+
if (normalized.includes('pagina') || normalized.includes('carregad')) {
|
|
14787
|
+
return '${loadedItemsCaption}';
|
|
14788
|
+
}
|
|
14789
|
+
if (normalized.includes('status')) {
|
|
14790
|
+
return '${statusCaption}';
|
|
14791
|
+
}
|
|
14792
|
+
return '${totalCaption}';
|
|
14793
|
+
}
|
|
14794
|
+
hasDynamicKpiBinding(node) {
|
|
14795
|
+
return !!(this.readString(node, 'valueExpr') || this.readString(node, 'valueTemplate'));
|
|
14796
|
+
}
|
|
14797
|
+
buildDashboardKpiDocument() {
|
|
14798
|
+
return {
|
|
14799
|
+
kind: 'praxis.rich-content',
|
|
14800
|
+
version: '1.0.0',
|
|
14801
|
+
nodes: [
|
|
14802
|
+
{
|
|
14803
|
+
type: 'statGroup',
|
|
14804
|
+
title: 'Leitura executiva',
|
|
14805
|
+
layout: 'grid',
|
|
14806
|
+
items: this.buildDashboardKpiItems(),
|
|
14807
|
+
},
|
|
14808
|
+
],
|
|
14809
|
+
};
|
|
14810
|
+
}
|
|
14811
|
+
buildDashboardKpiItems() {
|
|
14812
|
+
return [
|
|
14813
|
+
{
|
|
14814
|
+
label: 'Total filtrado',
|
|
14815
|
+
valueExpr: '${totalItems}',
|
|
14816
|
+
format: 'integer',
|
|
14817
|
+
icon: 'monitoring',
|
|
14818
|
+
captionExpr: '${totalCaption}',
|
|
14819
|
+
},
|
|
14820
|
+
{
|
|
14821
|
+
label: 'Itens na pagina',
|
|
14822
|
+
valueExpr: '${loadedItemsCount}',
|
|
14823
|
+
format: 'integer',
|
|
14824
|
+
icon: 'view_list',
|
|
14825
|
+
captionExpr: '${loadedItemsCaption}',
|
|
14826
|
+
},
|
|
14827
|
+
{
|
|
14828
|
+
label: 'Status da consulta',
|
|
14829
|
+
valueExpr: '${statusLabel}',
|
|
14830
|
+
icon: 'sync',
|
|
14831
|
+
captionExpr: '${statusCaption}',
|
|
14832
|
+
},
|
|
14833
|
+
];
|
|
14834
|
+
}
|
|
14835
|
+
dashboardKpiInitialContext(current) {
|
|
14836
|
+
return {
|
|
14837
|
+
totalItems: 0,
|
|
14838
|
+
loadedItemsCount: 0,
|
|
14839
|
+
statusLabel: this.context.tx('agentic.dashboardQuality.kpiStatus.loading', 'Carregando'),
|
|
14840
|
+
totalCaption: this.context.tx('agentic.dashboardQuality.kpiCaption.total', 'Total retornado pela consulta filtrada'),
|
|
14841
|
+
loadedItemsCaption: this.context.tx('agentic.dashboardQuality.kpiCaption.loaded', 'Itens carregados nesta pagina'),
|
|
14842
|
+
statusCaption: this.context.tx('agentic.dashboardQuality.kpiCaption.status', 'Atualizado pelo runtime da tabela'),
|
|
14843
|
+
...(this.cloneJsonObject(this.toJsonObject(current)) ?? {}),
|
|
14844
|
+
};
|
|
14845
|
+
}
|
|
14846
|
+
ensureDashboardKpiContextLinks(page, tableKey, kpiKey) {
|
|
14847
|
+
const links = this.dashboardCompositionLinks(page);
|
|
14848
|
+
const writeId = `${tableKey}.loadingStateChange->dashboardKpis`;
|
|
14849
|
+
const readId = `dashboardKpis->${kpiKey}.context`;
|
|
14850
|
+
let changed = false;
|
|
14851
|
+
if (!links.some((link) => this.readString(link, 'id') === writeId)) {
|
|
14852
|
+
links.push({
|
|
14853
|
+
id: writeId,
|
|
14854
|
+
intent: 'state-write',
|
|
14855
|
+
from: {
|
|
14856
|
+
kind: 'component-port',
|
|
14857
|
+
ref: { widget: tableKey, port: 'loadingStateChange', direction: 'output' },
|
|
14858
|
+
},
|
|
14859
|
+
to: {
|
|
14860
|
+
kind: 'state',
|
|
14861
|
+
ref: { path: 'dashboardKpis', layer: 'values', writable: true },
|
|
14862
|
+
},
|
|
14863
|
+
transform: {
|
|
14864
|
+
version: '2.0',
|
|
14865
|
+
phase: 'link-propagation',
|
|
14866
|
+
mode: 'object-fragment',
|
|
14867
|
+
sourceBindings: [{ source: 'event' }],
|
|
14868
|
+
steps: [
|
|
14869
|
+
{
|
|
14870
|
+
id: `${writeId}:summary`,
|
|
14871
|
+
kind: 'object-template',
|
|
14872
|
+
phase: 'link-propagation',
|
|
14873
|
+
input: { source: 'event' },
|
|
14874
|
+
config: {
|
|
14875
|
+
template: {
|
|
14876
|
+
totalItems: '${payload.totalItems}',
|
|
14877
|
+
loadedItemsCount: '${payload.loadedItemsCount}',
|
|
14878
|
+
statusLabel: '${payload.status}',
|
|
14879
|
+
totalCaption: 'Total retornado pela consulta filtrada',
|
|
14880
|
+
loadedItemsCaption: 'Itens carregados nesta pagina',
|
|
14881
|
+
statusCaption: '${payload.message}',
|
|
14882
|
+
},
|
|
14883
|
+
},
|
|
14884
|
+
},
|
|
14885
|
+
],
|
|
14886
|
+
},
|
|
14887
|
+
metadata: { source: 'persisted-composition-link' },
|
|
14888
|
+
});
|
|
14889
|
+
changed = true;
|
|
14890
|
+
}
|
|
14891
|
+
if (!links.some((link) => this.readString(link, 'id') === readId)) {
|
|
14892
|
+
links.push({
|
|
14893
|
+
id: readId,
|
|
14894
|
+
intent: 'state-read',
|
|
14895
|
+
from: {
|
|
14896
|
+
kind: 'state',
|
|
14897
|
+
ref: { path: 'dashboardKpis', layer: 'values' },
|
|
14898
|
+
},
|
|
14899
|
+
to: {
|
|
14900
|
+
kind: 'component-port',
|
|
14901
|
+
ref: { widget: kpiKey, port: 'context', direction: 'input' },
|
|
14902
|
+
},
|
|
14903
|
+
metadata: { source: 'persisted-composition-link' },
|
|
14904
|
+
});
|
|
14905
|
+
changed = true;
|
|
14906
|
+
}
|
|
14907
|
+
if (changed) {
|
|
14908
|
+
const composition = this.toJsonObject(page['composition']) ?? {};
|
|
14909
|
+
page['composition'] = {
|
|
14910
|
+
...composition,
|
|
14911
|
+
version: this.readString(composition, 'version') ?? '1.0.0',
|
|
14912
|
+
links,
|
|
14913
|
+
};
|
|
14914
|
+
}
|
|
14915
|
+
return changed;
|
|
14916
|
+
}
|
|
14917
|
+
repairDashboardChart(page, contextHints, repairLog) {
|
|
14918
|
+
const widgets = this.dashboardPageWidgets(page);
|
|
14919
|
+
if (widgets.some((widget) => this.dashboardWidgetComponentId(widget).includes('chart'))) {
|
|
14920
|
+
return;
|
|
14921
|
+
}
|
|
14922
|
+
const resourcePath = this.dashboardRepairResourcePath(contextHints);
|
|
14923
|
+
const categoryField = this.dashboardCategoryField(page);
|
|
14924
|
+
const chartKey = this.uniqueDashboardWidgetKey(page, 'dashboard-chart');
|
|
14925
|
+
const detailKey = this.dashboardDetailWidgetKey(page) ?? this.dashboardDetailWidgetKeyFromRepairContext(contextHints);
|
|
14926
|
+
this.insertDashboardWidget(page, {
|
|
14927
|
+
key: chartKey,
|
|
14928
|
+
shell: {
|
|
14929
|
+
kind: 'dashboard-card',
|
|
14930
|
+
title: `Distribuicao por ${this.humanizeFieldName(categoryField)}`,
|
|
14931
|
+
subtitle: 'Agrupamento analitico do mesmo recurso',
|
|
14932
|
+
},
|
|
14933
|
+
definition: {
|
|
14934
|
+
id: 'praxis-chart',
|
|
14935
|
+
bindingOrder: ['chartDocument', 'queryContext', 'enableCustomization'],
|
|
14936
|
+
inputs: {
|
|
14937
|
+
queryContext: { filters: {} },
|
|
14938
|
+
enableCustomization: true,
|
|
14939
|
+
chartDocument: {
|
|
14940
|
+
version: '1.0.0',
|
|
14941
|
+
chartId: chartKey,
|
|
14942
|
+
kind: 'bar',
|
|
14943
|
+
preset: 'dashboard-breakdown',
|
|
14944
|
+
title: `Distribuicao por ${this.humanizeFieldName(categoryField)}`,
|
|
14945
|
+
subtitle: 'Clique em uma barra para refinar os detalhes',
|
|
14946
|
+
source: {
|
|
14947
|
+
kind: 'praxis.stats',
|
|
14948
|
+
resource: resourcePath,
|
|
14949
|
+
operation: 'group-by',
|
|
14950
|
+
options: {
|
|
14951
|
+
groupBy: categoryField,
|
|
14952
|
+
metric: 'count',
|
|
14953
|
+
orderBy: 'value-desc',
|
|
14954
|
+
limit: 12,
|
|
14955
|
+
},
|
|
14956
|
+
},
|
|
14957
|
+
dimensions: [{ field: categoryField, label: this.humanizeFieldName(categoryField), role: 'category' }],
|
|
14958
|
+
metrics: [{ field: 'count', label: 'Registros', aggregation: 'count', seriesKind: 'bar' }],
|
|
14959
|
+
legend: false,
|
|
14960
|
+
labels: true,
|
|
14961
|
+
tooltip: true,
|
|
14962
|
+
events: {
|
|
14963
|
+
selectionChange: { action: 'emit' },
|
|
14964
|
+
pointClick: { action: 'emit' },
|
|
14965
|
+
},
|
|
14966
|
+
},
|
|
14967
|
+
},
|
|
14968
|
+
},
|
|
14969
|
+
}, Math.max(2, widgets.length - 1));
|
|
14970
|
+
if (detailKey) {
|
|
14971
|
+
this.addDashboardQueryContextLink(page, chartKey, 'selectionChange', detailKey);
|
|
14972
|
+
}
|
|
14973
|
+
repairLog.push('dashboard-chart-added');
|
|
14974
|
+
}
|
|
14975
|
+
repairDashboardSurfaces(page, contextHints, repairLog) {
|
|
14976
|
+
const resourcePath = this.dashboardRepairResourcePath(contextHints);
|
|
14977
|
+
let repaired = false;
|
|
14978
|
+
for (const widget of this.dashboardPageWidgets(page)) {
|
|
14979
|
+
const componentId = this.dashboardWidgetComponentId(widget);
|
|
14980
|
+
if (!componentId.includes('table') && !componentId.includes('list') && !componentId.includes('chart')) {
|
|
14981
|
+
continue;
|
|
14982
|
+
}
|
|
14983
|
+
const inputs = this.dashboardWidgetInputs(widget);
|
|
14984
|
+
const rowActions = this.arrayFromUnknown(inputs['rowActions'])
|
|
14985
|
+
.map((action) => this.cloneJsonObject(this.toJsonObject(action)))
|
|
14986
|
+
.filter((action) => !!action);
|
|
14987
|
+
const surfaces = this.arrayFromUnknown(inputs['surfaces'])
|
|
14988
|
+
.map((action) => this.cloneJsonObject(this.toJsonObject(action)))
|
|
14989
|
+
.filter((action) => !!action);
|
|
14990
|
+
const surfaceAction = {
|
|
14991
|
+
id: `${this.dashboardWidgetKey(widget)}-open-360`,
|
|
14992
|
+
action: 'surface.open',
|
|
14993
|
+
title: 'Abrir 360',
|
|
14994
|
+
icon: 'open_in_new',
|
|
14995
|
+
presentation: 'modal',
|
|
14996
|
+
resourceSurface: {
|
|
14997
|
+
id: `${this.dashboardWidgetKey(widget)}-record-360`,
|
|
14998
|
+
title: 'Detalhes 360',
|
|
14999
|
+
resourcePath,
|
|
15000
|
+
presentation: 'modal',
|
|
15001
|
+
},
|
|
15002
|
+
widget: {
|
|
15003
|
+
id: 'praxis-rich-content',
|
|
15004
|
+
inputs: {
|
|
15005
|
+
resourcePath,
|
|
15006
|
+
document: {
|
|
15007
|
+
kind: 'praxis.rich-content',
|
|
15008
|
+
version: '1.0.0',
|
|
15009
|
+
nodes: [
|
|
15010
|
+
{
|
|
15011
|
+
type: 'callout',
|
|
15012
|
+
tone: 'info',
|
|
15013
|
+
icon: 'badge',
|
|
15014
|
+
titleExpr: '${payload.item.nomeCompleto || payload.item.name || payload.label || "Registro"}',
|
|
15015
|
+
message: 'Surface 360 gerada pelo dashboard para explorar o registro selecionado.',
|
|
15016
|
+
},
|
|
15017
|
+
],
|
|
15018
|
+
},
|
|
15019
|
+
},
|
|
15020
|
+
},
|
|
15021
|
+
};
|
|
15022
|
+
if (!rowActions.some((action) => this.readString(this.toJsonObject(action) ?? {}, 'action') === 'surface.open')) {
|
|
15023
|
+
rowActions.push(surfaceAction);
|
|
15024
|
+
repaired = true;
|
|
15025
|
+
}
|
|
15026
|
+
if (!surfaces.some((action) => this.readString(this.toJsonObject(action) ?? {}, 'action') === 'surface.open')) {
|
|
15027
|
+
surfaces.push(surfaceAction);
|
|
15028
|
+
repaired = true;
|
|
15029
|
+
}
|
|
15030
|
+
this.setDashboardWidgetInputs(widget, { ...inputs, rowActions, surfaces });
|
|
15031
|
+
}
|
|
15032
|
+
if (repaired) {
|
|
15033
|
+
repairLog.push('dashboard-surfaces-added');
|
|
15034
|
+
}
|
|
15035
|
+
}
|
|
15036
|
+
repairDashboardConnections(page, repairLog) {
|
|
15037
|
+
const widgets = this.dashboardPageWidgets(page);
|
|
15038
|
+
const detailWidget = widgets.find((widget) => {
|
|
15039
|
+
const componentId = this.dashboardWidgetComponentId(widget);
|
|
15040
|
+
return componentId.includes('table') || componentId.includes('list');
|
|
15041
|
+
});
|
|
15042
|
+
if (!detailWidget) {
|
|
15043
|
+
return;
|
|
15044
|
+
}
|
|
15045
|
+
const detailKey = this.dashboardWidgetKey(detailWidget);
|
|
15046
|
+
const links = this.dashboardCompositionLinks(page);
|
|
15047
|
+
let repaired = false;
|
|
15048
|
+
for (const widget of widgets) {
|
|
15049
|
+
const componentId = this.dashboardWidgetComponentId(widget);
|
|
15050
|
+
const widgetKey = this.dashboardWidgetKey(widget);
|
|
15051
|
+
if (widgetKey === detailKey) {
|
|
15052
|
+
continue;
|
|
15053
|
+
}
|
|
15054
|
+
const port = componentId.includes('filter')
|
|
15055
|
+
? 'requestSearch'
|
|
15056
|
+
: componentId.includes('chart')
|
|
15057
|
+
? 'selectionChange'
|
|
15058
|
+
: '';
|
|
15059
|
+
if (!port) {
|
|
15060
|
+
continue;
|
|
15061
|
+
}
|
|
15062
|
+
const exists = links.some((link) => {
|
|
15063
|
+
const from = this.summarizeEndpoint(this.toJsonObject(link)?.['from']);
|
|
15064
|
+
const to = this.summarizeEndpoint(this.toJsonObject(link)?.['to']);
|
|
15065
|
+
const fromEndpoint = this.toJsonObject(from);
|
|
15066
|
+
const toEndpoint = this.toJsonObject(to);
|
|
15067
|
+
return this.readString(fromEndpoint ?? {}, 'widget') === widgetKey
|
|
15068
|
+
&& this.readString(toEndpoint ?? {}, 'widget') === detailKey
|
|
15069
|
+
&& this.readString(toEndpoint ?? {}, 'port') === 'queryContext';
|
|
15070
|
+
});
|
|
15071
|
+
if (exists) {
|
|
15072
|
+
continue;
|
|
15073
|
+
}
|
|
15074
|
+
links.push({
|
|
15075
|
+
...this.dashboardQueryContextLink(widgetKey, port, detailKey),
|
|
15076
|
+
});
|
|
15077
|
+
repaired = true;
|
|
15078
|
+
}
|
|
15079
|
+
if (repaired) {
|
|
15080
|
+
const composition = this.toJsonObject(page['composition']) ?? {};
|
|
15081
|
+
page['composition'] = {
|
|
15082
|
+
...composition,
|
|
15083
|
+
version: this.readString(composition, 'version') ?? '1.0.0',
|
|
15084
|
+
links,
|
|
15085
|
+
};
|
|
15086
|
+
repairLog.push('dashboard-widgets-connected');
|
|
15087
|
+
}
|
|
15088
|
+
}
|
|
15089
|
+
dashboardDetailWidgetKey(page) {
|
|
15090
|
+
const detailWidget = this.dashboardPageWidgets(page).find((widget) => {
|
|
15091
|
+
const componentId = this.dashboardWidgetComponentId(widget);
|
|
15092
|
+
return componentId.includes('table') || componentId.includes('list');
|
|
15093
|
+
});
|
|
15094
|
+
return detailWidget ? this.dashboardWidgetKey(detailWidget) : null;
|
|
15095
|
+
}
|
|
15096
|
+
dashboardDetailWidgetKeyFromRepairContext(contextHints) {
|
|
15097
|
+
const dashboardQuality = this.toJsonObject(contextHints['dashboardQuality']);
|
|
15098
|
+
for (const widget of this.arrayFromUnknown(dashboardQuality?.['widgets'])) {
|
|
15099
|
+
const record = this.toJsonObject(widget);
|
|
15100
|
+
const componentId = (this.readString(record, 'componentId') ?? '').toLowerCase();
|
|
15101
|
+
if (componentId.includes('table') || componentId.includes('list')) {
|
|
15102
|
+
return this.readString(record, 'key');
|
|
15103
|
+
}
|
|
15104
|
+
}
|
|
15105
|
+
return null;
|
|
15106
|
+
}
|
|
15107
|
+
addDashboardQueryContextLink(page, fromWidgetKey, fromPort, toWidgetKey) {
|
|
15108
|
+
const links = this.dashboardCompositionLinks(page);
|
|
15109
|
+
const link = this.dashboardQueryContextLink(fromWidgetKey, fromPort, toWidgetKey);
|
|
15110
|
+
if (links.some((candidate) => this.readString(candidate, 'id') === link.id)) {
|
|
15111
|
+
return false;
|
|
15112
|
+
}
|
|
15113
|
+
links.push(link);
|
|
15114
|
+
const composition = this.toJsonObject(page['composition']) ?? {};
|
|
15115
|
+
page['composition'] = {
|
|
15116
|
+
...composition,
|
|
15117
|
+
version: this.readString(composition, 'version') ?? '1.0.0',
|
|
15118
|
+
links,
|
|
15119
|
+
};
|
|
15120
|
+
return true;
|
|
15121
|
+
}
|
|
15122
|
+
dashboardQueryContextLink(fromWidgetKey, fromPort, toWidgetKey) {
|
|
15123
|
+
return {
|
|
15124
|
+
id: `${fromWidgetKey}.${fromPort}->${toWidgetKey}.queryContext`,
|
|
15125
|
+
intent: 'filter',
|
|
15126
|
+
from: {
|
|
15127
|
+
kind: 'component-port',
|
|
15128
|
+
ref: { widget: fromWidgetKey, port: fromPort, direction: 'output' },
|
|
15129
|
+
},
|
|
15130
|
+
to: {
|
|
15131
|
+
kind: 'component-port',
|
|
15132
|
+
ref: { widget: toWidgetKey, port: 'queryContext', direction: 'input' },
|
|
15133
|
+
},
|
|
15134
|
+
transform: { kind: 'query-context' },
|
|
15135
|
+
};
|
|
15136
|
+
}
|
|
15137
|
+
dashboardPageWidgets(page) {
|
|
15138
|
+
return this.arrayFromUnknown(page['widgets'])
|
|
15139
|
+
.map((widget) => this.toJsonObject(widget))
|
|
15140
|
+
.filter((widget) => !!widget);
|
|
15141
|
+
}
|
|
15142
|
+
dashboardCompositionLinks(page) {
|
|
15143
|
+
const composition = this.toJsonObject(page['composition']) ?? {};
|
|
15144
|
+
const links = this.arrayFromUnknown(composition['links'])
|
|
15145
|
+
.map((link) => this.toJsonObject(link))
|
|
15146
|
+
.filter((link) => !!link);
|
|
15147
|
+
if (!composition['links']) {
|
|
15148
|
+
page['composition'] = { ...composition, version: '1.0.0', links };
|
|
15149
|
+
}
|
|
15150
|
+
return links;
|
|
15151
|
+
}
|
|
15152
|
+
dashboardWidgetComponentId(widget) {
|
|
15153
|
+
return (this.readString(widget, 'componentId')
|
|
15154
|
+
|| this.readString(this.toJsonObject(widget['definition']) ?? {}, 'id')
|
|
15155
|
+
|| this.readString(widget, 'type')
|
|
15156
|
+
|| '').toLowerCase();
|
|
15157
|
+
}
|
|
15158
|
+
dashboardWidgetKey(widget) {
|
|
15159
|
+
return this.readString(widget, 'key') || this.readString(widget, 'id') || 'dashboard-widget';
|
|
15160
|
+
}
|
|
15161
|
+
dashboardWidgetInputs(widget) {
|
|
15162
|
+
return this.cloneJsonObject(this.toJsonObject(widget['inputs'])
|
|
15163
|
+
?? this.toJsonObject(this.toJsonObject(widget['definition'])?.['inputs'])
|
|
15164
|
+
?? this.toJsonObject(widget['inputValues'])
|
|
15165
|
+
?? this.toJsonObject(widget['props'])
|
|
15166
|
+
?? this.toJsonObject(widget['config'])
|
|
15167
|
+
?? {}) ?? {};
|
|
15168
|
+
}
|
|
15169
|
+
setDashboardWidgetInputs(widget, inputs) {
|
|
15170
|
+
const definition = this.toJsonObject(widget['definition']);
|
|
15171
|
+
if (definition) {
|
|
15172
|
+
definition['inputs'] = inputs;
|
|
15173
|
+
widget['definition'] = definition;
|
|
15174
|
+
return;
|
|
15175
|
+
}
|
|
15176
|
+
widget['inputs'] = inputs;
|
|
15177
|
+
}
|
|
15178
|
+
ensureDashboardWidgetBindingOrder(widget, required) {
|
|
15179
|
+
const definition = this.toJsonObject(widget['definition']);
|
|
15180
|
+
if (!definition) {
|
|
15181
|
+
return;
|
|
15182
|
+
}
|
|
15183
|
+
const current = this.arrayFromUnknown(definition['bindingOrder'])
|
|
15184
|
+
.map((item) => `${item}`.trim())
|
|
15185
|
+
.filter(Boolean);
|
|
15186
|
+
const next = [...current];
|
|
15187
|
+
for (const item of required) {
|
|
15188
|
+
if (!next.includes(item)) {
|
|
15189
|
+
next.push(item);
|
|
15190
|
+
}
|
|
15191
|
+
}
|
|
15192
|
+
definition['bindingOrder'] = next;
|
|
15193
|
+
widget['definition'] = definition;
|
|
15194
|
+
}
|
|
15195
|
+
insertDashboardWidget(page, widget, index) {
|
|
15196
|
+
const widgets = this.dashboardPageWidgets(page);
|
|
15197
|
+
widgets.splice(Math.max(0, Math.min(index, widgets.length)), 0, widget);
|
|
15198
|
+
page['widgets'] = widgets;
|
|
15199
|
+
this.ensureDashboardCanvasItem(page, this.dashboardWidgetKey(widget), this.dashboardWidgetComponentId(widget));
|
|
15200
|
+
}
|
|
15201
|
+
ensureDashboardCanvasItem(page, widgetKey, componentId) {
|
|
15202
|
+
if (!widgetKey) {
|
|
15203
|
+
return;
|
|
15204
|
+
}
|
|
15205
|
+
const canvas = this.toJsonObject(page['canvas']);
|
|
15206
|
+
if (!canvas) {
|
|
15207
|
+
return;
|
|
15208
|
+
}
|
|
15209
|
+
const items = this.toJsonObject(canvas['items']) ?? {};
|
|
15210
|
+
if (this.toJsonObject(items[widgetKey])) {
|
|
15211
|
+
return;
|
|
15212
|
+
}
|
|
15213
|
+
const columns = Math.max(1, Number(canvas['columns']) || 12);
|
|
15214
|
+
const existingItems = Object.values(items)
|
|
15215
|
+
.map((item) => this.toJsonObject(item))
|
|
15216
|
+
.filter((item) => !!item);
|
|
15217
|
+
const maxRowEnd = existingItems.reduce((max, item) => {
|
|
15218
|
+
const row = Math.max(1, Number(item['row']) || 1);
|
|
15219
|
+
const rowSpan = Math.max(1, Number(item['rowSpan']) || 1);
|
|
15220
|
+
return Math.max(max, row + rowSpan);
|
|
15221
|
+
}, 1);
|
|
15222
|
+
const isChart = componentId.includes('chart') || widgetKey.toLowerCase().includes('chart');
|
|
15223
|
+
const colSpan = Math.min(columns, isChart ? Math.max(6, Math.floor(columns / 2)) : columns);
|
|
15224
|
+
items[widgetKey] = {
|
|
15225
|
+
col: 1,
|
|
15226
|
+
row: maxRowEnd,
|
|
15227
|
+
colSpan,
|
|
15228
|
+
rowSpan: isChart ? 5 : 3,
|
|
15229
|
+
};
|
|
15230
|
+
canvas['items'] = items;
|
|
15231
|
+
page['canvas'] = canvas;
|
|
15232
|
+
}
|
|
15233
|
+
uniqueDashboardWidgetKey(page, baseKey) {
|
|
15234
|
+
const keys = new Set(this.dashboardPageWidgets(page).map((widget) => this.dashboardWidgetKey(widget)));
|
|
15235
|
+
if (!keys.has(baseKey)) {
|
|
15236
|
+
return baseKey;
|
|
15237
|
+
}
|
|
15238
|
+
let index = 2;
|
|
15239
|
+
while (keys.has(`${baseKey}-${index}`)) {
|
|
15240
|
+
index += 1;
|
|
15241
|
+
}
|
|
15242
|
+
return `${baseKey}-${index}`;
|
|
15243
|
+
}
|
|
15244
|
+
dashboardRepairResourcePath(contextHints) {
|
|
15245
|
+
return this.readString(contextHints, 'resourcePath')
|
|
15246
|
+
?? this.readString(this.toJsonObject(this.toJsonObject(contextHints['dashboardQuality'])?.['dto']) ?? {}, 'resourcePath')
|
|
15247
|
+
?? this.dashboardFirstResourcePath(this.toJsonObject(contextHints['materializedPage']))
|
|
15248
|
+
?? '/api/resource';
|
|
15249
|
+
}
|
|
15250
|
+
dashboardFirstResourcePath(page) {
|
|
15251
|
+
if (!page) {
|
|
15252
|
+
return null;
|
|
15253
|
+
}
|
|
15254
|
+
for (const widget of this.dashboardPageWidgets(page)) {
|
|
15255
|
+
const resourcePath = this.readString(this.dashboardWidgetInputs(widget), 'resourcePath');
|
|
15256
|
+
if (resourcePath) {
|
|
15257
|
+
return resourcePath;
|
|
15258
|
+
}
|
|
15259
|
+
}
|
|
15260
|
+
return null;
|
|
15261
|
+
}
|
|
15262
|
+
dashboardCategoryField(page) {
|
|
15263
|
+
const preferred = ['departamentoId', 'departamentoNome', 'cargoId', 'cargoNome', 'status', 'ativo'];
|
|
15264
|
+
const fieldIds = this.dashboardPageWidgets(page)
|
|
15265
|
+
.flatMap((widget) => this.arrayFromUnknown(this.dashboardWidgetInputs(widget)['selectedFieldIds']).map((field) => `${field}`));
|
|
15266
|
+
return preferred.find((field) => fieldIds.includes(field))
|
|
15267
|
+
?? fieldIds.find((field) => !/(^id$|nome|name|email|data|date)/i.test(field))
|
|
15268
|
+
?? 'status';
|
|
15269
|
+
}
|
|
15270
|
+
humanizeFieldName(field) {
|
|
15271
|
+
return field
|
|
15272
|
+
.replace(/Id$/i, '')
|
|
15273
|
+
.replace(/Nome$/i, '')
|
|
15274
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
15275
|
+
.replace(/[_-]+/g, ' ')
|
|
15276
|
+
.trim()
|
|
15277
|
+
.replace(/^./, (value) => value.toUpperCase());
|
|
15278
|
+
}
|
|
15279
|
+
normalizeText(value) {
|
|
15280
|
+
return value
|
|
15281
|
+
.normalize('NFD')
|
|
15282
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
15283
|
+
.toLowerCase();
|
|
15284
|
+
}
|
|
15285
|
+
cloneJsonObject(value) {
|
|
15286
|
+
if (!value) {
|
|
15287
|
+
return null;
|
|
15288
|
+
}
|
|
15289
|
+
return JSON.parse(JSON.stringify(value));
|
|
15290
|
+
}
|
|
14450
15291
|
async buildTurnStreamRequest(request, prompt) {
|
|
14451
15292
|
const startedAt = Date.now();
|
|
14452
15293
|
const capabilitiesStartedAt = Date.now();
|
|
@@ -14639,13 +15480,14 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
14639
15480
|
};
|
|
14640
15481
|
}
|
|
14641
15482
|
const status = this.decorateDashboardReviewStatus(assistantMessage || this.context.describePreviewStatus(preview), intentResolution, preview);
|
|
15483
|
+
const reviewCanApply = this.reviewCanApply(intentResolution, preview);
|
|
14642
15484
|
return {
|
|
14643
15485
|
state: 'review',
|
|
14644
15486
|
phase: 'review',
|
|
14645
15487
|
assistantMessage: status,
|
|
14646
|
-
quickReplies: this.
|
|
14647
|
-
canApply:
|
|
14648
|
-
statusText: this.reviewStatusText(status,
|
|
15488
|
+
quickReplies: this.reviewQuickReplies(quickReplies, intentResolution, preview),
|
|
15489
|
+
canApply: reviewCanApply,
|
|
15490
|
+
statusText: this.reviewStatusText(status, reviewCanApply),
|
|
14649
15491
|
errorText: '',
|
|
14650
15492
|
preview,
|
|
14651
15493
|
diagnostics: this.buildTurnDiagnostics(intentResolution, preview),
|
|
@@ -14713,13 +15555,14 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
14713
15555
|
};
|
|
14714
15556
|
}
|
|
14715
15557
|
const status = this.decorateDashboardReviewStatus(this.context.describePreviewStatus(preview), intentResolution, preview);
|
|
15558
|
+
const reviewCanApply = this.reviewCanApply(intentResolution, preview);
|
|
14716
15559
|
return {
|
|
14717
15560
|
state: 'review',
|
|
14718
15561
|
phase: 'review',
|
|
14719
15562
|
assistantMessage: status,
|
|
14720
|
-
quickReplies: this.
|
|
14721
|
-
canApply:
|
|
14722
|
-
statusText: this.reviewStatusText(status,
|
|
15563
|
+
quickReplies: this.reviewQuickReplies([], intentResolution, preview),
|
|
15564
|
+
canApply: reviewCanApply,
|
|
15565
|
+
statusText: this.reviewStatusText(status, reviewCanApply),
|
|
14723
15566
|
errorText: '',
|
|
14724
15567
|
preview,
|
|
14725
15568
|
diagnostics: this.buildTurnDiagnostics(intentResolution, preview),
|
|
@@ -15014,7 +15857,13 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
15014
15857
|
return true;
|
|
15015
15858
|
}
|
|
15016
15859
|
if (componentId === 'praxis-rich-content') {
|
|
15017
|
-
|
|
15860
|
+
if (this.richContentDocumentHasMetrics(this.toJsonObject(inputs['document']))) {
|
|
15861
|
+
return true;
|
|
15862
|
+
}
|
|
15863
|
+
const serializedDocument = JSON.stringify(inputs['document'] ?? '').toLowerCase();
|
|
15864
|
+
return serializedDocument.includes('statgroup')
|
|
15865
|
+
|| serializedDocument.includes('total filtrado')
|
|
15866
|
+
|| serializedDocument.includes('leitura executiva');
|
|
15018
15867
|
}
|
|
15019
15868
|
return false;
|
|
15020
15869
|
}
|
|
@@ -15068,6 +15917,9 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
15068
15917
|
if (!node) {
|
|
15069
15918
|
return;
|
|
15070
15919
|
}
|
|
15920
|
+
if (this.hasDynamicKpiBinding(node)) {
|
|
15921
|
+
return;
|
|
15922
|
+
}
|
|
15071
15923
|
const value = this.readString(node, 'value')?.trim() ?? '';
|
|
15072
15924
|
if (!value || value === '-' || value === '--' || value.toLowerCase() === 'n/a') {
|
|
15073
15925
|
const label = this.readString(node, 'label') ?? this.readString(node, 'id') ?? 'metric';
|
|
@@ -15228,6 +16080,24 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
15228
16080
|
const normalized = status.trim();
|
|
15229
16081
|
return normalized ? `${normalized} ${suffix}` : suffix;
|
|
15230
16082
|
}
|
|
16083
|
+
dashboardReviewCanApply(intentResolution, preview) {
|
|
16084
|
+
const diagnostics = this.buildDashboardAuthoringDiagnostics(intentResolution, preview);
|
|
16085
|
+
const validation = this.toJsonObject(diagnostics?.['validation']);
|
|
16086
|
+
const warnings = Array.isArray(validation?.['warnings'])
|
|
16087
|
+
? validation?.['warnings'].map((warning) => `${warning}`)
|
|
16088
|
+
: [];
|
|
16089
|
+
return warnings.length === 0;
|
|
16090
|
+
}
|
|
16091
|
+
reviewCanApply(intentResolution, preview) {
|
|
16092
|
+
return intentResolution.artifactKind === 'dashboard'
|
|
16093
|
+
? this.dashboardReviewCanApply(intentResolution, preview)
|
|
16094
|
+
: true;
|
|
16095
|
+
}
|
|
16096
|
+
reviewQuickReplies(quickReplies, intentResolution, preview) {
|
|
16097
|
+
return intentResolution.artifactKind === 'dashboard'
|
|
16098
|
+
? this.mergeDashboardQualityQuickReplies(quickReplies, intentResolution, preview)
|
|
16099
|
+
: [...quickReplies];
|
|
16100
|
+
}
|
|
15231
16101
|
describeDashboardQualityWarning(code) {
|
|
15232
16102
|
switch (code) {
|
|
15233
16103
|
case 'dashboard-without-chart-widget':
|
|
@@ -15264,7 +16134,9 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
15264
16134
|
];
|
|
15265
16135
|
}
|
|
15266
16136
|
dashboardQualityQuickReplies(intentResolution, preview) {
|
|
15267
|
-
|
|
16137
|
+
const patch = this.toJsonObject(preview.compiledFormPatch)?.['patch'];
|
|
16138
|
+
const materializedPage = this.toJsonObject(this.toJsonObject(patch)?.['page']);
|
|
16139
|
+
if (!preview.uiCompositionPlan && !this.hasDashboardSnapshotWidgets(materializedPage)) {
|
|
15268
16140
|
return [];
|
|
15269
16141
|
}
|
|
15270
16142
|
const diagnostics = this.buildDashboardAuthoringDiagnostics(intentResolution, preview);
|
|
@@ -16069,7 +16941,26 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
16069
16941
|
}
|
|
16070
16942
|
const actionId = request?.action?.id?.trim();
|
|
16071
16943
|
if (!actionId) {
|
|
16072
|
-
return
|
|
16944
|
+
return this.dashboardQualityActionContextFromPrompt(request);
|
|
16945
|
+
}
|
|
16946
|
+
if (actionId.startsWith('dashboard-quality-')) {
|
|
16947
|
+
const changeKind = this.dashboardQualityChangeKindFromActionId(actionId);
|
|
16948
|
+
if (changeKind) {
|
|
16949
|
+
const currentPage = this.cloneJsonObject(this.toJsonObject(this.context.currentPage()));
|
|
16950
|
+
return {
|
|
16951
|
+
source: 'dashboard-quality-gate',
|
|
16952
|
+
kind: 'dashboard-repair-action',
|
|
16953
|
+
operationKind: 'modify',
|
|
16954
|
+
artifactKind: 'dashboard',
|
|
16955
|
+
changeKind,
|
|
16956
|
+
resourcePath: this.dashboardFirstResourcePath(currentPage) ?? '',
|
|
16957
|
+
...(currentPage ? { materializedPage: currentPage } : {}),
|
|
16958
|
+
};
|
|
16959
|
+
}
|
|
16960
|
+
}
|
|
16961
|
+
const dashboardQualityContext = this.dashboardQualityActionContextFromPrompt(request);
|
|
16962
|
+
if (dashboardQualityContext) {
|
|
16963
|
+
return dashboardQualityContext;
|
|
16073
16964
|
}
|
|
16074
16965
|
const base = {
|
|
16075
16966
|
source: 'component-capability-catalog',
|
|
@@ -16116,6 +17007,90 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
16116
17007
|
}
|
|
16117
17008
|
return null;
|
|
16118
17009
|
}
|
|
17010
|
+
dashboardQualityActionContextFromPrompt(request) {
|
|
17011
|
+
const text = [
|
|
17012
|
+
request?.prompt,
|
|
17013
|
+
typeof request?.action?.value === 'string' ? request.action.value : undefined,
|
|
17014
|
+
request?.action?.displayPrompt,
|
|
17015
|
+
]
|
|
17016
|
+
.map((value) => value?.trim().toLowerCase())
|
|
17017
|
+
.find((value) => !!value) ?? '';
|
|
17018
|
+
const changeKind = this.dashboardQualityChangeKindFromActionText(text);
|
|
17019
|
+
if (!changeKind) {
|
|
17020
|
+
return null;
|
|
17021
|
+
}
|
|
17022
|
+
const currentPage = this.cloneJsonObject(this.toJsonObject(this.context.currentPage()));
|
|
17023
|
+
if (!currentPage || this.dashboardPageWidgets(currentPage).length === 0) {
|
|
17024
|
+
return null;
|
|
17025
|
+
}
|
|
17026
|
+
return {
|
|
17027
|
+
source: 'dashboard-quality-gate',
|
|
17028
|
+
kind: 'dashboard-repair-action',
|
|
17029
|
+
operationKind: 'modify',
|
|
17030
|
+
artifactKind: 'dashboard',
|
|
17031
|
+
changeKind,
|
|
17032
|
+
resourcePath: this.dashboardFirstResourcePath(currentPage) ?? '',
|
|
17033
|
+
materializedPage: currentPage,
|
|
17034
|
+
};
|
|
17035
|
+
}
|
|
17036
|
+
dashboardQualityChangeKindFromActionId(actionId) {
|
|
17037
|
+
switch (actionId) {
|
|
17038
|
+
case 'dashboard-quality-add-kpis':
|
|
17039
|
+
return 'add_dashboard_kpis';
|
|
17040
|
+
case 'dashboard-quality-bind-kpis':
|
|
17041
|
+
return 'bind_dashboard_kpis';
|
|
17042
|
+
case 'dashboard-quality-add-chart':
|
|
17043
|
+
return 'add_dashboard_chart';
|
|
17044
|
+
case 'dashboard-quality-add-surfaces':
|
|
17045
|
+
return 'add_dashboard_surfaces';
|
|
17046
|
+
case 'dashboard-quality-add-details':
|
|
17047
|
+
return 'add_dashboard_detail_widget';
|
|
17048
|
+
case 'dashboard-quality-connect-widgets':
|
|
17049
|
+
return 'connect_dashboard_widgets';
|
|
17050
|
+
default:
|
|
17051
|
+
return '';
|
|
17052
|
+
}
|
|
17053
|
+
}
|
|
17054
|
+
dashboardQualityChangeKindFromActionText(text) {
|
|
17055
|
+
const normalized = text.trim().toLowerCase();
|
|
17056
|
+
if (normalized.includes('placeholder') && normalized.includes('kpi')) {
|
|
17057
|
+
return 'bind_dashboard_kpis';
|
|
17058
|
+
}
|
|
17059
|
+
if (normalized.includes('surface.open')
|
|
17060
|
+
|| (normalized.includes('surface') && (normalized.includes('modal') || normalized.includes('drawer')))
|
|
17061
|
+
|| (normalized.includes('drill') && (normalized.includes('modal') || normalized.includes('drawer')))) {
|
|
17062
|
+
return 'add_dashboard_surfaces';
|
|
17063
|
+
}
|
|
17064
|
+
if (normalized.includes('analytical chart')
|
|
17065
|
+
|| normalized.includes('most relevant') && normalized.includes('chart')
|
|
17066
|
+
|| normalized.includes('grafico') && normalized.includes('analitico')
|
|
17067
|
+
|| normalized.includes('gráfico') && normalized.includes('analítico')) {
|
|
17068
|
+
return 'add_dashboard_chart';
|
|
17069
|
+
}
|
|
17070
|
+
switch (normalized) {
|
|
17071
|
+
case 'add kpis':
|
|
17072
|
+
case 'bind kpi values':
|
|
17073
|
+
case 'vincular valores dos kpis':
|
|
17074
|
+
return normalized === 'add kpis' ? 'add_dashboard_kpis' : 'bind_dashboard_kpis';
|
|
17075
|
+
case 'add chart':
|
|
17076
|
+
case 'adicionar grafico':
|
|
17077
|
+
case 'adicionar gráfico':
|
|
17078
|
+
return 'add_dashboard_chart';
|
|
17079
|
+
case 'add surfaces':
|
|
17080
|
+
case 'adicionar surfaces':
|
|
17081
|
+
case 'adicionar superficies':
|
|
17082
|
+
case 'adicionar superfícies':
|
|
17083
|
+
return 'add_dashboard_surfaces';
|
|
17084
|
+
case 'add details':
|
|
17085
|
+
case 'adicionar detalhes':
|
|
17086
|
+
return 'add_dashboard_detail_widget';
|
|
17087
|
+
case 'connect widgets':
|
|
17088
|
+
case 'conectar widgets':
|
|
17089
|
+
return 'connect_dashboard_widgets';
|
|
17090
|
+
default:
|
|
17091
|
+
return '';
|
|
17092
|
+
}
|
|
17093
|
+
}
|
|
16119
17094
|
contextualActionCandidate(contextHints) {
|
|
16120
17095
|
const resourcePath = this.readString(contextHints, 'resourcePath');
|
|
16121
17096
|
if (!resourcePath) {
|
|
@@ -16975,6 +17950,7 @@ class DynamicPageBuilderComponent {
|
|
|
16975
17950
|
pageLifecycleBusy = false;
|
|
16976
17951
|
pageLifecycleResetRevision = null;
|
|
16977
17952
|
pageChange = new EventEmitter();
|
|
17953
|
+
widgetEvent = new EventEmitter();
|
|
16978
17954
|
pageSaveRequested = new EventEmitter();
|
|
16979
17955
|
agenticAuthoringApplied = new EventEmitter();
|
|
16980
17956
|
agenticAuthoringSharedRuleHandoff = new EventEmitter();
|
|
@@ -17057,6 +18033,7 @@ class DynamicPageBuilderComponent {
|
|
|
17057
18033
|
this.pageChange.emit(cloned);
|
|
17058
18034
|
}
|
|
17059
18035
|
onRuntimeWidgetEvent(event) {
|
|
18036
|
+
this.widgetEvent.emit(event);
|
|
17060
18037
|
if (event.output !== AGENTIC_PAGE_COMPOSITION_REQUEST_OUTPUT) {
|
|
17061
18038
|
return;
|
|
17062
18039
|
}
|
|
@@ -17152,12 +18129,19 @@ class DynamicPageBuilderComponent {
|
|
|
17152
18129
|
this.runtime?.openPageSettings();
|
|
17153
18130
|
}
|
|
17154
18131
|
saveCurrentPage() {
|
|
18132
|
+
if (!this.canSaveCurrentPage()) {
|
|
18133
|
+
this.agenticAuthoringStatus.set(this.tx('agentic.status.reviewNeedsAttention', 'Review the pending points before saving.'));
|
|
18134
|
+
return;
|
|
18135
|
+
}
|
|
17155
18136
|
const runtimeSnapshot = this.runtime?.getPageSnapshot();
|
|
17156
18137
|
const cloned = this.clonePage(runtimeSnapshot || this.currentPage());
|
|
17157
18138
|
this.currentPage.set(cloned);
|
|
17158
18139
|
this.pageChange.emit(cloned);
|
|
17159
18140
|
this.pageSaveRequested.emit(this.clonePage(cloned));
|
|
17160
18141
|
}
|
|
18142
|
+
canSaveCurrentPage() {
|
|
18143
|
+
return this.hasPageWidgets() && !this.hasBlockingAgenticReview();
|
|
18144
|
+
}
|
|
17161
18145
|
applyConfigFromAdapter(config) {
|
|
17162
18146
|
if (!config.page)
|
|
17163
18147
|
return;
|
|
@@ -17349,6 +18333,9 @@ class DynamicPageBuilderComponent {
|
|
|
17349
18333
|
const widgets = this.currentPage().widgets;
|
|
17350
18334
|
return !Array.isArray(widgets) || widgets.length === 0;
|
|
17351
18335
|
}
|
|
18336
|
+
hasBlockingAgenticReview() {
|
|
18337
|
+
return !!this.agenticAuthoringPreviewResult()?.valid && !this.agenticAuthoringCanApply();
|
|
18338
|
+
}
|
|
17352
18339
|
agenticAuthoringSubmitAction() {
|
|
17353
18340
|
const label = this.tx('agentic.preview', 'Generate preview');
|
|
17354
18341
|
return {
|
|
@@ -18102,11 +19089,34 @@ class DynamicPageBuilderComponent {
|
|
|
18102
19089
|
? contextHints['kind'].trim()
|
|
18103
19090
|
: '';
|
|
18104
19091
|
const id = (reply.id || '').trim();
|
|
19092
|
+
const actionText = (reply.label || reply.prompt || '').trim().toLowerCase();
|
|
18105
19093
|
return source === 'component-capability-catalog'
|
|
19094
|
+
|| source === 'dashboard-quality-gate'
|
|
19095
|
+
|| kind === 'dashboard-repair-action'
|
|
18106
19096
|
|| kind === 'contextual-preview-action'
|
|
19097
|
+
|| id.startsWith('dashboard-quality-')
|
|
19098
|
+
|| this.isDashboardQualityQuickReplyText(actionText)
|
|
18107
19099
|
|| id.startsWith('chart-')
|
|
18108
19100
|
|| id.startsWith('table-export-');
|
|
18109
19101
|
}
|
|
19102
|
+
isDashboardQualityQuickReplyText(text) {
|
|
19103
|
+
const normalized = text.trim().toLowerCase();
|
|
19104
|
+
return normalized === 'add kpis'
|
|
19105
|
+
|| normalized === 'bind kpi values'
|
|
19106
|
+
|| normalized === 'add chart'
|
|
19107
|
+
|| normalized === 'add surfaces'
|
|
19108
|
+
|| normalized === 'add details'
|
|
19109
|
+
|| normalized === 'connect widgets'
|
|
19110
|
+
|| normalized === 'adicionar kpis'
|
|
19111
|
+
|| normalized === 'vincular valores dos kpis'
|
|
19112
|
+
|| normalized === 'adicionar gráfico'
|
|
19113
|
+
|| normalized === 'adicionar grafico'
|
|
19114
|
+
|| normalized === 'adicionar surfaces'
|
|
19115
|
+
|| normalized === 'adicionar superfícies'
|
|
19116
|
+
|| normalized === 'adicionar superficies'
|
|
19117
|
+
|| normalized === 'adicionar detalhes'
|
|
19118
|
+
|| normalized === 'conectar widgets';
|
|
19119
|
+
}
|
|
18110
19120
|
isGovernedConfirmationQuickReply(reply, contextHints) {
|
|
18111
19121
|
return this.isConfirmationQuickReply(reply)
|
|
18112
19122
|
&& this.hasResourceContextHint(contextHints);
|
|
@@ -19574,7 +20584,7 @@ class DynamicPageBuilderComponent {
|
|
|
19574
20584
|
return resolvePraxisPageBuilderText(this.i18n, key, fallback);
|
|
19575
20585
|
}
|
|
19576
20586
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicPageBuilderComponent, deps: [{ token: i1.MatDialog }, { token: SETTINGS_PANEL_BRIDGE, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
19577
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicPageBuilderComponent, isStandalone: true, selector: "praxis-dynamic-page-builder", inputs: { page: "page", context: "context", strictValidation: "strictValidation", autoPersist: "autoPersist", enableCustomization: "enableCustomization", showSettingsButton: "showSettingsButton", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", pageEditorComponent: "pageEditorComponent", enableAgenticAuthoring: "enableAgenticAuthoring", agenticAuthoringProvider: "agenticAuthoringProvider", agenticAuthoringModel: "agenticAuthoringModel", agenticAuthoringApiKey: "agenticAuthoringApiKey", agenticAuthoringComponentId: "agenticAuthoringComponentId", agenticAuthoringScope: "agenticAuthoringScope", agenticAuthoringEtag: "agenticAuthoringEtag", agenticAuthoringIncludeLlmDiagnostics: "agenticAuthoringIncludeLlmDiagnostics", agenticAuthoringEnableStreaming: "agenticAuthoringEnableStreaming", agenticAuthoringContextHints: "agenticAuthoringContextHints", showPageLifecycleActions: "showPageLifecycleActions", canDeleteSavedPage: "canDeleteSavedPage", pageLifecycleBusy: "pageLifecycleBusy", pageLifecycleResetRevision: "pageLifecycleResetRevision" }, outputs: { pageChange: "pageChange", pageSaveRequested: "pageSaveRequested", agenticAuthoringApplied: "agenticAuthoringApplied", agenticAuthoringSharedRuleHandoff: "agenticAuthoringSharedRuleHandoff", pageRestart: "pageRestart", savedPageDeleteRequested: "savedPageDeleteRequested" }, providers: [
|
|
20587
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicPageBuilderComponent, isStandalone: true, selector: "praxis-dynamic-page-builder", inputs: { page: "page", context: "context", strictValidation: "strictValidation", autoPersist: "autoPersist", enableCustomization: "enableCustomization", showSettingsButton: "showSettingsButton", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", pageEditorComponent: "pageEditorComponent", enableAgenticAuthoring: "enableAgenticAuthoring", agenticAuthoringProvider: "agenticAuthoringProvider", agenticAuthoringModel: "agenticAuthoringModel", agenticAuthoringApiKey: "agenticAuthoringApiKey", agenticAuthoringComponentId: "agenticAuthoringComponentId", agenticAuthoringScope: "agenticAuthoringScope", agenticAuthoringEtag: "agenticAuthoringEtag", agenticAuthoringIncludeLlmDiagnostics: "agenticAuthoringIncludeLlmDiagnostics", agenticAuthoringEnableStreaming: "agenticAuthoringEnableStreaming", agenticAuthoringContextHints: "agenticAuthoringContextHints", showPageLifecycleActions: "showPageLifecycleActions", canDeleteSavedPage: "canDeleteSavedPage", pageLifecycleBusy: "pageLifecycleBusy", pageLifecycleResetRevision: "pageLifecycleResetRevision" }, outputs: { pageChange: "pageChange", widgetEvent: "widgetEvent", pageSaveRequested: "pageSaveRequested", agenticAuthoringApplied: "agenticAuthoringApplied", agenticAuthoringSharedRuleHandoff: "agenticAuthoringSharedRuleHandoff", pageRestart: "pageRestart", savedPageDeleteRequested: "savedPageDeleteRequested" }, providers: [
|
|
19578
20588
|
providePraxisPageBuilderI18n(),
|
|
19579
20589
|
{ provide: DYNAMIC_PAGE_SHELL_EDITOR, useValue: WidgetShellEditorComponent },
|
|
19580
20590
|
], viewQueries: [{ propertyName: "runtime", first: true, predicate: ["runtime"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
@@ -19935,7 +20945,7 @@ class DynamicPageBuilderComponent {
|
|
|
19935
20945
|
[visible]="showSettings()"
|
|
19936
20946
|
[canUndo]="false"
|
|
19937
20947
|
[canRedo]="false"
|
|
19938
|
-
[showSave]="
|
|
20948
|
+
[showSave]="canSaveCurrentPage()"
|
|
19939
20949
|
[showPreview]="hasPageWidgets()"
|
|
19940
20950
|
(add)="onAddComponent()"
|
|
19941
20951
|
(settings)="openPageSettings()"
|
|
@@ -20376,7 +21386,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
20376
21386
|
[visible]="showSettings()"
|
|
20377
21387
|
[canUndo]="false"
|
|
20378
21388
|
[canRedo]="false"
|
|
20379
|
-
[showSave]="
|
|
21389
|
+
[showSave]="canSaveCurrentPage()"
|
|
20380
21390
|
[showPreview]="hasPageWidgets()"
|
|
20381
21391
|
(add)="onAddComponent()"
|
|
20382
21392
|
(settings)="openPageSettings()"
|
|
@@ -20500,6 +21510,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
20500
21510
|
type: Input
|
|
20501
21511
|
}], pageChange: [{
|
|
20502
21512
|
type: Output
|
|
21513
|
+
}], widgetEvent: [{
|
|
21514
|
+
type: Output
|
|
20503
21515
|
}], pageSaveRequested: [{
|
|
20504
21516
|
type: Output
|
|
20505
21517
|
}], agenticAuthoringApplied: [{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/page-builder",
|
|
3
|
-
"version": "8.0.0-beta.
|
|
3
|
+
"version": "8.0.0-beta.94",
|
|
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": "^8.0.0-beta.
|
|
12
|
-
"@praxisui/core": "^8.0.0-beta.
|
|
13
|
-
"@praxisui/settings-panel": "^8.0.0-beta.
|
|
11
|
+
"@praxisui/ai": "^8.0.0-beta.94",
|
|
12
|
+
"@praxisui/core": "^8.0.0-beta.94",
|
|
13
|
+
"@praxisui/settings-panel": "^8.0.0-beta.94",
|
|
14
14
|
"rxjs": "~7.8.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
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, Type, SimpleChanges } from '@angular/core';
|
|
4
|
-
import { ComponentDocMeta, ComponentMetadataRegistry, WidgetShellConfig, WidgetShellAction, EndpointRef, ComponentPortPathSegment, LinkIntent, CompositionLink, WidgetPageDefinition, TransformKind, SurfaceOpenPayload, SettingsValueProvider as SettingsValueProvider$1, WidgetPageGroupingDefinition, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, PageIdentity, WidgetStateNode, WidgetDerivedStateNode, AiCapability, AiCapabilityCategory, AiCapabilityCatalog, AiValueKind, DomainKnowledgeChangeSetRequest, DomainKnowledgeChangeSet, DomainKnowledgeChangeSetTimelineResponse, DomainKnowledgeChangeSetFilters, DomainKnowledgeValidationResponse, DomainKnowledgeStatusTransitionRequest, DomainRuleIntakeRequest, DomainRuleIntakeResponse, DomainRuleDefinitionRequest, DomainRuleDefinition, DomainRuleSimulationRequest, DomainRuleSimulationResponse, DomainRuleStatusTransitionRequest, DomainRulePublicationRequest, DomainRulePublicationResponse, DomainRuleMaterializationFilters, DomainRuleMaterialization, DomainRuleTimelineResponse, WidgetPageCanvasLayout, WidgetPageDeviceLayouts, WidgetPageSlotAssignments, WidgetPageStateInput, WidgetInstance, ComponentContextPack, ComponentAuthoringManifest, DynamicWidgetPageComponent,
|
|
4
|
+
import { ComponentDocMeta, ComponentMetadataRegistry, WidgetShellConfig, WidgetShellAction, EndpointRef, ComponentPortPathSegment, LinkIntent, CompositionLink, WidgetPageDefinition, TransformKind, SurfaceOpenPayload, SettingsValueProvider as SettingsValueProvider$1, WidgetPageGroupingDefinition, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, PageIdentity, WidgetStateNode, WidgetDerivedStateNode, AiCapability, AiCapabilityCategory, AiCapabilityCatalog, AiValueKind, DomainKnowledgeChangeSetRequest, DomainKnowledgeChangeSet, DomainKnowledgeChangeSetTimelineResponse, DomainKnowledgeChangeSetFilters, DomainKnowledgeValidationResponse, DomainKnowledgeStatusTransitionRequest, DomainRuleIntakeRequest, DomainRuleIntakeResponse, DomainRuleDefinitionRequest, DomainRuleDefinition, DomainRuleSimulationRequest, DomainRuleSimulationResponse, DomainRuleStatusTransitionRequest, DomainRulePublicationRequest, DomainRulePublicationResponse, DomainRuleMaterializationFilters, DomainRuleMaterialization, DomainRuleTimelineResponse, WidgetPageCanvasLayout, WidgetPageDeviceLayouts, WidgetPageSlotAssignments, WidgetPageStateInput, WidgetInstance, ComponentContextPack, ComponentAuthoringManifest, DynamicWidgetPageComponent, WidgetEventEnvelope, SettingsPanelBridge, RichTimelineItem } from '@praxisui/core';
|
|
5
5
|
export { WidgetShellComponent } from '@praxisui/core';
|
|
6
6
|
import * as rxjs from 'rxjs';
|
|
7
7
|
import { BehaviorSubject, Observable } from 'rxjs';
|
|
@@ -1670,6 +1670,7 @@ declare class DynamicPageBuilderComponent implements OnChanges {
|
|
|
1670
1670
|
pageLifecycleBusy: boolean;
|
|
1671
1671
|
pageLifecycleResetRevision: number | string | null;
|
|
1672
1672
|
pageChange: EventEmitter<WidgetPageDefinition>;
|
|
1673
|
+
widgetEvent: EventEmitter<WidgetEventEnvelope>;
|
|
1673
1674
|
pageSaveRequested: EventEmitter<WidgetPageDefinition>;
|
|
1674
1675
|
agenticAuthoringApplied: EventEmitter<PageBuilderApplyResult>;
|
|
1675
1676
|
agenticAuthoringSharedRuleHandoff: EventEmitter<PageBuilderAgenticAuthoringSharedRuleHandoff>;
|
|
@@ -1734,6 +1735,7 @@ declare class DynamicPageBuilderComponent implements OnChanges {
|
|
|
1734
1735
|
addWidget(selection: string | ComponentPaletteSelection): void;
|
|
1735
1736
|
openPageSettings(): void;
|
|
1736
1737
|
saveCurrentPage(): void;
|
|
1738
|
+
canSaveCurrentPage(): boolean;
|
|
1737
1739
|
applyConfigFromAdapter(config: PageBuilderConfig): void;
|
|
1738
1740
|
private createAdapterHost;
|
|
1739
1741
|
toggleAgenticAuthoring(): void;
|
|
@@ -1753,6 +1755,7 @@ declare class DynamicPageBuilderComponent implements OnChanges {
|
|
|
1753
1755
|
private agenticAuthoringEmptyConversationMessage;
|
|
1754
1756
|
private resolveAgenticAuthoredOpeningMessage;
|
|
1755
1757
|
private isAgenticAuthoringPageBlank;
|
|
1758
|
+
private hasBlockingAgenticReview;
|
|
1756
1759
|
agenticAuthoringSubmitAction(): PraxisAssistantShellAction;
|
|
1757
1760
|
agenticAuthoringDockIcon(): string;
|
|
1758
1761
|
agenticAuthoringDockBadge(): string;
|
|
@@ -1796,6 +1799,7 @@ declare class DynamicPageBuilderComponent implements OnChanges {
|
|
|
1796
1799
|
private agenticQuickReplyGovernedConfirmationPrompt;
|
|
1797
1800
|
private isResourceQuickReply;
|
|
1798
1801
|
private isContextualPreviewActionQuickReply;
|
|
1802
|
+
private isDashboardQualityQuickReplyText;
|
|
1799
1803
|
private isGovernedConfirmationQuickReply;
|
|
1800
1804
|
private isConfirmationQuickReply;
|
|
1801
1805
|
private hasResourceContextHint;
|
|
@@ -1905,7 +1909,7 @@ declare class DynamicPageBuilderComponent implements OnChanges {
|
|
|
1905
1909
|
private cloneValue;
|
|
1906
1910
|
tx(key: string, fallback: string): string;
|
|
1907
1911
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DynamicPageBuilderComponent, [null, { optional: true; }]>;
|
|
1908
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DynamicPageBuilderComponent, "praxis-dynamic-page-builder", never, { "page": { "alias": "page"; "required": false; }; "context": { "alias": "context"; "required": false; }; "strictValidation": { "alias": "strictValidation"; "required": false; }; "autoPersist": { "alias": "autoPersist"; "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; }; "enableAgenticAuthoring": { "alias": "enableAgenticAuthoring"; "required": false; }; "agenticAuthoringProvider": { "alias": "agenticAuthoringProvider"; "required": false; }; "agenticAuthoringModel": { "alias": "agenticAuthoringModel"; "required": false; }; "agenticAuthoringApiKey": { "alias": "agenticAuthoringApiKey"; "required": false; }; "agenticAuthoringComponentId": { "alias": "agenticAuthoringComponentId"; "required": false; }; "agenticAuthoringScope": { "alias": "agenticAuthoringScope"; "required": false; }; "agenticAuthoringEtag": { "alias": "agenticAuthoringEtag"; "required": false; }; "agenticAuthoringIncludeLlmDiagnostics": { "alias": "agenticAuthoringIncludeLlmDiagnostics"; "required": false; }; "agenticAuthoringEnableStreaming": { "alias": "agenticAuthoringEnableStreaming"; "required": false; }; "agenticAuthoringContextHints": { "alias": "agenticAuthoringContextHints"; "required": false; }; "showPageLifecycleActions": { "alias": "showPageLifecycleActions"; "required": false; }; "canDeleteSavedPage": { "alias": "canDeleteSavedPage"; "required": false; }; "pageLifecycleBusy": { "alias": "pageLifecycleBusy"; "required": false; }; "pageLifecycleResetRevision": { "alias": "pageLifecycleResetRevision"; "required": false; }; }, { "pageChange": "pageChange"; "pageSaveRequested": "pageSaveRequested"; "agenticAuthoringApplied": "agenticAuthoringApplied"; "agenticAuthoringSharedRuleHandoff": "agenticAuthoringSharedRuleHandoff"; "pageRestart": "pageRestart"; "savedPageDeleteRequested": "savedPageDeleteRequested"; }, never, never, true, never>;
|
|
1912
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DynamicPageBuilderComponent, "praxis-dynamic-page-builder", never, { "page": { "alias": "page"; "required": false; }; "context": { "alias": "context"; "required": false; }; "strictValidation": { "alias": "strictValidation"; "required": false; }; "autoPersist": { "alias": "autoPersist"; "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; }; "enableAgenticAuthoring": { "alias": "enableAgenticAuthoring"; "required": false; }; "agenticAuthoringProvider": { "alias": "agenticAuthoringProvider"; "required": false; }; "agenticAuthoringModel": { "alias": "agenticAuthoringModel"; "required": false; }; "agenticAuthoringApiKey": { "alias": "agenticAuthoringApiKey"; "required": false; }; "agenticAuthoringComponentId": { "alias": "agenticAuthoringComponentId"; "required": false; }; "agenticAuthoringScope": { "alias": "agenticAuthoringScope"; "required": false; }; "agenticAuthoringEtag": { "alias": "agenticAuthoringEtag"; "required": false; }; "agenticAuthoringIncludeLlmDiagnostics": { "alias": "agenticAuthoringIncludeLlmDiagnostics"; "required": false; }; "agenticAuthoringEnableStreaming": { "alias": "agenticAuthoringEnableStreaming"; "required": false; }; "agenticAuthoringContextHints": { "alias": "agenticAuthoringContextHints"; "required": false; }; "showPageLifecycleActions": { "alias": "showPageLifecycleActions"; "required": false; }; "canDeleteSavedPage": { "alias": "canDeleteSavedPage"; "required": false; }; "pageLifecycleBusy": { "alias": "pageLifecycleBusy"; "required": false; }; "pageLifecycleResetRevision": { "alias": "pageLifecycleResetRevision"; "required": false; }; }, { "pageChange": "pageChange"; "widgetEvent": "widgetEvent"; "pageSaveRequested": "pageSaveRequested"; "agenticAuthoringApplied": "agenticAuthoringApplied"; "agenticAuthoringSharedRuleHandoff": "agenticAuthoringSharedRuleHandoff"; "pageRestart": "pageRestart"; "savedPageDeleteRequested": "savedPageDeleteRequested"; }, never, never, true, never>;
|
|
1909
1913
|
}
|
|
1910
1914
|
|
|
1911
1915
|
export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, registerWidgetAiCatalog, registerWidgetAiCatalogs, validateUiCompositionPlan };
|