@acorex-platform/module-content-management-client 0.0.56 → 0.0.58
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/fesm2022/{acorex-platform-module-content-management-client-template-content-editor-widget-edit.component-CphFsFSd.mjs → acorex-platform-module-content-management-client-template-content-editor-widget-edit.component-h5ING7pF.mjs} +44 -49
- package/fesm2022/acorex-platform-module-content-management-client-template-content-editor-widget-edit.component-h5ING7pF.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-content-management-client.mjs +1 -1
- package/package.json +1 -1
- package/fesm2022/acorex-platform-module-content-management-client-template-content-editor-widget-edit.component-CphFsFSd.mjs.map +0 -1
|
@@ -12,8 +12,8 @@ import { AXTextAreaModule } from '@acorex/components/text-area';
|
|
|
12
12
|
import * as i5 from '@acorex/components/text-box';
|
|
13
13
|
import { AXTextBoxModule } from '@acorex/components/text-box';
|
|
14
14
|
import { AXToastService } from '@acorex/components/toast';
|
|
15
|
-
import * as i6 from '@acorex/components/
|
|
16
|
-
import {
|
|
15
|
+
import * as i6 from '@acorex/components/text-editor';
|
|
16
|
+
import { AXTextEditorModule } from '@acorex/components/text-editor';
|
|
17
17
|
import * as i2$1 from '@acorex/core/translation';
|
|
18
18
|
import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
|
|
19
19
|
import { AXValidationModule } from '@acorex/core/validation';
|
|
@@ -108,17 +108,17 @@ class AXMTemplateContentEditorWidgetEditComponent extends AXPValueWidgetComponen
|
|
|
108
108
|
/** Dedupes in-flight preview loads when effect re-runs. */
|
|
109
109
|
this.previewRequestSeq = 0;
|
|
110
110
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
111
|
+
* TipTap `commitValue(html, true)` marks hydration as a user edit.
|
|
112
|
+
* Ignore writes until that timer elapses after a programmatic sync.
|
|
113
113
|
*/
|
|
114
|
-
this.
|
|
115
|
-
this.
|
|
114
|
+
this.suppressEditorWrites = false;
|
|
115
|
+
this.suppressEditorWritesTimer = null;
|
|
116
116
|
this.lastSyncedChannel = null;
|
|
117
117
|
this.lastSyncedViewMode = null;
|
|
118
118
|
/** Drops the ax-tabs init event so it cannot overwrite the content-channel tab. */
|
|
119
119
|
this.ignoreNextChannelTabChange = false;
|
|
120
|
-
this.
|
|
121
|
-
...(ngDevMode ? [{ debugName: "
|
|
120
|
+
this.editorRef = viewChild('editorRef', /* @ts-ignore */
|
|
121
|
+
...(ngDevMode ? [{ debugName: "editorRef" }] : /* istanbul ignore next */ []));
|
|
122
122
|
this.bodyTextareaRef = viewChild('bodyTextarea', { ...(ngDevMode ? { debugName: "bodyTextareaRef" } : /* istanbul ignore next */ {}), read: (ElementRef) });
|
|
123
123
|
this.availableChannels = signal([], /* @ts-ignore */
|
|
124
124
|
...(ngDevMode ? [{ debugName: "availableChannels" }] : /* istanbul ignore next */ []));
|
|
@@ -169,7 +169,7 @@ class AXMTemplateContentEditorWidgetEditComponent extends AXPValueWidgetComponen
|
|
|
169
169
|
}
|
|
170
170
|
});
|
|
171
171
|
/**
|
|
172
|
-
*
|
|
172
|
+
* TipTap keeps its own document; one-way ngModel does not refresh it when the entity
|
|
173
173
|
* loads, the user discards, or the active channel tab changes.
|
|
174
174
|
*/
|
|
175
175
|
effect(() => {
|
|
@@ -177,29 +177,29 @@ class AXMTemplateContentEditorWidgetEditComponent extends AXPValueWidgetComponen
|
|
|
177
177
|
const channel = this.activeChannel();
|
|
178
178
|
const changeState = this.contextService.changeEvent().state;
|
|
179
179
|
const body = channel ? this.getChannelBody(channel.name) : '';
|
|
180
|
-
const editor = this.
|
|
180
|
+
const editor = this.editorRef();
|
|
181
181
|
if (viewMode !== 'edit' || !channel || channel.type === 'plain' || !editor) {
|
|
182
182
|
this.lastSyncedViewMode = viewMode;
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
185
|
const channelChanged = channel.name !== this.lastSyncedChannel;
|
|
186
186
|
const viewModeChanged = viewMode !== this.lastSyncedViewMode;
|
|
187
|
-
const editorChanged = editor !== this.
|
|
188
|
-
const contextReload = this.
|
|
187
|
+
const editorChanged = editor !== this.lastSyncedEditor;
|
|
188
|
+
const contextReload = this.shouldSyncEditorFromContext(changeState);
|
|
189
189
|
if (!channelChanged && !viewModeChanged && !editorChanged && !contextReload) {
|
|
190
190
|
return;
|
|
191
191
|
}
|
|
192
192
|
untracked(() => {
|
|
193
193
|
this.lastSyncedChannel = channel.name;
|
|
194
194
|
this.lastSyncedViewMode = viewMode;
|
|
195
|
-
this.
|
|
196
|
-
void this.
|
|
195
|
+
this.lastSyncedEditor = editor;
|
|
196
|
+
void this.applyEditorContentWhenReady(editor, body);
|
|
197
197
|
});
|
|
198
198
|
});
|
|
199
199
|
this.settingsService.onChanged.subscribe(() => {
|
|
200
200
|
void this.refreshChannelConfiguration();
|
|
201
201
|
});
|
|
202
|
-
this.destroyRef.onDestroy(() => this.
|
|
202
|
+
this.destroyRef.onDestroy(() => this.clearSuppressEditorWritesTimer());
|
|
203
203
|
}
|
|
204
204
|
isChannelConfigured(name) {
|
|
205
205
|
return this.channelConfigured()[name] ?? true;
|
|
@@ -309,7 +309,7 @@ class AXMTemplateContentEditorWidgetEditComponent extends AXPValueWidgetComponen
|
|
|
309
309
|
const idx = chs.findIndex((c) => names.includes(c.name));
|
|
310
310
|
if (idx >= 0) {
|
|
311
311
|
this.ignoreNextChannelTabChange = true;
|
|
312
|
-
this.
|
|
312
|
+
this.beginSuppressEditorWrites();
|
|
313
313
|
this.activeTabIndex.set(idx);
|
|
314
314
|
setTimeout(() => {
|
|
315
315
|
this.ignoreNextChannelTabChange = false;
|
|
@@ -321,7 +321,7 @@ class AXMTemplateContentEditorWidgetEditComponent extends AXPValueWidgetComponen
|
|
|
321
321
|
if (this.ignoreNextChannelTabChange || index === this.activeTabIndex()) {
|
|
322
322
|
return;
|
|
323
323
|
}
|
|
324
|
-
this.
|
|
324
|
+
this.beginSuppressEditorWrites();
|
|
325
325
|
this.activeTabIndex.set(index);
|
|
326
326
|
}
|
|
327
327
|
/** Capture cursor/selection before dropdown opens (runs in mousedown capture phase) */
|
|
@@ -397,8 +397,8 @@ class AXMTemplateContentEditorWidgetEditComponent extends AXPValueWidgetComponen
|
|
|
397
397
|
? startNode.parentElement
|
|
398
398
|
: startNode;
|
|
399
399
|
const editable = elem?.closest?.('[contenteditable="true"]');
|
|
400
|
-
const
|
|
401
|
-
const target = editable ??
|
|
400
|
+
const editorHost = this.editorRef();
|
|
401
|
+
const target = editable ?? editorHost?.getHostElement()?.querySelector?.('[contenteditable="true"]');
|
|
402
402
|
if (target) {
|
|
403
403
|
target.focus();
|
|
404
404
|
const sel = document.getSelection();
|
|
@@ -441,7 +441,7 @@ class AXMTemplateContentEditorWidgetEditComponent extends AXPValueWidgetComponen
|
|
|
441
441
|
this.setChannelBody(targetName, this.getChannelBody(sourceName));
|
|
442
442
|
const active = this.activeChannel();
|
|
443
443
|
if (active?.name === targetName && active.type === 'rich') {
|
|
444
|
-
void this.
|
|
444
|
+
void this.applyEditorContentWhenReady(this.editorRef(), this.getChannelBody(targetName));
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
447
|
getChannelSubject(name) {
|
|
@@ -481,8 +481,8 @@ class AXMTemplateContentEditorWidgetEditComponent extends AXPValueWidgetComponen
|
|
|
481
481
|
}
|
|
482
482
|
this.setChannelBody(name, e.value ?? '');
|
|
483
483
|
}
|
|
484
|
-
|
|
485
|
-
if (this.
|
|
484
|
+
handleEditorChange(name, e) {
|
|
485
|
+
if (this.suppressEditorWrites || !e.isUserInteraction) {
|
|
486
486
|
return;
|
|
487
487
|
}
|
|
488
488
|
const val = typeof e === 'object' && e !== null && 'value' in e
|
|
@@ -517,39 +517,34 @@ class AXMTemplateContentEditorWidgetEditComponent extends AXPValueWidgetComponen
|
|
|
517
517
|
}
|
|
518
518
|
this.setValue(nextValue);
|
|
519
519
|
}
|
|
520
|
-
|
|
520
|
+
shouldSyncEditorFromContext(state) {
|
|
521
521
|
return state === 'restored' || state === 'initiated';
|
|
522
522
|
}
|
|
523
|
-
|
|
524
|
-
this.
|
|
525
|
-
this.
|
|
526
|
-
this.
|
|
527
|
-
this.
|
|
528
|
-
this.
|
|
523
|
+
beginSuppressEditorWrites() {
|
|
524
|
+
this.suppressEditorWrites = true;
|
|
525
|
+
this.clearSuppressEditorWritesTimer();
|
|
526
|
+
this.suppressEditorWritesTimer = setTimeout(() => {
|
|
527
|
+
this.suppressEditorWrites = false;
|
|
528
|
+
this.suppressEditorWritesTimer = null;
|
|
529
529
|
}, 500);
|
|
530
530
|
}
|
|
531
|
-
|
|
532
|
-
if (this.
|
|
533
|
-
clearTimeout(this.
|
|
534
|
-
this.
|
|
531
|
+
clearSuppressEditorWritesTimer() {
|
|
532
|
+
if (this.suppressEditorWritesTimer) {
|
|
533
|
+
clearTimeout(this.suppressEditorWritesTimer);
|
|
534
|
+
this.suppressEditorWritesTimer = null;
|
|
535
535
|
}
|
|
536
536
|
}
|
|
537
|
-
async
|
|
537
|
+
async applyEditorContentWhenReady(host, text) {
|
|
538
538
|
const content = text ?? '';
|
|
539
539
|
for (let attempt = 0; attempt < 30; attempt++) {
|
|
540
|
-
const editor = this.
|
|
541
|
-
if (!editor) {
|
|
540
|
+
const editor = this.editorRef() ?? host;
|
|
541
|
+
if (!editor?.getEditor()) {
|
|
542
542
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
543
543
|
continue;
|
|
544
544
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
catch {
|
|
551
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
552
|
-
}
|
|
545
|
+
this.beginSuppressEditorWrites();
|
|
546
|
+
editor.getEditorService().setContent(content, false);
|
|
547
|
+
return;
|
|
553
548
|
}
|
|
554
549
|
}
|
|
555
550
|
/**
|
|
@@ -796,7 +791,7 @@ class AXMTemplateContentEditorWidgetEditComponent extends AXPValueWidgetComponen
|
|
|
796
791
|
.replace(/\n/g, '<br/>');
|
|
797
792
|
}
|
|
798
793
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMTemplateContentEditorWidgetEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
799
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMTemplateContentEditorWidgetEditComponent, isStandalone: true, selector: "axm-template-content-editor-widget-edit", viewQueries: [{ propertyName: "wysiwygRef", first: true, predicate: ["wysiwygRef"], descendants: true, isSignal: true }, { propertyName: "bodyTextareaRef", first: true, predicate: ["bodyTextarea"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Template Content Editor: Channel tabs and content per channel -->\n<div class=\"flex flex-col gap-4 w-full\">\n <!-- Channel tabs navigation -->\n <div class=\"flex items-center gap-2 flex-wrap\">\n <ax-tabs\n [look]=\"'with-line'\"\n (onActiveTabChanged)=\"onChannelTabChanged($event.index)\"\n class=\"flex-1 min-w-0\"\n >\n @for (ch of availableChannels(); track ch.name; let i = $index) {\n <ax-tab-item\n [text]=\"(ch.title | translate | async) ?? ch.name\"\n [key]=\"i.toString()\"\n [active]=\"activeTabIndex() === i\"\n ></ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n @if (activeChannel(); as ch) {\n <!-- Channel content area: Edit mode or Preview mode -->\n <div class=\"mb-4 p-4\">\n @if (!isChannelConfigured(ch.name) && ch.notConfiguredMessageKey) {\n <div\n class=\"mb-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-3 rounded border border-amber-300 bg-amber-50 dark:border-amber-700 dark:bg-amber-950/30\"\n >\n <p class=\"text-sm text-amber-900 dark:text-amber-100\">\n {{ ch.notConfiguredMessageKey | translate | async }}\n </p>\n @if (ch.configureSettings) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.configure-channel'\n | translate\n | async\n \"\n look=\"outline\"\n color=\"primary\"\n size=\"sm\"\n (onClick)=\"openChannelConfigure(ch)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-gear\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </div>\n }\n\n @if (viewMode() === 'edit') {\n <!-- Edit mode: Subject field (for channels that support it, e.g. Email) -->\n @if (ch.hasSubject) {\n <div class=\"mb-3\">\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}\n </label>\n <ax-text-box\n [ngModel]=\"getChannelSubject(ch.name)\"\n (onValueChanged)=\"handleSubjectChange(ch.name, $event)\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.subject.placeholder'\n | translate\n | async)!\n \"\n ></ax-text-box>\n </div>\n }\n\n <!-- Edit mode: Body field (plain text or rich WYSIWYG) -->\n <div>\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.body.title'\n | translate\n | async\n }}\n </label>\n <!--->\n <!-- ----- Plain-text body for SMS-style channels ----- -->\n @if (ch.type === 'plain') {\n <ax-text-area\n #bodyTextarea\n [ngModel]=\"getChannelBody(ch.name)\"\n (onValueChanged)=\"handlePlainBodyChange(ch.name, $event)\"\n [rows]=\"8\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.plain'\n | translate\n | async)!\n \"\n ></ax-text-area>\n }\n <!-- ----- Recreate Quill per channel so tab switches do not keep the previous HTML ----- -->\n @else {\n @for (channelName of [ch.name]; track channelName) {\n <ax-wysiwyg-container\n #wysiwygRef\n [placeHolder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.rich'\n | translate\n | async)!\n \"\n [ngModel]=\"getChannelBody(channelName)\"\n (onValueChanged)=\"handleWysiwygChange(channelName, $event)\"\n [look]=\"'solid'\"\n >\n <ax-wysiwyg-view [style.min-height.px]=\"200\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar>\n <ax-prefix>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n </ax-prefix>\n </ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n }\n }\n </div>\n } @else {\n <!-- Preview mode: Rendered content with variable placeholders replaced by sample values -->\n <div class=\"space-y-2\">\n @if (ch.hasSubject && previewSubject(ch.name)) {\n <div>\n <span class=\"text-xs text-gray-500\"\n >{{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}:\n </span>\n <span class=\"text-sm\">{{ previewSubject(ch.name) }}</span>\n </div>\n }\n <!-- ----- Rich email keeps inline styles; plain channels use pre-wrap ----- -->\n <div\n class=\"text-sm p-3 bg-gray-100 dark:bg-gray-900 rounded border overflow-auto\"\n [class.whitespace-pre-wrap]=\"ch.type !== 'rich'\"\n [innerHTML]=\"previewBodyHtml(ch.name)\"\n ></div>\n </div>\n }\n </div>\n\n <!-- Footer: Action buttons (left) + Edit/Preview toggle (right) in single row -->\n <div\n class=\"flex flex-nowrap items-center justify-between gap-3 pt-3 mt-1 border-t border-gray-200 dark:border-gray-700\"\n >\n <div class=\"flex flex-nowrap items-center gap-2 min-w-0\">\n @if (viewMode() === 'edit') {\n <!-- ----- Insert variable dropdown from platform tokens ----- -->\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-variable'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-code\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (v of availableVariables(); track v.name) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(v.title || v.name) + ' ({{' + v.name + '}})'\"\n (onClick)=\"insertVariable(ch.name, v.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getVariableIcon(v)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n </ax-button>\n </div>\n <!--->\n <!-- ----- Insert reserved [content] slot for master templates ----- -->\n @if (isMasterKind()) {\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-content-slot'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n (onClick)=\"insertContentSlot(ch.name)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n }\n <!--->\n <!-- ----- Copy subject/body from another channel ----- -->\n @if (otherChannelsWithContent(ch.name).length > 0) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.copy-from'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-copy\"></ax-icon>\n </ax-prefix>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (\n src of otherChannelsWithContent(ch.name);\n track src.name\n ) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(src.title | translate | async) ?? src.name\"\n (onClick)=\"copyFromChannel(ch.name, src.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getChannelIcon(src)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n }\n </div>\n <div>\n <ax-tabs [look]=\"'default'\">\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.edit'\n | translate\n | async) ?? 'Edit'\n \"\n [active]=\"viewMode() === 'edit'\"\n (onClick)=\"viewMode.set('edit')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.preview'\n | translate\n | async) ?? 'Preview'\n \"\n [active]=\"viewMode() === 'preview'\"\n (onClick)=\"viewMode.set('preview')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-eye\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n </ax-tabs>\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i3.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "reorderable", "reorderDelay", "renderMode", "stacked", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged", "onTabsReordered"] }, { kind: "component", type: i3.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "ngmodule", type: AXTextAreaModule }, { kind: "component", type: i4.AXTextAreaComponent, selector: "ax-text-area", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "placeholder", "maxLength", "look", "rows", "allowResize", "showCounter", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i5.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "maskPattern", "customTokens", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onMaskChanged"] }, { kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i6.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "readonly", "disabled", "value", "placeHolder", "initialLine", "mode"], outputs: ["onValueChanged"] }, { kind: "component", type: i6.AXWysiwygViewComponent, selector: "ax-wysiwyg-view" }, { kind: "component", type: i6.AXWysiwygFontStyleComponent, selector: "ax-wysiwyg-font-style", inputs: ["headingLevels", "buttons", "menuItems"] }, { kind: "component", type: i6.AXWysiwygHistoryComponent, selector: "ax-wysiwyg-history", inputs: ["buttons"] }, { kind: "component", type: i6.AXWysiwygListComponent, selector: "ax-wysiwyg-list", inputs: ["buttons"] }, { kind: "component", type: i6.AXWysiwygToolbarComponent, selector: "ax-wysiwyg-toolbar" }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i7.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i7.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i7.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i8.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
794
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMTemplateContentEditorWidgetEditComponent, isStandalone: true, selector: "axm-template-content-editor-widget-edit", viewQueries: [{ propertyName: "editorRef", first: true, predicate: ["editorRef"], descendants: true, isSignal: true }, { propertyName: "bodyTextareaRef", first: true, predicate: ["bodyTextarea"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Template Content Editor: Channel tabs and content per channel -->\n<div class=\"flex flex-col gap-4 w-full\">\n <!-- Channel tabs navigation -->\n <div class=\"flex items-center gap-2 flex-wrap\">\n <ax-tabs\n [look]=\"'with-line'\"\n (onActiveTabChanged)=\"onChannelTabChanged($event.index)\"\n class=\"flex-1 min-w-0\"\n >\n @for (ch of availableChannels(); track ch.name; let i = $index) {\n <ax-tab-item\n [text]=\"(ch.title | translate | async) ?? ch.name\"\n [key]=\"i.toString()\"\n [active]=\"activeTabIndex() === i\"\n ></ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n @if (activeChannel(); as ch) {\n <!-- Channel content area: Edit mode or Preview mode -->\n <div class=\"mb-4 p-4\">\n @if (!isChannelConfigured(ch.name) && ch.notConfiguredMessageKey) {\n <div\n class=\"mb-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-3 rounded border border-amber-300 bg-amber-50 dark:border-amber-700 dark:bg-amber-950/30\"\n >\n <p class=\"text-sm text-amber-900 dark:text-amber-100\">\n {{ ch.notConfiguredMessageKey | translate | async }}\n </p>\n @if (ch.configureSettings) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.configure-channel'\n | translate\n | async\n \"\n look=\"outline\"\n color=\"primary\"\n size=\"sm\"\n (onClick)=\"openChannelConfigure(ch)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-gear\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </div>\n }\n\n @if (viewMode() === 'edit') {\n <!-- Edit mode: Subject field (for channels that support it, e.g. Email) -->\n @if (ch.hasSubject) {\n <div class=\"mb-3\">\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}\n </label>\n <ax-text-box\n [ngModel]=\"getChannelSubject(ch.name)\"\n (onValueChanged)=\"handleSubjectChange(ch.name, $event)\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.subject.placeholder'\n | translate\n | async)!\n \"\n ></ax-text-box>\n </div>\n }\n\n <!-- Edit mode: Body field (plain text or rich text-editor) -->\n <div>\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.body.title'\n | translate\n | async\n }}\n </label>\n <!--->\n <!-- ----- Plain-text body for SMS-style channels ----- -->\n @if (ch.type === 'plain') {\n <ax-text-area\n #bodyTextarea\n [ngModel]=\"getChannelBody(ch.name)\"\n (onValueChanged)=\"handlePlainBodyChange(ch.name, $event)\"\n [rows]=\"8\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.plain'\n | translate\n | async)!\n \"\n ></ax-text-area>\n }\n <!-- ----- Recreate the rich editor per channel so tab switches do not keep the previous HTML ----- -->\n @else {\n @for (channelName of [ch.name]; track channelName) {\n <ax-text-editor\n #editorRef\n outputFormat=\"html\"\n [placeHolder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.rich'\n | translate\n | async)!\n \"\n [ngModel]=\"getChannelBody(channelName)\"\n (onValueChanged)=\"handleEditorChange(channelName, $event)\"\n [look]=\"'solid'\"\n [initialLine]=\"8\"\n >\n <ax-text-editor-content [style.min-height.px]=\"200\"></ax-text-editor-content>\n <ax-text-editor-toolbar>\n <ax-prefix>\n <ax-text-editor-history></ax-text-editor-history>\n <ax-text-editor-font-style></ax-text-editor-font-style>\n <ax-text-editor-list></ax-text-editor-list>\n </ax-prefix>\n </ax-text-editor-toolbar>\n </ax-text-editor>\n }\n }\n </div>\n } @else {\n <!-- Preview mode: Rendered content with variable placeholders replaced by sample values -->\n <div class=\"space-y-2\">\n @if (ch.hasSubject && previewSubject(ch.name)) {\n <div>\n <span class=\"text-xs text-gray-500\"\n >{{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}:\n </span>\n <span class=\"text-sm\">{{ previewSubject(ch.name) }}</span>\n </div>\n }\n <!-- ----- Rich email keeps inline styles; plain channels use pre-wrap ----- -->\n <div\n class=\"text-sm p-3 bg-gray-100 dark:bg-gray-900 rounded border overflow-auto\"\n [class.whitespace-pre-wrap]=\"ch.type !== 'rich'\"\n [innerHTML]=\"previewBodyHtml(ch.name)\"\n ></div>\n </div>\n }\n </div>\n\n <!-- Footer: Action buttons (left) + Edit/Preview toggle (right) in single row -->\n <div\n class=\"flex flex-nowrap items-center justify-between gap-3 pt-3 mt-1 border-t border-gray-200 dark:border-gray-700\"\n >\n <div class=\"flex flex-nowrap items-center gap-2 min-w-0\">\n @if (viewMode() === 'edit') {\n <!-- ----- Insert variable dropdown from platform tokens ----- -->\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-variable'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-code\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (v of availableVariables(); track v.name) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(v.title || v.name) + ' ({{' + v.name + '}})'\"\n (onClick)=\"insertVariable(ch.name, v.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getVariableIcon(v)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n </ax-button>\n </div>\n <!--->\n <!-- ----- Insert reserved [content] slot for master templates ----- -->\n @if (isMasterKind()) {\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-content-slot'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n (onClick)=\"insertContentSlot(ch.name)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n }\n <!--->\n <!-- ----- Copy subject/body from another channel ----- -->\n @if (otherChannelsWithContent(ch.name).length > 0) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.copy-from'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-copy\"></ax-icon>\n </ax-prefix>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (\n src of otherChannelsWithContent(ch.name);\n track src.name\n ) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(src.title | translate | async) ?? src.name\"\n (onClick)=\"copyFromChannel(ch.name, src.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getChannelIcon(src)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n }\n </div>\n <div>\n <ax-tabs [look]=\"'default'\">\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.edit'\n | translate\n | async) ?? 'Edit'\n \"\n [active]=\"viewMode() === 'edit'\"\n (onClick)=\"viewMode.set('edit')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.preview'\n | translate\n | async) ?? 'Preview'\n \"\n [active]=\"viewMode() === 'preview'\"\n (onClick)=\"viewMode.set('preview')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-eye\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n </ax-tabs>\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXTabsModule }, { kind: "component", type: i3.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "reorderable", "reorderDelay", "renderMode", "stacked", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged", "onTabsReordered"] }, { kind: "component", type: i3.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "ngmodule", type: AXTextAreaModule }, { kind: "component", type: i4.AXTextAreaComponent, selector: "ax-text-area", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "placeholder", "maxLength", "look", "rows", "allowResize", "showCounter", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i5.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "maskPattern", "customTokens", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onMaskChanged"] }, { kind: "ngmodule", type: AXTextEditorModule }, { kind: "component", type: i6.AXTextEditorComponent, selector: "ax-text-editor", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "look", "placeHolder", "outputFormat", "initialLine"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange"] }, { kind: "component", type: i6.AXTextEditorToolbarComponent, selector: "ax-text-editor-toolbar", inputs: ["orientation"] }, { kind: "component", type: i6.AXTextEditorContentComponent, selector: "ax-text-editor-content" }, { kind: "component", type: i6.AXTextEditorHistoryComponent, selector: "ax-text-editor-history" }, { kind: "component", type: i6.AXTextEditorFontStyleComponent, selector: "ax-text-editor-font-style" }, { kind: "component", type: i6.AXTextEditorListComponent, selector: "ax-text-editor-list" }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i7.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i7.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i7.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i8.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
800
795
|
}
|
|
801
796
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMTemplateContentEditorWidgetEditComponent, decorators: [{
|
|
802
797
|
type: Component,
|
|
@@ -808,13 +803,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
808
803
|
AXTabsModule,
|
|
809
804
|
AXTextAreaModule,
|
|
810
805
|
AXTextBoxModule,
|
|
811
|
-
|
|
806
|
+
AXTextEditorModule,
|
|
812
807
|
AXValidationModule,
|
|
813
808
|
AXTranslationModule,
|
|
814
809
|
AXButtonModule,
|
|
815
810
|
AXDropdownModule,
|
|
816
|
-
], template: "<!-- Template Content Editor: Channel tabs and content per channel -->\n<div class=\"flex flex-col gap-4 w-full\">\n <!-- Channel tabs navigation -->\n <div class=\"flex items-center gap-2 flex-wrap\">\n <ax-tabs\n [look]=\"'with-line'\"\n (onActiveTabChanged)=\"onChannelTabChanged($event.index)\"\n class=\"flex-1 min-w-0\"\n >\n @for (ch of availableChannels(); track ch.name; let i = $index) {\n <ax-tab-item\n [text]=\"(ch.title | translate | async) ?? ch.name\"\n [key]=\"i.toString()\"\n [active]=\"activeTabIndex() === i\"\n ></ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n @if (activeChannel(); as ch) {\n <!-- Channel content area: Edit mode or Preview mode -->\n <div class=\"mb-4 p-4\">\n @if (!isChannelConfigured(ch.name) && ch.notConfiguredMessageKey) {\n <div\n class=\"mb-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-3 rounded border border-amber-300 bg-amber-50 dark:border-amber-700 dark:bg-amber-950/30\"\n >\n <p class=\"text-sm text-amber-900 dark:text-amber-100\">\n {{ ch.notConfiguredMessageKey | translate | async }}\n </p>\n @if (ch.configureSettings) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.configure-channel'\n | translate\n | async\n \"\n look=\"outline\"\n color=\"primary\"\n size=\"sm\"\n (onClick)=\"openChannelConfigure(ch)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-gear\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </div>\n }\n\n @if (viewMode() === 'edit') {\n <!-- Edit mode: Subject field (for channels that support it, e.g. Email) -->\n @if (ch.hasSubject) {\n <div class=\"mb-3\">\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}\n </label>\n <ax-text-box\n [ngModel]=\"getChannelSubject(ch.name)\"\n (onValueChanged)=\"handleSubjectChange(ch.name, $event)\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.subject.placeholder'\n | translate\n | async)!\n \"\n ></ax-text-box>\n </div>\n }\n\n <!-- Edit mode: Body field (plain text or rich WYSIWYG) -->\n <div>\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.body.title'\n | translate\n | async\n }}\n </label>\n <!--->\n <!-- ----- Plain-text body for SMS-style channels ----- -->\n @if (ch.type === 'plain') {\n <ax-text-area\n #bodyTextarea\n [ngModel]=\"getChannelBody(ch.name)\"\n (onValueChanged)=\"handlePlainBodyChange(ch.name, $event)\"\n [rows]=\"8\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.plain'\n | translate\n | async)!\n \"\n ></ax-text-area>\n }\n <!-- ----- Recreate Quill per channel so tab switches do not keep the previous HTML ----- -->\n @else {\n @for (channelName of [ch.name]; track channelName) {\n <ax-wysiwyg-container\n #wysiwygRef\n [placeHolder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.rich'\n | translate\n | async)!\n \"\n [ngModel]=\"getChannelBody(channelName)\"\n (onValueChanged)=\"handleWysiwygChange(channelName, $event)\"\n [look]=\"'solid'\"\n >\n <ax-wysiwyg-view [style.min-height.px]=\"200\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar>\n <ax-prefix>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n </ax-prefix>\n </ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n }\n }\n </div>\n } @else {\n <!-- Preview mode: Rendered content with variable placeholders replaced by sample values -->\n <div class=\"space-y-2\">\n @if (ch.hasSubject && previewSubject(ch.name)) {\n <div>\n <span class=\"text-xs text-gray-500\"\n >{{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}:\n </span>\n <span class=\"text-sm\">{{ previewSubject(ch.name) }}</span>\n </div>\n }\n <!-- ----- Rich email keeps inline styles; plain channels use pre-wrap ----- -->\n <div\n class=\"text-sm p-3 bg-gray-100 dark:bg-gray-900 rounded border overflow-auto\"\n [class.whitespace-pre-wrap]=\"ch.type !== 'rich'\"\n [innerHTML]=\"previewBodyHtml(ch.name)\"\n ></div>\n </div>\n }\n </div>\n\n <!-- Footer: Action buttons (left) + Edit/Preview toggle (right) in single row -->\n <div\n class=\"flex flex-nowrap items-center justify-between gap-3 pt-3 mt-1 border-t border-gray-200 dark:border-gray-700\"\n >\n <div class=\"flex flex-nowrap items-center gap-2 min-w-0\">\n @if (viewMode() === 'edit') {\n <!-- ----- Insert variable dropdown from platform tokens ----- -->\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-variable'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-code\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (v of availableVariables(); track v.name) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(v.title || v.name) + ' ({{' + v.name + '}})'\"\n (onClick)=\"insertVariable(ch.name, v.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getVariableIcon(v)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n </ax-button>\n </div>\n <!--->\n <!-- ----- Insert reserved [content] slot for master templates ----- -->\n @if (isMasterKind()) {\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-content-slot'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n (onClick)=\"insertContentSlot(ch.name)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n }\n <!--->\n <!-- ----- Copy subject/body from another channel ----- -->\n @if (otherChannelsWithContent(ch.name).length > 0) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.copy-from'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-copy\"></ax-icon>\n </ax-prefix>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (\n src of otherChannelsWithContent(ch.name);\n track src.name\n ) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(src.title | translate | async) ?? src.name\"\n (onClick)=\"copyFromChannel(ch.name, src.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getChannelIcon(src)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n }\n </div>\n <div>\n <ax-tabs [look]=\"'default'\">\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.edit'\n | translate\n | async) ?? 'Edit'\n \"\n [active]=\"viewMode() === 'edit'\"\n (onClick)=\"viewMode.set('edit')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.preview'\n | translate\n | async) ?? 'Preview'\n \"\n [active]=\"viewMode() === 'preview'\"\n (onClick)=\"viewMode.set('preview')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-eye\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n </ax-tabs>\n </div>\n </div>\n }\n</div>\n" }]
|
|
817
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
811
|
+
], template: "<!-- Template Content Editor: Channel tabs and content per channel -->\n<div class=\"flex flex-col gap-4 w-full\">\n <!-- Channel tabs navigation -->\n <div class=\"flex items-center gap-2 flex-wrap\">\n <ax-tabs\n [look]=\"'with-line'\"\n (onActiveTabChanged)=\"onChannelTabChanged($event.index)\"\n class=\"flex-1 min-w-0\"\n >\n @for (ch of availableChannels(); track ch.name; let i = $index) {\n <ax-tab-item\n [text]=\"(ch.title | translate | async) ?? ch.name\"\n [key]=\"i.toString()\"\n [active]=\"activeTabIndex() === i\"\n ></ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n @if (activeChannel(); as ch) {\n <!-- Channel content area: Edit mode or Preview mode -->\n <div class=\"mb-4 p-4\">\n @if (!isChannelConfigured(ch.name) && ch.notConfiguredMessageKey) {\n <div\n class=\"mb-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-3 rounded border border-amber-300 bg-amber-50 dark:border-amber-700 dark:bg-amber-950/30\"\n >\n <p class=\"text-sm text-amber-900 dark:text-amber-100\">\n {{ ch.notConfiguredMessageKey | translate | async }}\n </p>\n @if (ch.configureSettings) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.configure-channel'\n | translate\n | async\n \"\n look=\"outline\"\n color=\"primary\"\n size=\"sm\"\n (onClick)=\"openChannelConfigure(ch)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-gear\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </div>\n }\n\n @if (viewMode() === 'edit') {\n <!-- Edit mode: Subject field (for channels that support it, e.g. Email) -->\n @if (ch.hasSubject) {\n <div class=\"mb-3\">\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}\n </label>\n <ax-text-box\n [ngModel]=\"getChannelSubject(ch.name)\"\n (onValueChanged)=\"handleSubjectChange(ch.name, $event)\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.subject.placeholder'\n | translate\n | async)!\n \"\n ></ax-text-box>\n </div>\n }\n\n <!-- Edit mode: Body field (plain text or rich text-editor) -->\n <div>\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.body.title'\n | translate\n | async\n }}\n </label>\n <!--->\n <!-- ----- Plain-text body for SMS-style channels ----- -->\n @if (ch.type === 'plain') {\n <ax-text-area\n #bodyTextarea\n [ngModel]=\"getChannelBody(ch.name)\"\n (onValueChanged)=\"handlePlainBodyChange(ch.name, $event)\"\n [rows]=\"8\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.plain'\n | translate\n | async)!\n \"\n ></ax-text-area>\n }\n <!-- ----- Recreate the rich editor per channel so tab switches do not keep the previous HTML ----- -->\n @else {\n @for (channelName of [ch.name]; track channelName) {\n <ax-text-editor\n #editorRef\n outputFormat=\"html\"\n [placeHolder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.rich'\n | translate\n | async)!\n \"\n [ngModel]=\"getChannelBody(channelName)\"\n (onValueChanged)=\"handleEditorChange(channelName, $event)\"\n [look]=\"'solid'\"\n [initialLine]=\"8\"\n >\n <ax-text-editor-content [style.min-height.px]=\"200\"></ax-text-editor-content>\n <ax-text-editor-toolbar>\n <ax-prefix>\n <ax-text-editor-history></ax-text-editor-history>\n <ax-text-editor-font-style></ax-text-editor-font-style>\n <ax-text-editor-list></ax-text-editor-list>\n </ax-prefix>\n </ax-text-editor-toolbar>\n </ax-text-editor>\n }\n }\n </div>\n } @else {\n <!-- Preview mode: Rendered content with variable placeholders replaced by sample values -->\n <div class=\"space-y-2\">\n @if (ch.hasSubject && previewSubject(ch.name)) {\n <div>\n <span class=\"text-xs text-gray-500\"\n >{{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}:\n </span>\n <span class=\"text-sm\">{{ previewSubject(ch.name) }}</span>\n </div>\n }\n <!-- ----- Rich email keeps inline styles; plain channels use pre-wrap ----- -->\n <div\n class=\"text-sm p-3 bg-gray-100 dark:bg-gray-900 rounded border overflow-auto\"\n [class.whitespace-pre-wrap]=\"ch.type !== 'rich'\"\n [innerHTML]=\"previewBodyHtml(ch.name)\"\n ></div>\n </div>\n }\n </div>\n\n <!-- Footer: Action buttons (left) + Edit/Preview toggle (right) in single row -->\n <div\n class=\"flex flex-nowrap items-center justify-between gap-3 pt-3 mt-1 border-t border-gray-200 dark:border-gray-700\"\n >\n <div class=\"flex flex-nowrap items-center gap-2 min-w-0\">\n @if (viewMode() === 'edit') {\n <!-- ----- Insert variable dropdown from platform tokens ----- -->\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-variable'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-code\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (v of availableVariables(); track v.name) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(v.title || v.name) + ' ({{' + v.name + '}})'\"\n (onClick)=\"insertVariable(ch.name, v.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getVariableIcon(v)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n </ax-button>\n </div>\n <!--->\n <!-- ----- Insert reserved [content] slot for master templates ----- -->\n @if (isMasterKind()) {\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-content-slot'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n (onClick)=\"insertContentSlot(ch.name)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n }\n <!--->\n <!-- ----- Copy subject/body from another channel ----- -->\n @if (otherChannelsWithContent(ch.name).length > 0) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.copy-from'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-copy\"></ax-icon>\n </ax-prefix>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (\n src of otherChannelsWithContent(ch.name);\n track src.name\n ) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(src.title | translate | async) ?? src.name\"\n (onClick)=\"copyFromChannel(ch.name, src.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getChannelIcon(src)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n }\n </div>\n <div>\n <ax-tabs [look]=\"'default'\">\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.edit'\n | translate\n | async) ?? 'Edit'\n \"\n [active]=\"viewMode() === 'edit'\"\n (onClick)=\"viewMode.set('edit')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.preview'\n | translate\n | async) ?? 'Preview'\n \"\n [active]=\"viewMode() === 'preview'\"\n (onClick)=\"viewMode.set('preview')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-eye\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n </ax-tabs>\n </div>\n </div>\n }\n</div>\n" }]
|
|
812
|
+
}], ctorParameters: () => [], propDecorators: { editorRef: [{ type: i0.ViewChild, args: ['editorRef', { isSignal: true }] }], bodyTextareaRef: [{ type: i0.ViewChild, args: ['bodyTextarea', { ...{ read: (ElementRef) }, isSignal: true }] }] } });
|
|
818
813
|
|
|
819
814
|
export { AXMTemplateContentEditorWidgetEditComponent };
|
|
820
|
-
//# sourceMappingURL=acorex-platform-module-content-management-client-template-content-editor-widget-edit.component-
|
|
815
|
+
//# sourceMappingURL=acorex-platform-module-content-management-client-template-content-editor-widget-edit.component-h5ING7pF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acorex-platform-module-content-management-client-template-content-editor-widget-edit.component-h5ING7pF.mjs","sources":["../../../../libs/modules/content-management/client/src/lib/features/template-content-editor/template-content-editor-widget-edit.component.ts","../../../../libs/modules/content-management/client/src/lib/features/template-content-editor/template-content-editor-widget-edit.component.html"],"sourcesContent":["import { AXButtonModule } from '@acorex/components/button';\nimport { AXDecoratorModule } from '@acorex/components/decorators';\nimport { AXDropdownModule } from '@acorex/components/dropdown';\nimport { AXFormModule } from '@acorex/components/form';\nimport { AXTabsModule } from '@acorex/components/tabs';\nimport { AXTextAreaModule } from '@acorex/components/text-area';\nimport { AXTextBoxModule } from '@acorex/components/text-box';\nimport { AXToastService } from '@acorex/components/toast';\nimport { AXTextEditorComponent, AXTextEditorModule } from '@acorex/components/text-editor';\nimport { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';\nimport { AXValidationModule } from '@acorex/core/validation';\nimport { AXPSettingsService, AXPTokenDefinitionService } from '@acorex-platform/framework-client/common';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\nimport { AXPValueWidgetComponent } from '@acorex-platform/framework-client/layout/widget-core';\nimport { AXPCommandExecutor } from '@acorex-platform/framework-client/runtime';\nimport { CommonModule } from '@angular/common';\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n ElementRef,\n effect,\n inject,\n OnInit,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { DomSanitizer, type SafeHtml } from '@angular/platform-browser';\nimport { FormsModule } from '@angular/forms';\nimport { AXValueChangedEvent } from '@acorex/cdk/common';\nimport {\n AXPContextState,\n AXPPlatformScope,\n isFormValueEqual,\n runtimeCommandPayloadData,\n type AXPMultiLanguageString,\n} from '@acorex-platform/framework-shared/core';\nimport {\n AXM_TEXT_TEMPLATE_PREVIEW_COMMAND_KEY,\n RootConfig,\n type AXMTextTemplatePreviewRequest,\n type AXMTextTemplatePreviewResult,\n} from '@acorex-platform/module-content-management-client/contracts';\nimport { AXP_TEXT_TEMPLATE_CHANNEL_DEFINITION_PROVIDER } from './channel-definition.provider';\nimport {\n AXMTextTemplateChannelDefinition,\n AXMTextTemplateChannelsValue,\n} from './channel-definition.types';\nimport {\n AXM_TEXT_TEMPLATE_CONTENT_SLOT,\n AXM_TEXT_TEMPLATE_KIND,\n AXM_TEXT_TEMPLATE_MAX_PARENT_DEPTH,\n collectTextTemplatePlaceholderNames,\n composeTextTemplateBodyChain,\n renderTextTemplateSource,\n replaceTextTemplatePlaceholders,\n resolveTextTemplateLocalizedString,\n type AXMTextTemplateEntityModel,\n} from './text-template-placeholder.util';\n\n/** Variable definition from PlatformManagement.Tokens for template preview and Insert variable */\ninterface TemplateVariable {\n name: string;\n title: string;\n sampleValue?: string;\n kind?: string;\n dataType?: string;\n}\n\n@Component({\n selector: 'axm-template-content-editor-widget-edit',\n templateUrl: './template-content-editor-widget-edit.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n CommonModule,\n AXDecoratorModule,\n FormsModule,\n AXFormModule,\n AXTabsModule,\n AXTextAreaModule,\n AXTextBoxModule,\n AXTextEditorModule,\n AXValidationModule,\n AXTranslationModule,\n AXButtonModule,\n AXDropdownModule,\n ],\n})\nexport class AXMTemplateContentEditorWidgetEditComponent\n extends AXPValueWidgetComponent<AXMTextTemplateChannelsValue | null>\n implements OnInit, AfterViewInit\n{\n /** Stored cursor/selection state before Insert Variable dropdown opens */\n private storedCursor: {\n channelName: string;\n isPlain: boolean;\n selectionStart?: number;\n selectionEnd?: number;\n range?: Range;\n } | null = null;\n private readonly channelProviders = inject(AXP_TEXT_TEMPLATE_CHANNEL_DEFINITION_PROVIDER, {\n optional: true,\n });\n private readonly settingsService = inject(AXPSettingsService);\n private readonly translationService = inject(AXTranslationService);\n private readonly entityService = inject(AXPEntityService);\n private readonly tokenDefinitionService = inject(AXPTokenDefinitionService, { optional: true });\n private readonly commandExecutor = inject(AXPCommandExecutor);\n private readonly toastService = inject(AXToastService);\n private readonly sanitizer = inject(DomSanitizer);\n private readonly destroyRef = inject(DestroyRef);\n private readonly hostRef = inject(ElementRef<HTMLElement>);\n\n /** Dedupes in-flight preview loads when effect re-runs. */\n private previewRequestSeq = 0;\n\n /**\n * TipTap `commitValue(html, true)` marks hydration as a user edit.\n * Ignore writes until that timer elapses after a programmatic sync.\n */\n private suppressEditorWrites = false;\n private suppressEditorWritesTimer: ReturnType<typeof setTimeout> | null = null;\n\n private lastSyncedChannel: string | null = null;\n private lastSyncedViewMode: 'edit' | 'preview' | null = null;\n private lastSyncedEditor: AXTextEditorComponent | undefined;\n /** Drops the ax-tabs init event so it cannot overwrite the content-channel tab. */\n private ignoreNextChannelTabChange = false;\n\n protected editorRef = viewChild<AXTextEditorComponent>('editorRef');\n protected bodyTextareaRef = viewChild('bodyTextarea', { read: ElementRef<HTMLElement> });\n\n protected availableChannels = signal<AXMTextTemplateChannelDefinition[]>([]);\n protected channelConfigured = signal<Record<string, boolean>>({});\n protected availableVariables = signal<TemplateVariable[]>([]);\n protected activeTabIndex = signal<number>(0);\n protected viewMode = signal<'edit' | 'preview'>('edit');\n\n /** Resolved values for local preview fallback: expression/token evaluation, then sampleValue */\n protected resolvedPreviewValues = signal<Record<string, string>>({});\n\n /** Parent-chain bodies (leaf → root) for the active locale, keyed by channel (local fallback). */\n protected composedPreviewBodies = signal<Record<string, string>>({});\n\n /** Server Preview results keyed by channel (preferred over local compose). */\n protected serverPreviewByChannel = signal<\n Record<string, { subject?: string; body: string }>\n >({});\n\n protected activeChannel = computed(() => {\n const idx = this.activeTabIndex();\n const chs = this.availableChannels();\n return chs[idx] ?? null;\n });\n\n /** True when the host entity form has Kind = Master. */\n protected isMasterKind = computed(() => {\n this.contextService.changeEvent();\n const kind = this.contextService.getValue('kind');\n return kind === AXM_TEXT_TEMPLATE_KIND.Master;\n });\n\n protected otherChannelsWithContent = (currentName: string) =>\n this.availableChannels().filter(\n (c) => c.name !== currentName && (this.getChannelBody(c.name) || (c.hasSubject && this.getChannelSubject(c.name)))\n );\n\n /** Returns icon class for a variable/token based on kind and dataType */\n protected getVariableIcon(v: TemplateVariable): string {\n const kindMap: Record<string, string> = {\n Static: 'fa-light fa-database',\n Context: 'fa-light fa-layer-group',\n Event: 'fa-light fa-bolt',\n Computed: 'fa-light fa-calculator',\n Secret: 'fa-light fa-key',\n };\n const dataTypeMap: Record<string, string> = {\n String: 'fa-light fa-font',\n Integer: 'fa-light fa-hashtag',\n Boolean: 'fa-light fa-toggle-on',\n Decimal: 'fa-light fa-calculator',\n DateTime: 'fa-light fa-clock',\n Json: 'fa-light fa-braces',\n };\n const byKind = v.kind && kindMap[v.kind];\n if (byKind) return byKind;\n const byDataType = v.dataType && dataTypeMap[v.dataType];\n if (byDataType) return byDataType;\n return 'fa-light fa-code';\n }\n\n /** Returns icon class for a channel based on name and type */\n protected getChannelIcon(ch: AXMTextTemplateChannelDefinition): string {\n const nameMap: Record<string, string> = {\n email: 'fa-light fa-envelope',\n sms: 'fa-light fa-comment-sms',\n whatsapp: 'fa-brands fa-whatsapp',\n push: 'fa-light fa-bell',\n telegram: 'fa-brands fa-telegram',\n 'in-app': 'fa-light fa-inbox',\n };\n const byName = nameMap[ch.name?.toLowerCase() ?? ''];\n if (byName) return byName;\n return ch.type === 'rich' ? 'fa-light fa-file-lines' : 'fa-light fa-align-left';\n }\n\n private getTemplateLocale(): string {\n return this.translationService.getActiveLang() ?? 'en-US';\n }\n\n /**\n * Builds a mutable locale map from a stored channel field (string legacy or ML object).\n */\n private normalizeChannelFieldToMl(\n existing: AXPMultiLanguageString | string | undefined,\n ): Record<string, string> {\n if (existing == null || existing === '') {\n return {};\n }\n if (typeof existing === 'string') {\n const s = existing;\n return { 'en-US': s, 'fa-IR': s };\n }\n return { ...(existing as Record<string, string>) };\n }\n\n constructor() {\n super();\n effect(() => {\n this.viewMode();\n this.activeTabIndex();\n this.getValue();\n this.contextService.changeEvent();\n if (this.viewMode() === 'preview') {\n void this.loadServerPreview();\n } else {\n this.previewRequestSeq += 1;\n this.resolvedPreviewValues.set({});\n this.composedPreviewBodies.set({});\n this.serverPreviewByChannel.set({});\n }\n });\n\n /**\n * TipTap keeps its own document; one-way ngModel does not refresh it when the entity\n * loads, the user discards, or the active channel tab changes.\n */\n effect(() => {\n const viewMode = this.viewMode();\n const channel = this.activeChannel();\n const changeState = this.contextService.changeEvent().state;\n const body = channel ? this.getChannelBody(channel.name) : '';\n const editor = this.editorRef();\n\n if (viewMode !== 'edit' || !channel || channel.type === 'plain' || !editor) {\n this.lastSyncedViewMode = viewMode;\n return;\n }\n\n const channelChanged = channel.name !== this.lastSyncedChannel;\n const viewModeChanged = viewMode !== this.lastSyncedViewMode;\n const editorChanged = editor !== this.lastSyncedEditor;\n const contextReload = this.shouldSyncEditorFromContext(changeState);\n\n if (!channelChanged && !viewModeChanged && !editorChanged && !contextReload) {\n return;\n }\n\n untracked(() => {\n this.lastSyncedChannel = channel.name;\n this.lastSyncedViewMode = viewMode;\n this.lastSyncedEditor = editor;\n void this.applyEditorContentWhenReady(editor, body);\n });\n });\n\n this.settingsService.onChanged.subscribe(() => {\n void this.refreshChannelConfiguration();\n });\n\n this.destroyRef.onDestroy(() => this.clearSuppressEditorWritesTimer());\n }\n\n protected isChannelConfigured(name: string): boolean {\n return this.channelConfigured()[name] ?? true;\n }\n\n protected async openChannelConfigure(channel: AXMTextTemplateChannelDefinition): Promise<void> {\n const configure = channel.configureSettings;\n if (!configure) {\n return;\n }\n\n const saved = await this.settingsService.showSectionPopup({\n scope: configure.scope,\n section: configure.section,\n group: configure.group,\n });\n if (saved) {\n await this.refreshChannelConfiguration();\n }\n }\n\n private async refreshChannelConfiguration(): Promise<void> {\n const channels = this.availableChannels();\n const next: Record<string, boolean> = {};\n for (const channel of channels) {\n next[channel.name] = await this.isChannelConfiguredInternal(channel);\n }\n this.channelConfigured.set(next);\n }\n\n private async isChannelConfiguredInternal(channel: AXMTextTemplateChannelDefinition): Promise<boolean> {\n const requiredKeys = channel.requiredSettingKeys ?? [];\n if (!requiredKeys.length) {\n return true;\n }\n const scopeKey = channel.configureSettings?.scope ?? 'T';\n const scoped = this.settingsService.scope(scopeKey as AXPPlatformScope);\n for (const key of requiredKeys) {\n const value = await scoped.get(key);\n if (!this.hasNonEmptySettingValue(value)) {\n return false;\n }\n }\n return true;\n }\n\n private hasNonEmptySettingValue(value: unknown): boolean {\n if (value == null) {\n return false;\n }\n if (typeof value === 'string') {\n return value.trim().length > 0;\n }\n if (typeof value === 'number') {\n return Number.isFinite(value);\n }\n if (typeof value === 'boolean') {\n return true;\n }\n if (typeof value === 'object' && 'value' in value) {\n return this.hasNonEmptySettingValue((value as { value?: unknown }).value);\n }\n return String(value).trim().length > 0;\n }\n\n ngAfterViewInit(): void {\n const el = this.hostRef.nativeElement;\n const handleMousedown = (e: MouseEvent) => {\n const target = e.target as Node;\n if (!target || !el.contains(target)) return;\n const trigger = (target as Element).closest?.('[data-insert-var-trigger]');\n if (!trigger) return;\n this.captureCursorBeforeInsert();\n };\n el.addEventListener('mousedown', handleMousedown, { capture: true });\n this.destroyRef.onDestroy(() =>\n el.removeEventListener('mousedown', handleMousedown, { capture: true })\n );\n }\n\n override async ngOnInit(): Promise<void> {\n super.ngOnInit();\n const rawCh = this.channelProviders;\n const chProviders = rawCh == null ? [] : Array.isArray(rawCh) ? rawCh : [rawCh];\n const allChannels: AXMTextTemplateChannelDefinition[] = [];\n for (const p of chProviders) {\n if (p?.getChannels) allChannels.push(...p.getChannels());\n }\n this.availableChannels.set(\n Array.from(new Map(allChannels.map((c) => [c.name, c])).values())\n );\n await this.refreshChannelConfiguration();\n\n try {\n const tokensAccessor = this.entityService.withEntity('PlatformManagement', 'Tokens').data();\n const result = await tokensAccessor.query({ skip: 0, take: 500 });\n const items = (result.items ?? []) as Array<{\n name?: string;\n title?: string;\n sampleValue?: string;\n kind?: string;\n dataType?: string;\n }>;\n const vars: TemplateVariable[] = items\n .map((t) => ({\n name: String(t.name ?? ''),\n title: String(t.title ?? t.name ?? ''),\n sampleValue: t.sampleValue != null ? String(t.sampleValue) : undefined,\n kind: t.kind,\n dataType: t.dataType,\n }))\n .filter((v) => v.name);\n this.availableVariables.set(Array.from(new Map(vars.map((v) => [v.name, v])).values()));\n } catch {\n this.availableVariables.set([]);\n }\n\n const value = this.getValue();\n if (value && typeof value === 'object' && Object.keys(value).length > 0) {\n const names = Object.keys(value);\n const chs = this.availableChannels();\n const idx = chs.findIndex((c) => names.includes(c.name));\n if (idx >= 0) {\n this.ignoreNextChannelTabChange = true;\n this.beginSuppressEditorWrites();\n this.activeTabIndex.set(idx);\n setTimeout(() => {\n this.ignoreNextChannelTabChange = false;\n });\n }\n }\n }\n\n protected onChannelTabChanged(index: number): void {\n if (this.ignoreNextChannelTabChange || index === this.activeTabIndex()) {\n return;\n }\n this.beginSuppressEditorWrites();\n this.activeTabIndex.set(index);\n }\n\n /** Capture cursor/selection before dropdown opens (runs in mousedown capture phase) */\n private captureCursorBeforeInsert(): void {\n const ch = this.activeChannel();\n if (!ch) return;\n this.storedCursor = null;\n const active = document.activeElement as HTMLElement | null;\n if (!active) return;\n if (ch.type === 'plain') {\n const textarea = this.getTextareaElement(active);\n if (textarea) {\n this.storedCursor = {\n channelName: ch.name,\n isPlain: true,\n selectionStart: textarea.selectionStart,\n selectionEnd: textarea.selectionEnd,\n };\n }\n } else {\n const editable = this.getContentEditableElement(active);\n if (editable) {\n const sel = document.getSelection();\n if (sel && sel.rangeCount > 0) {\n const range = sel.getRangeAt(0).cloneRange();\n this.storedCursor = {\n channelName: ch.name,\n isPlain: false,\n range,\n };\n }\n }\n }\n }\n\n private getTextareaElement(el: HTMLElement): HTMLTextAreaElement | null {\n if (el instanceof HTMLTextAreaElement) return el;\n return el.querySelector?.('textarea') ?? null;\n }\n\n private getContentEditableElement(el: HTMLElement): HTMLElement | null {\n if (el.isContentEditable) return el;\n return el.closest?.('[contenteditable=\"true\"]') ?? null;\n }\n\n protected insertVariable(channelName: string, varName: string): void {\n this.insertToken(channelName, `{{${varName}}}`);\n }\n\n protected insertContentSlot(channelName: string): void {\n this.insertToken(channelName, AXM_TEXT_TEMPLATE_CONTENT_SLOT);\n }\n\n private insertToken(channelName: string, token: string): void {\n const current = this.getChannelBody(channelName);\n const stored = this.storedCursor;\n this.storedCursor = null;\n\n if (stored && stored.channelName === channelName) {\n if (stored.isPlain) {\n const start = stored.selectionStart ?? current.length;\n const end = stored.selectionEnd ?? start;\n const before = current.slice(0, start);\n const after = current.slice(end);\n const newBody = before + token + after;\n this.setChannelBody(channelName, newBody);\n const newCursor = start + token.length;\n queueMicrotask(() => this.restoreTextareaCursor(newCursor));\n } else if (stored.range) {\n try {\n const startNode = stored.range.startContainer;\n const elem = startNode.nodeType === Node.TEXT_NODE\n ? (startNode as Text).parentElement\n : (startNode as Element);\n const editable = elem?.closest?.('[contenteditable=\"true\"]') as HTMLElement | null;\n const editorHost = this.editorRef();\n const target = editable ?? editorHost?.getHostElement()?.querySelector?.('[contenteditable=\"true\"]');\n if (target) {\n (target as HTMLElement).focus();\n const sel = document.getSelection();\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(stored.range);\n document.execCommand('insertText', false, token);\n }\n } else {\n this.setChannelBody(channelName, current + token);\n }\n } catch {\n this.setChannelBody(channelName, current + token);\n }\n }\n } else {\n this.setChannelBody(channelName, current + token);\n }\n }\n\n private restoreTextareaCursor(position: number): void {\n const ref = this.bodyTextareaRef();\n const el = ref?.nativeElement;\n const textarea = el?.querySelector?.('textarea') ?? (el instanceof HTMLTextAreaElement ? el : null);\n if (textarea) {\n textarea.focus();\n textarea.setSelectionRange(position, position);\n }\n }\n\n protected copyFromChannel(targetName: string, sourceName: string): void {\n const ch = this.availableChannels().find((c) => c.name === sourceName);\n if (!ch) return;\n const hasSubject = ch.hasSubject;\n if (hasSubject) {\n this.setChannelSubject(targetName, this.getChannelSubject(sourceName));\n }\n this.setChannelBody(targetName, this.getChannelBody(sourceName));\n const active = this.activeChannel();\n if (active?.name === targetName && active.type === 'rich') {\n void this.applyEditorContentWhenReady(this.editorRef(), this.getChannelBody(targetName));\n }\n }\n\n protected getChannelSubject(name: string): string {\n const v = this.getValue()?.[name];\n const raw =\n v && typeof v === 'object' && 'subject' in v ? (v as { subject?: AXPMultiLanguageString }).subject : undefined;\n return resolveTextTemplateLocalizedString(raw, this.getTemplateLocale());\n }\n\n protected handleSubjectChange(name: string, e: AXValueChangedEvent<string>): void {\n if (!e.isUserInteraction) {\n return;\n }\n this.setChannelSubject(name, e.value ?? '');\n }\n\n protected setChannelSubject(name: string, value: string): void {\n const nextText = value ?? '';\n if (this.getChannelSubject(name) === nextText) {\n return;\n }\n const current = this.getValue() || {};\n if (!current[name] && !nextText.trim()) {\n return;\n }\n const ch = current[name] || { body: '' };\n const locale = this.getTemplateLocale();\n const ml = this.normalizeChannelFieldToMl(ch.subject);\n ml[locale] = nextText;\n this.commitChannelValue(current, name, { ...ch, subject: ml });\n }\n\n protected getChannelBody(name: string): string {\n const v = this.getValue()?.[name];\n const raw =\n v && typeof v === 'object' && 'body' in v ? (v as { body?: AXPMultiLanguageString }).body : undefined;\n return resolveTextTemplateLocalizedString(raw, this.getTemplateLocale());\n }\n\n protected handlePlainBodyChange(name: string, e: AXValueChangedEvent<string>): void {\n if (!e.isUserInteraction) {\n return;\n }\n this.setChannelBody(name, e.value ?? '');\n }\n\n protected handleEditorChange(name: string, e: AXValueChangedEvent<string>): void {\n if (this.suppressEditorWrites || !e.isUserInteraction) {\n return;\n }\n const val =\n typeof e === 'object' && e !== null && 'value' in e\n ? ((e as { value: string | null }).value ?? '')\n : String(e ?? '');\n this.setChannelBody(name, val);\n }\n\n protected setChannelBody(name: string, value: string): void {\n const nextText = value ?? '';\n if (this.getChannelBody(name) === nextText) {\n return;\n }\n const current = this.getValue() || {};\n if (!current[name] && !nextText.trim()) {\n return;\n }\n const ch = current[name] || { body: '' };\n const locale = this.getTemplateLocale();\n const ml = this.normalizeChannelFieldToMl(ch.body);\n ml[locale] = nextText;\n this.commitChannelValue(current, name, { ...ch, body: ml });\n }\n\n private commitChannelValue(\n current: AXMTextTemplateChannelsValue,\n name: string,\n nextChannel: AXMTextTemplateChannelsValue[string],\n ): void {\n const nextValue = { ...current, [name]: nextChannel };\n if (isFormValueEqual(nextValue, current)) {\n return;\n }\n const path = this.fullPath();\n const saved = path ? this.contextService.getSavedValue(path) : undefined;\n if (saved !== undefined && isFormValueEqual(nextValue, saved)) {\n return;\n }\n this.setValue(nextValue);\n }\n\n private shouldSyncEditorFromContext(state: AXPContextState): boolean {\n return state === 'restored' || state === 'initiated';\n }\n\n private beginSuppressEditorWrites(): void {\n this.suppressEditorWrites = true;\n this.clearSuppressEditorWritesTimer();\n this.suppressEditorWritesTimer = setTimeout(() => {\n this.suppressEditorWrites = false;\n this.suppressEditorWritesTimer = null;\n }, 500);\n }\n\n private clearSuppressEditorWritesTimer(): void {\n if (this.suppressEditorWritesTimer) {\n clearTimeout(this.suppressEditorWritesTimer);\n this.suppressEditorWritesTimer = null;\n }\n }\n\n private async applyEditorContentWhenReady(\n host: AXTextEditorComponent | undefined,\n text: string,\n ): Promise<void> {\n const content = text ?? '';\n\n for (let attempt = 0; attempt < 30; attempt++) {\n const editor = this.editorRef() ?? host;\n if (!editor?.getEditor()) {\n await new Promise((resolve) => setTimeout(resolve, 50));\n continue;\n }\n\n this.beginSuppressEditorWrites();\n editor.getEditorService().setContent(content, false);\n return;\n }\n }\n\n /**\n * Prefer server draft Preview (Context tokens + Event samples + parent composition).\n * Falls back to local compose when the command fails.\n */\n private async loadServerPreview(): Promise<void> {\n const requestSeq = ++this.previewRequestSeq;\n const value = this.getValue();\n const channel = this.activeChannel()?.name?.trim() || '';\n if (!value || typeof value !== 'object' || !channel) {\n this.serverPreviewByChannel.set({});\n this.composedPreviewBodies.set({});\n return;\n }\n\n const locale = this.getTemplateLocale();\n const parentIdRaw = this.contextService.getValue('parentId');\n const parentId = typeof parentIdRaw === 'string' ? parentIdRaw.trim() : '';\n const kindRaw = this.contextService.getValue('kind');\n const kind = typeof kindRaw === 'string' ? kindRaw.trim() : undefined;\n\n const request: AXMTextTemplatePreviewRequest = {\n channels: value,\n channel,\n locale,\n ...(parentId ? { parentId } : {}),\n ...(kind ? { kind } : {}),\n };\n\n try {\n const result = await this.commandExecutor.execute<\n AXMTextTemplatePreviewRequest,\n AXMTextTemplatePreviewResult\n >(AXM_TEXT_TEMPLATE_PREVIEW_COMMAND_KEY, request);\n\n if (requestSeq !== this.previewRequestSeq) {\n return;\n }\n\n const preview = runtimeCommandPayloadData(result);\n if (preview?.body != null) {\n this.serverPreviewByChannel.update((prev) => ({\n ...prev,\n [channel]: {\n ...(preview.subject != null ? { subject: preview.subject } : {}),\n body: preview.body,\n },\n }));\n return;\n }\n\n const message =\n typeof result?.message?.text === 'string' && result.message.text.trim()\n ? result.message.text.trim()\n : undefined;\n await this.fallbackToLocalPreview(channel, message);\n } catch (error) {\n if (requestSeq !== this.previewRequestSeq) {\n return;\n }\n const message = error instanceof Error ? error.message : undefined;\n await this.fallbackToLocalPreview(channel, message);\n }\n }\n\n private async fallbackToLocalPreview(channel: string, errorMessage?: string): Promise<void> {\n const title = await this.translationService.translateAsync(\n '@content-management:templates.messages.preview-failed.title',\n );\n const content = await this.translationService.translateAsync(\n '@content-management:templates.messages.preview-failed.content',\n );\n this.toastService.show({\n color: 'warning',\n title,\n content: errorMessage ? `${content} ${errorMessage}` : content,\n closeButton: true,\n timeOut: 5000,\n });\n\n this.serverPreviewByChannel.update((prev) => {\n const next = { ...prev };\n delete next[channel];\n return next;\n });\n await this.resolveComposedPreviewBodies();\n }\n\n /** Resolve variable values for local preview fallback */\n private async resolvePreviewVariables(): Promise<void> {\n const value = this.getValue();\n if (!value || typeof value !== 'object') return;\n const locale = this.getTemplateLocale();\n const parts: string[] = [];\n for (const v of Object.values(value)) {\n if (v != null && typeof v === 'object' && 'body' in v) {\n const o = v as { subject?: AXPMultiLanguageString; body?: AXPMultiLanguageString };\n parts.push(resolveTextTemplateLocalizedString(o.subject, locale));\n parts.push(resolveTextTemplateLocalizedString(o.body, locale));\n }\n }\n for (const body of Object.values(this.composedPreviewBodies())) {\n parts.push(body);\n }\n const allText = parts.join('');\n const varNames = collectTextTemplatePlaceholderNames(allText);\n if (varNames.length === 0) return;\n const vars = this.availableVariables();\n const resolved: Record<string, string> = {};\n const svc = this.tokenDefinitionService;\n for (const name of varNames) {\n try {\n if (svc) {\n const val = await svc.getValue(name);\n resolved[name] = val != null ? String(val) : '';\n }\n } catch {\n /* use fallback */\n }\n if (!(name in resolved) || !resolved[name]) {\n const v = vars.find((x) => x.name === name);\n if (v?.sampleValue != null) {\n resolved[name] = v.sampleValue;\n } else if (!(name in resolved)) {\n resolved[name] = '';\n }\n }\n }\n this.resolvedPreviewValues.update((prev) => ({ ...prev, ...resolved }));\n }\n\n /**\n * Local fallback: loads optional parent masters and stores leaf→root body chains per channel.\n */\n private async resolveComposedPreviewBodies(): Promise<void> {\n const value = this.getValue();\n if (!value || typeof value !== 'object') {\n this.composedPreviewBodies.set({});\n return;\n }\n\n const parentIdRaw = this.contextService.getValue('parentId');\n const parentId = typeof parentIdRaw === 'string' ? parentIdRaw.trim() : '';\n const locale = this.getTemplateLocale();\n const next: Record<string, string> = {};\n\n if (!parentId) {\n for (const channelName of Object.keys(value)) {\n next[channelName] = this.getChannelBody(channelName);\n }\n this.composedPreviewBodies.set(next);\n await this.resolvePreviewVariables();\n return;\n }\n\n const parentBodiesByChannel: Record<string, string[]> = {};\n try {\n const accessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.textTemplate.name)\n .data<\n string,\n AXMTextTemplateEntityModel,\n AXMTextTemplateEntityModel,\n AXMTextTemplateEntityModel,\n AXMTextTemplateEntityModel\n >();\n\n const visited = new Set<string>();\n const selfIdRaw = this.contextService.getValue('id');\n const selfId = typeof selfIdRaw === 'string' ? selfIdRaw.trim() : '';\n if (selfId) {\n visited.add(selfId);\n }\n\n let currentId: string | null = parentId;\n let depth = 1;\n while (currentId && depth <= AXM_TEXT_TEMPLATE_MAX_PARENT_DEPTH) {\n if (visited.has(currentId)) {\n break;\n }\n visited.add(currentId);\n const parent = await accessor.byKey(currentId);\n if (!parent?.channels) {\n break;\n }\n for (const [channelName, channelDef] of Object.entries(parent.channels)) {\n const body = resolveTextTemplateLocalizedString(channelDef?.body, locale);\n if (!body) continue;\n (parentBodiesByChannel[channelName] ??= []).push(body);\n }\n currentId = parent.parentId?.trim() || null;\n depth += 1;\n }\n } catch {\n /* keep leaf-only preview */\n }\n\n for (const channelName of Object.keys(value)) {\n const leafBody = this.getChannelBody(channelName);\n const parents = parentBodiesByChannel[channelName] ?? [];\n next[channelName] = composeTextTemplateBodyChain([leafBody, ...parents]);\n }\n this.composedPreviewBodies.set(next);\n await this.resolvePreviewVariables();\n }\n\n /** Get preview value for variable: expression/token first, then sampleValue */\n private getPreviewValue(varName: string): string {\n const resolved = this.resolvedPreviewValues()[varName];\n if (resolved !== undefined && resolved !== '') return resolved;\n const v = this.availableVariables().find((x) => x.name === varName);\n return v?.sampleValue ?? `{{${varName}}}`;\n }\n\n /**\n * Merge map for interpolating `{{ path }}` in `text`.\n * When `escapeMergeValuesForHtml` is true, substitution values are escaped for safe `innerHTML` fragments.\n */\n private previewMergeFor(text: string, escapeMergeValuesForHtml: boolean): Record<string, string> {\n const out: Record<string, string> = {};\n for (const name of collectTextTemplatePlaceholderNames(text)) {\n let v = this.getPreviewValue(name);\n if (escapeMergeValuesForHtml) {\n v = v.replace(/</g, '<').replace(/>/g, '>');\n }\n out[name] = v;\n }\n return out;\n }\n\n protected previewSubject(channelName: string): string {\n const server = this.serverPreviewByChannel()[channelName];\n if (server?.subject != null) {\n return server.subject;\n }\n return this.previewText(this.getChannelSubject(channelName));\n }\n\n protected previewText(text: string): string {\n return replaceTextTemplatePlaceholders(text, this.previewMergeFor(text, false));\n }\n\n /**\n * Email/rich preview must bypass Angular's default innerHTML sanitizer;\n * otherwise inline `style` (colors, gradients, header bar) is stripped and\n * the preview diverges from the real sent email.\n */\n protected previewBodyHtml(channelName: string): SafeHtml | string {\n const ch = this.availableChannels().find((c) => c.name === channelName);\n const server = this.serverPreviewByChannel()[channelName];\n if (server?.body != null) {\n if (ch?.type === 'rich') {\n return this.sanitizer.bypassSecurityTrustHtml(server.body);\n }\n return server.body\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\\n/g, '<br/>');\n }\n\n const composed = this.composedPreviewBodies()[channelName];\n const body = composed ?? this.getChannelBody(channelName);\n // Local fallback: do not escape data for rich HTML (logo mark / styled shells).\n const merged = renderTextTemplateSource(\n body,\n this.previewMergeFor(body, ch?.type !== 'rich'),\n );\n if (ch?.type === 'rich') {\n return this.sanitizer.bypassSecurityTrustHtml(merged);\n }\n return merged\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\\n/g, '<br/>');\n }\n}\n","<!-- Template Content Editor: Channel tabs and content per channel -->\n<div class=\"flex flex-col gap-4 w-full\">\n <!-- Channel tabs navigation -->\n <div class=\"flex items-center gap-2 flex-wrap\">\n <ax-tabs\n [look]=\"'with-line'\"\n (onActiveTabChanged)=\"onChannelTabChanged($event.index)\"\n class=\"flex-1 min-w-0\"\n >\n @for (ch of availableChannels(); track ch.name; let i = $index) {\n <ax-tab-item\n [text]=\"(ch.title | translate | async) ?? ch.name\"\n [key]=\"i.toString()\"\n [active]=\"activeTabIndex() === i\"\n ></ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n @if (activeChannel(); as ch) {\n <!-- Channel content area: Edit mode or Preview mode -->\n <div class=\"mb-4 p-4\">\n @if (!isChannelConfigured(ch.name) && ch.notConfiguredMessageKey) {\n <div\n class=\"mb-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-3 rounded border border-amber-300 bg-amber-50 dark:border-amber-700 dark:bg-amber-950/30\"\n >\n <p class=\"text-sm text-amber-900 dark:text-amber-100\">\n {{ ch.notConfiguredMessageKey | translate | async }}\n </p>\n @if (ch.configureSettings) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.configure-channel'\n | translate\n | async\n \"\n look=\"outline\"\n color=\"primary\"\n size=\"sm\"\n (onClick)=\"openChannelConfigure(ch)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-gear\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </div>\n }\n\n @if (viewMode() === 'edit') {\n <!-- Edit mode: Subject field (for channels that support it, e.g. Email) -->\n @if (ch.hasSubject) {\n <div class=\"mb-3\">\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}\n </label>\n <ax-text-box\n [ngModel]=\"getChannelSubject(ch.name)\"\n (onValueChanged)=\"handleSubjectChange(ch.name, $event)\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.subject.placeholder'\n | translate\n | async)!\n \"\n ></ax-text-box>\n </div>\n }\n\n <!-- Edit mode: Body field (plain text or rich text-editor) -->\n <div>\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.body.title'\n | translate\n | async\n }}\n </label>\n <!--->\n <!-- ----- Plain-text body for SMS-style channels ----- -->\n @if (ch.type === 'plain') {\n <ax-text-area\n #bodyTextarea\n [ngModel]=\"getChannelBody(ch.name)\"\n (onValueChanged)=\"handlePlainBodyChange(ch.name, $event)\"\n [rows]=\"8\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.plain'\n | translate\n | async)!\n \"\n ></ax-text-area>\n }\n <!-- ----- Recreate the rich editor per channel so tab switches do not keep the previous HTML ----- -->\n @else {\n @for (channelName of [ch.name]; track channelName) {\n <ax-text-editor\n #editorRef\n outputFormat=\"html\"\n [placeHolder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.rich'\n | translate\n | async)!\n \"\n [ngModel]=\"getChannelBody(channelName)\"\n (onValueChanged)=\"handleEditorChange(channelName, $event)\"\n [look]=\"'solid'\"\n [initialLine]=\"8\"\n >\n <ax-text-editor-content [style.min-height.px]=\"200\"></ax-text-editor-content>\n <ax-text-editor-toolbar>\n <ax-prefix>\n <ax-text-editor-history></ax-text-editor-history>\n <ax-text-editor-font-style></ax-text-editor-font-style>\n <ax-text-editor-list></ax-text-editor-list>\n </ax-prefix>\n </ax-text-editor-toolbar>\n </ax-text-editor>\n }\n }\n </div>\n } @else {\n <!-- Preview mode: Rendered content with variable placeholders replaced by sample values -->\n <div class=\"space-y-2\">\n @if (ch.hasSubject && previewSubject(ch.name)) {\n <div>\n <span class=\"text-xs text-gray-500\"\n >{{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}:\n </span>\n <span class=\"text-sm\">{{ previewSubject(ch.name) }}</span>\n </div>\n }\n <!-- ----- Rich email keeps inline styles; plain channels use pre-wrap ----- -->\n <div\n class=\"text-sm p-3 bg-gray-100 dark:bg-gray-900 rounded border overflow-auto\"\n [class.whitespace-pre-wrap]=\"ch.type !== 'rich'\"\n [innerHTML]=\"previewBodyHtml(ch.name)\"\n ></div>\n </div>\n }\n </div>\n\n <!-- Footer: Action buttons (left) + Edit/Preview toggle (right) in single row -->\n <div\n class=\"flex flex-nowrap items-center justify-between gap-3 pt-3 mt-1 border-t border-gray-200 dark:border-gray-700\"\n >\n <div class=\"flex flex-nowrap items-center gap-2 min-w-0\">\n @if (viewMode() === 'edit') {\n <!-- ----- Insert variable dropdown from platform tokens ----- -->\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-variable'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-code\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (v of availableVariables(); track v.name) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(v.title || v.name) + ' ({{' + v.name + '}})'\"\n (onClick)=\"insertVariable(ch.name, v.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getVariableIcon(v)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n </ax-button>\n </div>\n <!--->\n <!-- ----- Insert reserved [content] slot for master templates ----- -->\n @if (isMasterKind()) {\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-content-slot'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n (onClick)=\"insertContentSlot(ch.name)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n }\n <!--->\n <!-- ----- Copy subject/body from another channel ----- -->\n @if (otherChannelsWithContent(ch.name).length > 0) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.copy-from'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-copy\"></ax-icon>\n </ax-prefix>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (\n src of otherChannelsWithContent(ch.name);\n track src.name\n ) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(src.title | translate | async) ?? src.name\"\n (onClick)=\"copyFromChannel(ch.name, src.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getChannelIcon(src)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n }\n </div>\n <div>\n <ax-tabs [look]=\"'default'\">\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.edit'\n | translate\n | async) ?? 'Edit'\n \"\n [active]=\"viewMode() === 'edit'\"\n (onClick)=\"viewMode.set('edit')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.preview'\n | translate\n | async) ?? 'Preview'\n \"\n [active]=\"viewMode() === 'preview'\"\n (onClick)=\"viewMode.set('preview')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-eye\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n </ax-tabs>\n </div>\n </div>\n }\n</div>\n"],"names":["i9","i10"],"mappings":"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"}
|
|
@@ -58,7 +58,7 @@ const AXMTemplateContentEditorWidget = {
|
|
|
58
58
|
component: () => import('./acorex-platform-module-content-management-client-template-content-editor-widget-view.component-CfupUZTI.mjs').then((c) => c.AXMTemplateContentEditorWidgetViewComponent),
|
|
59
59
|
},
|
|
60
60
|
edit: {
|
|
61
|
-
component: () => import('./acorex-platform-module-content-management-client-template-content-editor-widget-edit.component-
|
|
61
|
+
component: () => import('./acorex-platform-module-content-management-client-template-content-editor-widget-edit.component-h5ING7pF.mjs').then((c) => c.AXMTemplateContentEditorWidgetEditComponent),
|
|
62
62
|
},
|
|
63
63
|
},
|
|
64
64
|
};
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-platform-module-content-management-client-template-content-editor-widget-edit.component-CphFsFSd.mjs","sources":["../../../../libs/modules/content-management/client/src/lib/features/template-content-editor/template-content-editor-widget-edit.component.ts","../../../../libs/modules/content-management/client/src/lib/features/template-content-editor/template-content-editor-widget-edit.component.html"],"sourcesContent":["import { AXButtonModule } from '@acorex/components/button';\nimport { AXDecoratorModule } from '@acorex/components/decorators';\nimport { AXDropdownModule } from '@acorex/components/dropdown';\nimport { AXFormModule } from '@acorex/components/form';\nimport { AXTabsModule } from '@acorex/components/tabs';\nimport { AXTextAreaModule } from '@acorex/components/text-area';\nimport { AXTextBoxModule } from '@acorex/components/text-box';\nimport { AXToastService } from '@acorex/components/toast';\nimport {\n AXWysiwygContainerComponent,\n AXWysiwygModule,\n} from '@acorex/components/wysiwyg';\nimport { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';\nimport { AXValidationModule } from '@acorex/core/validation';\nimport { AXPSettingsService, AXPTokenDefinitionService } from '@acorex-platform/framework-client/common';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\nimport { AXPValueWidgetComponent } from '@acorex-platform/framework-client/layout/widget-core';\nimport { AXPCommandExecutor } from '@acorex-platform/framework-client/runtime';\nimport { CommonModule } from '@angular/common';\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n ElementRef,\n effect,\n inject,\n OnInit,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { DomSanitizer, type SafeHtml } from '@angular/platform-browser';\nimport { FormsModule } from '@angular/forms';\nimport { AXValueChangedEvent } from '@acorex/cdk/common';\nimport {\n AXPContextState,\n AXPPlatformScope,\n isFormValueEqual,\n runtimeCommandPayloadData,\n type AXPMultiLanguageString,\n} from '@acorex-platform/framework-shared/core';\nimport {\n AXM_TEXT_TEMPLATE_PREVIEW_COMMAND_KEY,\n RootConfig,\n type AXMTextTemplatePreviewRequest,\n type AXMTextTemplatePreviewResult,\n} from '@acorex-platform/module-content-management-client/contracts';\nimport { AXP_TEXT_TEMPLATE_CHANNEL_DEFINITION_PROVIDER } from './channel-definition.provider';\nimport {\n AXMTextTemplateChannelDefinition,\n AXMTextTemplateChannelsValue,\n} from './channel-definition.types';\nimport {\n AXM_TEXT_TEMPLATE_CONTENT_SLOT,\n AXM_TEXT_TEMPLATE_KIND,\n AXM_TEXT_TEMPLATE_MAX_PARENT_DEPTH,\n collectTextTemplatePlaceholderNames,\n composeTextTemplateBodyChain,\n renderTextTemplateSource,\n replaceTextTemplatePlaceholders,\n resolveTextTemplateLocalizedString,\n type AXMTextTemplateEntityModel,\n} from './text-template-placeholder.util';\n\n/** Variable definition from PlatformManagement.Tokens for template preview and Insert variable */\ninterface TemplateVariable {\n name: string;\n title: string;\n sampleValue?: string;\n kind?: string;\n dataType?: string;\n}\n\n@Component({\n selector: 'axm-template-content-editor-widget-edit',\n templateUrl: './template-content-editor-widget-edit.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n CommonModule,\n AXDecoratorModule,\n FormsModule,\n AXFormModule,\n AXTabsModule,\n AXTextAreaModule,\n AXTextBoxModule,\n AXWysiwygModule,\n AXValidationModule,\n AXTranslationModule,\n AXButtonModule,\n AXDropdownModule,\n ],\n})\nexport class AXMTemplateContentEditorWidgetEditComponent\n extends AXPValueWidgetComponent<AXMTextTemplateChannelsValue | null>\n implements OnInit, AfterViewInit\n{\n /** Stored cursor/selection state before Insert Variable dropdown opens */\n private storedCursor: {\n channelName: string;\n isPlain: boolean;\n selectionStart?: number;\n selectionEnd?: number;\n range?: Range;\n } | null = null;\n private readonly channelProviders = inject(AXP_TEXT_TEMPLATE_CHANNEL_DEFINITION_PROVIDER, {\n optional: true,\n });\n private readonly settingsService = inject(AXPSettingsService);\n private readonly translationService = inject(AXTranslationService);\n private readonly entityService = inject(AXPEntityService);\n private readonly tokenDefinitionService = inject(AXPTokenDefinitionService, { optional: true });\n private readonly commandExecutor = inject(AXPCommandExecutor);\n private readonly toastService = inject(AXToastService);\n private readonly sanitizer = inject(DomSanitizer);\n private readonly destroyRef = inject(DestroyRef);\n private readonly hostRef = inject(ElementRef<HTMLElement>);\n\n /** Dedupes in-flight preview loads when effect re-runs. */\n private previewRequestSeq = 0;\n\n /**\n * Quill `text-change` is debounced (~300ms) and `commitValue(html, true)` marks\n * hydration as a user edit. Ignore writes until that timer elapses after a programmatic sync.\n */\n private suppressWysiwygWrites = false;\n private suppressWysiwygWritesTimer: ReturnType<typeof setTimeout> | null = null;\n\n private lastSyncedChannel: string | null = null;\n private lastSyncedViewMode: 'edit' | 'preview' | null = null;\n private lastSyncedWysiwyg: AXWysiwygContainerComponent | undefined;\n /** Drops the ax-tabs init event so it cannot overwrite the content-channel tab. */\n private ignoreNextChannelTabChange = false;\n\n protected wysiwygRef = viewChild<AXWysiwygContainerComponent>('wysiwygRef');\n protected bodyTextareaRef = viewChild('bodyTextarea', { read: ElementRef<HTMLElement> });\n\n protected availableChannels = signal<AXMTextTemplateChannelDefinition[]>([]);\n protected channelConfigured = signal<Record<string, boolean>>({});\n protected availableVariables = signal<TemplateVariable[]>([]);\n protected activeTabIndex = signal<number>(0);\n protected viewMode = signal<'edit' | 'preview'>('edit');\n\n /** Resolved values for local preview fallback: expression/token evaluation, then sampleValue */\n protected resolvedPreviewValues = signal<Record<string, string>>({});\n\n /** Parent-chain bodies (leaf → root) for the active locale, keyed by channel (local fallback). */\n protected composedPreviewBodies = signal<Record<string, string>>({});\n\n /** Server Preview results keyed by channel (preferred over local compose). */\n protected serverPreviewByChannel = signal<\n Record<string, { subject?: string; body: string }>\n >({});\n\n protected activeChannel = computed(() => {\n const idx = this.activeTabIndex();\n const chs = this.availableChannels();\n return chs[idx] ?? null;\n });\n\n /** True when the host entity form has Kind = Master. */\n protected isMasterKind = computed(() => {\n this.contextService.changeEvent();\n const kind = this.contextService.getValue('kind');\n return kind === AXM_TEXT_TEMPLATE_KIND.Master;\n });\n\n protected otherChannelsWithContent = (currentName: string) =>\n this.availableChannels().filter(\n (c) => c.name !== currentName && (this.getChannelBody(c.name) || (c.hasSubject && this.getChannelSubject(c.name)))\n );\n\n /** Returns icon class for a variable/token based on kind and dataType */\n protected getVariableIcon(v: TemplateVariable): string {\n const kindMap: Record<string, string> = {\n Static: 'fa-light fa-database',\n Context: 'fa-light fa-layer-group',\n Event: 'fa-light fa-bolt',\n Computed: 'fa-light fa-calculator',\n Secret: 'fa-light fa-key',\n };\n const dataTypeMap: Record<string, string> = {\n String: 'fa-light fa-font',\n Integer: 'fa-light fa-hashtag',\n Boolean: 'fa-light fa-toggle-on',\n Decimal: 'fa-light fa-calculator',\n DateTime: 'fa-light fa-clock',\n Json: 'fa-light fa-braces',\n };\n const byKind = v.kind && kindMap[v.kind];\n if (byKind) return byKind;\n const byDataType = v.dataType && dataTypeMap[v.dataType];\n if (byDataType) return byDataType;\n return 'fa-light fa-code';\n }\n\n /** Returns icon class for a channel based on name and type */\n protected getChannelIcon(ch: AXMTextTemplateChannelDefinition): string {\n const nameMap: Record<string, string> = {\n email: 'fa-light fa-envelope',\n sms: 'fa-light fa-comment-sms',\n whatsapp: 'fa-brands fa-whatsapp',\n push: 'fa-light fa-bell',\n telegram: 'fa-brands fa-telegram',\n 'in-app': 'fa-light fa-inbox',\n };\n const byName = nameMap[ch.name?.toLowerCase() ?? ''];\n if (byName) return byName;\n return ch.type === 'rich' ? 'fa-light fa-file-lines' : 'fa-light fa-align-left';\n }\n\n private getTemplateLocale(): string {\n return this.translationService.getActiveLang() ?? 'en-US';\n }\n\n /**\n * Builds a mutable locale map from a stored channel field (string legacy or ML object).\n */\n private normalizeChannelFieldToMl(\n existing: AXPMultiLanguageString | string | undefined,\n ): Record<string, string> {\n if (existing == null || existing === '') {\n return {};\n }\n if (typeof existing === 'string') {\n const s = existing;\n return { 'en-US': s, 'fa-IR': s };\n }\n return { ...(existing as Record<string, string>) };\n }\n\n constructor() {\n super();\n effect(() => {\n this.viewMode();\n this.activeTabIndex();\n this.getValue();\n this.contextService.changeEvent();\n if (this.viewMode() === 'preview') {\n void this.loadServerPreview();\n } else {\n this.previewRequestSeq += 1;\n this.resolvedPreviewValues.set({});\n this.composedPreviewBodies.set({});\n this.serverPreviewByChannel.set({});\n }\n });\n\n /**\n * Quill keeps its own DOM; one-way ngModel does not refresh it when the entity\n * loads, the user discards, or the active channel tab changes.\n */\n effect(() => {\n const viewMode = this.viewMode();\n const channel = this.activeChannel();\n const changeState = this.contextService.changeEvent().state;\n const body = channel ? this.getChannelBody(channel.name) : '';\n const editor = this.wysiwygRef();\n\n if (viewMode !== 'edit' || !channel || channel.type === 'plain' || !editor) {\n this.lastSyncedViewMode = viewMode;\n return;\n }\n\n const channelChanged = channel.name !== this.lastSyncedChannel;\n const viewModeChanged = viewMode !== this.lastSyncedViewMode;\n const editorChanged = editor !== this.lastSyncedWysiwyg;\n const contextReload = this.shouldSyncWysiwygFromContext(changeState);\n\n if (!channelChanged && !viewModeChanged && !editorChanged && !contextReload) {\n return;\n }\n\n untracked(() => {\n this.lastSyncedChannel = channel.name;\n this.lastSyncedViewMode = viewMode;\n this.lastSyncedWysiwyg = editor;\n void this.applyWysiwygContentWhenReady(editor, body);\n });\n });\n\n this.settingsService.onChanged.subscribe(() => {\n void this.refreshChannelConfiguration();\n });\n\n this.destroyRef.onDestroy(() => this.clearSuppressWysiwygWritesTimer());\n }\n\n protected isChannelConfigured(name: string): boolean {\n return this.channelConfigured()[name] ?? true;\n }\n\n protected async openChannelConfigure(channel: AXMTextTemplateChannelDefinition): Promise<void> {\n const configure = channel.configureSettings;\n if (!configure) {\n return;\n }\n\n const saved = await this.settingsService.showSectionPopup({\n scope: configure.scope,\n section: configure.section,\n group: configure.group,\n });\n if (saved) {\n await this.refreshChannelConfiguration();\n }\n }\n\n private async refreshChannelConfiguration(): Promise<void> {\n const channels = this.availableChannels();\n const next: Record<string, boolean> = {};\n for (const channel of channels) {\n next[channel.name] = await this.isChannelConfiguredInternal(channel);\n }\n this.channelConfigured.set(next);\n }\n\n private async isChannelConfiguredInternal(channel: AXMTextTemplateChannelDefinition): Promise<boolean> {\n const requiredKeys = channel.requiredSettingKeys ?? [];\n if (!requiredKeys.length) {\n return true;\n }\n const scopeKey = channel.configureSettings?.scope ?? 'T';\n const scoped = this.settingsService.scope(scopeKey as AXPPlatformScope);\n for (const key of requiredKeys) {\n const value = await scoped.get(key);\n if (!this.hasNonEmptySettingValue(value)) {\n return false;\n }\n }\n return true;\n }\n\n private hasNonEmptySettingValue(value: unknown): boolean {\n if (value == null) {\n return false;\n }\n if (typeof value === 'string') {\n return value.trim().length > 0;\n }\n if (typeof value === 'number') {\n return Number.isFinite(value);\n }\n if (typeof value === 'boolean') {\n return true;\n }\n if (typeof value === 'object' && 'value' in value) {\n return this.hasNonEmptySettingValue((value as { value?: unknown }).value);\n }\n return String(value).trim().length > 0;\n }\n\n ngAfterViewInit(): void {\n const el = this.hostRef.nativeElement;\n const handleMousedown = (e: MouseEvent) => {\n const target = e.target as Node;\n if (!target || !el.contains(target)) return;\n const trigger = (target as Element).closest?.('[data-insert-var-trigger]');\n if (!trigger) return;\n this.captureCursorBeforeInsert();\n };\n el.addEventListener('mousedown', handleMousedown, { capture: true });\n this.destroyRef.onDestroy(() =>\n el.removeEventListener('mousedown', handleMousedown, { capture: true })\n );\n }\n\n override async ngOnInit(): Promise<void> {\n super.ngOnInit();\n const rawCh = this.channelProviders;\n const chProviders = rawCh == null ? [] : Array.isArray(rawCh) ? rawCh : [rawCh];\n const allChannels: AXMTextTemplateChannelDefinition[] = [];\n for (const p of chProviders) {\n if (p?.getChannels) allChannels.push(...p.getChannels());\n }\n this.availableChannels.set(\n Array.from(new Map(allChannels.map((c) => [c.name, c])).values())\n );\n await this.refreshChannelConfiguration();\n\n try {\n const tokensAccessor = this.entityService.withEntity('PlatformManagement', 'Tokens').data();\n const result = await tokensAccessor.query({ skip: 0, take: 500 });\n const items = (result.items ?? []) as Array<{\n name?: string;\n title?: string;\n sampleValue?: string;\n kind?: string;\n dataType?: string;\n }>;\n const vars: TemplateVariable[] = items\n .map((t) => ({\n name: String(t.name ?? ''),\n title: String(t.title ?? t.name ?? ''),\n sampleValue: t.sampleValue != null ? String(t.sampleValue) : undefined,\n kind: t.kind,\n dataType: t.dataType,\n }))\n .filter((v) => v.name);\n this.availableVariables.set(Array.from(new Map(vars.map((v) => [v.name, v])).values()));\n } catch {\n this.availableVariables.set([]);\n }\n\n const value = this.getValue();\n if (value && typeof value === 'object' && Object.keys(value).length > 0) {\n const names = Object.keys(value);\n const chs = this.availableChannels();\n const idx = chs.findIndex((c) => names.includes(c.name));\n if (idx >= 0) {\n this.ignoreNextChannelTabChange = true;\n this.beginSuppressWysiwygWrites();\n this.activeTabIndex.set(idx);\n setTimeout(() => {\n this.ignoreNextChannelTabChange = false;\n });\n }\n }\n }\n\n protected onChannelTabChanged(index: number): void {\n if (this.ignoreNextChannelTabChange || index === this.activeTabIndex()) {\n return;\n }\n this.beginSuppressWysiwygWrites();\n this.activeTabIndex.set(index);\n }\n\n /** Capture cursor/selection before dropdown opens (runs in mousedown capture phase) */\n private captureCursorBeforeInsert(): void {\n const ch = this.activeChannel();\n if (!ch) return;\n this.storedCursor = null;\n const active = document.activeElement as HTMLElement | null;\n if (!active) return;\n if (ch.type === 'plain') {\n const textarea = this.getTextareaElement(active);\n if (textarea) {\n this.storedCursor = {\n channelName: ch.name,\n isPlain: true,\n selectionStart: textarea.selectionStart,\n selectionEnd: textarea.selectionEnd,\n };\n }\n } else {\n const editable = this.getContentEditableElement(active);\n if (editable) {\n const sel = document.getSelection();\n if (sel && sel.rangeCount > 0) {\n const range = sel.getRangeAt(0).cloneRange();\n this.storedCursor = {\n channelName: ch.name,\n isPlain: false,\n range,\n };\n }\n }\n }\n }\n\n private getTextareaElement(el: HTMLElement): HTMLTextAreaElement | null {\n if (el instanceof HTMLTextAreaElement) return el;\n return el.querySelector?.('textarea') ?? null;\n }\n\n private getContentEditableElement(el: HTMLElement): HTMLElement | null {\n if (el.isContentEditable) return el;\n return el.closest?.('[contenteditable=\"true\"]') ?? null;\n }\n\n protected insertVariable(channelName: string, varName: string): void {\n this.insertToken(channelName, `{{${varName}}}`);\n }\n\n protected insertContentSlot(channelName: string): void {\n this.insertToken(channelName, AXM_TEXT_TEMPLATE_CONTENT_SLOT);\n }\n\n private insertToken(channelName: string, token: string): void {\n const current = this.getChannelBody(channelName);\n const stored = this.storedCursor;\n this.storedCursor = null;\n\n if (stored && stored.channelName === channelName) {\n if (stored.isPlain) {\n const start = stored.selectionStart ?? current.length;\n const end = stored.selectionEnd ?? start;\n const before = current.slice(0, start);\n const after = current.slice(end);\n const newBody = before + token + after;\n this.setChannelBody(channelName, newBody);\n const newCursor = start + token.length;\n queueMicrotask(() => this.restoreTextareaCursor(newCursor));\n } else if (stored.range) {\n try {\n const startNode = stored.range.startContainer;\n const elem = startNode.nodeType === Node.TEXT_NODE\n ? (startNode as Text).parentElement\n : (startNode as Element);\n const editable = elem?.closest?.('[contenteditable=\"true\"]') as HTMLElement | null;\n const wysiwyg = this.wysiwygRef();\n const target = editable ?? wysiwyg?.getHostElement()?.querySelector?.('[contenteditable=\"true\"]');\n if (target) {\n (target as HTMLElement).focus();\n const sel = document.getSelection();\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(stored.range);\n document.execCommand('insertText', false, token);\n }\n } else {\n this.setChannelBody(channelName, current + token);\n }\n } catch {\n this.setChannelBody(channelName, current + token);\n }\n }\n } else {\n this.setChannelBody(channelName, current + token);\n }\n }\n\n private restoreTextareaCursor(position: number): void {\n const ref = this.bodyTextareaRef();\n const el = ref?.nativeElement;\n const textarea = el?.querySelector?.('textarea') ?? (el instanceof HTMLTextAreaElement ? el : null);\n if (textarea) {\n textarea.focus();\n textarea.setSelectionRange(position, position);\n }\n }\n\n protected copyFromChannel(targetName: string, sourceName: string): void {\n const ch = this.availableChannels().find((c) => c.name === sourceName);\n if (!ch) return;\n const hasSubject = ch.hasSubject;\n if (hasSubject) {\n this.setChannelSubject(targetName, this.getChannelSubject(sourceName));\n }\n this.setChannelBody(targetName, this.getChannelBody(sourceName));\n const active = this.activeChannel();\n if (active?.name === targetName && active.type === 'rich') {\n void this.applyWysiwygContentWhenReady(this.wysiwygRef(), this.getChannelBody(targetName));\n }\n }\n\n protected getChannelSubject(name: string): string {\n const v = this.getValue()?.[name];\n const raw =\n v && typeof v === 'object' && 'subject' in v ? (v as { subject?: AXPMultiLanguageString }).subject : undefined;\n return resolveTextTemplateLocalizedString(raw, this.getTemplateLocale());\n }\n\n protected handleSubjectChange(name: string, e: AXValueChangedEvent<string>): void {\n if (!e.isUserInteraction) {\n return;\n }\n this.setChannelSubject(name, e.value ?? '');\n }\n\n protected setChannelSubject(name: string, value: string): void {\n const nextText = value ?? '';\n if (this.getChannelSubject(name) === nextText) {\n return;\n }\n const current = this.getValue() || {};\n if (!current[name] && !nextText.trim()) {\n return;\n }\n const ch = current[name] || { body: '' };\n const locale = this.getTemplateLocale();\n const ml = this.normalizeChannelFieldToMl(ch.subject);\n ml[locale] = nextText;\n this.commitChannelValue(current, name, { ...ch, subject: ml });\n }\n\n protected getChannelBody(name: string): string {\n const v = this.getValue()?.[name];\n const raw =\n v && typeof v === 'object' && 'body' in v ? (v as { body?: AXPMultiLanguageString }).body : undefined;\n return resolveTextTemplateLocalizedString(raw, this.getTemplateLocale());\n }\n\n protected handlePlainBodyChange(name: string, e: AXValueChangedEvent<string>): void {\n if (!e.isUserInteraction) {\n return;\n }\n this.setChannelBody(name, e.value ?? '');\n }\n\n protected handleWysiwygChange(name: string, e: AXValueChangedEvent<string>): void {\n if (this.suppressWysiwygWrites || !e.isUserInteraction) {\n return;\n }\n const val =\n typeof e === 'object' && e !== null && 'value' in e\n ? ((e as { value: string | null }).value ?? '')\n : String(e ?? '');\n this.setChannelBody(name, val);\n }\n\n protected setChannelBody(name: string, value: string): void {\n const nextText = value ?? '';\n if (this.getChannelBody(name) === nextText) {\n return;\n }\n const current = this.getValue() || {};\n if (!current[name] && !nextText.trim()) {\n return;\n }\n const ch = current[name] || { body: '' };\n const locale = this.getTemplateLocale();\n const ml = this.normalizeChannelFieldToMl(ch.body);\n ml[locale] = nextText;\n this.commitChannelValue(current, name, { ...ch, body: ml });\n }\n\n private commitChannelValue(\n current: AXMTextTemplateChannelsValue,\n name: string,\n nextChannel: AXMTextTemplateChannelsValue[string],\n ): void {\n const nextValue = { ...current, [name]: nextChannel };\n if (isFormValueEqual(nextValue, current)) {\n return;\n }\n const path = this.fullPath();\n const saved = path ? this.contextService.getSavedValue(path) : undefined;\n if (saved !== undefined && isFormValueEqual(nextValue, saved)) {\n return;\n }\n this.setValue(nextValue);\n }\n\n private shouldSyncWysiwygFromContext(state: AXPContextState): boolean {\n return state === 'restored' || state === 'initiated';\n }\n\n private beginSuppressWysiwygWrites(): void {\n this.suppressWysiwygWrites = true;\n this.clearSuppressWysiwygWritesTimer();\n this.suppressWysiwygWritesTimer = setTimeout(() => {\n this.suppressWysiwygWrites = false;\n this.suppressWysiwygWritesTimer = null;\n }, 500);\n }\n\n private clearSuppressWysiwygWritesTimer(): void {\n if (this.suppressWysiwygWritesTimer) {\n clearTimeout(this.suppressWysiwygWritesTimer);\n this.suppressWysiwygWritesTimer = null;\n }\n }\n\n private async applyWysiwygContentWhenReady(\n wysiwyg: AXWysiwygContainerComponent | undefined,\n text: string,\n ): Promise<void> {\n const content = text ?? '';\n\n for (let attempt = 0; attempt < 30; attempt++) {\n const editor = this.wysiwygRef() ?? wysiwyg;\n if (!editor) {\n await new Promise((resolve) => setTimeout(resolve, 50));\n continue;\n }\n\n try {\n this.beginSuppressWysiwygWrites();\n editor.setWysiwygContent(content);\n return;\n } catch {\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n }\n }\n\n /**\n * Prefer server draft Preview (Context tokens + Event samples + parent composition).\n * Falls back to local compose when the command fails.\n */\n private async loadServerPreview(): Promise<void> {\n const requestSeq = ++this.previewRequestSeq;\n const value = this.getValue();\n const channel = this.activeChannel()?.name?.trim() || '';\n if (!value || typeof value !== 'object' || !channel) {\n this.serverPreviewByChannel.set({});\n this.composedPreviewBodies.set({});\n return;\n }\n\n const locale = this.getTemplateLocale();\n const parentIdRaw = this.contextService.getValue('parentId');\n const parentId = typeof parentIdRaw === 'string' ? parentIdRaw.trim() : '';\n const kindRaw = this.contextService.getValue('kind');\n const kind = typeof kindRaw === 'string' ? kindRaw.trim() : undefined;\n\n const request: AXMTextTemplatePreviewRequest = {\n channels: value,\n channel,\n locale,\n ...(parentId ? { parentId } : {}),\n ...(kind ? { kind } : {}),\n };\n\n try {\n const result = await this.commandExecutor.execute<\n AXMTextTemplatePreviewRequest,\n AXMTextTemplatePreviewResult\n >(AXM_TEXT_TEMPLATE_PREVIEW_COMMAND_KEY, request);\n\n if (requestSeq !== this.previewRequestSeq) {\n return;\n }\n\n const preview = runtimeCommandPayloadData(result);\n if (preview?.body != null) {\n this.serverPreviewByChannel.update((prev) => ({\n ...prev,\n [channel]: {\n ...(preview.subject != null ? { subject: preview.subject } : {}),\n body: preview.body,\n },\n }));\n return;\n }\n\n const message =\n typeof result?.message?.text === 'string' && result.message.text.trim()\n ? result.message.text.trim()\n : undefined;\n await this.fallbackToLocalPreview(channel, message);\n } catch (error) {\n if (requestSeq !== this.previewRequestSeq) {\n return;\n }\n const message = error instanceof Error ? error.message : undefined;\n await this.fallbackToLocalPreview(channel, message);\n }\n }\n\n private async fallbackToLocalPreview(channel: string, errorMessage?: string): Promise<void> {\n const title = await this.translationService.translateAsync(\n '@content-management:templates.messages.preview-failed.title',\n );\n const content = await this.translationService.translateAsync(\n '@content-management:templates.messages.preview-failed.content',\n );\n this.toastService.show({\n color: 'warning',\n title,\n content: errorMessage ? `${content} ${errorMessage}` : content,\n closeButton: true,\n timeOut: 5000,\n });\n\n this.serverPreviewByChannel.update((prev) => {\n const next = { ...prev };\n delete next[channel];\n return next;\n });\n await this.resolveComposedPreviewBodies();\n }\n\n /** Resolve variable values for local preview fallback */\n private async resolvePreviewVariables(): Promise<void> {\n const value = this.getValue();\n if (!value || typeof value !== 'object') return;\n const locale = this.getTemplateLocale();\n const parts: string[] = [];\n for (const v of Object.values(value)) {\n if (v != null && typeof v === 'object' && 'body' in v) {\n const o = v as { subject?: AXPMultiLanguageString; body?: AXPMultiLanguageString };\n parts.push(resolveTextTemplateLocalizedString(o.subject, locale));\n parts.push(resolveTextTemplateLocalizedString(o.body, locale));\n }\n }\n for (const body of Object.values(this.composedPreviewBodies())) {\n parts.push(body);\n }\n const allText = parts.join('');\n const varNames = collectTextTemplatePlaceholderNames(allText);\n if (varNames.length === 0) return;\n const vars = this.availableVariables();\n const resolved: Record<string, string> = {};\n const svc = this.tokenDefinitionService;\n for (const name of varNames) {\n try {\n if (svc) {\n const val = await svc.getValue(name);\n resolved[name] = val != null ? String(val) : '';\n }\n } catch {\n /* use fallback */\n }\n if (!(name in resolved) || !resolved[name]) {\n const v = vars.find((x) => x.name === name);\n if (v?.sampleValue != null) {\n resolved[name] = v.sampleValue;\n } else if (!(name in resolved)) {\n resolved[name] = '';\n }\n }\n }\n this.resolvedPreviewValues.update((prev) => ({ ...prev, ...resolved }));\n }\n\n /**\n * Local fallback: loads optional parent masters and stores leaf→root body chains per channel.\n */\n private async resolveComposedPreviewBodies(): Promise<void> {\n const value = this.getValue();\n if (!value || typeof value !== 'object') {\n this.composedPreviewBodies.set({});\n return;\n }\n\n const parentIdRaw = this.contextService.getValue('parentId');\n const parentId = typeof parentIdRaw === 'string' ? parentIdRaw.trim() : '';\n const locale = this.getTemplateLocale();\n const next: Record<string, string> = {};\n\n if (!parentId) {\n for (const channelName of Object.keys(value)) {\n next[channelName] = this.getChannelBody(channelName);\n }\n this.composedPreviewBodies.set(next);\n await this.resolvePreviewVariables();\n return;\n }\n\n const parentBodiesByChannel: Record<string, string[]> = {};\n try {\n const accessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.textTemplate.name)\n .data<\n string,\n AXMTextTemplateEntityModel,\n AXMTextTemplateEntityModel,\n AXMTextTemplateEntityModel,\n AXMTextTemplateEntityModel\n >();\n\n const visited = new Set<string>();\n const selfIdRaw = this.contextService.getValue('id');\n const selfId = typeof selfIdRaw === 'string' ? selfIdRaw.trim() : '';\n if (selfId) {\n visited.add(selfId);\n }\n\n let currentId: string | null = parentId;\n let depth = 1;\n while (currentId && depth <= AXM_TEXT_TEMPLATE_MAX_PARENT_DEPTH) {\n if (visited.has(currentId)) {\n break;\n }\n visited.add(currentId);\n const parent = await accessor.byKey(currentId);\n if (!parent?.channels) {\n break;\n }\n for (const [channelName, channelDef] of Object.entries(parent.channels)) {\n const body = resolveTextTemplateLocalizedString(channelDef?.body, locale);\n if (!body) continue;\n (parentBodiesByChannel[channelName] ??= []).push(body);\n }\n currentId = parent.parentId?.trim() || null;\n depth += 1;\n }\n } catch {\n /* keep leaf-only preview */\n }\n\n for (const channelName of Object.keys(value)) {\n const leafBody = this.getChannelBody(channelName);\n const parents = parentBodiesByChannel[channelName] ?? [];\n next[channelName] = composeTextTemplateBodyChain([leafBody, ...parents]);\n }\n this.composedPreviewBodies.set(next);\n await this.resolvePreviewVariables();\n }\n\n /** Get preview value for variable: expression/token first, then sampleValue */\n private getPreviewValue(varName: string): string {\n const resolved = this.resolvedPreviewValues()[varName];\n if (resolved !== undefined && resolved !== '') return resolved;\n const v = this.availableVariables().find((x) => x.name === varName);\n return v?.sampleValue ?? `{{${varName}}}`;\n }\n\n /**\n * Merge map for interpolating `{{ path }}` in `text`.\n * When `escapeMergeValuesForHtml` is true, substitution values are escaped for safe `innerHTML` fragments.\n */\n private previewMergeFor(text: string, escapeMergeValuesForHtml: boolean): Record<string, string> {\n const out: Record<string, string> = {};\n for (const name of collectTextTemplatePlaceholderNames(text)) {\n let v = this.getPreviewValue(name);\n if (escapeMergeValuesForHtml) {\n v = v.replace(/</g, '<').replace(/>/g, '>');\n }\n out[name] = v;\n }\n return out;\n }\n\n protected previewSubject(channelName: string): string {\n const server = this.serverPreviewByChannel()[channelName];\n if (server?.subject != null) {\n return server.subject;\n }\n return this.previewText(this.getChannelSubject(channelName));\n }\n\n protected previewText(text: string): string {\n return replaceTextTemplatePlaceholders(text, this.previewMergeFor(text, false));\n }\n\n /**\n * Email/rich preview must bypass Angular's default innerHTML sanitizer;\n * otherwise inline `style` (colors, gradients, header bar) is stripped and\n * the preview diverges from the real sent email.\n */\n protected previewBodyHtml(channelName: string): SafeHtml | string {\n const ch = this.availableChannels().find((c) => c.name === channelName);\n const server = this.serverPreviewByChannel()[channelName];\n if (server?.body != null) {\n if (ch?.type === 'rich') {\n return this.sanitizer.bypassSecurityTrustHtml(server.body);\n }\n return server.body\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\\n/g, '<br/>');\n }\n\n const composed = this.composedPreviewBodies()[channelName];\n const body = composed ?? this.getChannelBody(channelName);\n // Local fallback: do not escape data for rich HTML (logo mark / styled shells).\n const merged = renderTextTemplateSource(\n body,\n this.previewMergeFor(body, ch?.type !== 'rich'),\n );\n if (ch?.type === 'rich') {\n return this.sanitizer.bypassSecurityTrustHtml(merged);\n }\n return merged\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\\n/g, '<br/>');\n }\n}\n","<!-- Template Content Editor: Channel tabs and content per channel -->\n<div class=\"flex flex-col gap-4 w-full\">\n <!-- Channel tabs navigation -->\n <div class=\"flex items-center gap-2 flex-wrap\">\n <ax-tabs\n [look]=\"'with-line'\"\n (onActiveTabChanged)=\"onChannelTabChanged($event.index)\"\n class=\"flex-1 min-w-0\"\n >\n @for (ch of availableChannels(); track ch.name; let i = $index) {\n <ax-tab-item\n [text]=\"(ch.title | translate | async) ?? ch.name\"\n [key]=\"i.toString()\"\n [active]=\"activeTabIndex() === i\"\n ></ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n @if (activeChannel(); as ch) {\n <!-- Channel content area: Edit mode or Preview mode -->\n <div class=\"mb-4 p-4\">\n @if (!isChannelConfigured(ch.name) && ch.notConfiguredMessageKey) {\n <div\n class=\"mb-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-3 rounded border border-amber-300 bg-amber-50 dark:border-amber-700 dark:bg-amber-950/30\"\n >\n <p class=\"text-sm text-amber-900 dark:text-amber-100\">\n {{ ch.notConfiguredMessageKey | translate | async }}\n </p>\n @if (ch.configureSettings) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.configure-channel'\n | translate\n | async\n \"\n look=\"outline\"\n color=\"primary\"\n size=\"sm\"\n (onClick)=\"openChannelConfigure(ch)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-gear\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </div>\n }\n\n @if (viewMode() === 'edit') {\n <!-- Edit mode: Subject field (for channels that support it, e.g. Email) -->\n @if (ch.hasSubject) {\n <div class=\"mb-3\">\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}\n </label>\n <ax-text-box\n [ngModel]=\"getChannelSubject(ch.name)\"\n (onValueChanged)=\"handleSubjectChange(ch.name, $event)\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.subject.placeholder'\n | translate\n | async)!\n \"\n ></ax-text-box>\n </div>\n }\n\n <!-- Edit mode: Body field (plain text or rich WYSIWYG) -->\n <div>\n <label class=\"block text-sm mb-1\">\n {{\n '@content-management:templates.entities.text-template.fields.body.title'\n | translate\n | async\n }}\n </label>\n <!--->\n <!-- ----- Plain-text body for SMS-style channels ----- -->\n @if (ch.type === 'plain') {\n <ax-text-area\n #bodyTextarea\n [ngModel]=\"getChannelBody(ch.name)\"\n (onValueChanged)=\"handlePlainBodyChange(ch.name, $event)\"\n [rows]=\"8\"\n [placeholder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.plain'\n | translate\n | async)!\n \"\n ></ax-text-area>\n }\n <!-- ----- Recreate Quill per channel so tab switches do not keep the previous HTML ----- -->\n @else {\n @for (channelName of [ch.name]; track channelName) {\n <ax-wysiwyg-container\n #wysiwygRef\n [placeHolder]=\"\n ('@content-management:templates.entities.text-template.fields.body-placeholder.rich'\n | translate\n | async)!\n \"\n [ngModel]=\"getChannelBody(channelName)\"\n (onValueChanged)=\"handleWysiwygChange(channelName, $event)\"\n [look]=\"'solid'\"\n >\n <ax-wysiwyg-view [style.min-height.px]=\"200\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar>\n <ax-prefix>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n </ax-prefix>\n </ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n }\n }\n </div>\n } @else {\n <!-- Preview mode: Rendered content with variable placeholders replaced by sample values -->\n <div class=\"space-y-2\">\n @if (ch.hasSubject && previewSubject(ch.name)) {\n <div>\n <span class=\"text-xs text-gray-500\"\n >{{\n '@content-management:templates.entities.text-template.fields.subject.title'\n | translate\n | async\n }}:\n </span>\n <span class=\"text-sm\">{{ previewSubject(ch.name) }}</span>\n </div>\n }\n <!-- ----- Rich email keeps inline styles; plain channels use pre-wrap ----- -->\n <div\n class=\"text-sm p-3 bg-gray-100 dark:bg-gray-900 rounded border overflow-auto\"\n [class.whitespace-pre-wrap]=\"ch.type !== 'rich'\"\n [innerHTML]=\"previewBodyHtml(ch.name)\"\n ></div>\n </div>\n }\n </div>\n\n <!-- Footer: Action buttons (left) + Edit/Preview toggle (right) in single row -->\n <div\n class=\"flex flex-nowrap items-center justify-between gap-3 pt-3 mt-1 border-t border-gray-200 dark:border-gray-700\"\n >\n <div class=\"flex flex-nowrap items-center gap-2 min-w-0\">\n @if (viewMode() === 'edit') {\n <!-- ----- Insert variable dropdown from platform tokens ----- -->\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-variable'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-code\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (v of availableVariables(); track v.name) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(v.title || v.name) + ' ({{' + v.name + '}})'\"\n (onClick)=\"insertVariable(ch.name, v.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getVariableIcon(v)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n </ax-button>\n </div>\n <!--->\n <!-- ----- Insert reserved [content] slot for master templates ----- -->\n @if (isMasterKind()) {\n <div data-insert-var-trigger>\n <ax-button\n [text]=\"\n '@content-management:templates.actions.insert-content-slot'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n (onClick)=\"insertContentSlot(ch.name)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n }\n <!--->\n <!-- ----- Copy subject/body from another channel ----- -->\n @if (otherChannelsWithContent(ch.name).length > 0) {\n <ax-button\n [text]=\"\n '@content-management:templates.actions.copy-from'\n | translate\n | async\n \"\n look=\"twotone\"\n color=\"default\"\n size=\"sm\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-copy\"></ax-icon>\n </ax-prefix>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-chevron-down\"></ax-icon>\n </ax-suffix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (\n src of otherChannelsWithContent(ch.name);\n track src.name\n ) {\n <ax-button-item\n look=\"blank\"\n color=\"default\"\n [text]=\"(src.title | translate | async) ?? src.name\"\n (onClick)=\"copyFromChannel(ch.name, src.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"getChannelIcon(src)\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n }\n </div>\n <div>\n <ax-tabs [look]=\"'default'\">\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.edit'\n | translate\n | async) ?? 'Edit'\n \"\n [active]=\"viewMode() === 'edit'\"\n (onClick)=\"viewMode.set('edit')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-pen\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n <ax-tab-item\n [text]=\"\n ('@content-management:templates.actions.preview'\n | translate\n | async) ?? 'Preview'\n \"\n [active]=\"viewMode() === 'preview'\"\n (onClick)=\"viewMode.set('preview')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-eye\" class=\"text-current\"></ax-icon>\n </ax-prefix>\n </ax-tab-item>\n </ax-tabs>\n </div>\n </div>\n }\n</div>\n"],"names":["i9","i10"],"mappings":"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"}
|