@acorex-platform/extension-layout-designer-legacy-import-client 0.0.46

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.
@@ -0,0 +1,995 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, Injectable, NgModule } from '@angular/core';
3
+ import { AXP_HOOK_PROVIDER } from '@acorex-platform/framework-client/core';
4
+ import { AXPLayoutDesignerHeaderMenuHookKeys } from '@acorex-platform/framework-client/layout/designer';
5
+ import { AXToastService } from '@acorex/components/toast';
6
+ import { AXFileService } from '@acorex/core/file';
7
+ import { AXTranslationService } from '@acorex/core/translation';
8
+
9
+ //#region ----- Types -----
10
+ //#endregion
11
+ //#region ----- Converter -----
12
+ const SCRIPT_KEYS = ['onInit', 'onValueChange', 'onItemClick', 'onSigned'];
13
+ /**
14
+ * Converts a legacy form-builder page JSON into a designer document
15
+ * (`document-layout` of `page-layout` nodes).
16
+ */
17
+ function convertLegacyFormPage(source) {
18
+ const page = asLegacyWidget(source);
19
+ if (!page || page.name !== 'page') {
20
+ throw new Error('LEGACY_PAGE_EXPECTED');
21
+ }
22
+ const context = new AXEConvertContext();
23
+ const header = [];
24
+ const footer = [];
25
+ const chunks = [[]];
26
+ for (const widget of childWidgets(page)) {
27
+ if (widget.name === 'page-break') {
28
+ chunks.push([]);
29
+ continue;
30
+ }
31
+ if (widget.name === 'page-header') {
32
+ header.push(...stamp(context.convertSequence(childWidgets(widget)), 'header'));
33
+ continue;
34
+ }
35
+ if (widget.name === 'page-footer') {
36
+ footer.push(...stamp(context.convertSequence(childWidgets(widget)), 'footer'));
37
+ continue;
38
+ }
39
+ chunks[chunks.length - 1].push(widget);
40
+ }
41
+ const bodyChunks = chunks.filter((chunk, index) => chunk.length > 0 || (index === 0 && chunks.length === 1));
42
+ const pages = (bodyChunks.length ? bodyChunks : [[]]).map((chunk, index) => context.page(chunk, index, page.options, header, footer));
43
+ return {
44
+ document: {
45
+ type: 'document-layout',
46
+ name: 'document',
47
+ children: pages,
48
+ },
49
+ warnings: context.warnings(),
50
+ };
51
+ }
52
+ //#endregion
53
+ //#region ----- Context -----
54
+ class AXEConvertContext {
55
+ constructor() {
56
+ this.names = new Set();
57
+ this.warningMap = new Map();
58
+ }
59
+ page(chunk, index, pageOptions, header, footer) {
60
+ const direction = stringOption(pageOptions, 'pageDirection');
61
+ const background = colorOption(pageOptions, 'bgColor');
62
+ return {
63
+ type: 'page-layout',
64
+ name: this.uniqueName(index === 0 ? 'page' : `page${index + 1}`, 'page-layout'),
65
+ options: {
66
+ hasHeader: header.length > 0 || pageOptions?.['showHeader'] === true,
67
+ hasFooter: footer.length > 0 || pageOptions?.['showFooter'] === true,
68
+ ...(direction === 'rtl' || direction === 'ltr' ? { direction } : {}),
69
+ ...(background ? { backgroundColor: background } : {}),
70
+ },
71
+ children: [...header, ...this.convertSequence(chunk), ...footer],
72
+ };
73
+ }
74
+ convertSequence(widgets) {
75
+ const nodes = [];
76
+ let rows = [];
77
+ const flushRows = () => {
78
+ if (!rows.length) {
79
+ return;
80
+ }
81
+ nodes.push(this.tableFromRows(rows, undefined));
82
+ rows = [];
83
+ };
84
+ for (const widget of widgets) {
85
+ if (widget.name === 'table-row') {
86
+ rows.push(widget);
87
+ continue;
88
+ }
89
+ flushRows();
90
+ const converted = this.convertWidget(widget);
91
+ if (converted) {
92
+ nodes.push(converted);
93
+ }
94
+ }
95
+ flushRows();
96
+ return nodes;
97
+ }
98
+ warnings() {
99
+ return [...this.warningMap.entries()].map(([code, entry]) => ({
100
+ code,
101
+ count: entry.count,
102
+ samples: entry.samples,
103
+ }));
104
+ }
105
+ convertWidget(widget) {
106
+ this.noteScripts(widget);
107
+ const options = widget.options ?? {};
108
+ switch (widget.name) {
109
+ case 'row':
110
+ return this.row(widget);
111
+ case 'col':
112
+ return this.column(widget);
113
+ case 'table':
114
+ return this.tableFromRows(childWidgets(widget).filter((child) => child.name === 'table-row'), widget);
115
+ case 'container':
116
+ return this.stack(widget);
117
+ case 'repeater':
118
+ return this.repeater(widget);
119
+ case 'text':
120
+ case 'text-heading':
121
+ return this.text(widget);
122
+ case 'textbox':
123
+ return this.editor(widget, this.editorType(options));
124
+ case 'textarea':
125
+ return this.editor(widget, 'large-text-editor');
126
+ case 'list':
127
+ case 'listsecond':
128
+ return this.choice(widget, 'selection-list-editor');
129
+ case 'dropdown':
130
+ return this.choice(widget, 'select-editor');
131
+ case 'date-input':
132
+ return this.editor(widget, 'date-time-editor', { format: { id: 'date', title: 'Date' } });
133
+ case 'time-input':
134
+ return this.editor(widget, 'date-time-editor', { format: { id: 'time', title: 'Time' } });
135
+ case 'signature':
136
+ return this.editor(widget, 'signature');
137
+ case 'image':
138
+ return this.image(widget);
139
+ case 'image-input':
140
+ this.warn('image-input', fieldName(widget) || 'image-input');
141
+ return this.placeholder('Image input was not converted');
142
+ case 'outlet':
143
+ this.warn('outlet', String(options['widgetId'] ?? (fieldName(widget) || 'outlet')));
144
+ return this.placeholder(`Embedded form ${String(options['widgetId'] ?? '')} was not converted`.trim());
145
+ case 'page':
146
+ case 'page-break':
147
+ case 'page-header':
148
+ case 'page-footer':
149
+ case 'table-row':
150
+ case 'table-cell':
151
+ return null;
152
+ default:
153
+ this.warn('unknown-widget', widget.name || 'unknown');
154
+ return this.placeholder(`Unsupported widget: ${widget.name || 'unknown'}`);
155
+ }
156
+ }
157
+ row(widget) {
158
+ const columns = childWidgets(widget).map((child) => child.name === 'col' ? child : { name: 'col', options: { size: 12, widgets: [child] } });
159
+ const sizes = columns.map((col) => Math.max(1, numberOption(col.options, 'size') ?? 12));
160
+ const total = sizes.reduce((sum, size) => sum + size, 0) || 1;
161
+ const rowBackground = colorOption(widget.options, 'bgColor');
162
+ const borderItems = borderItemsFromWidget(widget) ?? borderItemsFromWidgets(columns);
163
+ return {
164
+ type: 'table-layout',
165
+ name: this.uniqueName(fieldName(widget), 'table-layout'),
166
+ options: {
167
+ columns: Math.max(1, columns.length),
168
+ ...(columns.length ? { columnWidths: sizes.map((size) => sharePercent(size, total)).join(' ') } : {}),
169
+ ...(borderItems ? { borderItems } : {}),
170
+ },
171
+ children: columns.map((col) => ({
172
+ type: 'table-item-layout',
173
+ name: this.uniqueName(undefined, 'table-item-layout'),
174
+ options: cellChrome(col, rowBackground),
175
+ children: this.convertSequence(childWidgets(col)),
176
+ })),
177
+ };
178
+ }
179
+ column(widget) {
180
+ const size = numberOption(widget.options, 'size') ?? 12;
181
+ const basis = `${Math.max(1, Math.min(12, size)) * (100 / 12)}%`;
182
+ const alignSelf = alignSelfFromVertical(stringOption(widget.options, 'verticalAlign'));
183
+ return {
184
+ type: 'flex-item-layout',
185
+ name: this.uniqueName(undefined, 'flex-item-layout'),
186
+ options: {
187
+ grow: 0,
188
+ shrink: 0,
189
+ basis,
190
+ ...(alignSelf ? { alignSelf } : {}),
191
+ ...layoutChrome(widget),
192
+ },
193
+ children: this.convertSequence(childWidgets(widget)),
194
+ };
195
+ }
196
+ stack(widget) {
197
+ return {
198
+ type: 'flex-layout',
199
+ name: this.uniqueName(fieldName(widget), 'flex-layout'),
200
+ options: { flexDirection: 'column', gap: '8px', width: '100%', ...layoutChrome(widget) },
201
+ children: this.convertSequence(childWidgets(widget)).map((child) => ({
202
+ type: 'flex-item-layout',
203
+ name: this.uniqueName(undefined, 'flex-item-layout'),
204
+ options: { grow: 0, shrink: 0, basis: '100%' },
205
+ children: [child],
206
+ })),
207
+ };
208
+ }
209
+ tableFromRows(rows, owner) {
210
+ const liveRows = rows.filter((row) => row.options?.['isDelete'] !== true);
211
+ const placed = placeLegacyCells(liveRows);
212
+ const columns = placed.columns;
213
+ const columnWidths = columnWidthTracks(columns, placed.placed);
214
+ const cells = [];
215
+ let hasHeader = false;
216
+ for (const row of liveRows) {
217
+ if (row.options?.['isHeader'] === true) {
218
+ hasHeader = true;
219
+ }
220
+ const rowBackground = colorOption(row.options, 'bgColor');
221
+ for (const cell of childWidgets(row)) {
222
+ if (cell.options?.['isDelete'] === true) {
223
+ continue;
224
+ }
225
+ const rawColSpan = numberOption(cell.options, 'colspan') ?? 1;
226
+ const colSpan = Math.min(columns, rawColSpan);
227
+ const rowSpan = numberOption(cell.options, 'rowspan') ?? 1;
228
+ if (rawColSpan > columns) {
229
+ this.warn('table-span', `${rawColSpan}x${rowSpan}`);
230
+ }
231
+ const width = columnWidths ? undefined : singleColumnWidth(cell, columns);
232
+ cells.push({
233
+ type: 'table-item-layout',
234
+ name: this.uniqueName(undefined, 'table-item-layout'),
235
+ options: {
236
+ ...(colSpan > 1 ? { colSpan } : {}),
237
+ ...(rowSpan > 1 ? { rowSpan } : {}),
238
+ ...(width ? { width } : {}),
239
+ ...cellChrome(cell, rowBackground),
240
+ },
241
+ children: this.convertSequence(childWidgets(cell)),
242
+ });
243
+ }
244
+ }
245
+ const borderItems = tableBorderItems(liveRows);
246
+ return {
247
+ type: 'table-layout',
248
+ name: this.uniqueName(owner ? fieldName(owner) : undefined, 'table-layout'),
249
+ options: {
250
+ columns,
251
+ ...(columnWidths ? { columnWidths: columnWidths.join(' ') } : {}),
252
+ ...(hasHeader ? { hasHeader: true } : {}),
253
+ ...(borderItems ? { borderItems } : {}),
254
+ },
255
+ children: cells,
256
+ };
257
+ }
258
+ repeater(widget) {
259
+ return this.withVisibility(widget, {
260
+ type: 'repeater-layout',
261
+ name: this.uniqueName(fieldName(widget), 'repeater-layout'),
262
+ path: fieldName(widget),
263
+ options: { hasControls: widget.options?.['allowAdd'] !== false },
264
+ children: this.convertSequence(childWidgets(widget)),
265
+ });
266
+ }
267
+ text(widget) {
268
+ const raw = stringOption(widget.options, 'text') ?? '';
269
+ if (/\[[A-Za-z][\w]*\]/.test(raw)) {
270
+ this.warn('merge-field', raw);
271
+ }
272
+ const rendered = renderText(raw, widget.options);
273
+ return this.withVisibility(widget, {
274
+ type: 'text-block-layout',
275
+ name: this.uniqueName(fieldName(widget), 'text-block-layout'),
276
+ options: {
277
+ content: rendered.content,
278
+ format: rendered.format,
279
+ ...(rendered.style ? { style: rendered.style } : {}),
280
+ },
281
+ });
282
+ }
283
+ editor(widget, type, extraOptions = {}) {
284
+ const name = fieldName(widget);
285
+ const placeholder = stringOption(widget.options, 'placeholder');
286
+ return this.withVisibility(widget, {
287
+ type,
288
+ name: this.uniqueName(name, type),
289
+ path: name,
290
+ options: {
291
+ ...extraOptions,
292
+ ...(placeholder ? { placeholder } : {}),
293
+ ...(widget.options?.['readonly'] === true ? { readonly: true } : {}),
294
+ ...requiredOptions(widget),
295
+ },
296
+ });
297
+ }
298
+ choice(widget, type) {
299
+ const dataSource = recordOption(widget.options?.['dataSource']);
300
+ const mode = dataSource?.['mode'];
301
+ const items = arrayOption(dataSource, 'dataItems');
302
+ if (mode === 'remote') {
303
+ const sourceName = stringOption(recordOption(dataSource?.['dataSource']), 'name') ?? 'remote';
304
+ this.warn('remote-data', `${fieldName(widget) || widget.name || 'field'}:${sourceName}`);
305
+ }
306
+ const useItems = mode === 'manual' || (mode === 'remote' && !!items?.length);
307
+ const columns = numberOption(widget.options, 'columns');
308
+ if (type === 'selection-list-editor' && columns !== undefined && columns > 1) {
309
+ this.warn('list-columns', `${fieldName(widget) || widget.name || 'list'}:${columns}`);
310
+ }
311
+ const legacyDirection = stringOption(widget.options, 'direction');
312
+ const directionId = legacyDirection === 'horizontal' || legacyDirection === 'vertical'
313
+ ? legacyDirection
314
+ : type === 'selection-list-editor' && (columns === undefined || columns <= 1)
315
+ ? 'horizontal'
316
+ : undefined;
317
+ const defaults = (useItems ? items : [])
318
+ ?.map((item) => recordOption(item))
319
+ .filter((item) => item?.['DefaultValue'] === true)
320
+ .map((item) => item?.['value'])
321
+ .filter((value) => value !== undefined);
322
+ const multiple = widget.options?.['mode'] === 'multiple';
323
+ return this.editor(widget, type, {
324
+ ...(useItems && items ? { dataSource: items, valueField: 'value', textField: 'text', sourceMode: 'list' } : {}),
325
+ ...(multiple ? { multiple: true } : {}),
326
+ ...(directionId ? { direction: { id: directionId } } : {}),
327
+ ...(defaults && defaults.length > 0 ? { defaultValue: multiple ? defaults : defaults[0] } : {}),
328
+ });
329
+ }
330
+ image(widget) {
331
+ const value = recordOption(widget.options?.['value']);
332
+ const src = stringOption(value, 'srcData') ?? '';
333
+ const hosted = /^https?:\/\//i.test(src) || src.startsWith('data:');
334
+ if (src && !hosted) {
335
+ this.warn('image-source', src);
336
+ }
337
+ const name = this.uniqueName(fieldName(widget), 'image');
338
+ const width = cssLength(value?.['width']);
339
+ const height = cssLength(value?.['height']);
340
+ const stretch = value?.['isAspectRatio'] === false && !!width && !!height;
341
+ return this.withVisibility(widget, {
342
+ type: 'image',
343
+ name,
344
+ ...(hosted ? { path: name, defaultValue: src } : {}),
345
+ options: {
346
+ ...(stringOption(widget.options, 'alt') ? { alt: stringOption(widget.options, 'alt') } : {}),
347
+ ...(width ? { width } : {}),
348
+ ...(height ? { height } : {}),
349
+ ...(stretch ? { objectFit: 'fill' } : {}),
350
+ },
351
+ });
352
+ }
353
+ placeholder(content) {
354
+ return {
355
+ type: 'text-block-layout',
356
+ name: this.uniqueName(undefined, 'text-block-layout'),
357
+ options: { content, format: 'plain' },
358
+ };
359
+ }
360
+ editorType(options) {
361
+ const dataType = stringOption(options, 'dataType');
362
+ if (dataType === 'number' || dataType === 'int' || dataType === 'decimal') {
363
+ return 'number-editor';
364
+ }
365
+ return 'text-editor';
366
+ }
367
+ withVisibility(widget, node) {
368
+ if (widget.options?.['visible'] === false) {
369
+ node.visible = false;
370
+ }
371
+ return node;
372
+ }
373
+ noteScripts(widget) {
374
+ const options = widget.options ?? {};
375
+ for (const key of SCRIPT_KEYS) {
376
+ const value = options[key];
377
+ if (typeof value === 'string' && value.trim()) {
378
+ this.warn('script', `${fieldName(widget) || widget.name || 'widget'}.${key}`);
379
+ }
380
+ }
381
+ if (Array.isArray(options['formula']) && options['formula'].length > 0) {
382
+ this.warn('script', `${fieldName(widget) || widget.name || 'widget'}.formula`);
383
+ }
384
+ }
385
+ warn(code, sample) {
386
+ const bucket = this.warningMap.get(code) ?? { count: 0, samples: [] };
387
+ bucket.count += 1;
388
+ if (bucket.samples.length < 5 && !bucket.samples.includes(sample)) {
389
+ bucket.samples.push(sample);
390
+ }
391
+ this.warningMap.set(code, bucket);
392
+ }
393
+ uniqueName(preferred, fallback) {
394
+ const base = sanitizeName(preferred) || fallback;
395
+ let name = base;
396
+ let index = 2;
397
+ while (this.names.has(name)) {
398
+ name = `${base}${index}`;
399
+ index += 1;
400
+ }
401
+ this.names.add(name);
402
+ return name;
403
+ }
404
+ }
405
+ //#endregion
406
+ //#region ----- Helpers -----
407
+ function stamp(nodes, slot) {
408
+ return nodes.map((node) => ({ ...node, meta: { ...(node.meta ?? {}), [slot]: true } }));
409
+ }
410
+ function childWidgets(widget) {
411
+ const widgets = widget.options?.widgets;
412
+ return Array.isArray(widgets) ? widgets.filter((child) => !!child && typeof child === 'object') : [];
413
+ }
414
+ function asLegacyWidget(source) {
415
+ if (!source || typeof source !== 'object' || Array.isArray(source)) {
416
+ return null;
417
+ }
418
+ return source;
419
+ }
420
+ function fieldName(widget) {
421
+ const name = stringOption(widget.options, 'name');
422
+ return name || undefined;
423
+ }
424
+ function stringOption(record, key) {
425
+ const value = record?.[key];
426
+ return typeof value === 'string' ? value : undefined;
427
+ }
428
+ function numberOption(record, key) {
429
+ const value = record?.[key];
430
+ if (typeof value === 'number' && Number.isFinite(value)) {
431
+ return value;
432
+ }
433
+ if (typeof value === 'string' && value.trim() && Number.isFinite(Number(value))) {
434
+ return Number(value);
435
+ }
436
+ return undefined;
437
+ }
438
+ function recordOption(value) {
439
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
440
+ return undefined;
441
+ }
442
+ return value;
443
+ }
444
+ function arrayOption(record, key) {
445
+ const value = record?.[key];
446
+ return Array.isArray(value) ? value : undefined;
447
+ }
448
+ function colorOption(record, key) {
449
+ const value = stringOption(record, key);
450
+ if (!value || value === 'inherit') {
451
+ return undefined;
452
+ }
453
+ return value;
454
+ }
455
+ function requiredOptions(widget) {
456
+ const items = arrayOption(recordOption(widget.options?.['validator']), 'items') ?? [];
457
+ const required = items.some((item) => recordOption(item)?.['type'] === 'required');
458
+ return required ? { validations: { required: true } } : {};
459
+ }
460
+ function sanitizeName(value) {
461
+ return (value ?? '').trim().replace(/[^\w-]/g, '');
462
+ }
463
+ function renderText(text, options) {
464
+ const styles = Array.isArray(options?.['textStyle'])
465
+ ? options['textStyle'].filter((item) => typeof item === 'string')
466
+ : [];
467
+ const css = [];
468
+ const color = colorOption(options, 'color');
469
+ const align = presentStyle(stringOption(options, 'textAlign'));
470
+ const fontSize = presentStyle(stringOption(options, 'fontSize'));
471
+ const font = presentStyle(stringOption(options, 'font'));
472
+ if (color) {
473
+ css.push(`color:${color}`);
474
+ }
475
+ if (align) {
476
+ css.push(`text-align:${align}`);
477
+ }
478
+ if (fontSize) {
479
+ css.push(`font-size:${fontSizeToCss(fontSize)}`);
480
+ }
481
+ if (font) {
482
+ css.push(`font-family:${font}`);
483
+ }
484
+ if (styles.includes('bold')) {
485
+ css.push('font-weight:bold');
486
+ }
487
+ if (styles.includes('italic')) {
488
+ css.push('font-style:italic');
489
+ }
490
+ if (styles.includes('underline')) {
491
+ css.push('text-decoration:underline');
492
+ }
493
+ const tidy = tidyLegacyText(text);
494
+ const hasHtml = /<[a-z][\s\S]*>/i.test(tidy);
495
+ return {
496
+ content: tidy,
497
+ format: hasHtml ? 'html' : 'plain',
498
+ ...(css.length ? { style: css.join(';') } : {}),
499
+ };
500
+ }
501
+ function presentStyle(value) {
502
+ if (!value || value === 'inherit') {
503
+ return undefined;
504
+ }
505
+ return value;
506
+ }
507
+ function layoutChrome(widget) {
508
+ const box = parseBoxStyle(widget.options?.['boxStyle']);
509
+ const background = colorOption(widget.options, 'bgColor');
510
+ return {
511
+ ...(box ? borderOptions(box) : {}),
512
+ ...(box ? spacingOptions(box) : {}),
513
+ ...(background ? { backgroundColor: background } : {}),
514
+ };
515
+ }
516
+ function parseBoxStyle(raw) {
517
+ if (!raw) {
518
+ return undefined;
519
+ }
520
+ if (typeof raw === 'string') {
521
+ try {
522
+ const parsed = JSON.parse(raw);
523
+ return recordOption(parsed);
524
+ }
525
+ catch {
526
+ return undefined;
527
+ }
528
+ }
529
+ return recordOption(raw);
530
+ }
531
+ function borderOptions(box) {
532
+ const border = recordOption(box['border']);
533
+ if (!border) {
534
+ return {};
535
+ }
536
+ const sides = ['top', 'right', 'bottom', 'left'].map((side) => sideValue(border[side]));
537
+ if (sides.every((side) => side <= 0)) {
538
+ return {};
539
+ }
540
+ const declared = stringOption(box, 'borderColor') || stringOption(border, 'borderColor');
541
+ const color = declared || '#333';
542
+ return {
543
+ border: {
544
+ width: fourShorthand(sides.map((side) => (side > 0 ? `${side}px` : '0'))),
545
+ style: fourShorthand(sides.map((side) => (side > 0 ? 'solid' : 'none'))),
546
+ color: fourShorthand([color, color, color, color]),
547
+ },
548
+ };
549
+ }
550
+ function spacingOptions(box) {
551
+ const padding = sideShorthand(recordOption(box['padding']));
552
+ const margin = sideShorthand(recordOption(box['margin']));
553
+ if (!padding && !margin) {
554
+ return {};
555
+ }
556
+ return {
557
+ spacing: {
558
+ ...(padding ? { padding } : {}),
559
+ ...(margin ? { margin } : {}),
560
+ },
561
+ };
562
+ }
563
+ function sideShorthand(sides) {
564
+ if (!sides) {
565
+ return undefined;
566
+ }
567
+ const values = ['top', 'right', 'bottom', 'left'].map((side) => sideValue(sides[side]));
568
+ if (values.every((side) => side <= 0)) {
569
+ return undefined;
570
+ }
571
+ return fourShorthand(values.map((side) => `${side}px`));
572
+ }
573
+ function sideValue(value) {
574
+ if (typeof value === 'number' && Number.isFinite(value)) {
575
+ return value;
576
+ }
577
+ if (typeof value === 'string' && value.trim() && Number.isFinite(Number(value))) {
578
+ return Number(value);
579
+ }
580
+ return 0;
581
+ }
582
+ function fourShorthand(values) {
583
+ const [top, right, bottom, left] = values;
584
+ if (top === right && right === bottom && bottom === left) {
585
+ return top;
586
+ }
587
+ if (top === bottom && right === left) {
588
+ return `${top} ${right}`;
589
+ }
590
+ if (right === left) {
591
+ return `${top} ${right} ${bottom}`;
592
+ }
593
+ return `${top} ${right} ${bottom} ${left}`;
594
+ }
595
+ function cssLength(value) {
596
+ if (typeof value === 'number' && Number.isFinite(value)) {
597
+ return `${value}px`;
598
+ }
599
+ if (typeof value !== 'string') {
600
+ return undefined;
601
+ }
602
+ const trimmed = value.trim();
603
+ if (!trimmed || trimmed === 'inherit') {
604
+ return undefined;
605
+ }
606
+ return /^\d+(\.\d+)?$/.test(trimmed) ? `${trimmed}px` : trimmed;
607
+ }
608
+ /** Places legacy cells the same way the table widget does, so column tracks line up. */
609
+ function placeLegacyCells(rows) {
610
+ const rowCells = rows.map((row) => childWidgets(row).filter((cell) => cell.options?.['isDelete'] !== true));
611
+ const columns = Math.max(1, ...rowCells.map((cells) => cells.reduce((sum, cell) => sum + (numberOption(cell.options, 'colspan') ?? 1), 0)));
612
+ const occupied = [];
613
+ const placed = [];
614
+ const ensureRow = (rowIndex) => {
615
+ while (occupied.length <= rowIndex) {
616
+ occupied.push(Array.from({ length: columns }, () => false));
617
+ }
618
+ };
619
+ let rowIndex = 0;
620
+ for (const cells of rowCells) {
621
+ for (const cell of cells) {
622
+ const colSpan = Math.min(columns, Math.max(1, numberOption(cell.options, 'colspan') ?? 1));
623
+ const rowSpan = Math.max(1, numberOption(cell.options, 'rowspan') ?? 1);
624
+ let landed = false;
625
+ while (!landed) {
626
+ ensureRow(rowIndex);
627
+ for (let col = 0; col < columns; col++) {
628
+ if (col + colSpan > columns || occupied[rowIndex][col]) {
629
+ continue;
630
+ }
631
+ let free = true;
632
+ for (let row = 0; row < rowSpan && free; row++) {
633
+ ensureRow(rowIndex + row);
634
+ for (let span = 0; span < colSpan; span++) {
635
+ if (occupied[rowIndex + row][col + span]) {
636
+ free = false;
637
+ break;
638
+ }
639
+ }
640
+ }
641
+ if (!free) {
642
+ continue;
643
+ }
644
+ for (let row = 0; row < rowSpan; row++) {
645
+ for (let span = 0; span < colSpan; span++) {
646
+ occupied[rowIndex + row][col + span] = true;
647
+ }
648
+ }
649
+ placed.push({ cell, col, colSpan });
650
+ landed = true;
651
+ break;
652
+ }
653
+ if (!landed) {
654
+ rowIndex += 1;
655
+ }
656
+ }
657
+ }
658
+ rowIndex += 1;
659
+ }
660
+ return { columns, placed };
661
+ }
662
+ /**
663
+ * One CSS length per column. A colspan cell keeps a percentage by splitting it,
664
+ * and drops a pixel width (the old 30px-on-a-merged-cell leftover).
665
+ */
666
+ function columnWidthTracks(columns, placed) {
667
+ const tracks = Array.from({ length: columns });
668
+ for (const item of placed) {
669
+ if (item.colSpan !== 1 || tracks[item.col]) {
670
+ continue;
671
+ }
672
+ const length = trackLength(item.cell, columns);
673
+ if (length) {
674
+ tracks[item.col] = length;
675
+ }
676
+ }
677
+ for (const item of placed) {
678
+ if (item.colSpan <= 1) {
679
+ continue;
680
+ }
681
+ const length = cssLength(item.cell.options?.['width']);
682
+ if (!length?.endsWith('%')) {
683
+ continue;
684
+ }
685
+ const percent = Number(length.slice(0, -1));
686
+ if (!Number.isFinite(percent) || percent <= 0 || percent >= 100) {
687
+ continue;
688
+ }
689
+ const covered = Array.from({ length: item.colSpan }, (_, index) => item.col + index);
690
+ if (covered.some((index) => tracks[index])) {
691
+ continue;
692
+ }
693
+ const share = splitPercent(percent, item.colSpan);
694
+ for (const index of covered) {
695
+ tracks[index] = share;
696
+ }
697
+ }
698
+ if (tracks.some((track) => !track)) {
699
+ return undefined;
700
+ }
701
+ return tracks.filter((track) => !!track);
702
+ }
703
+ /** Width painted on one cell when the table has no complete column model. */
704
+ function singleColumnWidth(cell, columns) {
705
+ if ((numberOption(cell.options, 'colspan') ?? 1) !== 1) {
706
+ return undefined;
707
+ }
708
+ return trackLength(cell, columns);
709
+ }
710
+ function trackLength(cell, columns) {
711
+ const length = cssLength(cell.options?.['width']);
712
+ if (!length?.endsWith('%')) {
713
+ return length;
714
+ }
715
+ const percent = Number(length.slice(0, -1));
716
+ if (!Number.isFinite(percent) || percent <= 0 || (percent >= 100 && columns > 1)) {
717
+ return undefined;
718
+ }
719
+ return length;
720
+ }
721
+ /** First real cell border, applied once on the table so adjacent rules collapse. */
722
+ function tableBorderItems(rows) {
723
+ for (const row of rows) {
724
+ for (const cell of childWidgets(row)) {
725
+ if (cell.options?.['isDelete'] === true) {
726
+ continue;
727
+ }
728
+ const border = recordOption(layoutChrome(cell)['border']);
729
+ const width = border ? stringOption(border, 'width') : undefined;
730
+ if (!border || !width || width === '0' || width === '0px') {
731
+ continue;
732
+ }
733
+ return {
734
+ width,
735
+ style: stringOption(border, 'style') || 'solid',
736
+ color: stringOption(border, 'color') || '#333',
737
+ radius: '0',
738
+ };
739
+ }
740
+ }
741
+ return undefined;
742
+ }
743
+ function fontSizeToCss(value) {
744
+ const named = {
745
+ 'xx-small': '10px',
746
+ 'x-small': '12px',
747
+ smaller: '13px',
748
+ small: '14px',
749
+ medium: '16px',
750
+ large: '18px',
751
+ larger: '20px',
752
+ 'x-large': '24px',
753
+ 'xx-large': '32px',
754
+ };
755
+ return named[value] ?? value;
756
+ }
757
+ /** Drops the trailing breaks the old rich-text editor leaves on every label. */
758
+ function tidyLegacyText(text) {
759
+ return text.replace(/(?:&nbsp;|\s|<br\s*\/?>)+$/gi, '');
760
+ }
761
+ function cellChrome(widget, rowBackground) {
762
+ const chrome = layoutChrome(widget);
763
+ delete chrome['border'];
764
+ if (!chrome['backgroundColor'] && rowBackground) {
765
+ chrome['backgroundColor'] = rowBackground;
766
+ }
767
+ const textAlign = presentStyle(stringOption(widget.options, 'textAlign'));
768
+ const verticalAlign = presentStyle(stringOption(widget.options, 'verticalAlign'));
769
+ return {
770
+ ...chrome,
771
+ ...(textAlign ? { textAlign } : {}),
772
+ ...(verticalAlign ? { verticalAlign } : {}),
773
+ };
774
+ }
775
+ function borderItemsFromWidget(widget) {
776
+ const border = recordOption(layoutChrome(widget)['border']);
777
+ const width = border ? stringOption(border, 'width') : undefined;
778
+ if (!border || !width || width === '0' || width === '0px') {
779
+ return undefined;
780
+ }
781
+ return {
782
+ width,
783
+ style: stringOption(border, 'style') || 'solid',
784
+ color: stringOption(border, 'color') || '#333',
785
+ radius: '0',
786
+ };
787
+ }
788
+ function borderItemsFromWidgets(widgets) {
789
+ for (const widget of widgets) {
790
+ const border = borderItemsFromWidget(widget);
791
+ if (border) {
792
+ return border;
793
+ }
794
+ }
795
+ return undefined;
796
+ }
797
+ function sharePercent(part, total) {
798
+ return percentText((part / total) * 100);
799
+ }
800
+ function splitPercent(percent, parts) {
801
+ return percentText(percent / parts);
802
+ }
803
+ function percentText(value) {
804
+ const rounded = Math.round(value * 100) / 100;
805
+ return `${rounded}%`;
806
+ }
807
+ function alignSelfFromVertical(value) {
808
+ if (value === 'top') {
809
+ return 'flex-start';
810
+ }
811
+ if (value === 'middle') {
812
+ return 'center';
813
+ }
814
+ if (value === 'bottom') {
815
+ return 'flex-end';
816
+ }
817
+ return undefined;
818
+ }
819
+ //#endregion
820
+
821
+ //#region ----- Imports -----
822
+ //#endregion
823
+ //#region ----- Service -----
824
+ /**
825
+ * Picks a legacy form-builder JSON file, converts it, and loads the result
826
+ * onto the open layout designer.
827
+ */
828
+ class AXELegacyFormImportService {
829
+ constructor() {
830
+ //#region ----- Services & Dependencies -----
831
+ this.fileService = inject(AXFileService);
832
+ this.toastService = inject(AXToastService);
833
+ this.translationService = inject(AXTranslationService);
834
+ //#endregion
835
+ //#region ----- State Signals -----
836
+ this.selection = signal(null, /* @ts-ignore */
837
+ ...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
838
+ }
839
+ //#endregion
840
+ //#region ----- File Selection -----
841
+ async chooseJsonFile(designer) {
842
+ const files = await this.fileService.choose({ multiple: false, accept: 'application/json,.json' });
843
+ const file = files?.[0];
844
+ if (!file) {
845
+ return;
846
+ }
847
+ const rawText = await file.text();
848
+ const document = this.parseJsonDocument(rawText);
849
+ const fileName = file.name?.trim() || 'form.json';
850
+ if (document === undefined) {
851
+ this.selection.set(null);
852
+ await this.showInvalidJsonToast();
853
+ return;
854
+ }
855
+ try {
856
+ const converted = convertLegacyFormPage(document);
857
+ this.selection.set({
858
+ fileName,
859
+ rawText,
860
+ document,
861
+ converted: converted.document,
862
+ warnings: converted.warnings,
863
+ });
864
+ await this.loadOntoDesigner(designer, converted.document);
865
+ await this.showConvertedToast(fileName, converted.warnings);
866
+ }
867
+ catch (error) {
868
+ this.selection.set({ fileName, rawText, document, warnings: [] });
869
+ if (error instanceof Error && error.message === 'LEGACY_PAGE_EXPECTED') {
870
+ await this.showNotLegacyToast();
871
+ return;
872
+ }
873
+ await this.showConvertFailedToast();
874
+ }
875
+ }
876
+ //#endregion
877
+ //#region ----- Helpers -----
878
+ parseJsonDocument(rawText) {
879
+ try {
880
+ const parsed = JSON.parse(rawText);
881
+ if (parsed === null || typeof parsed !== 'object') {
882
+ return undefined;
883
+ }
884
+ return parsed;
885
+ }
886
+ catch {
887
+ return undefined;
888
+ }
889
+ }
890
+ async loadOntoDesigner(designer, document) {
891
+ if (!isDesignerContentLoader(designer)) {
892
+ return;
893
+ }
894
+ await designer.loadByContent(JSON.stringify(document));
895
+ }
896
+ async showConvertedToast(fileName, warnings) {
897
+ const title = await this.translationService.translateAsync('@form-template-management:legacyImport.converted-title');
898
+ const summary = (await Promise.all(warnings.map((warning) => this.translateWarning(warning)))).join(' ');
899
+ const content = await this.translationService.translateAsync('@form-template-management:legacyImport.converted-content', { params: { name: fileName, summary } });
900
+ this.toastService.show({ color: warnings.length ? 'warning' : 'success', title, content });
901
+ }
902
+ async translateWarning(warning) {
903
+ return this.translationService.translateAsync(`@form-template-management:legacyImport.warnings.${warning.code}`, { params: { count: warning.count } });
904
+ }
905
+ async showInvalidJsonToast() {
906
+ const title = await this.translationService.translateAsync('@form-template-management:legacyImport.invalid-title');
907
+ const content = await this.translationService.translateAsync('@form-template-management:legacyImport.invalid-content');
908
+ this.toastService.show({ color: 'danger', title, content });
909
+ }
910
+ async showNotLegacyToast() {
911
+ const title = await this.translationService.translateAsync('@form-template-management:legacyImport.not-legacy-title');
912
+ const content = await this.translationService.translateAsync('@form-template-management:legacyImport.not-legacy-content');
913
+ this.toastService.show({ color: 'danger', title, content });
914
+ }
915
+ async showConvertFailedToast() {
916
+ const title = await this.translationService.translateAsync('@form-template-management:legacyImport.failed-title');
917
+ const content = await this.translationService.translateAsync('@form-template-management:legacyImport.failed-content');
918
+ this.toastService.show({ color: 'danger', title, content });
919
+ }
920
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXELegacyFormImportService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
921
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXELegacyFormImportService, providedIn: 'root' }); }
922
+ }
923
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXELegacyFormImportService, decorators: [{
924
+ type: Injectable,
925
+ args: [{ providedIn: 'root' }]
926
+ }] });
927
+ //#endregion
928
+ function isDesignerContentLoader(value) {
929
+ return !!value && typeof value === 'object' && typeof value.loadByContent === 'function';
930
+ }
931
+
932
+ //#region ----- Imports -----
933
+ //#endregion
934
+ //#region ----- Designer Import menu -----
935
+ /** Adds File → Import → Convert Legacy JSON on the layout designer. */
936
+ const AXELegacyFormImportMenuHookProvider = {
937
+ key: AXPLayoutDesignerHeaderMenuHookKeys.submenu,
938
+ priority: 30,
939
+ execute: (payload) => {
940
+ if (payload.parentMenuId !== 'import') {
941
+ return payload;
942
+ }
943
+ const importer = inject(AXELegacyFormImportService);
944
+ payload.items.push({
945
+ id: 'extensions-layout-designer-legacy-import',
946
+ priority: 10,
947
+ labelKey: '@form-template-management:legacyImport.menu',
948
+ iconClass: 'fa-solid fa-right-left',
949
+ run: () => importer.chooseJsonFile(payload.designer),
950
+ });
951
+ return payload;
952
+ },
953
+ };
954
+ //#endregion
955
+
956
+ //#region ----- Imports -----
957
+ //#endregion
958
+ //#region ----- Module -----
959
+ /**
960
+ * Layout designer extension that adds File → Import → Convert Legacy JSON.
961
+ * The selected document is held for a later conversion step.
962
+ */
963
+ class AXELayoutDesignerLegacyImportExtensionModule {
964
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXELayoutDesignerLegacyImportExtensionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
965
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXELayoutDesignerLegacyImportExtensionModule }); }
966
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXELayoutDesignerLegacyImportExtensionModule, providers: [
967
+ {
968
+ provide: AXP_HOOK_PROVIDER,
969
+ multi: true,
970
+ useValue: AXELegacyFormImportMenuHookProvider,
971
+ },
972
+ ] }); }
973
+ }
974
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXELayoutDesignerLegacyImportExtensionModule, decorators: [{
975
+ type: NgModule,
976
+ args: [{
977
+ providers: [
978
+ {
979
+ provide: AXP_HOOK_PROVIDER,
980
+ multi: true,
981
+ useValue: AXELegacyFormImportMenuHookProvider,
982
+ },
983
+ ],
984
+ }]
985
+ }] });
986
+
987
+ //#region ----- Types -----
988
+ //#endregion
989
+
990
+ /**
991
+ * Generated bundle index. Do not edit.
992
+ */
993
+
994
+ export { AXELayoutDesignerLegacyImportExtensionModule, AXELegacyFormImportService, convertLegacyFormPage };
995
+ //# sourceMappingURL=acorex-platform-extension-layout-designer-legacy-import-client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acorex-platform-extension-layout-designer-legacy-import-client.mjs","sources":["../../../../libs/extensions/layout-designer/legacy-import/client/src/lib/legacy-form-converter.ts","../../../../libs/extensions/layout-designer/legacy-import/client/src/lib/legacy-form-import.service.ts","../../../../libs/extensions/layout-designer/legacy-import/client/src/lib/legacy-form-import-menu.hook.ts","../../../../libs/extensions/layout-designer/legacy-import/client/src/lib/layout-designer-legacy-import.module.ts","../../../../libs/extensions/layout-designer/legacy-import/client/src/lib/legacy-form-import.types.ts","../../../../libs/extensions/layout-designer/legacy-import/client/src/acorex-platform-extension-layout-designer-legacy-import-client.ts"],"sourcesContent":["//#region ----- Types -----\n\n/** Legacy form-builder node (`name` + `options.widgets`). */\ninterface AXELegacyWidget {\n name?: string;\n options?: AXELegacyOptions;\n}\n\ninterface AXELegacyOptions {\n widgets?: AXELegacyWidget[];\n [key: string]: unknown;\n}\n\n/** Designer widget tree produced by the converter. */\nexport interface AXEConvertedWidgetNode {\n type: string;\n name?: string;\n path?: string;\n visible?: boolean;\n options?: Record<string, unknown>;\n children?: AXEConvertedWidgetNode[];\n meta?: Record<string, unknown>;\n}\n\nexport interface AXELegacyFormConvertWarning {\n code:\n | 'script'\n | 'remote-data'\n | 'outlet'\n | 'image-source'\n | 'image-input'\n | 'unknown-widget'\n | 'table-span'\n | 'list-columns'\n | 'merge-field';\n count: number;\n samples: string[];\n}\n\nexport interface AXELegacyFormConvertResult {\n document: AXEConvertedWidgetNode;\n warnings: AXELegacyFormConvertWarning[];\n}\n\n//#endregion\n\n//#region ----- Converter -----\n\nconst SCRIPT_KEYS = ['onInit', 'onValueChange', 'onItemClick', 'onSigned'] as const;\n\n/**\n * Converts a legacy form-builder page JSON into a designer document\n * (`document-layout` of `page-layout` nodes).\n */\nexport function convertLegacyFormPage(source: unknown): AXELegacyFormConvertResult {\n const page = asLegacyWidget(source);\n if (!page || page.name !== 'page') {\n throw new Error('LEGACY_PAGE_EXPECTED');\n }\n\n const context = new AXEConvertContext();\n const header: AXEConvertedWidgetNode[] = [];\n const footer: AXEConvertedWidgetNode[] = [];\n const chunks: AXELegacyWidget[][] = [[]];\n\n for (const widget of childWidgets(page)) {\n if (widget.name === 'page-break') {\n chunks.push([]);\n continue;\n }\n if (widget.name === 'page-header') {\n header.push(...stamp(context.convertSequence(childWidgets(widget)), 'header'));\n continue;\n }\n if (widget.name === 'page-footer') {\n footer.push(...stamp(context.convertSequence(childWidgets(widget)), 'footer'));\n continue;\n }\n chunks[chunks.length - 1].push(widget);\n }\n\n const bodyChunks = chunks.filter((chunk, index) => chunk.length > 0 || (index === 0 && chunks.length === 1));\n const pages = (bodyChunks.length ? bodyChunks : [[]]).map((chunk, index) =>\n context.page(chunk, index, page.options, header, footer),\n );\n\n return {\n document: {\n type: 'document-layout',\n name: 'document',\n children: pages,\n },\n warnings: context.warnings(),\n };\n}\n\n//#endregion\n\n//#region ----- Context -----\n\nclass AXEConvertContext {\n private readonly names = new Set<string>();\n private readonly warningMap = new Map<AXELegacyFormConvertWarning['code'], { count: number; samples: string[] }>();\n\n page(\n chunk: AXELegacyWidget[],\n index: number,\n pageOptions: AXELegacyOptions | undefined,\n header: AXEConvertedWidgetNode[],\n footer: AXEConvertedWidgetNode[],\n ): AXEConvertedWidgetNode {\n const direction = stringOption(pageOptions, 'pageDirection');\n const background = colorOption(pageOptions, 'bgColor');\n return {\n type: 'page-layout',\n name: this.uniqueName(index === 0 ? 'page' : `page${index + 1}`, 'page-layout'),\n options: {\n hasHeader: header.length > 0 || pageOptions?.['showHeader'] === true,\n hasFooter: footer.length > 0 || pageOptions?.['showFooter'] === true,\n ...(direction === 'rtl' || direction === 'ltr' ? { direction } : {}),\n ...(background ? { backgroundColor: background } : {}),\n },\n children: [...header, ...this.convertSequence(chunk), ...footer],\n };\n }\n\n convertSequence(widgets: AXELegacyWidget[]): AXEConvertedWidgetNode[] {\n const nodes: AXEConvertedWidgetNode[] = [];\n let rows: AXELegacyWidget[] = [];\n const flushRows = () => {\n if (!rows.length) {\n return;\n }\n nodes.push(this.tableFromRows(rows, undefined));\n rows = [];\n };\n for (const widget of widgets) {\n if (widget.name === 'table-row') {\n rows.push(widget);\n continue;\n }\n flushRows();\n const converted = this.convertWidget(widget);\n if (converted) {\n nodes.push(converted);\n }\n }\n flushRows();\n return nodes;\n }\n\n warnings(): AXELegacyFormConvertWarning[] {\n return [...this.warningMap.entries()].map(([code, entry]) => ({\n code,\n count: entry.count,\n samples: entry.samples,\n }));\n }\n\n private convertWidget(widget: AXELegacyWidget): AXEConvertedWidgetNode | null {\n this.noteScripts(widget);\n const options = widget.options ?? {};\n switch (widget.name) {\n case 'row':\n return this.row(widget);\n case 'col':\n return this.column(widget);\n case 'table':\n return this.tableFromRows(childWidgets(widget).filter((child) => child.name === 'table-row'), widget);\n case 'container':\n return this.stack(widget);\n case 'repeater':\n return this.repeater(widget);\n case 'text':\n case 'text-heading':\n return this.text(widget);\n case 'textbox':\n return this.editor(widget, this.editorType(options));\n case 'textarea':\n return this.editor(widget, 'large-text-editor');\n case 'list':\n case 'listsecond':\n return this.choice(widget, 'selection-list-editor');\n case 'dropdown':\n return this.choice(widget, 'select-editor');\n case 'date-input':\n return this.editor(widget, 'date-time-editor', { format: { id: 'date', title: 'Date' } });\n case 'time-input':\n return this.editor(widget, 'date-time-editor', { format: { id: 'time', title: 'Time' } });\n case 'signature':\n return this.editor(widget, 'signature');\n case 'image':\n return this.image(widget);\n case 'image-input':\n this.warn('image-input', fieldName(widget) || 'image-input');\n return this.placeholder('Image input was not converted');\n case 'outlet':\n this.warn('outlet', String(options['widgetId'] ?? (fieldName(widget) || 'outlet')));\n return this.placeholder(`Embedded form ${String(options['widgetId'] ?? '')} was not converted`.trim());\n case 'page':\n case 'page-break':\n case 'page-header':\n case 'page-footer':\n case 'table-row':\n case 'table-cell':\n return null;\n default:\n this.warn('unknown-widget', widget.name || 'unknown');\n return this.placeholder(`Unsupported widget: ${widget.name || 'unknown'}`);\n }\n }\n\n private row(widget: AXELegacyWidget): AXEConvertedWidgetNode {\n const columns = childWidgets(widget).map((child) =>\n child.name === 'col' ? child : { name: 'col', options: { size: 12, widgets: [child] } },\n );\n const sizes = columns.map((col) => Math.max(1, numberOption(col.options, 'size') ?? 12));\n const total = sizes.reduce((sum, size) => sum + size, 0) || 1;\n const rowBackground = colorOption(widget.options, 'bgColor');\n const borderItems = borderItemsFromWidget(widget) ?? borderItemsFromWidgets(columns);\n return {\n type: 'table-layout',\n name: this.uniqueName(fieldName(widget), 'table-layout'),\n options: {\n columns: Math.max(1, columns.length),\n ...(columns.length ? { columnWidths: sizes.map((size) => sharePercent(size, total)).join(' ') } : {}),\n ...(borderItems ? { borderItems } : {}),\n },\n children: columns.map((col) => ({\n type: 'table-item-layout',\n name: this.uniqueName(undefined, 'table-item-layout'),\n options: cellChrome(col, rowBackground),\n children: this.convertSequence(childWidgets(col)),\n })),\n };\n }\n\n private column(widget: AXELegacyWidget): AXEConvertedWidgetNode {\n const size = numberOption(widget.options, 'size') ?? 12;\n const basis = `${Math.max(1, Math.min(12, size)) * (100 / 12)}%`;\n const alignSelf = alignSelfFromVertical(stringOption(widget.options, 'verticalAlign'));\n return {\n type: 'flex-item-layout',\n name: this.uniqueName(undefined, 'flex-item-layout'),\n options: {\n grow: 0,\n shrink: 0,\n basis,\n ...(alignSelf ? { alignSelf } : {}),\n ...layoutChrome(widget),\n },\n children: this.convertSequence(childWidgets(widget)),\n };\n }\n\n private stack(widget: AXELegacyWidget): AXEConvertedWidgetNode {\n return {\n type: 'flex-layout',\n name: this.uniqueName(fieldName(widget), 'flex-layout'),\n options: { flexDirection: 'column', gap: '8px', width: '100%', ...layoutChrome(widget) },\n children: this.convertSequence(childWidgets(widget)).map((child) => ({\n type: 'flex-item-layout',\n name: this.uniqueName(undefined, 'flex-item-layout'),\n options: { grow: 0, shrink: 0, basis: '100%' },\n children: [child],\n })),\n };\n }\n\n private tableFromRows(rows: AXELegacyWidget[], owner?: AXELegacyWidget): AXEConvertedWidgetNode {\n const liveRows = rows.filter((row) => row.options?.['isDelete'] !== true);\n const placed = placeLegacyCells(liveRows);\n const columns = placed.columns;\n const columnWidths = columnWidthTracks(columns, placed.placed);\n const cells: AXEConvertedWidgetNode[] = [];\n let hasHeader = false;\n for (const row of liveRows) {\n if (row.options?.['isHeader'] === true) {\n hasHeader = true;\n }\n const rowBackground = colorOption(row.options, 'bgColor');\n for (const cell of childWidgets(row)) {\n if (cell.options?.['isDelete'] === true) {\n continue;\n }\n const rawColSpan = numberOption(cell.options, 'colspan') ?? 1;\n const colSpan = Math.min(columns, rawColSpan);\n const rowSpan = numberOption(cell.options, 'rowspan') ?? 1;\n if (rawColSpan > columns) {\n this.warn('table-span', `${rawColSpan}x${rowSpan}`);\n }\n const width = columnWidths ? undefined : singleColumnWidth(cell, columns);\n cells.push({\n type: 'table-item-layout',\n name: this.uniqueName(undefined, 'table-item-layout'),\n options: {\n ...(colSpan > 1 ? { colSpan } : {}),\n ...(rowSpan > 1 ? { rowSpan } : {}),\n ...(width ? { width } : {}),\n ...cellChrome(cell, rowBackground),\n },\n children: this.convertSequence(childWidgets(cell)),\n });\n }\n }\n const borderItems = tableBorderItems(liveRows);\n return {\n type: 'table-layout',\n name: this.uniqueName(owner ? fieldName(owner) : undefined, 'table-layout'),\n options: {\n columns,\n ...(columnWidths ? { columnWidths: columnWidths.join(' ') } : {}),\n ...(hasHeader ? { hasHeader: true } : {}),\n ...(borderItems ? { borderItems } : {}),\n },\n children: cells,\n };\n }\n\n private repeater(widget: AXELegacyWidget): AXEConvertedWidgetNode {\n return this.withVisibility(widget, {\n type: 'repeater-layout',\n name: this.uniqueName(fieldName(widget), 'repeater-layout'),\n path: fieldName(widget),\n options: { hasControls: widget.options?.['allowAdd'] !== false },\n children: this.convertSequence(childWidgets(widget)),\n });\n }\n\n private text(widget: AXELegacyWidget): AXEConvertedWidgetNode {\n const raw = stringOption(widget.options, 'text') ?? '';\n if (/\\[[A-Za-z][\\w]*\\]/.test(raw)) {\n this.warn('merge-field', raw);\n }\n const rendered = renderText(raw, widget.options);\n return this.withVisibility(widget, {\n type: 'text-block-layout',\n name: this.uniqueName(fieldName(widget), 'text-block-layout'),\n options: {\n content: rendered.content,\n format: rendered.format,\n ...(rendered.style ? { style: rendered.style } : {}),\n },\n });\n }\n\n private editor(\n widget: AXELegacyWidget,\n type: string,\n extraOptions: Record<string, unknown> = {},\n ): AXEConvertedWidgetNode {\n const name = fieldName(widget);\n const placeholder = stringOption(widget.options, 'placeholder');\n return this.withVisibility(widget, {\n type,\n name: this.uniqueName(name, type),\n path: name,\n options: {\n ...extraOptions,\n ...(placeholder ? { placeholder } : {}),\n ...(widget.options?.['readonly'] === true ? { readonly: true } : {}),\n ...requiredOptions(widget),\n },\n });\n }\n\n private choice(widget: AXELegacyWidget, type: string): AXEConvertedWidgetNode {\n const dataSource = recordOption(widget.options?.['dataSource']);\n const mode = dataSource?.['mode'];\n const items = arrayOption(dataSource, 'dataItems');\n if (mode === 'remote') {\n const sourceName = stringOption(recordOption(dataSource?.['dataSource']), 'name') ?? 'remote';\n this.warn('remote-data', `${fieldName(widget) || widget.name || 'field'}:${sourceName}`);\n }\n const useItems = mode === 'manual' || (mode === 'remote' && !!items?.length);\n const columns = numberOption(widget.options, 'columns');\n if (type === 'selection-list-editor' && columns !== undefined && columns > 1) {\n this.warn('list-columns', `${fieldName(widget) || widget.name || 'list'}:${columns}`);\n }\n const legacyDirection = stringOption(widget.options, 'direction');\n const directionId =\n legacyDirection === 'horizontal' || legacyDirection === 'vertical'\n ? legacyDirection\n : type === 'selection-list-editor' && (columns === undefined || columns <= 1)\n ? 'horizontal'\n : undefined;\n const defaults = (useItems ? items : [])\n ?.map((item) => recordOption(item))\n .filter((item) => item?.['DefaultValue'] === true)\n .map((item) => item?.['value'])\n .filter((value) => value !== undefined);\n const multiple = widget.options?.['mode'] === 'multiple';\n return this.editor(widget, type, {\n ...(useItems && items ? { dataSource: items, valueField: 'value', textField: 'text', sourceMode: 'list' } : {}),\n ...(multiple ? { multiple: true } : {}),\n ...(directionId ? { direction: { id: directionId } } : {}),\n ...(defaults && defaults.length > 0 ? { defaultValue: multiple ? defaults : defaults[0] } : {}),\n });\n }\n\n private image(widget: AXELegacyWidget): AXEConvertedWidgetNode {\n const value = recordOption(widget.options?.['value']);\n const src = stringOption(value, 'srcData') ?? '';\n const hosted = /^https?:\\/\\//i.test(src) || src.startsWith('data:');\n if (src && !hosted) {\n this.warn('image-source', src);\n }\n const name = this.uniqueName(fieldName(widget), 'image');\n const width = cssLength(value?.['width']);\n const height = cssLength(value?.['height']);\n const stretch = value?.['isAspectRatio'] === false && !!width && !!height;\n return this.withVisibility(widget, {\n type: 'image',\n name,\n ...(hosted ? { path: name, defaultValue: src } : {}),\n options: {\n ...(stringOption(widget.options, 'alt') ? { alt: stringOption(widget.options, 'alt') } : {}),\n ...(width ? { width } : {}),\n ...(height ? { height } : {}),\n ...(stretch ? { objectFit: 'fill' } : {}),\n },\n });\n }\n\n private placeholder(content: string): AXEConvertedWidgetNode {\n return {\n type: 'text-block-layout',\n name: this.uniqueName(undefined, 'text-block-layout'),\n options: { content, format: 'plain' },\n };\n }\n\n private editorType(options: AXELegacyOptions): string {\n const dataType = stringOption(options, 'dataType');\n if (dataType === 'number' || dataType === 'int' || dataType === 'decimal') {\n return 'number-editor';\n }\n return 'text-editor';\n }\n\n private withVisibility(widget: AXELegacyWidget, node: AXEConvertedWidgetNode): AXEConvertedWidgetNode {\n if (widget.options?.['visible'] === false) {\n node.visible = false;\n }\n return node;\n }\n\n private noteScripts(widget: AXELegacyWidget): void {\n const options = widget.options ?? {};\n for (const key of SCRIPT_KEYS) {\n const value = options[key];\n if (typeof value === 'string' && value.trim()) {\n this.warn('script', `${fieldName(widget) || widget.name || 'widget'}.${key}`);\n }\n }\n if (Array.isArray(options['formula']) && options['formula'].length > 0) {\n this.warn('script', `${fieldName(widget) || widget.name || 'widget'}.formula`);\n }\n }\n\n private warn(code: AXELegacyFormConvertWarning['code'], sample: string): void {\n const bucket = this.warningMap.get(code) ?? { count: 0, samples: [] };\n bucket.count += 1;\n if (bucket.samples.length < 5 && !bucket.samples.includes(sample)) {\n bucket.samples.push(sample);\n }\n this.warningMap.set(code, bucket);\n }\n\n private uniqueName(preferred: string | undefined, fallback: string): string {\n const base = sanitizeName(preferred) || fallback;\n let name = base;\n let index = 2;\n while (this.names.has(name)) {\n name = `${base}${index}`;\n index += 1;\n }\n this.names.add(name);\n return name;\n }\n}\n\n//#endregion\n\n//#region ----- Helpers -----\n\nfunction stamp(nodes: AXEConvertedWidgetNode[], slot: 'header' | 'footer'): AXEConvertedWidgetNode[] {\n return nodes.map((node) => ({ ...node, meta: { ...(node.meta ?? {}), [slot]: true } }));\n}\n\nfunction childWidgets(widget: AXELegacyWidget): AXELegacyWidget[] {\n const widgets = widget.options?.widgets;\n return Array.isArray(widgets) ? widgets.filter((child) => !!child && typeof child === 'object') : [];\n}\n\nfunction asLegacyWidget(source: unknown): AXELegacyWidget | null {\n if (!source || typeof source !== 'object' || Array.isArray(source)) {\n return null;\n }\n return source as AXELegacyWidget;\n}\n\nfunction fieldName(widget: AXELegacyWidget): string | undefined {\n const name = stringOption(widget.options, 'name');\n return name || undefined;\n}\n\nfunction stringOption(record: Record<string, unknown> | undefined, key: string): string | undefined {\n const value = record?.[key];\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction numberOption(record: Record<string, unknown> | undefined, key: string): number | undefined {\n const value = record?.[key];\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === 'string' && value.trim() && Number.isFinite(Number(value))) {\n return Number(value);\n }\n return undefined;\n}\n\nfunction recordOption(value: unknown): Record<string, unknown> | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n return value as Record<string, unknown>;\n}\n\nfunction arrayOption(record: Record<string, unknown> | undefined, key: string): unknown[] | undefined {\n const value = record?.[key];\n return Array.isArray(value) ? value : undefined;\n}\n\nfunction colorOption(record: AXELegacyOptions | undefined, key: string): string | undefined {\n const value = stringOption(record, key);\n if (!value || value === 'inherit') {\n return undefined;\n }\n return value;\n}\n\nfunction requiredOptions(widget: AXELegacyWidget): Record<string, unknown> {\n const items = arrayOption(recordOption(widget.options?.['validator']), 'items') ?? [];\n const required = items.some((item) => recordOption(item)?.['type'] === 'required');\n return required ? { validations: { required: true } } : {};\n}\n\nfunction sanitizeName(value: string | undefined): string {\n return (value ?? '').trim().replace(/[^\\w-]/g, '');\n}\n\nfunction renderText(\n text: string,\n options: AXELegacyOptions | undefined,\n): { content: string; format: 'plain' | 'html'; style?: string } {\n const styles = Array.isArray(options?.['textStyle'])\n ? options['textStyle'].filter((item): item is string => typeof item === 'string')\n : [];\n const css: string[] = [];\n const color = colorOption(options, 'color');\n const align = presentStyle(stringOption(options, 'textAlign'));\n const fontSize = presentStyle(stringOption(options, 'fontSize'));\n const font = presentStyle(stringOption(options, 'font'));\n if (color) {\n css.push(`color:${color}`);\n }\n if (align) {\n css.push(`text-align:${align}`);\n }\n if (fontSize) {\n css.push(`font-size:${fontSizeToCss(fontSize)}`);\n }\n if (font) {\n css.push(`font-family:${font}`);\n }\n if (styles.includes('bold')) {\n css.push('font-weight:bold');\n }\n if (styles.includes('italic')) {\n css.push('font-style:italic');\n }\n if (styles.includes('underline')) {\n css.push('text-decoration:underline');\n }\n const tidy = tidyLegacyText(text);\n const hasHtml = /<[a-z][\\s\\S]*>/i.test(tidy);\n return {\n content: tidy,\n format: hasHtml ? 'html' : 'plain',\n ...(css.length ? { style: css.join(';') } : {}),\n };\n}\n\nfunction presentStyle(value: string | undefined): string | undefined {\n if (!value || value === 'inherit') {\n return undefined;\n }\n return value;\n}\n\nfunction layoutChrome(widget: AXELegacyWidget): Record<string, unknown> {\n const box = parseBoxStyle(widget.options?.['boxStyle']);\n const background = colorOption(widget.options, 'bgColor');\n return {\n ...(box ? borderOptions(box) : {}),\n ...(box ? spacingOptions(box) : {}),\n ...(background ? { backgroundColor: background } : {}),\n };\n}\n\nfunction parseBoxStyle(raw: unknown): Record<string, unknown> | undefined {\n if (!raw) {\n return undefined;\n }\n if (typeof raw === 'string') {\n try {\n const parsed: unknown = JSON.parse(raw);\n return recordOption(parsed);\n } catch {\n return undefined;\n }\n }\n return recordOption(raw);\n}\n\nfunction borderOptions(box: Record<string, unknown>): Record<string, unknown> {\n const border = recordOption(box['border']);\n if (!border) {\n return {};\n }\n const sides = (['top', 'right', 'bottom', 'left'] as const).map((side) => sideValue(border[side]));\n if (sides.every((side) => side <= 0)) {\n return {};\n }\n const declared = stringOption(box, 'borderColor') || stringOption(border, 'borderColor');\n const color = declared || '#333';\n return {\n border: {\n width: fourShorthand(sides.map((side) => (side > 0 ? `${side}px` : '0'))),\n style: fourShorthand(sides.map((side) => (side > 0 ? 'solid' : 'none'))),\n color: fourShorthand([color, color, color, color]),\n },\n };\n}\n\nfunction spacingOptions(box: Record<string, unknown>): Record<string, unknown> {\n const padding = sideShorthand(recordOption(box['padding']));\n const margin = sideShorthand(recordOption(box['margin']));\n if (!padding && !margin) {\n return {};\n }\n return {\n spacing: {\n ...(padding ? { padding } : {}),\n ...(margin ? { margin } : {}),\n },\n };\n}\n\nfunction sideShorthand(sides: Record<string, unknown> | undefined): string | undefined {\n if (!sides) {\n return undefined;\n }\n const values = (['top', 'right', 'bottom', 'left'] as const).map((side) => sideValue(sides[side]));\n if (values.every((side) => side <= 0)) {\n return undefined;\n }\n return fourShorthand(values.map((side) => `${side}px`));\n}\n\nfunction sideValue(value: unknown): number {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === 'string' && value.trim() && Number.isFinite(Number(value))) {\n return Number(value);\n }\n return 0;\n}\n\nfunction fourShorthand(values: string[]): string {\n const [top, right, bottom, left] = values;\n if (top === right && right === bottom && bottom === left) {\n return top;\n }\n if (top === bottom && right === left) {\n return `${top} ${right}`;\n }\n if (right === left) {\n return `${top} ${right} ${bottom}`;\n }\n return `${top} ${right} ${bottom} ${left}`;\n}\n\nfunction cssLength(value: unknown): string | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return `${value}px`;\n }\n if (typeof value !== 'string') {\n return undefined;\n }\n const trimmed = value.trim();\n if (!trimmed || trimmed === 'inherit') {\n return undefined;\n }\n return /^\\d+(\\.\\d+)?$/.test(trimmed) ? `${trimmed}px` : trimmed;\n}\n\ninterface AXEPlacedLegacyCell {\n cell: AXELegacyWidget;\n col: number;\n colSpan: number;\n}\n\n/** Places legacy cells the same way the table widget does, so column tracks line up. */\nfunction placeLegacyCells(rows: AXELegacyWidget[]): { columns: number; placed: AXEPlacedLegacyCell[] } {\n const rowCells = rows.map((row) => childWidgets(row).filter((cell) => cell.options?.['isDelete'] !== true));\n const columns = Math.max(\n 1,\n ...rowCells.map((cells) => cells.reduce((sum, cell) => sum + (numberOption(cell.options, 'colspan') ?? 1), 0)),\n );\n const occupied: boolean[][] = [];\n const placed: AXEPlacedLegacyCell[] = [];\n const ensureRow = (rowIndex: number) => {\n while (occupied.length <= rowIndex) {\n occupied.push(Array.from({ length: columns }, () => false));\n }\n };\n let rowIndex = 0;\n for (const cells of rowCells) {\n for (const cell of cells) {\n const colSpan = Math.min(columns, Math.max(1, numberOption(cell.options, 'colspan') ?? 1));\n const rowSpan = Math.max(1, numberOption(cell.options, 'rowspan') ?? 1);\n let landed = false;\n while (!landed) {\n ensureRow(rowIndex);\n for (let col = 0; col < columns; col++) {\n if (col + colSpan > columns || occupied[rowIndex][col]) {\n continue;\n }\n let free = true;\n for (let row = 0; row < rowSpan && free; row++) {\n ensureRow(rowIndex + row);\n for (let span = 0; span < colSpan; span++) {\n if (occupied[rowIndex + row][col + span]) {\n free = false;\n break;\n }\n }\n }\n if (!free) {\n continue;\n }\n for (let row = 0; row < rowSpan; row++) {\n for (let span = 0; span < colSpan; span++) {\n occupied[rowIndex + row][col + span] = true;\n }\n }\n placed.push({ cell, col, colSpan });\n landed = true;\n break;\n }\n if (!landed) {\n rowIndex += 1;\n }\n }\n }\n rowIndex += 1;\n }\n return { columns, placed };\n}\n\n/**\n * One CSS length per column. A colspan cell keeps a percentage by splitting it,\n * and drops a pixel width (the old 30px-on-a-merged-cell leftover).\n */\nfunction columnWidthTracks(columns: number, placed: AXEPlacedLegacyCell[]): string[] | undefined {\n const tracks: Array<string | undefined> = Array.from({ length: columns });\n for (const item of placed) {\n if (item.colSpan !== 1 || tracks[item.col]) {\n continue;\n }\n const length = trackLength(item.cell, columns);\n if (length) {\n tracks[item.col] = length;\n }\n }\n for (const item of placed) {\n if (item.colSpan <= 1) {\n continue;\n }\n const length = cssLength(item.cell.options?.['width']);\n if (!length?.endsWith('%')) {\n continue;\n }\n const percent = Number(length.slice(0, -1));\n if (!Number.isFinite(percent) || percent <= 0 || percent >= 100) {\n continue;\n }\n const covered = Array.from({ length: item.colSpan }, (_, index) => item.col + index);\n if (covered.some((index) => tracks[index])) {\n continue;\n }\n const share = splitPercent(percent, item.colSpan);\n for (const index of covered) {\n tracks[index] = share;\n }\n }\n if (tracks.some((track) => !track)) {\n return undefined;\n }\n return tracks.filter((track): track is string => !!track);\n}\n\n/** Width painted on one cell when the table has no complete column model. */\nfunction singleColumnWidth(cell: AXELegacyWidget, columns: number): string | undefined {\n if ((numberOption(cell.options, 'colspan') ?? 1) !== 1) {\n return undefined;\n }\n return trackLength(cell, columns);\n}\n\nfunction trackLength(cell: AXELegacyWidget, columns: number): string | undefined {\n const length = cssLength(cell.options?.['width']);\n if (!length?.endsWith('%')) {\n return length;\n }\n const percent = Number(length.slice(0, -1));\n if (!Number.isFinite(percent) || percent <= 0 || (percent >= 100 && columns > 1)) {\n return undefined;\n }\n return length;\n}\n\n/** First real cell border, applied once on the table so adjacent rules collapse. */\nfunction tableBorderItems(rows: AXELegacyWidget[]): Record<string, string> | undefined {\n for (const row of rows) {\n for (const cell of childWidgets(row)) {\n if (cell.options?.['isDelete'] === true) {\n continue;\n }\n const border = recordOption(layoutChrome(cell)['border']);\n const width = border ? stringOption(border, 'width') : undefined;\n if (!border || !width || width === '0' || width === '0px') {\n continue;\n }\n return {\n width,\n style: stringOption(border, 'style') || 'solid',\n color: stringOption(border, 'color') || '#333',\n radius: '0',\n };\n }\n }\n return undefined;\n}\n\nfunction fontSizeToCss(value: string): string {\n const named: Record<string, string> = {\n 'xx-small': '10px',\n 'x-small': '12px',\n smaller: '13px',\n small: '14px',\n medium: '16px',\n large: '18px',\n larger: '20px',\n 'x-large': '24px',\n 'xx-large': '32px',\n };\n return named[value] ?? value;\n}\n\n/** Drops the trailing breaks the old rich-text editor leaves on every label. */\nfunction tidyLegacyText(text: string): string {\n return text.replace(/(?:&nbsp;|\\s|<br\\s*\\/?>)+$/gi, '');\n}\n\nfunction cellChrome(widget: AXELegacyWidget, rowBackground?: string): Record<string, unknown> {\n const chrome = layoutChrome(widget);\n delete chrome['border'];\n if (!chrome['backgroundColor'] && rowBackground) {\n chrome['backgroundColor'] = rowBackground;\n }\n const textAlign = presentStyle(stringOption(widget.options, 'textAlign'));\n const verticalAlign = presentStyle(stringOption(widget.options, 'verticalAlign'));\n return {\n ...chrome,\n ...(textAlign ? { textAlign } : {}),\n ...(verticalAlign ? { verticalAlign } : {}),\n };\n}\n\nfunction borderItemsFromWidget(widget: AXELegacyWidget): Record<string, string> | undefined {\n const border = recordOption(layoutChrome(widget)['border']);\n const width = border ? stringOption(border, 'width') : undefined;\n if (!border || !width || width === '0' || width === '0px') {\n return undefined;\n }\n return {\n width,\n style: stringOption(border, 'style') || 'solid',\n color: stringOption(border, 'color') || '#333',\n radius: '0',\n };\n}\n\nfunction borderItemsFromWidgets(widgets: AXELegacyWidget[]): Record<string, string> | undefined {\n for (const widget of widgets) {\n const border = borderItemsFromWidget(widget);\n if (border) {\n return border;\n }\n }\n return undefined;\n}\n\nfunction sharePercent(part: number, total: number): string {\n return percentText((part / total) * 100);\n}\n\nfunction splitPercent(percent: number, parts: number): string {\n return percentText(percent / parts);\n}\n\nfunction percentText(value: number): string {\n const rounded = Math.round(value * 100) / 100;\n return `${rounded}%`;\n}\n\nfunction alignSelfFromVertical(value: string | undefined): string | undefined {\n if (value === 'top') {\n return 'flex-start';\n }\n if (value === 'middle') {\n return 'center';\n }\n if (value === 'bottom') {\n return 'flex-end';\n }\n return undefined;\n}\n\n//#endregion\n","//#region ----- Imports -----\n\nimport { AXToastService } from '@acorex/components/toast';\nimport { AXFileService } from '@acorex/core/file';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { Injectable, inject, signal } from '@angular/core';\nimport {\n convertLegacyFormPage,\n type AXELegacyFormConvertWarning,\n} from './legacy-form-converter';\nimport type { AXELegacyFormImportSelection } from './legacy-form-import.types';\n\n//#endregion\n\n//#region ----- Types -----\n\ninterface AXEDesignerContentLoader {\n loadByContent(content: string): Promise<void>;\n}\n\n//#endregion\n\n//#region ----- Service -----\n\n/**\n * Picks a legacy form-builder JSON file, converts it, and loads the result\n * onto the open layout designer.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXELegacyFormImportService {\n //#region ----- Services & Dependencies -----\n\n private readonly fileService = inject(AXFileService);\n private readonly toastService = inject(AXToastService);\n private readonly translationService = inject(AXTranslationService);\n\n //#endregion\n\n //#region ----- State Signals -----\n\n readonly selection = signal<AXELegacyFormImportSelection | null>(null);\n\n //#endregion\n\n //#region ----- File Selection -----\n\n async chooseJsonFile(designer: unknown): Promise<void> {\n const files = await this.fileService.choose({ multiple: false, accept: 'application/json,.json' });\n const file = files?.[0];\n if (!file) {\n return;\n }\n\n const rawText = await file.text();\n const document = this.parseJsonDocument(rawText);\n const fileName = file.name?.trim() || 'form.json';\n if (document === undefined) {\n this.selection.set(null);\n await this.showInvalidJsonToast();\n return;\n }\n\n try {\n const converted = convertLegacyFormPage(document);\n this.selection.set({\n fileName,\n rawText,\n document,\n converted: converted.document,\n warnings: converted.warnings,\n });\n await this.loadOntoDesigner(designer, converted.document);\n await this.showConvertedToast(fileName, converted.warnings);\n } catch (error) {\n this.selection.set({ fileName, rawText, document, warnings: [] });\n if (error instanceof Error && error.message === 'LEGACY_PAGE_EXPECTED') {\n await this.showNotLegacyToast();\n return;\n }\n await this.showConvertFailedToast();\n }\n }\n\n //#endregion\n\n //#region ----- Helpers -----\n\n private parseJsonDocument(rawText: string): unknown | undefined {\n try {\n const parsed: unknown = JSON.parse(rawText);\n if (parsed === null || typeof parsed !== 'object') {\n return undefined;\n }\n return parsed;\n } catch {\n return undefined;\n }\n }\n\n private async loadOntoDesigner(designer: unknown, document: unknown): Promise<void> {\n if (!isDesignerContentLoader(designer)) {\n return;\n }\n await designer.loadByContent(JSON.stringify(document));\n }\n\n private async showConvertedToast(fileName: string, warnings: AXELegacyFormConvertWarning[]): Promise<void> {\n const title = await this.translationService.translateAsync(\n '@form-template-management:legacyImport.converted-title',\n );\n const summary = (\n await Promise.all(warnings.map((warning) => this.translateWarning(warning)))\n ).join(' ');\n const content = await this.translationService.translateAsync(\n '@form-template-management:legacyImport.converted-content',\n { params: { name: fileName, summary } },\n );\n this.toastService.show({ color: warnings.length ? 'warning' : 'success', title, content });\n }\n\n private async translateWarning(warning: AXELegacyFormConvertWarning): Promise<string> {\n return this.translationService.translateAsync(\n `@form-template-management:legacyImport.warnings.${warning.code}`,\n { params: { count: warning.count } },\n );\n }\n\n private async showInvalidJsonToast(): Promise<void> {\n const title = await this.translationService.translateAsync(\n '@form-template-management:legacyImport.invalid-title',\n );\n const content = await this.translationService.translateAsync(\n '@form-template-management:legacyImport.invalid-content',\n );\n this.toastService.show({ color: 'danger', title, content });\n }\n\n private async showNotLegacyToast(): Promise<void> {\n const title = await this.translationService.translateAsync(\n '@form-template-management:legacyImport.not-legacy-title',\n );\n const content = await this.translationService.translateAsync(\n '@form-template-management:legacyImport.not-legacy-content',\n );\n this.toastService.show({ color: 'danger', title, content });\n }\n\n private async showConvertFailedToast(): Promise<void> {\n const title = await this.translationService.translateAsync(\n '@form-template-management:legacyImport.failed-title',\n );\n const content = await this.translationService.translateAsync(\n '@form-template-management:legacyImport.failed-content',\n );\n this.toastService.show({ color: 'danger', title, content });\n }\n\n //#endregion\n}\n\n//#endregion\n\nfunction isDesignerContentLoader(value: unknown): value is AXEDesignerContentLoader {\n return !!value && typeof value === 'object' && typeof (value as AXEDesignerContentLoader).loadByContent === 'function';\n}\n","//#region ----- Imports -----\n\nimport { AXPHookProvider } from '@acorex-platform/framework-client/core';\nimport {\n AXPLayoutDesignerHeaderMenuHookKeys,\n type AXPLayoutDesignerHeaderMenuSubmenuPayload,\n} from '@acorex-platform/framework-client/layout/designer';\nimport { inject } from '@angular/core';\nimport { AXELegacyFormImportService } from './legacy-form-import.service';\n\n//#endregion\n\n//#region ----- Designer Import menu -----\n\n/** Adds File → Import → Convert Legacy JSON on the layout designer. */\nexport const AXELegacyFormImportMenuHookProvider: AXPHookProvider<\n AXPLayoutDesignerHeaderMenuSubmenuPayload,\n AXPLayoutDesignerHeaderMenuSubmenuPayload\n> = {\n key: AXPLayoutDesignerHeaderMenuHookKeys.submenu,\n priority: 30,\n execute: (payload: AXPLayoutDesignerHeaderMenuSubmenuPayload) => {\n if (payload.parentMenuId !== 'import') {\n return payload;\n }\n\n const importer = inject(AXELegacyFormImportService);\n payload.items.push({\n id: 'extensions-layout-designer-legacy-import',\n priority: 10,\n labelKey: '@form-template-management:legacyImport.menu',\n iconClass: 'fa-solid fa-right-left',\n run: () => importer.chooseJsonFile(payload.designer),\n });\n return payload;\n },\n};\n\n//#endregion\n","//#region ----- Imports -----\n\nimport { NgModule } from '@angular/core';\nimport { AXP_HOOK_PROVIDER } from '@acorex-platform/framework-client/core';\nimport { AXELegacyFormImportMenuHookProvider } from './legacy-form-import-menu.hook';\n\n//#endregion\n\n//#region ----- Module -----\n\n/**\n * Layout designer extension that adds File → Import → Convert Legacy JSON.\n * The selected document is held for a later conversion step.\n */\n@NgModule({\n providers: [\n {\n provide: AXP_HOOK_PROVIDER,\n multi: true,\n useValue: AXELegacyFormImportMenuHookProvider,\n },\n ],\n})\nexport class AXELayoutDesignerLegacyImportExtensionModule {}\n\n//#endregion\n","//#region ----- Types -----\n\nimport type { AXEConvertedWidgetNode, AXELegacyFormConvertWarning } from './legacy-form-converter';\n\n/** JSON picked from the designer menu, plus the converted designer document. */\nexport interface AXELegacyFormImportSelection {\n fileName: string;\n rawText: string;\n document: unknown;\n converted?: AXEConvertedWidgetNode;\n warnings: AXELegacyFormConvertWarning[];\n}\n\n//#endregion\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@acorex-platform/extension-layout-designer-legacy-import-client",
3
+ "version": "0.0.46",
4
+ "sideEffects": false,
5
+ "peerDependencies": {
6
+ "@angular/common": "^21.0.0 || ^22.0.0",
7
+ "@angular/core": "^21.0.0 || ^22.0.0"
8
+ },
9
+ "dependencies": {
10
+ "tslib": "^2.3.0"
11
+ },
12
+ "module": "fesm2022/acorex-platform-extension-layout-designer-legacy-import-client.mjs",
13
+ "typings": "types/acorex-platform-extension-layout-designer-legacy-import-client.d.ts",
14
+ "exports": {
15
+ "./package.json": {
16
+ "default": "./package.json"
17
+ },
18
+ ".": {
19
+ "types": "./types/acorex-platform-extension-layout-designer-legacy-import-client.d.ts",
20
+ "default": "./fesm2022/acorex-platform-extension-layout-designer-legacy-import-client.mjs"
21
+ }
22
+ },
23
+ "type": "module"
24
+ }
@@ -0,0 +1,69 @@
1
+ import * as i0 from '@angular/core';
2
+
3
+ /**
4
+ * Layout designer extension that adds File → Import → Convert Legacy JSON.
5
+ * The selected document is held for a later conversion step.
6
+ */
7
+ declare class AXELayoutDesignerLegacyImportExtensionModule {
8
+ static ɵfac: i0.ɵɵFactoryDeclaration<AXELayoutDesignerLegacyImportExtensionModule, never>;
9
+ static ɵmod: i0.ɵɵNgModuleDeclaration<AXELayoutDesignerLegacyImportExtensionModule, never, never, never>;
10
+ static ɵinj: i0.ɵɵInjectorDeclaration<AXELayoutDesignerLegacyImportExtensionModule>;
11
+ }
12
+
13
+ /** Designer widget tree produced by the converter. */
14
+ interface AXEConvertedWidgetNode {
15
+ type: string;
16
+ name?: string;
17
+ path?: string;
18
+ visible?: boolean;
19
+ options?: Record<string, unknown>;
20
+ children?: AXEConvertedWidgetNode[];
21
+ meta?: Record<string, unknown>;
22
+ }
23
+ interface AXELegacyFormConvertWarning {
24
+ code: 'script' | 'remote-data' | 'outlet' | 'image-source' | 'image-input' | 'unknown-widget' | 'table-span' | 'list-columns' | 'merge-field';
25
+ count: number;
26
+ samples: string[];
27
+ }
28
+ interface AXELegacyFormConvertResult {
29
+ document: AXEConvertedWidgetNode;
30
+ warnings: AXELegacyFormConvertWarning[];
31
+ }
32
+ /**
33
+ * Converts a legacy form-builder page JSON into a designer document
34
+ * (`document-layout` of `page-layout` nodes).
35
+ */
36
+ declare function convertLegacyFormPage(source: unknown): AXELegacyFormConvertResult;
37
+
38
+ /** JSON picked from the designer menu, plus the converted designer document. */
39
+ interface AXELegacyFormImportSelection {
40
+ fileName: string;
41
+ rawText: string;
42
+ document: unknown;
43
+ converted?: AXEConvertedWidgetNode;
44
+ warnings: AXELegacyFormConvertWarning[];
45
+ }
46
+
47
+ /**
48
+ * Picks a legacy form-builder JSON file, converts it, and loads the result
49
+ * onto the open layout designer.
50
+ */
51
+ declare class AXELegacyFormImportService {
52
+ private readonly fileService;
53
+ private readonly toastService;
54
+ private readonly translationService;
55
+ readonly selection: i0.WritableSignal<AXELegacyFormImportSelection | null>;
56
+ chooseJsonFile(designer: unknown): Promise<void>;
57
+ private parseJsonDocument;
58
+ private loadOntoDesigner;
59
+ private showConvertedToast;
60
+ private translateWarning;
61
+ private showInvalidJsonToast;
62
+ private showNotLegacyToast;
63
+ private showConvertFailedToast;
64
+ static ɵfac: i0.ɵɵFactoryDeclaration<AXELegacyFormImportService, never>;
65
+ static ɵprov: i0.ɵɵInjectableDeclaration<AXELegacyFormImportService>;
66
+ }
67
+
68
+ export { AXELayoutDesignerLegacyImportExtensionModule, AXELegacyFormImportService, convertLegacyFormPage };
69
+ export type { AXEConvertedWidgetNode, AXELegacyFormConvertResult, AXELegacyFormConvertWarning, AXELegacyFormImportSelection };