@praxisui/manual-form 10.0.0-rc.40 → 10.0.0-rc.42
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-
|
|
3
|
+
"generatedAt": "2026-11-01T13:59:56.156Z",
|
|
4
4
|
"packageName": "@praxisui/manual-form",
|
|
5
|
-
"packageVersion": "10.0.0-rc.
|
|
5
|
+
"packageVersion": "10.0.0-rc.42",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 1,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ensureIds, DynamicFormService, ASYNC_CONFIG_STORAGE, RULE_PROPERTY_SCHEMA, deepMerge, resolveControlTypeAlias, FieldControlType, normalizeControlTypeKey, PraxisIconButtonComponent, FormHooksRegistry, ComponentKeyService, FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, DEFAULT_FIELD_SELECTOR_CONTROL_TYPE_MAP, FieldSelectorRegistry, providePraxisI18n, PraxisI18nService, API_URL, ComponentMetadataRegistry } from '@praxisui/core';
|
|
1
|
+
import { ensureIds, DynamicFormService, ASYNC_CONFIG_STORAGE, RULE_PROPERTY_SCHEMA, deepMerge, PRAXIS_RUNTIME_FORM_VALUE_PROPOSAL_SCHEMA_VERSION, resolveControlTypeAlias, FieldControlType, normalizeControlTypeKey, PraxisIconButtonComponent, FormHooksRegistry, ComponentKeyService, FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, DEFAULT_FIELD_SELECTOR_CONTROL_TYPE_MAP, FieldSelectorRegistry, PraxisRuntimeFormValueSessionJournal, previewRuntimeFormValueProposal, applyRuntimeFormValueProposal, undoRuntimeFormValueApply, instanceKeyFor, evaluateFieldAccess, providePraxisI18n, PraxisI18nService, API_URL, ComponentMetadataRegistry } from '@praxisui/core';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { inject, Optional, Inject, Injectable, input, output, ChangeDetectionStrategy, Component, Input, InjectionToken, isDevMode, EventEmitter, HostListener, ViewChild, Output, ChangeDetectorRef, DestroyRef, PLATFORM_ID, effect, ContentChildren, signal, computed, Directive, ENVIRONMENT_INITIALIZER } from '@angular/core';
|
|
4
4
|
import { BehaviorSubject, firstValueFrom, debounceTime, fromEvent, of } from 'rxjs';
|
|
@@ -459,6 +459,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
459
459
|
|
|
460
460
|
class ManualFormActionsComponent {
|
|
461
461
|
actions = input(...(ngDevMode ? [undefined, { debugName: "actions" }] : /* istanbul ignore next */ []));
|
|
462
|
+
submitDisabled = input(false, ...(ngDevMode ? [{ debugName: "submitDisabled" }] : /* istanbul ignore next */ []));
|
|
462
463
|
trackByFn = null;
|
|
463
464
|
actionClick = output();
|
|
464
465
|
isVisible(action) {
|
|
@@ -473,7 +474,7 @@ class ManualFormActionsComponent {
|
|
|
473
474
|
}
|
|
474
475
|
}
|
|
475
476
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
476
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ManualFormActionsComponent, isStandalone: true, selector: "praxis-manual-form-actions", inputs: { actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, trackByFn: { classPropertyName: "trackByFn", publicName: "trackByFn", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: `
|
|
477
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ManualFormActionsComponent, isStandalone: true, selector: "praxis-manual-form-actions", inputs: { actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, submitDisabled: { classPropertyName: "submitDisabled", publicName: "submitDisabled", isSignal: true, isRequired: false, transformFunction: null }, trackByFn: { classPropertyName: "trackByFn", publicName: "trackByFn", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: `
|
|
477
478
|
@if (actions(); as layout) {
|
|
478
479
|
<footer class="pdx-manual-form__actions">
|
|
479
480
|
<div class="pdx-manual-form__actions-secondary">
|
|
@@ -502,7 +503,7 @@ class ManualFormActionsComponent {
|
|
|
502
503
|
<div class="pdx-manual-form__actions-primary">
|
|
503
504
|
@if (layout.submit; as submitBtn) {
|
|
504
505
|
@if (isVisible(submitBtn)) {
|
|
505
|
-
<button type="submit" class="pdx-btn pdx-btn--primary" [disabled]="submitBtn.disabled" (click)="emit('submit', submitBtn)">
|
|
506
|
+
<button type="submit" class="pdx-btn pdx-btn--primary" [disabled]="submitBtn.disabled || submitDisabled()" (click)="emit('submit', submitBtn)">
|
|
506
507
|
{{ submitBtn.label || 'Salvar' }}
|
|
507
508
|
</button>
|
|
508
509
|
}
|
|
@@ -543,7 +544,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
543
544
|
<div class="pdx-manual-form__actions-primary">
|
|
544
545
|
@if (layout.submit; as submitBtn) {
|
|
545
546
|
@if (isVisible(submitBtn)) {
|
|
546
|
-
<button type="submit" class="pdx-btn pdx-btn--primary" [disabled]="submitBtn.disabled" (click)="emit('submit', submitBtn)">
|
|
547
|
+
<button type="submit" class="pdx-btn pdx-btn--primary" [disabled]="submitBtn.disabled || submitDisabled()" (click)="emit('submit', submitBtn)">
|
|
547
548
|
{{ submitBtn.label || 'Salvar' }}
|
|
548
549
|
</button>
|
|
549
550
|
}
|
|
@@ -552,7 +553,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
552
553
|
</footer>
|
|
553
554
|
}
|
|
554
555
|
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.pdx-manual-form__actions{display:flex;justify-content:space-between;align-items:center;gap:1rem;margin-top:2rem;flex-wrap:wrap}.pdx-manual-form__actions-secondary,.pdx-manual-form__actions-primary{display:flex;gap:.5rem}.pdx-btn{min-height:36px;padding:0 14px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.pdx-btn:hover{background:var(--md-sys-color-surface-container)}.pdx-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-btn:disabled{opacity:.6;cursor:not-allowed}.pdx-btn--ghost{background:transparent;border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.pdx-btn--primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);border-color:var(--md-sys-color-primary)}.pdx-btn--primary:hover{background:var(--md-sys-color-primary-container);border-color:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}\n"] }]
|
|
555
|
-
}], propDecorators: { actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], trackByFn: [{
|
|
556
|
+
}], propDecorators: { actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], submitDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitDisabled", required: false }] }], trackByFn: [{
|
|
556
557
|
type: Input
|
|
557
558
|
}], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
|
|
558
559
|
|
|
@@ -1146,19 +1147,92 @@ class ManualFormAiAdapter extends BaseAiAdapter {
|
|
|
1146
1147
|
.filter((field) => typeof field.name === 'string' && !!field.name.trim());
|
|
1147
1148
|
}
|
|
1148
1149
|
getAuthoringContext() {
|
|
1150
|
+
const autoSaveEnabled = !!this.host.enableAutoSave();
|
|
1151
|
+
const targetIdentity = this.getRuntimeValueTargetIdentity();
|
|
1152
|
+
const eligibility = this.getRuntimeValueEligibility();
|
|
1153
|
+
const canAssistRuntimeValues = !autoSaveEnabled && (eligibility ? eligibility.eligible : false);
|
|
1149
1154
|
return {
|
|
1150
1155
|
authoringManifestRef: 'PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST',
|
|
1151
1156
|
runtimeAuthoringPolicy: {
|
|
1152
|
-
mode: 'agentic-authoring',
|
|
1157
|
+
mode: this.host.enableCustomization() ? 'agentic-authoring' : 'runtime-value-assistance',
|
|
1153
1158
|
enableCustomization: !!this.host.enableCustomization(),
|
|
1154
1159
|
canApplyLocalPatch: false,
|
|
1155
|
-
|
|
1160
|
+
canAssistRuntimeValues,
|
|
1161
|
+
autoSaveEnabled,
|
|
1162
|
+
reason: autoSaveEnabled
|
|
1163
|
+
? 'praxis-manual-form com enableAutoSave=true não aplica rascunho transitório automaticamente para evitar persistência implícita.'
|
|
1164
|
+
: eligibility?.blockMessage
|
|
1165
|
+
? eligibility.blockMessage
|
|
1166
|
+
: 'praxis-manual-form ainda exige componentEditPlan manifest-backed antes de aplicar patch local pelo copiloto.',
|
|
1156
1167
|
},
|
|
1168
|
+
...(targetIdentity
|
|
1169
|
+
? {
|
|
1170
|
+
runtimeValueAssistance: {
|
|
1171
|
+
enabled: canAssistRuntimeValues,
|
|
1172
|
+
targetIdentity,
|
|
1173
|
+
autoSaveEnabled,
|
|
1174
|
+
hasPendingReactiveDeterminations: eligibility?.hasPendingReactiveDeterminations ?? false,
|
|
1175
|
+
hasPendingAsyncValidators: eligibility?.hasPendingAsyncValidators ?? false,
|
|
1176
|
+
writableFields: eligibility?.writableFields ?? [],
|
|
1177
|
+
nonOverwritableFields: eligibility?.nonOverwritableFields ?? [],
|
|
1178
|
+
...(this.resolveGovernedSchemaPayload(targetIdentity)
|
|
1179
|
+
? { governedSchema: this.resolveGovernedSchemaPayload(targetIdentity) }
|
|
1180
|
+
: {}),
|
|
1181
|
+
defaultApplyMode: 'empty-only',
|
|
1182
|
+
},
|
|
1183
|
+
}
|
|
1184
|
+
: {}),
|
|
1157
1185
|
domainCatalog: {
|
|
1158
1186
|
recommendedAuthoringFlow: 'component_authoring',
|
|
1159
1187
|
},
|
|
1160
1188
|
};
|
|
1161
1189
|
}
|
|
1190
|
+
resolveGovernedSchemaPayload(targetIdentity) {
|
|
1191
|
+
const rawGoverned = this.host.governedSchema?.();
|
|
1192
|
+
if (!rawGoverned) {
|
|
1193
|
+
return null;
|
|
1194
|
+
}
|
|
1195
|
+
if (Array.isArray(rawGoverned)) {
|
|
1196
|
+
const properties = {};
|
|
1197
|
+
for (const item of rawGoverned) {
|
|
1198
|
+
if (item && typeof item === 'object' && typeof item.name === 'string') {
|
|
1199
|
+
properties[item.name] = item;
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
return {
|
|
1203
|
+
...(targetIdentity.schemaHash ? { 'x-schema-hash': targetIdentity.schemaHash } : {}),
|
|
1204
|
+
properties,
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
if (typeof rawGoverned === 'object') {
|
|
1208
|
+
return {
|
|
1209
|
+
...(targetIdentity.schemaHash ? { 'x-schema-hash': targetIdentity.schemaHash } : {}),
|
|
1210
|
+
...rawGoverned,
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
return null;
|
|
1214
|
+
}
|
|
1215
|
+
getRuntimeValueTargetIdentity() {
|
|
1216
|
+
return this.host.getRuntimeValueTargetIdentity?.() ?? null;
|
|
1217
|
+
}
|
|
1218
|
+
getRuntimeValueEligibility() {
|
|
1219
|
+
return this.host.getRuntimeValueEligibility?.() ?? null;
|
|
1220
|
+
}
|
|
1221
|
+
previewRuntimeValues(proposal, options) {
|
|
1222
|
+
return this.host.previewRuntimeValues?.(proposal, options) ?? null;
|
|
1223
|
+
}
|
|
1224
|
+
async applyRuntimeValues(request) {
|
|
1225
|
+
if (!this.host.applyRuntimeValues) {
|
|
1226
|
+
return null;
|
|
1227
|
+
}
|
|
1228
|
+
return await this.host.applyRuntimeValues(request);
|
|
1229
|
+
}
|
|
1230
|
+
async undoRuntimeValues(receiptId) {
|
|
1231
|
+
if (!this.host.undoRuntimeValues) {
|
|
1232
|
+
return null;
|
|
1233
|
+
}
|
|
1234
|
+
return await this.host.undoRuntimeValues(receiptId);
|
|
1235
|
+
}
|
|
1162
1236
|
createSnapshot() {
|
|
1163
1237
|
return this.getCurrentConfig();
|
|
1164
1238
|
}
|
|
@@ -1241,6 +1315,10 @@ class ManualFormAgenticAuthoringTurnFlow {
|
|
|
1241
1315
|
this.aiApi = aiApi;
|
|
1242
1316
|
}
|
|
1243
1317
|
async submit(request) {
|
|
1318
|
+
if (request.action?.kind === 'runtime-form-value-undo' ||
|
|
1319
|
+
request.action?.id === 'undo-runtime-values') {
|
|
1320
|
+
return this.apply(request);
|
|
1321
|
+
}
|
|
1244
1322
|
const prompt = (request.prompt ?? '').trim();
|
|
1245
1323
|
if (!prompt) {
|
|
1246
1324
|
return {
|
|
@@ -1285,7 +1363,115 @@ class ManualFormAgenticAuthoringTurnFlow {
|
|
|
1285
1363
|
})));
|
|
1286
1364
|
return this.toTurnResult(this.compileAdapterResponse(response), request);
|
|
1287
1365
|
}
|
|
1288
|
-
async apply(
|
|
1366
|
+
async apply(request) {
|
|
1367
|
+
const runtimeAdapter = this.adapter;
|
|
1368
|
+
if (request.action?.kind === 'runtime-form-value-undo' ||
|
|
1369
|
+
request.action?.id === 'undo-runtime-values') {
|
|
1370
|
+
const actionHints = this.toRecord(request.action?.contextHints);
|
|
1371
|
+
const receiptId = typeof actionHints?.['receiptId'] === 'string'
|
|
1372
|
+
? actionHints['receiptId']
|
|
1373
|
+
: typeof request.action?.value === 'string'
|
|
1374
|
+
? request.action.value
|
|
1375
|
+
: undefined;
|
|
1376
|
+
const undoReceipt = await runtimeAdapter.undoRuntimeValues?.(receiptId);
|
|
1377
|
+
if (!undoReceipt || undoReceipt.revertedFields.length === 0) {
|
|
1378
|
+
const preservedMsg = undoReceipt && undoReceipt.preservedManualFields.length > 0
|
|
1379
|
+
? `Nenhum campo foi revertido porque ${undoReceipt.preservedManualFields.length} campo(s) foram editados manualmente após a aplicação.`
|
|
1380
|
+
: 'Não há preenchimento pendente para desfazer nesta instância.';
|
|
1381
|
+
return {
|
|
1382
|
+
state: 'success',
|
|
1383
|
+
phase: 'summarize',
|
|
1384
|
+
assistantMessage: preservedMsg,
|
|
1385
|
+
statusText: preservedMsg,
|
|
1386
|
+
canApply: false,
|
|
1387
|
+
pendingPatch: null,
|
|
1388
|
+
diagnostics: undoReceipt
|
|
1389
|
+
? { runtimeValueUndoReceipt: undoReceipt }
|
|
1390
|
+
: undefined,
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
const manualSuffix = undoReceipt.preservedManualFields.length > 0
|
|
1394
|
+
? ` (${undoReceipt.preservedManualFields.length} campo(s) editado(s) manualmente foram preservados).`
|
|
1395
|
+
: '.';
|
|
1396
|
+
const message = `Preenchimento desfeito em ${undoReceipt.revertedFields.length} campo(s)${manualSuffix}`;
|
|
1397
|
+
return {
|
|
1398
|
+
state: 'success',
|
|
1399
|
+
phase: 'summarize',
|
|
1400
|
+
assistantMessage: message,
|
|
1401
|
+
statusText: message,
|
|
1402
|
+
canApply: false,
|
|
1403
|
+
pendingPatch: null,
|
|
1404
|
+
preview: {
|
|
1405
|
+
kind: 'runtime-form-value-undo-receipt',
|
|
1406
|
+
undoReceipt,
|
|
1407
|
+
},
|
|
1408
|
+
diagnostics: {
|
|
1409
|
+
runtimeValueUndoReceipt: undoReceipt,
|
|
1410
|
+
},
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
const runtimeProposal = this.extractRuntimeValueProposal(request.runtimeValueProposal) ??
|
|
1414
|
+
this.extractRuntimeValueProposal(request.pendingPatch);
|
|
1415
|
+
if (runtimeProposal) {
|
|
1416
|
+
const actionHints = this.toRecord(request.action?.contextHints);
|
|
1417
|
+
const selectedFieldPaths = Array.isArray(actionHints?.['selectedFieldPaths'])
|
|
1418
|
+
? actionHints['selectedFieldPaths'].filter((item) => typeof item === 'string' && item.trim().length > 0)
|
|
1419
|
+
: undefined;
|
|
1420
|
+
const applyModeCandidate = actionHints?.['applyMode'];
|
|
1421
|
+
const applyMode = applyModeCandidate === 'empty-only' || applyModeCandidate === 'selected-fields'
|
|
1422
|
+
? applyModeCandidate
|
|
1423
|
+
: undefined;
|
|
1424
|
+
const receipt = await runtimeAdapter.applyRuntimeValues?.({
|
|
1425
|
+
proposal: runtimeProposal,
|
|
1426
|
+
selectedFieldPaths,
|
|
1427
|
+
applyMode,
|
|
1428
|
+
});
|
|
1429
|
+
if (!receipt || receipt.appliedFields.length === 0) {
|
|
1430
|
+
const blockMessage = receipt?.warnings?.[receipt.warnings.length - 1] ??
|
|
1431
|
+
'A proposta de preenchimento do formulário manual não pôde ser aplicada.';
|
|
1432
|
+
return {
|
|
1433
|
+
state: 'clarification',
|
|
1434
|
+
phase: 'clarify',
|
|
1435
|
+
assistantMessage: blockMessage,
|
|
1436
|
+
statusText: blockMessage,
|
|
1437
|
+
canApply: false,
|
|
1438
|
+
pendingPatch: null,
|
|
1439
|
+
runtimeValueProposal: runtimeProposal,
|
|
1440
|
+
runtimeValueReceipt: receipt ?? null,
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
1443
|
+
const appliedLabels = receipt.appliedFields
|
|
1444
|
+
.map((field) => field.label || field.fieldPath)
|
|
1445
|
+
.join(', ');
|
|
1446
|
+
return {
|
|
1447
|
+
state: 'success',
|
|
1448
|
+
phase: 'summarize',
|
|
1449
|
+
assistantMessage: `Preenchimento transitório aplicado em ${receipt.appliedFields.length} campo(s) (${appliedLabels}). Os dados permanecem não salvos até o envio explícito do formulário.`,
|
|
1450
|
+
statusText: `${receipt.appliedFields.length} campo(s) preenchido(s) no formulário manual.`,
|
|
1451
|
+
canApply: false,
|
|
1452
|
+
pendingPatch: null,
|
|
1453
|
+
runtimeValueProposal: runtimeProposal,
|
|
1454
|
+
runtimeValueReceipt: receipt,
|
|
1455
|
+
preview: {
|
|
1456
|
+
kind: 'runtime-form-value-receipt',
|
|
1457
|
+
receipt,
|
|
1458
|
+
},
|
|
1459
|
+
quickReplies: receipt.canUndo
|
|
1460
|
+
? [
|
|
1461
|
+
{
|
|
1462
|
+
id: 'undo-runtime-values',
|
|
1463
|
+
label: 'Desfazer preenchimento',
|
|
1464
|
+
prompt: 'Desfazer preenchimento aplicado',
|
|
1465
|
+
kind: 'runtime-form-value-undo',
|
|
1466
|
+
icon: 'undo',
|
|
1467
|
+
contextHints: {
|
|
1468
|
+
receiptId: receipt.receiptId,
|
|
1469
|
+
},
|
|
1470
|
+
},
|
|
1471
|
+
]
|
|
1472
|
+
: [],
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1289
1475
|
return {
|
|
1290
1476
|
state: 'error',
|
|
1291
1477
|
phase: 'apply',
|
|
@@ -1324,20 +1510,82 @@ class ManualFormAgenticAuthoringTurnFlow {
|
|
|
1324
1510
|
errorText: 'Resposta vazia da IA.',
|
|
1325
1511
|
};
|
|
1326
1512
|
}
|
|
1513
|
+
const runtimeProposal = this.extractRuntimeValueProposal(response['runtimeValueProposal']) ?? this.extractRuntimeValueProposal(response.patch);
|
|
1514
|
+
if (runtimeProposal) {
|
|
1515
|
+
const runtimeAdapter = this.adapter;
|
|
1516
|
+
const preview = runtimeAdapter.previewRuntimeValues?.(runtimeProposal) ?? null;
|
|
1517
|
+
const canApply = Boolean(preview?.canApply);
|
|
1518
|
+
if (!canApply) {
|
|
1519
|
+
const blockMessage = preview?.blockMessage ||
|
|
1520
|
+
this.sanitizeBlockedAssistantMessage(response.message ||
|
|
1521
|
+
response.explanation ||
|
|
1522
|
+
'A proposta de preenchimento do formulário manual está bloqueada no estado atual.');
|
|
1523
|
+
return {
|
|
1524
|
+
state: 'clarification',
|
|
1525
|
+
phase: 'clarify',
|
|
1526
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
1527
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
1528
|
+
assistantMessage: blockMessage,
|
|
1529
|
+
statusText: blockMessage,
|
|
1530
|
+
canApply: false,
|
|
1531
|
+
pendingPatch: null,
|
|
1532
|
+
runtimeValueProposal: runtimeProposal,
|
|
1533
|
+
preview: {
|
|
1534
|
+
kind: 'runtime-form-value-proposal',
|
|
1535
|
+
proposal: runtimeProposal,
|
|
1536
|
+
...(preview ? { runtimePreview: preview } : {}),
|
|
1537
|
+
},
|
|
1538
|
+
diagnostics: {
|
|
1539
|
+
...(preview
|
|
1540
|
+
? {
|
|
1541
|
+
runtimeValuePreview: preview,
|
|
1542
|
+
}
|
|
1543
|
+
: {}),
|
|
1544
|
+
},
|
|
1545
|
+
};
|
|
1546
|
+
}
|
|
1547
|
+
const summaryMessage = response.message ||
|
|
1548
|
+
response.explanation ||
|
|
1549
|
+
`Proposta de preenchimento pronta para revisão (${preview?.applicableCount ?? runtimeProposal.assignments.length} campo(s) aplicável(is)).`;
|
|
1550
|
+
return {
|
|
1551
|
+
state: 'review',
|
|
1552
|
+
phase: 'review',
|
|
1553
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
1554
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
1555
|
+
assistantMessage: summaryMessage,
|
|
1556
|
+
statusText: summaryMessage,
|
|
1557
|
+
canApply: true,
|
|
1558
|
+
pendingPatch: runtimeProposal,
|
|
1559
|
+
runtimeValueProposal: runtimeProposal,
|
|
1560
|
+
preview: {
|
|
1561
|
+
kind: 'runtime-form-value-proposal',
|
|
1562
|
+
proposal: runtimeProposal,
|
|
1563
|
+
...(preview ? { runtimePreview: preview } : {}),
|
|
1564
|
+
},
|
|
1565
|
+
diagnostics: {
|
|
1566
|
+
...(preview
|
|
1567
|
+
? {
|
|
1568
|
+
runtimeValuePreview: preview,
|
|
1569
|
+
}
|
|
1570
|
+
: {}),
|
|
1571
|
+
},
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1327
1574
|
if (response.type === 'clarification') {
|
|
1575
|
+
const assistantMessage = this.sanitizeBlockedAssistantMessage(response.message || 'Preciso de mais detalhes para continuar.');
|
|
1328
1576
|
return {
|
|
1329
1577
|
state: 'clarification',
|
|
1330
1578
|
phase: 'clarify',
|
|
1331
1579
|
sessionId: response.sessionId ?? request.sessionId,
|
|
1332
1580
|
observationId: response.observationId ?? request.observationId ?? null,
|
|
1333
|
-
assistantMessage
|
|
1581
|
+
assistantMessage,
|
|
1334
1582
|
clarificationQuestions: this.toClarificationQuestions(response),
|
|
1335
1583
|
quickReplies: this.toQuickReplies(response),
|
|
1336
1584
|
canApply: false,
|
|
1337
1585
|
};
|
|
1338
1586
|
}
|
|
1339
1587
|
if (response.type === 'info') {
|
|
1340
|
-
const message = response.message || response.explanation || 'Informacao gerada.';
|
|
1588
|
+
const message = this.sanitizeBlockedAssistantMessage(response.message || response.explanation || 'Informacao gerada.');
|
|
1341
1589
|
return {
|
|
1342
1590
|
state: 'success',
|
|
1343
1591
|
phase: 'summarize',
|
|
@@ -1530,6 +1778,27 @@ class ManualFormAgenticAuthoringTurnFlow {
|
|
|
1530
1778
|
},
|
|
1531
1779
|
};
|
|
1532
1780
|
}
|
|
1781
|
+
sanitizeBlockedAssistantMessage(message) {
|
|
1782
|
+
const trimmed = (message ?? '').trim();
|
|
1783
|
+
if (!trimmed) {
|
|
1784
|
+
return 'Esta operação não pôde ser executada automaticamente neste turno. Revise o escopo ou informe os dados desejados.';
|
|
1785
|
+
}
|
|
1786
|
+
const kept = trimmed
|
|
1787
|
+
.split(/(?<=[.!?])\s+/)
|
|
1788
|
+
.map((part) => part.trim())
|
|
1789
|
+
.filter((part) => part.length > 0 && !this.isFalseExecutionPromiseSentence(part));
|
|
1790
|
+
if (kept.length === 0) {
|
|
1791
|
+
return 'Esta operação não pôde ser executada automaticamente neste turno. Revise o escopo ou informe os dados desejados.';
|
|
1792
|
+
}
|
|
1793
|
+
return kept.join(' ');
|
|
1794
|
+
}
|
|
1795
|
+
isFalseExecutionPromiseSentence(sentence) {
|
|
1796
|
+
return (/^(pronto|feito|conclu[ií]do|done|ready)[.!]*$/i.test(sentence) ||
|
|
1797
|
+
/\b(preenchi|preenchemos|preenchido[s]?|apliquei|aplicamos|salvei|salvamos)\b.*\b(campo[s]?|formul[aá]rio|altera[cç][oõ]es|configura[cç][aã]o|valores)\b/i.test(sentence) ||
|
|
1798
|
+
/\b(confirme|clique)\s+para\s+(aplicar|salvar|preencher|materializar)\b/i.test(sentence) ||
|
|
1799
|
+
/\bdeseja\s+(aplicar|salvar|materializar)\s+(a\s+configura[cç][aã]o|o\s+patch|as\s+altera[cç][oõ]es|os\s+valores)\b/i.test(sentence) ||
|
|
1800
|
+
/\bposso\s+aplicar\s+agora\b/i.test(sentence));
|
|
1801
|
+
}
|
|
1533
1802
|
optionalJsonObject(value) {
|
|
1534
1803
|
if (value === undefined || value === null) {
|
|
1535
1804
|
return undefined;
|
|
@@ -1564,6 +1833,16 @@ class ManualFormAgenticAuthoringTurnFlow {
|
|
|
1564
1833
|
? value
|
|
1565
1834
|
: null;
|
|
1566
1835
|
}
|
|
1836
|
+
extractRuntimeValueProposal(candidate) {
|
|
1837
|
+
const record = this.toRecord(candidate);
|
|
1838
|
+
if (!record ||
|
|
1839
|
+
record['schemaVersion'] !== PRAXIS_RUNTIME_FORM_VALUE_PROPOSAL_SCHEMA_VERSION ||
|
|
1840
|
+
!Array.isArray(record['assignments']) ||
|
|
1841
|
+
!this.toRecord(record['targetIdentity'])) {
|
|
1842
|
+
return null;
|
|
1843
|
+
}
|
|
1844
|
+
return record;
|
|
1845
|
+
}
|
|
1567
1846
|
}
|
|
1568
1847
|
|
|
1569
1848
|
const MANUAL_FORM_SELECTOR_TO_CONTROL_TYPE = new InjectionToken('MANUAL_FORM_SELECTOR_TO_CONTROL_TYPE');
|
|
@@ -2036,6 +2315,7 @@ class ManualFormComponent {
|
|
|
2036
2315
|
showActions = input(true, ...(ngDevMode ? [{ debugName: "showActions" }] : /* istanbul ignore next */ []));
|
|
2037
2316
|
enableAutoSave = input(true, ...(ngDevMode ? [{ debugName: "enableAutoSave" }] : /* istanbul ignore next */ []));
|
|
2038
2317
|
componentInstanceId = input(...(ngDevMode ? [undefined, { debugName: "componentInstanceId" }] : /* istanbul ignore next */ []));
|
|
2318
|
+
showAiAssistant = input(true, ...(ngDevMode ? [{ debugName: "showAiAssistant" }] : /* istanbul ignore next */ []));
|
|
2039
2319
|
// Allows editor affordances (e.g., opening metadata editor on interactions)
|
|
2040
2320
|
enableCustomization = input(false, ...(ngDevMode ? [{ debugName: "enableCustomization" }] : /* istanbul ignore next */ []));
|
|
2041
2321
|
persistenceOptions = input(...(ngDevMode ? [undefined, { debugName: "persistenceOptions" }] : /* istanbul ignore next */ []));
|
|
@@ -2044,6 +2324,11 @@ class ManualFormComponent {
|
|
|
2044
2324
|
usePathNames = input(false, ...(ngDevMode ? [{ debugName: "usePathNames" }] : /* istanbul ignore next */ []));
|
|
2045
2325
|
// Debounce interval for autosave (ms). Only used when enableAutoSave is true.
|
|
2046
2326
|
autoSaveDebounceMs = input(800, ...(ngDevMode ? [{ debugName: "autoSaveDebounceMs" }] : /* istanbul ignore next */ []));
|
|
2327
|
+
resourcePath = input(...(ngDevMode ? [undefined, { debugName: "resourcePath" }] : /* istanbul ignore next */ []));
|
|
2328
|
+
governedSchema = input(null, ...(ngDevMode ? [{ debugName: "governedSchema" }] : /* istanbul ignore next */ []));
|
|
2329
|
+
schemaHash = input(...(ngDevMode ? [undefined, { debugName: "schemaHash" }] : /* istanbul ignore next */ []));
|
|
2330
|
+
mode = input('create', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
2331
|
+
entityId = input(null, ...(ngDevMode ? [{ debugName: "entityId" }] : /* istanbul ignore next */ []));
|
|
2047
2332
|
submitted = output();
|
|
2048
2333
|
saved = output();
|
|
2049
2334
|
resetEvent = output({ alias: 'reset' });
|
|
@@ -2071,6 +2356,12 @@ class ManualFormComponent {
|
|
|
2071
2356
|
aiAssistantStateSubscription = null;
|
|
2072
2357
|
formGroup = new FormGroup({});
|
|
2073
2358
|
registeredDirectives = [];
|
|
2359
|
+
runtimeValueJournal = new PraxisRuntimeFormValueSessionJournal();
|
|
2360
|
+
runtimeValueRevision = 0;
|
|
2361
|
+
runtimeValueTrackedForm = null;
|
|
2362
|
+
runtimeValueStatusSub;
|
|
2363
|
+
runtimeValueTrackedControls = new Map();
|
|
2364
|
+
suppressRuntimeValueTrackingDepth = 0;
|
|
2074
2365
|
constructor() {
|
|
2075
2366
|
// Host-typed mode: if a FormGroupDirective is present, adopt its FormGroup without monkey patches.
|
|
2076
2367
|
if (this.hostFormGroupDirective) {
|
|
@@ -2120,9 +2411,16 @@ class ManualFormComponent {
|
|
|
2120
2411
|
this.metadataSubscription?.unsubscribe();
|
|
2121
2412
|
this.toolbarOverlayRef?.dispose();
|
|
2122
2413
|
this.outsideClickSubscription?.unsubscribe();
|
|
2414
|
+
this.clearRuntimeValueControlSubscriptions();
|
|
2123
2415
|
this.assistantSessions.removeContextSession(this.buildAiAssistantContextSnapshot().identity);
|
|
2124
2416
|
this.aiAssistantStateSubscription?.unsubscribe();
|
|
2125
2417
|
}
|
|
2418
|
+
get effectiveFormIsValid() {
|
|
2419
|
+
this.syncHostFormGroupReference();
|
|
2420
|
+
return (!this.formGroup.invalid &&
|
|
2421
|
+
!this.formGroup.pending &&
|
|
2422
|
+
this.formGroup.status === 'VALID');
|
|
2423
|
+
}
|
|
2126
2424
|
// =============================
|
|
2127
2425
|
// ControlContainer interface
|
|
2128
2426
|
// =============================
|
|
@@ -2234,14 +2532,35 @@ class ManualFormComponent {
|
|
|
2234
2532
|
}
|
|
2235
2533
|
}
|
|
2236
2534
|
async handleSubmit() {
|
|
2535
|
+
this.syncHostFormGroupReference();
|
|
2237
2536
|
if (!this.instance) {
|
|
2238
2537
|
return;
|
|
2239
2538
|
}
|
|
2539
|
+
if (this.formGroup.invalid ||
|
|
2540
|
+
this.formGroup.pending ||
|
|
2541
|
+
this.formGroup.status !== 'VALID') {
|
|
2542
|
+
this.formGroup.markAllAsTouched();
|
|
2543
|
+
if (!this.formGroup.pending) {
|
|
2544
|
+
this.formGroup.updateValueAndValidity({ onlySelf: false, emitEvent: false });
|
|
2545
|
+
}
|
|
2546
|
+
this.cdr.markForCheck();
|
|
2547
|
+
return;
|
|
2548
|
+
}
|
|
2240
2549
|
const value = this.formGroup.getRawValue();
|
|
2241
2550
|
const beforeSubmitOk = await this.runHooks('beforeSubmit', { value });
|
|
2242
2551
|
if (!beforeSubmitOk) {
|
|
2243
2552
|
return;
|
|
2244
2553
|
}
|
|
2554
|
+
if (this.formGroup.invalid ||
|
|
2555
|
+
this.formGroup.pending ||
|
|
2556
|
+
this.formGroup.status !== 'VALID') {
|
|
2557
|
+
this.formGroup.markAllAsTouched();
|
|
2558
|
+
if (!this.formGroup.pending) {
|
|
2559
|
+
this.formGroup.updateValueAndValidity({ onlySelf: false, emitEvent: false });
|
|
2560
|
+
}
|
|
2561
|
+
this.cdr.markForCheck();
|
|
2562
|
+
return;
|
|
2563
|
+
}
|
|
2245
2564
|
if (this.enableAutoSave()) {
|
|
2246
2565
|
this.instance.saveDraft(value);
|
|
2247
2566
|
}
|
|
@@ -2380,8 +2699,8 @@ class ManualFormComponent {
|
|
|
2380
2699
|
this.cdr.markForCheck();
|
|
2381
2700
|
});
|
|
2382
2701
|
}
|
|
2383
|
-
onAiAssistantApply() {
|
|
2384
|
-
this.aiAssistantController?.apply().subscribe((state) => {
|
|
2702
|
+
onAiAssistantApply(contextHints) {
|
|
2703
|
+
this.aiAssistantController?.apply(contextHints ?? undefined).subscribe((state) => {
|
|
2385
2704
|
this.aiAssistantViewState = state;
|
|
2386
2705
|
this.syncAiAssistantSession();
|
|
2387
2706
|
this.cdr.markForCheck();
|
|
@@ -2560,7 +2879,7 @@ class ManualFormComponent {
|
|
|
2560
2879
|
};
|
|
2561
2880
|
}
|
|
2562
2881
|
syncAiAssistantSession(visibility = null) {
|
|
2563
|
-
if (!this.enableCustomization())
|
|
2882
|
+
if (!this.showAiAssistant() && !this.enableCustomization())
|
|
2564
2883
|
return;
|
|
2565
2884
|
if (!this.aiAssistantOpen && !this.hasAiAssistantSessionState() && visibility !== 'minimized')
|
|
2566
2885
|
return;
|
|
@@ -2602,6 +2921,10 @@ class ManualFormComponent {
|
|
|
2602
2921
|
return routePath || 'local';
|
|
2603
2922
|
}
|
|
2604
2923
|
resolveAiAssistantSummary() {
|
|
2924
|
+
const retentionPolicy = this.aiAssistantViewState?.runtimeValueProposal?.['retentionPolicy'];
|
|
2925
|
+
if (retentionPolicy === 'zero') {
|
|
2926
|
+
return 'Assistência efêmera de preenchimento (retenção zero).';
|
|
2927
|
+
}
|
|
2605
2928
|
const status = this.aiAssistantViewState?.statusText?.trim();
|
|
2606
2929
|
if (status)
|
|
2607
2930
|
return status;
|
|
@@ -2686,6 +3009,7 @@ class ManualFormComponent {
|
|
|
2686
3009
|
this.applyInstanceToTemplate(fields);
|
|
2687
3010
|
this.registerToolbarBindings(fields);
|
|
2688
3011
|
this.attachMetadataSync();
|
|
3012
|
+
this.ensureRuntimeValueTracking();
|
|
2689
3013
|
// Auto-save value changes with debounce
|
|
2690
3014
|
if (this.enableAutoSave() && this.instance) {
|
|
2691
3015
|
this.instance.form.valueChanges
|
|
@@ -3249,11 +3573,477 @@ class ManualFormComponent {
|
|
|
3249
3573
|
resetButtonLabel: source.resetButtonLabel ?? base.resetButtonLabel,
|
|
3250
3574
|
};
|
|
3251
3575
|
}
|
|
3576
|
+
getRuntimeValueTargetIdentity() {
|
|
3577
|
+
this.syncHostFormGroupReference();
|
|
3578
|
+
this.ensureRuntimeValueTracking();
|
|
3579
|
+
const rawFormId = this.safeAiAssistantFormId() || 'praxis-manual-form';
|
|
3580
|
+
const rawInstanceId = this.componentInstanceId()?.trim() || rawFormId;
|
|
3581
|
+
const rawEntityId = this.entityId();
|
|
3582
|
+
const entityId = typeof rawEntityId === 'number' && Number.isFinite(rawEntityId)
|
|
3583
|
+
? rawEntityId
|
|
3584
|
+
: typeof rawEntityId === 'string' && rawEntityId.trim().length > 0
|
|
3585
|
+
? rawEntityId.trim()
|
|
3586
|
+
: null;
|
|
3587
|
+
const resolvedSchemaHash = this.schemaHash()?.trim() ||
|
|
3588
|
+
this.extractGovernedSchemaHash() ||
|
|
3589
|
+
this.instance?.currentConfig?.metadata?.['serverHash']
|
|
3590
|
+
?.toString()
|
|
3591
|
+
.trim() ||
|
|
3592
|
+
null;
|
|
3593
|
+
const rawMode = this.mode();
|
|
3594
|
+
const normalizedMode = rawMode === 'edit' ? 'edit' : rawMode === 'view' ? 'view' : 'create';
|
|
3595
|
+
return {
|
|
3596
|
+
componentId: rawFormId,
|
|
3597
|
+
instanceId: rawInstanceId,
|
|
3598
|
+
formId: rawFormId,
|
|
3599
|
+
resourcePath: this.resourcePath()?.trim() || null,
|
|
3600
|
+
mode: normalizedMode,
|
|
3601
|
+
entityId,
|
|
3602
|
+
schemaHash: resolvedSchemaHash,
|
|
3603
|
+
valueRevision: this.runtimeValueRevision,
|
|
3604
|
+
};
|
|
3605
|
+
}
|
|
3606
|
+
getRuntimeValueEligibility() {
|
|
3607
|
+
this.syncHostFormGroupReference();
|
|
3608
|
+
this.ensureRuntimeValueTracking();
|
|
3609
|
+
const autoSaveEnabled = Boolean(this.enableAutoSave());
|
|
3610
|
+
const hasPendingAsyncValidators = Boolean(this.formGroup?.pending);
|
|
3611
|
+
const mode = this.getRuntimeValueTargetIdentity().mode;
|
|
3612
|
+
const { writableFields, nonOverwritableFields, hasGovernedSource } = this.collectRuntimeValueFieldClassification();
|
|
3613
|
+
if (mode === 'view') {
|
|
3614
|
+
return {
|
|
3615
|
+
eligible: false,
|
|
3616
|
+
blockReason: 'view-mode-read-only',
|
|
3617
|
+
blockMessage: 'O formulário manual está em modo somente leitura e não aceita preenchimento.',
|
|
3618
|
+
autoSaveEnabled,
|
|
3619
|
+
hasPendingReactiveDeterminations: false,
|
|
3620
|
+
hasPendingAsyncValidators,
|
|
3621
|
+
writableFields: [],
|
|
3622
|
+
nonOverwritableFields,
|
|
3623
|
+
};
|
|
3624
|
+
}
|
|
3625
|
+
if (autoSaveEnabled) {
|
|
3626
|
+
return {
|
|
3627
|
+
eligible: false,
|
|
3628
|
+
blockReason: 'auto-save-enabled',
|
|
3629
|
+
blockMessage: 'A aplicação automática está bloqueada porque o salvamento automático (enableAutoSave) está ativo neste formulário.',
|
|
3630
|
+
autoSaveEnabled: true,
|
|
3631
|
+
hasPendingReactiveDeterminations: false,
|
|
3632
|
+
hasPendingAsyncValidators,
|
|
3633
|
+
writableFields,
|
|
3634
|
+
nonOverwritableFields,
|
|
3635
|
+
};
|
|
3636
|
+
}
|
|
3637
|
+
if (!hasGovernedSource) {
|
|
3638
|
+
return {
|
|
3639
|
+
eligible: false,
|
|
3640
|
+
blockReason: 'governed-schema-required',
|
|
3641
|
+
blockMessage: 'O formulário manual exige contrato de criação ou artefato governado (resourcePath/governedSchema) para validar campos elegíveis; allowedFields apenas do navegador não autoriza escrita.',
|
|
3642
|
+
autoSaveEnabled: false,
|
|
3643
|
+
hasPendingReactiveDeterminations: false,
|
|
3644
|
+
hasPendingAsyncValidators,
|
|
3645
|
+
writableFields: [],
|
|
3646
|
+
nonOverwritableFields,
|
|
3647
|
+
};
|
|
3648
|
+
}
|
|
3649
|
+
if (hasPendingAsyncValidators) {
|
|
3650
|
+
return {
|
|
3651
|
+
eligible: false,
|
|
3652
|
+
blockReason: 'pending-async-validators',
|
|
3653
|
+
blockMessage: 'Existem validações assíncronas pendentes no formulário. Aguarde a conclusão antes de aplicar valores.',
|
|
3654
|
+
autoSaveEnabled: false,
|
|
3655
|
+
hasPendingReactiveDeterminations: false,
|
|
3656
|
+
hasPendingAsyncValidators: true,
|
|
3657
|
+
writableFields,
|
|
3658
|
+
nonOverwritableFields,
|
|
3659
|
+
};
|
|
3660
|
+
}
|
|
3661
|
+
if (writableFields.length === 0) {
|
|
3662
|
+
return {
|
|
3663
|
+
eligible: false,
|
|
3664
|
+
blockReason: 'no-writable-fields',
|
|
3665
|
+
blockMessage: 'O formulário manual não possui campos elegíveis para preenchimento assistido.',
|
|
3666
|
+
autoSaveEnabled: false,
|
|
3667
|
+
hasPendingReactiveDeterminations: false,
|
|
3668
|
+
hasPendingAsyncValidators,
|
|
3669
|
+
writableFields,
|
|
3670
|
+
nonOverwritableFields,
|
|
3671
|
+
};
|
|
3672
|
+
}
|
|
3673
|
+
return {
|
|
3674
|
+
eligible: true,
|
|
3675
|
+
blockReason: null,
|
|
3676
|
+
blockMessage: null,
|
|
3677
|
+
autoSaveEnabled: false,
|
|
3678
|
+
hasPendingReactiveDeterminations: false,
|
|
3679
|
+
hasPendingAsyncValidators,
|
|
3680
|
+
writableFields,
|
|
3681
|
+
nonOverwritableFields,
|
|
3682
|
+
};
|
|
3683
|
+
}
|
|
3684
|
+
previewRuntimeValues(proposal, options) {
|
|
3685
|
+
this.syncHostFormGroupReference();
|
|
3686
|
+
this.ensureRuntimeValueTracking();
|
|
3687
|
+
return previewRuntimeFormValueProposal(this.createRuntimeFormHostCallbacks(), proposal, options);
|
|
3688
|
+
}
|
|
3689
|
+
applyRuntimeValues(request) {
|
|
3690
|
+
this.syncHostFormGroupReference();
|
|
3691
|
+
this.ensureRuntimeValueTracking();
|
|
3692
|
+
const receipt = applyRuntimeFormValueProposal(this.createRuntimeFormHostCallbacks(), this.runtimeValueJournal, request);
|
|
3693
|
+
if (receipt.appliedFields.length > 0) {
|
|
3694
|
+
this.cdr.markForCheck();
|
|
3695
|
+
}
|
|
3696
|
+
return receipt;
|
|
3697
|
+
}
|
|
3698
|
+
undoRuntimeValues(receiptId) {
|
|
3699
|
+
this.syncHostFormGroupReference();
|
|
3700
|
+
this.ensureRuntimeValueTracking();
|
|
3701
|
+
const receipt = undoRuntimeFormValueApply(this.createRuntimeFormHostCallbacks(), this.runtimeValueJournal, receiptId);
|
|
3702
|
+
if (receipt.revertedFields.length > 0) {
|
|
3703
|
+
this.cdr.markForCheck();
|
|
3704
|
+
}
|
|
3705
|
+
return receipt;
|
|
3706
|
+
}
|
|
3707
|
+
clearRuntimeValueControlSubscriptions() {
|
|
3708
|
+
this.runtimeValueStatusSub?.unsubscribe();
|
|
3709
|
+
this.runtimeValueStatusSub = undefined;
|
|
3710
|
+
for (const entry of this.runtimeValueTrackedControls.values()) {
|
|
3711
|
+
entry.sub.unsubscribe();
|
|
3712
|
+
}
|
|
3713
|
+
this.runtimeValueTrackedControls.clear();
|
|
3714
|
+
this.runtimeValueTrackedForm = null;
|
|
3715
|
+
}
|
|
3716
|
+
collectLeafFormControls(group, prefix = '', out = new Map()) {
|
|
3717
|
+
if (!group?.controls) {
|
|
3718
|
+
return out;
|
|
3719
|
+
}
|
|
3720
|
+
for (const [key, control] of Object.entries(group.controls)) {
|
|
3721
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
3722
|
+
if (control instanceof FormGroup) {
|
|
3723
|
+
this.collectLeafFormControls(control, path, out);
|
|
3724
|
+
}
|
|
3725
|
+
else if (control) {
|
|
3726
|
+
out.set(path, control);
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
return out;
|
|
3730
|
+
}
|
|
3731
|
+
ensureRuntimeValueTracking() {
|
|
3732
|
+
if (!this.formGroup) {
|
|
3733
|
+
return;
|
|
3734
|
+
}
|
|
3735
|
+
if (this.runtimeValueTrackedForm !== this.formGroup) {
|
|
3736
|
+
this.clearRuntimeValueControlSubscriptions();
|
|
3737
|
+
this.runtimeValueTrackedForm = this.formGroup;
|
|
3738
|
+
this.runtimeValueStatusSub = this.formGroup.statusChanges
|
|
3739
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3740
|
+
.subscribe(() => {
|
|
3741
|
+
this.cdr.markForCheck();
|
|
3742
|
+
});
|
|
3743
|
+
}
|
|
3744
|
+
const leafControls = this.collectLeafFormControls(this.formGroup);
|
|
3745
|
+
for (const [fieldPath, control] of leafControls.entries()) {
|
|
3746
|
+
const existing = this.runtimeValueTrackedControls.get(fieldPath);
|
|
3747
|
+
if (existing?.control === control) {
|
|
3748
|
+
continue;
|
|
3749
|
+
}
|
|
3750
|
+
existing?.sub.unsubscribe();
|
|
3751
|
+
const sub = control.valueChanges
|
|
3752
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3753
|
+
.subscribe(() => {
|
|
3754
|
+
if (this.suppressRuntimeValueTrackingDepth > 0) {
|
|
3755
|
+
return;
|
|
3756
|
+
}
|
|
3757
|
+
this.runtimeValueRevision += 1;
|
|
3758
|
+
const instanceKey = instanceKeyFor(this.getRuntimeValueTargetIdentity());
|
|
3759
|
+
this.runtimeValueJournal.markFieldManuallyEdited(instanceKey, fieldPath);
|
|
3760
|
+
});
|
|
3761
|
+
this.runtimeValueTrackedControls.set(fieldPath, { control, sub });
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
createRuntimeFormHostCallbacks() {
|
|
3765
|
+
return {
|
|
3766
|
+
getTargetIdentity: () => this.getRuntimeValueTargetIdentity(),
|
|
3767
|
+
getEligibility: () => this.getRuntimeValueEligibility(),
|
|
3768
|
+
getControl: (fieldPath) => {
|
|
3769
|
+
const control = this.formGroup?.get(fieldPath) ?? null;
|
|
3770
|
+
if (!control) {
|
|
3771
|
+
return null;
|
|
3772
|
+
}
|
|
3773
|
+
return {
|
|
3774
|
+
exists: true,
|
|
3775
|
+
getValue: () => control.value,
|
|
3776
|
+
setValue: (value) => {
|
|
3777
|
+
control.setValue(value);
|
|
3778
|
+
},
|
|
3779
|
+
isDirty: () => control.dirty,
|
|
3780
|
+
setDirty: (dirty) => {
|
|
3781
|
+
if (dirty) {
|
|
3782
|
+
control.markAsDirty();
|
|
3783
|
+
}
|
|
3784
|
+
else {
|
|
3785
|
+
control.markAsPristine({ onlySelf: true });
|
|
3786
|
+
const anyControlDirty = Object.values(this.formGroup?.controls ?? {}).some((item) => item.dirty);
|
|
3787
|
+
if (!anyControlDirty) {
|
|
3788
|
+
this.formGroup?.markAsPristine({ onlySelf: true });
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
},
|
|
3792
|
+
isTouched: () => control.touched,
|
|
3793
|
+
setTouched: (touched) => {
|
|
3794
|
+
if (touched) {
|
|
3795
|
+
control.markAsTouched();
|
|
3796
|
+
}
|
|
3797
|
+
else {
|
|
3798
|
+
control.markAsUntouched({ onlySelf: true });
|
|
3799
|
+
const anyControlTouched = Object.values(this.formGroup?.controls ?? {}).some((item) => item.touched);
|
|
3800
|
+
if (!anyControlTouched) {
|
|
3801
|
+
this.formGroup?.markAsUntouched({ onlySelf: true });
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3804
|
+
},
|
|
3805
|
+
};
|
|
3806
|
+
},
|
|
3807
|
+
incrementValueRevision: () => {
|
|
3808
|
+
this.runtimeValueRevision += 1;
|
|
3809
|
+
return this.runtimeValueRevision;
|
|
3810
|
+
},
|
|
3811
|
+
withSuppressedCommandSideEffects: (fn) => {
|
|
3812
|
+
this.suppressRuntimeValueTrackingDepth += 1;
|
|
3813
|
+
try {
|
|
3814
|
+
return fn();
|
|
3815
|
+
}
|
|
3816
|
+
finally {
|
|
3817
|
+
this.suppressRuntimeValueTrackingDepth = Math.max(0, this.suppressRuntimeValueTrackingDepth - 1);
|
|
3818
|
+
}
|
|
3819
|
+
},
|
|
3820
|
+
};
|
|
3821
|
+
}
|
|
3822
|
+
extractGovernedSchemaHash() {
|
|
3823
|
+
const governed = this.governedSchema();
|
|
3824
|
+
if (!governed || Array.isArray(governed) || typeof governed !== 'object') {
|
|
3825
|
+
return null;
|
|
3826
|
+
}
|
|
3827
|
+
const rawHash = governed['schemaHash'] ??
|
|
3828
|
+
governed['x-schema-hash'];
|
|
3829
|
+
return typeof rawHash === 'string' && rawHash.trim().length > 0
|
|
3830
|
+
? rawHash.trim()
|
|
3831
|
+
: null;
|
|
3832
|
+
}
|
|
3833
|
+
extractGovernedFieldMap() {
|
|
3834
|
+
const governed = this.governedSchema();
|
|
3835
|
+
const fieldsByName = new Map();
|
|
3836
|
+
if (Array.isArray(governed)) {
|
|
3837
|
+
for (const item of governed) {
|
|
3838
|
+
if (item && typeof item === 'object' && typeof item.name === 'string') {
|
|
3839
|
+
fieldsByName.set(item.name, item);
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
return {
|
|
3843
|
+
hasGovernedSource: true,
|
|
3844
|
+
strictGovernedAllowlist: true,
|
|
3845
|
+
fieldsByName,
|
|
3846
|
+
};
|
|
3847
|
+
}
|
|
3848
|
+
if (governed && typeof governed === 'object') {
|
|
3849
|
+
const properties = governed['properties'];
|
|
3850
|
+
const requiredSet = new Set(Array.isArray(governed['required'])
|
|
3851
|
+
? governed['required']
|
|
3852
|
+
: []);
|
|
3853
|
+
if (properties && typeof properties === 'object' && !Array.isArray(properties)) {
|
|
3854
|
+
for (const [fieldName, prop] of Object.entries(properties)) {
|
|
3855
|
+
if (prop && typeof prop === 'object') {
|
|
3856
|
+
fieldsByName.set(fieldName, {
|
|
3857
|
+
...prop,
|
|
3858
|
+
name: fieldName,
|
|
3859
|
+
required: prop['required'] ?? requiredSet.has(fieldName),
|
|
3860
|
+
});
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
return {
|
|
3865
|
+
hasGovernedSource: true,
|
|
3866
|
+
strictGovernedAllowlist: true,
|
|
3867
|
+
fieldsByName,
|
|
3868
|
+
};
|
|
3869
|
+
}
|
|
3870
|
+
const hasResourceOrHash = Boolean(this.resourcePath()?.trim() || this.schemaHash()?.trim());
|
|
3871
|
+
if (hasResourceOrHash) {
|
|
3872
|
+
for (const meta of this.instance?.currentConfig?.fieldMetadata ?? []) {
|
|
3873
|
+
if (meta?.name) {
|
|
3874
|
+
fieldsByName.set(meta.name, meta);
|
|
3875
|
+
}
|
|
3876
|
+
}
|
|
3877
|
+
return {
|
|
3878
|
+
hasGovernedSource: true,
|
|
3879
|
+
strictGovernedAllowlist: fieldsByName.size > 0,
|
|
3880
|
+
fieldsByName,
|
|
3881
|
+
};
|
|
3882
|
+
}
|
|
3883
|
+
return {
|
|
3884
|
+
hasGovernedSource: false,
|
|
3885
|
+
strictGovernedAllowlist: false,
|
|
3886
|
+
fieldsByName,
|
|
3887
|
+
};
|
|
3888
|
+
}
|
|
3889
|
+
collectRuntimeValueFieldClassification() {
|
|
3890
|
+
const writableFields = [];
|
|
3891
|
+
const nonOverwritableFields = [];
|
|
3892
|
+
const { hasGovernedSource, strictGovernedAllowlist, fieldsByName } = this.extractGovernedFieldMap();
|
|
3893
|
+
const instanceMetaByName = new Map();
|
|
3894
|
+
for (const meta of this.instance?.currentConfig?.fieldMetadata ?? []) {
|
|
3895
|
+
if (meta?.name) {
|
|
3896
|
+
instanceMetaByName.set(meta.name, meta);
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
const leafControls = this.collectLeafFormControls(this.formGroup);
|
|
3900
|
+
const allFieldNames = new Set([
|
|
3901
|
+
...fieldsByName.keys(),
|
|
3902
|
+
...instanceMetaByName.keys(),
|
|
3903
|
+
...leafControls.keys(),
|
|
3904
|
+
]);
|
|
3905
|
+
const evalMode = this.mode() === 'edit' ? 'edit' : this.mode() === 'view' ? 'view' : 'create';
|
|
3906
|
+
for (const fieldPath of allFieldNames) {
|
|
3907
|
+
const governedField = fieldsByName.get(fieldPath);
|
|
3908
|
+
const instanceField = instanceMetaByName.get(fieldPath);
|
|
3909
|
+
const field = {
|
|
3910
|
+
...(instanceField ?? {}),
|
|
3911
|
+
...(governedField ?? {}),
|
|
3912
|
+
};
|
|
3913
|
+
const control = this.formGroup?.get(fieldPath) ?? null;
|
|
3914
|
+
const label = typeof field['label'] === 'string' && field['label'].trim()
|
|
3915
|
+
? field['label'].trim()
|
|
3916
|
+
: typeof field['x-ui']?.['label'] === 'string' &&
|
|
3917
|
+
field['x-ui']['label'].trim()
|
|
3918
|
+
? field['x-ui']['label'].trim()
|
|
3919
|
+
: fieldPath;
|
|
3920
|
+
if (strictGovernedAllowlist && !fieldsByName.has(fieldPath)) {
|
|
3921
|
+
nonOverwritableFields.push({
|
|
3922
|
+
fieldPath,
|
|
3923
|
+
label,
|
|
3924
|
+
reason: 'restricted-by-field-access',
|
|
3925
|
+
message: 'Campo ausente no contrato de criação / artefato governado do formulário manual.',
|
|
3926
|
+
});
|
|
3927
|
+
continue;
|
|
3928
|
+
}
|
|
3929
|
+
const xUi = (field['x-ui'] ?? {});
|
|
3930
|
+
const rawFieldAccess = field['fieldAccess'] ?? xUi['fieldAccess'];
|
|
3931
|
+
const access = evaluateFieldAccess(rawFieldAccess);
|
|
3932
|
+
const rawAiPolicy = String(field['aiUsagePolicy'] ??
|
|
3933
|
+
field['domainGovernance']?.['aiUsagePolicy'] ??
|
|
3934
|
+
xUi['aiUsagePolicy'] ??
|
|
3935
|
+
xUi['domainGovernance']?.['aiUsagePolicy'] ??
|
|
3936
|
+
rawFieldAccess?.['aiUsagePolicy'] ??
|
|
3937
|
+
'')
|
|
3938
|
+
.trim()
|
|
3939
|
+
.toUpperCase();
|
|
3940
|
+
const aiDisallowed = field['allowedForAiPrompting'] === false ||
|
|
3941
|
+
field['domainGovernance']?.['allowedForAiPrompting'] === false ||
|
|
3942
|
+
xUi['allowedForAiPrompting'] === false ||
|
|
3943
|
+
rawFieldAccess?.['allowedForAiPrompting'] === false ||
|
|
3944
|
+
rawAiPolicy === 'NEVER' ||
|
|
3945
|
+
rawAiPolicy === 'NONE' ||
|
|
3946
|
+
rawAiPolicy === 'FORBIDDEN' ||
|
|
3947
|
+
rawAiPolicy === 'READ_ONLY' ||
|
|
3948
|
+
rawAiPolicy === 'MASKED_ONLY' ||
|
|
3949
|
+
rawAiPolicy === 'REDACTED_ONLY';
|
|
3950
|
+
if (aiDisallowed) {
|
|
3951
|
+
nonOverwritableFields.push({
|
|
3952
|
+
fieldPath,
|
|
3953
|
+
label,
|
|
3954
|
+
reason: 'restricted-by-ai-policy',
|
|
3955
|
+
message: 'Campo restrito pela governança de IA (@DomainGovernance / AiUsagePolicy).',
|
|
3956
|
+
});
|
|
3957
|
+
continue;
|
|
3958
|
+
}
|
|
3959
|
+
const restrictedByFieldAccess = rawFieldAccess != null &&
|
|
3960
|
+
(access.editable === false ||
|
|
3961
|
+
access.visible === false ||
|
|
3962
|
+
(rawFieldAccess['creatable'] === false && evalMode === 'create') ||
|
|
3963
|
+
(rawFieldAccess['updatable'] === false && evalMode === 'edit') ||
|
|
3964
|
+
rawFieldAccess['writable'] === false);
|
|
3965
|
+
if (restrictedByFieldAccess) {
|
|
3966
|
+
nonOverwritableFields.push({
|
|
3967
|
+
fieldPath,
|
|
3968
|
+
label,
|
|
3969
|
+
reason: 'restricted-by-field-access',
|
|
3970
|
+
message: 'Campo restrito pela política de acesso (x-ui.fieldAccess).',
|
|
3971
|
+
});
|
|
3972
|
+
continue;
|
|
3973
|
+
}
|
|
3974
|
+
const isReadOnly = evalMode === 'view' ||
|
|
3975
|
+
field['readOnly'] === true ||
|
|
3976
|
+
field['readonly'] === true ||
|
|
3977
|
+
xUi['readOnly'] === true ||
|
|
3978
|
+
xUi['readonly'] === true;
|
|
3979
|
+
if (isReadOnly) {
|
|
3980
|
+
nonOverwritableFields.push({
|
|
3981
|
+
fieldPath,
|
|
3982
|
+
label,
|
|
3983
|
+
reason: 'read-only',
|
|
3984
|
+
message: 'Campo somente leitura não pode ser sobrescrito.',
|
|
3985
|
+
});
|
|
3986
|
+
continue;
|
|
3987
|
+
}
|
|
3988
|
+
const isDisabled = Boolean(control?.disabled) ||
|
|
3989
|
+
field['disabled'] === true ||
|
|
3990
|
+
xUi['disabled'] === true;
|
|
3991
|
+
if (isDisabled) {
|
|
3992
|
+
nonOverwritableFields.push({
|
|
3993
|
+
fieldPath,
|
|
3994
|
+
label,
|
|
3995
|
+
reason: 'disabled',
|
|
3996
|
+
message: 'Campo desabilitado não pode ser sobrescrito.',
|
|
3997
|
+
});
|
|
3998
|
+
continue;
|
|
3999
|
+
}
|
|
4000
|
+
const isHidden = field['hidden'] === true ||
|
|
4001
|
+
field['formHidden'] === true ||
|
|
4002
|
+
field['visible'] === false ||
|
|
4003
|
+
xUi['hidden'] === true ||
|
|
4004
|
+
xUi['visible'] === false;
|
|
4005
|
+
if (isHidden) {
|
|
4006
|
+
nonOverwritableFields.push({
|
|
4007
|
+
fieldPath,
|
|
4008
|
+
label,
|
|
4009
|
+
reason: 'hidden',
|
|
4010
|
+
message: 'Campo oculto não pode ser sobrescrito.',
|
|
4011
|
+
});
|
|
4012
|
+
continue;
|
|
4013
|
+
}
|
|
4014
|
+
if (!control) {
|
|
4015
|
+
nonOverwritableFields.push({
|
|
4016
|
+
fieldPath,
|
|
4017
|
+
label,
|
|
4018
|
+
reason: 'unsupported-control',
|
|
4019
|
+
message: 'Controle não encontrado no FormGroup do formulário manual.',
|
|
4020
|
+
});
|
|
4021
|
+
continue;
|
|
4022
|
+
}
|
|
4023
|
+
const optionSource = (field['optionSource'] ??
|
|
4024
|
+
xUi['optionSource'] ??
|
|
4025
|
+
null);
|
|
4026
|
+
writableFields.push({
|
|
4027
|
+
fieldPath,
|
|
4028
|
+
label,
|
|
4029
|
+
dataType: field['type'] ??
|
|
4030
|
+
field['dataType'] ??
|
|
4031
|
+
null,
|
|
4032
|
+
controlType: field['controlType'] ??
|
|
4033
|
+
xUi['controlType'] ??
|
|
4034
|
+
null,
|
|
4035
|
+
required: Boolean(field['required'] || field['validators']?.['required']),
|
|
4036
|
+
optionSourceKey: typeof optionSource?.['key'] === 'string' ? optionSource['key'] : null,
|
|
4037
|
+
optionSourceType: typeof optionSource?.['type'] === 'string' ? optionSource['type'] : null,
|
|
4038
|
+
});
|
|
4039
|
+
}
|
|
4040
|
+
return { writableFields, nonOverwritableFields, hasGovernedSource };
|
|
4041
|
+
}
|
|
3252
4042
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3253
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ManualFormComponent, isStandalone: true, selector: "praxis-manual-form", inputs: { formId: { classPropertyName: "formId", publicName: "formId", isSignal: true, isRequired: true, transformFunction: null }, formTitle: { classPropertyName: "formTitle", publicName: "formTitle", isSignal: true, isRequired: false, transformFunction: null }, formDescription: { classPropertyName: "formDescription", publicName: "formDescription", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, showActions: { classPropertyName: "showActions", publicName: "showActions", isSignal: true, isRequired: false, transformFunction: null }, enableAutoSave: { classPropertyName: "enableAutoSave", publicName: "enableAutoSave", isSignal: true, isRequired: false, transformFunction: null }, componentInstanceId: { classPropertyName: "componentInstanceId", publicName: "componentInstanceId", isSignal: true, isRequired: false, transformFunction: null }, enableCustomization: { classPropertyName: "enableCustomization", publicName: "enableCustomization", isSignal: true, isRequired: false, transformFunction: null }, persistenceOptions: { classPropertyName: "persistenceOptions", publicName: "persistenceOptions", isSignal: true, isRequired: false, transformFunction: null }, usePathNames: { classPropertyName: "usePathNames", publicName: "usePathNames", isSignal: true, isRequired: false, transformFunction: null }, autoSaveDebounceMs: { classPropertyName: "autoSaveDebounceMs", publicName: "autoSaveDebounceMs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted", saved: "saved", resetEvent: "reset", metadataChange: "metadataChange" }, providers: [
|
|
4043
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ManualFormComponent, isStandalone: true, selector: "praxis-manual-form", inputs: { formId: { classPropertyName: "formId", publicName: "formId", isSignal: true, isRequired: true, transformFunction: null }, formTitle: { classPropertyName: "formTitle", publicName: "formTitle", isSignal: true, isRequired: false, transformFunction: null }, formDescription: { classPropertyName: "formDescription", publicName: "formDescription", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, showActions: { classPropertyName: "showActions", publicName: "showActions", isSignal: true, isRequired: false, transformFunction: null }, enableAutoSave: { classPropertyName: "enableAutoSave", publicName: "enableAutoSave", isSignal: true, isRequired: false, transformFunction: null }, componentInstanceId: { classPropertyName: "componentInstanceId", publicName: "componentInstanceId", isSignal: true, isRequired: false, transformFunction: null }, showAiAssistant: { classPropertyName: "showAiAssistant", publicName: "showAiAssistant", isSignal: true, isRequired: false, transformFunction: null }, enableCustomization: { classPropertyName: "enableCustomization", publicName: "enableCustomization", isSignal: true, isRequired: false, transformFunction: null }, persistenceOptions: { classPropertyName: "persistenceOptions", publicName: "persistenceOptions", isSignal: true, isRequired: false, transformFunction: null }, usePathNames: { classPropertyName: "usePathNames", publicName: "usePathNames", isSignal: true, isRequired: false, transformFunction: null }, autoSaveDebounceMs: { classPropertyName: "autoSaveDebounceMs", publicName: "autoSaveDebounceMs", isSignal: true, isRequired: false, transformFunction: null }, resourcePath: { classPropertyName: "resourcePath", publicName: "resourcePath", isSignal: true, isRequired: false, transformFunction: null }, governedSchema: { classPropertyName: "governedSchema", publicName: "governedSchema", isSignal: true, isRequired: false, transformFunction: null }, schemaHash: { classPropertyName: "schemaHash", publicName: "schemaHash", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted", saved: "saved", resetEvent: "reset", metadataChange: "metadataChange" }, providers: [
|
|
3254
4044
|
// Provide a ControlContainer at the host boundary so projected formControlName can resolve it
|
|
3255
4045
|
{ provide: ControlContainer, useExisting: ManualFormComponent },
|
|
3256
|
-
], queries: [{ propertyName: "formControls", predicate: FormControlName, descendants: true }], ngImport: i0, template: "<div class=\"pdx-manual-form\">\n @if (showHeader()) {\n <praxis-manual-form-header [instance]=\"instance\" [title]=\"formTitle()\" [description]=\"formDescription()\"\n [enableCustomization]=\"enableCustomization()\" (editForm)=\"openFormEditor()\" (save)=\"handleSave()\"\n (reset)=\"handleReset()\"></praxis-manual-form-header>\n }\n\n @if (enableCustomization()) {\n <div class=\"pdx-manual-form__assistant\">\n <button\n type=\"button\"\n class=\"pdx-manual-form__assistant-trigger\"\n (click)=\"openAiAssistant()\"\n aria-label=\"Abrir copiloto
|
|
4046
|
+
], queries: [{ propertyName: "formControls", predicate: FormControlName, descendants: true }], ngImport: i0, template: "<div class=\"pdx-manual-form\">\n @if (showHeader()) {\n <praxis-manual-form-header [instance]=\"instance\" [title]=\"formTitle()\" [description]=\"formDescription()\"\n [enableCustomization]=\"enableCustomization()\" (editForm)=\"openFormEditor()\" (save)=\"handleSave()\"\n (reset)=\"handleReset()\"></praxis-manual-form-header>\n }\n\n @if (showAiAssistant() || enableCustomization()) {\n <div class=\"pdx-manual-form__assistant\">\n <button\n type=\"button\"\n class=\"pdx-manual-form__assistant-trigger\"\n (click)=\"openAiAssistant()\"\n [attr.aria-label]=\"enableCustomization() ? 'Abrir copiloto sem\u00E2ntico Praxis do formul\u00E1rio manual' : 'Abrir assistente de preenchimento do formul\u00E1rio manual'\"\n data-testid=\"praxis-manual-form-ai-assistant-trigger\"\n >\n {{ enableCustomization() ? 'Copiloto Praxis' : 'Assistente de preenchimento' }}\n </button>\n </div>\n }\n\n @if (aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\n [canApply]=\"aiAssistantViewState.canApply\"\n [preview]=\"aiAssistantViewState.preview\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"praxis-manual-form-ai-assistant\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply($event)\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (close)=\"closeAiAssistant()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n ></praxis-ai-assistant-shell>\n }\n\n <form class=\"pdx-manual-form__form\" [formGroup]=\"formGroup\" (submit)=\"handleSubmit(); $event.preventDefault()\">\n <ng-content></ng-content>\n </form>\n\n @if (showActions() && resolvedActions) {\n <praxis-manual-form-actions [actions]=\"resolvedActions\" [submitDisabled]=\"!effectiveFormIsValid\"\n (actionClick)=\"handleAction($event)\"></praxis-manual-form-actions>\n }\n</div>\n", styles: [".pdx-manual-form{display:flex;flex-direction:column;gap:var(--pdx-manual-form-gap, 24px);color:var(--md-sys-color-on-surface)}.pdx-manual-form__form{display:grid;gap:var(--pdx-manual-form-field-gap, 16px);padding:var(--pdx-manual-form-padding, 20px);border-radius:var(--pdx-manual-form-radius, 16px);background:var(--pdx-manual-form-surface, var(--md-sys-color-surface-container));border:1px solid var(--pdx-manual-form-outline, var(--md-sys-color-outline-variant));box-shadow:var(--pdx-manual-form-shadow, var(--md-sys-elevation-level1, none))}.pdx-manual-form__form:focus-within{border-color:var(--pdx-manual-form-focus, var(--md-sys-color-primary));box-shadow:0 0 0 2px var(--md-sys-color-primary),var(--pdx-manual-form-shadow, var(--md-sys-elevation-level1, none))}.pdx-manual-form__assistant{display:flex;justify-content:flex-end}.pdx-manual-form__assistant-trigger{border:0;border-radius:999px;padding:8px 14px;cursor:pointer;color:var(--md-sys-color-on-primary, #fff);background:var(--md-sys-color-primary, #3451d1);box-shadow:var(--md-sys-elevation-level2, 0 4px 12px rgba(0, 0, 0, .18))}.pdx-manual-form__assistant-trigger:hover{background:var(--md-sys-color-primary-container, #223fb6)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "preview", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }, { kind: "component", type: ManualFormHeaderComponent, selector: "praxis-manual-form-header", inputs: ["instance", "title", "description", "saveLabel", "resetLabel", "enableCustomization", "editFormLabel"], outputs: ["save", "reset", "editForm"] }, { kind: "component", type: ManualFormActionsComponent, selector: "praxis-manual-form-actions", inputs: ["actions", "submitDisabled", "trackByFn"], outputs: ["actionClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3257
4047
|
}
|
|
3258
4048
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormComponent, decorators: [{
|
|
3259
4049
|
type: Component,
|
|
@@ -3265,8 +4055,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
3265
4055
|
], providers: [
|
|
3266
4056
|
// Provide a ControlContainer at the host boundary so projected formControlName can resolve it
|
|
3267
4057
|
{ provide: ControlContainer, useExisting: ManualFormComponent },
|
|
3268
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"pdx-manual-form\">\n @if (showHeader()) {\n <praxis-manual-form-header [instance]=\"instance\" [title]=\"formTitle()\" [description]=\"formDescription()\"\n [enableCustomization]=\"enableCustomization()\" (editForm)=\"openFormEditor()\" (save)=\"handleSave()\"\n (reset)=\"handleReset()\"></praxis-manual-form-header>\n }\n\n @if (enableCustomization()) {\n <div class=\"pdx-manual-form__assistant\">\n <button\n type=\"button\"\n class=\"pdx-manual-form__assistant-trigger\"\n (click)=\"openAiAssistant()\"\n aria-label=\"Abrir copiloto
|
|
3269
|
-
}], ctorParameters: () => [], propDecorators: { formId: [{ type: i0.Input, args: [{ isSignal: true, alias: "formId", required: true }] }], formTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "formTitle", required: false }] }], formDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "formDescription", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], showActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActions", required: false }] }], enableAutoSave: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableAutoSave", required: false }] }], componentInstanceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentInstanceId", required: false }] }], enableCustomization: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableCustomization", required: false }] }], persistenceOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "persistenceOptions", required: false }] }], usePathNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "usePathNames", required: false }] }], autoSaveDebounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoSaveDebounceMs", required: false }] }], submitted: [{ type: i0.Output, args: ["submitted"] }], saved: [{ type: i0.Output, args: ["saved"] }], resetEvent: [{ type: i0.Output, args: ["reset"] }], metadataChange: [{ type: i0.Output, args: ["metadataChange"] }], formControls: [{
|
|
4058
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"pdx-manual-form\">\n @if (showHeader()) {\n <praxis-manual-form-header [instance]=\"instance\" [title]=\"formTitle()\" [description]=\"formDescription()\"\n [enableCustomization]=\"enableCustomization()\" (editForm)=\"openFormEditor()\" (save)=\"handleSave()\"\n (reset)=\"handleReset()\"></praxis-manual-form-header>\n }\n\n @if (showAiAssistant() || enableCustomization()) {\n <div class=\"pdx-manual-form__assistant\">\n <button\n type=\"button\"\n class=\"pdx-manual-form__assistant-trigger\"\n (click)=\"openAiAssistant()\"\n [attr.aria-label]=\"enableCustomization() ? 'Abrir copiloto sem\u00E2ntico Praxis do formul\u00E1rio manual' : 'Abrir assistente de preenchimento do formul\u00E1rio manual'\"\n data-testid=\"praxis-manual-form-ai-assistant-trigger\"\n >\n {{ enableCustomization() ? 'Copiloto Praxis' : 'Assistente de preenchimento' }}\n </button>\n </div>\n }\n\n @if (aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\n [canApply]=\"aiAssistantViewState.canApply\"\n [preview]=\"aiAssistantViewState.preview\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"praxis-manual-form-ai-assistant\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply($event)\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (close)=\"closeAiAssistant()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n ></praxis-ai-assistant-shell>\n }\n\n <form class=\"pdx-manual-form__form\" [formGroup]=\"formGroup\" (submit)=\"handleSubmit(); $event.preventDefault()\">\n <ng-content></ng-content>\n </form>\n\n @if (showActions() && resolvedActions) {\n <praxis-manual-form-actions [actions]=\"resolvedActions\" [submitDisabled]=\"!effectiveFormIsValid\"\n (actionClick)=\"handleAction($event)\"></praxis-manual-form-actions>\n }\n</div>\n", styles: [".pdx-manual-form{display:flex;flex-direction:column;gap:var(--pdx-manual-form-gap, 24px);color:var(--md-sys-color-on-surface)}.pdx-manual-form__form{display:grid;gap:var(--pdx-manual-form-field-gap, 16px);padding:var(--pdx-manual-form-padding, 20px);border-radius:var(--pdx-manual-form-radius, 16px);background:var(--pdx-manual-form-surface, var(--md-sys-color-surface-container));border:1px solid var(--pdx-manual-form-outline, var(--md-sys-color-outline-variant));box-shadow:var(--pdx-manual-form-shadow, var(--md-sys-elevation-level1, none))}.pdx-manual-form__form:focus-within{border-color:var(--pdx-manual-form-focus, var(--md-sys-color-primary));box-shadow:0 0 0 2px var(--md-sys-color-primary),var(--pdx-manual-form-shadow, var(--md-sys-elevation-level1, none))}.pdx-manual-form__assistant{display:flex;justify-content:flex-end}.pdx-manual-form__assistant-trigger{border:0;border-radius:999px;padding:8px 14px;cursor:pointer;color:var(--md-sys-color-on-primary, #fff);background:var(--md-sys-color-primary, #3451d1);box-shadow:var(--md-sys-elevation-level2, 0 4px 12px rgba(0, 0, 0, .18))}.pdx-manual-form__assistant-trigger:hover{background:var(--md-sys-color-primary-container, #223fb6)}\n"] }]
|
|
4059
|
+
}], ctorParameters: () => [], propDecorators: { formId: [{ type: i0.Input, args: [{ isSignal: true, alias: "formId", required: true }] }], formTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "formTitle", required: false }] }], formDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "formDescription", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], showActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActions", required: false }] }], enableAutoSave: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableAutoSave", required: false }] }], componentInstanceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentInstanceId", required: false }] }], showAiAssistant: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAiAssistant", required: false }] }], enableCustomization: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableCustomization", required: false }] }], persistenceOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "persistenceOptions", required: false }] }], usePathNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "usePathNames", required: false }] }], autoSaveDebounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoSaveDebounceMs", required: false }] }], resourcePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "resourcePath", required: false }] }], governedSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "governedSchema", required: false }] }], schemaHash: [{ type: i0.Input, args: [{ isSignal: true, alias: "schemaHash", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], entityId: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityId", required: false }] }], submitted: [{ type: i0.Output, args: ["submitted"] }], saved: [{ type: i0.Output, args: ["saved"] }], resetEvent: [{ type: i0.Output, args: ["reset"] }], metadataChange: [{ type: i0.Output, args: ["metadataChange"] }], formControls: [{
|
|
3270
4060
|
type: ContentChildren,
|
|
3271
4061
|
args: [FormControlName, { descendants: true }]
|
|
3272
4062
|
}] } });
|
|
@@ -6101,7 +6891,7 @@ setCustomizationEnabled(enabled: boolean): void {
|
|
|
6101
6891
|
</ol>
|
|
6102
6892
|
</div>
|
|
6103
6893
|
</praxis-manual-form-doc-example>
|
|
6104
|
-
`, isInline: true, styles: [":host{display:block}.showcase-art{display:flex;gap:6px;flex-wrap:wrap}.showcase-art__chip{border-radius:999px;padding:4px 8px;font-size:11px;font-weight:700;border:1px solid color-mix(in srgb,var(--md-sys-color-outline, #98a3af) 50%,#d7dde3);background:color-mix(in srgb,var(--md-sys-color-primary, #00796b) 14%,#ffffff);color:var(--md-sys-color-on-surface, #151b22)}.showcase-live{display:grid;gap:12px}.showcase-mode{margin:0;border-radius:10px;border:1px solid #d6dde4;background:#f6f8fb;padding:8px 10px;color:#3b4651;font-size:13px}.showcase-mode--enabled{border-color:#5ebdb0;background:#e9f9f5;color:#075146}.showcase-field{display:grid;gap:6px}.showcase-field span{font-size:13px;font-weight:600}.showcase-field input,.showcase-field textarea{width:100%;border-radius:8px;border:1px solid #c8d2dc;padding:9px 10px;font:inherit;color:#1a222b;background:#fff}.showcase-field input:focus-visible,.showcase-field textarea:focus-visible{outline:2px solid #2d7f73;outline-offset:1px}.showcase-diagram{border-radius:12px;border:1px dashed #bdd0db;background:#f8fbff;padding:12px 14px}.showcase-diagram ol{margin:0;padding-left:20px;display:grid;gap:6px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: ManualFormComponent, selector: "praxis-manual-form", inputs: ["formId", "formTitle", "formDescription", "actions", "showHeader", "showActions", "enableAutoSave", "componentInstanceId", "enableCustomization", "persistenceOptions", "usePathNames", "autoSaveDebounceMs"], outputs: ["submitted", "saved", "reset", "metadataChange"] }, { kind: "component", type: ManualFormDocExampleComponent, selector: "praxis-manual-form-doc-example", inputs: ["title", "subtitle", "level", "bannerTitle", "bannerDescription", "templateCode", "tsCode", "configCode", "customizationEnabled", "showCustomizationToggle", "important", "note", "tip"], outputs: ["tabChange", "customizationEnabledChange", "codeCopied"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6894
|
+
`, isInline: true, styles: [":host{display:block}.showcase-art{display:flex;gap:6px;flex-wrap:wrap}.showcase-art__chip{border-radius:999px;padding:4px 8px;font-size:11px;font-weight:700;border:1px solid color-mix(in srgb,var(--md-sys-color-outline, #98a3af) 50%,#d7dde3);background:color-mix(in srgb,var(--md-sys-color-primary, #00796b) 14%,#ffffff);color:var(--md-sys-color-on-surface, #151b22)}.showcase-live{display:grid;gap:12px}.showcase-mode{margin:0;border-radius:10px;border:1px solid #d6dde4;background:#f6f8fb;padding:8px 10px;color:#3b4651;font-size:13px}.showcase-mode--enabled{border-color:#5ebdb0;background:#e9f9f5;color:#075146}.showcase-field{display:grid;gap:6px}.showcase-field span{font-size:13px;font-weight:600}.showcase-field input,.showcase-field textarea{width:100%;border-radius:8px;border:1px solid #c8d2dc;padding:9px 10px;font:inherit;color:#1a222b;background:#fff}.showcase-field input:focus-visible,.showcase-field textarea:focus-visible{outline:2px solid #2d7f73;outline-offset:1px}.showcase-diagram{border-radius:12px;border:1px dashed #bdd0db;background:#f8fbff;padding:12px 14px}.showcase-diagram ol{margin:0;padding-left:20px;display:grid;gap:6px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: ManualFormComponent, selector: "praxis-manual-form", inputs: ["formId", "formTitle", "formDescription", "actions", "showHeader", "showActions", "enableAutoSave", "componentInstanceId", "showAiAssistant", "enableCustomization", "persistenceOptions", "usePathNames", "autoSaveDebounceMs", "resourcePath", "governedSchema", "schemaHash", "mode", "entityId"], outputs: ["submitted", "saved", "reset", "metadataChange"] }, { kind: "component", type: ManualFormDocExampleComponent, selector: "praxis-manual-form-doc-example", inputs: ["title", "subtitle", "level", "bannerTitle", "bannerDescription", "templateCode", "tsCode", "configCode", "customizationEnabled", "showCustomizationToggle", "important", "note", "tip"], outputs: ["tabChange", "customizationEnabledChange", "codeCopied"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6105
6895
|
}
|
|
6106
6896
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormDocExampleShowcaseComponent, decorators: [{
|
|
6107
6897
|
type: Component,
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/manual-form",
|
|
3
|
-
"version": "10.0.0-rc.
|
|
3
|
+
"version": "10.0.0-rc.42",
|
|
4
4
|
"description": "Manual form toolkit for Praxis UI: container, instance factory and editor bridge for @praxisui/* fields.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
7
7
|
"@angular/core": "^21.0.0",
|
|
8
|
-
"@praxisui/core": "^10.0.0-rc.
|
|
9
|
-
"@praxisui/dynamic-fields": "^10.0.0-rc.
|
|
10
|
-
"@praxisui/settings-panel": "^10.0.0-rc.
|
|
11
|
-
"@praxisui/metadata-editor": "^10.0.0-rc.
|
|
8
|
+
"@praxisui/core": "^10.0.0-rc.42",
|
|
9
|
+
"@praxisui/dynamic-fields": "^10.0.0-rc.42",
|
|
10
|
+
"@praxisui/settings-panel": "^10.0.0-rc.42",
|
|
11
|
+
"@praxisui/metadata-editor": "^10.0.0-rc.42",
|
|
12
12
|
"@angular/cdk": "^21.0.0",
|
|
13
13
|
"@angular/forms": "^21.0.0",
|
|
14
14
|
"@angular/material": "^21.0.0",
|
|
15
15
|
"@angular/router": "^21.0.0",
|
|
16
|
-
"@praxisui/ai": "^10.0.0-rc.
|
|
16
|
+
"@praxisui/ai": "^10.0.0-rc.42",
|
|
17
17
|
"rxjs": "~7.8.0"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FormConfig, FieldMetadata, DynamicFormService, AsyncConfigStorage, FormActionsLayout, FormActionButton, AiCapability, FormMessagesLayout, FormBehaviorLayout, FormHookStage, FieldDefinition, FieldControlType, AiCapabilityCategory, AiCapabilityCatalog, AiValueKind, ComponentAuthoringManifest, ComponentDocMeta } from '@praxisui/core';
|
|
1
|
+
import { FormConfig, FieldMetadata, DynamicFormService, AsyncConfigStorage, FormActionsLayout, FormActionButton, AiCapability, PraxisRuntimeFormValueTargetIdentity, PraxisRuntimeFormValueEligibility, PraxisRuntimeFormValueProposal, PraxisRuntimeFormValueApplyMode, PraxisRuntimeFormValuePreviewResult, PraxisRuntimeFormValueApplyRequest, PraxisRuntimeFormValueApplyReceipt, PraxisRuntimeFormValueUndoReceipt, PraxisRuntimeFormValueTargetPort, PraxisRuntimeFormValueMode, FormMessagesLayout, FormBehaviorLayout, FormHookStage, FieldDefinition, FieldControlType, AiCapabilityCategory, AiCapabilityCatalog, AiValueKind, ComponentAuthoringManifest, ComponentDocMeta } from '@praxisui/core';
|
|
2
2
|
import { FormGroup, FormControlName, FormGroupName, AbstractControl, FormControl } from '@angular/forms';
|
|
3
3
|
import { Observable, BehaviorSubject } from 'rxjs';
|
|
4
4
|
import * as _angular_core from '@angular/core';
|
|
@@ -144,12 +144,13 @@ declare class ManualFormHeaderComponent {
|
|
|
144
144
|
|
|
145
145
|
declare class ManualFormActionsComponent {
|
|
146
146
|
readonly actions: _angular_core.InputSignal<FormActionsLayout | null | undefined>;
|
|
147
|
+
readonly submitDisabled: _angular_core.InputSignal<boolean>;
|
|
147
148
|
trackByFn: ((idx: number, item: FormActionButton) => unknown) | null;
|
|
148
149
|
readonly actionClick: _angular_core.OutputEmitterRef<string>;
|
|
149
150
|
isVisible(action?: FormActionButton | null): boolean;
|
|
150
151
|
emit(kind: string, action?: FormActionButton | null): void;
|
|
151
152
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ManualFormActionsComponent, never>;
|
|
152
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ManualFormActionsComponent, "praxis-manual-form-actions", never, { "actions": { "alias": "actions"; "required": false; "isSignal": true; }; "trackByFn": { "alias": "trackByFn"; "required": false; }; }, { "actionClick": "actionClick"; }, never, never, true, never>;
|
|
153
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ManualFormActionsComponent, "praxis-manual-form-actions", never, { "actions": { "alias": "actions"; "required": false; "isSignal": true; }; "submitDisabled": { "alias": "submitDisabled"; "required": false; "isSignal": true; }; "trackByFn": { "alias": "trackByFn"; "required": false; }; }, { "actionClick": "actionClick"; }, never, never, true, never>;
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
declare class ManualFormAiAdapter extends BaseAiAdapter<FormConfig> {
|
|
@@ -164,6 +165,15 @@ declare class ManualFormAiAdapter extends BaseAiAdapter<FormConfig> {
|
|
|
164
165
|
getDataProfile(): Record<string, any>;
|
|
165
166
|
getSchemaFields(): Record<string, any>[];
|
|
166
167
|
getAuthoringContext(): Record<string, any>;
|
|
168
|
+
private resolveGovernedSchemaPayload;
|
|
169
|
+
getRuntimeValueTargetIdentity(): PraxisRuntimeFormValueTargetIdentity | null;
|
|
170
|
+
getRuntimeValueEligibility(): PraxisRuntimeFormValueEligibility | null;
|
|
171
|
+
previewRuntimeValues(proposal: PraxisRuntimeFormValueProposal, options?: {
|
|
172
|
+
readonly selectedFieldPaths?: readonly string[];
|
|
173
|
+
readonly applyMode?: PraxisRuntimeFormValueApplyMode;
|
|
174
|
+
}): PraxisRuntimeFormValuePreviewResult | null;
|
|
175
|
+
applyRuntimeValues(request: PraxisRuntimeFormValueApplyRequest): Promise<PraxisRuntimeFormValueApplyReceipt | null>;
|
|
176
|
+
undoRuntimeValues(receiptId?: string): Promise<PraxisRuntimeFormValueUndoReceipt | null>;
|
|
167
177
|
createSnapshot(): FormConfig;
|
|
168
178
|
restoreSnapshot(snapshot: FormConfig): Promise<void>;
|
|
169
179
|
applyPatch(patch: Partial<FormConfig>, _intent?: string): Promise<PatchResult>;
|
|
@@ -173,7 +183,7 @@ declare class ManualFormAiAdapter extends BaseAiAdapter<FormConfig> {
|
|
|
173
183
|
private safeFormId;
|
|
174
184
|
}
|
|
175
185
|
|
|
176
|
-
declare class ManualFormComponent implements AfterContentInit, OnDestroy {
|
|
186
|
+
declare class ManualFormComponent implements AfterContentInit, OnDestroy, PraxisRuntimeFormValueTargetPort {
|
|
177
187
|
private readonly instanceFactory;
|
|
178
188
|
private readonly cdr;
|
|
179
189
|
private readonly destroyRef;
|
|
@@ -210,10 +220,16 @@ declare class ManualFormComponent implements AfterContentInit, OnDestroy {
|
|
|
210
220
|
readonly showActions: _angular_core.InputSignal<boolean>;
|
|
211
221
|
readonly enableAutoSave: _angular_core.InputSignal<boolean>;
|
|
212
222
|
readonly componentInstanceId: _angular_core.InputSignal<string | undefined>;
|
|
223
|
+
readonly showAiAssistant: _angular_core.InputSignal<boolean>;
|
|
213
224
|
readonly enableCustomization: _angular_core.InputSignal<boolean>;
|
|
214
225
|
readonly persistenceOptions: _angular_core.InputSignal<ManualFormPersistenceOptions | undefined>;
|
|
215
226
|
readonly usePathNames: _angular_core.InputSignal<boolean>;
|
|
216
227
|
readonly autoSaveDebounceMs: _angular_core.InputSignal<number>;
|
|
228
|
+
readonly resourcePath: _angular_core.InputSignal<string | undefined>;
|
|
229
|
+
readonly governedSchema: _angular_core.InputSignal<Record<string, unknown> | readonly FieldMetadata[] | null | undefined>;
|
|
230
|
+
readonly schemaHash: _angular_core.InputSignal<string | undefined>;
|
|
231
|
+
readonly mode: _angular_core.InputSignal<PraxisRuntimeFormValueMode>;
|
|
232
|
+
readonly entityId: _angular_core.InputSignal<string | number | null | undefined>;
|
|
217
233
|
readonly submitted: _angular_core.OutputEmitterRef<{
|
|
218
234
|
value: any;
|
|
219
235
|
instance: ManualFormInstance;
|
|
@@ -235,9 +251,16 @@ declare class ManualFormComponent implements AfterContentInit, OnDestroy {
|
|
|
235
251
|
private aiAssistantStateSubscription;
|
|
236
252
|
formGroup: FormGroup;
|
|
237
253
|
private readonly registeredDirectives;
|
|
254
|
+
private readonly runtimeValueJournal;
|
|
255
|
+
private runtimeValueRevision;
|
|
256
|
+
private runtimeValueTrackedForm;
|
|
257
|
+
private runtimeValueStatusSub?;
|
|
258
|
+
private readonly runtimeValueTrackedControls;
|
|
259
|
+
private suppressRuntimeValueTrackingDepth;
|
|
238
260
|
constructor();
|
|
239
261
|
ngAfterContentInit(): void;
|
|
240
262
|
ngOnDestroy(): void;
|
|
263
|
+
get effectiveFormIsValid(): boolean;
|
|
241
264
|
get formDirective(): any;
|
|
242
265
|
get control(): FormGroup;
|
|
243
266
|
get path(): any[];
|
|
@@ -268,7 +291,7 @@ declare class ManualFormComponent implements AfterContentInit, OnDestroy {
|
|
|
268
291
|
closeAiAssistant(): void;
|
|
269
292
|
onAiAssistantPromptChange(prompt: string): void;
|
|
270
293
|
onAiAssistantSubmit(prompt: string): void;
|
|
271
|
-
onAiAssistantApply(): void;
|
|
294
|
+
onAiAssistantApply(contextHints?: Record<string, unknown> | void): void;
|
|
272
295
|
onAiAssistantRetry(): void;
|
|
273
296
|
onAiAssistantCancel(): void;
|
|
274
297
|
onAiAssistantQuickReply(reply: PraxisAssistantShellQuickReply): void;
|
|
@@ -324,8 +347,23 @@ declare class ManualFormComponent implements AfterContentInit, OnDestroy {
|
|
|
324
347
|
private applyMetadataToComponent;
|
|
325
348
|
private buildCurrentConfigSnapshot;
|
|
326
349
|
private normalizeActions;
|
|
350
|
+
getRuntimeValueTargetIdentity(): PraxisRuntimeFormValueTargetIdentity;
|
|
351
|
+
getRuntimeValueEligibility(): PraxisRuntimeFormValueEligibility;
|
|
352
|
+
previewRuntimeValues(proposal: PraxisRuntimeFormValueProposal, options?: {
|
|
353
|
+
readonly selectedFieldPaths?: readonly string[];
|
|
354
|
+
readonly applyMode?: PraxisRuntimeFormValueApplyMode;
|
|
355
|
+
}): PraxisRuntimeFormValuePreviewResult;
|
|
356
|
+
applyRuntimeValues(request: PraxisRuntimeFormValueApplyRequest): PraxisRuntimeFormValueApplyReceipt;
|
|
357
|
+
undoRuntimeValues(receiptId?: string): PraxisRuntimeFormValueUndoReceipt;
|
|
358
|
+
private clearRuntimeValueControlSubscriptions;
|
|
359
|
+
private collectLeafFormControls;
|
|
360
|
+
private ensureRuntimeValueTracking;
|
|
361
|
+
private createRuntimeFormHostCallbacks;
|
|
362
|
+
private extractGovernedSchemaHash;
|
|
363
|
+
private extractGovernedFieldMap;
|
|
364
|
+
private collectRuntimeValueFieldClassification;
|
|
327
365
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ManualFormComponent, never>;
|
|
328
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ManualFormComponent, "praxis-manual-form", never, { "formId": { "alias": "formId"; "required": true; "isSignal": true; }; "formTitle": { "alias": "formTitle"; "required": false; "isSignal": true; }; "formDescription": { "alias": "formDescription"; "required": false; "isSignal": true; }; "actions": { "alias": "actions"; "required": false; "isSignal": true; }; "showHeader": { "alias": "showHeader"; "required": false; "isSignal": true; }; "showActions": { "alias": "showActions"; "required": false; "isSignal": true; }; "enableAutoSave": { "alias": "enableAutoSave"; "required": false; "isSignal": true; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; "isSignal": true; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; "isSignal": true; }; "persistenceOptions": { "alias": "persistenceOptions"; "required": false; "isSignal": true; }; "usePathNames": { "alias": "usePathNames"; "required": false; "isSignal": true; }; "autoSaveDebounceMs": { "alias": "autoSaveDebounceMs"; "required": false; "isSignal": true; }; }, { "submitted": "submitted"; "saved": "saved"; "resetEvent": "reset"; "metadataChange": "metadataChange"; }, ["formControls"], ["*"], true, never>;
|
|
366
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ManualFormComponent, "praxis-manual-form", never, { "formId": { "alias": "formId"; "required": true; "isSignal": true; }; "formTitle": { "alias": "formTitle"; "required": false; "isSignal": true; }; "formDescription": { "alias": "formDescription"; "required": false; "isSignal": true; }; "actions": { "alias": "actions"; "required": false; "isSignal": true; }; "showHeader": { "alias": "showHeader"; "required": false; "isSignal": true; }; "showActions": { "alias": "showActions"; "required": false; "isSignal": true; }; "enableAutoSave": { "alias": "enableAutoSave"; "required": false; "isSignal": true; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; "isSignal": true; }; "showAiAssistant": { "alias": "showAiAssistant"; "required": false; "isSignal": true; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; "isSignal": true; }; "persistenceOptions": { "alias": "persistenceOptions"; "required": false; "isSignal": true; }; "usePathNames": { "alias": "usePathNames"; "required": false; "isSignal": true; }; "autoSaveDebounceMs": { "alias": "autoSaveDebounceMs"; "required": false; "isSignal": true; }; "resourcePath": { "alias": "resourcePath"; "required": false; "isSignal": true; }; "governedSchema": { "alias": "governedSchema"; "required": false; "isSignal": true; }; "schemaHash": { "alias": "schemaHash"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "entityId": { "alias": "entityId"; "required": false; "isSignal": true; }; }, { "submitted": "submitted"; "saved": "saved"; "resetEvent": "reset"; "metadataChange": "metadataChange"; }, ["formControls"], ["*"], true, never>;
|
|
329
367
|
}
|
|
330
368
|
|
|
331
369
|
interface PanelInputs {
|