@memberjunction/ng-core-entity-forms 2.57.0 → 2.59.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.
@@ -4,14 +4,18 @@ import { MJNotificationService } from '@memberjunction/ng-notifications';
4
4
  import { TemplateEngineBase } from '@memberjunction/templates-base-types';
5
5
  import { languages } from '@codemirror/language-data';
6
6
  import { Subject } from 'rxjs';
7
+ import { DEFAULT_SYSTEM_PLACEHOLDERS, SYSTEM_PLACEHOLDER_CATEGORIES } from '@memberjunction/ai-core-plus';
7
8
  import * as i0 from "@angular/core";
8
- import * as i1 from "@angular/common";
9
- import * as i2 from "@angular/forms";
10
- import * as i3 from "@progress/kendo-angular-inputs";
11
- import * as i4 from "@progress/kendo-angular-dropdowns";
12
- import * as i5 from "@memberjunction/ng-code-editor";
9
+ import * as i1 from "@memberjunction/ng-notifications";
10
+ import * as i2 from "@angular/common";
11
+ import * as i3 from "@angular/forms";
12
+ import * as i4 from "@progress/kendo-angular-inputs";
13
+ import * as i5 from "@progress/kendo-angular-dropdowns";
14
+ import * as i6 from "@memberjunction/ng-code-editor";
13
15
  const _c0 = ["codeEditor"];
14
16
  const _forTrack0 = ($index, $item) => $item.ID || $index;
17
+ const _forTrack1 = ($index, $item) => $item.category.name;
18
+ const _forTrack2 = ($index, $item) => $item.name;
15
19
  function TemplateEditorComponent_div_0_Conditional_1_For_3_Conditional_6_Template(rf, ctx) { if (rf & 1) {
16
20
  i0.ɵɵtext(0, " \u2022 ");
17
21
  i0.ɵɵelementStart(1, "span", 14);
@@ -191,46 +195,182 @@ function TemplateEditorComponent_div_0_Conditional_2_Conditional_31_Template(rf,
191
195
  i0.ɵɵadvance();
192
196
  i0.ɵɵconditional(ctx_r2.isRunningTemplate ? 1 : 2);
193
197
  } }
194
- function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Template(rf, ctx) { if (rf & 1) {
195
- i0.ɵɵelementStart(0, "div", 45)(1, "div", 58);
196
- i0.ɵɵelement(2, "i", 59);
197
- i0.ɵɵtext(3, " Template Syntax Quick Reference: ");
198
- i0.ɵɵelementEnd();
199
- i0.ɵɵelementStart(4, "div", 60)(5, "div")(6, "strong");
200
- i0.ɵɵtext(7, "Parameters:");
201
- i0.ɵɵelementEnd();
202
- i0.ɵɵelementStart(8, "code", 61);
203
- i0.ɵɵtext(9);
198
+ function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_9_Template(rf, ctx) { if (rf & 1) {
199
+ i0.ɵɵelementStart(0, "div", 62)(1, "div", 64);
200
+ i0.ɵɵelement(2, "i", 65);
201
+ i0.ɵɵtext(3, " Template Syntax Quick Reference ");
204
202
  i0.ɵɵelementEnd();
205
- i0.ɵɵelement(10, "br");
206
- i0.ɵɵelementStart(11, "strong");
207
- i0.ɵɵtext(12, "Includes:");
203
+ i0.ɵɵelementStart(4, "div", 66)(5, "div")(6, "div", 67)(7, "strong");
204
+ i0.ɵɵtext(8, "Parameters:");
208
205
  i0.ɵɵelementEnd();
209
- i0.ɵɵelementStart(13, "code", 61);
210
- i0.ɵɵtext(14);
206
+ i0.ɵɵelement(9, "br");
207
+ i0.ɵɵelementStart(10, "code", 68);
208
+ i0.ɵɵtext(11);
211
209
  i0.ɵɵelementEnd()();
212
- i0.ɵɵelementStart(15, "div")(16, "strong");
213
- i0.ɵɵtext(17, "Conditionals:");
210
+ i0.ɵɵelementStart(12, "div")(13, "strong");
211
+ i0.ɵɵtext(14, "Template Includes:");
214
212
  i0.ɵɵelementEnd();
215
- i0.ɵɵelementStart(18, "code", 61);
216
- i0.ɵɵtext(19);
217
- i0.ɵɵelementEnd();
218
- i0.ɵɵelement(20, "br");
219
- i0.ɵɵelementStart(21, "strong");
220
- i0.ɵɵtext(22, "Loops:");
213
+ i0.ɵɵelement(15, "br");
214
+ i0.ɵɵelementStart(16, "code", 68);
215
+ i0.ɵɵtext(17);
216
+ i0.ɵɵelementEnd()()();
217
+ i0.ɵɵelementStart(18, "div")(19, "div", 67)(20, "strong");
218
+ i0.ɵɵtext(21, "Conditionals:");
221
219
  i0.ɵɵelementEnd();
222
- i0.ɵɵelementStart(23, "code", 61);
220
+ i0.ɵɵelement(22, "br");
221
+ i0.ɵɵelementStart(23, "code", 68);
223
222
  i0.ɵɵtext(24);
224
- i0.ɵɵelementEnd()()()();
223
+ i0.ɵɵelementEnd()();
224
+ i0.ɵɵelementStart(25, "div")(26, "strong");
225
+ i0.ɵɵtext(27, "Loops:");
226
+ i0.ɵɵelementEnd();
227
+ i0.ɵɵelement(28, "br");
228
+ i0.ɵɵelementStart(29, "code", 68);
229
+ i0.ɵɵtext(30);
230
+ i0.ɵɵelementEnd()()()()();
225
231
  } if (rf & 2) {
226
- i0.ɵɵadvance(9);
232
+ i0.ɵɵadvance(11);
227
233
  i0.ɵɵtextInterpolate2("", "{{", " paramName ", "}}", "");
228
- i0.ɵɵadvance(5);
234
+ i0.ɵɵadvance(6);
229
235
  i0.ɵɵtextInterpolate("{% template \"TemplateName\" %}");
236
+ i0.ɵɵadvance(7);
237
+ i0.ɵɵtextInterpolate2("", "{% if condition %}", " ... ", "{% endif %}", "");
238
+ i0.ɵɵadvance(6);
239
+ i0.ɵɵtextInterpolate2("", "{% for item in items %}", " ... ", "{% endfor %}", "");
240
+ } }
241
+ function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_8_Template(rf, ctx) { if (rf & 1) {
242
+ const _r13 = i0.ɵɵgetCurrentView();
243
+ i0.ɵɵelementStart(0, "button", 78);
244
+ i0.ɵɵlistener("click", function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_8_Template_button_click_0_listener() { const categoryGroup_r14 = i0.ɵɵrestoreView(_r13).$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.activePlaceholderCategory = categoryGroup_r14.category.name); });
245
+ i0.ɵɵelement(1, "i", 79);
246
+ i0.ɵɵtext(2);
247
+ i0.ɵɵelementStart(3, "span", 80);
248
+ i0.ɵɵtext(4);
249
+ i0.ɵɵelementEnd()();
250
+ } if (rf & 2) {
251
+ const categoryGroup_r14 = ctx.$implicit;
252
+ const ctx_r2 = i0.ɵɵnextContext(5);
253
+ i0.ɵɵstyleProp("border-color", ctx_r2.activePlaceholderCategory === categoryGroup_r14.category.name ? categoryGroup_r14.category.color : "#dee2e6")("background", ctx_r2.activePlaceholderCategory === categoryGroup_r14.category.name ? categoryGroup_r14.category.color + "10" : "white")("color", ctx_r2.activePlaceholderCategory === categoryGroup_r14.category.name ? categoryGroup_r14.category.color : "#6c757d");
254
+ i0.ɵɵclassProp("active", ctx_r2.activePlaceholderCategory === categoryGroup_r14.category.name);
255
+ i0.ɵɵadvance();
256
+ i0.ɵɵclassMap("fa-solid " + categoryGroup_r14.category.icon);
257
+ i0.ɵɵadvance();
258
+ i0.ɵɵtextInterpolate1(" ", categoryGroup_r14.category.name, " ");
259
+ i0.ɵɵadvance(2);
260
+ i0.ɵɵtextInterpolate1(" ", categoryGroup_r14.placeholders.length, " ");
261
+ } }
262
+ function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Conditional_8_Template(rf, ctx) { if (rf & 1) {
263
+ i0.ɵɵelementStart(0, "div", 90);
264
+ i0.ɵɵtext(1);
265
+ i0.ɵɵelementEnd();
266
+ } if (rf & 2) {
267
+ const placeholder_r16 = i0.ɵɵnextContext().$implicit;
268
+ i0.ɵɵadvance();
269
+ i0.ɵɵtextInterpolate(placeholder_r16.description);
270
+ } }
271
+ function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Template(rf, ctx) { if (rf & 1) {
272
+ const _r15 = i0.ɵɵgetCurrentView();
273
+ i0.ɵɵelementStart(0, "div", 85)(1, "div", 74)(2, "div")(3, "div", 86)(4, "code", 87);
274
+ i0.ɵɵtext(5);
275
+ i0.ɵɵelementEnd();
276
+ i0.ɵɵelementStart(6, "button", 88);
277
+ i0.ɵɵlistener("click", function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Template_button_click_6_listener() { const placeholder_r16 = i0.ɵɵrestoreView(_r15).$implicit; const ctx_r2 = i0.ɵɵnextContext(7); return i0.ɵɵresetView(ctx_r2.copyPlaceholder(placeholder_r16.name)); });
278
+ i0.ɵɵelement(7, "i", 89);
279
+ i0.ɵɵelementEnd()();
280
+ i0.ɵɵtemplate(8, TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Conditional_8_Template, 2, 1, "div", 90);
281
+ i0.ɵɵelementEnd()()();
282
+ } if (rf & 2) {
283
+ const placeholder_r16 = ctx.$implicit;
230
284
  i0.ɵɵadvance(5);
231
- i0.ɵɵtextInterpolate("{% if condition %}");
232
- i0.ɵɵadvance(5);
233
- i0.ɵɵtextInterpolate("{% for item in items %}");
285
+ i0.ɵɵtextInterpolate3("", "{{", " ", placeholder_r16.name, " ", "}}", "");
286
+ i0.ɵɵadvance(3);
287
+ i0.ɵɵconditional(placeholder_r16.description ? 8 : -1);
288
+ } }
289
+ function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_Template(rf, ctx) { if (rf & 1) {
290
+ i0.ɵɵelementStart(0, "div", 81);
291
+ i0.ɵɵelement(1, "i", 82);
292
+ i0.ɵɵelementStart(2, "h5", 83);
293
+ i0.ɵɵtext(3);
294
+ i0.ɵɵelementEnd()();
295
+ i0.ɵɵelementStart(4, "div", 84);
296
+ i0.ɵɵrepeaterCreate(5, TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Template, 9, 4, "div", 85, _forTrack2);
297
+ i0.ɵɵelementEnd();
298
+ } if (rf & 2) {
299
+ const categoryGroup_r17 = i0.ɵɵnextContext().$implicit;
300
+ i0.ɵɵadvance();
301
+ i0.ɵɵclassMap("fa-solid " + categoryGroup_r17.category.icon);
302
+ i0.ɵɵstyleProp("color", categoryGroup_r17.category.color);
303
+ i0.ɵɵadvance(2);
304
+ i0.ɵɵtextInterpolate(categoryGroup_r17.category.name);
305
+ i0.ɵɵadvance(2);
306
+ i0.ɵɵrepeater(categoryGroup_r17.placeholders);
307
+ } }
308
+ function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_11_Template(rf, ctx) { if (rf & 1) {
309
+ i0.ɵɵtemplate(0, TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_Template, 7, 5);
310
+ } if (rf & 2) {
311
+ const categoryGroup_r17 = ctx.$implicit;
312
+ const ctx_r2 = i0.ɵɵnextContext(5);
313
+ i0.ɵɵconditional(ctx_r2.activePlaceholderCategory === categoryGroup_r17.category.name ? 0 : -1);
314
+ } }
315
+ function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_Template(rf, ctx) { if (rf & 1) {
316
+ i0.ɵɵelementStart(0, "div", 63)(1, "div", 64);
317
+ i0.ɵɵelement(2, "i", 60);
318
+ i0.ɵɵtext(3, " System Placeholders Reference ");
319
+ i0.ɵɵelementEnd();
320
+ i0.ɵɵelementStart(4, "p", 69);
321
+ i0.ɵɵtext(5, " 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. ");
322
+ i0.ɵɵelementEnd();
323
+ i0.ɵɵelementStart(6, "div", 70);
324
+ i0.ɵɵrepeaterCreate(7, TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_8_Template, 5, 12, "button", 71, _forTrack1);
325
+ i0.ɵɵelementEnd();
326
+ i0.ɵɵelementStart(9, "div", 72);
327
+ i0.ɵɵrepeaterCreate(10, TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_For_11_Template, 1, 1, null, null, _forTrack1);
328
+ i0.ɵɵelementEnd();
329
+ i0.ɵɵelementStart(12, "div", 73)(13, "div", 74);
330
+ i0.ɵɵelement(14, "i", 75);
331
+ i0.ɵɵelementStart(15, "div", 76)(16, "strong");
332
+ i0.ɵɵtext(17, "Usage Example:");
333
+ i0.ɵɵelementEnd();
334
+ i0.ɵɵtext(18, " To use a system placeholder in your template, simply include it in double curly braces. For example: ");
335
+ i0.ɵɵelementStart(19, "code", 77);
336
+ i0.ɵɵtext(20);
337
+ i0.ɵɵelementEnd()()()()();
338
+ } if (rf & 2) {
339
+ const ctx_r2 = i0.ɵɵnextContext(4);
340
+ i0.ɵɵadvance(7);
341
+ i0.ɵɵrepeater(ctx_r2.placeholderCategories);
342
+ i0.ɵɵadvance(3);
343
+ i0.ɵɵrepeater(ctx_r2.placeholderCategories);
344
+ i0.ɵɵadvance(10);
345
+ i0.ɵɵtextInterpolate4("\"Today is ", "{{", " _CURRENT_DATE ", "}}", " and the current user is ", "{{", " _USER_NAME ", "}}", "\"");
346
+ } }
347
+ function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Template(rf, ctx) { if (rf & 1) {
348
+ const _r12 = i0.ɵɵgetCurrentView();
349
+ i0.ɵɵelementStart(0, "div", 45)(1, "div", 58)(2, "button", 59);
350
+ i0.ɵɵlistener("click", function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.activeHelpTab = "syntax"); });
351
+ i0.ɵɵelement(3, "i", 39);
352
+ i0.ɵɵtext(4, " Template Syntax ");
353
+ i0.ɵɵelementEnd();
354
+ i0.ɵɵelementStart(5, "button", 59);
355
+ i0.ɵɵlistener("click", function TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.activeHelpTab = "placeholders"); });
356
+ i0.ɵɵelement(6, "i", 60);
357
+ i0.ɵɵtext(7, " System Placeholders ");
358
+ i0.ɵɵelementEnd()();
359
+ i0.ɵɵelementStart(8, "div", 61);
360
+ i0.ɵɵtemplate(9, TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_9_Template, 31, 7, "div", 62)(10, TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Conditional_10_Template, 21, 4, "div", 63);
361
+ i0.ɵɵelementEnd()();
362
+ } if (rf & 2) {
363
+ const ctx_r2 = i0.ɵɵnextContext(3);
364
+ i0.ɵɵadvance(2);
365
+ i0.ɵɵstyleProp("color", ctx_r2.activeHelpTab === "syntax" ? "#28a745" : "#6c757d")("border-bottom-color", ctx_r2.activeHelpTab === "syntax" ? "#28a745" : "transparent");
366
+ i0.ɵɵclassProp("active", ctx_r2.activeHelpTab === "syntax");
367
+ i0.ɵɵadvance(3);
368
+ i0.ɵɵstyleProp("color", ctx_r2.activeHelpTab === "placeholders" ? "#28a745" : "#6c757d")("border-bottom-color", ctx_r2.activeHelpTab === "placeholders" ? "#28a745" : "transparent");
369
+ i0.ɵɵclassProp("active", ctx_r2.activeHelpTab === "placeholders");
370
+ i0.ɵɵadvance(4);
371
+ i0.ɵɵconditional(ctx_r2.activeHelpTab === "syntax" ? 9 : -1);
372
+ i0.ɵɵadvance();
373
+ i0.ɵɵconditional(ctx_r2.activeHelpTab === "placeholders" ? 10 : -1);
234
374
  } }
235
375
  function TemplateEditorComponent_div_0_Conditional_2_Template(rf, ctx) { if (rf & 1) {
236
376
  const _r7 = i0.ɵɵgetCurrentView();
@@ -264,7 +404,7 @@ function TemplateEditorComponent_div_0_Conditional_2_Template(rf, ctx) { if (rf
264
404
  i0.ɵɵelementStart(32, "mj-code-editor", 44, 0);
265
405
  i0.ɵɵlistener("change", function TemplateEditorComponent_div_0_Conditional_2_Template_mj_code_editor_change_32_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onTemplateTextChange($event)); });
266
406
  i0.ɵɵelementEnd();
267
- i0.ɵɵtemplate(34, TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Template, 25, 5, "div", 45);
407
+ i0.ɵɵtemplate(34, TemplateEditorComponent_div_0_Conditional_2_Conditional_34_Template, 11, 14, "div", 45);
268
408
  i0.ɵɵelementEnd()();
269
409
  } if (rf & 2) {
270
410
  const ctx_r2 = i0.ɵɵnextContext(2);
@@ -288,23 +428,23 @@ function TemplateEditorComponent_div_0_Conditional_2_Template(rf, ctx) { if (rf
288
428
  i0.ɵɵconditional(!ctx_r2.config.compactMode ? 34 : -1);
289
429
  } }
290
430
  function TemplateEditorComponent_div_0_Conditional_3_Conditional_6_Template(rf, ctx) { if (rf & 1) {
291
- const _r12 = i0.ɵɵgetCurrentView();
292
- i0.ɵɵelementStart(0, "button", 66);
293
- i0.ɵɵlistener("click", function TemplateEditorComponent_div_0_Conditional_3_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.addNewTemplateContent()); });
294
- i0.ɵɵelement(1, "i", 67);
431
+ const _r18 = i0.ɵɵgetCurrentView();
432
+ i0.ɵɵelementStart(0, "button", 95);
433
+ i0.ɵɵlistener("click", function TemplateEditorComponent_div_0_Conditional_3_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.addNewTemplateContent()); });
434
+ i0.ɵɵelement(1, "i", 96);
295
435
  i0.ɵɵtext(2, " Create First Content Version ");
296
436
  i0.ɵɵelementEnd();
297
437
  } }
298
438
  function TemplateEditorComponent_div_0_Conditional_3_Template(rf, ctx) { if (rf & 1) {
299
439
  i0.ɵɵelementStart(0, "div", 5);
300
- i0.ɵɵelement(1, "i", 62);
301
- i0.ɵɵelementStart(2, "h5", 63);
440
+ i0.ɵɵelement(1, "i", 91);
441
+ i0.ɵɵelementStart(2, "h5", 92);
302
442
  i0.ɵɵtext(3, "No Template Content");
303
443
  i0.ɵɵelementEnd();
304
- i0.ɵɵelementStart(4, "p", 64);
444
+ i0.ɵɵelementStart(4, "p", 93);
305
445
  i0.ɵɵtext(5, "Create your first template content version to get started.");
306
446
  i0.ɵɵelementEnd();
307
- i0.ɵɵtemplate(6, TemplateEditorComponent_div_0_Conditional_3_Conditional_6_Template, 3, 0, "button", 65);
447
+ i0.ɵɵtemplate(6, TemplateEditorComponent_div_0_Conditional_3_Conditional_6_Template, 3, 0, "button", 94);
308
448
  i0.ɵɵelementEnd();
309
449
  } if (rf & 2) {
310
450
  const ctx_r2 = i0.ɵɵnextContext(2);
@@ -323,7 +463,8 @@ function TemplateEditorComponent_div_0_Template(rf, ctx) { if (rf & 1) {
323
463
  i0.ɵɵconditional(ctx_r2.currentTemplateContent ? 2 : 3);
324
464
  } }
325
465
  export class TemplateEditorComponent {
326
- constructor() {
466
+ constructor(notificationService) {
467
+ this.notificationService = notificationService;
327
468
  this.template = null;
328
469
  this.config = {
329
470
  allowEdit: true,
@@ -340,6 +481,10 @@ export class TemplateEditorComponent {
340
481
  this.contentTypeOptions = [];
341
482
  this.supportedLanguages = languages;
342
483
  this.isRunningTemplate = false;
484
+ this.activeHelpTab = 'syntax';
485
+ this.activePlaceholderCategory = '';
486
+ // System placeholders organized by category
487
+ this.placeholderCategories = [];
343
488
  this.codeEditor = null;
344
489
  this.isUpdatingEditorValue = false;
345
490
  this.destroy$ = new Subject();
@@ -347,10 +492,51 @@ export class TemplateEditorComponent {
347
492
  }
348
493
  async ngOnInit() {
349
494
  this.loadContentTypes();
495
+ this.organizePlaceholdersByCategory();
350
496
  if (this.template) {
351
497
  await this.loadTemplateContents();
352
498
  }
353
499
  }
500
+ organizePlaceholdersByCategory() {
501
+ // Group placeholders by their category
502
+ this.placeholderCategories = SYSTEM_PLACEHOLDER_CATEGORIES.map(category => {
503
+ const categoryPlaceholders = DEFAULT_SYSTEM_PLACEHOLDERS.filter(placeholder => placeholder.category === category.name);
504
+ return {
505
+ category: category,
506
+ placeholders: categoryPlaceholders
507
+ };
508
+ }).filter(cat => cat.placeholders.length > 0); // Only include categories that have placeholders
509
+ // Add any uncategorized placeholders to a misc category if needed
510
+ const categorized = DEFAULT_SYSTEM_PLACEHOLDERS.filter(p => p.category);
511
+ const uncategorized = DEFAULT_SYSTEM_PLACEHOLDERS.filter(p => !p.category);
512
+ if (uncategorized.length > 0) {
513
+ this.placeholderCategories.push({
514
+ category: {
515
+ name: 'Other',
516
+ icon: 'fa-ellipsis-h',
517
+ color: '#6c757d'
518
+ },
519
+ placeholders: uncategorized
520
+ });
521
+ }
522
+ // Set the first category as active
523
+ if (this.placeholderCategories.length > 0) {
524
+ this.activePlaceholderCategory = this.placeholderCategories[0].category.name;
525
+ }
526
+ }
527
+ /**
528
+ * Copies a placeholder to the clipboard
529
+ */
530
+ async copyPlaceholder(placeholderName) {
531
+ try {
532
+ await navigator.clipboard.writeText(`{{ ${placeholderName} }}`);
533
+ this.notificationService.CreateSimpleNotification('Placeholder copied to clipboard!', 'success', 2000);
534
+ }
535
+ catch (error) {
536
+ console.error('Failed to copy placeholder:', error);
537
+ this.notificationService.CreateSimpleNotification('Failed to copy placeholder', 'error', 3000);
538
+ }
539
+ }
354
540
  ngOnDestroy() {
355
541
  this.destroy$.next();
356
542
  this.destroy$.complete();
@@ -639,22 +825,22 @@ export class TemplateEditorComponent {
639
825
  // Always exclude "Select Type..." option for all content
640
826
  return this.contentTypeOptions.filter(option => option.value !== '');
641
827
  }
642
- static { this.ɵfac = function TemplateEditorComponent_Factory(t) { return new (t || TemplateEditorComponent)(); }; }
828
+ static { this.ɵfac = function TemplateEditorComponent_Factory(t) { return new (t || TemplateEditorComponent)(i0.ɵɵdirectiveInject(i1.MJNotificationService)); }; }
643
829
  static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TemplateEditorComponent, selectors: [["mj-template-editor"]], viewQuery: function TemplateEditorComponent_Query(rf, ctx) { if (rf & 1) {
644
830
  i0.ɵɵviewQuery(_c0, 5);
645
831
  } if (rf & 2) {
646
832
  let _t;
647
833
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.codeEditor = _t.first);
648
- } }, inputs: { template: "template", config: "config" }, outputs: { contentChange: "contentChange", runTemplate: "runTemplate" }, decls: 1, vars: 1, consts: [["codeEditor", ""], ["class", "template-editor", "style", "height: 100%; display: flex; flex-direction: column;", 4, "ngIf"], [1, "template-editor", 2, "height", "100%", "display", "flex", "flex-direction", "column"], [1, "content-versions-tabs", 2, "margin-bottom", "16px", "border-bottom", "2px solid #e0e0e0", "padding-bottom", "8px"], [1, "content-editor-container", 2, "flex", "1", "display", "flex", "flex-direction", "column", "background", "#fff", "border", "1px solid #dee2e6", "border-radius", "8px", "overflow", "hidden"], [1, "no-content-state", 2, "flex", "1", "display", "flex", "flex-direction", "column", "align-items", "center", "justify-content", "center", "background", "#f8f9fa", "border", "2px dashed #dee2e6", "border-radius", "8px", "padding", "40px", "text-align", "center"], [1, "content-tabs", 2, "display", "flex", "gap", "6px", "flex-wrap", "wrap"], [1, "content-version-tab", 2, "padding", "8px 12px", "border", "1px solid #ccc", "border-radius", "6px", "cursor", "pointer", "background", "#fff", "display", "flex", "align-items", "center", "gap", "6px", "transition", "all 0.2s", "position", "relative", 3, "active", "border-color", "background"], [1, "content-version-tab", "active", 2, "padding", "8px 12px", "border", "1px solid #28a745", "border-radius", "6px", "background", "#d4edda", "display", "flex", "align-items", "center", "gap", "6px"], ["onmouseover", "this.style.backgroundColor='#e8f5e9'; this.style.borderStyle='solid';", "onmouseout", "this.style.backgroundColor='#f8f9fa'; this.style.borderStyle='dashed';", "title", "Add new template content", 1, "content-version-tab", "add-new", 2, "padding", "8px 12px", "border", "1px dashed #28a745", "border-radius", "6px", "background", "#f8f9fa", "display", "flex", "align-items", "center", "gap", "6px", "cursor", "pointer", "transition", "all 0.2s"], [1, "content-version-tab", 2, "padding", "8px 12px", "border", "1px solid #ccc", "border-radius", "6px", "cursor", "pointer", "background", "#fff", "display", "flex", "align-items", "center", "gap", "6px", "transition", "all 0.2s", "position", "relative", 3, "click"], [2, "flex", "1"], [2, "font-weight", "600", "font-size", "0.85em", "color", "#495057"], [2, "font-size", "0.7em", "color", "#6c757d"], [2, "color", "#dc3545"], ["type", "button", "onmouseover", "this.style.backgroundColor='#dc3545'; this.style.color='white';", "onmouseout", "this.style.backgroundColor='transparent'; this.style.color='#dc3545';", "title", "Delete this content version", 1, "btn-sm", "delete-btn", 2, "background", "none", "border", "none", "color", "#dc3545", "padding", "4px", "border-radius", "3px", "transition", "all 0.2s", "cursor", "pointer"], ["type", "button", "onmouseover", "this.style.backgroundColor='#dc3545'; this.style.color='white';", "onmouseout", "this.style.backgroundColor='transparent'; this.style.color='#dc3545';", "title", "Delete this content version", 1, "btn-sm", "delete-btn", 2, "background", "none", "border", "none", "color", "#dc3545", "padding", "4px", "border-radius", "3px", "transition", "all 0.2s", "cursor", "pointer", 3, "click"], [1, "fa-solid", "fa-trash", "fa-xs"], [1, "fa-solid", "fa-plus", "text-success"], [2, "font-weight", "600", "color", "#155724", "font-size", "0.85em"], ["onmouseover", "this.style.backgroundColor='#e8f5e9'; this.style.borderStyle='solid';", "onmouseout", "this.style.backgroundColor='#f8f9fa'; this.style.borderStyle='dashed';", "title", "Add new template content", 1, "content-version-tab", "add-new", 2, "padding", "8px 12px", "border", "1px dashed #28a745", "border-radius", "6px", "background", "#f8f9fa", "display", "flex", "align-items", "center", "gap", "6px", "cursor", "pointer", "transition", "all 0.2s", 3, "click"], [1, "fa-solid", "fa-plus", 2, "color", "#28a745", "font-size", "0.75em"], [2, "font-weight", "500", "color", "#28a745", "font-size", "0.85em"], [1, "content-metadata-bar", 2, "background", "#f8f9fa", "border-bottom", "1px solid #dee2e6", "padding", "16px 20px"], [2, "display", "grid", "grid-template-columns", "2fr 1fr 1fr auto", "gap", "20px", "align-items", "end"], [1, "form-group", 2, "margin", "0"], ["for", "contentType", 1, "form-label", 2, "margin-bottom", "4px", "font-size", "0.9em", "font-weight", "600"], [1, "fa-solid", "fa-tag"], ["name", "contentType", "textField", "text", "valueField", "value", 3, "ngModel", "data", "valuePrimitive"], [1, "form-control-plaintext", 2, "font-size", "0.9em", "padding", "4px 0"], ["for", "priority", 1, "form-label", 2, "margin-bottom", "4px", "font-size", "0.9em", "font-weight", "600"], [1, "fa-solid", "fa-sort-numeric-up"], ["name", "priority", 3, "ngModel", "min", "step", "format"], [1, "form-label", 2, "margin-bottom", "4px", "font-size", "0.9em", "font-weight", "600"], [1, "fa-solid", "fa-toggle-on"], [1, "form-check", 2, "margin-top", "8px"], [1, "content-text-editor", 2, "flex", "1", "padding", "20px", "display", "flex", "flex-direction", "column"], [2, "display", "flex", "justify-content", "space-between", "align-items", "center", "margin-bottom", "12px"], ["for", "templateContent", 1, "form-label", 2, "margin", "0", "font-weight", "600", "display", "flex", "align-items", "center", "gap", "8px"], [1, "fa-solid", "fa-code"], [1, "badge", 2, "padding", "4px 8px", "border-radius", "4px", "font-size", "0.75em"], [2, "display", "flex", "align-items", "center", "gap", "12px"], [1, "unsaved-indicator", 2, "color", "#fd7e14", "font-size", "0.85em", "display", "flex", "align-items", "center", "gap", "4px"], ["type", "button", "onmouseover", "this.style.background='#138496'", "onmouseout", "this.style.background='#17a2b8'", "title", "Test run this template", 1, "btn", "btn-sm", 2, "background", "#17a2b8", "color", "white", "border", "none", "padding", "6px 12px", "border-radius", "4px", "font-size", "0.85em", "display", "flex", "align-items", "center", "gap", "6px", "transition", "all 0.2s", 3, "disabled"], [2, "flex", "1", "height", "350px", "border", "1px solid #ced4da", "border-radius", "4px", 3, "change", "readonly", "language", "languages"], [1, "syntax-help", 2, "margin-top", "16px", "padding", "12px", "background", "#e8f5e8", "border-left", "4px solid #28a745", "border-radius", "4px", "font-size", "0.85em"], ["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", 2, "font-size", "0.9em"], [1, "badge", "badge-success", 2, "background", "#28a745", "color", "white", "padding", "3px 8px", "border-radius", "3px", "font-size", "0.75em"], [1, "badge", "badge-secondary", 2, "background", "#6c757d", "color", "white", "padding", "3px 8px", "border-radius", "3px", "font-size", "0.75em"], [1, "fa-solid", "fa-check-circle"], [1, "fa-solid", "fa-pause-circle"], [1, "fa-solid", "fa-circle", 2, "font-size", "0.5em"], ["type", "button", "onmouseover", "this.style.background='#138496'", "onmouseout", "this.style.background='#17a2b8'", "title", "Test run this template", 1, "btn", "btn-sm", 2, "background", "#17a2b8", "color", "white", "border", "none", "padding", "6px 12px", "border-radius", "4px", "font-size", "0.85em", "display", "flex", "align-items", "center", "gap", "6px", "transition", "all 0.2s", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-play"], [2, "font-weight", "600", "margin-bottom", "8px", "color", "#155724"], [1, "fa-solid", "fa-lightbulb"], [2, "display", "grid", "grid-template-columns", "1fr 1fr", "gap", "12px"], [2, "background", "#fff", "padding", "2px 4px", "border-radius", "3px"], [1, "fa-solid", "fa-file-plus", 2, "font-size", "48px", "margin-bottom", "16px", "color", "#6c757d", "opacity", "0.6"], [2, "color", "#495057", "margin-bottom", "8px"], [2, "color", "#6c757d", "margin-bottom", "20px"], ["type", "button", 1, "btn", "btn-primary"], ["type", "button", 1, "btn", "btn-primary", 3, "click"], [1, "fa-solid", "fa-plus"]], template: function TemplateEditorComponent_Template(rf, ctx) { if (rf & 1) {
834
+ } }, inputs: { template: "template", config: "config" }, outputs: { contentChange: "contentChange", runTemplate: "runTemplate" }, decls: 1, vars: 1, consts: [["codeEditor", ""], ["class", "template-editor", "style", "height: 100%; display: flex; flex-direction: column;", 4, "ngIf"], [1, "template-editor", 2, "height", "100%", "display", "flex", "flex-direction", "column"], [1, "content-versions-tabs", 2, "margin-bottom", "16px", "border-bottom", "2px solid #e0e0e0", "padding-bottom", "8px"], [1, "content-editor-container", 2, "flex", "1", "display", "flex", "flex-direction", "column", "background", "#fff", "border", "1px solid #dee2e6", "border-radius", "8px", "overflow", "hidden"], [1, "no-content-state", 2, "flex", "1", "display", "flex", "flex-direction", "column", "align-items", "center", "justify-content", "center", "background", "#f8f9fa", "border", "2px dashed #dee2e6", "border-radius", "8px", "padding", "40px", "text-align", "center"], [1, "content-tabs", 2, "display", "flex", "gap", "6px", "flex-wrap", "wrap"], [1, "content-version-tab", 2, "padding", "8px 12px", "border", "1px solid #ccc", "border-radius", "6px", "cursor", "pointer", "background", "#fff", "display", "flex", "align-items", "center", "gap", "6px", "transition", "all 0.2s", "position", "relative", 3, "active", "border-color", "background"], [1, "content-version-tab", "active", 2, "padding", "8px 12px", "border", "1px solid #28a745", "border-radius", "6px", "background", "#d4edda", "display", "flex", "align-items", "center", "gap", "6px"], ["onmouseover", "this.style.backgroundColor='#e8f5e9'; this.style.borderStyle='solid';", "onmouseout", "this.style.backgroundColor='#f8f9fa'; this.style.borderStyle='dashed';", "title", "Add new template content", 1, "content-version-tab", "add-new", 2, "padding", "8px 12px", "border", "1px dashed #28a745", "border-radius", "6px", "background", "#f8f9fa", "display", "flex", "align-items", "center", "gap", "6px", "cursor", "pointer", "transition", "all 0.2s"], [1, "content-version-tab", 2, "padding", "8px 12px", "border", "1px solid #ccc", "border-radius", "6px", "cursor", "pointer", "background", "#fff", "display", "flex", "align-items", "center", "gap", "6px", "transition", "all 0.2s", "position", "relative", 3, "click"], [2, "flex", "1"], [2, "font-weight", "600", "font-size", "0.85em", "color", "#495057"], [2, "font-size", "0.7em", "color", "#6c757d"], [2, "color", "#dc3545"], ["type", "button", "onmouseover", "this.style.backgroundColor='#dc3545'; this.style.color='white';", "onmouseout", "this.style.backgroundColor='transparent'; this.style.color='#dc3545';", "title", "Delete this content version", 1, "btn-sm", "delete-btn", 2, "background", "none", "border", "none", "color", "#dc3545", "padding", "4px", "border-radius", "3px", "transition", "all 0.2s", "cursor", "pointer"], ["type", "button", "onmouseover", "this.style.backgroundColor='#dc3545'; this.style.color='white';", "onmouseout", "this.style.backgroundColor='transparent'; this.style.color='#dc3545';", "title", "Delete this content version", 1, "btn-sm", "delete-btn", 2, "background", "none", "border", "none", "color", "#dc3545", "padding", "4px", "border-radius", "3px", "transition", "all 0.2s", "cursor", "pointer", 3, "click"], [1, "fa-solid", "fa-trash", "fa-xs"], [1, "fa-solid", "fa-plus", "text-success"], [2, "font-weight", "600", "color", "#155724", "font-size", "0.85em"], ["onmouseover", "this.style.backgroundColor='#e8f5e9'; this.style.borderStyle='solid';", "onmouseout", "this.style.backgroundColor='#f8f9fa'; this.style.borderStyle='dashed';", "title", "Add new template content", 1, "content-version-tab", "add-new", 2, "padding", "8px 12px", "border", "1px dashed #28a745", "border-radius", "6px", "background", "#f8f9fa", "display", "flex", "align-items", "center", "gap", "6px", "cursor", "pointer", "transition", "all 0.2s", 3, "click"], [1, "fa-solid", "fa-plus", 2, "color", "#28a745", "font-size", "0.75em"], [2, "font-weight", "500", "color", "#28a745", "font-size", "0.85em"], [1, "content-metadata-bar", 2, "background", "#f8f9fa", "border-bottom", "1px solid #dee2e6", "padding", "16px 20px"], [2, "display", "grid", "grid-template-columns", "2fr 1fr 1fr auto", "gap", "20px", "align-items", "end"], [1, "form-group", 2, "margin", "0"], ["for", "contentType", 1, "form-label", 2, "margin-bottom", "4px", "font-size", "0.9em", "font-weight", "600"], [1, "fa-solid", "fa-tag"], ["name", "contentType", "textField", "text", "valueField", "value", 3, "ngModel", "data", "valuePrimitive"], [1, "form-control-plaintext", 2, "font-size", "0.9em", "padding", "4px 0"], ["for", "priority", 1, "form-label", 2, "margin-bottom", "4px", "font-size", "0.9em", "font-weight", "600"], [1, "fa-solid", "fa-sort-numeric-up"], ["name", "priority", 3, "ngModel", "min", "step", "format"], [1, "form-label", 2, "margin-bottom", "4px", "font-size", "0.9em", "font-weight", "600"], [1, "fa-solid", "fa-toggle-on"], [1, "form-check", 2, "margin-top", "8px"], [1, "content-text-editor", 2, "flex", "1", "padding", "20px", "display", "flex", "flex-direction", "column"], [2, "display", "flex", "justify-content", "space-between", "align-items", "center", "margin-bottom", "12px"], ["for", "templateContent", 1, "form-label", 2, "margin", "0", "font-weight", "600", "display", "flex", "align-items", "center", "gap", "8px"], [1, "fa-solid", "fa-code"], [1, "badge", 2, "padding", "4px 8px", "border-radius", "4px", "font-size", "0.75em"], [2, "display", "flex", "align-items", "center", "gap", "12px"], [1, "unsaved-indicator", 2, "color", "#fd7e14", "font-size", "0.85em", "display", "flex", "align-items", "center", "gap", "4px"], ["type", "button", "onmouseover", "this.style.background='#138496'", "onmouseout", "this.style.background='#17a2b8'", "title", "Test run this template", 1, "btn", "btn-sm", 2, "background", "#17a2b8", "color", "white", "border", "none", "padding", "6px 12px", "border-radius", "4px", "font-size", "0.85em", "display", "flex", "align-items", "center", "gap", "6px", "transition", "all 0.2s", 3, "disabled"], [2, "flex", "1", "height", "350px", "border", "1px solid #ced4da", "border-radius", "4px", 3, "change", "readonly", "language", "languages"], [1, "template-help-section", 2, "margin-top", "16px"], ["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", 2, "font-size", "0.9em"], [1, "badge", "badge-success", 2, "background", "#28a745", "color", "white", "padding", "3px 8px", "border-radius", "3px", "font-size", "0.75em"], [1, "badge", "badge-secondary", 2, "background", "#6c757d", "color", "white", "padding", "3px 8px", "border-radius", "3px", "font-size", "0.75em"], [1, "fa-solid", "fa-check-circle"], [1, "fa-solid", "fa-pause-circle"], [1, "fa-solid", "fa-circle", 2, "font-size", "0.5em"], ["type", "button", "onmouseover", "this.style.background='#138496'", "onmouseout", "this.style.background='#17a2b8'", "title", "Test run this template", 1, "btn", "btn-sm", 2, "background", "#17a2b8", "color", "white", "border", "none", "padding", "6px 12px", "border-radius", "4px", "font-size", "0.85em", "display", "flex", "align-items", "center", "gap", "6px", "transition", "all 0.2s", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-play"], [1, "help-tabs", 2, "display", "flex", "border-bottom", "2px solid #dee2e6", "margin-bottom", "0"], ["type", "button", 1, "help-tab", 2, "padding", "8px 16px", "border", "none", "background", "none", "cursor", "pointer", "font-size", "0.9em", "font-weight", "600", "color", "#6c757d", "border-bottom", "3px solid transparent", "transition", "all 0.2s", 3, "click"], [1, "fa-solid", "fa-at"], [1, "help-content", 2, "padding", "16px", "background", "#f8f9fa", "border", "1px solid #dee2e6", "border-top", "none", "border-radius", "0 0 4px 4px"], [1, "syntax-help", 2, "font-size", "0.85em"], [1, "placeholders-help", 2, "font-size", "0.85em"], [2, "font-weight", "600", "margin-bottom", "12px", "color", "#155724"], [1, "fa-solid", "fa-lightbulb"], [2, "display", "grid", "grid-template-columns", "1fr 1fr", "gap", "16px"], [2, "margin-bottom", "8px"], [2, "background", "#fff", "padding", "4px 6px", "border-radius", "3px", "display", "inline-block", "margin-top", "4px"], [2, "margin-bottom", "16px", "color", "#495057", "line-height", "1.5"], [1, "category-tabs", 2, "display", "flex", "gap", "8px", "margin-bottom", "16px", "flex-wrap", "wrap"], ["type", "button", 1, "category-tab", 2, "padding", "6px 14px", "border", "1px solid #dee2e6", "background", "white", "border-radius", "20px", "cursor", "pointer", "font-size", "0.85em", "font-weight", "500", "display", "flex", "align-items", "center", "gap", "6px", "transition", "all 0.2s", "position", "relative", 3, "active", "border-color", "background", "color"], [1, "placeholder-content", 2, "background", "white", "border", "1px solid #dee2e6", "border-radius", "8px", "padding", "16px"], [2, "margin-top", "20px", "padding", "12px", "background", "#e3f2fd", "border-radius", "6px", "border", "1px solid #bbdefb"], [2, "display", "flex", "align-items", "flex-start", "gap", "8px"], [1, "fa-solid", "fa-info-circle", 2, "color", "#1976d2", "margin-top", "2px"], [2, "flex", "1", "font-size", "0.85em", "color", "#1565c0", "line-height", "1.5"], [2, "background", "white", "padding", "2px 4px", "border-radius", "3px"], ["type", "button", 1, "category-tab", 2, "padding", "6px 14px", "border", "1px solid #dee2e6", "background", "white", "border-radius", "20px", "cursor", "pointer", "font-size", "0.85em", "font-weight", "500", "display", "flex", "align-items", "center", "gap", "6px", "transition", "all 0.2s", "position", "relative", 3, "click"], [2, "font-size", "0.9em"], [1, "badge", 2, "background", "rgba(0,0,0,0.1)", "color", "inherit", "padding", "2px 6px", "border-radius", "10px", "font-size", "0.75em", "margin-left", "4px"], [1, "category-header", 2, "display", "flex", "align-items", "center", "gap", "8px", "margin-bottom", "16px"], [2, "font-size", "1.2em"], [2, "margin", "0", "color", "#343a40", "font-weight", "600"], [2, "display", "grid", "gap", "10px"], ["onmouseover", "this.style.borderColor='#007bff'; this.style.background='#f0f8ff'; this.querySelector('.copy-btn').style.opacity='1';", "onmouseout", "this.style.borderColor='#e9ecef'; this.style.background='#f8f9fa'; this.querySelector('.copy-btn').style.opacity='0';", 1, "placeholder-item", 2, "padding", "12px 16px", "background", "#f8f9fa", "border", "1px solid #e9ecef", "border-radius", "6px", "position", "relative", "transition", "all 0.2s", "max-width", "800px"], [2, "display", "inline-flex", "align-items", "center", "gap", "8px"], [2, "color", "#e83e8c", "font-weight", "600", "font-size", "0.95em"], ["type", "button", "onmouseover", "this.style.background='#e7f3ff';", "onmouseout", "this.style.background='none';", "title", "Copy placeholder to clipboard", 1, "copy-btn", 2, "opacity", "0", "transition", "opacity 0.2s", "background", "none", "border", "none", "padding", "4px 8px", "cursor", "pointer", "color", "#007bff", "border-radius", "4px", "display", "inline-flex", "align-items", "center", 3, "click"], [1, "fa-solid", "fa-copy", 2, "font-size", "0.85em"], [2, "color", "#6c757d", "margin-top", "4px", "line-height", "1.4"], [1, "fa-solid", "fa-file-plus", 2, "font-size", "48px", "margin-bottom", "16px", "color", "#6c757d", "opacity", "0.6"], [2, "color", "#495057", "margin-bottom", "8px"], [2, "color", "#6c757d", "margin-bottom", "20px"], ["type", "button", 1, "btn", "btn-primary"], ["type", "button", 1, "btn", "btn-primary", 3, "click"], [1, "fa-solid", "fa-plus"]], template: function TemplateEditorComponent_Template(rf, ctx) { if (rf & 1) {
649
835
  i0.ɵɵtemplate(0, TemplateEditorComponent_div_0_Template, 4, 2, "div", 1);
650
836
  } if (rf & 2) {
651
837
  i0.ɵɵproperty("ngIf", ctx.template);
652
- } }, dependencies: [i1.NgIf, 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: #f8f9fa !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 rgba(0,0,0,0.1);\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}"] }); }
838
+ } }, dependencies: [i2.NgIf, i3.CheckboxControlValueAccessor, i3.NgControlStatus, i3.NgModel, i4.NumericTextBoxComponent, i5.DropDownListComponent, i6.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: #f8f9fa !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 rgba(0,0,0,0.1);\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}"] }); }
653
839
  }
654
840
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TemplateEditorComponent, [{
655
841
  type: Component,
656
- args: [{ selector: 'mj-template-editor', template: "<div class=\"template-editor\" *ngIf=\"template\" style=\"height: 100%; display: flex; flex-direction: column;\">\n\n <!-- Content Versions List/Tabs -->\n @if (templateContents.length > 0) {\n <div class=\"content-versions-tabs\" style=\"margin-bottom: 16px; border-bottom: 2px solid #e0e0e0; padding-bottom: 8px;\">\n <div class=\"content-tabs\" style=\"display: flex; gap: 6px; flex-wrap: wrap;\">\n \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 style=\"padding: 8px 12px; border: 1px solid #ccc; border-radius: 6px; cursor: pointer; background: #fff; display: flex; align-items: center; gap: 6px; transition: all 0.2s; position: relative;\"\n [style.border-color]=\"selectedContentIndex === i && !isAddingNewContent ? '#007bff' : '#ccc'\"\n [style.background]=\"selectedContentIndex === i && !isAddingNewContent ? '#e3f2fd' : '#fff'\">\n \n <div style=\"flex: 1;\">\n <div style=\"font-weight: 600; font-size: 0.85em; color: #495057;\">\n {{ content.Type || 'Version ' + (i + 1) }}\n </div>\n <div style=\"font-size: 0.7em; color: #6c757d;\">\n P:{{ content.Priority }}\n @if (!content.IsActive) {\n \u2022 <span style=\"color: #dc3545;\">Inactive</span>\n }\n </div>\n </div>\n \n @if (templateContents.length > 1 && config.allowEdit) {\n <button type=\"button\" \n (click)=\"deleteTemplateContent(i); $event.stopPropagation()\"\n class=\"btn-sm delete-btn\"\n style=\"background: none; border: none; color: #dc3545; padding: 4px; border-radius: 3px; transition: all 0.2s; cursor: pointer;\"\n onmouseover=\"this.style.backgroundColor='#dc3545'; this.style.color='white';\"\n onmouseout=\"this.style.backgroundColor='transparent'; this.style.color='#dc3545';\"\n title=\"Delete this content version\">\n <i class=\"fa-solid fa-trash fa-xs\"></i>\n </button>\n }\n </div>\n }\n \n @if (isAddingNewContent) {\n <div class=\"content-version-tab active\" \n style=\"padding: 8px 12px; border: 1px solid #28a745; border-radius: 6px; background: #d4edda; display: flex; align-items: center; gap: 6px;\">\n <i class=\"fa-solid fa-plus text-success\"></i>\n <span style=\"font-weight: 600; color: #155724; font-size: 0.85em;\">New</span>\n </div>\n }\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 style=\"padding: 8px 12px; border: 1px dashed #28a745; border-radius: 6px; background: #f8f9fa; display: flex; align-items: center; gap: 6px; cursor: pointer; transition: all 0.2s;\"\n onmouseover=\"this.style.backgroundColor='#e8f5e9'; this.style.borderStyle='solid';\"\n onmouseout=\"this.style.backgroundColor='#f8f9fa'; this.style.borderStyle='dashed';\"\n title=\"Add new template content\">\n <i class=\"fa-solid fa-plus\" style=\"color: #28a745; font-size: 0.75em;\"></i>\n <span style=\"font-weight: 500; color: #28a745; font-size: 0.85em;\">New</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Content Editor -->\n @if (currentTemplateContent) {\n <div class=\"content-editor-container\" style=\"flex: 1; display: flex; flex-direction: column; background: #fff; border: 1px solid #dee2e6; border-radius: 8px; overflow: hidden;\">\n \n <!-- Content Metadata Bar -->\n <div class=\"content-metadata-bar\" style=\"background: #f8f9fa; border-bottom: 1px solid #dee2e6; padding: 16px 20px;\">\n <div style=\"display: grid; grid-template-columns: 2fr 1fr 1fr auto; gap: 20px; align-items: end;\">\n \n <div class=\"form-group\" style=\"margin: 0;\">\n <label for=\"contentType\" class=\"form-label\" style=\"margin-bottom: 4px; font-size: 0.9em; font-weight: 600;\">\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\" style=\"font-size: 0.9em; padding: 4px 0;\">\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n </div>\n }\n </div>\n \n <div class=\"form-group\" style=\"margin: 0;\">\n <label for=\"priority\" class=\"form-label\" style=\"margin-bottom: 4px; font-size: 0.9em; font-weight: 600;\">\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\" style=\"font-size: 0.9em; padding: 4px 0;\">\n {{ currentTemplateContent.Priority || '-' }}\n </div>\n }\n </div>\n \n <div class=\"form-group\" style=\"margin: 0;\">\n <label class=\"form-label\" style=\"margin-bottom: 4px; font-size: 0.9em; font-weight: 600;\">\n <i class=\"fa-solid fa-toggle-on\"></i> Status\n </label>\n @if (config.allowEdit) {\n <div class=\"form-check\" style=\"margin-top: 8px;\">\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\" style=\"font-size: 0.9em;\">\n Active\n </label>\n </div>\n } @else {\n <div class=\"form-control-plaintext\" style=\"font-size: 0.9em; padding: 4px 0;\">\n @if (currentTemplateContent.IsActive) {\n <span class=\"badge badge-success\" style=\"background: #28a745; color: white; padding: 3px 8px; border-radius: 3px; font-size: 0.75em;\">\n <i class=\"fa-solid fa-check-circle\"></i> Active\n </span>\n } @else {\n <span class=\"badge badge-secondary\" style=\"background: #6c757d; color: white; padding: 3px 8px; border-radius: 3px; font-size: 0.75em;\">\n <i class=\"fa-solid fa-pause-circle\"></i> Inactive\n </span>\n }\n </div>\n }\n </div>\n\n </div>\n </div>\n \n <!-- Content Text Editor -->\n <div class=\"content-text-editor\" style=\"flex: 1; padding: 20px; display: flex; flex-direction: column;\">\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;\">\n <label for=\"templateContent\" class=\"form-label\" style=\"margin: 0; font-weight: 600; display: flex; align-items: center; gap: 8px;\">\n <i class=\"fa-solid fa-code\"></i> Template Content\n <span class=\"badge\" style=\"padding: 4px 8px; border-radius: 4px; font-size: 0.75em;\"\n [style.background]=\"!currentTemplateContent.ID ? '#28a745' : '#6c757d'\"\n [style.color]=\"'white'\">\n @if (!currentTemplateContent.ID) {\n New\n } @else {\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n }\n </span>\n </label>\n \n <div style=\"display: flex; align-items: center; gap: 12px;\">\n @if (!isAddingNewContent && hasUnsavedChanges) {\n <span class=\"unsaved-indicator\" style=\"color: #fd7e14; font-size: 0.85em; display: flex; align-items: center; gap: 4px;\">\n <i class=\"fa-solid fa-circle\" style=\"font-size: 0.5em;\"></i>\n Unsaved changes\n </span>\n }\n \n @if (template.IsSaved && currentTemplateContent && config.showRunButton) {\n <button type=\"button\" \n class=\"btn btn-sm\"\n [disabled]=\"isRunningTemplate\"\n (click)=\"onRunTemplate()\"\n style=\"background: #17a2b8; color: white; border: none; padding: 6px 12px; border-radius: 4px; font-size: 0.85em; display: flex; align-items: center; gap: 6px; transition: all 0.2s;\"\n onmouseover=\"this.style.background='#138496'\"\n onmouseout=\"this.style.background='#17a2b8'\"\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 \n <mj-code-editor \n #codeEditor\n (change)=\"onTemplateTextChange($event)\"\n [readonly]=\"!config.allowEdit\"\n [language]=\"getEditorLanguage()\"\n [languages]=\"supportedLanguages\"\n style=\"flex: 1; height: 350px; border: 1px solid #ced4da; border-radius: 4px;\">\n </mj-code-editor>\n \n <!-- Template Syntax Help -->\n @if (!config.compactMode) {\n <div class=\"syntax-help\" style=\"margin-top: 16px; padding: 12px; background: #e8f5e8; border-left: 4px solid #28a745; border-radius: 4px; font-size: 0.85em;\">\n <div style=\"font-weight: 600; margin-bottom: 8px; color: #155724;\">\n <i class=\"fa-solid fa-lightbulb\"></i> Template Syntax Quick Reference:\n </div>\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 12px;\">\n <div>\n <strong>Parameters:</strong> <code style=\"background: #fff; padding: 2px 4px; border-radius: 3px;\">{{'{{'}} paramName {{'}}'}}</code><br>\n <strong>Includes:</strong> <code style=\"background: #fff; padding: 2px 4px; border-radius: 3px;\">{{'{% template \"TemplateName\" %}'}}</code>\n </div>\n <div>\n <strong>Conditionals:</strong> <code style=\"background: #fff; padding: 2px 4px; border-radius: 3px;\">{{'{% if condition %}'}}</code><br>\n <strong>Loops:</strong> <code style=\"background: #fff; padding: 2px 4px; border-radius: 3px;\">{{'{% for item in items %}'}}</code>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- No Content State -->\n <div class=\"no-content-state\" style=\"flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; background: #f8f9fa; border: 2px dashed #dee2e6; border-radius: 8px; padding: 40px; text-align: center;\">\n <i class=\"fa-solid fa-file-plus\" style=\"font-size: 48px; margin-bottom: 16px; color: #6c757d; opacity: 0.6;\"></i>\n <h5 style=\"color: #495057; margin-bottom: 8px;\">No Template Content</h5>\n <p style=\"color: #6c757d; margin-bottom: 20px;\">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>", 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: #f8f9fa !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 rgba(0,0,0,0.1);\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}"] }]
657
- }], null, { template: [{
842
+ args: [{ selector: 'mj-template-editor', template: "<div class=\"template-editor\" *ngIf=\"template\" style=\"height: 100%; display: flex; flex-direction: column;\">\n\n <!-- Content Versions List/Tabs -->\n @if (templateContents.length > 0) {\n <div class=\"content-versions-tabs\" style=\"margin-bottom: 16px; border-bottom: 2px solid #e0e0e0; padding-bottom: 8px;\">\n <div class=\"content-tabs\" style=\"display: flex; gap: 6px; flex-wrap: wrap;\">\n \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 style=\"padding: 8px 12px; border: 1px solid #ccc; border-radius: 6px; cursor: pointer; background: #fff; display: flex; align-items: center; gap: 6px; transition: all 0.2s; position: relative;\"\n [style.border-color]=\"selectedContentIndex === i && !isAddingNewContent ? '#007bff' : '#ccc'\"\n [style.background]=\"selectedContentIndex === i && !isAddingNewContent ? '#e3f2fd' : '#fff'\">\n \n <div style=\"flex: 1;\">\n <div style=\"font-weight: 600; font-size: 0.85em; color: #495057;\">\n {{ content.Type || 'Version ' + (i + 1) }}\n </div>\n <div style=\"font-size: 0.7em; color: #6c757d;\">\n P:{{ content.Priority }}\n @if (!content.IsActive) {\n \u2022 <span style=\"color: #dc3545;\">Inactive</span>\n }\n </div>\n </div>\n \n @if (templateContents.length > 1 && config.allowEdit) {\n <button type=\"button\" \n (click)=\"deleteTemplateContent(i); $event.stopPropagation()\"\n class=\"btn-sm delete-btn\"\n style=\"background: none; border: none; color: #dc3545; padding: 4px; border-radius: 3px; transition: all 0.2s; cursor: pointer;\"\n onmouseover=\"this.style.backgroundColor='#dc3545'; this.style.color='white';\"\n onmouseout=\"this.style.backgroundColor='transparent'; this.style.color='#dc3545';\"\n title=\"Delete this content version\">\n <i class=\"fa-solid fa-trash fa-xs\"></i>\n </button>\n }\n </div>\n }\n \n @if (isAddingNewContent) {\n <div class=\"content-version-tab active\" \n style=\"padding: 8px 12px; border: 1px solid #28a745; border-radius: 6px; background: #d4edda; display: flex; align-items: center; gap: 6px;\">\n <i class=\"fa-solid fa-plus text-success\"></i>\n <span style=\"font-weight: 600; color: #155724; font-size: 0.85em;\">New</span>\n </div>\n }\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 style=\"padding: 8px 12px; border: 1px dashed #28a745; border-radius: 6px; background: #f8f9fa; display: flex; align-items: center; gap: 6px; cursor: pointer; transition: all 0.2s;\"\n onmouseover=\"this.style.backgroundColor='#e8f5e9'; this.style.borderStyle='solid';\"\n onmouseout=\"this.style.backgroundColor='#f8f9fa'; this.style.borderStyle='dashed';\"\n title=\"Add new template content\">\n <i class=\"fa-solid fa-plus\" style=\"color: #28a745; font-size: 0.75em;\"></i>\n <span style=\"font-weight: 500; color: #28a745; font-size: 0.85em;\">New</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Content Editor -->\n @if (currentTemplateContent) {\n <div class=\"content-editor-container\" style=\"flex: 1; display: flex; flex-direction: column; background: #fff; border: 1px solid #dee2e6; border-radius: 8px; overflow: hidden;\">\n \n <!-- Content Metadata Bar -->\n <div class=\"content-metadata-bar\" style=\"background: #f8f9fa; border-bottom: 1px solid #dee2e6; padding: 16px 20px;\">\n <div style=\"display: grid; grid-template-columns: 2fr 1fr 1fr auto; gap: 20px; align-items: end;\">\n \n <div class=\"form-group\" style=\"margin: 0;\">\n <label for=\"contentType\" class=\"form-label\" style=\"margin-bottom: 4px; font-size: 0.9em; font-weight: 600;\">\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\" style=\"font-size: 0.9em; padding: 4px 0;\">\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n </div>\n }\n </div>\n \n <div class=\"form-group\" style=\"margin: 0;\">\n <label for=\"priority\" class=\"form-label\" style=\"margin-bottom: 4px; font-size: 0.9em; font-weight: 600;\">\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\" style=\"font-size: 0.9em; padding: 4px 0;\">\n {{ currentTemplateContent.Priority || '-' }}\n </div>\n }\n </div>\n \n <div class=\"form-group\" style=\"margin: 0;\">\n <label class=\"form-label\" style=\"margin-bottom: 4px; font-size: 0.9em; font-weight: 600;\">\n <i class=\"fa-solid fa-toggle-on\"></i> Status\n </label>\n @if (config.allowEdit) {\n <div class=\"form-check\" style=\"margin-top: 8px;\">\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\" style=\"font-size: 0.9em;\">\n Active\n </label>\n </div>\n } @else {\n <div class=\"form-control-plaintext\" style=\"font-size: 0.9em; padding: 4px 0;\">\n @if (currentTemplateContent.IsActive) {\n <span class=\"badge badge-success\" style=\"background: #28a745; color: white; padding: 3px 8px; border-radius: 3px; font-size: 0.75em;\">\n <i class=\"fa-solid fa-check-circle\"></i> Active\n </span>\n } @else {\n <span class=\"badge badge-secondary\" style=\"background: #6c757d; color: white; padding: 3px 8px; border-radius: 3px; font-size: 0.75em;\">\n <i class=\"fa-solid fa-pause-circle\"></i> Inactive\n </span>\n }\n </div>\n }\n </div>\n\n </div>\n </div>\n \n <!-- Content Text Editor -->\n <div class=\"content-text-editor\" style=\"flex: 1; padding: 20px; display: flex; flex-direction: column;\">\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;\">\n <label for=\"templateContent\" class=\"form-label\" style=\"margin: 0; font-weight: 600; display: flex; align-items: center; gap: 8px;\">\n <i class=\"fa-solid fa-code\"></i> Template Content\n <span class=\"badge\" style=\"padding: 4px 8px; border-radius: 4px; font-size: 0.75em;\"\n [style.background]=\"!currentTemplateContent.ID ? '#28a745' : '#6c757d'\"\n [style.color]=\"'white'\">\n @if (!currentTemplateContent.ID) {\n New\n } @else {\n {{ getContentTypeDisplayText(currentTemplateContent.TypeID) }}\n }\n </span>\n </label>\n \n <div style=\"display: flex; align-items: center; gap: 12px;\">\n @if (!isAddingNewContent && hasUnsavedChanges) {\n <span class=\"unsaved-indicator\" style=\"color: #fd7e14; font-size: 0.85em; display: flex; align-items: center; gap: 4px;\">\n <i class=\"fa-solid fa-circle\" style=\"font-size: 0.5em;\"></i>\n Unsaved changes\n </span>\n }\n \n @if (template.IsSaved && currentTemplateContent && config.showRunButton) {\n <button type=\"button\" \n class=\"btn btn-sm\"\n [disabled]=\"isRunningTemplate\"\n (click)=\"onRunTemplate()\"\n style=\"background: #17a2b8; color: white; border: none; padding: 6px 12px; border-radius: 4px; font-size: 0.85em; display: flex; align-items: center; gap: 6px; transition: all 0.2s;\"\n onmouseover=\"this.style.background='#138496'\"\n onmouseout=\"this.style.background='#17a2b8'\"\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 \n <mj-code-editor \n #codeEditor\n (change)=\"onTemplateTextChange($event)\"\n [readonly]=\"!config.allowEdit\"\n [language]=\"getEditorLanguage()\"\n [languages]=\"supportedLanguages\"\n style=\"flex: 1; height: 350px; border: 1px solid #ced4da; border-radius: 4px;\">\n </mj-code-editor>\n \n <!-- Template Help Section with Tabs -->\n @if (!config.compactMode) {\n <div class=\"template-help-section\" style=\"margin-top: 16px;\">\n <!-- Tab Navigation -->\n <div class=\"help-tabs\" style=\"display: flex; border-bottom: 2px solid #dee2e6; margin-bottom: 0;\">\n <button type=\"button\" \n class=\"help-tab\" \n [class.active]=\"activeHelpTab === 'syntax'\"\n (click)=\"activeHelpTab = 'syntax'\"\n style=\"padding: 8px 16px; border: none; background: none; cursor: pointer; font-size: 0.9em; font-weight: 600; color: #6c757d; border-bottom: 3px solid transparent; transition: all 0.2s;\"\n [style.color]=\"activeHelpTab === 'syntax' ? '#28a745' : '#6c757d'\"\n [style.border-bottom-color]=\"activeHelpTab === 'syntax' ? '#28a745' : 'transparent'\">\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 style=\"padding: 8px 16px; border: none; background: none; cursor: pointer; font-size: 0.9em; font-weight: 600; color: #6c757d; border-bottom: 3px solid transparent; transition: all 0.2s;\"\n [style.color]=\"activeHelpTab === 'placeholders' ? '#28a745' : '#6c757d'\"\n [style.border-bottom-color]=\"activeHelpTab === 'placeholders' ? '#28a745' : 'transparent'\">\n <i class=\"fa-solid fa-at\"></i> System Placeholders\n </button>\n </div>\n \n <!-- Tab Content -->\n <div class=\"help-content\" style=\"padding: 16px; background: #f8f9fa; border: 1px solid #dee2e6; border-top: none; border-radius: 0 0 4px 4px;\">\n <!-- Template Syntax Tab -->\n @if (activeHelpTab === 'syntax') {\n <div class=\"syntax-help\" style=\"font-size: 0.85em;\">\n <div style=\"font-weight: 600; margin-bottom: 12px; color: #155724;\">\n <i class=\"fa-solid fa-lightbulb\"></i> Template Syntax Quick Reference\n </div>\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 16px;\">\n <div>\n <div style=\"margin-bottom: 8px;\">\n <strong>Parameters:</strong><br>\n <code style=\"background: #fff; padding: 4px 6px; border-radius: 3px; display: inline-block; margin-top: 4px;\">{{'{{'}} paramName {{'}}'}}</code>\n </div>\n <div>\n <strong>Template Includes:</strong><br>\n <code style=\"background: #fff; padding: 4px 6px; border-radius: 3px; display: inline-block; margin-top: 4px;\">{{'{% template \"TemplateName\" %}'}}</code>\n </div>\n </div>\n <div>\n <div style=\"margin-bottom: 8px;\">\n <strong>Conditionals:</strong><br>\n <code style=\"background: #fff; padding: 4px 6px; border-radius: 3px; display: inline-block; margin-top: 4px;\">{{'{% if condition %}'}} ... {{'{% endif %}'}}</code>\n </div>\n <div>\n <strong>Loops:</strong><br>\n <code style=\"background: #fff; padding: 4px 6px; border-radius: 3px; display: inline-block; margin-top: 4px;\">{{'{% for item in items %}'}} ... {{'{% endfor %}'}}</code>\n </div>\n </div>\n </div>\n </div>\n }\n \n <!-- System Placeholders Tab -->\n @if (activeHelpTab === 'placeholders') {\n <div class=\"placeholders-help\" style=\"font-size: 0.85em;\">\n <div style=\"font-weight: 600; margin-bottom: 12px; color: #155724;\">\n <i class=\"fa-solid fa-at\"></i> System Placeholders Reference\n </div>\n <p style=\"margin-bottom: 16px; color: #495057; line-height: 1.5;\">\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 \n <!-- Category Sub-tabs -->\n <div class=\"category-tabs\" style=\"display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap;\">\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 style=\"padding: 6px 14px; border: 1px solid #dee2e6; background: white; border-radius: 20px; cursor: pointer; font-size: 0.85em; font-weight: 500; display: flex; align-items: center; gap: 6px; transition: all 0.2s; position: relative;\"\n [style.border-color]=\"activePlaceholderCategory === categoryGroup.category.name ? categoryGroup.category.color : '#dee2e6'\"\n [style.background]=\"activePlaceholderCategory === categoryGroup.category.name ? categoryGroup.category.color + '10' : 'white'\"\n [style.color]=\"activePlaceholderCategory === categoryGroup.category.name ? categoryGroup.category.color : '#6c757d'\">\n <i [class]=\"'fa-solid ' + categoryGroup.category.icon\" style=\"font-size: 0.9em;\"></i>\n {{ categoryGroup.category.name }}\n <span class=\"badge\" \n style=\"background: rgba(0,0,0,0.1); color: inherit; padding: 2px 6px; border-radius: 10px; font-size: 0.75em; margin-left: 4px;\">\n {{ categoryGroup.placeholders.length }}\n </span>\n </button>\n }\n </div>\n \n <!-- Active Category Content -->\n <div class=\"placeholder-content\" style=\"background: white; border: 1px solid #dee2e6; border-radius: 8px; padding: 16px;\">\n @for (categoryGroup of placeholderCategories; track categoryGroup.category.name) {\n @if (activePlaceholderCategory === categoryGroup.category.name) {\n <div class=\"category-header\" style=\"display: flex; align-items: center; gap: 8px; margin-bottom: 16px;\">\n <i [class]=\"'fa-solid ' + categoryGroup.category.icon\" \n [style.color]=\"categoryGroup.category.color\" \n style=\"font-size: 1.2em;\"></i>\n <h5 style=\"margin: 0; color: #343a40; font-weight: 600;\">{{ categoryGroup.category.name }}</h5>\n </div>\n \n <div style=\"display: grid; gap: 10px;\">\n @for (placeholder of categoryGroup.placeholders; track placeholder.name) {\n <div class=\"placeholder-item\" \n style=\"padding: 12px 16px; background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 6px; position: relative; transition: all 0.2s; max-width: 800px;\"\n onmouseover=\"this.style.borderColor='#007bff'; this.style.background='#f0f8ff'; this.querySelector('.copy-btn').style.opacity='1';\"\n onmouseout=\"this.style.borderColor='#e9ecef'; this.style.background='#f8f9fa'; this.querySelector('.copy-btn').style.opacity='0';\">\n <div style=\"display: flex; align-items: flex-start; gap: 8px;\">\n <div>\n <div style=\"display: inline-flex; align-items: center; gap: 8px;\">\n <code style=\"color: #e83e8c; font-weight: 600; font-size: 0.95em;\">{{'{{'}} {{ placeholder.name }} {{'}}'}}</code>\n <button type=\"button\"\n class=\"copy-btn\"\n (click)=\"copyPlaceholder(placeholder.name)\"\n style=\"opacity: 0; transition: opacity 0.2s; background: none; border: none; padding: 4px 8px; cursor: pointer; color: #007bff; border-radius: 4px; display: inline-flex; align-items: center;\"\n onmouseover=\"this.style.background='#e7f3ff';\"\n onmouseout=\"this.style.background='none';\"\n title=\"Copy placeholder to clipboard\">\n <i class=\"fa-solid fa-copy\" style=\"font-size: 0.85em;\"></i>\n </button>\n </div>\n @if (placeholder.description) {\n <div style=\"color: #6c757d; margin-top: 4px; line-height: 1.4;\">{{ placeholder.description }}</div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n \n <!-- Usage Example -->\n <div style=\"margin-top: 20px; padding: 12px; background: #e3f2fd; border-radius: 6px; border: 1px solid #bbdefb;\">\n <div style=\"display: flex; align-items: flex-start; gap: 8px;\">\n <i class=\"fa-solid fa-info-circle\" style=\"color: #1976d2; margin-top: 2px;\"></i>\n <div style=\"flex: 1; font-size: 0.85em; color: #1565c0; line-height: 1.5;\">\n <strong>Usage Example:</strong> To use a system placeholder in your template, simply include it in double curly braces. \n For example: <code style=\"background: white; padding: 2px 4px; border-radius: 3px;\">\"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\" style=\"flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; background: #f8f9fa; border: 2px dashed #dee2e6; border-radius: 8px; padding: 40px; text-align: center;\">\n <i class=\"fa-solid fa-file-plus\" style=\"font-size: 48px; margin-bottom: 16px; color: #6c757d; opacity: 0.6;\"></i>\n <h5 style=\"color: #495057; margin-bottom: 8px;\">No Template Content</h5>\n <p style=\"color: #6c757d; margin-bottom: 20px;\">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>", 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: #f8f9fa !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 rgba(0,0,0,0.1);\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}"] }]
843
+ }], () => [{ type: i1.MJNotificationService }], { template: [{
658
844
  type: Input
659
845
  }], config: [{
660
846
  type: Input
@@ -666,5 +852,5 @@ export class TemplateEditorComponent {
666
852
  type: ViewChild,
667
853
  args: ['codeEditor']
668
854
  }] }); })();
669
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TemplateEditorComponent, { className: "TemplateEditorComponent", filePath: "src/lib/shared/components/template-editor.component.ts", lineNumber: 22 }); })();
855
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TemplateEditorComponent, { className: "TemplateEditorComponent", filePath: "src/lib/shared/components/template-editor.component.ts", lineNumber: 23 }); })();
670
856
  //# sourceMappingURL=template-editor.component.js.map