@memberjunction/ng-core-entity-forms 5.22.0 → 5.24.0
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/dist/lib/custom/AIAgents/add-action-dialog.component.d.ts +4 -5
- package/dist/lib/custom/AIAgents/add-action-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/add-action-dialog.component.js +55 -59
- package/dist/lib/custom/AIAgents/add-action-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/agent-advanced-settings-dialog.component.js +0 -1
- package/dist/lib/custom/AIAgents/agent-advanced-settings-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.d.ts +4 -5
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js +54 -71
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js +1053 -1096
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-management.service.d.ts +2 -3
- package/dist/lib/custom/AIAgents/ai-agent-management.service.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-management.service.js +39 -82
- package/dist/lib/custom/AIAgents/ai-agent-management.service.js.map +1 -1
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.d.ts +4 -5
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js +28 -31
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.d.ts +4 -5
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js +15 -14
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.d.ts +4 -7
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.js +77 -124
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/new-agent-dialog.service.d.ts +2 -2
- package/dist/lib/custom/AIAgents/new-agent-dialog.service.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/new-agent-dialog.service.js +10 -11
- package/dist/lib/custom/AIAgents/new-agent-dialog.service.js.map +1 -1
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.d.ts +4 -5
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js +18 -18
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.d.ts +4 -5
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js +59 -80
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.d.ts +4 -5
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js +23 -24
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +862 -906
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
- package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.js +4 -5
- package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.js.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +448 -499
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-management.service.d.ts +2 -2
- package/dist/lib/custom/AIPrompts/ai-prompt-management.service.d.ts.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-management.service.js +6 -11
- package/dist/lib/custom/AIPrompts/ai-prompt-management.service.js.map +1 -1
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.d.ts +4 -5
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.js +16 -15
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.js +160 -166
- package/dist/lib/custom/Actions/action-execution-log-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.js +93 -94
- package/dist/lib/custom/Actions/action-form.component.js.map +1 -1
- package/dist/lib/custom/ContentSources/content-source-form.component.d.ts +22 -0
- package/dist/lib/custom/ContentSources/content-source-form.component.d.ts.map +1 -0
- package/dist/lib/custom/ContentSources/content-source-form.component.js +165 -0
- package/dist/lib/custom/ContentSources/content-source-form.component.js.map +1 -0
- package/dist/lib/custom/Entities/entity-form.component.js +2 -2
- package/dist/lib/custom/Lists/list-form.component.js +61 -63
- package/dist/lib/custom/Lists/list-form.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-category-dialog.component.js +33 -59
- package/dist/lib/custom/Queries/query-category-dialog.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.js +354 -360
- package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-run-dialog.component.js +62 -71
- package/dist/lib/custom/Queries/query-run-dialog.component.js.map +1 -1
- package/dist/lib/custom/Templates/template-param-dialog.component.js +128 -124
- package/dist/lib/custom/Templates/template-param-dialog.component.js.map +1 -1
- package/dist/lib/custom/Templates/template-params-grid.component.d.ts +45 -22
- package/dist/lib/custom/Templates/template-params-grid.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/template-params-grid.component.js +380 -384
- package/dist/lib/custom/Templates/template-params-grid.component.js.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.js +34 -36
- package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +8 -9
- package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-run-feedback-form.component.js +4 -4
- package/dist/lib/custom/Tests/test-run-feedback-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.js +7 -7
- package/dist/lib/custom/Tests/test-run-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.js +6 -7
- package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-run-form.component.js +6 -7
- package/dist/lib/custom/Tests/test-suite-run-form.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +381 -409
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js +74 -63
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-visualization.component.js +10 -10
- package/dist/lib/custom/ai-agent-run/ai-agent-run-visualization.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +352 -332
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts +25 -29
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +57 -82
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/dist/lib/custom/shared/entity-selector-dialog.component.d.ts +4 -5
- package/dist/lib/custom/shared/entity-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/shared/entity-selector-dialog.component.js +59 -66
- package/dist/lib/custom/shared/entity-selector-dialog.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js +176 -156
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentClientTool/mjaiagentclienttool.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJAIAgentClientTool/mjaiagentclienttool.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJAIAgentClientTool/mjaiagentclienttool.form.component.js +65 -0
- package/dist/lib/generated/Entities/MJAIAgentClientTool/mjaiagentclienttool.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJAIClientToolDefinition/mjaiclienttooldefinition.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJAIClientToolDefinition/mjaiclienttooldefinition.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJAIClientToolDefinition/mjaiclienttooldefinition.form.component.js +89 -0
- package/dist/lib/generated/Entities/MJAIClientToolDefinition/mjaiclienttooldefinition.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js +98 -44
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js +35 -17
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentItem/mjcontentitem.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentItem/mjcontentitem.form.component.js +79 -20
- package/dist/lib/generated/Entities/MJContentItem/mjcontentitem.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentItemDuplicate/mjcontentitemduplicate.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJContentItemDuplicate/mjcontentitemduplicate.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJContentItemDuplicate/mjcontentitemduplicate.form.component.js +73 -0
- package/dist/lib/generated/Entities/MJContentItemDuplicate/mjcontentitemduplicate.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJContentItemTag/mjcontentitemtag.form.component.js +11 -6
- package/dist/lib/generated/Entities/MJContentItemTag/mjcontentitemtag.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentProcessRun/mjcontentprocessrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentProcessRun/mjcontentprocessrun.form.component.js +49 -8
- package/dist/lib/generated/Entities/MJContentProcessRun/mjcontentprocessrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentProcessRunDetail/mjcontentprocessrundetail.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJContentProcessRunDetail/mjcontentprocessrundetail.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJContentProcessRunDetail/mjcontentprocessrundetail.form.component.js +107 -0
- package/dist/lib/generated/Entities/MJContentProcessRunDetail/mjcontentprocessrundetail.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJContentProcessRunPromptRun/mjcontentprocessrunpromptrun.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJContentProcessRunPromptRun/mjcontentprocessrunpromptrun.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJContentProcessRunPromptRun/mjcontentprocessrunpromptrun.form.component.js +57 -0
- package/dist/lib/generated/Entities/MJContentProcessRunPromptRun/mjcontentprocessrunpromptrun.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJContentSource/mjcontentsource.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentSource/mjcontentsource.form.component.js +71 -24
- package/dist/lib/generated/Entities/MJContentSource/mjcontentsource.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentSourceType/mjcontentsourcetype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentSourceType/mjcontentsourcetype.form.component.js +43 -15
- package/dist/lib/generated/Entities/MJContentSourceType/mjcontentsourcetype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentType/mjcontenttype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentType/mjcontenttype.form.component.js +43 -17
- package/dist/lib/generated/Entities/MJContentType/mjcontenttype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJDuplicateRun/mjduplicaterun.form.component.js +21 -11
- package/dist/lib/generated/Entities/MJDuplicateRun/mjduplicaterun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJDuplicateRunDetail/mjduplicaterundetail.form.component.js +19 -13
- package/dist/lib/generated/Entities/MJDuplicateRunDetail/mjduplicaterundetail.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJDuplicateRunDetailMatch/mjduplicaterundetailmatch.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJDuplicateRunDetailMatch/mjduplicaterundetailmatch.form.component.js +7 -9
- package/dist/lib/generated/Entities/MJDuplicateRunDetailMatch/mjduplicaterundetailmatch.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +78 -60
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.js +24 -6
- package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js +21 -9
- package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityRecordDocument/mjentityrecorddocument.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityRecordDocument/mjentityrecorddocument.form.component.js +23 -5
- package/dist/lib/generated/Entities/MJEntityRecordDocument/mjentityrecorddocument.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJKnowledgeHubSavedSearch/mjknowledgehubsavedsearch.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJKnowledgeHubSavedSearch/mjknowledgehubsavedsearch.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJKnowledgeHubSavedSearch/mjknowledgehubsavedsearch.form.component.js +77 -0
- package/dist/lib/generated/Entities/MJKnowledgeHubSavedSearch/mjknowledgehubsavedsearch.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJScheduledAction/mjscheduledaction.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJScheduledAction/mjscheduledaction.form.component.js +22 -4
- package/dist/lib/generated/Entities/MJScheduledAction/mjscheduledaction.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTag/mjtag.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTag/mjtag.form.component.js +139 -19
- package/dist/lib/generated/Entities/MJTag/mjtag.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTagAuditLog/mjtagauditlog.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJTagAuditLog/mjtagauditlog.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJTagAuditLog/mjtagauditlog.form.component.js +67 -0
- package/dist/lib/generated/Entities/MJTagAuditLog/mjtagauditlog.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJTagCoOccurrence/mjtagcooccurrence.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJTagCoOccurrence/mjtagcooccurrence.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJTagCoOccurrence/mjtagcooccurrence.form.component.js +65 -0
- package/dist/lib/generated/Entities/MJTagCoOccurrence/mjtagcooccurrence.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJTaggedItem/mjtaggeditem.form.component.js +10 -8
- package/dist/lib/generated/Entities/MJTaggedItem/mjtaggeditem.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +226 -154
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJVectorIndex/mjvectorindex.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJVectorIndex/mjvectorindex.form.component.js +41 -5
- package/dist/lib/generated/Entities/MJVectorIndex/mjvectorindex.form.component.js.map +1 -1
- package/dist/lib/generated/generated-forms.module.d.ts +286 -279
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +192 -214
- package/dist/lib/generated/generated-forms.module.js.map +1 -1
- package/dist/lib/shared/components/template-editor.component.js +14 -15
- package/dist/lib/shared/components/template-editor.component.js.map +1 -1
- package/package.json +34 -41
|
@@ -8,9 +8,8 @@ import { DEFAULT_SYSTEM_PLACEHOLDERS, SYSTEM_PLACEHOLDER_CATEGORIES } from '@mem
|
|
|
8
8
|
import * as i0 from "@angular/core";
|
|
9
9
|
import * as i1 from "@memberjunction/ng-notifications";
|
|
10
10
|
import * as i2 from "@angular/forms";
|
|
11
|
-
import * as i3 from "@
|
|
12
|
-
import * as i4 from "@
|
|
13
|
-
import * as i5 from "@memberjunction/ng-code-editor";
|
|
11
|
+
import * as i3 from "@memberjunction/ng-ui-components";
|
|
12
|
+
import * as i4 from "@memberjunction/ng-code-editor";
|
|
14
13
|
const _c0 = ["codeEditor"];
|
|
15
14
|
const _forTrack0 = ($index, $item) => $item.ID || $index;
|
|
16
15
|
const _forTrack1 = ($index, $item) => $item.category.name;
|
|
@@ -88,14 +87,14 @@ function TemplateEditorComponent_Conditional_0_Conditional_1_Template(rf, ctx) {
|
|
|
88
87
|
} }
|
|
89
88
|
function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
90
89
|
const _r8 = i0.ɵɵgetCurrentView();
|
|
91
|
-
i0.ɵɵelementStart(0, "
|
|
92
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
93
|
-
i0.ɵɵlistener("
|
|
90
|
+
i0.ɵɵelementStart(0, "mj-dropdown", 44);
|
|
91
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_7_Template_mj_dropdown_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r2.currentTemplateContent.TypeID, $event) || (ctx_r2.currentTemplateContent.TypeID = $event); return i0.ɵɵresetView($event); });
|
|
92
|
+
i0.ɵɵlistener("ValueChange", function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_7_Template_mj_dropdown_ValueChange_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onContentTypeChange()); });
|
|
94
93
|
i0.ɵɵelementEnd();
|
|
95
94
|
} if (rf & 2) {
|
|
96
95
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
97
96
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.currentTemplateContent.TypeID);
|
|
98
|
-
i0.ɵɵproperty("
|
|
97
|
+
i0.ɵɵproperty("Data", ctx_r2.getContentTypeOptionsForContent())("ValuePrimitive", true);
|
|
99
98
|
} }
|
|
100
99
|
function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
101
100
|
i0.ɵɵelementStart(0, "div", 27);
|
|
@@ -108,13 +107,13 @@ function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_8_Templ
|
|
|
108
107
|
} }
|
|
109
108
|
function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
110
109
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
111
|
-
i0.ɵɵelementStart(0, "
|
|
112
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
110
|
+
i0.ɵɵelementStart(0, "mj-numeric-input", 45);
|
|
111
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_13_Template_mj_numeric_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r2.currentTemplateContent.Priority, $event) || (ctx_r2.currentTemplateContent.Priority = $event); return i0.ɵɵresetView($event); });
|
|
113
112
|
i0.ɵɵelementEnd();
|
|
114
113
|
} if (rf & 2) {
|
|
115
114
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
116
115
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.currentTemplateContent.Priority);
|
|
117
|
-
i0.ɵɵproperty("
|
|
116
|
+
i0.ɵɵproperty("Min", 1)("Step", 1)("Format", "n0");
|
|
118
117
|
} }
|
|
119
118
|
function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
120
119
|
i0.ɵɵelementStart(0, "div", 27);
|
|
@@ -375,13 +374,13 @@ function TemplateEditorComponent_Conditional_0_Conditional_2_Template(rf, ctx) {
|
|
|
375
374
|
i0.ɵɵelement(5, "i", 25);
|
|
376
375
|
i0.ɵɵtext(6, " Content Type ");
|
|
377
376
|
i0.ɵɵelementEnd();
|
|
378
|
-
i0.ɵɵconditionalCreate(7, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_7_Template, 1, 3, "
|
|
377
|
+
i0.ɵɵconditionalCreate(7, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_7_Template, 1, 3, "mj-dropdown", 26)(8, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_8_Template, 2, 1, "div", 27);
|
|
379
378
|
i0.ɵɵelementEnd();
|
|
380
379
|
i0.ɵɵelementStart(9, "div", 23)(10, "label", 28);
|
|
381
380
|
i0.ɵɵelement(11, "i", 29);
|
|
382
381
|
i0.ɵɵtext(12, " Priority ");
|
|
383
382
|
i0.ɵɵelementEnd();
|
|
384
|
-
i0.ɵɵconditionalCreate(13, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_13_Template, 1, 4, "
|
|
383
|
+
i0.ɵɵconditionalCreate(13, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_13_Template, 1, 4, "mj-numeric-input", 30)(14, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_14_Template, 2, 1, "div", 27);
|
|
385
384
|
i0.ɵɵelementEnd();
|
|
386
385
|
i0.ɵɵelementStart(15, "div", 23)(16, "label", 31);
|
|
387
386
|
i0.ɵɵelement(17, "i", 32);
|
|
@@ -884,15 +883,15 @@ export class TemplateEditorComponent {
|
|
|
884
883
|
} if (rf & 2) {
|
|
885
884
|
let _t;
|
|
886
885
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.codeEditor = _t.first);
|
|
887
|
-
} }, inputs: { template: "template", config: "config" }, outputs: { contentChange: "contentChange", runTemplate: "runTemplate" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 1, vars: 1, consts: [["codeEditor", ""], [1, "template-editor", 2, "height", "100%", "display", "flex", "flex-direction", "column"], [1, "content-versions-tabs"], [1, "content-editor-container"], [1, "no-content-state"], [1, "content-tabs"], [1, "content-version-tab", 3, "active"], [1, "content-version-tab", "adding-new"], ["title", "Add new template content", 1, "content-version-tab", "add-new"], [1, "content-version-tab", 3, "click"], [2, "flex", "1"], [1, "tab-label"], [1, "tab-meta"], ["type", "button", "title", "Delete this content version", 1, "delete-btn"], [1, "inactive-label"], ["type", "button", "title", "Delete this content version", 1, "delete-btn", 3, "click"], [1, "fa-solid", "fa-trash", "fa-xs"], [1, "fa-solid", "fa-plus", "text-success"], [1, "new-label"], ["title", "Add new template content", 1, "content-version-tab", "add-new", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "content-metadata-bar"], [1, "metadata-grid"], [1, "form-group"], ["for", "contentType", 1, "form-label"], [1, "fa-solid", "fa-tag"], ["name", "contentType", "
|
|
886
|
+
} }, inputs: { template: "template", config: "config" }, outputs: { contentChange: "contentChange", runTemplate: "runTemplate" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 1, vars: 1, consts: [["codeEditor", ""], [1, "template-editor", 2, "height", "100%", "display", "flex", "flex-direction", "column"], [1, "content-versions-tabs"], [1, "content-editor-container"], [1, "no-content-state"], [1, "content-tabs"], [1, "content-version-tab", 3, "active"], [1, "content-version-tab", "adding-new"], ["title", "Add new template content", 1, "content-version-tab", "add-new"], [1, "content-version-tab", 3, "click"], [2, "flex", "1"], [1, "tab-label"], [1, "tab-meta"], ["type", "button", "title", "Delete this content version", 1, "delete-btn"], [1, "inactive-label"], ["type", "button", "title", "Delete this content version", 1, "delete-btn", 3, "click"], [1, "fa-solid", "fa-trash", "fa-xs"], [1, "fa-solid", "fa-plus", "text-success"], [1, "new-label"], ["title", "Add new template content", 1, "content-version-tab", "add-new", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "content-metadata-bar"], [1, "metadata-grid"], [1, "form-group"], ["for", "contentType", 1, "form-label"], [1, "fa-solid", "fa-tag"], ["name", "contentType", "TextField", "text", "ValueField", "value", 3, "ngModel", "Data", "ValuePrimitive"], [1, "form-control-plaintext"], ["for", "priority", 1, "form-label"], [1, "fa-solid", "fa-sort-numeric-up"], ["name", "priority", 3, "ngModel", "Min", "Step", "Format"], [1, "form-label"], [1, "fa-solid", "fa-toggle-on"], [1, "form-check"], [1, "content-text-editor"], [1, "editor-header"], ["for", "templateContent", 1, "editor-label"], [1, "fa-solid", "fa-code"], [1, "content-type-badge"], [1, "editor-actions"], [1, "unsaved-indicator"], ["type", "button", "title", "Test run this template", 1, "run-btn", 3, "disabled"], [1, "code-editor-wrapper", 3, "change", "readonly", "language", "languages"], [1, "template-help-section"], ["name", "contentType", "TextField", "text", "ValueField", "value", 3, "ngModelChange", "ValueChange", "ngModel", "Data", "ValuePrimitive"], ["name", "priority", 3, "ngModelChange", "ngModel", "Min", "Step", "Format"], ["type", "checkbox", "id", "isActive", "name", "isActive", 1, "form-check-input", 3, "ngModelChange", "ngModel"], ["for", "isActive", 1, "form-check-label"], [1, "badge-success"], [1, "badge-secondary"], [1, "fa-solid", "fa-check-circle"], [1, "fa-solid", "fa-pause-circle"], [1, "fa-solid", "fa-circle"], ["type", "button", "title", "Test run this template", 1, "run-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-play"], [1, "help-tabs"], ["type", "button", 1, "help-tab", 3, "click"], [1, "fa-solid", "fa-at"], [1, "help-content"], [1, "syntax-help"], [1, "placeholders-help"], [1, "section-title"], [1, "fa-solid", "fa-lightbulb"], [1, "syntax-grid"], [1, "syntax-item"], [1, "placeholders-description"], [1, "category-tabs"], ["type", "button", 1, "category-tab", 3, "active"], [1, "placeholder-content"], [1, "usage-example"], [1, "usage-example-inner"], [1, "fa-solid", "fa-info-circle"], [1, "usage-example-text"], ["type", "button", 1, "category-tab", 3, "click"], [2, "font-size", "0.9em"], [1, "tab-badge"], [1, "category-header"], [1, "placeholder-grid"], [1, "placeholder-item"], [1, "placeholder-item-inner"], [1, "placeholder-name-row"], [1, "placeholder-code"], ["type", "button", "title", "Copy placeholder to clipboard", 1, "copy-btn", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "placeholder-description"], [1, "fa-solid", "fa-file-plus"], ["type", "button", 1, "btn", "btn-primary"], ["type", "button", 1, "btn", "btn-primary", 3, "click"]], template: function TemplateEditorComponent_Template(rf, ctx) { if (rf & 1) {
|
|
888
887
|
i0.ɵɵconditionalCreate(0, TemplateEditorComponent_Conditional_0_Template, 4, 2, "div", 1);
|
|
889
888
|
} if (rf & 2) {
|
|
890
889
|
i0.ɵɵconditional(ctx.template ? 0 : -1);
|
|
891
|
-
} }, dependencies: [i2.CheckboxControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.NumericTextBoxComponent, i4.DropDownListComponent, i5.CodeEditorComponent], styles: [".template-editor[_ngcontent-%COMP%] {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n}\n\n.section-header[_ngcontent-%COMP%] h6[_ngcontent-%COMP%] {\n font-size: 0.9em;\n}\n\n.param-row[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-card) !important;\n}\n\n.content-item[_ngcontent-%COMP%] {\n transition: box-shadow 0.2s ease;\n}\n\n.content-item[_ngcontent-%COMP%]:hover {\n box-shadow: 0 2px 4px var(--mj-shadow-sm);\n}\n\n.loading-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n}\n\n.badge[_ngcontent-%COMP%] {\n display: inline-block;\n font-size: 0.7em;\n line-height: 1;\n}\n\n\n\n.template-editor[_ngcontent-%COMP%] kendo-textbox[_ngcontent-%COMP%], \n.template-editor[_ngcontent-%COMP%] kendo-textarea[_ngcontent-%COMP%], \n.template-editor[_ngcontent-%COMP%] kendo-dropdownlist[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.template-editor[_ngcontent-%COMP%] kendo-button[_ngcontent-%COMP%] {\n min-width: auto;\n}\n\n\n\n.content-versions-tabs[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n border-bottom: 2px solid var(--mj-border-default);\n padding-bottom: 8px;\n}\n\n.content-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.content-version-tab[_ngcontent-%COMP%] {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n cursor: pointer;\n background: var(--mj-bg-surface);\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n position: relative;\n}\n\n.content-version-tab.active[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.content-version-tab[_ngcontent-%COMP%] .tab-label[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.85em;\n color: var(--mj-text-secondary);\n}\n\n.content-version-tab[_ngcontent-%COMP%] .tab-meta[_ngcontent-%COMP%] {\n font-size: 0.7em;\n color: var(--mj-text-muted);\n}\n\n.content-version-tab[_ngcontent-%COMP%] .tab-meta[_ngcontent-%COMP%] .inactive-label[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.content-version-tab[_ngcontent-%COMP%] .delete-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: var(--mj-status-error);\n padding: 4px;\n border-radius: 3px;\n transition: all 0.2s;\n cursor: pointer;\n}\n\n.content-version-tab[_ngcontent-%COMP%] .delete-btn[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n\n\n.content-version-tab.adding-new[_ngcontent-%COMP%] {\n border-color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n}\n\n.content-version-tab.adding-new[_ngcontent-%COMP%] .new-label[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-status-success);\n font-size: 0.85em;\n}\n\n\n\n.content-version-tab.add-new[_ngcontent-%COMP%] {\n border: 1px dashed var(--mj-status-success);\n background: var(--mj-bg-surface-card);\n}\n\n.content-version-tab.add-new[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-style: solid;\n}\n\n.content-version-tab.add-new[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n font-size: 0.75em;\n}\n\n.content-version-tab.add-new[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 500;\n color: var(--mj-status-success);\n font-size: 0.85em;\n}\n\n\n\n.content-editor-container[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n\n\n.content-metadata-bar[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 16px 20px;\n}\n\n.metadata-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr auto;\n gap: 20px;\n align-items: end;\n}\n\n.form-group[_ngcontent-%COMP%] {\n margin: 0;\n}\n\n.form-label[_ngcontent-%COMP%] {\n margin-bottom: 4px;\n font-size: 0.9em;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-control-plaintext[_ngcontent-%COMP%] {\n font-size: 0.9em;\n padding: 4px 0;\n}\n\n.form-check[_ngcontent-%COMP%] {\n margin-top: 8px;\n}\n\n.form-check-label[_ngcontent-%COMP%] {\n font-size: 0.9em;\n}\n\n.badge-success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 0.75em;\n font-weight: 600;\n}\n\n.badge-secondary[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-text-muted) 15%, var(--mj-bg-surface));\n color: var(--mj-text-muted);\n border: 1px solid color-mix(in srgb, var(--mj-text-muted) 30%, transparent);\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 0.75em;\n font-weight: 600;\n}\n\n\n\n.content-text-editor[_ngcontent-%COMP%] {\n flex: 1;\n padding: 20px;\n display: flex;\n flex-direction: column;\n}\n\n.editor-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.editor-label[_ngcontent-%COMP%] {\n margin: 0;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.content-type-badge[_ngcontent-%COMP%] {\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 0.75em;\n color: var(--mj-text-inverse);\n}\n\n.content-type-badge.new[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n.content-type-badge.existing[_ngcontent-%COMP%] {\n background: var(--mj-text-muted);\n}\n\n.editor-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.unsaved-indicator[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 0.85em;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.unsaved-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.5em;\n}\n\n.run-btn[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n padding: 6px 12px;\n border-radius: 4px;\n font-size: 0.85em;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n cursor: pointer;\n}\n\n.run-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n\n\n.code-editor-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n height: 350px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n}\n\n\n\n.template-help-section[_ngcontent-%COMP%] {\n margin-top: 16px;\n}\n\n.help-tabs[_ngcontent-%COMP%] {\n display: flex;\n border-bottom: 2px solid var(--mj-border-default);\n margin-bottom: 0;\n}\n\n.help-tab[_ngcontent-%COMP%] {\n padding: 8px 16px;\n border: none;\n background: none;\n cursor: pointer;\n font-size: 0.9em;\n font-weight: 600;\n color: var(--mj-text-muted);\n border-bottom: 3px solid transparent;\n transition: all 0.2s;\n}\n\n.help-tab.active[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n border-bottom-color: var(--mj-status-success);\n}\n\n\n\n.help-content[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-top: none;\n border-radius: 0 0 4px 4px;\n}\n\n\n\n.syntax-help[_ngcontent-%COMP%] {\n font-size: 0.85em;\n}\n\n.syntax-help[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%] {\n font-weight: 600;\n margin-bottom: 12px;\n color: var(--mj-status-success);\n}\n\n.syntax-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 16px;\n}\n\n.syntax-item[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n}\n\n.syntax-help[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n padding: 4px 6px;\n border-radius: 3px;\n display: inline-block;\n margin-top: 4px;\n color: var(--mj-text-primary);\n}\n\n\n\n.placeholders-help[_ngcontent-%COMP%] {\n font-size: 0.85em;\n}\n\n.placeholders-help[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%] {\n font-weight: 600;\n margin-bottom: 12px;\n color: var(--mj-status-success);\n}\n\n.placeholders-description[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n\n\n.category-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n}\n\n.category-tab[_ngcontent-%COMP%] {\n padding: 6px 14px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 20px;\n cursor: pointer;\n font-size: 0.85em;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n color: var(--mj-text-muted);\n}\n\n.category-tab.active[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.category-tab[_ngcontent-%COMP%] .tab-badge[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n color: inherit;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 0.75em;\n margin-left: 4px;\n}\n\n\n\n.placeholder-content[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 16px;\n}\n\n.category-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.category-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.2em;\n}\n\n.category-header[_ngcontent-%COMP%] h5[_ngcontent-%COMP%] {\n margin: 0;\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n.placeholder-grid[_ngcontent-%COMP%] {\n display: grid;\n gap: 10px;\n}\n\n\n\n.placeholder-item[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n position: relative;\n transition: all 0.2s;\n max-width: 800px;\n}\n\n.placeholder-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.placeholder-item[_ngcontent-%COMP%]:hover .copy-btn[_ngcontent-%COMP%] {\n opacity: 1 !important;\n}\n\n.placeholder-item-inner[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n\n.placeholder-name-row[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n\n.placeholder-code[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n font-weight: 600;\n font-size: 0.95em;\n}\n\n.copy-btn[_ngcontent-%COMP%] {\n opacity: 0;\n transition: opacity 0.2s;\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-brand-primary);\n border-radius: 4px;\n display: inline-flex;\n align-items: center;\n}\n\n.copy-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.copy-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.85em;\n}\n\n.placeholder-description[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n margin-top: 4px;\n line-height: 1.4;\n}\n\n\n\n.usage-example[_ngcontent-%COMP%] {\n margin-top: 20px;\n padding: 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-radius: 6px;\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-bg-surface));\n}\n\n.usage-example-inner[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n\n.usage-example[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n margin-top: 2px;\n}\n\n.usage-example-text[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 0.85em;\n color: var(--mj-brand-primary);\n line-height: 1.5;\n}\n\n.usage-example[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n padding: 2px 4px;\n border-radius: 3px;\n}\n\n\n\n.no-content-state[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-card);\n border: 2px dashed var(--mj-border-default);\n border-radius: 8px;\n padding: 40px;\n text-align: center;\n}\n\n.no-content-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n color: var(--mj-text-muted);\n opacity: 0.6;\n}\n\n.no-content-state[_ngcontent-%COMP%] h5[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.no-content-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n margin-bottom: 20px;\n}"] }); }
|
|
890
|
+
} }, dependencies: [i2.CheckboxControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.MJDropdownComponent, i3.MJNumericInputComponent, i4.CodeEditorComponent], styles: [".template-editor[_ngcontent-%COMP%] {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n}\n\n.section-header[_ngcontent-%COMP%] h6[_ngcontent-%COMP%] {\n font-size: 0.9em;\n}\n\n.param-row[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-card) !important;\n}\n\n.content-item[_ngcontent-%COMP%] {\n transition: box-shadow 0.2s ease;\n}\n\n.content-item[_ngcontent-%COMP%]:hover {\n box-shadow: 0 2px 4px var(--mj-shadow-sm);\n}\n\n.loading-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n}\n\n.badge[_ngcontent-%COMP%] {\n display: inline-block;\n font-size: 0.7em;\n line-height: 1;\n}\n\n\n\n.template-editor[_ngcontent-%COMP%] .mj-input[_ngcontent-%COMP%], \n.template-editor[_ngcontent-%COMP%] .mj-textarea[_ngcontent-%COMP%], \n.template-editor[_ngcontent-%COMP%] mj-dropdown[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.template-editor[_ngcontent-%COMP%] [mjButton][_ngcontent-%COMP%] {\n min-width: auto;\n}\n\n\n\n.content-versions-tabs[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n border-bottom: 2px solid var(--mj-border-default);\n padding-bottom: 8px;\n}\n\n.content-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.content-version-tab[_ngcontent-%COMP%] {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n cursor: pointer;\n background: var(--mj-bg-surface);\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n position: relative;\n}\n\n.content-version-tab.active[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.content-version-tab[_ngcontent-%COMP%] .tab-label[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.85em;\n color: var(--mj-text-secondary);\n}\n\n.content-version-tab[_ngcontent-%COMP%] .tab-meta[_ngcontent-%COMP%] {\n font-size: 0.7em;\n color: var(--mj-text-muted);\n}\n\n.content-version-tab[_ngcontent-%COMP%] .tab-meta[_ngcontent-%COMP%] .inactive-label[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.content-version-tab[_ngcontent-%COMP%] .delete-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: var(--mj-status-error);\n padding: 4px;\n border-radius: 3px;\n transition: all 0.2s;\n cursor: pointer;\n}\n\n.content-version-tab[_ngcontent-%COMP%] .delete-btn[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n\n\n.content-version-tab.adding-new[_ngcontent-%COMP%] {\n border-color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n}\n\n.content-version-tab.adding-new[_ngcontent-%COMP%] .new-label[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-status-success);\n font-size: 0.85em;\n}\n\n\n\n.content-version-tab.add-new[_ngcontent-%COMP%] {\n border: 1px dashed var(--mj-status-success);\n background: var(--mj-bg-surface-card);\n}\n\n.content-version-tab.add-new[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-style: solid;\n}\n\n.content-version-tab.add-new[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n font-size: 0.75em;\n}\n\n.content-version-tab.add-new[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 500;\n color: var(--mj-status-success);\n font-size: 0.85em;\n}\n\n\n\n.content-editor-container[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n\n\n.content-metadata-bar[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 16px 20px;\n}\n\n.metadata-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr auto;\n gap: 20px;\n align-items: end;\n}\n\n.form-group[_ngcontent-%COMP%] {\n margin: 0;\n}\n\n.form-label[_ngcontent-%COMP%] {\n margin-bottom: 4px;\n font-size: 0.9em;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-control-plaintext[_ngcontent-%COMP%] {\n font-size: 0.9em;\n padding: 4px 0;\n}\n\n.form-check[_ngcontent-%COMP%] {\n margin-top: 8px;\n}\n\n.form-check-label[_ngcontent-%COMP%] {\n font-size: 0.9em;\n}\n\n.badge-success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 0.75em;\n font-weight: 600;\n}\n\n.badge-secondary[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-text-muted) 15%, var(--mj-bg-surface));\n color: var(--mj-text-muted);\n border: 1px solid color-mix(in srgb, var(--mj-text-muted) 30%, transparent);\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 0.75em;\n font-weight: 600;\n}\n\n\n\n.content-text-editor[_ngcontent-%COMP%] {\n flex: 1;\n padding: 20px;\n display: flex;\n flex-direction: column;\n}\n\n.editor-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.editor-label[_ngcontent-%COMP%] {\n margin: 0;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.content-type-badge[_ngcontent-%COMP%] {\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 0.75em;\n color: var(--mj-text-inverse);\n}\n\n.content-type-badge.new[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n.content-type-badge.existing[_ngcontent-%COMP%] {\n background: var(--mj-text-muted);\n}\n\n.editor-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.unsaved-indicator[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 0.85em;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.unsaved-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.5em;\n}\n\n.run-btn[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n padding: 6px 12px;\n border-radius: 4px;\n font-size: 0.85em;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n cursor: pointer;\n}\n\n.run-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n\n\n.code-editor-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n height: 350px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n}\n\n\n\n.template-help-section[_ngcontent-%COMP%] {\n margin-top: 16px;\n}\n\n.help-tabs[_ngcontent-%COMP%] {\n display: flex;\n border-bottom: 2px solid var(--mj-border-default);\n margin-bottom: 0;\n}\n\n.help-tab[_ngcontent-%COMP%] {\n padding: 8px 16px;\n border: none;\n background: none;\n cursor: pointer;\n font-size: 0.9em;\n font-weight: 600;\n color: var(--mj-text-muted);\n border-bottom: 3px solid transparent;\n transition: all 0.2s;\n}\n\n.help-tab.active[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n border-bottom-color: var(--mj-status-success);\n}\n\n\n\n.help-content[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-top: none;\n border-radius: 0 0 4px 4px;\n}\n\n\n\n.syntax-help[_ngcontent-%COMP%] {\n font-size: 0.85em;\n}\n\n.syntax-help[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%] {\n font-weight: 600;\n margin-bottom: 12px;\n color: var(--mj-status-success);\n}\n\n.syntax-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 16px;\n}\n\n.syntax-item[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n}\n\n.syntax-help[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n padding: 4px 6px;\n border-radius: 3px;\n display: inline-block;\n margin-top: 4px;\n color: var(--mj-text-primary);\n}\n\n\n\n.placeholders-help[_ngcontent-%COMP%] {\n font-size: 0.85em;\n}\n\n.placeholders-help[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%] {\n font-weight: 600;\n margin-bottom: 12px;\n color: var(--mj-status-success);\n}\n\n.placeholders-description[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n\n\n.category-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n}\n\n.category-tab[_ngcontent-%COMP%] {\n padding: 6px 14px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 20px;\n cursor: pointer;\n font-size: 0.85em;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n color: var(--mj-text-muted);\n}\n\n.category-tab.active[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.category-tab[_ngcontent-%COMP%] .tab-badge[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n color: inherit;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 0.75em;\n margin-left: 4px;\n}\n\n\n\n.placeholder-content[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 16px;\n}\n\n.category-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.category-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.2em;\n}\n\n.category-header[_ngcontent-%COMP%] h5[_ngcontent-%COMP%] {\n margin: 0;\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n.placeholder-grid[_ngcontent-%COMP%] {\n display: grid;\n gap: 10px;\n}\n\n\n\n.placeholder-item[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n position: relative;\n transition: all 0.2s;\n max-width: 800px;\n}\n\n.placeholder-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.placeholder-item[_ngcontent-%COMP%]:hover .copy-btn[_ngcontent-%COMP%] {\n opacity: 1 !important;\n}\n\n.placeholder-item-inner[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n\n.placeholder-name-row[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n\n.placeholder-code[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n font-weight: 600;\n font-size: 0.95em;\n}\n\n.copy-btn[_ngcontent-%COMP%] {\n opacity: 0;\n transition: opacity 0.2s;\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-brand-primary);\n border-radius: 4px;\n display: inline-flex;\n align-items: center;\n}\n\n.copy-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.copy-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.85em;\n}\n\n.placeholder-description[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n margin-top: 4px;\n line-height: 1.4;\n}\n\n\n\n.usage-example[_ngcontent-%COMP%] {\n margin-top: 20px;\n padding: 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-radius: 6px;\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-bg-surface));\n}\n\n.usage-example-inner[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n\n.usage-example[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n margin-top: 2px;\n}\n\n.usage-example-text[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 0.85em;\n color: var(--mj-brand-primary);\n line-height: 1.5;\n}\n\n.usage-example[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n padding: 2px 4px;\n border-radius: 3px;\n}\n\n\n\n.no-content-state[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-card);\n border: 2px dashed var(--mj-border-default);\n border-radius: 8px;\n padding: 40px;\n text-align: center;\n}\n\n.no-content-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n color: var(--mj-text-muted);\n opacity: 0.6;\n}\n\n.no-content-state[_ngcontent-%COMP%] h5[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.no-content-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n margin-bottom: 20px;\n}"] }); }
|
|
892
891
|
}
|
|
893
892
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TemplateEditorComponent, [{
|
|
894
893
|
type: Component,
|
|
895
|
-
args: [{ standalone: false, selector: 'mj-template-editor', template: "@if (template) {\n <div class=\"template-editor\" style=\"height: 100%; display: flex; flex-direction: column;\">\n <!-- Content Versions List/Tabs -->\n @if (templateContents.length > 0) {\n <div class=\"content-versions-tabs\">\n <div class=\"content-tabs\">\n @for (content of templateContents; track content.ID || $index; let i = $index) {\n <div class=\"content-version-tab\"\n [class.active]=\"selectedContentIndex === i && !isAddingNewContent\"\n (click)=\"selectTemplateContent(i, false)\">\n <div style=\"flex: 1;\">\n <div class=\"tab-label\">\n {{ content.Type || 'Version ' + (i + 1) }}\n </div>\n <div class=\"tab-meta\">\n P:{{ content.Priority }}\n @if (!content.IsActive) {\n \u2022 <span class=\"inactive-label\">Inactive</span>\n }\n </div>\n </div>\n @if (templateContents.length > 1 && config.allowEdit) {\n <button type=\"button\"\n (click)=\"deleteTemplateContent(i); $event.stopPropagation()\"\n class=\"delete-btn\"\n title=\"Delete this content version\">\n <i class=\"fa-solid fa-trash fa-xs\"></i>\n </button>\n }\n </div>\n }\n @if (isAddingNewContent) {\n <div class=\"content-version-tab adding-new\">\n <i class=\"fa-solid fa-plus text-success\"></i>\n <span class=\"new-label\">New</span>\n </div>\n }\n <!-- Add New Content (Edit Mode Only) -->\n @if (config.allowEdit && !isAddingNewContent) {\n <div class=\"content-version-tab add-new\"\n (click)=\"addNewTemplateContent()\"\n title=\"Add new template content\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New</span>\n </div>\n }\n </div>\n </div>\n }\n <!-- Content Editor -->\n @if (currentTemplateContent) {\n <div class=\"content-editor-container\">\n <!-- Content Metadata Bar -->\n <div class=\"content-metadata-bar\">\n <div class=\"metadata-grid\">\n <div class=\"form-group\">\n <label for=\"contentType\" class=\"form-label\">\n <i class=\"fa-solid fa-tag\"></i> Content Type\n </label>\n @if (config.allowEdit) {\n <kendo-dropdownlist [(ngModel)]=\"currentTemplateContent.TypeID\"\n name=\"contentType\"\n [data]=\"getContentTypeOptionsForContent()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n (valueChange)=\"onContentTypeChange()\">\n </kendo-dropdownlist>\n } @else {\n <div class=\"form-control-plaintext\">\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n </div>\n }\n </div>\n <div class=\"form-group\">\n <label for=\"priority\" class=\"form-label\">\n <i class=\"fa-solid fa-sort-numeric-up\"></i> Priority\n </label>\n @if (config.allowEdit) {\n <kendo-numerictextbox [(ngModel)]=\"currentTemplateContent.Priority\"\n name=\"priority\"\n [min]=\"1\"\n [step]=\"1\"\n [format]=\"'n0'\">\n </kendo-numerictextbox>\n } @else {\n <div class=\"form-control-plaintext\">\n {{ currentTemplateContent.Priority || '-' }}\n </div>\n }\n </div>\n <div class=\"form-group\">\n <label class=\"form-label\">\n <i class=\"fa-solid fa-toggle-on\"></i> Status\n </label>\n @if (config.allowEdit) {\n <div class=\"form-check\">\n <input type=\"checkbox\"\n id=\"isActive\"\n class=\"form-check-input\"\n [(ngModel)]=\"currentTemplateContent.IsActive\"\n name=\"isActive\">\n <label class=\"form-check-label\" for=\"isActive\">\n Active\n </label>\n </div>\n } @else {\n <div class=\"form-control-plaintext\">\n @if (currentTemplateContent.IsActive) {\n <span class=\"badge-success\">\n <i class=\"fa-solid fa-check-circle\"></i> Active\n </span>\n } @else {\n <span class=\"badge-secondary\">\n <i class=\"fa-solid fa-pause-circle\"></i> Inactive\n </span>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Content Text Editor -->\n <div class=\"content-text-editor\">\n <div class=\"editor-header\">\n <label for=\"templateContent\" class=\"editor-label\">\n <i class=\"fa-solid fa-code\"></i> Template Content\n <span class=\"content-type-badge\"\n [class.new]=\"!currentTemplateContent.ID\"\n [class.existing]=\"!!currentTemplateContent.ID\">\n @if (!currentTemplateContent.ID) {\n New\n } @else {\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n }\n </span>\n </label>\n <div class=\"editor-actions\">\n @if (!isAddingNewContent && hasUnsavedChanges) {\n <span class=\"unsaved-indicator\">\n <i class=\"fa-solid fa-circle\"></i>\n Unsaved changes\n </span>\n }\n @if (template.IsSaved && currentTemplateContent && config.showRunButton) {\n <button type=\"button\"\n class=\"run-btn\"\n [disabled]=\"isRunningTemplate\"\n (click)=\"onRunTemplate()\"\n title=\"Test run this template\">\n @if (isRunningTemplate) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Running...\n } @else {\n <i class=\"fa-solid fa-play\"></i>\n Run\n }\n </button>\n }\n </div>\n </div>\n <mj-code-editor\n #codeEditor\n (change)=\"onTemplateTextChange($event)\"\n [readonly]=\"!config.allowEdit\"\n [language]=\"getEditorLanguage()\"\n [languages]=\"supportedLanguages\"\n class=\"code-editor-wrapper\">\n </mj-code-editor>\n <!-- Template Help Section with Tabs -->\n @if (!config.compactMode) {\n <div class=\"template-help-section\">\n <!-- Tab Navigation -->\n <div class=\"help-tabs\">\n <button type=\"button\"\n class=\"help-tab\"\n [class.active]=\"activeHelpTab === 'syntax'\"\n (click)=\"activeHelpTab = 'syntax'\">\n <i class=\"fa-solid fa-code\"></i> Template Syntax\n </button>\n <button type=\"button\"\n class=\"help-tab\"\n [class.active]=\"activeHelpTab === 'placeholders'\"\n (click)=\"activeHelpTab = 'placeholders'\">\n <i class=\"fa-solid fa-at\"></i> System Placeholders\n </button>\n </div>\n <!-- Tab Content -->\n <div class=\"help-content\">\n <!-- Template Syntax Tab -->\n @if (activeHelpTab === 'syntax') {\n <div class=\"syntax-help\">\n <div class=\"section-title\">\n <i class=\"fa-solid fa-lightbulb\"></i> Template Syntax Quick Reference\n </div>\n <div class=\"syntax-grid\">\n <div>\n <div class=\"syntax-item\">\n <strong>Parameters:</strong><br>\n <code>{{'{{'}} paramName {{'}}'}}</code>\n </div>\n <div>\n <strong>Template Includes:</strong><br>\n <code>{{'{% template \"TemplateName\" %}'}}</code>\n </div>\n </div>\n <div>\n <div class=\"syntax-item\">\n <strong>Conditionals:</strong><br>\n <code>{{'{% if condition %}'}} ... {{'{% endif %}'}}</code>\n </div>\n <div>\n <strong>Loops:</strong><br>\n <code>{{'{% for item in items %}'}} ... {{'{% endfor %}'}}</code>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- System Placeholders Tab -->\n @if (activeHelpTab === 'placeholders') {\n <div class=\"placeholders-help\">\n <div class=\"section-title\">\n <i class=\"fa-solid fa-at\"></i> System Placeholders Reference\n </div>\n <p class=\"placeholders-description\">\n System placeholders are automatically available in all AI prompt templates. Simply use them in your template text and they will be replaced with their current values at execution time.\n </p>\n <!-- Category Sub-tabs -->\n <div class=\"category-tabs\">\n @for (categoryGroup of placeholderCategories; track categoryGroup.category.name) {\n <button type=\"button\"\n class=\"category-tab\"\n [class.active]=\"activePlaceholderCategory === categoryGroup.category.name\"\n (click)=\"activePlaceholderCategory = categoryGroup.category.name\">\n <i [class]=\"'fa-solid ' + categoryGroup.category.icon\" style=\"font-size: 0.9em;\"></i>\n {{ categoryGroup.category.name }}\n <span class=\"tab-badge\">\n {{ categoryGroup.placeholders.length }}\n </span>\n </button>\n }\n </div>\n <!-- Active Category Content -->\n <div class=\"placeholder-content\">\n @for (categoryGroup of placeholderCategories; track categoryGroup.category.name) {\n @if (activePlaceholderCategory === categoryGroup.category.name) {\n <div class=\"category-header\">\n <i [class]=\"'fa-solid ' + categoryGroup.category.icon\"\n [style.color]=\"categoryGroup.category.color\"></i>\n <h5>{{ categoryGroup.category.name }}</h5>\n </div>\n <div class=\"placeholder-grid\">\n @for (placeholder of categoryGroup.placeholders; track placeholder.name) {\n <div class=\"placeholder-item\">\n <div class=\"placeholder-item-inner\">\n <div>\n <div class=\"placeholder-name-row\">\n <code class=\"placeholder-code\">{{'{{'}} {{ placeholder.name }} {{'}}'}}</code>\n <button type=\"button\"\n class=\"copy-btn\"\n (click)=\"copyPlaceholder(placeholder.name)\"\n title=\"Copy placeholder to clipboard\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n @if (placeholder.description) {\n <div class=\"placeholder-description\">{{ placeholder.description }}</div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n <!-- Usage Example -->\n <div class=\"usage-example\">\n <div class=\"usage-example-inner\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <div class=\"usage-example-text\">\n <strong>Usage Example:</strong> To use a system placeholder in your template, simply include it in double curly braces.\n For example: <code>\"Today is {{'{{'}} _CURRENT_DATE {{'}}'}} and the current user is {{'{{'}} _USER_NAME {{'}}'}}\"</code>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- No Content State -->\n <div class=\"no-content-state\">\n <i class=\"fa-solid fa-file-plus\"></i>\n <h5>No Template Content</h5>\n <p>Create your first template content version to get started.</p>\n @if (config.allowEdit) {\n <button type=\"button\"\n (click)=\"addNewTemplateContent()\"\n class=\"btn btn-primary\">\n <i class=\"fa-solid fa-plus\"></i> Create First Content Version\n </button>\n }\n </div>\n }\n </div>\n}\n", styles: [".template-editor {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n}\n\n.section-header h6 {\n font-size: 0.9em;\n}\n\n.param-row:hover {\n background-color: var(--mj-bg-surface-card) !important;\n}\n\n.content-item {\n transition: box-shadow 0.2s ease;\n}\n\n.content-item:hover {\n box-shadow: 0 2px 4px var(--mj-shadow-sm);\n}\n\n.loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n}\n\n.badge {\n display: inline-block;\n font-size: 0.7em;\n line-height: 1;\n}\n\n/* Kendo UI overrides for better integration */\n.template-editor kendo-textbox,\n.template-editor kendo-textarea,\n.template-editor kendo-dropdownlist {\n width: 100%;\n}\n\n.template-editor kendo-button {\n min-width: auto;\n}\n\n/* Content version tabs */\n.content-versions-tabs {\n margin-bottom: 16px;\n border-bottom: 2px solid var(--mj-border-default);\n padding-bottom: 8px;\n}\n\n.content-tabs {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.content-version-tab {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n cursor: pointer;\n background: var(--mj-bg-surface);\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n position: relative;\n}\n\n.content-version-tab.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.content-version-tab .tab-label {\n font-weight: 600;\n font-size: 0.85em;\n color: var(--mj-text-secondary);\n}\n\n.content-version-tab .tab-meta {\n font-size: 0.7em;\n color: var(--mj-text-muted);\n}\n\n.content-version-tab .tab-meta .inactive-label {\n color: var(--mj-status-error);\n}\n\n.content-version-tab .delete-btn {\n background: none;\n border: none;\n color: var(--mj-status-error);\n padding: 4px;\n border-radius: 3px;\n transition: all 0.2s;\n cursor: pointer;\n}\n\n.content-version-tab .delete-btn:hover {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n/* New content tab (adding state) */\n.content-version-tab.adding-new {\n border-color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n}\n\n.content-version-tab.adding-new .new-label {\n font-weight: 600;\n color: var(--mj-status-success);\n font-size: 0.85em;\n}\n\n/* Add new content button */\n.content-version-tab.add-new {\n border: 1px dashed var(--mj-status-success);\n background: var(--mj-bg-surface-card);\n}\n\n.content-version-tab.add-new:hover {\n background: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-style: solid;\n}\n\n.content-version-tab.add-new i {\n color: var(--mj-status-success);\n font-size: 0.75em;\n}\n\n.content-version-tab.add-new span {\n font-weight: 500;\n color: var(--mj-status-success);\n font-size: 0.85em;\n}\n\n/* Content editor container */\n.content-editor-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n/* Content metadata bar */\n.content-metadata-bar {\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 16px 20px;\n}\n\n.metadata-grid {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr auto;\n gap: 20px;\n align-items: end;\n}\n\n.form-group {\n margin: 0;\n}\n\n.form-label {\n margin-bottom: 4px;\n font-size: 0.9em;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-control-plaintext {\n font-size: 0.9em;\n padding: 4px 0;\n}\n\n.form-check {\n margin-top: 8px;\n}\n\n.form-check-label {\n font-size: 0.9em;\n}\n\n.badge-success {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 0.75em;\n font-weight: 600;\n}\n\n.badge-secondary {\n background: color-mix(in srgb, var(--mj-text-muted) 15%, var(--mj-bg-surface));\n color: var(--mj-text-muted);\n border: 1px solid color-mix(in srgb, var(--mj-text-muted) 30%, transparent);\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 0.75em;\n font-weight: 600;\n}\n\n/* Content text editor area */\n.content-text-editor {\n flex: 1;\n padding: 20px;\n display: flex;\n flex-direction: column;\n}\n\n.editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.editor-label {\n margin: 0;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.content-type-badge {\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 0.75em;\n color: var(--mj-text-inverse);\n}\n\n.content-type-badge.new {\n background: var(--mj-status-success);\n}\n\n.content-type-badge.existing {\n background: var(--mj-text-muted);\n}\n\n.editor-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.unsaved-indicator {\n color: var(--mj-status-warning);\n font-size: 0.85em;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.unsaved-indicator i {\n font-size: 0.5em;\n}\n\n.run-btn {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n padding: 6px 12px;\n border-radius: 4px;\n font-size: 0.85em;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n cursor: pointer;\n}\n\n.run-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n/* Code editor border */\n.code-editor-wrapper {\n flex: 1;\n height: 350px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n}\n\n/* Help section tabs */\n.template-help-section {\n margin-top: 16px;\n}\n\n.help-tabs {\n display: flex;\n border-bottom: 2px solid var(--mj-border-default);\n margin-bottom: 0;\n}\n\n.help-tab {\n padding: 8px 16px;\n border: none;\n background: none;\n cursor: pointer;\n font-size: 0.9em;\n font-weight: 600;\n color: var(--mj-text-muted);\n border-bottom: 3px solid transparent;\n transition: all 0.2s;\n}\n\n.help-tab.active {\n color: var(--mj-status-success);\n border-bottom-color: var(--mj-status-success);\n}\n\n/* Help content area */\n.help-content {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-top: none;\n border-radius: 0 0 4px 4px;\n}\n\n/* Syntax help */\n.syntax-help {\n font-size: 0.85em;\n}\n\n.syntax-help .section-title {\n font-weight: 600;\n margin-bottom: 12px;\n color: var(--mj-status-success);\n}\n\n.syntax-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 16px;\n}\n\n.syntax-item {\n margin-bottom: 8px;\n}\n\n.syntax-help code {\n background: var(--mj-bg-surface);\n padding: 4px 6px;\n border-radius: 3px;\n display: inline-block;\n margin-top: 4px;\n color: var(--mj-text-primary);\n}\n\n/* Placeholders help */\n.placeholders-help {\n font-size: 0.85em;\n}\n\n.placeholders-help .section-title {\n font-weight: 600;\n margin-bottom: 12px;\n color: var(--mj-status-success);\n}\n\n.placeholders-description {\n margin-bottom: 16px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n/* Category tabs */\n.category-tabs {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n}\n\n.category-tab {\n padding: 6px 14px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 20px;\n cursor: pointer;\n font-size: 0.85em;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n color: var(--mj-text-muted);\n}\n\n.category-tab.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.category-tab .tab-badge {\n background: color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n color: inherit;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 0.75em;\n margin-left: 4px;\n}\n\n/* Placeholder content area */\n.placeholder-content {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 16px;\n}\n\n.category-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.category-header i {\n font-size: 1.2em;\n}\n\n.category-header h5 {\n margin: 0;\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n.placeholder-grid {\n display: grid;\n gap: 10px;\n}\n\n/* Placeholder item */\n.placeholder-item {\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n position: relative;\n transition: all 0.2s;\n max-width: 800px;\n}\n\n.placeholder-item:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.placeholder-item:hover .copy-btn {\n opacity: 1 !important;\n}\n\n.placeholder-item-inner {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n\n.placeholder-name-row {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n\n.placeholder-code {\n color: var(--mj-status-error);\n font-weight: 600;\n font-size: 0.95em;\n}\n\n.copy-btn {\n opacity: 0;\n transition: opacity 0.2s;\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-brand-primary);\n border-radius: 4px;\n display: inline-flex;\n align-items: center;\n}\n\n.copy-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.copy-btn i {\n font-size: 0.85em;\n}\n\n.placeholder-description {\n color: var(--mj-text-muted);\n margin-top: 4px;\n line-height: 1.4;\n}\n\n/* Usage example box */\n.usage-example {\n margin-top: 20px;\n padding: 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-radius: 6px;\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-bg-surface));\n}\n\n.usage-example-inner {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n\n.usage-example i {\n color: var(--mj-brand-primary);\n margin-top: 2px;\n}\n\n.usage-example-text {\n flex: 1;\n font-size: 0.85em;\n color: var(--mj-brand-primary);\n line-height: 1.5;\n}\n\n.usage-example code {\n background: var(--mj-bg-surface);\n padding: 2px 4px;\n border-radius: 3px;\n}\n\n/* No content state */\n.no-content-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-card);\n border: 2px dashed var(--mj-border-default);\n border-radius: 8px;\n padding: 40px;\n text-align: center;\n}\n\n.no-content-state i {\n font-size: 48px;\n margin-bottom: 16px;\n color: var(--mj-text-muted);\n opacity: 0.6;\n}\n\n.no-content-state h5 {\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.no-content-state p {\n color: var(--mj-text-muted);\n margin-bottom: 20px;\n}\n"] }]
|
|
894
|
+
args: [{ standalone: false, selector: 'mj-template-editor', template: "@if (template) {\n <div class=\"template-editor\" style=\"height: 100%; display: flex; flex-direction: column;\">\n <!-- Content Versions List/Tabs -->\n @if (templateContents.length > 0) {\n <div class=\"content-versions-tabs\">\n <div class=\"content-tabs\">\n @for (content of templateContents; track content.ID || $index; let i = $index) {\n <div class=\"content-version-tab\"\n [class.active]=\"selectedContentIndex === i && !isAddingNewContent\"\n (click)=\"selectTemplateContent(i, false)\">\n <div style=\"flex: 1;\">\n <div class=\"tab-label\">\n {{ content.Type || 'Version ' + (i + 1) }}\n </div>\n <div class=\"tab-meta\">\n P:{{ content.Priority }}\n @if (!content.IsActive) {\n \u2022 <span class=\"inactive-label\">Inactive</span>\n }\n </div>\n </div>\n @if (templateContents.length > 1 && config.allowEdit) {\n <button type=\"button\"\n (click)=\"deleteTemplateContent(i); $event.stopPropagation()\"\n class=\"delete-btn\"\n title=\"Delete this content version\">\n <i class=\"fa-solid fa-trash fa-xs\"></i>\n </button>\n }\n </div>\n }\n @if (isAddingNewContent) {\n <div class=\"content-version-tab adding-new\">\n <i class=\"fa-solid fa-plus text-success\"></i>\n <span class=\"new-label\">New</span>\n </div>\n }\n <!-- Add New Content (Edit Mode Only) -->\n @if (config.allowEdit && !isAddingNewContent) {\n <div class=\"content-version-tab add-new\"\n (click)=\"addNewTemplateContent()\"\n title=\"Add new template content\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New</span>\n </div>\n }\n </div>\n </div>\n }\n <!-- Content Editor -->\n @if (currentTemplateContent) {\n <div class=\"content-editor-container\">\n <!-- Content Metadata Bar -->\n <div class=\"content-metadata-bar\">\n <div class=\"metadata-grid\">\n <div class=\"form-group\">\n <label for=\"contentType\" class=\"form-label\">\n <i class=\"fa-solid fa-tag\"></i> Content Type\n </label>\n @if (config.allowEdit) {\n <mj-dropdown [(ngModel)]=\"currentTemplateContent.TypeID\"\n name=\"contentType\"\n [Data]=\"getContentTypeOptionsForContent()\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n (ValueChange)=\"onContentTypeChange()\">\n </mj-dropdown>\n } @else {\n <div class=\"form-control-plaintext\">\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n </div>\n }\n </div>\n <div class=\"form-group\">\n <label for=\"priority\" class=\"form-label\">\n <i class=\"fa-solid fa-sort-numeric-up\"></i> Priority\n </label>\n @if (config.allowEdit) {\n <mj-numeric-input [(ngModel)]=\"currentTemplateContent.Priority\"\n name=\"priority\"\n [Min]=\"1\"\n [Step]=\"1\"\n [Format]=\"'n0'\">\n </mj-numeric-input>\n } @else {\n <div class=\"form-control-plaintext\">\n {{ currentTemplateContent.Priority || '-' }}\n </div>\n }\n </div>\n <div class=\"form-group\">\n <label class=\"form-label\">\n <i class=\"fa-solid fa-toggle-on\"></i> Status\n </label>\n @if (config.allowEdit) {\n <div class=\"form-check\">\n <input type=\"checkbox\"\n id=\"isActive\"\n class=\"form-check-input\"\n [(ngModel)]=\"currentTemplateContent.IsActive\"\n name=\"isActive\">\n <label class=\"form-check-label\" for=\"isActive\">\n Active\n </label>\n </div>\n } @else {\n <div class=\"form-control-plaintext\">\n @if (currentTemplateContent.IsActive) {\n <span class=\"badge-success\">\n <i class=\"fa-solid fa-check-circle\"></i> Active\n </span>\n } @else {\n <span class=\"badge-secondary\">\n <i class=\"fa-solid fa-pause-circle\"></i> Inactive\n </span>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Content Text Editor -->\n <div class=\"content-text-editor\">\n <div class=\"editor-header\">\n <label for=\"templateContent\" class=\"editor-label\">\n <i class=\"fa-solid fa-code\"></i> Template Content\n <span class=\"content-type-badge\"\n [class.new]=\"!currentTemplateContent.ID\"\n [class.existing]=\"!!currentTemplateContent.ID\">\n @if (!currentTemplateContent.ID) {\n New\n } @else {\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n }\n </span>\n </label>\n <div class=\"editor-actions\">\n @if (!isAddingNewContent && hasUnsavedChanges) {\n <span class=\"unsaved-indicator\">\n <i class=\"fa-solid fa-circle\"></i>\n Unsaved changes\n </span>\n }\n @if (template.IsSaved && currentTemplateContent && config.showRunButton) {\n <button type=\"button\"\n class=\"run-btn\"\n [disabled]=\"isRunningTemplate\"\n (click)=\"onRunTemplate()\"\n title=\"Test run this template\">\n @if (isRunningTemplate) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Running...\n } @else {\n <i class=\"fa-solid fa-play\"></i>\n Run\n }\n </button>\n }\n </div>\n </div>\n <mj-code-editor\n #codeEditor\n (change)=\"onTemplateTextChange($event)\"\n [readonly]=\"!config.allowEdit\"\n [language]=\"getEditorLanguage()\"\n [languages]=\"supportedLanguages\"\n class=\"code-editor-wrapper\">\n </mj-code-editor>\n <!-- Template Help Section with Tabs -->\n @if (!config.compactMode) {\n <div class=\"template-help-section\">\n <!-- Tab Navigation -->\n <div class=\"help-tabs\">\n <button type=\"button\"\n class=\"help-tab\"\n [class.active]=\"activeHelpTab === 'syntax'\"\n (click)=\"activeHelpTab = 'syntax'\">\n <i class=\"fa-solid fa-code\"></i> Template Syntax\n </button>\n <button type=\"button\"\n class=\"help-tab\"\n [class.active]=\"activeHelpTab === 'placeholders'\"\n (click)=\"activeHelpTab = 'placeholders'\">\n <i class=\"fa-solid fa-at\"></i> System Placeholders\n </button>\n </div>\n <!-- Tab Content -->\n <div class=\"help-content\">\n <!-- Template Syntax Tab -->\n @if (activeHelpTab === 'syntax') {\n <div class=\"syntax-help\">\n <div class=\"section-title\">\n <i class=\"fa-solid fa-lightbulb\"></i> Template Syntax Quick Reference\n </div>\n <div class=\"syntax-grid\">\n <div>\n <div class=\"syntax-item\">\n <strong>Parameters:</strong><br>\n <code>{{'{{'}} paramName {{'}}'}}</code>\n </div>\n <div>\n <strong>Template Includes:</strong><br>\n <code>{{'{% template \"TemplateName\" %}'}}</code>\n </div>\n </div>\n <div>\n <div class=\"syntax-item\">\n <strong>Conditionals:</strong><br>\n <code>{{'{% if condition %}'}} ... {{'{% endif %}'}}</code>\n </div>\n <div>\n <strong>Loops:</strong><br>\n <code>{{'{% for item in items %}'}} ... {{'{% endfor %}'}}</code>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- System Placeholders Tab -->\n @if (activeHelpTab === 'placeholders') {\n <div class=\"placeholders-help\">\n <div class=\"section-title\">\n <i class=\"fa-solid fa-at\"></i> System Placeholders Reference\n </div>\n <p class=\"placeholders-description\">\n System placeholders are automatically available in all AI prompt templates. Simply use them in your template text and they will be replaced with their current values at execution time.\n </p>\n <!-- Category Sub-tabs -->\n <div class=\"category-tabs\">\n @for (categoryGroup of placeholderCategories; track categoryGroup.category.name) {\n <button type=\"button\"\n class=\"category-tab\"\n [class.active]=\"activePlaceholderCategory === categoryGroup.category.name\"\n (click)=\"activePlaceholderCategory = categoryGroup.category.name\">\n <i [class]=\"'fa-solid ' + categoryGroup.category.icon\" style=\"font-size: 0.9em;\"></i>\n {{ categoryGroup.category.name }}\n <span class=\"tab-badge\">\n {{ categoryGroup.placeholders.length }}\n </span>\n </button>\n }\n </div>\n <!-- Active Category Content -->\n <div class=\"placeholder-content\">\n @for (categoryGroup of placeholderCategories; track categoryGroup.category.name) {\n @if (activePlaceholderCategory === categoryGroup.category.name) {\n <div class=\"category-header\">\n <i [class]=\"'fa-solid ' + categoryGroup.category.icon\"\n [style.color]=\"categoryGroup.category.color\"></i>\n <h5>{{ categoryGroup.category.name }}</h5>\n </div>\n <div class=\"placeholder-grid\">\n @for (placeholder of categoryGroup.placeholders; track placeholder.name) {\n <div class=\"placeholder-item\">\n <div class=\"placeholder-item-inner\">\n <div>\n <div class=\"placeholder-name-row\">\n <code class=\"placeholder-code\">{{'{{'}} {{ placeholder.name }} {{'}}'}}</code>\n <button type=\"button\"\n class=\"copy-btn\"\n (click)=\"copyPlaceholder(placeholder.name)\"\n title=\"Copy placeholder to clipboard\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n @if (placeholder.description) {\n <div class=\"placeholder-description\">{{ placeholder.description }}</div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n <!-- Usage Example -->\n <div class=\"usage-example\">\n <div class=\"usage-example-inner\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <div class=\"usage-example-text\">\n <strong>Usage Example:</strong> To use a system placeholder in your template, simply include it in double curly braces.\n For example: <code>\"Today is {{'{{'}} _CURRENT_DATE {{'}}'}} and the current user is {{'{{'}} _USER_NAME {{'}}'}}\"</code>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- No Content State -->\n <div class=\"no-content-state\">\n <i class=\"fa-solid fa-file-plus\"></i>\n <h5>No Template Content</h5>\n <p>Create your first template content version to get started.</p>\n @if (config.allowEdit) {\n <button type=\"button\"\n (click)=\"addNewTemplateContent()\"\n class=\"btn btn-primary\">\n <i class=\"fa-solid fa-plus\"></i> Create First Content Version\n </button>\n }\n </div>\n }\n </div>\n}\n", styles: [".template-editor {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n}\n\n.section-header h6 {\n font-size: 0.9em;\n}\n\n.param-row:hover {\n background-color: var(--mj-bg-surface-card) !important;\n}\n\n.content-item {\n transition: box-shadow 0.2s ease;\n}\n\n.content-item:hover {\n box-shadow: 0 2px 4px var(--mj-shadow-sm);\n}\n\n.loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n}\n\n.badge {\n display: inline-block;\n font-size: 0.7em;\n line-height: 1;\n}\n\n/* Form control sizing */\n.template-editor .mj-input,\n.template-editor .mj-textarea,\n.template-editor mj-dropdown {\n width: 100%;\n}\n\n.template-editor [mjButton] {\n min-width: auto;\n}\n\n/* Content version tabs */\n.content-versions-tabs {\n margin-bottom: 16px;\n border-bottom: 2px solid var(--mj-border-default);\n padding-bottom: 8px;\n}\n\n.content-tabs {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.content-version-tab {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n cursor: pointer;\n background: var(--mj-bg-surface);\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n position: relative;\n}\n\n.content-version-tab.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.content-version-tab .tab-label {\n font-weight: 600;\n font-size: 0.85em;\n color: var(--mj-text-secondary);\n}\n\n.content-version-tab .tab-meta {\n font-size: 0.7em;\n color: var(--mj-text-muted);\n}\n\n.content-version-tab .tab-meta .inactive-label {\n color: var(--mj-status-error);\n}\n\n.content-version-tab .delete-btn {\n background: none;\n border: none;\n color: var(--mj-status-error);\n padding: 4px;\n border-radius: 3px;\n transition: all 0.2s;\n cursor: pointer;\n}\n\n.content-version-tab .delete-btn:hover {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n/* New content tab (adding state) */\n.content-version-tab.adding-new {\n border-color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n}\n\n.content-version-tab.adding-new .new-label {\n font-weight: 600;\n color: var(--mj-status-success);\n font-size: 0.85em;\n}\n\n/* Add new content button */\n.content-version-tab.add-new {\n border: 1px dashed var(--mj-status-success);\n background: var(--mj-bg-surface-card);\n}\n\n.content-version-tab.add-new:hover {\n background: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-style: solid;\n}\n\n.content-version-tab.add-new i {\n color: var(--mj-status-success);\n font-size: 0.75em;\n}\n\n.content-version-tab.add-new span {\n font-weight: 500;\n color: var(--mj-status-success);\n font-size: 0.85em;\n}\n\n/* Content editor container */\n.content-editor-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n/* Content metadata bar */\n.content-metadata-bar {\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 16px 20px;\n}\n\n.metadata-grid {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr auto;\n gap: 20px;\n align-items: end;\n}\n\n.form-group {\n margin: 0;\n}\n\n.form-label {\n margin-bottom: 4px;\n font-size: 0.9em;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-control-plaintext {\n font-size: 0.9em;\n padding: 4px 0;\n}\n\n.form-check {\n margin-top: 8px;\n}\n\n.form-check-label {\n font-size: 0.9em;\n}\n\n.badge-success {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 0.75em;\n font-weight: 600;\n}\n\n.badge-secondary {\n background: color-mix(in srgb, var(--mj-text-muted) 15%, var(--mj-bg-surface));\n color: var(--mj-text-muted);\n border: 1px solid color-mix(in srgb, var(--mj-text-muted) 30%, transparent);\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 0.75em;\n font-weight: 600;\n}\n\n/* Content text editor area */\n.content-text-editor {\n flex: 1;\n padding: 20px;\n display: flex;\n flex-direction: column;\n}\n\n.editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.editor-label {\n margin: 0;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.content-type-badge {\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 0.75em;\n color: var(--mj-text-inverse);\n}\n\n.content-type-badge.new {\n background: var(--mj-status-success);\n}\n\n.content-type-badge.existing {\n background: var(--mj-text-muted);\n}\n\n.editor-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.unsaved-indicator {\n color: var(--mj-status-warning);\n font-size: 0.85em;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.unsaved-indicator i {\n font-size: 0.5em;\n}\n\n.run-btn {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n padding: 6px 12px;\n border-radius: 4px;\n font-size: 0.85em;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n cursor: pointer;\n}\n\n.run-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n/* Code editor border */\n.code-editor-wrapper {\n flex: 1;\n height: 350px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n}\n\n/* Help section tabs */\n.template-help-section {\n margin-top: 16px;\n}\n\n.help-tabs {\n display: flex;\n border-bottom: 2px solid var(--mj-border-default);\n margin-bottom: 0;\n}\n\n.help-tab {\n padding: 8px 16px;\n border: none;\n background: none;\n cursor: pointer;\n font-size: 0.9em;\n font-weight: 600;\n color: var(--mj-text-muted);\n border-bottom: 3px solid transparent;\n transition: all 0.2s;\n}\n\n.help-tab.active {\n color: var(--mj-status-success);\n border-bottom-color: var(--mj-status-success);\n}\n\n/* Help content area */\n.help-content {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-top: none;\n border-radius: 0 0 4px 4px;\n}\n\n/* Syntax help */\n.syntax-help {\n font-size: 0.85em;\n}\n\n.syntax-help .section-title {\n font-weight: 600;\n margin-bottom: 12px;\n color: var(--mj-status-success);\n}\n\n.syntax-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 16px;\n}\n\n.syntax-item {\n margin-bottom: 8px;\n}\n\n.syntax-help code {\n background: var(--mj-bg-surface);\n padding: 4px 6px;\n border-radius: 3px;\n display: inline-block;\n margin-top: 4px;\n color: var(--mj-text-primary);\n}\n\n/* Placeholders help */\n.placeholders-help {\n font-size: 0.85em;\n}\n\n.placeholders-help .section-title {\n font-weight: 600;\n margin-bottom: 12px;\n color: var(--mj-status-success);\n}\n\n.placeholders-description {\n margin-bottom: 16px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n/* Category tabs */\n.category-tabs {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n}\n\n.category-tab {\n padding: 6px 14px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 20px;\n cursor: pointer;\n font-size: 0.85em;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n color: var(--mj-text-muted);\n}\n\n.category-tab.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.category-tab .tab-badge {\n background: color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n color: inherit;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 0.75em;\n margin-left: 4px;\n}\n\n/* Placeholder content area */\n.placeholder-content {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 16px;\n}\n\n.category-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.category-header i {\n font-size: 1.2em;\n}\n\n.category-header h5 {\n margin: 0;\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n.placeholder-grid {\n display: grid;\n gap: 10px;\n}\n\n/* Placeholder item */\n.placeholder-item {\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n position: relative;\n transition: all 0.2s;\n max-width: 800px;\n}\n\n.placeholder-item:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.placeholder-item:hover .copy-btn {\n opacity: 1 !important;\n}\n\n.placeholder-item-inner {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n\n.placeholder-name-row {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n\n.placeholder-code {\n color: var(--mj-status-error);\n font-weight: 600;\n font-size: 0.95em;\n}\n\n.copy-btn {\n opacity: 0;\n transition: opacity 0.2s;\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-brand-primary);\n border-radius: 4px;\n display: inline-flex;\n align-items: center;\n}\n\n.copy-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.copy-btn i {\n font-size: 0.85em;\n}\n\n.placeholder-description {\n color: var(--mj-text-muted);\n margin-top: 4px;\n line-height: 1.4;\n}\n\n/* Usage example box */\n.usage-example {\n margin-top: 20px;\n padding: 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-radius: 6px;\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-bg-surface));\n}\n\n.usage-example-inner {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n\n.usage-example i {\n color: var(--mj-brand-primary);\n margin-top: 2px;\n}\n\n.usage-example-text {\n flex: 1;\n font-size: 0.85em;\n color: var(--mj-brand-primary);\n line-height: 1.5;\n}\n\n.usage-example code {\n background: var(--mj-bg-surface);\n padding: 2px 4px;\n border-radius: 3px;\n}\n\n/* No content state */\n.no-content-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-card);\n border: 2px dashed var(--mj-border-default);\n border-radius: 8px;\n padding: 40px;\n text-align: center;\n}\n\n.no-content-state i {\n font-size: 48px;\n margin-bottom: 16px;\n color: var(--mj-text-muted);\n opacity: 0.6;\n}\n\n.no-content-state h5 {\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.no-content-state p {\n color: var(--mj-text-muted);\n margin-bottom: 20px;\n}\n"] }]
|
|
896
895
|
}], () => [{ type: i1.MJNotificationService }], { template: [{
|
|
897
896
|
type: Input
|
|
898
897
|
}], config: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-editor.component.js","sourceRoot":"","sources":["../../../../src/lib/shared/components/template-editor.component.ts","../../../../src/lib/shared/components/template-editor.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges, SimpleChanges, ViewChild, AfterViewInit } from '@angular/core';\nimport { MJTemplateEntity, MJTemplateContentEntity } from '@memberjunction/core-entities';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { TemplateEngineBase } from '@memberjunction/templates-base-types';\nimport { LanguageDescription } from '@codemirror/language';\nimport { languages } from '@codemirror/language-data';\nimport { CodeEditorComponent } from '@memberjunction/ng-code-editor';\nimport { Subject } from 'rxjs';\nimport { DEFAULT_SYSTEM_PLACEHOLDERS, SystemPlaceholder, SYSTEM_PLACEHOLDER_CATEGORIES, SystemPlaceholderCategory } from '@memberjunction/ai-core-plus';\n\nexport interface TemplateEditorConfig {\n allowEdit?: boolean;\n showRunButton?: boolean;\n compactMode?: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-template-editor',\n templateUrl: './template-editor.component.html',\n styleUrls: ['./template-editor.component.css']\n})\nexport class TemplateEditorComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit {\n @Input() template: MJTemplateEntity | null = null;\n @Input() config: TemplateEditorConfig = {\n allowEdit: true,\n showRunButton: false,\n compactMode: false\n };\n \n @Output() contentChange = new EventEmitter<MJTemplateContentEntity[]>();\n @Output() runTemplate = new EventEmitter<MJTemplateEntity>();\n \n public templateContents: MJTemplateContentEntity[] = [];\n public selectedContentIndex: number = 0;\n public isAddingNewContent: boolean = false;\n public newTemplateContent: MJTemplateContentEntity | null = null;\n public hasUnsavedChanges: boolean = false;\n public contentTypeOptions: Array<{text: string, value: string}> = [];\n public supportedLanguages: LanguageDescription[] = languages;\n public isRunningTemplate = false;\n public activeHelpTab: 'syntax' | 'placeholders' = 'syntax';\n public activePlaceholderCategory: string = '';\n \n // System placeholders organized by category\n public placeholderCategories: Array<{\n category: SystemPlaceholderCategory;\n placeholders: SystemPlaceholder[];\n }> = [];\n \n @ViewChild('codeEditor') codeEditor: CodeEditorComponent | null = null;\n private isUpdatingEditorValue = false;\n private destroy$ = new Subject<void>();\n private _metadata = new Metadata();\n private activeTimeouts: number[] = [];\n \n constructor(private notificationService: MJNotificationService) {}\n\n async ngOnInit() {\n this.loadContentTypes();\n this.organizePlaceholdersByCategory();\n if (this.template) {\n await this.loadTemplateContents();\n }\n }\n\n async ngOnChanges(changes: SimpleChanges) {\n if (changes['template']) {\n // Template input has changed, reload contents\n if (this.template) {\n await this.loadTemplateContents();\n } else {\n // Template cleared, reset state\n this.templateContents = [];\n this.selectedContentIndex = 0;\n this.isAddingNewContent = false;\n this.newTemplateContent = null;\n this.hasUnsavedChanges = false;\n }\n }\n }\n \n private organizePlaceholdersByCategory() {\n // Group placeholders by their category\n this.placeholderCategories = SYSTEM_PLACEHOLDER_CATEGORIES.map(category => {\n const categoryPlaceholders = DEFAULT_SYSTEM_PLACEHOLDERS.filter(\n placeholder => placeholder.category === category.name\n );\n \n return {\n category: category,\n placeholders: categoryPlaceholders\n };\n }).filter(cat => cat.placeholders.length > 0); // Only include categories that have placeholders\n \n // Add any uncategorized placeholders to a misc category if needed\n const categorized = DEFAULT_SYSTEM_PLACEHOLDERS.filter(p => p.category);\n const uncategorized = DEFAULT_SYSTEM_PLACEHOLDERS.filter(p => !p.category);\n \n if (uncategorized.length > 0) {\n this.placeholderCategories.push({\n category: {\n name: 'Other',\n icon: 'fa-ellipsis-h',\n color: 'var(--mj-text-muted)'\n },\n placeholders: uncategorized\n });\n }\n \n // Set the first category as active\n if (this.placeholderCategories.length > 0) {\n this.activePlaceholderCategory = this.placeholderCategories[0].category.name;\n }\n }\n \n /**\n * Copies a placeholder to the clipboard\n */\n public async copyPlaceholder(placeholderName: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(`{{ ${placeholderName} }}`);\n this.notificationService.CreateSimpleNotification('Placeholder copied to clipboard!', 'success', 2000);\n } catch (error) {\n console.error('Failed to copy placeholder:', error);\n this.notificationService.CreateSimpleNotification('Failed to copy placeholder', 'error', 3000);\n }\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n \n // Clean up any active timeouts\n this.activeTimeouts.forEach(timeoutId => clearTimeout(timeoutId));\n this.activeTimeouts.length = 0;\n }\n\n ngAfterViewInit() {\n // Initial sync when view is ready\n this.syncEditorValue();\n }\n\n async loadTemplateContents() {\n if (this.template) {\n // Reset state first\n this.templateContents = [];\n this.selectedContentIndex = 0;\n this.isAddingNewContent = false;\n this.newTemplateContent = null;\n this.hasUnsavedChanges = false;\n \n if (this.template.IsSaved && this.template.ID) {\n // Load existing template contents for saved templates\n try {\n const rv = new RunView();\n const results = await rv.RunView<MJTemplateContentEntity>({\n EntityName: 'MJ: Template Contents',\n ExtraFilter: `TemplateID='${this.template.ID}'`,\n OrderBy: 'Priority ASC, __mj_CreatedAt ASC',\n ResultType: 'entity_object'\n });\n \n this.templateContents = results.Results;\n } catch (error) {\n console.error('Error loading template contents:', error);\n }\n }\n \n // If we have contents but no selection, select the first one\n if (this.templateContents.length > 0) {\n this.selectedContentIndex = 0;\n }\n \n // If no template contents exist (either new template or saved template with no content), \n // create a default one for single-content optimization\n if (this.templateContents.length === 0) {\n await this.createDefaultTemplateContent();\n }\n\n // Sync editor value after loading content\n this.syncEditorValue();\n this.contentChange.emit(this.templateContents);\n }\n }\n\n /**\n * Public method to refresh the template editor and discard unsaved changes\n * This should be called when canceling edits to restore the original state\n */\n public async refreshAndDiscardChanges() {\n await this.loadTemplateContents();\n }\n\n async createDefaultTemplateContent() {\n const defaultContent = await this._metadata.GetEntityObject<MJTemplateContentEntity>('MJ: Template Contents');\n defaultContent.TemplateID = this.template!.ID;\n defaultContent.Priority = 1;\n defaultContent.IsActive = true;\n \n // Set default to first real content type (skip \"Select Type...\" if it exists)\n const validContentTypes = this.contentTypeOptions.filter(option => option.value !== '');\n if (validContentTypes.length > 0) {\n defaultContent.TypeID = validContentTypes[0].value;\n }\n \n this.templateContents = [defaultContent];\n this.selectedContentIndex = 0;\n \n // Sync editor value after creating default content\n this.syncEditorValue();\n }\n\n selectTemplateContent(index: number, confirmSwitch: boolean = true) {\n // If we're adding new content and user clicks on existing content, ask for confirmation\n if (this.isAddingNewContent && confirmSwitch) {\n if (!confirm('You have unsaved changes to a new content version. Are you sure you want to switch? Your changes will be lost.')) {\n return;\n }\n }\n \n if (index >= 0 && index < this.templateContents.length) {\n this.selectedContentIndex = index;\n this.isAddingNewContent = false;\n // Don't clear newTemplateContent to preserve the work in progress\n \n // Sync editor value when switching content\n this.syncEditorValue();\n }\n }\n\n loadContentTypes() {\n try {\n // Get content types from TemplateEngine cache\n const contentTypes = TemplateEngineBase.Instance.TemplateContentTypes;\n this.contentTypeOptions = [\n { text: 'Select Type...', value: '' },\n ...contentTypes.map(ct => ({\n text: ct.Name,\n value: ct.ID\n }))\n ];\n } catch (error) {\n console.error('Error loading content types:', error);\n // Fallback to basic types\n this.contentTypeOptions = [\n { text: 'Select Type...', value: '' },\n { text: 'HTML', value: 'HTML' },\n { text: 'Plain Text', value: 'Text' },\n { text: 'Markdown', value: 'Markdown' }\n ];\n }\n }\n\n async addNewTemplateContent() {\n if (!this.config.allowEdit) return;\n \n this.newTemplateContent = await this._metadata.GetEntityObject<MJTemplateContentEntity>('MJ: Template Contents');\n this.newTemplateContent.TemplateID = this.template!.ID;\n this.newTemplateContent.Priority = this.templateContents.length + 1;\n this.newTemplateContent.IsActive = true;\n \n // Set default to first real content type (skip \"Select Type...\" if it exists)\n const validContentTypes = this.contentTypeOptions.filter(option => option.value !== '');\n if (validContentTypes.length > 0) {\n this.newTemplateContent.TypeID = validContentTypes[0].value;\n }\n this.newTemplateContent.TemplateText = '';\n \n // Add immediately to the array\n this.templateContents.push(this.newTemplateContent);\n this.selectedContentIndex = this.templateContents.length - 1;\n this.isAddingNewContent = true;\n \n // Sync editor value when adding new content\n this.syncEditorValue();\n }\n\n async deleteTemplateContent(index: number) {\n if (!this.config.allowEdit || index < 0 || index >= this.templateContents.length) return;\n \n const contentToDelete = this.templateContents[index];\n \n // Check if the entity is actually saved, not just if it has an ID\n if (contentToDelete.IsSaved) {\n try {\n const result = await contentToDelete.Delete();\n if (result) {\n this.templateContents.splice(index, 1);\n \n // Adjust selected index if necessary\n if (this.selectedContentIndex >= this.templateContents.length) {\n this.selectedContentIndex = Math.max(0, this.templateContents.length - 1);\n }\n \n // If no contents remain, create a default one\n if (this.templateContents.length === 0) {\n await this.createDefaultTemplateContent();\n }\n \n this.contentChange.emit(this.templateContents);\n } else {\n MJNotificationService.Instance.CreateSimpleNotification(`Failed to delete template content. ${contentToDelete.LatestResult?.Message}`, 'error');\n }\n } catch (error) {\n console.error('Error deleting template content:', error);\n MJNotificationService.Instance.CreateSimpleNotification(`Error deleting template content: ${error}`, 'error');\n }\n } else {\n // Not saved yet, just remove from array\n this.templateContents.splice(index, 1);\n if (this.selectedContentIndex >= this.templateContents.length) {\n this.selectedContentIndex = Math.max(0, this.templateContents.length - 1);\n }\n \n // Reset adding new content state if we're deleting the new content\n if (this.isAddingNewContent && index === this.templateContents.length) {\n this.isAddingNewContent = false;\n this.newTemplateContent = null;\n }\n \n this.contentChange.emit(this.templateContents);\n }\n }\n\n get currentTemplateContent(): MJTemplateContentEntity | null {\n if (this.isAddingNewContent) {\n return this.newTemplateContent;\n }\n return this.templateContents[this.selectedContentIndex] || null;\n }\n\n get hasMultipleContents(): boolean {\n return this.templateContents.length > 1 || this.isAddingNewContent;\n }\n\n onContentTypeChange() {\n // Content type changes just modify the current content, no new record creation\n this.updateUnsavedChangesFlag();\n }\n\n onContentChange() {\n this.updateUnsavedChangesFlag();\n }\n\n /**\n * Updates the hasUnsavedChanges flag based on entity dirty states\n */\n private updateUnsavedChangesFlag() {\n this.hasUnsavedChanges = this.templateContents.some(content => content.Dirty) || \n this.isAddingNewContent;\n }\n\n onTemplateTextChange(event: any) {\n if (this.isUpdatingEditorValue) {\n // Ignore change events when we're programmatically updating the editor\n return;\n }\n \n if (this.currentTemplateContent) {\n // Extract value from event - might be event.target.value or just event depending on component\n const value = typeof event === 'string' ? event : (event.target?.value || event);\n this.currentTemplateContent.TemplateText = value;\n this.updateUnsavedChangesFlag();\n }\n }\n\n /**\n * Helper method to track setTimeout calls for cleanup\n */\n private setTrackedTimeout(callback: () => void, delay: number): number {\n const timeoutId = setTimeout(() => {\n // Remove from tracking when it executes\n const index = this.activeTimeouts.indexOf(timeoutId);\n if (index > -1) {\n this.activeTimeouts.splice(index, 1);\n }\n callback();\n }, delay) as any as number;\n this.activeTimeouts.push(timeoutId);\n return timeoutId;\n }\n\n /**\n * Manually sync the editor value without triggering change events\n */\n private syncEditorValue() {\n // Use Promise.resolve() to wait for the next microtask after any pending changes\n Promise.resolve().then(() => {\n // Then tracked setTimeout for the next macrotask to ensure DOM is updated\n this.setTrackedTimeout(() => {\n if (!this.codeEditor) {\n return;\n }\n \n this.isUpdatingEditorValue = true;\n const newValue = this.currentTemplateContent?.TemplateText || '';\n \n // Use the setValue method from mj-code-editor component\n this.codeEditor.setValue(newValue); \n this.isUpdatingEditorValue = false;\n }, 0);\n });\n }\n\n async saveTemplateContents(): Promise<boolean> {\n if (!this.config.allowEdit) return false;\n \n try {\n // Save all template contents that have changes\n for (const content of this.templateContents) {\n content.TemplateID = this.template!.ID; // Ensure FK is set\n if (content.Dirty || !content.ID) {\n const contentResult = await content.Save();\n if (!contentResult) {\n console.error('Failed to save template content:', content);\n return false;\n }\n }\n }\n\n this.isAddingNewContent = false;\n this.newTemplateContent = null;\n this.updateUnsavedChangesFlag();\n this.contentChange.emit(this.templateContents);\n return true;\n } catch (error) {\n console.error('Error saving template contents:', error);\n return false;\n }\n }\n\n getContentTypeDisplayText(typeId: string): string {\n if (!typeId) return '-';\n const option = this.contentTypeOptions.find(opt => opt.value === typeId);\n return option ? option.text : typeId;\n }\n\n getEditorLanguage(): string {\n if (!this.currentTemplateContent?.TypeID) {\n return 'jinja2'; // default to jinja2 for template syntax (compatible with Nunjucks)\n }\n\n const contentType = this.currentTemplateContent.TypeID.toLowerCase();\n \n // Map content types to CodeMirror language modes\n switch (contentType) {\n case 'html':\n return 'jinja2'; // Use jinja2 for HTML templates to get template syntax highlighting\n case 'markdown':\n case 'md':\n return 'markdown';\n case 'javascript':\n case 'js':\n return 'javascript';\n case 'css':\n return 'css';\n case 'json':\n return 'json';\n case 'xml':\n return 'xml';\n case 'sql':\n return 'sql';\n case 'text':\n case 'plain':\n default:\n return 'jinja2'; // Default to jinja2 since templates often contain template syntax\n }\n }\n\n /**\n * Test run the current template using the parameter dialog\n */\n async onRunTemplate() {\n if (!this.template?.IsSaved || !this.currentTemplateContent) {\n MJNotificationService.Instance.CreateSimpleNotification(\n 'Please save the template before running it.', \n 'warning'\n );\n return;\n }\n\n // Save any unsaved changes first\n if (this.hasUnsavedChanges) {\n const saveResult = await this.saveTemplateContents();\n if (!saveResult) {\n MJNotificationService.Instance.CreateSimpleNotification(\n 'Failed to save template changes.', \n 'error'\n );\n return;\n }\n }\n\n // Emit the run template event\n this.runTemplate.emit(this.template);\n }\n\n getContentTypeOptionsForContent(): Array<{text: string, value: string}> {\n // Always exclude \"Select Type...\" option for all content\n return this.contentTypeOptions.filter(option => option.value !== '');\n }\n}","@if (template) {\n <div class=\"template-editor\" style=\"height: 100%; display: flex; flex-direction: column;\">\n <!-- Content Versions List/Tabs -->\n @if (templateContents.length > 0) {\n <div class=\"content-versions-tabs\">\n <div class=\"content-tabs\">\n @for (content of templateContents; track content.ID || $index; let i = $index) {\n <div class=\"content-version-tab\"\n [class.active]=\"selectedContentIndex === i && !isAddingNewContent\"\n (click)=\"selectTemplateContent(i, false)\">\n <div style=\"flex: 1;\">\n <div class=\"tab-label\">\n {{ content.Type || 'Version ' + (i + 1) }}\n </div>\n <div class=\"tab-meta\">\n P:{{ content.Priority }}\n @if (!content.IsActive) {\n • <span class=\"inactive-label\">Inactive</span>\n }\n </div>\n </div>\n @if (templateContents.length > 1 && config.allowEdit) {\n <button type=\"button\"\n (click)=\"deleteTemplateContent(i); $event.stopPropagation()\"\n class=\"delete-btn\"\n title=\"Delete this content version\">\n <i class=\"fa-solid fa-trash fa-xs\"></i>\n </button>\n }\n </div>\n }\n @if (isAddingNewContent) {\n <div class=\"content-version-tab adding-new\">\n <i class=\"fa-solid fa-plus text-success\"></i>\n <span class=\"new-label\">New</span>\n </div>\n }\n <!-- Add New Content (Edit Mode Only) -->\n @if (config.allowEdit && !isAddingNewContent) {\n <div class=\"content-version-tab add-new\"\n (click)=\"addNewTemplateContent()\"\n title=\"Add new template content\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New</span>\n </div>\n }\n </div>\n </div>\n }\n <!-- Content Editor -->\n @if (currentTemplateContent) {\n <div class=\"content-editor-container\">\n <!-- Content Metadata Bar -->\n <div class=\"content-metadata-bar\">\n <div class=\"metadata-grid\">\n <div class=\"form-group\">\n <label for=\"contentType\" class=\"form-label\">\n <i class=\"fa-solid fa-tag\"></i> Content Type\n </label>\n @if (config.allowEdit) {\n <kendo-dropdownlist [(ngModel)]=\"currentTemplateContent.TypeID\"\n name=\"contentType\"\n [data]=\"getContentTypeOptionsForContent()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n (valueChange)=\"onContentTypeChange()\">\n </kendo-dropdownlist>\n } @else {\n <div class=\"form-control-plaintext\">\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n </div>\n }\n </div>\n <div class=\"form-group\">\n <label for=\"priority\" class=\"form-label\">\n <i class=\"fa-solid fa-sort-numeric-up\"></i> Priority\n </label>\n @if (config.allowEdit) {\n <kendo-numerictextbox [(ngModel)]=\"currentTemplateContent.Priority\"\n name=\"priority\"\n [min]=\"1\"\n [step]=\"1\"\n [format]=\"'n0'\">\n </kendo-numerictextbox>\n } @else {\n <div class=\"form-control-plaintext\">\n {{ currentTemplateContent.Priority || '-' }}\n </div>\n }\n </div>\n <div class=\"form-group\">\n <label class=\"form-label\">\n <i class=\"fa-solid fa-toggle-on\"></i> Status\n </label>\n @if (config.allowEdit) {\n <div class=\"form-check\">\n <input type=\"checkbox\"\n id=\"isActive\"\n class=\"form-check-input\"\n [(ngModel)]=\"currentTemplateContent.IsActive\"\n name=\"isActive\">\n <label class=\"form-check-label\" for=\"isActive\">\n Active\n </label>\n </div>\n } @else {\n <div class=\"form-control-plaintext\">\n @if (currentTemplateContent.IsActive) {\n <span class=\"badge-success\">\n <i class=\"fa-solid fa-check-circle\"></i> Active\n </span>\n } @else {\n <span class=\"badge-secondary\">\n <i class=\"fa-solid fa-pause-circle\"></i> Inactive\n </span>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Content Text Editor -->\n <div class=\"content-text-editor\">\n <div class=\"editor-header\">\n <label for=\"templateContent\" class=\"editor-label\">\n <i class=\"fa-solid fa-code\"></i> Template Content\n <span class=\"content-type-badge\"\n [class.new]=\"!currentTemplateContent.ID\"\n [class.existing]=\"!!currentTemplateContent.ID\">\n @if (!currentTemplateContent.ID) {\n New\n } @else {\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n }\n </span>\n </label>\n <div class=\"editor-actions\">\n @if (!isAddingNewContent && hasUnsavedChanges) {\n <span class=\"unsaved-indicator\">\n <i class=\"fa-solid fa-circle\"></i>\n Unsaved changes\n </span>\n }\n @if (template.IsSaved && currentTemplateContent && config.showRunButton) {\n <button type=\"button\"\n class=\"run-btn\"\n [disabled]=\"isRunningTemplate\"\n (click)=\"onRunTemplate()\"\n title=\"Test run this template\">\n @if (isRunningTemplate) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Running...\n } @else {\n <i class=\"fa-solid fa-play\"></i>\n Run\n }\n </button>\n }\n </div>\n </div>\n <mj-code-editor\n #codeEditor\n (change)=\"onTemplateTextChange($event)\"\n [readonly]=\"!config.allowEdit\"\n [language]=\"getEditorLanguage()\"\n [languages]=\"supportedLanguages\"\n class=\"code-editor-wrapper\">\n </mj-code-editor>\n <!-- Template Help Section with Tabs -->\n @if (!config.compactMode) {\n <div class=\"template-help-section\">\n <!-- Tab Navigation -->\n <div class=\"help-tabs\">\n <button type=\"button\"\n class=\"help-tab\"\n [class.active]=\"activeHelpTab === 'syntax'\"\n (click)=\"activeHelpTab = 'syntax'\">\n <i class=\"fa-solid fa-code\"></i> Template Syntax\n </button>\n <button type=\"button\"\n class=\"help-tab\"\n [class.active]=\"activeHelpTab === 'placeholders'\"\n (click)=\"activeHelpTab = 'placeholders'\">\n <i class=\"fa-solid fa-at\"></i> System Placeholders\n </button>\n </div>\n <!-- Tab Content -->\n <div class=\"help-content\">\n <!-- Template Syntax Tab -->\n @if (activeHelpTab === 'syntax') {\n <div class=\"syntax-help\">\n <div class=\"section-title\">\n <i class=\"fa-solid fa-lightbulb\"></i> Template Syntax Quick Reference\n </div>\n <div class=\"syntax-grid\">\n <div>\n <div class=\"syntax-item\">\n <strong>Parameters:</strong><br>\n <code>{{'{{'}} paramName {{'}}'}}</code>\n </div>\n <div>\n <strong>Template Includes:</strong><br>\n <code>{{'{% template \"TemplateName\" %}'}}</code>\n </div>\n </div>\n <div>\n <div class=\"syntax-item\">\n <strong>Conditionals:</strong><br>\n <code>{{'{% if condition %}'}} ... {{'{% endif %}'}}</code>\n </div>\n <div>\n <strong>Loops:</strong><br>\n <code>{{'{% for item in items %}'}} ... {{'{% endfor %}'}}</code>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- System Placeholders Tab -->\n @if (activeHelpTab === 'placeholders') {\n <div class=\"placeholders-help\">\n <div class=\"section-title\">\n <i class=\"fa-solid fa-at\"></i> System Placeholders Reference\n </div>\n <p class=\"placeholders-description\">\n System placeholders are automatically available in all AI prompt templates. Simply use them in your template text and they will be replaced with their current values at execution time.\n </p>\n <!-- Category Sub-tabs -->\n <div class=\"category-tabs\">\n @for (categoryGroup of placeholderCategories; track categoryGroup.category.name) {\n <button type=\"button\"\n class=\"category-tab\"\n [class.active]=\"activePlaceholderCategory === categoryGroup.category.name\"\n (click)=\"activePlaceholderCategory = categoryGroup.category.name\">\n <i [class]=\"'fa-solid ' + categoryGroup.category.icon\" style=\"font-size: 0.9em;\"></i>\n {{ categoryGroup.category.name }}\n <span class=\"tab-badge\">\n {{ categoryGroup.placeholders.length }}\n </span>\n </button>\n }\n </div>\n <!-- Active Category Content -->\n <div class=\"placeholder-content\">\n @for (categoryGroup of placeholderCategories; track categoryGroup.category.name) {\n @if (activePlaceholderCategory === categoryGroup.category.name) {\n <div class=\"category-header\">\n <i [class]=\"'fa-solid ' + categoryGroup.category.icon\"\n [style.color]=\"categoryGroup.category.color\"></i>\n <h5>{{ categoryGroup.category.name }}</h5>\n </div>\n <div class=\"placeholder-grid\">\n @for (placeholder of categoryGroup.placeholders; track placeholder.name) {\n <div class=\"placeholder-item\">\n <div class=\"placeholder-item-inner\">\n <div>\n <div class=\"placeholder-name-row\">\n <code class=\"placeholder-code\">{{'{{'}} {{ placeholder.name }} {{'}}'}}</code>\n <button type=\"button\"\n class=\"copy-btn\"\n (click)=\"copyPlaceholder(placeholder.name)\"\n title=\"Copy placeholder to clipboard\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n @if (placeholder.description) {\n <div class=\"placeholder-description\">{{ placeholder.description }}</div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n <!-- Usage Example -->\n <div class=\"usage-example\">\n <div class=\"usage-example-inner\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <div class=\"usage-example-text\">\n <strong>Usage Example:</strong> To use a system placeholder in your template, simply include it in double curly braces.\n For example: <code>\"Today is {{'{{'}} _CURRENT_DATE {{'}}'}} and the current user is {{'{{'}} _USER_NAME {{'}}'}}\"</code>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- No Content State -->\n <div class=\"no-content-state\">\n <i class=\"fa-solid fa-file-plus\"></i>\n <h5>No Template Content</h5>\n <p>Create your first template content version to get started.</p>\n @if (config.allowEdit) {\n <button type=\"button\"\n (click)=\"addNewTemplateContent()\"\n class=\"btn btn-primary\">\n <i class=\"fa-solid fa-plus\"></i> Create First Content Version\n </button>\n }\n </div>\n }\n </div>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"template-editor.component.js","sourceRoot":"","sources":["../../../../src/lib/shared/components/template-editor.component.ts","../../../../src/lib/shared/components/template-editor.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges, SimpleChanges, ViewChild, AfterViewInit } from '@angular/core';\nimport { MJTemplateEntity, MJTemplateContentEntity } from '@memberjunction/core-entities';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { TemplateEngineBase } from '@memberjunction/templates-base-types';\nimport { LanguageDescription } from '@codemirror/language';\nimport { languages } from '@codemirror/language-data';\nimport { CodeEditorComponent } from '@memberjunction/ng-code-editor';\nimport { Subject } from 'rxjs';\nimport { DEFAULT_SYSTEM_PLACEHOLDERS, SystemPlaceholder, SYSTEM_PLACEHOLDER_CATEGORIES, SystemPlaceholderCategory } from '@memberjunction/ai-core-plus';\n\nexport interface TemplateEditorConfig {\n allowEdit?: boolean;\n showRunButton?: boolean;\n compactMode?: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-template-editor',\n templateUrl: './template-editor.component.html',\n styleUrls: ['./template-editor.component.css']\n})\nexport class TemplateEditorComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit {\n @Input() template: MJTemplateEntity | null = null;\n @Input() config: TemplateEditorConfig = {\n allowEdit: true,\n showRunButton: false,\n compactMode: false\n };\n \n @Output() contentChange = new EventEmitter<MJTemplateContentEntity[]>();\n @Output() runTemplate = new EventEmitter<MJTemplateEntity>();\n \n public templateContents: MJTemplateContentEntity[] = [];\n public selectedContentIndex: number = 0;\n public isAddingNewContent: boolean = false;\n public newTemplateContent: MJTemplateContentEntity | null = null;\n public hasUnsavedChanges: boolean = false;\n public contentTypeOptions: Array<{text: string, value: string}> = [];\n public supportedLanguages: LanguageDescription[] = languages;\n public isRunningTemplate = false;\n public activeHelpTab: 'syntax' | 'placeholders' = 'syntax';\n public activePlaceholderCategory: string = '';\n \n // System placeholders organized by category\n public placeholderCategories: Array<{\n category: SystemPlaceholderCategory;\n placeholders: SystemPlaceholder[];\n }> = [];\n \n @ViewChild('codeEditor') codeEditor: CodeEditorComponent | null = null;\n private isUpdatingEditorValue = false;\n private destroy$ = new Subject<void>();\n private _metadata = new Metadata();\n private activeTimeouts: number[] = [];\n \n constructor(private notificationService: MJNotificationService) {}\n\n async ngOnInit() {\n this.loadContentTypes();\n this.organizePlaceholdersByCategory();\n if (this.template) {\n await this.loadTemplateContents();\n }\n }\n\n async ngOnChanges(changes: SimpleChanges) {\n if (changes['template']) {\n // Template input has changed, reload contents\n if (this.template) {\n await this.loadTemplateContents();\n } else {\n // Template cleared, reset state\n this.templateContents = [];\n this.selectedContentIndex = 0;\n this.isAddingNewContent = false;\n this.newTemplateContent = null;\n this.hasUnsavedChanges = false;\n }\n }\n }\n \n private organizePlaceholdersByCategory() {\n // Group placeholders by their category\n this.placeholderCategories = SYSTEM_PLACEHOLDER_CATEGORIES.map(category => {\n const categoryPlaceholders = DEFAULT_SYSTEM_PLACEHOLDERS.filter(\n placeholder => placeholder.category === category.name\n );\n \n return {\n category: category,\n placeholders: categoryPlaceholders\n };\n }).filter(cat => cat.placeholders.length > 0); // Only include categories that have placeholders\n \n // Add any uncategorized placeholders to a misc category if needed\n const categorized = DEFAULT_SYSTEM_PLACEHOLDERS.filter(p => p.category);\n const uncategorized = DEFAULT_SYSTEM_PLACEHOLDERS.filter(p => !p.category);\n \n if (uncategorized.length > 0) {\n this.placeholderCategories.push({\n category: {\n name: 'Other',\n icon: 'fa-ellipsis-h',\n color: 'var(--mj-text-muted)'\n },\n placeholders: uncategorized\n });\n }\n \n // Set the first category as active\n if (this.placeholderCategories.length > 0) {\n this.activePlaceholderCategory = this.placeholderCategories[0].category.name;\n }\n }\n \n /**\n * Copies a placeholder to the clipboard\n */\n public async copyPlaceholder(placeholderName: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(`{{ ${placeholderName} }}`);\n this.notificationService.CreateSimpleNotification('Placeholder copied to clipboard!', 'success', 2000);\n } catch (error) {\n console.error('Failed to copy placeholder:', error);\n this.notificationService.CreateSimpleNotification('Failed to copy placeholder', 'error', 3000);\n }\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n \n // Clean up any active timeouts\n this.activeTimeouts.forEach(timeoutId => clearTimeout(timeoutId));\n this.activeTimeouts.length = 0;\n }\n\n ngAfterViewInit() {\n // Initial sync when view is ready\n this.syncEditorValue();\n }\n\n async loadTemplateContents() {\n if (this.template) {\n // Reset state first\n this.templateContents = [];\n this.selectedContentIndex = 0;\n this.isAddingNewContent = false;\n this.newTemplateContent = null;\n this.hasUnsavedChanges = false;\n \n if (this.template.IsSaved && this.template.ID) {\n // Load existing template contents for saved templates\n try {\n const rv = new RunView();\n const results = await rv.RunView<MJTemplateContentEntity>({\n EntityName: 'MJ: Template Contents',\n ExtraFilter: `TemplateID='${this.template.ID}'`,\n OrderBy: 'Priority ASC, __mj_CreatedAt ASC',\n ResultType: 'entity_object'\n });\n \n this.templateContents = results.Results;\n } catch (error) {\n console.error('Error loading template contents:', error);\n }\n }\n \n // If we have contents but no selection, select the first one\n if (this.templateContents.length > 0) {\n this.selectedContentIndex = 0;\n }\n \n // If no template contents exist (either new template or saved template with no content), \n // create a default one for single-content optimization\n if (this.templateContents.length === 0) {\n await this.createDefaultTemplateContent();\n }\n\n // Sync editor value after loading content\n this.syncEditorValue();\n this.contentChange.emit(this.templateContents);\n }\n }\n\n /**\n * Public method to refresh the template editor and discard unsaved changes\n * This should be called when canceling edits to restore the original state\n */\n public async refreshAndDiscardChanges() {\n await this.loadTemplateContents();\n }\n\n async createDefaultTemplateContent() {\n const defaultContent = await this._metadata.GetEntityObject<MJTemplateContentEntity>('MJ: Template Contents');\n defaultContent.TemplateID = this.template!.ID;\n defaultContent.Priority = 1;\n defaultContent.IsActive = true;\n \n // Set default to first real content type (skip \"Select Type...\" if it exists)\n const validContentTypes = this.contentTypeOptions.filter(option => option.value !== '');\n if (validContentTypes.length > 0) {\n defaultContent.TypeID = validContentTypes[0].value;\n }\n \n this.templateContents = [defaultContent];\n this.selectedContentIndex = 0;\n \n // Sync editor value after creating default content\n this.syncEditorValue();\n }\n\n selectTemplateContent(index: number, confirmSwitch: boolean = true) {\n // If we're adding new content and user clicks on existing content, ask for confirmation\n if (this.isAddingNewContent && confirmSwitch) {\n if (!confirm('You have unsaved changes to a new content version. Are you sure you want to switch? Your changes will be lost.')) {\n return;\n }\n }\n \n if (index >= 0 && index < this.templateContents.length) {\n this.selectedContentIndex = index;\n this.isAddingNewContent = false;\n // Don't clear newTemplateContent to preserve the work in progress\n \n // Sync editor value when switching content\n this.syncEditorValue();\n }\n }\n\n loadContentTypes() {\n try {\n // Get content types from TemplateEngine cache\n const contentTypes = TemplateEngineBase.Instance.TemplateContentTypes;\n this.contentTypeOptions = [\n { text: 'Select Type...', value: '' },\n ...contentTypes.map(ct => ({\n text: ct.Name,\n value: ct.ID\n }))\n ];\n } catch (error) {\n console.error('Error loading content types:', error);\n // Fallback to basic types\n this.contentTypeOptions = [\n { text: 'Select Type...', value: '' },\n { text: 'HTML', value: 'HTML' },\n { text: 'Plain Text', value: 'Text' },\n { text: 'Markdown', value: 'Markdown' }\n ];\n }\n }\n\n async addNewTemplateContent() {\n if (!this.config.allowEdit) return;\n \n this.newTemplateContent = await this._metadata.GetEntityObject<MJTemplateContentEntity>('MJ: Template Contents');\n this.newTemplateContent.TemplateID = this.template!.ID;\n this.newTemplateContent.Priority = this.templateContents.length + 1;\n this.newTemplateContent.IsActive = true;\n \n // Set default to first real content type (skip \"Select Type...\" if it exists)\n const validContentTypes = this.contentTypeOptions.filter(option => option.value !== '');\n if (validContentTypes.length > 0) {\n this.newTemplateContent.TypeID = validContentTypes[0].value;\n }\n this.newTemplateContent.TemplateText = '';\n \n // Add immediately to the array\n this.templateContents.push(this.newTemplateContent);\n this.selectedContentIndex = this.templateContents.length - 1;\n this.isAddingNewContent = true;\n \n // Sync editor value when adding new content\n this.syncEditorValue();\n }\n\n async deleteTemplateContent(index: number) {\n if (!this.config.allowEdit || index < 0 || index >= this.templateContents.length) return;\n \n const contentToDelete = this.templateContents[index];\n \n // Check if the entity is actually saved, not just if it has an ID\n if (contentToDelete.IsSaved) {\n try {\n const result = await contentToDelete.Delete();\n if (result) {\n this.templateContents.splice(index, 1);\n \n // Adjust selected index if necessary\n if (this.selectedContentIndex >= this.templateContents.length) {\n this.selectedContentIndex = Math.max(0, this.templateContents.length - 1);\n }\n \n // If no contents remain, create a default one\n if (this.templateContents.length === 0) {\n await this.createDefaultTemplateContent();\n }\n \n this.contentChange.emit(this.templateContents);\n } else {\n MJNotificationService.Instance.CreateSimpleNotification(`Failed to delete template content. ${contentToDelete.LatestResult?.Message}`, 'error');\n }\n } catch (error) {\n console.error('Error deleting template content:', error);\n MJNotificationService.Instance.CreateSimpleNotification(`Error deleting template content: ${error}`, 'error');\n }\n } else {\n // Not saved yet, just remove from array\n this.templateContents.splice(index, 1);\n if (this.selectedContentIndex >= this.templateContents.length) {\n this.selectedContentIndex = Math.max(0, this.templateContents.length - 1);\n }\n \n // Reset adding new content state if we're deleting the new content\n if (this.isAddingNewContent && index === this.templateContents.length) {\n this.isAddingNewContent = false;\n this.newTemplateContent = null;\n }\n \n this.contentChange.emit(this.templateContents);\n }\n }\n\n get currentTemplateContent(): MJTemplateContentEntity | null {\n if (this.isAddingNewContent) {\n return this.newTemplateContent;\n }\n return this.templateContents[this.selectedContentIndex] || null;\n }\n\n get hasMultipleContents(): boolean {\n return this.templateContents.length > 1 || this.isAddingNewContent;\n }\n\n onContentTypeChange() {\n // Content type changes just modify the current content, no new record creation\n this.updateUnsavedChangesFlag();\n }\n\n onContentChange() {\n this.updateUnsavedChangesFlag();\n }\n\n /**\n * Updates the hasUnsavedChanges flag based on entity dirty states\n */\n private updateUnsavedChangesFlag() {\n this.hasUnsavedChanges = this.templateContents.some(content => content.Dirty) || \n this.isAddingNewContent;\n }\n\n onTemplateTextChange(event: any) {\n if (this.isUpdatingEditorValue) {\n // Ignore change events when we're programmatically updating the editor\n return;\n }\n \n if (this.currentTemplateContent) {\n // Extract value from event - might be event.target.value or just event depending on component\n const value = typeof event === 'string' ? event : (event.target?.value || event);\n this.currentTemplateContent.TemplateText = value;\n this.updateUnsavedChangesFlag();\n }\n }\n\n /**\n * Helper method to track setTimeout calls for cleanup\n */\n private setTrackedTimeout(callback: () => void, delay: number): number {\n const timeoutId = setTimeout(() => {\n // Remove from tracking when it executes\n const index = this.activeTimeouts.indexOf(timeoutId);\n if (index > -1) {\n this.activeTimeouts.splice(index, 1);\n }\n callback();\n }, delay) as any as number;\n this.activeTimeouts.push(timeoutId);\n return timeoutId;\n }\n\n /**\n * Manually sync the editor value without triggering change events\n */\n private syncEditorValue() {\n // Use Promise.resolve() to wait for the next microtask after any pending changes\n Promise.resolve().then(() => {\n // Then tracked setTimeout for the next macrotask to ensure DOM is updated\n this.setTrackedTimeout(() => {\n if (!this.codeEditor) {\n return;\n }\n \n this.isUpdatingEditorValue = true;\n const newValue = this.currentTemplateContent?.TemplateText || '';\n \n // Use the setValue method from mj-code-editor component\n this.codeEditor.setValue(newValue); \n this.isUpdatingEditorValue = false;\n }, 0);\n });\n }\n\n async saveTemplateContents(): Promise<boolean> {\n if (!this.config.allowEdit) return false;\n \n try {\n // Save all template contents that have changes\n for (const content of this.templateContents) {\n content.TemplateID = this.template!.ID; // Ensure FK is set\n if (content.Dirty || !content.ID) {\n const contentResult = await content.Save();\n if (!contentResult) {\n console.error('Failed to save template content:', content);\n return false;\n }\n }\n }\n\n this.isAddingNewContent = false;\n this.newTemplateContent = null;\n this.updateUnsavedChangesFlag();\n this.contentChange.emit(this.templateContents);\n return true;\n } catch (error) {\n console.error('Error saving template contents:', error);\n return false;\n }\n }\n\n getContentTypeDisplayText(typeId: string): string {\n if (!typeId) return '-';\n const option = this.contentTypeOptions.find(opt => opt.value === typeId);\n return option ? option.text : typeId;\n }\n\n getEditorLanguage(): string {\n if (!this.currentTemplateContent?.TypeID) {\n return 'jinja2'; // default to jinja2 for template syntax (compatible with Nunjucks)\n }\n\n const contentType = this.currentTemplateContent.TypeID.toLowerCase();\n \n // Map content types to CodeMirror language modes\n switch (contentType) {\n case 'html':\n return 'jinja2'; // Use jinja2 for HTML templates to get template syntax highlighting\n case 'markdown':\n case 'md':\n return 'markdown';\n case 'javascript':\n case 'js':\n return 'javascript';\n case 'css':\n return 'css';\n case 'json':\n return 'json';\n case 'xml':\n return 'xml';\n case 'sql':\n return 'sql';\n case 'text':\n case 'plain':\n default:\n return 'jinja2'; // Default to jinja2 since templates often contain template syntax\n }\n }\n\n /**\n * Test run the current template using the parameter dialog\n */\n async onRunTemplate() {\n if (!this.template?.IsSaved || !this.currentTemplateContent) {\n MJNotificationService.Instance.CreateSimpleNotification(\n 'Please save the template before running it.', \n 'warning'\n );\n return;\n }\n\n // Save any unsaved changes first\n if (this.hasUnsavedChanges) {\n const saveResult = await this.saveTemplateContents();\n if (!saveResult) {\n MJNotificationService.Instance.CreateSimpleNotification(\n 'Failed to save template changes.', \n 'error'\n );\n return;\n }\n }\n\n // Emit the run template event\n this.runTemplate.emit(this.template);\n }\n\n getContentTypeOptionsForContent(): Array<{text: string, value: string}> {\n // Always exclude \"Select Type...\" option for all content\n return this.contentTypeOptions.filter(option => option.value !== '');\n }\n}","@if (template) {\n <div class=\"template-editor\" style=\"height: 100%; display: flex; flex-direction: column;\">\n <!-- Content Versions List/Tabs -->\n @if (templateContents.length > 0) {\n <div class=\"content-versions-tabs\">\n <div class=\"content-tabs\">\n @for (content of templateContents; track content.ID || $index; let i = $index) {\n <div class=\"content-version-tab\"\n [class.active]=\"selectedContentIndex === i && !isAddingNewContent\"\n (click)=\"selectTemplateContent(i, false)\">\n <div style=\"flex: 1;\">\n <div class=\"tab-label\">\n {{ content.Type || 'Version ' + (i + 1) }}\n </div>\n <div class=\"tab-meta\">\n P:{{ content.Priority }}\n @if (!content.IsActive) {\n • <span class=\"inactive-label\">Inactive</span>\n }\n </div>\n </div>\n @if (templateContents.length > 1 && config.allowEdit) {\n <button type=\"button\"\n (click)=\"deleteTemplateContent(i); $event.stopPropagation()\"\n class=\"delete-btn\"\n title=\"Delete this content version\">\n <i class=\"fa-solid fa-trash fa-xs\"></i>\n </button>\n }\n </div>\n }\n @if (isAddingNewContent) {\n <div class=\"content-version-tab adding-new\">\n <i class=\"fa-solid fa-plus text-success\"></i>\n <span class=\"new-label\">New</span>\n </div>\n }\n <!-- Add New Content (Edit Mode Only) -->\n @if (config.allowEdit && !isAddingNewContent) {\n <div class=\"content-version-tab add-new\"\n (click)=\"addNewTemplateContent()\"\n title=\"Add new template content\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New</span>\n </div>\n }\n </div>\n </div>\n }\n <!-- Content Editor -->\n @if (currentTemplateContent) {\n <div class=\"content-editor-container\">\n <!-- Content Metadata Bar -->\n <div class=\"content-metadata-bar\">\n <div class=\"metadata-grid\">\n <div class=\"form-group\">\n <label for=\"contentType\" class=\"form-label\">\n <i class=\"fa-solid fa-tag\"></i> Content Type\n </label>\n @if (config.allowEdit) {\n <mj-dropdown [(ngModel)]=\"currentTemplateContent.TypeID\"\n name=\"contentType\"\n [Data]=\"getContentTypeOptionsForContent()\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n (ValueChange)=\"onContentTypeChange()\">\n </mj-dropdown>\n } @else {\n <div class=\"form-control-plaintext\">\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n </div>\n }\n </div>\n <div class=\"form-group\">\n <label for=\"priority\" class=\"form-label\">\n <i class=\"fa-solid fa-sort-numeric-up\"></i> Priority\n </label>\n @if (config.allowEdit) {\n <mj-numeric-input [(ngModel)]=\"currentTemplateContent.Priority\"\n name=\"priority\"\n [Min]=\"1\"\n [Step]=\"1\"\n [Format]=\"'n0'\">\n </mj-numeric-input>\n } @else {\n <div class=\"form-control-plaintext\">\n {{ currentTemplateContent.Priority || '-' }}\n </div>\n }\n </div>\n <div class=\"form-group\">\n <label class=\"form-label\">\n <i class=\"fa-solid fa-toggle-on\"></i> Status\n </label>\n @if (config.allowEdit) {\n <div class=\"form-check\">\n <input type=\"checkbox\"\n id=\"isActive\"\n class=\"form-check-input\"\n [(ngModel)]=\"currentTemplateContent.IsActive\"\n name=\"isActive\">\n <label class=\"form-check-label\" for=\"isActive\">\n Active\n </label>\n </div>\n } @else {\n <div class=\"form-control-plaintext\">\n @if (currentTemplateContent.IsActive) {\n <span class=\"badge-success\">\n <i class=\"fa-solid fa-check-circle\"></i> Active\n </span>\n } @else {\n <span class=\"badge-secondary\">\n <i class=\"fa-solid fa-pause-circle\"></i> Inactive\n </span>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Content Text Editor -->\n <div class=\"content-text-editor\">\n <div class=\"editor-header\">\n <label for=\"templateContent\" class=\"editor-label\">\n <i class=\"fa-solid fa-code\"></i> Template Content\n <span class=\"content-type-badge\"\n [class.new]=\"!currentTemplateContent.ID\"\n [class.existing]=\"!!currentTemplateContent.ID\">\n @if (!currentTemplateContent.ID) {\n New\n } @else {\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n }\n </span>\n </label>\n <div class=\"editor-actions\">\n @if (!isAddingNewContent && hasUnsavedChanges) {\n <span class=\"unsaved-indicator\">\n <i class=\"fa-solid fa-circle\"></i>\n Unsaved changes\n </span>\n }\n @if (template.IsSaved && currentTemplateContent && config.showRunButton) {\n <button type=\"button\"\n class=\"run-btn\"\n [disabled]=\"isRunningTemplate\"\n (click)=\"onRunTemplate()\"\n title=\"Test run this template\">\n @if (isRunningTemplate) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Running...\n } @else {\n <i class=\"fa-solid fa-play\"></i>\n Run\n }\n </button>\n }\n </div>\n </div>\n <mj-code-editor\n #codeEditor\n (change)=\"onTemplateTextChange($event)\"\n [readonly]=\"!config.allowEdit\"\n [language]=\"getEditorLanguage()\"\n [languages]=\"supportedLanguages\"\n class=\"code-editor-wrapper\">\n </mj-code-editor>\n <!-- Template Help Section with Tabs -->\n @if (!config.compactMode) {\n <div class=\"template-help-section\">\n <!-- Tab Navigation -->\n <div class=\"help-tabs\">\n <button type=\"button\"\n class=\"help-tab\"\n [class.active]=\"activeHelpTab === 'syntax'\"\n (click)=\"activeHelpTab = 'syntax'\">\n <i class=\"fa-solid fa-code\"></i> Template Syntax\n </button>\n <button type=\"button\"\n class=\"help-tab\"\n [class.active]=\"activeHelpTab === 'placeholders'\"\n (click)=\"activeHelpTab = 'placeholders'\">\n <i class=\"fa-solid fa-at\"></i> System Placeholders\n </button>\n </div>\n <!-- Tab Content -->\n <div class=\"help-content\">\n <!-- Template Syntax Tab -->\n @if (activeHelpTab === 'syntax') {\n <div class=\"syntax-help\">\n <div class=\"section-title\">\n <i class=\"fa-solid fa-lightbulb\"></i> Template Syntax Quick Reference\n </div>\n <div class=\"syntax-grid\">\n <div>\n <div class=\"syntax-item\">\n <strong>Parameters:</strong><br>\n <code>{{'{{'}} paramName {{'}}'}}</code>\n </div>\n <div>\n <strong>Template Includes:</strong><br>\n <code>{{'{% template \"TemplateName\" %}'}}</code>\n </div>\n </div>\n <div>\n <div class=\"syntax-item\">\n <strong>Conditionals:</strong><br>\n <code>{{'{% if condition %}'}} ... {{'{% endif %}'}}</code>\n </div>\n <div>\n <strong>Loops:</strong><br>\n <code>{{'{% for item in items %}'}} ... {{'{% endfor %}'}}</code>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- System Placeholders Tab -->\n @if (activeHelpTab === 'placeholders') {\n <div class=\"placeholders-help\">\n <div class=\"section-title\">\n <i class=\"fa-solid fa-at\"></i> System Placeholders Reference\n </div>\n <p class=\"placeholders-description\">\n System placeholders are automatically available in all AI prompt templates. Simply use them in your template text and they will be replaced with their current values at execution time.\n </p>\n <!-- Category Sub-tabs -->\n <div class=\"category-tabs\">\n @for (categoryGroup of placeholderCategories; track categoryGroup.category.name) {\n <button type=\"button\"\n class=\"category-tab\"\n [class.active]=\"activePlaceholderCategory === categoryGroup.category.name\"\n (click)=\"activePlaceholderCategory = categoryGroup.category.name\">\n <i [class]=\"'fa-solid ' + categoryGroup.category.icon\" style=\"font-size: 0.9em;\"></i>\n {{ categoryGroup.category.name }}\n <span class=\"tab-badge\">\n {{ categoryGroup.placeholders.length }}\n </span>\n </button>\n }\n </div>\n <!-- Active Category Content -->\n <div class=\"placeholder-content\">\n @for (categoryGroup of placeholderCategories; track categoryGroup.category.name) {\n @if (activePlaceholderCategory === categoryGroup.category.name) {\n <div class=\"category-header\">\n <i [class]=\"'fa-solid ' + categoryGroup.category.icon\"\n [style.color]=\"categoryGroup.category.color\"></i>\n <h5>{{ categoryGroup.category.name }}</h5>\n </div>\n <div class=\"placeholder-grid\">\n @for (placeholder of categoryGroup.placeholders; track placeholder.name) {\n <div class=\"placeholder-item\">\n <div class=\"placeholder-item-inner\">\n <div>\n <div class=\"placeholder-name-row\">\n <code class=\"placeholder-code\">{{'{{'}} {{ placeholder.name }} {{'}}'}}</code>\n <button type=\"button\"\n class=\"copy-btn\"\n (click)=\"copyPlaceholder(placeholder.name)\"\n title=\"Copy placeholder to clipboard\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n @if (placeholder.description) {\n <div class=\"placeholder-description\">{{ placeholder.description }}</div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n <!-- Usage Example -->\n <div class=\"usage-example\">\n <div class=\"usage-example-inner\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <div class=\"usage-example-text\">\n <strong>Usage Example:</strong> To use a system placeholder in your template, simply include it in double curly braces.\n For example: <code>\"Today is {{'{{'}} _CURRENT_DATE {{'}}'}} and the current user is {{'{{'}} _USER_NAME {{'}}'}}\"</code>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- No Content State -->\n <div class=\"no-content-state\">\n <i class=\"fa-solid fa-file-plus\"></i>\n <h5>No Template Content</h5>\n <p>Create your first template content version to get started.</p>\n @if (config.allowEdit) {\n <button type=\"button\"\n (click)=\"addNewTemplateContent()\"\n class=\"btn btn-primary\">\n <i class=\"fa-solid fa-plus\"></i> Create First Content Version\n </button>\n }\n </div>\n }\n </div>\n}\n"]}
|