@praxisui/editorial-forms 1.0.0-beta.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +6 -0
- package/README.md +421 -0
- package/fesm2022/praxisui-editorial-forms.mjs +2611 -0
- package/fesm2022/praxisui-editorial-forms.mjs.map +1 -0
- package/index.d.ts +438 -0
- package/package.json +46 -0
|
@@ -0,0 +1,2611 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { makeEnvironmentProviders, InjectionToken, inject, input, output, signal, computed, effect, ChangeDetectionStrategy, Component, reflectComponentType, Input } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/common';
|
|
4
|
+
import { CommonModule, NgComponentOutlet } from '@angular/common';
|
|
5
|
+
import { DynamicWidgetLoaderDirective } from '@praxisui/core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Root provider entrypoint for the editorial runtime package.
|
|
9
|
+
*
|
|
10
|
+
* Intentionally minimal in v1:
|
|
11
|
+
* - no global singleton graph yet
|
|
12
|
+
* - no dependency on @praxisui/dynamic-form
|
|
13
|
+
* - safe to consume from apps without pulling generic form authoring
|
|
14
|
+
*/
|
|
15
|
+
function providePraxisEditorialForms() {
|
|
16
|
+
return makeEnvironmentProviders([]);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const DEFAULT_EDITORIAL_RUNTIME_HOST_CONFIG = {
|
|
20
|
+
emitOperationalEvents: true,
|
|
21
|
+
forwardAdapterOperationalEvents: true,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
function resolveActiveJourney(journeys, journeyId) {
|
|
25
|
+
if (!journeys.length) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return journeys.find((journey) => journey.journeyId === journeyId) ?? journeys[0];
|
|
29
|
+
}
|
|
30
|
+
function resolveActiveStep(journey, stepId) {
|
|
31
|
+
if (!journey?.steps.length) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return journey.steps.find((step) => step.stepId === stepId) ?? journey.steps[0];
|
|
35
|
+
}
|
|
36
|
+
function getVisibleBlocks(blocks, runtimeContext) {
|
|
37
|
+
return (blocks ?? []).filter((block) => isBlockVisible(block, runtimeContext));
|
|
38
|
+
}
|
|
39
|
+
function isBlockVisible(block, runtimeContext) {
|
|
40
|
+
if (!block.visibility?.length) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return block.visibility.every((rule) => matchesVisibilityRule(rule, runtimeContext));
|
|
44
|
+
}
|
|
45
|
+
function matchesVisibilityRule(rule, runtimeContext) {
|
|
46
|
+
if (!rule.when) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
const currentValue = getValueAtPath(runtimeContext ?? {}, rule.when);
|
|
50
|
+
if (rule.exists === true) {
|
|
51
|
+
return currentValue != null;
|
|
52
|
+
}
|
|
53
|
+
if (rule.exists === false) {
|
|
54
|
+
return currentValue == null;
|
|
55
|
+
}
|
|
56
|
+
if (rule.equals !== undefined) {
|
|
57
|
+
return currentValue === rule.equals;
|
|
58
|
+
}
|
|
59
|
+
if (rule.notEquals !== undefined) {
|
|
60
|
+
return currentValue !== rule.notEquals;
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
function getValueAtPath(source, path) {
|
|
65
|
+
return path.split('.').reduce((current, segment) => {
|
|
66
|
+
if (!current || typeof current !== 'object') {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return current[segment];
|
|
70
|
+
}, source);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getEditorialDataBlockAdapterToken() {
|
|
74
|
+
const registryKey = '__PAX_EDITORIAL_DATA_BLOCK_ADAPTER_TOKEN__';
|
|
75
|
+
const globalRegistry = globalThis;
|
|
76
|
+
if (!globalRegistry[registryKey]) {
|
|
77
|
+
globalRegistry[registryKey] = new InjectionToken('EDITORIAL_DATA_BLOCK_ADAPTER');
|
|
78
|
+
}
|
|
79
|
+
return globalRegistry[registryKey];
|
|
80
|
+
}
|
|
81
|
+
const EDITORIAL_DATA_BLOCK_ADAPTER = getEditorialDataBlockAdapterToken();
|
|
82
|
+
function resolveEditorialDataBlockFormConfigDetails(block, instance) {
|
|
83
|
+
if (block.formConfig) {
|
|
84
|
+
return {
|
|
85
|
+
source: 'block.formConfig',
|
|
86
|
+
formConfig: block.formConfig,
|
|
87
|
+
lookupKey: block.formBlockId,
|
|
88
|
+
ambiguous: false,
|
|
89
|
+
matchedSources: ['block.formConfig'],
|
|
90
|
+
matchedKeys: [block.formBlockId],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const runtimeConfigs = instance?.overrides?.runtimeFormConfigs;
|
|
94
|
+
const compatibilityConfigs = instance?.compatibilityFormConfigs;
|
|
95
|
+
const candidateKeys = [...new Set([block.formConfigRef, block.formBlockId].filter((value) => Boolean(value)))];
|
|
96
|
+
const matches = [];
|
|
97
|
+
for (const key of candidateKeys) {
|
|
98
|
+
const runtimeResolved = runtimeConfigs?.[key];
|
|
99
|
+
if (runtimeResolved) {
|
|
100
|
+
matches.push({
|
|
101
|
+
source: 'instance.overrides.runtimeFormConfigs',
|
|
102
|
+
formConfig: runtimeResolved,
|
|
103
|
+
lookupKey: key,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
const compatibilityResolved = compatibilityConfigs?.[key];
|
|
107
|
+
if (compatibilityResolved) {
|
|
108
|
+
matches.push({
|
|
109
|
+
source: 'instance.compatibilityFormConfigs',
|
|
110
|
+
formConfig: compatibilityResolved,
|
|
111
|
+
lookupKey: key,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (matches.length) {
|
|
116
|
+
const selected = matches[0];
|
|
117
|
+
return {
|
|
118
|
+
source: selected.source,
|
|
119
|
+
formConfig: selected.formConfig,
|
|
120
|
+
lookupKey: selected.lookupKey,
|
|
121
|
+
ambiguous: matches.length > 1,
|
|
122
|
+
matchedSources: matches.map((match) => match.source),
|
|
123
|
+
matchedKeys: matches.map((match) => match.lookupKey),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
source: 'unresolved',
|
|
128
|
+
formConfig: null,
|
|
129
|
+
lookupKey: block.formConfigRef ?? block.formBlockId,
|
|
130
|
+
ambiguous: false,
|
|
131
|
+
matchedSources: [],
|
|
132
|
+
matchedKeys: [],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function resolveEditorialDataBlockFormConfig(block, instance) {
|
|
136
|
+
return resolveEditorialDataBlockFormConfigDetails(block, instance).formConfig;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
class EditorialDataBlockAdapterRegistry {
|
|
140
|
+
adapters;
|
|
141
|
+
constructor(adapters) {
|
|
142
|
+
this.adapters = adapters;
|
|
143
|
+
}
|
|
144
|
+
resolve(context) {
|
|
145
|
+
return resolveEditorialDataBlockAdapter(this.adapters, context);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function provideEditorialDataBlockAdapter(adapter) {
|
|
149
|
+
return makeEnvironmentProviders([
|
|
150
|
+
{
|
|
151
|
+
provide: EDITORIAL_DATA_BLOCK_ADAPTER,
|
|
152
|
+
useValue: adapter,
|
|
153
|
+
multi: true,
|
|
154
|
+
},
|
|
155
|
+
]);
|
|
156
|
+
}
|
|
157
|
+
function resolveEditorialDataBlockAdapter(adapters, context) {
|
|
158
|
+
if (!adapters.length) {
|
|
159
|
+
return {
|
|
160
|
+
status: 'missing',
|
|
161
|
+
adapter: null,
|
|
162
|
+
adapterIds: [],
|
|
163
|
+
registrySize: 0,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
const resolved = adapters.find((candidate) => candidate.supports?.(context) ?? true) ?? null;
|
|
167
|
+
return {
|
|
168
|
+
status: resolved ? 'resolved' : 'incompatible',
|
|
169
|
+
adapter: resolved,
|
|
170
|
+
adapterIds: adapters.map((item) => item.adapterId),
|
|
171
|
+
registrySize: adapters.length,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
class EditorialDataCollectionBlockOutletComponent {
|
|
176
|
+
adapters = inject(EDITORIAL_DATA_BLOCK_ADAPTER, {
|
|
177
|
+
optional: true,
|
|
178
|
+
}) ?? [];
|
|
179
|
+
adapterRegistry = new EditorialDataBlockAdapterRegistry(this.adapters);
|
|
180
|
+
loadVersion = 0;
|
|
181
|
+
lastAdapterEventSignature = null;
|
|
182
|
+
block = input.required(...(ngDevMode ? [{ debugName: "block" }] : []));
|
|
183
|
+
runtimeContext = input(null, ...(ngDevMode ? [{ debugName: "runtimeContext" }] : []));
|
|
184
|
+
solution = input(null, ...(ngDevMode ? [{ debugName: "solution" }] : []));
|
|
185
|
+
instance = input(null, ...(ngDevMode ? [{ debugName: "instance" }] : []));
|
|
186
|
+
operationalEvent = output();
|
|
187
|
+
resolvedComponent = signal(null, ...(ngDevMode ? [{ debugName: "resolvedComponent" }] : []));
|
|
188
|
+
state = signal({ kind: 'idle' }, ...(ngDevMode ? [{ debugName: "state" }] : []));
|
|
189
|
+
adapterContext = computed(() => ({
|
|
190
|
+
block: this.block(),
|
|
191
|
+
runtimeContext: this.runtimeContext(),
|
|
192
|
+
solution: this.solution(),
|
|
193
|
+
instance: this.instance(),
|
|
194
|
+
resolvedFormConfig: resolveEditorialDataBlockFormConfig(this.block(), this.instance()),
|
|
195
|
+
}), ...(ngDevMode ? [{ debugName: "adapterContext" }] : []));
|
|
196
|
+
resolution = computed(() => resolveEditorialDataBlockFormConfigDetails(this.block(), this.instance()), ...(ngDevMode ? [{ debugName: "resolution" }] : []));
|
|
197
|
+
adapterResolution = computed(() => this.adapterRegistry.resolve(this.adapterContext()), ...(ngDevMode ? [{ debugName: "adapterResolution" }] : []));
|
|
198
|
+
adapter = computed(() => this.adapterResolution().adapter, ...(ngDevMode ? [{ debugName: "adapter" }] : []));
|
|
199
|
+
adapterComponent = computed(() => this.resolvedComponent() ?? this.adapter()?.component ?? null, ...(ngDevMode ? [{ debugName: "adapterComponent" }] : []));
|
|
200
|
+
loadingState = computed(() => {
|
|
201
|
+
const state = this.state();
|
|
202
|
+
return state.kind === 'loading' ? state : null;
|
|
203
|
+
}, ...(ngDevMode ? [{ debugName: "loadingState" }] : []));
|
|
204
|
+
errorState = computed(() => {
|
|
205
|
+
const state = this.state();
|
|
206
|
+
return state.kind === 'error' ? state : null;
|
|
207
|
+
}, ...(ngDevMode ? [{ debugName: "errorState" }] : []));
|
|
208
|
+
adapterInputs = computed(() => {
|
|
209
|
+
const adapter = this.adapter();
|
|
210
|
+
if (!adapter) {
|
|
211
|
+
return {};
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
block: this.block(),
|
|
215
|
+
runtimeContext: this.runtimeContext(),
|
|
216
|
+
solution: this.solution(),
|
|
217
|
+
instance: this.instance(),
|
|
218
|
+
resolvedFormConfig: this.resolution().formConfig,
|
|
219
|
+
...(adapter.buildInputs?.(this.adapterContext()) ?? {}),
|
|
220
|
+
};
|
|
221
|
+
}, ...(ngDevMode ? [{ debugName: "adapterInputs" }] : []));
|
|
222
|
+
fallbackMessage = computed(() => {
|
|
223
|
+
const resolution = this.resolution();
|
|
224
|
+
const block = this.block();
|
|
225
|
+
const adapterResolution = this.adapterResolution();
|
|
226
|
+
const errorState = this.errorState();
|
|
227
|
+
const snapshotState = isResolvedDataCollectionBlock(block)
|
|
228
|
+
? block.dataCollectionState
|
|
229
|
+
: null;
|
|
230
|
+
if (errorState) {
|
|
231
|
+
return errorState.message;
|
|
232
|
+
}
|
|
233
|
+
if (snapshotState?.readiness === 'invalid') {
|
|
234
|
+
return `O bloco "${block.formBlockId}" foi materializado com estado invalido. Revise formBlockId, formConfigRef e a configuracao editorial herdada.`;
|
|
235
|
+
}
|
|
236
|
+
if (snapshotState?.readiness === 'missingConfig') {
|
|
237
|
+
return `O bloco "${block.formBlockId}" nao encontrou configuracao de coleta. Chave consultada: ${snapshotState.resolvedFormConfigLookupKey ?? 'nenhuma chave candidata'}.`;
|
|
238
|
+
}
|
|
239
|
+
if (adapterResolution.status === 'incompatible') {
|
|
240
|
+
return `O bloco "${block.formBlockId}" encontrou adapters registrados (${adapterResolution.adapterIds.join(', ')}), mas nenhum declarou compatibilidade para esta coleta.`;
|
|
241
|
+
}
|
|
242
|
+
if (!resolution.formConfig && adapterResolution.status === 'missing') {
|
|
243
|
+
return `O bloco "${block.formBlockId}" nao encontrou configuracao de coleta nem adaptador registrado. Verifique o provider do host e a materializacao do FormConfig editorial.`;
|
|
244
|
+
}
|
|
245
|
+
if (!resolution.formConfig) {
|
|
246
|
+
return `O bloco "${block.formBlockId}" encontrou um adaptador, mas nao encontrou FormConfig em ${resolution.lookupKey ?? 'nenhuma chave conhecida'}.`;
|
|
247
|
+
}
|
|
248
|
+
return `Existe configuracao para "${block.formBlockId}" (${resolution.source}), mas nenhum adaptador de coleta foi registrado para materializar a engine.`;
|
|
249
|
+
}, ...(ngDevMode ? [{ debugName: "fallbackMessage" }] : []));
|
|
250
|
+
constructor() {
|
|
251
|
+
effect(() => {
|
|
252
|
+
const context = this.adapterContext();
|
|
253
|
+
const resolution = this.resolution();
|
|
254
|
+
const adapterResolution = this.adapterResolution();
|
|
255
|
+
const adapter = adapterResolution.adapter;
|
|
256
|
+
const requestVersion = ++this.loadVersion;
|
|
257
|
+
this.emitAdapterResolutionEvent(adapterResolution.status, adapter, undefined);
|
|
258
|
+
if (!adapter) {
|
|
259
|
+
this.resolvedComponent.set(null);
|
|
260
|
+
this.state.set({ kind: 'idle' });
|
|
261
|
+
if (adapterResolution.status === 'incompatible') {
|
|
262
|
+
this.state.set({
|
|
263
|
+
kind: 'error',
|
|
264
|
+
title: 'Adaptador incompatível',
|
|
265
|
+
message: `Nenhum adaptador registrado aceitou o bloco "${context.block.formBlockId}".`,
|
|
266
|
+
details: `Adapters disponiveis: ${adapterResolution.adapterIds.join(', ') || 'nenhum'}.`,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (!resolution.formConfig) {
|
|
272
|
+
this.resolvedComponent.set(null);
|
|
273
|
+
this.state.set({
|
|
274
|
+
kind: 'error',
|
|
275
|
+
title: 'Configuracao de coleta ausente',
|
|
276
|
+
message: `O bloco "${context.block.formBlockId}" nao possui FormConfig resolvido para a engine de coleta.`,
|
|
277
|
+
details: `Origem consultada: ${resolution.lookupKey ?? 'nenhuma chave candidata'}.`,
|
|
278
|
+
});
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (!adapter.resolveComponent) {
|
|
282
|
+
const component = adapter.component ?? null;
|
|
283
|
+
if (!component) {
|
|
284
|
+
this.resolvedComponent.set(null);
|
|
285
|
+
this.emitAdapterResolutionEvent('invalid', adapter, 'Registre um componente compatível ou implemente resolveComponent().');
|
|
286
|
+
this.state.set({
|
|
287
|
+
kind: 'error',
|
|
288
|
+
title: 'Adaptador incompleto',
|
|
289
|
+
message: `O adaptador "${adapter.displayName ?? adapter.adapterId}" nao expôs um componente de coleta.`,
|
|
290
|
+
details: 'Registre um componente compatível ou implemente resolveComponent().',
|
|
291
|
+
});
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
this.applyResolvedComponent(component, adapter, context, requestVersion);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
this.state.set({
|
|
298
|
+
kind: 'loading',
|
|
299
|
+
message: `Carregando a engine de coleta para "${context.block.formBlockId}"...`,
|
|
300
|
+
});
|
|
301
|
+
void this.loadAdapterComponent(adapter, context, requestVersion);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
async loadAdapterComponent(adapter, context, requestVersion) {
|
|
305
|
+
try {
|
|
306
|
+
const component = await adapter.resolveComponent?.(context);
|
|
307
|
+
this.applyResolvedComponent(component ?? null, adapter, context, requestVersion);
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
if (requestVersion !== this.loadVersion) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
this.resolvedComponent.set(null);
|
|
314
|
+
this.state.set({
|
|
315
|
+
kind: 'error',
|
|
316
|
+
title: 'Falha ao carregar a engine',
|
|
317
|
+
message: `O adaptador "${adapter.displayName ?? adapter.adapterId}" falhou ao preparar a coleta do bloco "${context.block.formBlockId}".`,
|
|
318
|
+
details: 'Valide o provider opcional do host e a disponibilidade do componente compatível.',
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
applyResolvedComponent(component, adapter, context, requestVersion) {
|
|
323
|
+
if (requestVersion !== this.loadVersion) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (!component) {
|
|
327
|
+
this.resolvedComponent.set(null);
|
|
328
|
+
this.state.set({
|
|
329
|
+
kind: 'error',
|
|
330
|
+
title: 'Componente nao resolvido',
|
|
331
|
+
message: `O adaptador "${adapter.displayName ?? adapter.adapterId}" nao retornou um componente para o bloco "${context.block.formBlockId}".`,
|
|
332
|
+
details: 'Implemente component ou resolveComponent() com um componente Angular compatível.',
|
|
333
|
+
});
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const validation = adapter.validateComponent?.(component, context) ?? { ok: true };
|
|
337
|
+
if (!validation.ok) {
|
|
338
|
+
this.resolvedComponent.set(null);
|
|
339
|
+
this.emitAdapterResolutionEvent('invalid', adapter, validation.reason);
|
|
340
|
+
this.state.set({
|
|
341
|
+
kind: 'error',
|
|
342
|
+
title: 'Componente incompatível',
|
|
343
|
+
message: `O adaptador "${adapter.displayName ?? adapter.adapterId}" retornou um componente incompatível para "${context.block.formBlockId}".`,
|
|
344
|
+
details: validation.reason,
|
|
345
|
+
});
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
this.resolvedComponent.set(component);
|
|
349
|
+
this.state.set({ kind: 'ready' });
|
|
350
|
+
this.emitAdapterResolutionEvent('resolved', adapter);
|
|
351
|
+
}
|
|
352
|
+
emitAdapterResolutionEvent(status, adapter, reason) {
|
|
353
|
+
const block = this.block();
|
|
354
|
+
const adapterIds = this.adapterResolution().adapterIds;
|
|
355
|
+
const signature = `${status}:${block.blockId}:${block.formBlockId}:${adapter?.adapterId ?? 'none'}:${reason ?? ''}:${adapterIds.join(',')}`;
|
|
356
|
+
if (signature === this.lastAdapterEventSignature) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
this.lastAdapterEventSignature = signature;
|
|
360
|
+
if (status === 'resolved' && adapter) {
|
|
361
|
+
this.operationalEvent.emit({
|
|
362
|
+
eventType: 'data-collection-adapter-resolved',
|
|
363
|
+
timestamp: Date.now(),
|
|
364
|
+
severity: 'info',
|
|
365
|
+
blockId: block.blockId,
|
|
366
|
+
payload: {
|
|
367
|
+
adapterId: adapter.adapterId,
|
|
368
|
+
formBlockId: block.formBlockId,
|
|
369
|
+
},
|
|
370
|
+
});
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (status === 'invalid' && adapter) {
|
|
374
|
+
this.operationalEvent.emit({
|
|
375
|
+
eventType: 'data-collection-adapter-invalid',
|
|
376
|
+
timestamp: Date.now(),
|
|
377
|
+
severity: 'error',
|
|
378
|
+
blockId: block.blockId,
|
|
379
|
+
payload: {
|
|
380
|
+
adapterId: adapter.adapterId,
|
|
381
|
+
formBlockId: block.formBlockId,
|
|
382
|
+
reason: reason ?? 'Adaptador retornou componente incompatível.',
|
|
383
|
+
},
|
|
384
|
+
});
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (status === 'incompatible') {
|
|
388
|
+
this.operationalEvent.emit({
|
|
389
|
+
eventType: 'data-collection-adapter-incompatible',
|
|
390
|
+
timestamp: Date.now(),
|
|
391
|
+
severity: 'warning',
|
|
392
|
+
blockId: block.blockId,
|
|
393
|
+
payload: {
|
|
394
|
+
formBlockId: block.formBlockId,
|
|
395
|
+
adapterIds,
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
this.operationalEvent.emit({
|
|
401
|
+
eventType: 'data-collection-adapter-missing',
|
|
402
|
+
timestamp: Date.now(),
|
|
403
|
+
severity: 'warning',
|
|
404
|
+
blockId: block.blockId,
|
|
405
|
+
payload: {
|
|
406
|
+
formBlockId: block.formBlockId,
|
|
407
|
+
adapterIds,
|
|
408
|
+
},
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialDataCollectionBlockOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
412
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialDataCollectionBlockOutletComponent, isStandalone: true, selector: "praxis-editorial-data-collection-block-outlet", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: true, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null }, solution: { classPropertyName: "solution", publicName: "solution", isSignal: true, isRequired: false, transformFunction: null }, instance: { classPropertyName: "instance", publicName: "instance", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { operationalEvent: "operationalEvent" }, ngImport: i0, template: `
|
|
413
|
+
<section class="block-card data-block">
|
|
414
|
+
@if (block().title) {
|
|
415
|
+
<h3>{{ block().title }}</h3>
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@if (block().description) {
|
|
419
|
+
<p class="description">{{ block().description }}</p>
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
@if (adapterComponent(); as adapterComponent) {
|
|
423
|
+
<ng-container
|
|
424
|
+
*ngComponentOutlet="adapterComponent; inputs: adapterInputs()"
|
|
425
|
+
/>
|
|
426
|
+
} @else if (loadingState(); as loadingState) {
|
|
427
|
+
<div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
|
|
428
|
+
<strong>Preparando coleta</strong>
|
|
429
|
+
<p>{{ loadingState.message }}</p>
|
|
430
|
+
</div>
|
|
431
|
+
} @else if (errorState(); as errorState) {
|
|
432
|
+
<div class="feedback error" role="alert" aria-live="assertive" aria-atomic="true">
|
|
433
|
+
<strong>{{ errorState.title }}</strong>
|
|
434
|
+
<p>{{ errorState.message }}</p>
|
|
435
|
+
@if (errorState.details) {
|
|
436
|
+
<p class="details">{{ errorState.details }}</p>
|
|
437
|
+
}
|
|
438
|
+
</div>
|
|
439
|
+
} @else {
|
|
440
|
+
<div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
|
|
441
|
+
<strong>Coleta nao disponivel</strong>
|
|
442
|
+
<p>{{ fallbackMessage() }}</p>
|
|
443
|
+
</div>
|
|
444
|
+
}
|
|
445
|
+
</section>
|
|
446
|
+
`, isInline: true, styles: [":host{display:block}.block-card{display:grid;gap:12px;padding:18px;border-radius:18px;background:var(--md-sys-color-surface-container-low, #f7f2fa);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent)}h3,p{margin:0}.description,.feedback{color:var(--md-sys-color-on-surface-variant, #49454f)}.feedback{display:grid;gap:6px;padding:12px 14px;border-radius:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent);background:var(--md-sys-color-surface, #fff)}.feedback strong{color:var(--md-sys-color-on-surface, #1b1b1f)}.error{border-color:color-mix(in srgb,var(--md-sys-color-error, #b3261e) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container, #f9dedc) 35%,var(--md-sys-color-surface, #fff))}.details{font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
447
|
+
}
|
|
448
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialDataCollectionBlockOutletComponent, decorators: [{
|
|
449
|
+
type: Component,
|
|
450
|
+
args: [{ selector: 'praxis-editorial-data-collection-block-outlet', standalone: true, imports: [CommonModule, NgComponentOutlet], template: `
|
|
451
|
+
<section class="block-card data-block">
|
|
452
|
+
@if (block().title) {
|
|
453
|
+
<h3>{{ block().title }}</h3>
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
@if (block().description) {
|
|
457
|
+
<p class="description">{{ block().description }}</p>
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
@if (adapterComponent(); as adapterComponent) {
|
|
461
|
+
<ng-container
|
|
462
|
+
*ngComponentOutlet="adapterComponent; inputs: adapterInputs()"
|
|
463
|
+
/>
|
|
464
|
+
} @else if (loadingState(); as loadingState) {
|
|
465
|
+
<div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
|
|
466
|
+
<strong>Preparando coleta</strong>
|
|
467
|
+
<p>{{ loadingState.message }}</p>
|
|
468
|
+
</div>
|
|
469
|
+
} @else if (errorState(); as errorState) {
|
|
470
|
+
<div class="feedback error" role="alert" aria-live="assertive" aria-atomic="true">
|
|
471
|
+
<strong>{{ errorState.title }}</strong>
|
|
472
|
+
<p>{{ errorState.message }}</p>
|
|
473
|
+
@if (errorState.details) {
|
|
474
|
+
<p class="details">{{ errorState.details }}</p>
|
|
475
|
+
}
|
|
476
|
+
</div>
|
|
477
|
+
} @else {
|
|
478
|
+
<div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
|
|
479
|
+
<strong>Coleta nao disponivel</strong>
|
|
480
|
+
<p>{{ fallbackMessage() }}</p>
|
|
481
|
+
</div>
|
|
482
|
+
}
|
|
483
|
+
</section>
|
|
484
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.block-card{display:grid;gap:12px;padding:18px;border-radius:18px;background:var(--md-sys-color-surface-container-low, #f7f2fa);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent)}h3,p{margin:0}.description,.feedback{color:var(--md-sys-color-on-surface-variant, #49454f)}.feedback{display:grid;gap:6px;padding:12px 14px;border-radius:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent);background:var(--md-sys-color-surface, #fff)}.feedback strong{color:var(--md-sys-color-on-surface, #1b1b1f)}.error{border-color:color-mix(in srgb,var(--md-sys-color-error, #b3261e) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container, #f9dedc) 35%,var(--md-sys-color-surface, #fff))}.details{font-size:.9rem}\n"] }]
|
|
485
|
+
}], ctorParameters: () => [], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: true }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }], solution: [{ type: i0.Input, args: [{ isSignal: true, alias: "solution", required: false }] }], instance: [{ type: i0.Input, args: [{ isSignal: true, alias: "instance", required: false }] }], operationalEvent: [{ type: i0.Output, args: ["operationalEvent"] }] } });
|
|
486
|
+
function isResolvedDataCollectionBlock(block) {
|
|
487
|
+
return 'dataCollectionState' in block;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
class EditorialBlockRendererComponent {
|
|
491
|
+
block = input.required(...(ngDevMode ? [{ debugName: "block" }] : []));
|
|
492
|
+
runtimeContext = input(null, ...(ngDevMode ? [{ debugName: "runtimeContext" }] : []));
|
|
493
|
+
solution = input(null, ...(ngDevMode ? [{ debugName: "solution" }] : []));
|
|
494
|
+
instance = input(null, ...(ngDevMode ? [{ debugName: "instance" }] : []));
|
|
495
|
+
operationalEvent = output();
|
|
496
|
+
hero = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "hero" }] : []));
|
|
497
|
+
richText = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "richText" }] : []));
|
|
498
|
+
policyList = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "policyList" }] : []));
|
|
499
|
+
timeline = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "timeline" }] : []));
|
|
500
|
+
review = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "review" }] : []));
|
|
501
|
+
contextSummary = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "contextSummary" }] : []));
|
|
502
|
+
infoCards = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "infoCards" }] : []));
|
|
503
|
+
faq = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "faq" }] : []));
|
|
504
|
+
dataCollection = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "dataCollection" }] : []));
|
|
505
|
+
customWidget = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "customWidget" }] : []));
|
|
506
|
+
resolveValue(valuePath, fallback = '-') {
|
|
507
|
+
if (!valuePath) {
|
|
508
|
+
return fallback;
|
|
509
|
+
}
|
|
510
|
+
const value = getValueAtPath(this.runtimeContext() ?? {}, valuePath);
|
|
511
|
+
return value == null || value === '' ? fallback : String(value);
|
|
512
|
+
}
|
|
513
|
+
resolveContextPath(valuePath) {
|
|
514
|
+
const contextPath = this.contextSummary().contextPath;
|
|
515
|
+
if (!contextPath) {
|
|
516
|
+
return valuePath;
|
|
517
|
+
}
|
|
518
|
+
return valuePath ? `${contextPath}.${valuePath}` : contextPath;
|
|
519
|
+
}
|
|
520
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialBlockRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
521
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialBlockRendererComponent, isStandalone: true, selector: "praxis-editorial-block-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: true, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null }, solution: { classPropertyName: "solution", publicName: "solution", isSignal: true, isRequired: false, transformFunction: null }, instance: { classPropertyName: "instance", publicName: "instance", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { operationalEvent: "operationalEvent" }, ngImport: i0, template: `
|
|
522
|
+
@switch (block().kind) {
|
|
523
|
+
@case ('hero') {
|
|
524
|
+
<section class="block-card hero-block">
|
|
525
|
+
@if (hero().subtitle) {
|
|
526
|
+
<p class="eyebrow">{{ hero().subtitle }}</p>
|
|
527
|
+
}
|
|
528
|
+
<h3>
|
|
529
|
+
{{ hero().title }}
|
|
530
|
+
@if (hero().titleAccent) {
|
|
531
|
+
<span>{{ hero().titleAccent }}</span>
|
|
532
|
+
}
|
|
533
|
+
</h3>
|
|
534
|
+
@if (hero().description) {
|
|
535
|
+
<p class="description">{{ hero().description }}</p>
|
|
536
|
+
}
|
|
537
|
+
</section>
|
|
538
|
+
}
|
|
539
|
+
@case ('richText') {
|
|
540
|
+
<section class="block-card">
|
|
541
|
+
@if (richText().title) {
|
|
542
|
+
<h3>{{ richText().title }}</h3>
|
|
543
|
+
}
|
|
544
|
+
<div class="content">{{ richText().content }}</div>
|
|
545
|
+
</section>
|
|
546
|
+
}
|
|
547
|
+
@case ('legalNotice') {
|
|
548
|
+
<section class="block-card notice-block">
|
|
549
|
+
@if (richText().title) {
|
|
550
|
+
<h3>{{ richText().title }}</h3>
|
|
551
|
+
}
|
|
552
|
+
<div class="content">{{ richText().content }}</div>
|
|
553
|
+
</section>
|
|
554
|
+
}
|
|
555
|
+
@case ('policyList') {
|
|
556
|
+
<section class="block-card">
|
|
557
|
+
@if (policyList().title) {
|
|
558
|
+
<h3>{{ policyList().title }}</h3>
|
|
559
|
+
}
|
|
560
|
+
<ul class="list-reset stack-sm">
|
|
561
|
+
@for (item of policyList().items; track item.id) {
|
|
562
|
+
<li class="policy-item">
|
|
563
|
+
<strong>{{ item.title }}</strong>
|
|
564
|
+
@if (item.summary) {
|
|
565
|
+
<p>{{ item.summary }}</p>
|
|
566
|
+
}
|
|
567
|
+
</li>
|
|
568
|
+
}
|
|
569
|
+
</ul>
|
|
570
|
+
</section>
|
|
571
|
+
}
|
|
572
|
+
@case ('timelineSteps') {
|
|
573
|
+
<section class="block-card">
|
|
574
|
+
@if (timeline().title) {
|
|
575
|
+
<h3>{{ timeline().title }}</h3>
|
|
576
|
+
}
|
|
577
|
+
<ol class="timeline">
|
|
578
|
+
@for (item of timeline().steps; track item.id) {
|
|
579
|
+
<li class="timeline-item">
|
|
580
|
+
<strong>{{ item.label }}</strong>
|
|
581
|
+
@if (item.description) {
|
|
582
|
+
<span>{{ item.description }}</span>
|
|
583
|
+
}
|
|
584
|
+
</li>
|
|
585
|
+
}
|
|
586
|
+
</ol>
|
|
587
|
+
</section>
|
|
588
|
+
}
|
|
589
|
+
@case ('reviewSummary') {
|
|
590
|
+
<section class="block-card">
|
|
591
|
+
@if (review().title) {
|
|
592
|
+
<h3>{{ review().title }}</h3>
|
|
593
|
+
}
|
|
594
|
+
<dl class="review-grid">
|
|
595
|
+
@for (field of review().fields; track field.key) {
|
|
596
|
+
<div>
|
|
597
|
+
<dt>{{ field.label }}</dt>
|
|
598
|
+
<dd>{{ resolveValue(field.valuePath, field.fallback) }}</dd>
|
|
599
|
+
</div>
|
|
600
|
+
}
|
|
601
|
+
</dl>
|
|
602
|
+
</section>
|
|
603
|
+
}
|
|
604
|
+
@case ('contextSummary') {
|
|
605
|
+
<section class="block-card">
|
|
606
|
+
@if (contextSummary().title) {
|
|
607
|
+
<h3>{{ contextSummary().title }}</h3>
|
|
608
|
+
}
|
|
609
|
+
<dl class="review-grid">
|
|
610
|
+
@for (field of contextSummary().fields; track field.key) {
|
|
611
|
+
<div>
|
|
612
|
+
<dt>{{ field.label }}</dt>
|
|
613
|
+
<dd>{{ resolveValue(resolveContextPath(field.valuePath), field.fallback) }}</dd>
|
|
614
|
+
</div>
|
|
615
|
+
}
|
|
616
|
+
</dl>
|
|
617
|
+
</section>
|
|
618
|
+
}
|
|
619
|
+
@case ('infoCards') {
|
|
620
|
+
<section class="block-card">
|
|
621
|
+
<div class="cards-grid">
|
|
622
|
+
@for (item of infoCards().items; track item.id) {
|
|
623
|
+
<article class="info-card">
|
|
624
|
+
<strong>{{ item.title }}</strong>
|
|
625
|
+
@if (item.description) {
|
|
626
|
+
<p>{{ item.description }}</p>
|
|
627
|
+
}
|
|
628
|
+
</article>
|
|
629
|
+
}
|
|
630
|
+
</div>
|
|
631
|
+
</section>
|
|
632
|
+
}
|
|
633
|
+
@case ('faqAccordion') {
|
|
634
|
+
<section class="block-card stack-sm">
|
|
635
|
+
@for (item of faq().items; track item.id) {
|
|
636
|
+
<details class="faq-item">
|
|
637
|
+
<summary>{{ item.question }}</summary>
|
|
638
|
+
<p>{{ item.answer }}</p>
|
|
639
|
+
</details>
|
|
640
|
+
}
|
|
641
|
+
</section>
|
|
642
|
+
}
|
|
643
|
+
@case ('dataCollection') {
|
|
644
|
+
<praxis-editorial-data-collection-block-outlet
|
|
645
|
+
[block]="dataCollection()"
|
|
646
|
+
[runtimeContext]="runtimeContext()"
|
|
647
|
+
[solution]="solution()"
|
|
648
|
+
[instance]="instance()"
|
|
649
|
+
(operationalEvent)="operationalEvent.emit($event)"
|
|
650
|
+
/>
|
|
651
|
+
}
|
|
652
|
+
@case ('customWidget') {
|
|
653
|
+
<ng-container
|
|
654
|
+
[dynamicWidgetLoader]="customWidget().widget"
|
|
655
|
+
[context]="runtimeContext()"
|
|
656
|
+
[strictValidation]="true"
|
|
657
|
+
[autoWireOutputs]="true"
|
|
658
|
+
/>
|
|
659
|
+
}
|
|
660
|
+
@case ('footerLinks') {
|
|
661
|
+
<ng-container
|
|
662
|
+
[dynamicWidgetLoader]="customWidget().widget"
|
|
663
|
+
[context]="runtimeContext()"
|
|
664
|
+
[strictValidation]="true"
|
|
665
|
+
[autoWireOutputs]="true"
|
|
666
|
+
/>
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
`, isInline: true, styles: [":host{display:block}.block-card{display:grid;gap:12px;padding:18px;border-radius:18px;background:var(--md-sys-color-surface-container-low, #f7f2fa);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent)}.eyebrow{margin:0;font-size:.8rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-primary, #6750a4)}h3,p,ul,ol,dl{margin:0}.description,.content,.timeline-item span,.policy-item p,.info-card p,.faq-item p{color:var(--md-sys-color-on-surface-variant, #49454f)}.hero-block h3 span{color:var(--md-sys-color-primary, #6750a4)}.review-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.review-grid dt{margin-bottom:4px;font-size:.78rem;color:var(--md-sys-color-on-surface-variant, #49454f)}.review-grid dd{margin:0;font-weight:600}.list-reset{list-style:none;padding:0;margin:0}.stack-sm{display:grid;gap:10px}.timeline{display:grid;gap:12px;padding-left:18px;margin:0}.timeline-item{display:grid;gap:4px}.policy-item,.faq-item,.info-card{padding:12px;border-radius:14px;background:var(--md-sys-color-surface, #fff)}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}.notice-block{border-left:4px solid var(--md-sys-color-primary, #6750a4)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: EditorialDataCollectionBlockOutletComponent, selector: "praxis-editorial-data-collection-block-outlet", inputs: ["block", "runtimeContext", "solution", "instance"], outputs: ["operationalEvent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
670
|
+
}
|
|
671
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialBlockRendererComponent, decorators: [{
|
|
672
|
+
type: Component,
|
|
673
|
+
args: [{ selector: 'praxis-editorial-block-renderer', standalone: true, imports: [
|
|
674
|
+
CommonModule,
|
|
675
|
+
DynamicWidgetLoaderDirective,
|
|
676
|
+
EditorialDataCollectionBlockOutletComponent,
|
|
677
|
+
], template: `
|
|
678
|
+
@switch (block().kind) {
|
|
679
|
+
@case ('hero') {
|
|
680
|
+
<section class="block-card hero-block">
|
|
681
|
+
@if (hero().subtitle) {
|
|
682
|
+
<p class="eyebrow">{{ hero().subtitle }}</p>
|
|
683
|
+
}
|
|
684
|
+
<h3>
|
|
685
|
+
{{ hero().title }}
|
|
686
|
+
@if (hero().titleAccent) {
|
|
687
|
+
<span>{{ hero().titleAccent }}</span>
|
|
688
|
+
}
|
|
689
|
+
</h3>
|
|
690
|
+
@if (hero().description) {
|
|
691
|
+
<p class="description">{{ hero().description }}</p>
|
|
692
|
+
}
|
|
693
|
+
</section>
|
|
694
|
+
}
|
|
695
|
+
@case ('richText') {
|
|
696
|
+
<section class="block-card">
|
|
697
|
+
@if (richText().title) {
|
|
698
|
+
<h3>{{ richText().title }}</h3>
|
|
699
|
+
}
|
|
700
|
+
<div class="content">{{ richText().content }}</div>
|
|
701
|
+
</section>
|
|
702
|
+
}
|
|
703
|
+
@case ('legalNotice') {
|
|
704
|
+
<section class="block-card notice-block">
|
|
705
|
+
@if (richText().title) {
|
|
706
|
+
<h3>{{ richText().title }}</h3>
|
|
707
|
+
}
|
|
708
|
+
<div class="content">{{ richText().content }}</div>
|
|
709
|
+
</section>
|
|
710
|
+
}
|
|
711
|
+
@case ('policyList') {
|
|
712
|
+
<section class="block-card">
|
|
713
|
+
@if (policyList().title) {
|
|
714
|
+
<h3>{{ policyList().title }}</h3>
|
|
715
|
+
}
|
|
716
|
+
<ul class="list-reset stack-sm">
|
|
717
|
+
@for (item of policyList().items; track item.id) {
|
|
718
|
+
<li class="policy-item">
|
|
719
|
+
<strong>{{ item.title }}</strong>
|
|
720
|
+
@if (item.summary) {
|
|
721
|
+
<p>{{ item.summary }}</p>
|
|
722
|
+
}
|
|
723
|
+
</li>
|
|
724
|
+
}
|
|
725
|
+
</ul>
|
|
726
|
+
</section>
|
|
727
|
+
}
|
|
728
|
+
@case ('timelineSteps') {
|
|
729
|
+
<section class="block-card">
|
|
730
|
+
@if (timeline().title) {
|
|
731
|
+
<h3>{{ timeline().title }}</h3>
|
|
732
|
+
}
|
|
733
|
+
<ol class="timeline">
|
|
734
|
+
@for (item of timeline().steps; track item.id) {
|
|
735
|
+
<li class="timeline-item">
|
|
736
|
+
<strong>{{ item.label }}</strong>
|
|
737
|
+
@if (item.description) {
|
|
738
|
+
<span>{{ item.description }}</span>
|
|
739
|
+
}
|
|
740
|
+
</li>
|
|
741
|
+
}
|
|
742
|
+
</ol>
|
|
743
|
+
</section>
|
|
744
|
+
}
|
|
745
|
+
@case ('reviewSummary') {
|
|
746
|
+
<section class="block-card">
|
|
747
|
+
@if (review().title) {
|
|
748
|
+
<h3>{{ review().title }}</h3>
|
|
749
|
+
}
|
|
750
|
+
<dl class="review-grid">
|
|
751
|
+
@for (field of review().fields; track field.key) {
|
|
752
|
+
<div>
|
|
753
|
+
<dt>{{ field.label }}</dt>
|
|
754
|
+
<dd>{{ resolveValue(field.valuePath, field.fallback) }}</dd>
|
|
755
|
+
</div>
|
|
756
|
+
}
|
|
757
|
+
</dl>
|
|
758
|
+
</section>
|
|
759
|
+
}
|
|
760
|
+
@case ('contextSummary') {
|
|
761
|
+
<section class="block-card">
|
|
762
|
+
@if (contextSummary().title) {
|
|
763
|
+
<h3>{{ contextSummary().title }}</h3>
|
|
764
|
+
}
|
|
765
|
+
<dl class="review-grid">
|
|
766
|
+
@for (field of contextSummary().fields; track field.key) {
|
|
767
|
+
<div>
|
|
768
|
+
<dt>{{ field.label }}</dt>
|
|
769
|
+
<dd>{{ resolveValue(resolveContextPath(field.valuePath), field.fallback) }}</dd>
|
|
770
|
+
</div>
|
|
771
|
+
}
|
|
772
|
+
</dl>
|
|
773
|
+
</section>
|
|
774
|
+
}
|
|
775
|
+
@case ('infoCards') {
|
|
776
|
+
<section class="block-card">
|
|
777
|
+
<div class="cards-grid">
|
|
778
|
+
@for (item of infoCards().items; track item.id) {
|
|
779
|
+
<article class="info-card">
|
|
780
|
+
<strong>{{ item.title }}</strong>
|
|
781
|
+
@if (item.description) {
|
|
782
|
+
<p>{{ item.description }}</p>
|
|
783
|
+
}
|
|
784
|
+
</article>
|
|
785
|
+
}
|
|
786
|
+
</div>
|
|
787
|
+
</section>
|
|
788
|
+
}
|
|
789
|
+
@case ('faqAccordion') {
|
|
790
|
+
<section class="block-card stack-sm">
|
|
791
|
+
@for (item of faq().items; track item.id) {
|
|
792
|
+
<details class="faq-item">
|
|
793
|
+
<summary>{{ item.question }}</summary>
|
|
794
|
+
<p>{{ item.answer }}</p>
|
|
795
|
+
</details>
|
|
796
|
+
}
|
|
797
|
+
</section>
|
|
798
|
+
}
|
|
799
|
+
@case ('dataCollection') {
|
|
800
|
+
<praxis-editorial-data-collection-block-outlet
|
|
801
|
+
[block]="dataCollection()"
|
|
802
|
+
[runtimeContext]="runtimeContext()"
|
|
803
|
+
[solution]="solution()"
|
|
804
|
+
[instance]="instance()"
|
|
805
|
+
(operationalEvent)="operationalEvent.emit($event)"
|
|
806
|
+
/>
|
|
807
|
+
}
|
|
808
|
+
@case ('customWidget') {
|
|
809
|
+
<ng-container
|
|
810
|
+
[dynamicWidgetLoader]="customWidget().widget"
|
|
811
|
+
[context]="runtimeContext()"
|
|
812
|
+
[strictValidation]="true"
|
|
813
|
+
[autoWireOutputs]="true"
|
|
814
|
+
/>
|
|
815
|
+
}
|
|
816
|
+
@case ('footerLinks') {
|
|
817
|
+
<ng-container
|
|
818
|
+
[dynamicWidgetLoader]="customWidget().widget"
|
|
819
|
+
[context]="runtimeContext()"
|
|
820
|
+
[strictValidation]="true"
|
|
821
|
+
[autoWireOutputs]="true"
|
|
822
|
+
/>
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.block-card{display:grid;gap:12px;padding:18px;border-radius:18px;background:var(--md-sys-color-surface-container-low, #f7f2fa);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent)}.eyebrow{margin:0;font-size:.8rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-primary, #6750a4)}h3,p,ul,ol,dl{margin:0}.description,.content,.timeline-item span,.policy-item p,.info-card p,.faq-item p{color:var(--md-sys-color-on-surface-variant, #49454f)}.hero-block h3 span{color:var(--md-sys-color-primary, #6750a4)}.review-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.review-grid dt{margin-bottom:4px;font-size:.78rem;color:var(--md-sys-color-on-surface-variant, #49454f)}.review-grid dd{margin:0;font-weight:600}.list-reset{list-style:none;padding:0;margin:0}.stack-sm{display:grid;gap:10px}.timeline{display:grid;gap:12px;padding-left:18px;margin:0}.timeline-item{display:grid;gap:4px}.policy-item,.faq-item,.info-card{padding:12px;border-radius:14px;background:var(--md-sys-color-surface, #fff)}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}.notice-block{border-left:4px solid var(--md-sys-color-primary, #6750a4)}\n"] }]
|
|
826
|
+
}], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: true }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }], solution: [{ type: i0.Input, args: [{ isSignal: true, alias: "solution", required: false }] }], instance: [{ type: i0.Input, args: [{ isSignal: true, alias: "instance", required: false }] }], operationalEvent: [{ type: i0.Output, args: ["operationalEvent"] }] } });
|
|
827
|
+
|
|
828
|
+
function resolveEditorialRuntimeSnapshot(input) {
|
|
829
|
+
const diagnostics = [];
|
|
830
|
+
const solution = input.solution;
|
|
831
|
+
const instance = input.instance;
|
|
832
|
+
const context = mergeContext(instance?.context ?? {}, instance?.overrides?.contextPatch ?? {}, input.runtimeContext ?? {});
|
|
833
|
+
const effectiveThemePreset = resolveEffectiveThemePreset(solution, instance, diagnostics);
|
|
834
|
+
const effectiveCompliancePresets = resolveEffectiveCompliancePresets(solution, instance, diagnostics);
|
|
835
|
+
validateContextContract(solution?.contextContract ?? [], context, diagnostics);
|
|
836
|
+
validateComplianceContext(effectiveCompliancePresets, context, diagnostics);
|
|
837
|
+
const journeys = mergeJourneys(solution, instance, diagnostics);
|
|
838
|
+
applyCompliancePresetBlocks(journeys, effectiveCompliancePresets, solution, instance);
|
|
839
|
+
applyJourneyOverrides(journeys, instance?.overrides?.journeyOverrides ?? [], diagnostics, instance);
|
|
840
|
+
diagnoseResolvedBlocks(journeys, diagnostics, instance);
|
|
841
|
+
annotateDiagnostics(journeys, diagnostics);
|
|
842
|
+
if (!solution && !instance) {
|
|
843
|
+
diagnostics.push({
|
|
844
|
+
code: 'solution-missing',
|
|
845
|
+
severity: 'warning',
|
|
846
|
+
message: 'Nenhuma solution ou instance editorial foi fornecida ao runtime.',
|
|
847
|
+
scopeKind: 'global',
|
|
848
|
+
path: 'runtime',
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
return {
|
|
852
|
+
solutionId: solution?.solutionId ?? instance?.template.templateId ?? null,
|
|
853
|
+
instanceId: instance?.instanceId ?? null,
|
|
854
|
+
title: solution?.title ?? instance?.template.title ?? null,
|
|
855
|
+
description: solution?.description ?? null,
|
|
856
|
+
problemType: solution?.problemType ?? instance?.template.problemType ?? null,
|
|
857
|
+
context,
|
|
858
|
+
effectiveThemePreset,
|
|
859
|
+
effectiveCompliancePresets,
|
|
860
|
+
journeys,
|
|
861
|
+
diagnostics: {
|
|
862
|
+
items: diagnostics,
|
|
863
|
+
hasErrors: diagnostics.some((item) => item.severity === 'error'),
|
|
864
|
+
hasWarnings: diagnostics.some((item) => item.severity === 'warning'),
|
|
865
|
+
},
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
function resolveEffectiveThemePreset(solution, instance, diagnostics) {
|
|
869
|
+
if (instance?.selectedThemePreset) {
|
|
870
|
+
return instance.selectedThemePreset;
|
|
871
|
+
}
|
|
872
|
+
const requestedThemeId = instance?.overrides?.themePresetId;
|
|
873
|
+
if (!requestedThemeId) {
|
|
874
|
+
return solution?.themePresets?.[0] ?? null;
|
|
875
|
+
}
|
|
876
|
+
const resolved = solution?.themePresets?.find((preset) => preset.themeId === requestedThemeId) ?? null;
|
|
877
|
+
if (!resolved) {
|
|
878
|
+
diagnostics.push({
|
|
879
|
+
code: 'theme-preset-not-found',
|
|
880
|
+
severity: 'warning',
|
|
881
|
+
message: `Theme preset "${requestedThemeId}" nao foi resolvido no catalogo da solution.`,
|
|
882
|
+
scopeKind: 'global',
|
|
883
|
+
path: `themePreset:${requestedThemeId}`,
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
return resolved;
|
|
887
|
+
}
|
|
888
|
+
function resolveEffectiveCompliancePresets(solution, instance, diagnostics) {
|
|
889
|
+
if (instance?.selectedCompliancePresets?.length) {
|
|
890
|
+
return instance.selectedCompliancePresets;
|
|
891
|
+
}
|
|
892
|
+
const requestedPresetIds = instance?.overrides?.compliancePresetIds;
|
|
893
|
+
if (!requestedPresetIds?.length) {
|
|
894
|
+
return solution?.compliancePresets ?? [];
|
|
895
|
+
}
|
|
896
|
+
const resolved = [];
|
|
897
|
+
for (const presetId of requestedPresetIds) {
|
|
898
|
+
const preset = solution?.compliancePresets?.find((item) => item.presetId === presetId);
|
|
899
|
+
if (!preset) {
|
|
900
|
+
diagnostics.push({
|
|
901
|
+
code: 'compliance-preset-not-found',
|
|
902
|
+
severity: 'warning',
|
|
903
|
+
message: `Compliance preset "${presetId}" nao foi resolvido no catalogo da solution.`,
|
|
904
|
+
scopeKind: 'global',
|
|
905
|
+
path: `compliancePreset:${presetId}`,
|
|
906
|
+
});
|
|
907
|
+
continue;
|
|
908
|
+
}
|
|
909
|
+
resolved.push(preset);
|
|
910
|
+
}
|
|
911
|
+
return resolved;
|
|
912
|
+
}
|
|
913
|
+
function validateContextContract(contract, context, diagnostics) {
|
|
914
|
+
for (const field of contract) {
|
|
915
|
+
if (!field.required) {
|
|
916
|
+
continue;
|
|
917
|
+
}
|
|
918
|
+
const value = getValueAtPath(context, field.key);
|
|
919
|
+
if (value != null && value !== '') {
|
|
920
|
+
continue;
|
|
921
|
+
}
|
|
922
|
+
diagnostics.push({
|
|
923
|
+
code: 'context-required-missing',
|
|
924
|
+
severity: 'error',
|
|
925
|
+
message: `Contexto obrigatorio ausente: "${field.key}".`,
|
|
926
|
+
scopeKind: 'global',
|
|
927
|
+
path: field.key,
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
function validateComplianceContext(presets, context, diagnostics) {
|
|
932
|
+
for (const preset of presets) {
|
|
933
|
+
for (const key of preset.requiredContextKeys ?? []) {
|
|
934
|
+
const value = getValueAtPath(context, key);
|
|
935
|
+
if (value != null && value !== '') {
|
|
936
|
+
continue;
|
|
937
|
+
}
|
|
938
|
+
diagnostics.push({
|
|
939
|
+
code: 'compliance-context-required-missing',
|
|
940
|
+
severity: 'error',
|
|
941
|
+
message: `Compliance preset "${preset.presetId}" requer o contexto "${key}".`,
|
|
942
|
+
scopeKind: 'global',
|
|
943
|
+
path: `compliancePreset:${preset.presetId}:${key}`,
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
function mergeJourneys(solution, instance, diagnostics) {
|
|
949
|
+
const resolvedJourneys = new Map();
|
|
950
|
+
const order = [];
|
|
951
|
+
for (const journey of solution?.journeys ?? []) {
|
|
952
|
+
resolvedJourneys.set(journey.journeyId, createResolvedJourney(journey, createSourceRef('solution', {
|
|
953
|
+
solutionId: solution?.solutionId ?? undefined,
|
|
954
|
+
journeyId: journey.journeyId,
|
|
955
|
+
}), instance));
|
|
956
|
+
order.push(journey.journeyId);
|
|
957
|
+
}
|
|
958
|
+
for (const journey of instance?.journeys ?? []) {
|
|
959
|
+
const existing = resolvedJourneys.get(journey.journeyId);
|
|
960
|
+
if (!existing) {
|
|
961
|
+
resolvedJourneys.set(journey.journeyId, createResolvedJourney(journey, createSourceRef('instanceJourney', {
|
|
962
|
+
instanceId: instance?.instanceId ?? undefined,
|
|
963
|
+
journeyId: journey.journeyId,
|
|
964
|
+
}), instance));
|
|
965
|
+
order.push(journey.journeyId);
|
|
966
|
+
continue;
|
|
967
|
+
}
|
|
968
|
+
resolvedJourneys.set(journey.journeyId, mergeJourney(existing, journey, createSourceRef('instanceJourney', {
|
|
969
|
+
instanceId: instance?.instanceId ?? undefined,
|
|
970
|
+
journeyId: journey.journeyId,
|
|
971
|
+
}), diagnostics, instance));
|
|
972
|
+
}
|
|
973
|
+
return order
|
|
974
|
+
.map((journeyId) => resolvedJourneys.get(journeyId))
|
|
975
|
+
.filter((journey) => Boolean(journey));
|
|
976
|
+
}
|
|
977
|
+
function createResolvedJourney(journey, source, instance) {
|
|
978
|
+
return {
|
|
979
|
+
journeyId: journey.journeyId,
|
|
980
|
+
label: journey.label,
|
|
981
|
+
description: journey.description,
|
|
982
|
+
steps: journey.steps.map((step) => createResolvedStep(step, {
|
|
983
|
+
...source,
|
|
984
|
+
stepId: step.stepId,
|
|
985
|
+
}, instance)),
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
function createResolvedStep(step, source, instance) {
|
|
989
|
+
return {
|
|
990
|
+
stepId: step.stepId,
|
|
991
|
+
label: step.label,
|
|
992
|
+
description: step.description,
|
|
993
|
+
blocks: step.blocks.map((block) => createResolvedBlock(block, {
|
|
994
|
+
...source,
|
|
995
|
+
blockId: block.blockId,
|
|
996
|
+
}, instance)),
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
function createResolvedBlock(block, source, instance, previousTrail = [], operation = 'seed') {
|
|
1000
|
+
const trail = dedupeTrail([
|
|
1001
|
+
...previousTrail,
|
|
1002
|
+
{ operation, source },
|
|
1003
|
+
]);
|
|
1004
|
+
if (block.kind === 'dataCollection') {
|
|
1005
|
+
return {
|
|
1006
|
+
...block,
|
|
1007
|
+
provenance: {
|
|
1008
|
+
primarySource: source,
|
|
1009
|
+
trail,
|
|
1010
|
+
},
|
|
1011
|
+
dataCollectionState: buildDataCollectionState(block, instance),
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
return {
|
|
1015
|
+
...block,
|
|
1016
|
+
provenance: {
|
|
1017
|
+
primarySource: source,
|
|
1018
|
+
trail,
|
|
1019
|
+
},
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
function mergeJourney(base, override, source, diagnostics, instance) {
|
|
1023
|
+
const steps = new Map(base.steps.map((step) => [step.stepId, step]));
|
|
1024
|
+
const order = base.steps.map((step) => step.stepId);
|
|
1025
|
+
for (const step of override.steps) {
|
|
1026
|
+
const existing = steps.get(step.stepId);
|
|
1027
|
+
if (!existing) {
|
|
1028
|
+
steps.set(step.stepId, createResolvedStep(step, {
|
|
1029
|
+
...source,
|
|
1030
|
+
stepId: step.stepId,
|
|
1031
|
+
}, instance));
|
|
1032
|
+
order.push(step.stepId);
|
|
1033
|
+
continue;
|
|
1034
|
+
}
|
|
1035
|
+
const mergedBlocks = [...existing.blocks];
|
|
1036
|
+
for (const block of step.blocks) {
|
|
1037
|
+
const hasConflict = mergedBlocks.some((candidate) => candidate.blockId === block.blockId);
|
|
1038
|
+
if (hasConflict) {
|
|
1039
|
+
diagnostics.push({
|
|
1040
|
+
code: 'instance-journey-block-conflict',
|
|
1041
|
+
severity: 'warning',
|
|
1042
|
+
message: `Journey da instance tentou redefinir o bloco "${block.blockId}" em "${override.journeyId}/${step.stepId}" sem usar journeyOverrides.`,
|
|
1043
|
+
scopeKind: 'block',
|
|
1044
|
+
path: `instanceJourney:${override.journeyId}:${step.stepId}:${block.blockId}`,
|
|
1045
|
+
journeyId: override.journeyId,
|
|
1046
|
+
stepId: step.stepId,
|
|
1047
|
+
blockId: block.blockId,
|
|
1048
|
+
});
|
|
1049
|
+
continue;
|
|
1050
|
+
}
|
|
1051
|
+
mergedBlocks.push(createResolvedBlock(block, {
|
|
1052
|
+
...source,
|
|
1053
|
+
stepId: step.stepId,
|
|
1054
|
+
blockId: block.blockId,
|
|
1055
|
+
}, instance, [], 'instance-journey-append'));
|
|
1056
|
+
}
|
|
1057
|
+
steps.set(step.stepId, {
|
|
1058
|
+
stepId: step.stepId,
|
|
1059
|
+
label: step.label || existing.label,
|
|
1060
|
+
description: step.description ?? existing.description,
|
|
1061
|
+
blocks: mergedBlocks,
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
return {
|
|
1065
|
+
journeyId: override.journeyId,
|
|
1066
|
+
label: override.label || base.label,
|
|
1067
|
+
description: override.description ?? base.description,
|
|
1068
|
+
steps: order
|
|
1069
|
+
.map((stepId) => steps.get(stepId))
|
|
1070
|
+
.filter((step) => Boolean(step)),
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
function applyCompliancePresetBlocks(journeys, presets, solution, instance) {
|
|
1074
|
+
for (const journey of journeys) {
|
|
1075
|
+
const targetStep = journey.steps[journey.steps.length - 1];
|
|
1076
|
+
if (!targetStep) {
|
|
1077
|
+
continue;
|
|
1078
|
+
}
|
|
1079
|
+
for (const preset of presets) {
|
|
1080
|
+
for (const block of preset.blocks ?? []) {
|
|
1081
|
+
targetStep.blocks.push(createResolvedBlock(block, createSourceRef('compliancePreset', {
|
|
1082
|
+
solutionId: solution?.solutionId ?? undefined,
|
|
1083
|
+
presetId: preset.presetId,
|
|
1084
|
+
journeyId: journey.journeyId,
|
|
1085
|
+
stepId: targetStep.stepId,
|
|
1086
|
+
blockId: block.blockId,
|
|
1087
|
+
}), instance, [], 'compliance-append'));
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
function applyJourneyOverrides(journeys, overrides, diagnostics, instance) {
|
|
1093
|
+
for (const journeyOverride of overrides) {
|
|
1094
|
+
const journey = journeys.find((candidate) => candidate.journeyId === journeyOverride.journeyId);
|
|
1095
|
+
if (!journey) {
|
|
1096
|
+
diagnostics.push({
|
|
1097
|
+
code: 'journey-override-target-missing',
|
|
1098
|
+
severity: 'warning',
|
|
1099
|
+
message: `Journey override referencia a jornada inexistente "${journeyOverride.journeyId}".`,
|
|
1100
|
+
scopeKind: 'journey',
|
|
1101
|
+
path: `journeyOverride:${journeyOverride.journeyId}`,
|
|
1102
|
+
journeyId: journeyOverride.journeyId,
|
|
1103
|
+
});
|
|
1104
|
+
continue;
|
|
1105
|
+
}
|
|
1106
|
+
const touchedTargets = new Set();
|
|
1107
|
+
for (const stepOverride of journeyOverride.stepOverrides ?? []) {
|
|
1108
|
+
const step = journey.steps.find((candidate) => candidate.stepId === stepOverride.stepId);
|
|
1109
|
+
if (!step) {
|
|
1110
|
+
diagnostics.push({
|
|
1111
|
+
code: 'step-override-target-missing',
|
|
1112
|
+
severity: 'warning',
|
|
1113
|
+
message: `Journey override referencia a etapa inexistente "${stepOverride.stepId}" na jornada "${journeyOverride.journeyId}".`,
|
|
1114
|
+
scopeKind: 'step',
|
|
1115
|
+
path: `journeyOverride:${journeyOverride.journeyId}:${stepOverride.stepId}`,
|
|
1116
|
+
journeyId: journeyOverride.journeyId,
|
|
1117
|
+
stepId: stepOverride.stepId,
|
|
1118
|
+
});
|
|
1119
|
+
continue;
|
|
1120
|
+
}
|
|
1121
|
+
for (const blockOverride of stepOverride.blockOverrides ?? []) {
|
|
1122
|
+
applyBlockOverride(step, blockOverride, diagnostics, journeyOverride.journeyId, touchedTargets, instance);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
function applyBlockOverride(step, override, diagnostics, journeyId, touchedTargets, instance) {
|
|
1128
|
+
const source = createSourceRef('instanceOverride', {
|
|
1129
|
+
instanceId: instance?.instanceId ?? undefined,
|
|
1130
|
+
journeyId,
|
|
1131
|
+
stepId: step.stepId,
|
|
1132
|
+
blockId: override.blockId,
|
|
1133
|
+
});
|
|
1134
|
+
const conflictKeys = buildOverrideConflictKeys(step.stepId, override);
|
|
1135
|
+
if (conflictKeys.some((key) => touchedTargets.has(key))) {
|
|
1136
|
+
diagnostics.push({
|
|
1137
|
+
code: 'block-override-conflict',
|
|
1138
|
+
severity: 'warning',
|
|
1139
|
+
message: `Multiplas operacoes de override atingem o bloco "${override.blockId}" em "${journeyId}/${step.stepId}". A ordem declarada sera aplicada de forma deterministica.`,
|
|
1140
|
+
scopeKind: 'block',
|
|
1141
|
+
path: `journeyOverride:${journeyId}:${step.stepId}:${override.blockId}`,
|
|
1142
|
+
journeyId,
|
|
1143
|
+
stepId: step.stepId,
|
|
1144
|
+
blockId: override.blockId,
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
for (const key of conflictKeys) {
|
|
1148
|
+
touchedTargets.add(key);
|
|
1149
|
+
}
|
|
1150
|
+
if (override.operation === 'append') {
|
|
1151
|
+
if (!override.value) {
|
|
1152
|
+
diagnostics.push(createInvalidBlockOverrideDiagnostic(journeyId, step.stepId, override, 'Append requer value.'));
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
step.blocks.push(createResolvedBlock(override.value, source, instance, [], 'instance-override-append'));
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
const blockIndex = step.blocks.findIndex((block) => block.blockId === override.blockId);
|
|
1159
|
+
if (override.operation === 'remove' || override.operation === 'replace') {
|
|
1160
|
+
if (blockIndex === -1) {
|
|
1161
|
+
diagnostics.push(createMissingBlockOverrideTargetDiagnostic(journeyId, step.stepId, override.blockId));
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
if (override.operation === 'remove') {
|
|
1165
|
+
step.blocks.splice(blockIndex, 1);
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
if (!override.value) {
|
|
1169
|
+
diagnostics.push(createInvalidBlockOverrideDiagnostic(journeyId, step.stepId, override, 'Replace requer value.'));
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
const previous = step.blocks[blockIndex];
|
|
1173
|
+
step.blocks.splice(blockIndex, 1, createResolvedBlock(override.value, source, instance, previous.provenance.trail, 'instance-override-replace'));
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
if (!override.referenceBlockId || !override.value) {
|
|
1177
|
+
diagnostics.push(createInvalidBlockOverrideDiagnostic(journeyId, step.stepId, override, 'InsertBefore/InsertAfter requerem referenceBlockId e value.'));
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1180
|
+
const referenceIndex = step.blocks.findIndex((block) => block.blockId === override.referenceBlockId);
|
|
1181
|
+
if (referenceIndex === -1) {
|
|
1182
|
+
diagnostics.push(createMissingBlockOverrideTargetDiagnostic(journeyId, step.stepId, override.referenceBlockId));
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
const insertIndex = override.operation === 'insertBefore'
|
|
1186
|
+
? referenceIndex
|
|
1187
|
+
: referenceIndex + 1;
|
|
1188
|
+
step.blocks.splice(insertIndex, 0, createResolvedBlock(override.value, source, instance, [], override.operation === 'insertBefore'
|
|
1189
|
+
? 'instance-override-insert-before'
|
|
1190
|
+
: 'instance-override-insert-after'));
|
|
1191
|
+
}
|
|
1192
|
+
function buildOverrideConflictKeys(stepId, override) {
|
|
1193
|
+
const keys = [`${stepId}:block:${override.blockId}`];
|
|
1194
|
+
if (override.operation === 'replace' || override.operation === 'remove') {
|
|
1195
|
+
keys.push(`${stepId}:target:${override.blockId}`);
|
|
1196
|
+
}
|
|
1197
|
+
if (override.referenceBlockId) {
|
|
1198
|
+
keys.push(`${stepId}:reference:${override.referenceBlockId}`);
|
|
1199
|
+
keys.push(`${stepId}:target:${override.referenceBlockId}`);
|
|
1200
|
+
}
|
|
1201
|
+
return keys;
|
|
1202
|
+
}
|
|
1203
|
+
function createInvalidBlockOverrideDiagnostic(journeyId, stepId, override, reason) {
|
|
1204
|
+
return {
|
|
1205
|
+
code: 'block-override-invalid',
|
|
1206
|
+
severity: 'warning',
|
|
1207
|
+
message: `Override invalido para bloco "${override.blockId}" em "${journeyId}/${stepId}": ${reason}`,
|
|
1208
|
+
scopeKind: 'block',
|
|
1209
|
+
path: `journeyOverride:${journeyId}:${stepId}:${override.blockId}`,
|
|
1210
|
+
journeyId,
|
|
1211
|
+
stepId,
|
|
1212
|
+
blockId: override.blockId,
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
function createMissingBlockOverrideTargetDiagnostic(journeyId, stepId, blockId) {
|
|
1216
|
+
return {
|
|
1217
|
+
code: 'block-override-target-missing',
|
|
1218
|
+
severity: 'warning',
|
|
1219
|
+
message: `Override referencia bloco inexistente "${blockId}" em "${journeyId}/${stepId}".`,
|
|
1220
|
+
scopeKind: 'block',
|
|
1221
|
+
path: `journeyOverride:${journeyId}:${stepId}:${blockId}`,
|
|
1222
|
+
journeyId,
|
|
1223
|
+
stepId,
|
|
1224
|
+
blockId,
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
function diagnoseResolvedBlocks(journeys, diagnostics, instance) {
|
|
1228
|
+
for (const journey of journeys) {
|
|
1229
|
+
for (const step of journey.steps) {
|
|
1230
|
+
for (const block of step.blocks) {
|
|
1231
|
+
if (block.kind !== 'dataCollection') {
|
|
1232
|
+
continue;
|
|
1233
|
+
}
|
|
1234
|
+
const dataBlock = block;
|
|
1235
|
+
const resolution = resolveEditorialDataBlockFormConfigDetails(dataBlock, instance);
|
|
1236
|
+
if (resolution.ambiguous) {
|
|
1237
|
+
diagnostics.push({
|
|
1238
|
+
code: 'data-collection-config-ambiguous',
|
|
1239
|
+
severity: 'warning',
|
|
1240
|
+
message: `Bloco dataCollection "${block.blockId}" encontrou mais de uma configuracao candidata para "${block.formBlockId}". A primeira correspondencia valida foi aplicada de forma deterministica.`,
|
|
1241
|
+
scopeKind: 'block',
|
|
1242
|
+
path: `journey:${journey.journeyId}:${step.stepId}:${block.blockId}`,
|
|
1243
|
+
journeyId: journey.journeyId,
|
|
1244
|
+
stepId: step.stepId,
|
|
1245
|
+
blockId: block.blockId,
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
if (dataBlock.dataCollectionState.readiness === 'missingConfig') {
|
|
1249
|
+
diagnostics.push({
|
|
1250
|
+
code: 'data-collection-config-missing',
|
|
1251
|
+
severity: 'error',
|
|
1252
|
+
message: `Bloco dataCollection "${block.blockId}" nao possui FormConfig resolvido para "${block.formBlockId}".`,
|
|
1253
|
+
scopeKind: 'block',
|
|
1254
|
+
path: `journey:${journey.journeyId}:${step.stepId}:${block.blockId}`,
|
|
1255
|
+
journeyId: journey.journeyId,
|
|
1256
|
+
stepId: step.stepId,
|
|
1257
|
+
blockId: block.blockId,
|
|
1258
|
+
});
|
|
1259
|
+
continue;
|
|
1260
|
+
}
|
|
1261
|
+
if (dataBlock.dataCollectionState.readiness === 'requiresAdapter') {
|
|
1262
|
+
diagnostics.push({
|
|
1263
|
+
code: 'data-collection-adapter-missing',
|
|
1264
|
+
severity: 'warning',
|
|
1265
|
+
message: `Bloco dataCollection "${block.blockId}" depende de adaptador opcional para materializar "${block.formBlockId}".`,
|
|
1266
|
+
scopeKind: 'block',
|
|
1267
|
+
path: `journey:${journey.journeyId}:${step.stepId}:${block.blockId}`,
|
|
1268
|
+
journeyId: journey.journeyId,
|
|
1269
|
+
stepId: step.stepId,
|
|
1270
|
+
blockId: block.blockId,
|
|
1271
|
+
});
|
|
1272
|
+
continue;
|
|
1273
|
+
}
|
|
1274
|
+
if (dataBlock.dataCollectionState.readiness === 'invalid') {
|
|
1275
|
+
diagnostics.push({
|
|
1276
|
+
code: 'data-collection-invalid',
|
|
1277
|
+
severity: 'error',
|
|
1278
|
+
message: `Bloco dataCollection "${block.blockId}" possui materializacao invalida para "${block.formBlockId}".`,
|
|
1279
|
+
scopeKind: 'block',
|
|
1280
|
+
path: `journey:${journey.journeyId}:${step.stepId}:${block.blockId}`,
|
|
1281
|
+
journeyId: journey.journeyId,
|
|
1282
|
+
stepId: step.stepId,
|
|
1283
|
+
blockId: block.blockId,
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
function annotateDiagnostics(journeys, diagnostics) {
|
|
1291
|
+
for (const diagnostic of diagnostics) {
|
|
1292
|
+
const journey = diagnostic.journeyId
|
|
1293
|
+
? journeys.find((item) => item.journeyId === diagnostic.journeyId)
|
|
1294
|
+
: undefined;
|
|
1295
|
+
const step = diagnostic.stepId
|
|
1296
|
+
? journey?.steps.find((item) => item.stepId === diagnostic.stepId)
|
|
1297
|
+
: undefined;
|
|
1298
|
+
const block = diagnostic.blockId
|
|
1299
|
+
? step?.blocks.find((item) => item.blockId === diagnostic.blockId)
|
|
1300
|
+
: undefined;
|
|
1301
|
+
if (!diagnostic.scopeKind) {
|
|
1302
|
+
diagnostic.scopeKind = block
|
|
1303
|
+
? 'block'
|
|
1304
|
+
: step
|
|
1305
|
+
? 'step'
|
|
1306
|
+
: journey
|
|
1307
|
+
? 'journey'
|
|
1308
|
+
: 'global';
|
|
1309
|
+
}
|
|
1310
|
+
if (journey) {
|
|
1311
|
+
diagnostic.journeyLabel = journey.label;
|
|
1312
|
+
}
|
|
1313
|
+
if (step) {
|
|
1314
|
+
diagnostic.stepLabel = step.label;
|
|
1315
|
+
}
|
|
1316
|
+
if (block) {
|
|
1317
|
+
diagnostic.blockLabel = block.title ?? block.subtitle ?? block.blockId;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
function dedupeTrail(trail) {
|
|
1322
|
+
const seen = new Set();
|
|
1323
|
+
const deduped = [];
|
|
1324
|
+
for (const entry of trail) {
|
|
1325
|
+
const key = `${entry.operation}:${entry.source.kind}:${entry.source.sourceId}:${entry.source.journeyId ?? ''}:${entry.source.stepId ?? ''}:${entry.source.blockId ?? ''}`;
|
|
1326
|
+
if (seen.has(key)) {
|
|
1327
|
+
continue;
|
|
1328
|
+
}
|
|
1329
|
+
seen.add(key);
|
|
1330
|
+
deduped.push(entry);
|
|
1331
|
+
}
|
|
1332
|
+
return deduped;
|
|
1333
|
+
}
|
|
1334
|
+
function buildDataCollectionState(block, instance) {
|
|
1335
|
+
const resolution = resolveEditorialDataBlockFormConfigDetails(block, instance);
|
|
1336
|
+
const hasInlineFormConfig = Boolean(block.formConfig);
|
|
1337
|
+
const hasResolvedFormConfig = Boolean(resolution.formConfig);
|
|
1338
|
+
let readiness;
|
|
1339
|
+
if (!block.formBlockId) {
|
|
1340
|
+
readiness = 'invalid';
|
|
1341
|
+
}
|
|
1342
|
+
else if (!hasResolvedFormConfig) {
|
|
1343
|
+
readiness = 'missingConfig';
|
|
1344
|
+
}
|
|
1345
|
+
else {
|
|
1346
|
+
readiness = 'requiresAdapter';
|
|
1347
|
+
}
|
|
1348
|
+
return {
|
|
1349
|
+
formBlockId: block.formBlockId,
|
|
1350
|
+
formConfigRef: block.formConfigRef,
|
|
1351
|
+
hasInlineFormConfig,
|
|
1352
|
+
resolvedFormConfigSource: resolution.source,
|
|
1353
|
+
resolvedFormConfigLookupKey: resolution.lookupKey,
|
|
1354
|
+
hasResolvedFormConfig,
|
|
1355
|
+
expectedAdapter: 'required',
|
|
1356
|
+
readiness,
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
function createSourceRef(kind, details) {
|
|
1360
|
+
const sourceId = [
|
|
1361
|
+
kind,
|
|
1362
|
+
details.solutionId,
|
|
1363
|
+
details.presetId,
|
|
1364
|
+
details.instanceId,
|
|
1365
|
+
details.journeyId,
|
|
1366
|
+
details.stepId,
|
|
1367
|
+
details.blockId,
|
|
1368
|
+
]
|
|
1369
|
+
.filter((value) => Boolean(value))
|
|
1370
|
+
.join(':');
|
|
1371
|
+
return {
|
|
1372
|
+
kind,
|
|
1373
|
+
sourceId: sourceId || kind,
|
|
1374
|
+
...details,
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1377
|
+
function mergeContext(...sources) {
|
|
1378
|
+
const result = {};
|
|
1379
|
+
for (const source of sources) {
|
|
1380
|
+
mergeContextInto(result, source);
|
|
1381
|
+
}
|
|
1382
|
+
return result;
|
|
1383
|
+
}
|
|
1384
|
+
function mergeContextInto(target, source) {
|
|
1385
|
+
for (const [key, value] of Object.entries(source)) {
|
|
1386
|
+
if (isPlainObject(value) && isPlainObject(target[key])) {
|
|
1387
|
+
mergeContextInto(target[key], value);
|
|
1388
|
+
continue;
|
|
1389
|
+
}
|
|
1390
|
+
if (isPlainObject(value)) {
|
|
1391
|
+
target[key] = clonePlainObject(value);
|
|
1392
|
+
continue;
|
|
1393
|
+
}
|
|
1394
|
+
target[key] = value;
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
function clonePlainObject(value) {
|
|
1398
|
+
const target = {};
|
|
1399
|
+
mergeContextInto(target, value);
|
|
1400
|
+
return target;
|
|
1401
|
+
}
|
|
1402
|
+
function isPlainObject(value) {
|
|
1403
|
+
return value != null && typeof value === 'object' && !Array.isArray(value);
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
class EditorialRuntimeState {
|
|
1407
|
+
journeyId = signal(null, ...(ngDevMode ? [{ debugName: "journeyId" }] : []));
|
|
1408
|
+
stepId = signal(null, ...(ngDevMode ? [{ debugName: "stepId" }] : []));
|
|
1409
|
+
activeJourneyId = this.journeyId.asReadonly();
|
|
1410
|
+
activeStepId = this.stepId.asReadonly();
|
|
1411
|
+
connect(solution, instance, runtimeContext) {
|
|
1412
|
+
const snapshot = computed(() => resolveEditorialRuntimeSnapshot({
|
|
1413
|
+
solution: solution(),
|
|
1414
|
+
instance: instance(),
|
|
1415
|
+
runtimeContext: runtimeContext(),
|
|
1416
|
+
}), ...(ngDevMode ? [{ debugName: "snapshot" }] : []));
|
|
1417
|
+
const journeys = computed(() => snapshot().journeys, ...(ngDevMode ? [{ debugName: "journeys" }] : []));
|
|
1418
|
+
const activeJourney = computed(() => resolveActiveJourney(journeys(), this.journeyId()), ...(ngDevMode ? [{ debugName: "activeJourney" }] : []));
|
|
1419
|
+
const activeStep = computed(() => resolveActiveStep(activeJourney(), this.stepId()), ...(ngDevMode ? [{ debugName: "activeStep" }] : []));
|
|
1420
|
+
return {
|
|
1421
|
+
snapshot,
|
|
1422
|
+
journeys,
|
|
1423
|
+
activeJourney,
|
|
1424
|
+
activeStep,
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
selectJourney(journeyId) {
|
|
1428
|
+
this.journeyId.set(journeyId);
|
|
1429
|
+
this.stepId.set(null);
|
|
1430
|
+
}
|
|
1431
|
+
selectStep(stepId) {
|
|
1432
|
+
this.stepId.set(stepId);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
function deriveRuntimeFallbackState(snapshot, scope = {}) {
|
|
1437
|
+
const diagnostics = snapshot.diagnostics.items;
|
|
1438
|
+
const blockingDiagnostics = diagnostics.filter((item) => {
|
|
1439
|
+
if (item.severity !== 'error') {
|
|
1440
|
+
return false;
|
|
1441
|
+
}
|
|
1442
|
+
if (item.scopeKind === 'global') {
|
|
1443
|
+
return true;
|
|
1444
|
+
}
|
|
1445
|
+
return item.journeyId === scope.journeyId && item.stepId === scope.stepId;
|
|
1446
|
+
});
|
|
1447
|
+
const hasGlobalErrors = diagnostics.some((item) => item.severity === 'error' && item.scopeKind === 'global');
|
|
1448
|
+
const hasActiveStepErrors = diagnostics.some((item) => item.severity === 'error'
|
|
1449
|
+
&& item.scopeKind !== 'global'
|
|
1450
|
+
&& item.journeyId === scope.journeyId
|
|
1451
|
+
&& item.stepId === scope.stepId);
|
|
1452
|
+
const hasAnyErrors = diagnostics.some((item) => item.severity === 'error');
|
|
1453
|
+
const hasWarnings = diagnostics.some((item) => item.severity === 'warning');
|
|
1454
|
+
const requiresEngineAttention = diagnostics.some((item) => item.code === 'data-collection-adapter-missing');
|
|
1455
|
+
let mode = 'normal';
|
|
1456
|
+
if (blockingDiagnostics.length) {
|
|
1457
|
+
mode = 'blocked';
|
|
1458
|
+
}
|
|
1459
|
+
else if (hasAnyErrors || requiresEngineAttention) {
|
|
1460
|
+
mode = 'degraded';
|
|
1461
|
+
}
|
|
1462
|
+
else if (hasWarnings) {
|
|
1463
|
+
mode = 'warning';
|
|
1464
|
+
}
|
|
1465
|
+
return {
|
|
1466
|
+
mode,
|
|
1467
|
+
progressionBlocked: blockingDiagnostics.length > 0,
|
|
1468
|
+
hasGlobalErrors,
|
|
1469
|
+
hasActiveStepErrors,
|
|
1470
|
+
hasWarnings,
|
|
1471
|
+
requiresEngineAttention,
|
|
1472
|
+
diagnostics,
|
|
1473
|
+
blockingDiagnostics,
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
class EditorialFormRuntimeComponent {
|
|
1478
|
+
solution = input(null, ...(ngDevMode ? [{ debugName: "solution" }] : []));
|
|
1479
|
+
instance = input(null, ...(ngDevMode ? [{ debugName: "instance" }] : []));
|
|
1480
|
+
runtimeContext = input(null, ...(ngDevMode ? [{ debugName: "runtimeContext" }] : []));
|
|
1481
|
+
hostConfig = input(null, ...(ngDevMode ? [{ debugName: "hostConfig" }] : []));
|
|
1482
|
+
snapshotChange = output();
|
|
1483
|
+
fallbackChange = output();
|
|
1484
|
+
operationalEvent = output();
|
|
1485
|
+
state = new EditorialRuntimeState();
|
|
1486
|
+
solutionState = signal(null, ...(ngDevMode ? [{ debugName: "solutionState" }] : []));
|
|
1487
|
+
instanceState = signal(null, ...(ngDevMode ? [{ debugName: "instanceState" }] : []));
|
|
1488
|
+
lastSnapshotSignature = null;
|
|
1489
|
+
lastDiagnosticsSignature = null;
|
|
1490
|
+
lastFallbackSignature = null;
|
|
1491
|
+
lastBlockingSignature = null;
|
|
1492
|
+
lastOverrideConflictSignature = null;
|
|
1493
|
+
runtime = this.state.connect(this.solutionState, this.instanceState, this.runtimeContext);
|
|
1494
|
+
snapshot = computed(() => this.runtime.snapshot(), ...(ngDevMode ? [{ debugName: "snapshot" }] : []));
|
|
1495
|
+
resolvedHostConfig = computed(() => ({
|
|
1496
|
+
...DEFAULT_EDITORIAL_RUNTIME_HOST_CONFIG,
|
|
1497
|
+
...(this.hostConfig() ?? {}),
|
|
1498
|
+
}), ...(ngDevMode ? [{ debugName: "resolvedHostConfig" }] : []));
|
|
1499
|
+
journeys = computed(() => this.runtime.journeys(), ...(ngDevMode ? [{ debugName: "journeys" }] : []));
|
|
1500
|
+
activeJourney = computed(() => this.runtime.activeJourney(), ...(ngDevMode ? [{ debugName: "activeJourney" }] : []));
|
|
1501
|
+
activeStep = computed(() => this.runtime.activeStep(), ...(ngDevMode ? [{ debugName: "activeStep" }] : []));
|
|
1502
|
+
resolvedContext = computed(() => this.snapshot().context, ...(ngDevMode ? [{ debugName: "resolvedContext" }] : []));
|
|
1503
|
+
runtimeDiagnostics = computed(() => this.snapshot().diagnostics, ...(ngDevMode ? [{ debugName: "runtimeDiagnostics" }] : []));
|
|
1504
|
+
fallbackState = computed(() => deriveRuntimeFallbackState(this.snapshot(), {
|
|
1505
|
+
journeyId: this.activeJourney()?.journeyId,
|
|
1506
|
+
stepId: this.activeStep()?.stepId,
|
|
1507
|
+
}), ...(ngDevMode ? [{ debugName: "fallbackState" }] : []));
|
|
1508
|
+
diagnosticItems = computed(() => sortDiagnostics(dedupeDiagnostics(this.runtimeDiagnostics().items)), ...(ngDevMode ? [{ debugName: "diagnosticItems" }] : []));
|
|
1509
|
+
globalDiagnostics = computed(() => this.diagnosticItems().filter((item) => item.scopeKind === 'global'), ...(ngDevMode ? [{ debugName: "globalDiagnostics" }] : []));
|
|
1510
|
+
contextualDiagnostics = computed(() => this.diagnosticItems().filter((item) => item.scopeKind !== 'global'), ...(ngDevMode ? [{ debugName: "contextualDiagnostics" }] : []));
|
|
1511
|
+
diagnosticsErrorCount = computed(() => this.diagnosticItems().filter((item) => item.severity === 'error').length, ...(ngDevMode ? [{ debugName: "diagnosticsErrorCount" }] : []));
|
|
1512
|
+
diagnosticsWarningCount = computed(() => this.diagnosticItems().filter((item) => item.severity === 'warning').length, ...(ngDevMode ? [{ debugName: "diagnosticsWarningCount" }] : []));
|
|
1513
|
+
diagnosticsInfoCount = computed(() => this.diagnosticItems().filter((item) => item.severity === 'info').length, ...(ngDevMode ? [{ debugName: "diagnosticsInfoCount" }] : []));
|
|
1514
|
+
activeStepDiagnostics = computed(() => this.diagnosticItems().filter((item) => isDiagnosticInActiveStep(item, this.activeJourney()?.journeyId, this.activeStep()?.stepId)), ...(ngDevMode ? [{ debugName: "activeStepDiagnostics" }] : []));
|
|
1515
|
+
activeStepHasErrors = computed(() => this.activeStepDiagnostics().some((item) => item.severity === 'error'), ...(ngDevMode ? [{ debugName: "activeStepHasErrors" }] : []));
|
|
1516
|
+
activeStepHasWarnings = computed(() => this.activeStepDiagnostics().some((item) => item.severity === 'warning'), ...(ngDevMode ? [{ debugName: "activeStepHasWarnings" }] : []));
|
|
1517
|
+
diagnosticsMessage = computed(() => this.fallbackState().mode === 'blocked'
|
|
1518
|
+
? 'Existem inconsistencias bloqueadoras que impedem a progressao segura do fluxo editorial.'
|
|
1519
|
+
: this.fallbackState().mode === 'degraded'
|
|
1520
|
+
? 'O runtime esta operando de forma degradada e requer atencao operacional.'
|
|
1521
|
+
: this.runtimeDiagnostics().hasErrors
|
|
1522
|
+
? 'Existem inconsistencias que podem comprometer a experiencia editorial.'
|
|
1523
|
+
: 'Existem avisos operacionais para revisar nesta instancia editorial.', ...(ngDevMode ? [{ debugName: "diagnosticsMessage" }] : []));
|
|
1524
|
+
activeGlobalDiagnostics = computed(() => this.globalDiagnostics().filter((item) => item.severity === 'error'), ...(ngDevMode ? [{ debugName: "activeGlobalDiagnostics" }] : []));
|
|
1525
|
+
visibleBlocks = computed(() => getVisibleBlocks(this.activeStep()?.blocks, this.resolvedContext()), ...(ngDevMode ? [{ debugName: "visibleBlocks" }] : []));
|
|
1526
|
+
runtimeTitle = computed(() => this.snapshot().title, ...(ngDevMode ? [{ debugName: "runtimeTitle" }] : []));
|
|
1527
|
+
runtimeDescription = computed(() => this.snapshot().description, ...(ngDevMode ? [{ debugName: "runtimeDescription" }] : []));
|
|
1528
|
+
runtimeEyebrow = computed(() => this.snapshot().problemType, ...(ngDevMode ? [{ debugName: "runtimeEyebrow" }] : []));
|
|
1529
|
+
fallbackLabel = computed(() => {
|
|
1530
|
+
if (this.fallbackState().mode === 'blocked') {
|
|
1531
|
+
return 'Runtime bloqueado';
|
|
1532
|
+
}
|
|
1533
|
+
if (this.fallbackState().mode === 'degraded') {
|
|
1534
|
+
return 'Runtime degradado';
|
|
1535
|
+
}
|
|
1536
|
+
if (this.fallbackState().mode === 'warning') {
|
|
1537
|
+
return 'Runtime com aviso';
|
|
1538
|
+
}
|
|
1539
|
+
return 'Runtime saudavel';
|
|
1540
|
+
}, ...(ngDevMode ? [{ debugName: "fallbackLabel" }] : []));
|
|
1541
|
+
currentStepIndex = computed(() => {
|
|
1542
|
+
const journey = this.activeJourney();
|
|
1543
|
+
const step = this.activeStep();
|
|
1544
|
+
if (!journey || !step) {
|
|
1545
|
+
return 0;
|
|
1546
|
+
}
|
|
1547
|
+
return Math.max(0, journey.steps.findIndex((candidate) => candidate.stepId === step.stepId));
|
|
1548
|
+
}, ...(ngDevMode ? [{ debugName: "currentStepIndex" }] : []));
|
|
1549
|
+
hasPreviousStep = computed(() => this.currentStepIndex() > 0, ...(ngDevMode ? [{ debugName: "hasPreviousStep" }] : []));
|
|
1550
|
+
hasNextStep = computed(() => {
|
|
1551
|
+
const journey = this.activeJourney();
|
|
1552
|
+
return !!journey && this.currentStepIndex() < journey.steps.length - 1;
|
|
1553
|
+
}, ...(ngDevMode ? [{ debugName: "hasNextStep" }] : []));
|
|
1554
|
+
constructor() {
|
|
1555
|
+
effect(() => {
|
|
1556
|
+
this.solutionState.set(this.solution());
|
|
1557
|
+
this.instanceState.set(this.instance());
|
|
1558
|
+
});
|
|
1559
|
+
effect(() => {
|
|
1560
|
+
const snapshot = this.snapshot();
|
|
1561
|
+
const snapshotSignature = buildSnapshotSignature(snapshot);
|
|
1562
|
+
if (snapshotSignature !== this.lastSnapshotSignature) {
|
|
1563
|
+
this.lastSnapshotSignature = snapshotSignature;
|
|
1564
|
+
this.snapshotChange.emit(snapshot);
|
|
1565
|
+
}
|
|
1566
|
+
});
|
|
1567
|
+
effect(() => {
|
|
1568
|
+
const fallback = this.fallbackState();
|
|
1569
|
+
const signature = `${fallback.mode}:${fallback.progressionBlocked}:${fallback.requiresEngineAttention}:${fallback.blockingDiagnostics.map((item) => item.path ?? item.message).join('|')}`;
|
|
1570
|
+
if (signature !== this.lastFallbackSignature) {
|
|
1571
|
+
this.lastFallbackSignature = signature;
|
|
1572
|
+
this.fallbackChange.emit(fallback);
|
|
1573
|
+
this.emitOperationalEvent({
|
|
1574
|
+
eventType: 'fallback-changed',
|
|
1575
|
+
timestamp: Date.now(),
|
|
1576
|
+
severity: fallback.mode === 'blocked'
|
|
1577
|
+
? 'error'
|
|
1578
|
+
: fallback.mode === 'degraded'
|
|
1579
|
+
? 'warning'
|
|
1580
|
+
: 'info',
|
|
1581
|
+
journeyId: this.activeJourney()?.journeyId ?? undefined,
|
|
1582
|
+
stepId: this.activeStep()?.stepId ?? undefined,
|
|
1583
|
+
payload: {
|
|
1584
|
+
fallback,
|
|
1585
|
+
},
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1588
|
+
if (!fallback.blockingDiagnostics.length) {
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1591
|
+
const blockingSignature = fallback.blockingDiagnostics
|
|
1592
|
+
.map((item) => item.path ?? item.message)
|
|
1593
|
+
.join('|');
|
|
1594
|
+
if (blockingSignature === this.lastBlockingSignature) {
|
|
1595
|
+
return;
|
|
1596
|
+
}
|
|
1597
|
+
this.lastBlockingSignature = blockingSignature;
|
|
1598
|
+
this.emitOperationalEvent({
|
|
1599
|
+
eventType: 'blocking-error-detected',
|
|
1600
|
+
timestamp: Date.now(),
|
|
1601
|
+
severity: 'error',
|
|
1602
|
+
journeyId: this.activeJourney()?.journeyId ?? undefined,
|
|
1603
|
+
stepId: this.activeStep()?.stepId ?? undefined,
|
|
1604
|
+
payload: {
|
|
1605
|
+
diagnostics: fallback.blockingDiagnostics,
|
|
1606
|
+
scope: fallback.hasGlobalErrors ? 'global' : 'step',
|
|
1607
|
+
},
|
|
1608
|
+
});
|
|
1609
|
+
});
|
|
1610
|
+
effect(() => {
|
|
1611
|
+
const diagnostics = this.diagnosticItems();
|
|
1612
|
+
const signature = diagnostics
|
|
1613
|
+
.map((item) => `${item.severity}:${item.code}:${item.path ?? ''}`)
|
|
1614
|
+
.join('|');
|
|
1615
|
+
if (signature === this.lastDiagnosticsSignature) {
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
this.lastDiagnosticsSignature = signature;
|
|
1619
|
+
const errorCount = diagnostics.filter((item) => item.severity === 'error').length;
|
|
1620
|
+
const warningCount = diagnostics.filter((item) => item.severity === 'warning').length;
|
|
1621
|
+
const infoCount = diagnostics.filter((item) => item.severity === 'info').length;
|
|
1622
|
+
this.emitOperationalEvent({
|
|
1623
|
+
eventType: 'diagnostics-emitted',
|
|
1624
|
+
timestamp: Date.now(),
|
|
1625
|
+
severity: errorCount ? 'error' : warningCount ? 'warning' : 'info',
|
|
1626
|
+
journeyId: this.activeJourney()?.journeyId ?? undefined,
|
|
1627
|
+
stepId: this.activeStep()?.stepId ?? undefined,
|
|
1628
|
+
payload: {
|
|
1629
|
+
diagnostics,
|
|
1630
|
+
errorCount,
|
|
1631
|
+
warningCount,
|
|
1632
|
+
infoCount,
|
|
1633
|
+
},
|
|
1634
|
+
});
|
|
1635
|
+
const overrideConflictDiagnostics = diagnostics.filter((item) => item.code === 'block-override-conflict');
|
|
1636
|
+
const overrideSignature = overrideConflictDiagnostics
|
|
1637
|
+
.map((item) => item.path ?? item.message)
|
|
1638
|
+
.join('|');
|
|
1639
|
+
if (overrideConflictDiagnostics.length && overrideSignature !== this.lastOverrideConflictSignature) {
|
|
1640
|
+
this.lastOverrideConflictSignature = overrideSignature;
|
|
1641
|
+
this.emitOperationalEvent({
|
|
1642
|
+
eventType: 'override-conflict-detected',
|
|
1643
|
+
timestamp: Date.now(),
|
|
1644
|
+
severity: 'warning',
|
|
1645
|
+
journeyId: overrideConflictDiagnostics[0]?.journeyId,
|
|
1646
|
+
stepId: overrideConflictDiagnostics[0]?.stepId,
|
|
1647
|
+
blockId: overrideConflictDiagnostics[0]?.blockId,
|
|
1648
|
+
payload: {
|
|
1649
|
+
diagnostics: overrideConflictDiagnostics,
|
|
1650
|
+
},
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
selectJourney(journeyId) {
|
|
1656
|
+
if (this.isJourneySelectionBlocked(journeyId)) {
|
|
1657
|
+
return;
|
|
1658
|
+
}
|
|
1659
|
+
this.state.selectJourney(journeyId);
|
|
1660
|
+
}
|
|
1661
|
+
selectStep(stepId) {
|
|
1662
|
+
if (this.isStepSelectionBlocked(stepId)) {
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
this.state.selectStep(stepId);
|
|
1666
|
+
}
|
|
1667
|
+
goToPreviousStep() {
|
|
1668
|
+
const journey = this.activeJourney();
|
|
1669
|
+
if (!journey || !this.hasPreviousStep()) {
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
const previous = journey.steps[this.currentStepIndex() - 1];
|
|
1673
|
+
if (previous) {
|
|
1674
|
+
this.state.selectStep(previous.stepId);
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
goToNextStep() {
|
|
1678
|
+
const journey = this.activeJourney();
|
|
1679
|
+
if (!journey || !this.hasNextStep() || this.isForwardNavigationBlocked()) {
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
const next = journey.steps[this.currentStepIndex() + 1];
|
|
1683
|
+
if (next) {
|
|
1684
|
+
this.state.selectStep(next.stepId);
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
journeyErrorCount(journeyId) {
|
|
1688
|
+
return this.countDiagnostics((item) => item.journeyId === journeyId && item.severity === 'error');
|
|
1689
|
+
}
|
|
1690
|
+
journeyWarningCount(journeyId) {
|
|
1691
|
+
return this.countDiagnostics((item) => item.journeyId === journeyId && item.severity === 'warning');
|
|
1692
|
+
}
|
|
1693
|
+
stepErrorCount(stepId) {
|
|
1694
|
+
return this.countDiagnostics((item) => item.journeyId === this.activeJourney()?.journeyId && item.stepId === stepId && item.severity === 'error');
|
|
1695
|
+
}
|
|
1696
|
+
stepWarningCount(stepId) {
|
|
1697
|
+
return this.countDiagnostics((item) => item.journeyId === this.activeJourney()?.journeyId && item.stepId === stepId && item.severity === 'warning');
|
|
1698
|
+
}
|
|
1699
|
+
formatDiagnosticSeverity(item) {
|
|
1700
|
+
if (item.severity === 'error') {
|
|
1701
|
+
return 'Erro';
|
|
1702
|
+
}
|
|
1703
|
+
if (item.severity === 'warning') {
|
|
1704
|
+
return 'Aviso';
|
|
1705
|
+
}
|
|
1706
|
+
return 'Info';
|
|
1707
|
+
}
|
|
1708
|
+
formatDiagnosticScope(item) {
|
|
1709
|
+
const parts = [
|
|
1710
|
+
item.scopeKind === 'global' ? 'Escopo: runtime global' : null,
|
|
1711
|
+
formatScopeLabel('Jornada', item.journeyLabel, item.journeyId),
|
|
1712
|
+
formatScopeLabel('Etapa', item.stepLabel, item.stepId),
|
|
1713
|
+
formatScopeLabel('Bloco', item.blockLabel, item.blockId),
|
|
1714
|
+
item.path ? `Path: ${item.path}` : null,
|
|
1715
|
+
].filter((value) => Boolean(value));
|
|
1716
|
+
return parts.join(' | ');
|
|
1717
|
+
}
|
|
1718
|
+
isForwardNavigationBlocked() {
|
|
1719
|
+
return this.fallbackState().progressionBlocked;
|
|
1720
|
+
}
|
|
1721
|
+
isJourneySelectionBlocked(journeyId) {
|
|
1722
|
+
const activeJourneyId = this.activeJourney()?.journeyId;
|
|
1723
|
+
if (journeyId === activeJourneyId) {
|
|
1724
|
+
return false;
|
|
1725
|
+
}
|
|
1726
|
+
return this.isForwardNavigationBlocked();
|
|
1727
|
+
}
|
|
1728
|
+
isStepSelectionBlocked(stepId) {
|
|
1729
|
+
const activeStepId = this.activeStep()?.stepId;
|
|
1730
|
+
if (stepId === activeStepId) {
|
|
1731
|
+
return false;
|
|
1732
|
+
}
|
|
1733
|
+
return this.isForwardNavigationBlocked();
|
|
1734
|
+
}
|
|
1735
|
+
navigationBlockingMessage() {
|
|
1736
|
+
if (this.activeGlobalDiagnostics().length) {
|
|
1737
|
+
return 'A navegacao de avanço foi bloqueada porque o runtime possui erro global que precisa ser corrigido antes de continuar.';
|
|
1738
|
+
}
|
|
1739
|
+
return 'A navegacao de avanço foi bloqueada porque a etapa atual possui erro estrutural.';
|
|
1740
|
+
}
|
|
1741
|
+
countDiagnostics(predicate) {
|
|
1742
|
+
return this.diagnosticItems().filter(predicate).length;
|
|
1743
|
+
}
|
|
1744
|
+
emitOperationalEvent(event) {
|
|
1745
|
+
if (!this.resolvedHostConfig().emitOperationalEvents) {
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1748
|
+
if (!this.resolvedHostConfig().forwardAdapterOperationalEvents
|
|
1749
|
+
&& event.eventType.startsWith('data-collection-adapter-')) {
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
this.operationalEvent.emit(event);
|
|
1753
|
+
}
|
|
1754
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialFormRuntimeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1755
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialFormRuntimeComponent, isStandalone: true, selector: "praxis-editorial-form-runtime", inputs: { solution: { classPropertyName: "solution", publicName: "solution", isSignal: true, isRequired: false, transformFunction: null }, instance: { classPropertyName: "instance", publicName: "instance", isSignal: true, isRequired: false, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null }, hostConfig: { classPropertyName: "hostConfig", publicName: "hostConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { snapshotChange: "snapshotChange", fallbackChange: "fallbackChange", operationalEvent: "operationalEvent" }, ngImport: i0, template: `
|
|
1756
|
+
<section class="editorial-runtime">
|
|
1757
|
+
@if (runtimeDiagnostics().items.length) {
|
|
1758
|
+
<section
|
|
1759
|
+
class="diagnostics-panel"
|
|
1760
|
+
[class.error]="runtimeDiagnostics().hasErrors"
|
|
1761
|
+
[class.warning]="runtimeDiagnostics().hasWarnings"
|
|
1762
|
+
[attr.role]="runtimeDiagnostics().hasErrors ? 'alert' : 'status'"
|
|
1763
|
+
[attr.aria-live]="runtimeDiagnostics().hasErrors ? 'assertive' : 'polite'"
|
|
1764
|
+
aria-atomic="true"
|
|
1765
|
+
>
|
|
1766
|
+
<h2>Diagnosticos do runtime</h2>
|
|
1767
|
+
<p>{{ diagnosticsMessage() }}</p>
|
|
1768
|
+
<div class="diagnostics-summary" aria-label="Resumo de severidade">
|
|
1769
|
+
<span class="summary-pill error">Erros: {{ diagnosticsErrorCount() }}</span>
|
|
1770
|
+
<span class="summary-pill warning">Avisos: {{ diagnosticsWarningCount() }}</span>
|
|
1771
|
+
<span class="summary-pill info">Infos: {{ diagnosticsInfoCount() }}</span>
|
|
1772
|
+
</div>
|
|
1773
|
+
<details class="diagnostics-details">
|
|
1774
|
+
<summary>Ver detalhes ({{ diagnosticItems().length }})</summary>
|
|
1775
|
+
@if (globalDiagnostics().length) {
|
|
1776
|
+
<section class="diagnostic-group global" aria-label="Erros globais do runtime">
|
|
1777
|
+
<h3>Erros globais do runtime</h3>
|
|
1778
|
+
<ul class="diagnostics-list">
|
|
1779
|
+
@for (item of globalDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
|
|
1780
|
+
<li>
|
|
1781
|
+
<strong>{{ formatDiagnosticSeverity(item) }}:</strong>
|
|
1782
|
+
{{ item.message }}
|
|
1783
|
+
@if (formatDiagnosticScope(item); as scope) {
|
|
1784
|
+
<span class="diagnostic-location">{{ scope }}</span>
|
|
1785
|
+
}
|
|
1786
|
+
</li>
|
|
1787
|
+
}
|
|
1788
|
+
</ul>
|
|
1789
|
+
</section>
|
|
1790
|
+
}
|
|
1791
|
+
<ul class="diagnostics-list">
|
|
1792
|
+
@for (item of contextualDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
|
|
1793
|
+
<li>
|
|
1794
|
+
<strong>{{ formatDiagnosticSeverity(item) }}:</strong>
|
|
1795
|
+
{{ item.message }}
|
|
1796
|
+
@if (formatDiagnosticScope(item); as scope) {
|
|
1797
|
+
<span class="diagnostic-location">{{ scope }}</span>
|
|
1798
|
+
}
|
|
1799
|
+
</li>
|
|
1800
|
+
}
|
|
1801
|
+
</ul>
|
|
1802
|
+
</details>
|
|
1803
|
+
</section>
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
@if (runtimeTitle(); as title) {
|
|
1807
|
+
<header class="runtime-header">
|
|
1808
|
+
<span class="runtime-state-pill" [attr.data-mode]="fallbackState().mode">
|
|
1809
|
+
{{ fallbackLabel() }}
|
|
1810
|
+
</span>
|
|
1811
|
+
@if (runtimeEyebrow()) {
|
|
1812
|
+
<p class="eyebrow">{{ runtimeEyebrow() }}</p>
|
|
1813
|
+
}
|
|
1814
|
+
<h1>{{ title }}</h1>
|
|
1815
|
+
@if (runtimeDescription()) {
|
|
1816
|
+
<p class="description">{{ runtimeDescription() }}</p>
|
|
1817
|
+
}
|
|
1818
|
+
</header>
|
|
1819
|
+
|
|
1820
|
+
@if (journeys().length > 1) {
|
|
1821
|
+
<nav class="journey-tabs" aria-label="Jornadas editoriais">
|
|
1822
|
+
@for (journey of journeys(); track journey.journeyId) {
|
|
1823
|
+
<button
|
|
1824
|
+
type="button"
|
|
1825
|
+
class="journey-tab"
|
|
1826
|
+
[class.active]="activeJourney()?.journeyId === journey.journeyId"
|
|
1827
|
+
[disabled]="isJourneySelectionBlocked(journey.journeyId)"
|
|
1828
|
+
[attr.aria-describedby]="isJourneySelectionBlocked(journey.journeyId) ? 'navigation-blocking-note' : null"
|
|
1829
|
+
(click)="selectJourney(journey.journeyId)"
|
|
1830
|
+
>
|
|
1831
|
+
{{ journey.label }}
|
|
1832
|
+
@if (journeyErrorCount(journey.journeyId)) {
|
|
1833
|
+
<span class="status-badge error" aria-label="Jornada com erros">
|
|
1834
|
+
{{ journeyErrorCount(journey.journeyId) }}
|
|
1835
|
+
</span>
|
|
1836
|
+
} @else if (journeyWarningCount(journey.journeyId)) {
|
|
1837
|
+
<span class="status-badge warning" aria-label="Jornada com avisos">
|
|
1838
|
+
{{ journeyWarningCount(journey.journeyId) }}
|
|
1839
|
+
</span>
|
|
1840
|
+
}
|
|
1841
|
+
</button>
|
|
1842
|
+
}
|
|
1843
|
+
</nav>
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
@if (activeJourney(); as journey) {
|
|
1847
|
+
<section class="journey-card">
|
|
1848
|
+
<header class="journey-header">
|
|
1849
|
+
<h2>{{ journey.label }}</h2>
|
|
1850
|
+
@if (journey.description) {
|
|
1851
|
+
<p>{{ journey.description }}</p>
|
|
1852
|
+
}
|
|
1853
|
+
</header>
|
|
1854
|
+
|
|
1855
|
+
@if (journey.steps.length > 1) {
|
|
1856
|
+
<ol class="steps-nav" aria-label="Etapas da jornada">
|
|
1857
|
+
@for (step of journey.steps; track step.stepId) {
|
|
1858
|
+
<li>
|
|
1859
|
+
<button
|
|
1860
|
+
type="button"
|
|
1861
|
+
class="step-chip"
|
|
1862
|
+
[class.active]="activeStep()?.stepId === step.stepId"
|
|
1863
|
+
[disabled]="isStepSelectionBlocked(step.stepId)"
|
|
1864
|
+
[attr.aria-describedby]="isStepSelectionBlocked(step.stepId) ? 'navigation-blocking-note' : null"
|
|
1865
|
+
(click)="selectStep(step.stepId)"
|
|
1866
|
+
>
|
|
1867
|
+
{{ step.label }}
|
|
1868
|
+
@if (stepErrorCount(step.stepId)) {
|
|
1869
|
+
<span class="status-badge error" aria-label="Etapa com erros">
|
|
1870
|
+
{{ stepErrorCount(step.stepId) }}
|
|
1871
|
+
</span>
|
|
1872
|
+
} @else if (stepWarningCount(step.stepId)) {
|
|
1873
|
+
<span class="status-badge warning" aria-label="Etapa com avisos">
|
|
1874
|
+
{{ stepWarningCount(step.stepId) }}
|
|
1875
|
+
</span>
|
|
1876
|
+
}
|
|
1877
|
+
</button>
|
|
1878
|
+
</li>
|
|
1879
|
+
}
|
|
1880
|
+
</ol>
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
@if (activeStep(); as step) {
|
|
1884
|
+
<section
|
|
1885
|
+
class="step-panel"
|
|
1886
|
+
[class.error]="activeStepHasErrors() || activeGlobalDiagnostics().length"
|
|
1887
|
+
[class.warning]="!activeStepHasErrors() && !activeGlobalDiagnostics().length && activeStepHasWarnings()"
|
|
1888
|
+
>
|
|
1889
|
+
<header class="step-header">
|
|
1890
|
+
<div>
|
|
1891
|
+
<h3>{{ step.label }}</h3>
|
|
1892
|
+
@if (step.description) {
|
|
1893
|
+
<p>{{ step.description }}</p>
|
|
1894
|
+
}
|
|
1895
|
+
</div>
|
|
1896
|
+
<div class="step-counter">
|
|
1897
|
+
Etapa {{ currentStepIndex() + 1 }} de {{ journey.steps.length }}
|
|
1898
|
+
</div>
|
|
1899
|
+
</header>
|
|
1900
|
+
|
|
1901
|
+
@if (activeStepDiagnostics().length) {
|
|
1902
|
+
<section
|
|
1903
|
+
class="step-diagnostics"
|
|
1904
|
+
[class.error]="activeStepHasErrors()"
|
|
1905
|
+
[class.warning]="!activeStepHasErrors() && activeStepHasWarnings()"
|
|
1906
|
+
[attr.role]="activeStepHasErrors() ? 'alert' : 'status'"
|
|
1907
|
+
[attr.aria-live]="activeStepHasErrors() ? 'assertive' : 'polite'"
|
|
1908
|
+
aria-atomic="true"
|
|
1909
|
+
>
|
|
1910
|
+
<h4>Situacao desta etapa</h4>
|
|
1911
|
+
<ul class="diagnostics-list contextual">
|
|
1912
|
+
@for (item of activeStepDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
|
|
1913
|
+
<li>
|
|
1914
|
+
<strong>{{ formatDiagnosticSeverity(item) }}:</strong>
|
|
1915
|
+
{{ item.message }}
|
|
1916
|
+
@if (formatDiagnosticScope(item); as scope) {
|
|
1917
|
+
<span class="diagnostic-location">{{ scope }}</span>
|
|
1918
|
+
}
|
|
1919
|
+
</li>
|
|
1920
|
+
}
|
|
1921
|
+
</ul>
|
|
1922
|
+
</section>
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
@if (activeGlobalDiagnostics().length) {
|
|
1926
|
+
<section
|
|
1927
|
+
class="step-diagnostics global"
|
|
1928
|
+
role="alert"
|
|
1929
|
+
aria-live="assertive"
|
|
1930
|
+
aria-atomic="true"
|
|
1931
|
+
>
|
|
1932
|
+
<h4>Erro global do runtime</h4>
|
|
1933
|
+
<ul class="diagnostics-list contextual">
|
|
1934
|
+
@for (item of activeGlobalDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
|
|
1935
|
+
<li>
|
|
1936
|
+
<strong>{{ formatDiagnosticSeverity(item) }}:</strong>
|
|
1937
|
+
{{ item.message }}
|
|
1938
|
+
@if (formatDiagnosticScope(item); as scope) {
|
|
1939
|
+
<span class="diagnostic-location">{{ scope }}</span>
|
|
1940
|
+
}
|
|
1941
|
+
</li>
|
|
1942
|
+
}
|
|
1943
|
+
</ul>
|
|
1944
|
+
</section>
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
<div class="block-stack">
|
|
1948
|
+
@for (block of visibleBlocks(); track block.blockId) {
|
|
1949
|
+
<praxis-editorial-block-renderer
|
|
1950
|
+
[block]="block"
|
|
1951
|
+
[runtimeContext]="resolvedContext()"
|
|
1952
|
+
[solution]="solution()"
|
|
1953
|
+
[instance]="instance()"
|
|
1954
|
+
(operationalEvent)="emitOperationalEvent($event)"
|
|
1955
|
+
/>
|
|
1956
|
+
}
|
|
1957
|
+
</div>
|
|
1958
|
+
|
|
1959
|
+
@if (journey.steps.length > 1) {
|
|
1960
|
+
<footer class="step-actions">
|
|
1961
|
+
<button type="button" (click)="goToPreviousStep()" [disabled]="!hasPreviousStep()">
|
|
1962
|
+
Etapa anterior
|
|
1963
|
+
</button>
|
|
1964
|
+
<button
|
|
1965
|
+
type="button"
|
|
1966
|
+
(click)="goToNextStep()"
|
|
1967
|
+
[disabled]="!hasNextStep() || isForwardNavigationBlocked()"
|
|
1968
|
+
[attr.aria-describedby]="isForwardNavigationBlocked() ? 'navigation-blocking-note' : null"
|
|
1969
|
+
>
|
|
1970
|
+
{{ isForwardNavigationBlocked() ? 'Corrija os erros para avancar' : 'Proxima etapa' }}
|
|
1971
|
+
</button>
|
|
1972
|
+
</footer>
|
|
1973
|
+
@if (isForwardNavigationBlocked()) {
|
|
1974
|
+
<p id="navigation-blocking-note" class="step-blocking-note">
|
|
1975
|
+
{{ navigationBlockingMessage() }}
|
|
1976
|
+
</p>
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
</section>
|
|
1980
|
+
}
|
|
1981
|
+
</section>
|
|
1982
|
+
} @else {
|
|
1983
|
+
<section class="empty-state">
|
|
1984
|
+
<h2>Editorial runtime sem jornada</h2>
|
|
1985
|
+
<p>Nenhuma jornada editorial foi resolvida para o estado atual.</p>
|
|
1986
|
+
</section>
|
|
1987
|
+
}
|
|
1988
|
+
} @else {
|
|
1989
|
+
<section class="empty-state">
|
|
1990
|
+
<h2>Editorial runtime vazio</h2>
|
|
1991
|
+
<p>Forneca uma solution ou instance editorial para materializar a jornada.</p>
|
|
1992
|
+
</section>
|
|
1993
|
+
}
|
|
1994
|
+
</section>
|
|
1995
|
+
`, isInline: true, styles: [":host{display:block}.editorial-runtime{display:grid;gap:24px;padding:24px;color:var(--md-sys-color-on-surface, #1b1b1f);background:var(--md-sys-color-surface, #fdf8fd)}.runtime-header,.journey-card,.empty-state,.diagnostics-panel{border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent);border-radius:20px;background:var(--md-sys-color-surface-container-low, #f7f2fa);padding:20px}.diagnostics-panel{display:grid;gap:10px}.diagnostics-panel.warning{border-color:color-mix(in srgb,#b26a00 55%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fff4de 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-panel.error{border-color:color-mix(in srgb,#b3261e 60%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fde7e9 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-list{margin:0;padding-left:18px;display:grid;gap:8px}.diagnostics-summary{display:flex;flex-wrap:wrap;gap:8px}.summary-pill{display:inline-flex;align-items:center;min-height:32px;padding:6px 10px;border-radius:999px;font-size:.85rem;border:1px solid transparent;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 85%,transparent)}.summary-pill.error{border-color:color-mix(in srgb,#b3261e 45%,transparent)}.summary-pill.warning{border-color:color-mix(in srgb,#b26a00 45%,transparent)}.summary-pill.info{border-color:color-mix(in srgb,#00639b 45%,transparent)}.status-badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;min-height:22px;padding:0 6px;border-radius:999px;font-size:.75rem;font-weight:700;background:var(--md-sys-color-surface, #fff)}.status-badge.error{color:#8c1d18;background:#fde7e9}.status-badge.warning{color:#7a4b00;background:#fff4de}.diagnostics-details summary{cursor:pointer;font-weight:600}.diagnostic-group{display:grid;gap:8px;padding:12px 0}.diagnostic-group.global{border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent);margin-bottom:12px}.step-panel.error{border-left:4px solid #b3261e}.step-panel.warning{border-left:4px solid #b26a00}.step-diagnostics{display:grid;gap:8px;padding:14px 16px;border-radius:16px}.step-diagnostics.error{background:#fde7e9;color:#5b1210}.step-diagnostics.warning{background:#fff4de;color:#6b4300}.step-diagnostics.global{background:#fde7e9;color:#5b1210;border:1px solid color-mix(in srgb,#b3261e 35%,transparent)}.diagnostics-list.contextual{padding-left:16px}.diagnostic-location{display:block;margin-top:4px;font-size:.82rem;opacity:.85}.step-blocking-note{font-size:.9rem;color:#8c1d18}.eyebrow{margin:0 0 8px;text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;color:var(--md-sys-color-primary, #6750a4);font-weight:700}.runtime-state-pill{justify-self:start;display:inline-flex;align-items:center;min-height:30px;padding:4px 10px;border-radius:999px;font-size:.8rem;font-weight:700;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 88%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent)}.runtime-state-pill[data-mode=warning]{color:#7a4b00;background:#fff4de}.runtime-state-pill[data-mode=degraded]{color:#8c1d18;background:#fde7e9}.runtime-state-pill[data-mode=blocked]{color:#8c1d18;background:#fde7e9;border-color:color-mix(in srgb,#b3261e 55%,transparent)}h1,h2,h3,p{margin:0}.runtime-header,.journey-card,.journey-header,.step-panel{display:grid;gap:12px}.description,.journey-header p,.step-header p,.step-counter,.empty-state p{color:var(--md-sys-color-on-surface-variant, #49454f)}.journey-tabs,.steps-nav,.step-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.steps-nav{list-style:none;padding:0;margin:0}.journey-tab,.step-chip,.step-actions button{display:inline-flex;align-items:center;justify-content:center;min-height:42px;padding:10px 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 75%,transparent);background:var(--md-sys-color-surface, #fff);color:inherit;cursor:pointer}.journey-tab.active,.step-chip.active{background:var(--md-sys-color-primary, #6750a4);color:var(--md-sys-color-on-primary, #fff)}.step-header{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between}.block-stack{display:grid;gap:16px}.step-actions button[disabled]{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: EditorialBlockRendererComponent, selector: "praxis-editorial-block-renderer", inputs: ["block", "runtimeContext", "solution", "instance"], outputs: ["operationalEvent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1996
|
+
}
|
|
1997
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialFormRuntimeComponent, decorators: [{
|
|
1998
|
+
type: Component,
|
|
1999
|
+
args: [{ selector: 'praxis-editorial-form-runtime', standalone: true, imports: [CommonModule, EditorialBlockRendererComponent], template: `
|
|
2000
|
+
<section class="editorial-runtime">
|
|
2001
|
+
@if (runtimeDiagnostics().items.length) {
|
|
2002
|
+
<section
|
|
2003
|
+
class="diagnostics-panel"
|
|
2004
|
+
[class.error]="runtimeDiagnostics().hasErrors"
|
|
2005
|
+
[class.warning]="runtimeDiagnostics().hasWarnings"
|
|
2006
|
+
[attr.role]="runtimeDiagnostics().hasErrors ? 'alert' : 'status'"
|
|
2007
|
+
[attr.aria-live]="runtimeDiagnostics().hasErrors ? 'assertive' : 'polite'"
|
|
2008
|
+
aria-atomic="true"
|
|
2009
|
+
>
|
|
2010
|
+
<h2>Diagnosticos do runtime</h2>
|
|
2011
|
+
<p>{{ diagnosticsMessage() }}</p>
|
|
2012
|
+
<div class="diagnostics-summary" aria-label="Resumo de severidade">
|
|
2013
|
+
<span class="summary-pill error">Erros: {{ diagnosticsErrorCount() }}</span>
|
|
2014
|
+
<span class="summary-pill warning">Avisos: {{ diagnosticsWarningCount() }}</span>
|
|
2015
|
+
<span class="summary-pill info">Infos: {{ diagnosticsInfoCount() }}</span>
|
|
2016
|
+
</div>
|
|
2017
|
+
<details class="diagnostics-details">
|
|
2018
|
+
<summary>Ver detalhes ({{ diagnosticItems().length }})</summary>
|
|
2019
|
+
@if (globalDiagnostics().length) {
|
|
2020
|
+
<section class="diagnostic-group global" aria-label="Erros globais do runtime">
|
|
2021
|
+
<h3>Erros globais do runtime</h3>
|
|
2022
|
+
<ul class="diagnostics-list">
|
|
2023
|
+
@for (item of globalDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
|
|
2024
|
+
<li>
|
|
2025
|
+
<strong>{{ formatDiagnosticSeverity(item) }}:</strong>
|
|
2026
|
+
{{ item.message }}
|
|
2027
|
+
@if (formatDiagnosticScope(item); as scope) {
|
|
2028
|
+
<span class="diagnostic-location">{{ scope }}</span>
|
|
2029
|
+
}
|
|
2030
|
+
</li>
|
|
2031
|
+
}
|
|
2032
|
+
</ul>
|
|
2033
|
+
</section>
|
|
2034
|
+
}
|
|
2035
|
+
<ul class="diagnostics-list">
|
|
2036
|
+
@for (item of contextualDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
|
|
2037
|
+
<li>
|
|
2038
|
+
<strong>{{ formatDiagnosticSeverity(item) }}:</strong>
|
|
2039
|
+
{{ item.message }}
|
|
2040
|
+
@if (formatDiagnosticScope(item); as scope) {
|
|
2041
|
+
<span class="diagnostic-location">{{ scope }}</span>
|
|
2042
|
+
}
|
|
2043
|
+
</li>
|
|
2044
|
+
}
|
|
2045
|
+
</ul>
|
|
2046
|
+
</details>
|
|
2047
|
+
</section>
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
@if (runtimeTitle(); as title) {
|
|
2051
|
+
<header class="runtime-header">
|
|
2052
|
+
<span class="runtime-state-pill" [attr.data-mode]="fallbackState().mode">
|
|
2053
|
+
{{ fallbackLabel() }}
|
|
2054
|
+
</span>
|
|
2055
|
+
@if (runtimeEyebrow()) {
|
|
2056
|
+
<p class="eyebrow">{{ runtimeEyebrow() }}</p>
|
|
2057
|
+
}
|
|
2058
|
+
<h1>{{ title }}</h1>
|
|
2059
|
+
@if (runtimeDescription()) {
|
|
2060
|
+
<p class="description">{{ runtimeDescription() }}</p>
|
|
2061
|
+
}
|
|
2062
|
+
</header>
|
|
2063
|
+
|
|
2064
|
+
@if (journeys().length > 1) {
|
|
2065
|
+
<nav class="journey-tabs" aria-label="Jornadas editoriais">
|
|
2066
|
+
@for (journey of journeys(); track journey.journeyId) {
|
|
2067
|
+
<button
|
|
2068
|
+
type="button"
|
|
2069
|
+
class="journey-tab"
|
|
2070
|
+
[class.active]="activeJourney()?.journeyId === journey.journeyId"
|
|
2071
|
+
[disabled]="isJourneySelectionBlocked(journey.journeyId)"
|
|
2072
|
+
[attr.aria-describedby]="isJourneySelectionBlocked(journey.journeyId) ? 'navigation-blocking-note' : null"
|
|
2073
|
+
(click)="selectJourney(journey.journeyId)"
|
|
2074
|
+
>
|
|
2075
|
+
{{ journey.label }}
|
|
2076
|
+
@if (journeyErrorCount(journey.journeyId)) {
|
|
2077
|
+
<span class="status-badge error" aria-label="Jornada com erros">
|
|
2078
|
+
{{ journeyErrorCount(journey.journeyId) }}
|
|
2079
|
+
</span>
|
|
2080
|
+
} @else if (journeyWarningCount(journey.journeyId)) {
|
|
2081
|
+
<span class="status-badge warning" aria-label="Jornada com avisos">
|
|
2082
|
+
{{ journeyWarningCount(journey.journeyId) }}
|
|
2083
|
+
</span>
|
|
2084
|
+
}
|
|
2085
|
+
</button>
|
|
2086
|
+
}
|
|
2087
|
+
</nav>
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
@if (activeJourney(); as journey) {
|
|
2091
|
+
<section class="journey-card">
|
|
2092
|
+
<header class="journey-header">
|
|
2093
|
+
<h2>{{ journey.label }}</h2>
|
|
2094
|
+
@if (journey.description) {
|
|
2095
|
+
<p>{{ journey.description }}</p>
|
|
2096
|
+
}
|
|
2097
|
+
</header>
|
|
2098
|
+
|
|
2099
|
+
@if (journey.steps.length > 1) {
|
|
2100
|
+
<ol class="steps-nav" aria-label="Etapas da jornada">
|
|
2101
|
+
@for (step of journey.steps; track step.stepId) {
|
|
2102
|
+
<li>
|
|
2103
|
+
<button
|
|
2104
|
+
type="button"
|
|
2105
|
+
class="step-chip"
|
|
2106
|
+
[class.active]="activeStep()?.stepId === step.stepId"
|
|
2107
|
+
[disabled]="isStepSelectionBlocked(step.stepId)"
|
|
2108
|
+
[attr.aria-describedby]="isStepSelectionBlocked(step.stepId) ? 'navigation-blocking-note' : null"
|
|
2109
|
+
(click)="selectStep(step.stepId)"
|
|
2110
|
+
>
|
|
2111
|
+
{{ step.label }}
|
|
2112
|
+
@if (stepErrorCount(step.stepId)) {
|
|
2113
|
+
<span class="status-badge error" aria-label="Etapa com erros">
|
|
2114
|
+
{{ stepErrorCount(step.stepId) }}
|
|
2115
|
+
</span>
|
|
2116
|
+
} @else if (stepWarningCount(step.stepId)) {
|
|
2117
|
+
<span class="status-badge warning" aria-label="Etapa com avisos">
|
|
2118
|
+
{{ stepWarningCount(step.stepId) }}
|
|
2119
|
+
</span>
|
|
2120
|
+
}
|
|
2121
|
+
</button>
|
|
2122
|
+
</li>
|
|
2123
|
+
}
|
|
2124
|
+
</ol>
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
@if (activeStep(); as step) {
|
|
2128
|
+
<section
|
|
2129
|
+
class="step-panel"
|
|
2130
|
+
[class.error]="activeStepHasErrors() || activeGlobalDiagnostics().length"
|
|
2131
|
+
[class.warning]="!activeStepHasErrors() && !activeGlobalDiagnostics().length && activeStepHasWarnings()"
|
|
2132
|
+
>
|
|
2133
|
+
<header class="step-header">
|
|
2134
|
+
<div>
|
|
2135
|
+
<h3>{{ step.label }}</h3>
|
|
2136
|
+
@if (step.description) {
|
|
2137
|
+
<p>{{ step.description }}</p>
|
|
2138
|
+
}
|
|
2139
|
+
</div>
|
|
2140
|
+
<div class="step-counter">
|
|
2141
|
+
Etapa {{ currentStepIndex() + 1 }} de {{ journey.steps.length }}
|
|
2142
|
+
</div>
|
|
2143
|
+
</header>
|
|
2144
|
+
|
|
2145
|
+
@if (activeStepDiagnostics().length) {
|
|
2146
|
+
<section
|
|
2147
|
+
class="step-diagnostics"
|
|
2148
|
+
[class.error]="activeStepHasErrors()"
|
|
2149
|
+
[class.warning]="!activeStepHasErrors() && activeStepHasWarnings()"
|
|
2150
|
+
[attr.role]="activeStepHasErrors() ? 'alert' : 'status'"
|
|
2151
|
+
[attr.aria-live]="activeStepHasErrors() ? 'assertive' : 'polite'"
|
|
2152
|
+
aria-atomic="true"
|
|
2153
|
+
>
|
|
2154
|
+
<h4>Situacao desta etapa</h4>
|
|
2155
|
+
<ul class="diagnostics-list contextual">
|
|
2156
|
+
@for (item of activeStepDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
|
|
2157
|
+
<li>
|
|
2158
|
+
<strong>{{ formatDiagnosticSeverity(item) }}:</strong>
|
|
2159
|
+
{{ item.message }}
|
|
2160
|
+
@if (formatDiagnosticScope(item); as scope) {
|
|
2161
|
+
<span class="diagnostic-location">{{ scope }}</span>
|
|
2162
|
+
}
|
|
2163
|
+
</li>
|
|
2164
|
+
}
|
|
2165
|
+
</ul>
|
|
2166
|
+
</section>
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
@if (activeGlobalDiagnostics().length) {
|
|
2170
|
+
<section
|
|
2171
|
+
class="step-diagnostics global"
|
|
2172
|
+
role="alert"
|
|
2173
|
+
aria-live="assertive"
|
|
2174
|
+
aria-atomic="true"
|
|
2175
|
+
>
|
|
2176
|
+
<h4>Erro global do runtime</h4>
|
|
2177
|
+
<ul class="diagnostics-list contextual">
|
|
2178
|
+
@for (item of activeGlobalDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
|
|
2179
|
+
<li>
|
|
2180
|
+
<strong>{{ formatDiagnosticSeverity(item) }}:</strong>
|
|
2181
|
+
{{ item.message }}
|
|
2182
|
+
@if (formatDiagnosticScope(item); as scope) {
|
|
2183
|
+
<span class="diagnostic-location">{{ scope }}</span>
|
|
2184
|
+
}
|
|
2185
|
+
</li>
|
|
2186
|
+
}
|
|
2187
|
+
</ul>
|
|
2188
|
+
</section>
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
<div class="block-stack">
|
|
2192
|
+
@for (block of visibleBlocks(); track block.blockId) {
|
|
2193
|
+
<praxis-editorial-block-renderer
|
|
2194
|
+
[block]="block"
|
|
2195
|
+
[runtimeContext]="resolvedContext()"
|
|
2196
|
+
[solution]="solution()"
|
|
2197
|
+
[instance]="instance()"
|
|
2198
|
+
(operationalEvent)="emitOperationalEvent($event)"
|
|
2199
|
+
/>
|
|
2200
|
+
}
|
|
2201
|
+
</div>
|
|
2202
|
+
|
|
2203
|
+
@if (journey.steps.length > 1) {
|
|
2204
|
+
<footer class="step-actions">
|
|
2205
|
+
<button type="button" (click)="goToPreviousStep()" [disabled]="!hasPreviousStep()">
|
|
2206
|
+
Etapa anterior
|
|
2207
|
+
</button>
|
|
2208
|
+
<button
|
|
2209
|
+
type="button"
|
|
2210
|
+
(click)="goToNextStep()"
|
|
2211
|
+
[disabled]="!hasNextStep() || isForwardNavigationBlocked()"
|
|
2212
|
+
[attr.aria-describedby]="isForwardNavigationBlocked() ? 'navigation-blocking-note' : null"
|
|
2213
|
+
>
|
|
2214
|
+
{{ isForwardNavigationBlocked() ? 'Corrija os erros para avancar' : 'Proxima etapa' }}
|
|
2215
|
+
</button>
|
|
2216
|
+
</footer>
|
|
2217
|
+
@if (isForwardNavigationBlocked()) {
|
|
2218
|
+
<p id="navigation-blocking-note" class="step-blocking-note">
|
|
2219
|
+
{{ navigationBlockingMessage() }}
|
|
2220
|
+
</p>
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
</section>
|
|
2224
|
+
}
|
|
2225
|
+
</section>
|
|
2226
|
+
} @else {
|
|
2227
|
+
<section class="empty-state">
|
|
2228
|
+
<h2>Editorial runtime sem jornada</h2>
|
|
2229
|
+
<p>Nenhuma jornada editorial foi resolvida para o estado atual.</p>
|
|
2230
|
+
</section>
|
|
2231
|
+
}
|
|
2232
|
+
} @else {
|
|
2233
|
+
<section class="empty-state">
|
|
2234
|
+
<h2>Editorial runtime vazio</h2>
|
|
2235
|
+
<p>Forneca uma solution ou instance editorial para materializar a jornada.</p>
|
|
2236
|
+
</section>
|
|
2237
|
+
}
|
|
2238
|
+
</section>
|
|
2239
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.editorial-runtime{display:grid;gap:24px;padding:24px;color:var(--md-sys-color-on-surface, #1b1b1f);background:var(--md-sys-color-surface, #fdf8fd)}.runtime-header,.journey-card,.empty-state,.diagnostics-panel{border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent);border-radius:20px;background:var(--md-sys-color-surface-container-low, #f7f2fa);padding:20px}.diagnostics-panel{display:grid;gap:10px}.diagnostics-panel.warning{border-color:color-mix(in srgb,#b26a00 55%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fff4de 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-panel.error{border-color:color-mix(in srgb,#b3261e 60%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fde7e9 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-list{margin:0;padding-left:18px;display:grid;gap:8px}.diagnostics-summary{display:flex;flex-wrap:wrap;gap:8px}.summary-pill{display:inline-flex;align-items:center;min-height:32px;padding:6px 10px;border-radius:999px;font-size:.85rem;border:1px solid transparent;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 85%,transparent)}.summary-pill.error{border-color:color-mix(in srgb,#b3261e 45%,transparent)}.summary-pill.warning{border-color:color-mix(in srgb,#b26a00 45%,transparent)}.summary-pill.info{border-color:color-mix(in srgb,#00639b 45%,transparent)}.status-badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;min-height:22px;padding:0 6px;border-radius:999px;font-size:.75rem;font-weight:700;background:var(--md-sys-color-surface, #fff)}.status-badge.error{color:#8c1d18;background:#fde7e9}.status-badge.warning{color:#7a4b00;background:#fff4de}.diagnostics-details summary{cursor:pointer;font-weight:600}.diagnostic-group{display:grid;gap:8px;padding:12px 0}.diagnostic-group.global{border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent);margin-bottom:12px}.step-panel.error{border-left:4px solid #b3261e}.step-panel.warning{border-left:4px solid #b26a00}.step-diagnostics{display:grid;gap:8px;padding:14px 16px;border-radius:16px}.step-diagnostics.error{background:#fde7e9;color:#5b1210}.step-diagnostics.warning{background:#fff4de;color:#6b4300}.step-diagnostics.global{background:#fde7e9;color:#5b1210;border:1px solid color-mix(in srgb,#b3261e 35%,transparent)}.diagnostics-list.contextual{padding-left:16px}.diagnostic-location{display:block;margin-top:4px;font-size:.82rem;opacity:.85}.step-blocking-note{font-size:.9rem;color:#8c1d18}.eyebrow{margin:0 0 8px;text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;color:var(--md-sys-color-primary, #6750a4);font-weight:700}.runtime-state-pill{justify-self:start;display:inline-flex;align-items:center;min-height:30px;padding:4px 10px;border-radius:999px;font-size:.8rem;font-weight:700;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 88%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent)}.runtime-state-pill[data-mode=warning]{color:#7a4b00;background:#fff4de}.runtime-state-pill[data-mode=degraded]{color:#8c1d18;background:#fde7e9}.runtime-state-pill[data-mode=blocked]{color:#8c1d18;background:#fde7e9;border-color:color-mix(in srgb,#b3261e 55%,transparent)}h1,h2,h3,p{margin:0}.runtime-header,.journey-card,.journey-header,.step-panel{display:grid;gap:12px}.description,.journey-header p,.step-header p,.step-counter,.empty-state p{color:var(--md-sys-color-on-surface-variant, #49454f)}.journey-tabs,.steps-nav,.step-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.steps-nav{list-style:none;padding:0;margin:0}.journey-tab,.step-chip,.step-actions button{display:inline-flex;align-items:center;justify-content:center;min-height:42px;padding:10px 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 75%,transparent);background:var(--md-sys-color-surface, #fff);color:inherit;cursor:pointer}.journey-tab.active,.step-chip.active{background:var(--md-sys-color-primary, #6750a4);color:var(--md-sys-color-on-primary, #fff)}.step-header{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between}.block-stack{display:grid;gap:16px}.step-actions button[disabled]{opacity:.5;cursor:not-allowed}\n"] }]
|
|
2240
|
+
}], ctorParameters: () => [], propDecorators: { solution: [{ type: i0.Input, args: [{ isSignal: true, alias: "solution", required: false }] }], instance: [{ type: i0.Input, args: [{ isSignal: true, alias: "instance", required: false }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }], hostConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "hostConfig", required: false }] }], snapshotChange: [{ type: i0.Output, args: ["snapshotChange"] }], fallbackChange: [{ type: i0.Output, args: ["fallbackChange"] }], operationalEvent: [{ type: i0.Output, args: ["operationalEvent"] }] } });
|
|
2241
|
+
function buildSnapshotSignature(snapshot) {
|
|
2242
|
+
return [
|
|
2243
|
+
snapshot.solutionId ?? '',
|
|
2244
|
+
snapshot.instanceId ?? '',
|
|
2245
|
+
snapshot.journeys.length,
|
|
2246
|
+
snapshot.diagnostics.items.length,
|
|
2247
|
+
snapshot.diagnostics.hasErrors,
|
|
2248
|
+
snapshot.diagnostics.hasWarnings,
|
|
2249
|
+
].join(':');
|
|
2250
|
+
}
|
|
2251
|
+
function dedupeDiagnostics(items) {
|
|
2252
|
+
const seen = new Set();
|
|
2253
|
+
const deduped = [];
|
|
2254
|
+
for (const item of items) {
|
|
2255
|
+
const key = `${item.severity}:${item.code}:${item.journeyId ?? ''}:${item.stepId ?? ''}:${item.blockId ?? ''}:${item.path ?? item.message}`;
|
|
2256
|
+
if (seen.has(key)) {
|
|
2257
|
+
continue;
|
|
2258
|
+
}
|
|
2259
|
+
seen.add(key);
|
|
2260
|
+
deduped.push(item);
|
|
2261
|
+
}
|
|
2262
|
+
return deduped;
|
|
2263
|
+
}
|
|
2264
|
+
function sortDiagnostics(items) {
|
|
2265
|
+
return [...items].sort((left, right) => {
|
|
2266
|
+
const severityScore = getSeverityScore(left.severity) - getSeverityScore(right.severity);
|
|
2267
|
+
if (severityScore !== 0) {
|
|
2268
|
+
return severityScore;
|
|
2269
|
+
}
|
|
2270
|
+
const scopeScore = getScopeScore(left.scopeKind) - getScopeScore(right.scopeKind);
|
|
2271
|
+
if (scopeScore !== 0) {
|
|
2272
|
+
return scopeScore;
|
|
2273
|
+
}
|
|
2274
|
+
return `${left.journeyLabel ?? left.journeyId ?? ''}${left.stepLabel ?? left.stepId ?? ''}${left.blockLabel ?? left.blockId ?? ''}${left.path ?? ''}`
|
|
2275
|
+
.localeCompare(`${right.journeyLabel ?? right.journeyId ?? ''}${right.stepLabel ?? right.stepId ?? ''}${right.blockLabel ?? right.blockId ?? ''}${right.path ?? ''}`);
|
|
2276
|
+
});
|
|
2277
|
+
}
|
|
2278
|
+
function getSeverityScore(severity) {
|
|
2279
|
+
if (severity === 'error') {
|
|
2280
|
+
return 0;
|
|
2281
|
+
}
|
|
2282
|
+
if (severity === 'warning') {
|
|
2283
|
+
return 1;
|
|
2284
|
+
}
|
|
2285
|
+
return 2;
|
|
2286
|
+
}
|
|
2287
|
+
function getScopeScore(scopeKind) {
|
|
2288
|
+
if (scopeKind === 'global') {
|
|
2289
|
+
return 0;
|
|
2290
|
+
}
|
|
2291
|
+
if (scopeKind === 'journey') {
|
|
2292
|
+
return 1;
|
|
2293
|
+
}
|
|
2294
|
+
if (scopeKind === 'step') {
|
|
2295
|
+
return 2;
|
|
2296
|
+
}
|
|
2297
|
+
return 3;
|
|
2298
|
+
}
|
|
2299
|
+
function isDiagnosticInActiveStep(item, journeyId, stepId) {
|
|
2300
|
+
if (!journeyId || !stepId) {
|
|
2301
|
+
return false;
|
|
2302
|
+
}
|
|
2303
|
+
return item.journeyId === journeyId && item.stepId === stepId;
|
|
2304
|
+
}
|
|
2305
|
+
function formatScopeLabel(labelName, label, id) {
|
|
2306
|
+
if (label && id && label !== id) {
|
|
2307
|
+
return `${labelName}: ${label} (${id})`;
|
|
2308
|
+
}
|
|
2309
|
+
if (label) {
|
|
2310
|
+
return `${labelName}: ${label}`;
|
|
2311
|
+
}
|
|
2312
|
+
if (id) {
|
|
2313
|
+
return `${labelName}: ${id}`;
|
|
2314
|
+
}
|
|
2315
|
+
return null;
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
const REQUIRED_DYNAMIC_FORM_INPUTS = ['config', 'formId', 'editorialContext'];
|
|
2319
|
+
function createEditorialDynamicFormAdapter(options) {
|
|
2320
|
+
return {
|
|
2321
|
+
adapterId: 'dynamic-form',
|
|
2322
|
+
displayName: 'Praxis Dynamic Form',
|
|
2323
|
+
supports(_context) {
|
|
2324
|
+
return true;
|
|
2325
|
+
},
|
|
2326
|
+
resolveComponent() {
|
|
2327
|
+
return options.component;
|
|
2328
|
+
},
|
|
2329
|
+
buildInputs(context) {
|
|
2330
|
+
return {
|
|
2331
|
+
config: context.resolvedFormConfig,
|
|
2332
|
+
formId: context.block.formBlockId,
|
|
2333
|
+
editorialContext: context.runtimeContext,
|
|
2334
|
+
};
|
|
2335
|
+
},
|
|
2336
|
+
validateComponent(component) {
|
|
2337
|
+
const mirror = reflectComponentType(component);
|
|
2338
|
+
if (!mirror) {
|
|
2339
|
+
return {
|
|
2340
|
+
ok: false,
|
|
2341
|
+
reason: 'O componente informado nao parece ser um componente Angular valido para o adaptador dynamic-form.',
|
|
2342
|
+
};
|
|
2343
|
+
}
|
|
2344
|
+
const availableInputs = new Set(mirror.inputs.map((input) => input.propName));
|
|
2345
|
+
const missingInputs = REQUIRED_DYNAMIC_FORM_INPUTS.filter((inputName) => !availableInputs.has(inputName));
|
|
2346
|
+
if (missingInputs.length) {
|
|
2347
|
+
return {
|
|
2348
|
+
ok: false,
|
|
2349
|
+
reason: `O componente informado nao segue a convencao do adapter dynamic-form. Inputs ausentes: ${missingInputs.join(', ')}.`,
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
return { ok: true };
|
|
2353
|
+
},
|
|
2354
|
+
};
|
|
2355
|
+
}
|
|
2356
|
+
function provideEditorialDynamicFormAdapter(options) {
|
|
2357
|
+
return provideEditorialDataBlockAdapter(createEditorialDynamicFormAdapter(options));
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
class HarnessDataEngineComponent {
|
|
2361
|
+
config;
|
|
2362
|
+
formId;
|
|
2363
|
+
editorialContext = null;
|
|
2364
|
+
block = null;
|
|
2365
|
+
runtimeContext = null;
|
|
2366
|
+
solution = null;
|
|
2367
|
+
instance = null;
|
|
2368
|
+
resolvedFormConfig = null;
|
|
2369
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: HarnessDataEngineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2370
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: HarnessDataEngineComponent, isStandalone: true, selector: "praxis-editorial-harness-data-engine", inputs: { config: "config", formId: "formId", editorialContext: "editorialContext", block: "block", runtimeContext: "runtimeContext", solution: "solution", instance: "instance", resolvedFormConfig: "resolvedFormConfig" }, ngImport: i0, template: '<p>Harness data engine</p>', isInline: true });
|
|
2371
|
+
}
|
|
2372
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: HarnessDataEngineComponent, decorators: [{
|
|
2373
|
+
type: Component,
|
|
2374
|
+
args: [{
|
|
2375
|
+
standalone: true,
|
|
2376
|
+
selector: 'praxis-editorial-harness-data-engine',
|
|
2377
|
+
template: '<p>Harness data engine</p>',
|
|
2378
|
+
}]
|
|
2379
|
+
}], propDecorators: { config: [{
|
|
2380
|
+
type: Input
|
|
2381
|
+
}], formId: [{
|
|
2382
|
+
type: Input
|
|
2383
|
+
}], editorialContext: [{
|
|
2384
|
+
type: Input
|
|
2385
|
+
}], block: [{
|
|
2386
|
+
type: Input
|
|
2387
|
+
}], runtimeContext: [{
|
|
2388
|
+
type: Input
|
|
2389
|
+
}], solution: [{
|
|
2390
|
+
type: Input
|
|
2391
|
+
}], instance: [{
|
|
2392
|
+
type: Input
|
|
2393
|
+
}], resolvedFormConfig: [{
|
|
2394
|
+
type: Input
|
|
2395
|
+
}] } });
|
|
2396
|
+
function createEditorialRuntimeHarnessCatalog() {
|
|
2397
|
+
const warningSolution = {
|
|
2398
|
+
solutionId: 'solution-warning',
|
|
2399
|
+
version: '1.0.0',
|
|
2400
|
+
problemType: 'event-registration',
|
|
2401
|
+
title: 'Warning solution',
|
|
2402
|
+
themePresets: [
|
|
2403
|
+
{
|
|
2404
|
+
themeId: 'default-theme',
|
|
2405
|
+
label: 'Default',
|
|
2406
|
+
shellVariant: 'page',
|
|
2407
|
+
},
|
|
2408
|
+
],
|
|
2409
|
+
journeys: [
|
|
2410
|
+
{
|
|
2411
|
+
journeyId: 'journey-warning',
|
|
2412
|
+
label: 'Journey Warning',
|
|
2413
|
+
steps: [
|
|
2414
|
+
{
|
|
2415
|
+
stepId: 'step-warning',
|
|
2416
|
+
label: 'Step Warning',
|
|
2417
|
+
blocks: [
|
|
2418
|
+
{
|
|
2419
|
+
blockId: 'copy-warning',
|
|
2420
|
+
kind: 'richText',
|
|
2421
|
+
content: 'Warning content',
|
|
2422
|
+
},
|
|
2423
|
+
],
|
|
2424
|
+
},
|
|
2425
|
+
],
|
|
2426
|
+
},
|
|
2427
|
+
],
|
|
2428
|
+
};
|
|
2429
|
+
const warningInstance = {
|
|
2430
|
+
instanceId: 'instance-warning',
|
|
2431
|
+
template: {
|
|
2432
|
+
templateId: 'solution-warning',
|
|
2433
|
+
version: '1.0.0',
|
|
2434
|
+
title: 'Warning solution',
|
|
2435
|
+
problemType: 'event-registration',
|
|
2436
|
+
},
|
|
2437
|
+
context: {},
|
|
2438
|
+
journeys: [],
|
|
2439
|
+
overrides: {
|
|
2440
|
+
themePresetId: 'missing-theme',
|
|
2441
|
+
},
|
|
2442
|
+
};
|
|
2443
|
+
const healthyInstance = {
|
|
2444
|
+
instanceId: 'instance-healthy',
|
|
2445
|
+
template: {
|
|
2446
|
+
templateId: 'solution-warning',
|
|
2447
|
+
version: '1.0.0',
|
|
2448
|
+
title: 'Warning solution',
|
|
2449
|
+
problemType: 'event-registration',
|
|
2450
|
+
},
|
|
2451
|
+
context: {},
|
|
2452
|
+
journeys: [],
|
|
2453
|
+
};
|
|
2454
|
+
const globalErrorSolution = {
|
|
2455
|
+
solutionId: 'solution-global-error',
|
|
2456
|
+
version: '1.0.0',
|
|
2457
|
+
problemType: 'event-registration',
|
|
2458
|
+
title: 'Global error solution',
|
|
2459
|
+
contextContract: [
|
|
2460
|
+
{
|
|
2461
|
+
key: 'accountContext.user.name',
|
|
2462
|
+
required: true,
|
|
2463
|
+
},
|
|
2464
|
+
],
|
|
2465
|
+
journeys: [
|
|
2466
|
+
{
|
|
2467
|
+
journeyId: 'journey-global',
|
|
2468
|
+
label: 'Journey Global',
|
|
2469
|
+
steps: [
|
|
2470
|
+
{
|
|
2471
|
+
stepId: 'step-global',
|
|
2472
|
+
label: 'Step Global',
|
|
2473
|
+
blocks: [
|
|
2474
|
+
{
|
|
2475
|
+
blockId: 'copy-global',
|
|
2476
|
+
kind: 'richText',
|
|
2477
|
+
content: 'Global error content',
|
|
2478
|
+
},
|
|
2479
|
+
],
|
|
2480
|
+
},
|
|
2481
|
+
],
|
|
2482
|
+
},
|
|
2483
|
+
],
|
|
2484
|
+
};
|
|
2485
|
+
const globalErrorInstance = {
|
|
2486
|
+
instanceId: 'instance-global-error',
|
|
2487
|
+
template: {
|
|
2488
|
+
templateId: 'solution-global-error',
|
|
2489
|
+
version: '1.0.0',
|
|
2490
|
+
title: 'Global error solution',
|
|
2491
|
+
problemType: 'event-registration',
|
|
2492
|
+
},
|
|
2493
|
+
context: {},
|
|
2494
|
+
journeys: [],
|
|
2495
|
+
};
|
|
2496
|
+
const dataCollectionSolution = {
|
|
2497
|
+
solutionId: 'solution-data',
|
|
2498
|
+
version: '1.0.0',
|
|
2499
|
+
problemType: 'event-registration',
|
|
2500
|
+
title: 'Data collection solution',
|
|
2501
|
+
journeys: [
|
|
2502
|
+
{
|
|
2503
|
+
journeyId: 'journey-data',
|
|
2504
|
+
label: 'Journey Data',
|
|
2505
|
+
steps: [
|
|
2506
|
+
{
|
|
2507
|
+
stepId: 'step-data',
|
|
2508
|
+
label: 'Step Data',
|
|
2509
|
+
blocks: [
|
|
2510
|
+
{
|
|
2511
|
+
blockId: 'collect-data',
|
|
2512
|
+
kind: 'dataCollection',
|
|
2513
|
+
formBlockId: 'registration-form',
|
|
2514
|
+
formConfigRef: 'registration-form',
|
|
2515
|
+
},
|
|
2516
|
+
],
|
|
2517
|
+
},
|
|
2518
|
+
],
|
|
2519
|
+
},
|
|
2520
|
+
],
|
|
2521
|
+
};
|
|
2522
|
+
const dataCollectionInstance = {
|
|
2523
|
+
instanceId: 'instance-data',
|
|
2524
|
+
template: {
|
|
2525
|
+
templateId: 'solution-data',
|
|
2526
|
+
version: '1.0.0',
|
|
2527
|
+
title: 'Data collection solution',
|
|
2528
|
+
problemType: 'event-registration',
|
|
2529
|
+
},
|
|
2530
|
+
context: {},
|
|
2531
|
+
journeys: [],
|
|
2532
|
+
overrides: {
|
|
2533
|
+
runtimeFormConfigs: {
|
|
2534
|
+
'registration-form': {
|
|
2535
|
+
sections: [],
|
|
2536
|
+
},
|
|
2537
|
+
},
|
|
2538
|
+
},
|
|
2539
|
+
};
|
|
2540
|
+
return {
|
|
2541
|
+
healthy: {
|
|
2542
|
+
id: 'healthy',
|
|
2543
|
+
title: 'Fixture healthy',
|
|
2544
|
+
input: {
|
|
2545
|
+
solution: warningSolution,
|
|
2546
|
+
instance: healthyInstance,
|
|
2547
|
+
runtimeContext: null,
|
|
2548
|
+
},
|
|
2549
|
+
expectedFallbackMode: 'normal',
|
|
2550
|
+
expectsAdapter: false,
|
|
2551
|
+
},
|
|
2552
|
+
warning: {
|
|
2553
|
+
id: 'warning',
|
|
2554
|
+
title: 'Fixture warning',
|
|
2555
|
+
input: {
|
|
2556
|
+
solution: warningSolution,
|
|
2557
|
+
instance: warningInstance,
|
|
2558
|
+
runtimeContext: null,
|
|
2559
|
+
},
|
|
2560
|
+
expectedFallbackMode: 'warning',
|
|
2561
|
+
expectsAdapter: false,
|
|
2562
|
+
},
|
|
2563
|
+
globalError: {
|
|
2564
|
+
id: 'global-error',
|
|
2565
|
+
title: 'Fixture global error',
|
|
2566
|
+
input: {
|
|
2567
|
+
solution: globalErrorSolution,
|
|
2568
|
+
instance: globalErrorInstance,
|
|
2569
|
+
runtimeContext: null,
|
|
2570
|
+
},
|
|
2571
|
+
expectedFallbackMode: 'blocked',
|
|
2572
|
+
expectsAdapter: false,
|
|
2573
|
+
},
|
|
2574
|
+
dataCollectionMissingAdapter: {
|
|
2575
|
+
id: 'data-collection-missing-adapter',
|
|
2576
|
+
title: 'Fixture dataCollection missing adapter',
|
|
2577
|
+
input: {
|
|
2578
|
+
solution: dataCollectionSolution,
|
|
2579
|
+
instance: dataCollectionInstance,
|
|
2580
|
+
runtimeContext: null,
|
|
2581
|
+
},
|
|
2582
|
+
expectedFallbackMode: 'degraded',
|
|
2583
|
+
expectsAdapter: true,
|
|
2584
|
+
},
|
|
2585
|
+
dataCollectionWithAdapter: {
|
|
2586
|
+
id: 'data-collection-with-adapter',
|
|
2587
|
+
title: 'Fixture dataCollection with adapter',
|
|
2588
|
+
input: {
|
|
2589
|
+
solution: dataCollectionSolution,
|
|
2590
|
+
instance: dataCollectionInstance,
|
|
2591
|
+
runtimeContext: null,
|
|
2592
|
+
},
|
|
2593
|
+
expectedFallbackMode: 'degraded',
|
|
2594
|
+
expectsAdapter: true,
|
|
2595
|
+
},
|
|
2596
|
+
};
|
|
2597
|
+
}
|
|
2598
|
+
function getHarnessDataEngineComponent() {
|
|
2599
|
+
return HarnessDataEngineComponent;
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
/*
|
|
2603
|
+
* Public API Surface of praxis-editorial-forms
|
|
2604
|
+
*/
|
|
2605
|
+
|
|
2606
|
+
/**
|
|
2607
|
+
* Generated bundle index. Do not edit.
|
|
2608
|
+
*/
|
|
2609
|
+
|
|
2610
|
+
export { DEFAULT_EDITORIAL_RUNTIME_HOST_CONFIG, EDITORIAL_DATA_BLOCK_ADAPTER, EditorialBlockRendererComponent, EditorialDataBlockAdapterRegistry, EditorialDataCollectionBlockOutletComponent, EditorialFormRuntimeComponent, EditorialRuntimeState, HarnessDataEngineComponent, createEditorialDynamicFormAdapter, createEditorialRuntimeHarnessCatalog, deriveRuntimeFallbackState, getHarnessDataEngineComponent, getValueAtPath, getVisibleBlocks, isBlockVisible, matchesVisibilityRule, provideEditorialDataBlockAdapter, provideEditorialDynamicFormAdapter, providePraxisEditorialForms, resolveActiveJourney, resolveActiveStep, resolveEditorialDataBlockAdapter, resolveEditorialDataBlockFormConfig, resolveEditorialDataBlockFormConfigDetails, resolveEditorialRuntimeSnapshot };
|
|
2611
|
+
//# sourceMappingURL=praxisui-editorial-forms.mjs.map
|