@memberjunction/ng-core-entity-forms 6.2.0-edge.5 → 6.2.0-edge.7

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.
Files changed (228) hide show
  1. package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.d.ts +2 -0
  2. package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.d.ts.map +1 -1
  3. package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js +103 -95
  4. package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js.map +1 -1
  5. package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts +6 -0
  6. package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
  7. package/dist/lib/custom/AIAgents/ai-agent-form.component.js +7 -1
  8. package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
  9. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts +2 -0
  10. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
  11. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +4 -2
  12. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
  13. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts +2 -0
  14. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts.map +1 -1
  15. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +21 -1
  16. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
  17. package/dist/lib/custom/Actions/action-form.component.d.ts +2 -0
  18. package/dist/lib/custom/Actions/action-form.component.d.ts.map +1 -1
  19. package/dist/lib/custom/Actions/action-form.component.js +29 -11
  20. package/dist/lib/custom/Actions/action-form.component.js.map +1 -1
  21. package/dist/lib/custom/Conversations/conversation-overview.panel.js +1 -1
  22. package/dist/lib/custom/Conversations/conversation-overview.panel.js.map +1 -1
  23. package/dist/lib/custom/Entities/entity-form.component.js +3 -3
  24. package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
  25. package/dist/lib/custom/EntityActions/entityaction.form.component.d.ts +2 -0
  26. package/dist/lib/custom/EntityActions/entityaction.form.component.d.ts.map +1 -1
  27. package/dist/lib/custom/EntityActions/entityaction.form.component.js +2 -0
  28. package/dist/lib/custom/EntityActions/entityaction.form.component.js.map +1 -1
  29. package/dist/lib/custom/Files/file-form.component.d.ts +8 -0
  30. package/dist/lib/custom/Files/file-form.component.d.ts.map +1 -1
  31. package/dist/lib/custom/Files/file-form.component.js +21 -5
  32. package/dist/lib/custom/Files/file-form.component.js.map +1 -1
  33. package/dist/lib/custom/Files/file-form.logic.d.ts +7 -0
  34. package/dist/lib/custom/Files/file-form.logic.d.ts.map +1 -1
  35. package/dist/lib/custom/Files/file-form.logic.js +20 -0
  36. package/dist/lib/custom/Files/file-form.logic.js.map +1 -1
  37. package/dist/lib/custom/Lists/list-form.component.js +5 -5
  38. package/dist/lib/custom/Lists/list-form.component.js.map +1 -1
  39. package/dist/lib/custom/MLModels/ml-model-view-models.d.ts +11 -4
  40. package/dist/lib/custom/MLModels/ml-model-view-models.d.ts.map +1 -1
  41. package/dist/lib/custom/MLModels/ml-model-view-models.js +14 -0
  42. package/dist/lib/custom/MLModels/ml-model-view-models.js.map +1 -1
  43. package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts +15 -0
  44. package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts.map +1 -1
  45. package/dist/lib/custom/MLModels/ps-model-detail.component.js +186 -92
  46. package/dist/lib/custom/MLModels/ps-model-detail.component.js.map +1 -1
  47. package/dist/lib/custom/Queries/query-child-labels.d.ts +12 -0
  48. package/dist/lib/custom/Queries/query-child-labels.d.ts.map +1 -0
  49. package/dist/lib/custom/Queries/query-child-labels.js +28 -0
  50. package/dist/lib/custom/Queries/query-child-labels.js.map +1 -0
  51. package/dist/lib/custom/Queries/query-fields-grid.component.d.ts +37 -0
  52. package/dist/lib/custom/Queries/query-fields-grid.component.d.ts.map +1 -0
  53. package/dist/lib/custom/Queries/query-fields-grid.component.js +321 -0
  54. package/dist/lib/custom/Queries/query-fields-grid.component.js.map +1 -0
  55. package/dist/lib/custom/Queries/query-form-logic.d.ts +37 -0
  56. package/dist/lib/custom/Queries/query-form-logic.d.ts.map +1 -0
  57. package/dist/lib/custom/Queries/query-form-logic.js +48 -0
  58. package/dist/lib/custom/Queries/query-form-logic.js.map +1 -0
  59. package/dist/lib/custom/Queries/query-form.component.d.ts +78 -7
  60. package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
  61. package/dist/lib/custom/Queries/query-form.component.js +742 -688
  62. package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
  63. package/dist/lib/custom/Queries/query-parameters-grid.component.d.ts +31 -0
  64. package/dist/lib/custom/Queries/query-parameters-grid.component.d.ts.map +1 -0
  65. package/dist/lib/custom/Queries/query-parameters-grid.component.js +298 -0
  66. package/dist/lib/custom/Queries/query-parameters-grid.component.js.map +1 -0
  67. package/dist/lib/custom/Rubrics/record-forms.component.js +2 -2
  68. package/dist/lib/custom/Rubrics/record-forms.component.js.map +1 -1
  69. package/dist/lib/custom/Rubrics/scale-form.component.d.ts.map +1 -1
  70. package/dist/lib/custom/Rubrics/scale-form.component.js +2 -1
  71. package/dist/lib/custom/Rubrics/scale-form.component.js.map +1 -1
  72. package/dist/lib/custom/SearchScopes/searchscope-form.component.js +1 -1
  73. package/dist/lib/custom/SearchScopes/searchscope-form.component.js.map +1 -1
  74. package/dist/lib/custom/Templates/templates-form.component.d.ts +19 -1
  75. package/dist/lib/custom/Templates/templates-form.component.d.ts.map +1 -1
  76. package/dist/lib/custom/Templates/templates-form.component.js +20 -27
  77. package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
  78. package/dist/lib/custom/Tests/entity-link-pill.component.d.ts.map +1 -1
  79. package/dist/lib/custom/Tests/entity-link-pill.component.js +14 -6
  80. package/dist/lib/custom/Tests/entity-link-pill.component.js.map +1 -1
  81. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
  82. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +121 -111
  83. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
  84. package/dist/lib/custom/custom-forms.module.d.ts +41 -35
  85. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
  86. package/dist/lib/custom/custom-forms.module.js +32 -3
  87. package/dist/lib/custom/custom-forms.module.js.map +1 -1
  88. package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.d.ts.map +1 -1
  89. package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js +234 -226
  90. package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js.map +1 -1
  91. package/dist/lib/generated/Entities/MJAIAgentConfiguration/mjaiagentconfiguration.form.component.d.ts.map +1 -1
  92. package/dist/lib/generated/Entities/MJAIAgentConfiguration/mjaiagentconfiguration.form.component.js +25 -6
  93. package/dist/lib/generated/Entities/MJAIAgentConfiguration/mjaiagentconfiguration.form.component.js.map +1 -1
  94. package/dist/lib/generated/Entities/MJAIAgentRelationship/mjaiagentrelationship.form.component.d.ts.map +1 -1
  95. package/dist/lib/generated/Entities/MJAIAgentRelationship/mjaiagentrelationship.form.component.js +13 -3
  96. package/dist/lib/generated/Entities/MJAIAgentRelationship/mjaiagentrelationship.form.component.js.map +1 -1
  97. package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js +105 -103
  98. package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js.map +1 -1
  99. package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.js +2 -2
  100. package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.js.map +1 -1
  101. package/dist/lib/generated/Entities/MJBrandKit/mjbrandkit.form.component.d.ts +10 -0
  102. package/dist/lib/generated/Entities/MJBrandKit/mjbrandkit.form.component.d.ts.map +1 -0
  103. package/dist/lib/generated/Entities/MJBrandKit/mjbrandkit.form.component.js +91 -0
  104. package/dist/lib/generated/Entities/MJBrandKit/mjbrandkit.form.component.js.map +1 -0
  105. package/dist/lib/generated/Entities/MJBrandKitAsset/mjbrandkitasset.form.component.d.ts +10 -0
  106. package/dist/lib/generated/Entities/MJBrandKitAsset/mjbrandkitasset.form.component.d.ts.map +1 -0
  107. package/dist/lib/generated/Entities/MJBrandKitAsset/mjbrandkitasset.form.component.js +72 -0
  108. package/dist/lib/generated/Entities/MJBrandKitAsset/mjbrandkitasset.form.component.js.map +1 -0
  109. package/dist/lib/generated/Entities/MJCalendarEventLink/mjcalendareventlink.form.component.d.ts +10 -0
  110. package/dist/lib/generated/Entities/MJCalendarEventLink/mjcalendareventlink.form.component.d.ts.map +1 -0
  111. package/dist/lib/generated/Entities/MJCalendarEventLink/mjcalendareventlink.form.component.js +74 -0
  112. package/dist/lib/generated/Entities/MJCalendarEventLink/mjcalendareventlink.form.component.js.map +1 -0
  113. package/dist/lib/generated/Entities/MJCalendarSyncState/mjcalendarsyncstate.form.component.d.ts +10 -0
  114. package/dist/lib/generated/Entities/MJCalendarSyncState/mjcalendarsyncstate.form.component.d.ts.map +1 -0
  115. package/dist/lib/generated/Entities/MJCalendarSyncState/mjcalendarsyncstate.form.component.js +64 -0
  116. package/dist/lib/generated/Entities/MJCalendarSyncState/mjcalendarsyncstate.form.component.js.map +1 -0
  117. package/dist/lib/generated/Entities/MJCommunicationProvider/mjcommunicationprovider.form.component.d.ts.map +1 -1
  118. package/dist/lib/generated/Entities/MJCommunicationProvider/mjcommunicationprovider.form.component.js +62 -16
  119. package/dist/lib/generated/Entities/MJCommunicationProvider/mjcommunicationprovider.form.component.js.map +1 -1
  120. package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.d.ts.map +1 -1
  121. package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.js +46 -10
  122. package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.js.map +1 -1
  123. package/dist/lib/generated/Entities/MJCompanyIntegration/mjcompanyintegration.form.component.d.ts.map +1 -1
  124. package/dist/lib/generated/Entities/MJCompanyIntegration/mjcompanyintegration.form.component.js +28 -10
  125. package/dist/lib/generated/Entities/MJCompanyIntegration/mjcompanyintegration.form.component.js.map +1 -1
  126. package/dist/lib/generated/Entities/MJCompanyIntegrationObject/mjcompanyintegrationobject.form.component.d.ts +10 -0
  127. package/dist/lib/generated/Entities/MJCompanyIntegrationObject/mjcompanyintegrationobject.form.component.d.ts.map +1 -0
  128. package/dist/lib/generated/Entities/MJCompanyIntegrationObject/mjcompanyintegrationobject.form.component.js +189 -0
  129. package/dist/lib/generated/Entities/MJCompanyIntegrationObject/mjcompanyintegrationobject.form.component.js.map +1 -0
  130. package/dist/lib/generated/Entities/MJCompanyIntegrationObjectField/mjcompanyintegrationobjectfield.form.component.d.ts +10 -0
  131. package/dist/lib/generated/Entities/MJCompanyIntegrationObjectField/mjcompanyintegrationobjectfield.form.component.d.ts.map +1 -0
  132. package/dist/lib/generated/Entities/MJCompanyIntegrationObjectField/mjcompanyintegrationobjectfield.form.component.js +116 -0
  133. package/dist/lib/generated/Entities/MJCompanyIntegrationObjectField/mjcompanyintegrationobjectfield.form.component.js.map +1 -0
  134. package/dist/lib/generated/Entities/MJComponent/mjcomponent.form.component.d.ts.map +1 -1
  135. package/dist/lib/generated/Entities/MJComponent/mjcomponent.form.component.js +51 -35
  136. package/dist/lib/generated/Entities/MJComponent/mjcomponent.form.component.js.map +1 -1
  137. package/dist/lib/generated/Entities/MJContentFileType/mjcontentfiletype.form.component.d.ts.map +1 -1
  138. package/dist/lib/generated/Entities/MJContentFileType/mjcontentfiletype.form.component.js +36 -18
  139. package/dist/lib/generated/Entities/MJContentFileType/mjcontentfiletype.form.component.js.map +1 -1
  140. package/dist/lib/generated/Entities/MJContentItem/mjcontentitem.form.component.d.ts.map +1 -1
  141. package/dist/lib/generated/Entities/MJContentItem/mjcontentitem.form.component.js +74 -60
  142. package/dist/lib/generated/Entities/MJContentItem/mjcontentitem.form.component.js.map +1 -1
  143. package/dist/lib/generated/Entities/MJContentItemChunk/mjcontentitemchunk.form.component.d.ts.map +1 -1
  144. package/dist/lib/generated/Entities/MJContentItemChunk/mjcontentitemchunk.form.component.js +30 -32
  145. package/dist/lib/generated/Entities/MJContentItemChunk/mjcontentitemchunk.form.component.js.map +1 -1
  146. package/dist/lib/generated/Entities/MJContentSource/mjcontentsource.form.component.js +43 -35
  147. package/dist/lib/generated/Entities/MJContentSource/mjcontentsource.form.component.js.map +1 -1
  148. package/dist/lib/generated/Entities/MJContentType/mjcontenttype.form.component.js +21 -19
  149. package/dist/lib/generated/Entities/MJContentType/mjcontenttype.form.component.js.map +1 -1
  150. package/dist/lib/generated/Entities/MJDashboard/mjdashboard.form.component.d.ts.map +1 -1
  151. package/dist/lib/generated/Entities/MJDashboard/mjdashboard.form.component.js +45 -29
  152. package/dist/lib/generated/Entities/MJDashboard/mjdashboard.form.component.js.map +1 -1
  153. package/dist/lib/generated/Entities/MJDuplicateRun/mjduplicaterun.form.component.js +19 -17
  154. package/dist/lib/generated/Entities/MJDuplicateRun/mjduplicaterun.form.component.js.map +1 -1
  155. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
  156. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +485 -441
  157. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
  158. package/dist/lib/generated/Entities/MJEntityAlternateBaseView/mjentityalternatebaseview.form.component.d.ts +10 -0
  159. package/dist/lib/generated/Entities/MJEntityAlternateBaseView/mjentityalternatebaseview.form.component.d.ts.map +1 -0
  160. package/dist/lib/generated/Entities/MJEntityAlternateBaseView/mjentityalternatebaseview.form.component.js +129 -0
  161. package/dist/lib/generated/Entities/MJEntityAlternateBaseView/mjentityalternatebaseview.form.component.js.map +1 -0
  162. package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.d.ts.map +1 -1
  163. package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.js +27 -9
  164. package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.js.map +1 -1
  165. package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.d.ts.map +1 -1
  166. package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js +24 -6
  167. package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js.map +1 -1
  168. package/dist/lib/generated/Entities/MJFile/mjfile.form.component.d.ts.map +1 -1
  169. package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js +48 -12
  170. package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js.map +1 -1
  171. package/dist/lib/generated/Entities/MJIntegration/mjintegration.form.component.d.ts.map +1 -1
  172. package/dist/lib/generated/Entities/MJIntegration/mjintegration.form.component.js +26 -8
  173. package/dist/lib/generated/Entities/MJIntegration/mjintegration.form.component.js.map +1 -1
  174. package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.d.ts.map +1 -1
  175. package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.js +24 -6
  176. package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.js.map +1 -1
  177. package/dist/lib/generated/Entities/MJIntegrationObjectField/mjintegrationobjectfield.form.component.d.ts.map +1 -1
  178. package/dist/lib/generated/Entities/MJIntegrationObjectField/mjintegrationobjectfield.form.component.js +25 -6
  179. package/dist/lib/generated/Entities/MJIntegrationObjectField/mjintegrationobjectfield.form.component.js.map +1 -1
  180. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.d.ts.map +1 -1
  181. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js +77 -57
  182. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js.map +1 -1
  183. package/dist/lib/generated/Entities/MJQueryEntity/mjqueryentity.form.component.js +10 -8
  184. package/dist/lib/generated/Entities/MJQueryEntity/mjqueryentity.form.component.js.map +1 -1
  185. package/dist/lib/generated/Entities/MJQueryField/mjqueryfield.form.component.d.ts.map +1 -1
  186. package/dist/lib/generated/Entities/MJQueryField/mjqueryfield.form.component.js +15 -3
  187. package/dist/lib/generated/Entities/MJQueryField/mjqueryfield.form.component.js.map +1 -1
  188. package/dist/lib/generated/Entities/MJQueryParameter/mjqueryparameter.form.component.d.ts.map +1 -1
  189. package/dist/lib/generated/Entities/MJQueryParameter/mjqueryparameter.form.component.js +12 -4
  190. package/dist/lib/generated/Entities/MJQueryParameter/mjqueryparameter.form.component.js.map +1 -1
  191. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.d.ts.map +1 -1
  192. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +209 -137
  193. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
  194. package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.js +50 -38
  195. package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.js.map +1 -1
  196. package/dist/lib/generated/Entities/MJVideoArchetype/mjvideoarchetype.form.component.d.ts +10 -0
  197. package/dist/lib/generated/Entities/MJVideoArchetype/mjvideoarchetype.form.component.d.ts.map +1 -0
  198. package/dist/lib/generated/Entities/MJVideoArchetype/mjvideoarchetype.form.component.js +80 -0
  199. package/dist/lib/generated/Entities/MJVideoArchetype/mjvideoarchetype.form.component.js.map +1 -0
  200. package/dist/lib/generated/generated-forms.module.d.ts +449 -441
  201. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  202. package/dist/lib/generated/generated-forms.module.js +26 -2
  203. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  204. package/dist/lib/panels/brand-kits/brand-kit-assets.panel.d.ts +15 -0
  205. package/dist/lib/panels/brand-kits/brand-kit-assets.panel.d.ts.map +1 -0
  206. package/dist/lib/panels/brand-kits/brand-kit-assets.panel.js +52 -0
  207. package/dist/lib/panels/brand-kits/brand-kit-assets.panel.js.map +1 -0
  208. package/dist/lib/panels/brand-kits/brand-kit-generation-policy.panel.d.ts +15 -0
  209. package/dist/lib/panels/brand-kits/brand-kit-generation-policy.panel.d.ts.map +1 -0
  210. package/dist/lib/panels/brand-kits/brand-kit-generation-policy.panel.js +52 -0
  211. package/dist/lib/panels/brand-kits/brand-kit-generation-policy.panel.js.map +1 -0
  212. package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts +10 -0
  213. package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts.map +1 -1
  214. package/dist/lib/panels/model-predictions/model-prediction.logic.js +15 -1
  215. package/dist/lib/panels/model-predictions/model-prediction.logic.js.map +1 -1
  216. package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts +4 -0
  217. package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts.map +1 -1
  218. package/dist/lib/panels/model-predictions/model-prediction.panel.js +77 -61
  219. package/dist/lib/panels/model-predictions/model-prediction.panel.js.map +1 -1
  220. package/dist/lib/shared/components/template-editor.component.d.ts +37 -0
  221. package/dist/lib/shared/components/template-editor.component.d.ts.map +1 -1
  222. package/dist/lib/shared/components/template-editor.component.js +424 -285
  223. package/dist/lib/shared/components/template-editor.component.js.map +1 -1
  224. package/dist/public-api.d.ts +2 -0
  225. package/dist/public-api.d.ts.map +1 -1
  226. package/dist/public-api.js +3 -0
  227. package/dist/public-api.js.map +1 -1
  228. package/package.json +50 -48
@@ -1,6 +1,6 @@
1
1
  import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, inject } from '@angular/core';
2
2
  import { RunView } from '@memberjunction/core';
3
- import { MJEventType, MJGlobal } from '@memberjunction/global';
3
+ import { EscapeSQLString, MJEventType, MJGlobal } from '@memberjunction/global';
4
4
  import { MJNotificationService } from '@memberjunction/ng-notifications';
5
5
  import { IsDescendantElement } from '@memberjunction/ng-shared-generic';
6
6
  import { TemplateEngineBase } from '@memberjunction/templates-base-types';
@@ -14,195 +14,215 @@ import * as i1 from "@memberjunction/ng-notifications";
14
14
  import * as i2 from "@memberjunction/ng-ui-components";
15
15
  import * as i3 from "@angular/forms";
16
16
  import * as i4 from "@memberjunction/ng-code-editor";
17
+ import * as i5 from "@memberjunction/ng-shared-generic";
17
18
  const _c0 = ["codeEditor"];
18
19
  const _forTrack0 = ($index, $item) => $item.ID || $index;
19
20
  const _forTrack1 = ($index, $item) => $item.category.name;
20
21
  const _forTrack2 = ($index, $item) => $item.name;
21
- function TemplateEditorComponent_Conditional_0_Conditional_1_For_3_Conditional_6_Template(rf, ctx) { if (rf & 1) {
22
+ function TemplateEditorComponent_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
23
+ i0.ɵɵelement(0, "mj-loading", 2);
24
+ } }
25
+ function TemplateEditorComponent_Conditional_0_Conditional_2_Template(rf, ctx) { if (rf & 1) {
26
+ const _r1 = i0.ɵɵgetCurrentView();
27
+ i0.ɵɵelementStart(0, "div", 3);
28
+ i0.ɵɵelement(1, "i", 4);
29
+ i0.ɵɵelementStart(2, "h5");
30
+ i0.ɵɵtext(3, "Template contents could not be loaded");
31
+ i0.ɵɵelementEnd();
32
+ i0.ɵɵelementStart(4, "p");
33
+ i0.ɵɵtext(5, "Nothing is shown so nothing can be saved over contents that were not read.");
34
+ i0.ɵɵelementEnd();
35
+ i0.ɵɵelementStart(6, "button", 5);
36
+ i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_2_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.RefreshAndDiscardChanges()); });
37
+ i0.ɵɵelement(7, "i", 6);
38
+ i0.ɵɵtext(8, " Retry ");
39
+ i0.ɵɵelementEnd()();
40
+ } }
41
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_For_3_Conditional_6_Template(rf, ctx) { if (rf & 1) {
22
42
  i0.ɵɵtext(0, " \u2022 ");
23
- i0.ɵɵelementStart(1, "span", 14);
43
+ i0.ɵɵelementStart(1, "span", 19);
24
44
  i0.ɵɵtext(2, "Inactive");
25
45
  i0.ɵɵelementEnd();
26
46
  } }
27
- function TemplateEditorComponent_Conditional_0_Conditional_1_For_3_Conditional_7_Template(rf, ctx) { if (rf & 1) {
28
- const _r4 = i0.ɵɵgetCurrentView();
29
- i0.ɵɵelementStart(0, "button", 15);
30
- i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_1_For_3_Conditional_7_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r4); const ɵ$index_9_r2 = i0.ɵɵnextContext().$index; const ctx_r2 = i0.ɵɵnextContext(3); ctx_r2.deleteTemplateContent(ɵ$index_9_r2); return i0.ɵɵresetView($event.stopPropagation()); });
31
- i0.ɵɵelement(1, "i", 16);
47
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_For_3_Conditional_7_Template(rf, ctx) { if (rf & 1) {
48
+ const _r5 = i0.ɵɵgetCurrentView();
49
+ i0.ɵɵelementStart(0, "button", 20);
50
+ i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_For_3_Conditional_7_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r5); const ɵ$index_29_r4 = i0.ɵɵnextContext().$index; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.deleteTemplateContent(ɵ$index_29_r4); return i0.ɵɵresetView($event.stopPropagation()); });
51
+ i0.ɵɵelement(1, "i", 21);
32
52
  i0.ɵɵelementEnd();
33
53
  } }
34
- function TemplateEditorComponent_Conditional_0_Conditional_1_For_3_Template(rf, ctx) { if (rf & 1) {
35
- const _r1 = i0.ɵɵgetCurrentView();
36
- i0.ɵɵelementStart(0, "div", 9);
37
- i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_1_For_3_Template_div_click_0_listener() { const ɵ$index_9_r2 = i0.ɵɵrestoreView(_r1).$index; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.selectTemplateContent(ɵ$index_9_r2, false)); });
38
- i0.ɵɵelementStart(1, "div", 10)(2, "div", 11);
54
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_For_3_Template(rf, ctx) { if (rf & 1) {
55
+ const _r3 = i0.ɵɵgetCurrentView();
56
+ i0.ɵɵelementStart(0, "div", 14);
57
+ i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_For_3_Template_div_click_0_listener() { const ɵ$index_29_r4 = i0.ɵɵrestoreView(_r3).$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.selectTemplateContent(ɵ$index_29_r4, false)); });
58
+ i0.ɵɵelementStart(1, "div", 15)(2, "div", 16);
39
59
  i0.ɵɵtext(3);
40
60
  i0.ɵɵelementEnd();
41
- i0.ɵɵelementStart(4, "div", 12);
61
+ i0.ɵɵelementStart(4, "div", 17);
42
62
  i0.ɵɵtext(5);
43
- i0.ɵɵconditionalCreate(6, TemplateEditorComponent_Conditional_0_Conditional_1_For_3_Conditional_6_Template, 3, 0);
63
+ i0.ɵɵconditionalCreate(6, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_For_3_Conditional_6_Template, 3, 0);
44
64
  i0.ɵɵelementEnd()();
45
- i0.ɵɵconditionalCreate(7, TemplateEditorComponent_Conditional_0_Conditional_1_For_3_Conditional_7_Template, 2, 0, "button", 13);
65
+ i0.ɵɵconditionalCreate(7, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_For_3_Conditional_7_Template, 2, 0, "button", 18);
46
66
  i0.ɵɵelementEnd();
47
67
  } if (rf & 2) {
48
- const content_r5 = ctx.$implicit;
49
- const ɵ$index_9_r2 = ctx.$index;
50
- const ctx_r2 = i0.ɵɵnextContext(3);
51
- i0.ɵɵclassProp("active", ctx_r2.selectedContentIndex === ɵ$index_9_r2 && !ctx_r2.isAddingNewContent);
68
+ const content_r6 = ctx.$implicit;
69
+ const ɵ$index_29_r4 = ctx.$index;
70
+ const ctx_r1 = i0.ɵɵnextContext(4);
71
+ i0.ɵɵclassProp("active", ctx_r1.selectedContentIndex === ɵ$index_29_r4 && !ctx_r1.isAddingNewContent);
52
72
  i0.ɵɵadvance(3);
53
- i0.ɵɵtextInterpolate1(" ", content_r5.Type || "Version " + (ɵ$index_9_r2 + 1), " ");
73
+ i0.ɵɵtextInterpolate1(" ", content_r6.TypeID ? ctx_r1.GetContentTypeDisplayText(content_r6.TypeID) : "Version " + (ɵ$index_29_r4 + 1), " ");
54
74
  i0.ɵɵadvance(2);
55
- i0.ɵɵtextInterpolate1(" P:", content_r5.Priority, " ");
75
+ i0.ɵɵtextInterpolate1(" P:", content_r6.Priority, " ");
56
76
  i0.ɵɵadvance();
57
- i0.ɵɵconditional(!content_r5.IsActive ? 6 : -1);
77
+ i0.ɵɵconditional(!content_r6.IsActive ? 6 : -1);
58
78
  i0.ɵɵadvance();
59
- i0.ɵɵconditional(ctx_r2.templateContents.length > 1 && ctx_r2.config.allowEdit ? 7 : -1);
79
+ i0.ɵɵconditional(ctx_r1.templateContents.length > 1 && ctx_r1.config.allowEdit ? 7 : -1);
60
80
  } }
61
- function TemplateEditorComponent_Conditional_0_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
62
- i0.ɵɵelementStart(0, "div", 7);
63
- i0.ɵɵelement(1, "i", 17);
64
- i0.ɵɵelementStart(2, "span", 18);
81
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_Conditional_4_Template(rf, ctx) { if (rf & 1) {
82
+ i0.ɵɵelementStart(0, "div", 12);
83
+ i0.ɵɵelement(1, "i", 22);
84
+ i0.ɵɵelementStart(2, "span", 23);
65
85
  i0.ɵɵtext(3, "New");
66
86
  i0.ɵɵelementEnd()();
67
87
  } }
68
- function TemplateEditorComponent_Conditional_0_Conditional_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
69
- const _r6 = i0.ɵɵgetCurrentView();
70
- i0.ɵɵelementStart(0, "div", 19);
71
- i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_1_Conditional_5_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.addNewTemplateContent()); });
72
- i0.ɵɵelement(1, "i", 20);
88
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_Conditional_5_Template(rf, ctx) { if (rf & 1) {
89
+ const _r7 = i0.ɵɵgetCurrentView();
90
+ i0.ɵɵelementStart(0, "div", 24);
91
+ i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_Conditional_5_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.addNewTemplateContent()); });
92
+ i0.ɵɵelement(1, "i", 25);
73
93
  i0.ɵɵelementStart(2, "span");
74
94
  i0.ɵɵtext(3, "New");
75
95
  i0.ɵɵelementEnd()();
76
96
  } }
77
- function TemplateEditorComponent_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
78
- i0.ɵɵelementStart(0, "div", 2)(1, "div", 5);
79
- i0.ɵɵrepeaterCreate(2, TemplateEditorComponent_Conditional_0_Conditional_1_For_3_Template, 8, 6, "div", 6, _forTrack0);
80
- i0.ɵɵconditionalCreate(4, TemplateEditorComponent_Conditional_0_Conditional_1_Conditional_4_Template, 4, 0, "div", 7);
81
- i0.ɵɵconditionalCreate(5, TemplateEditorComponent_Conditional_0_Conditional_1_Conditional_5_Template, 4, 0, "div", 8);
97
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
98
+ i0.ɵɵelementStart(0, "div", 7)(1, "div", 10);
99
+ i0.ɵɵrepeaterCreate(2, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_For_3_Template, 8, 6, "div", 11, _forTrack0);
100
+ i0.ɵɵconditionalCreate(4, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_Conditional_4_Template, 4, 0, "div", 12);
101
+ i0.ɵɵconditionalCreate(5, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_Conditional_5_Template, 4, 0, "div", 13);
82
102
  i0.ɵɵelementEnd()();
83
103
  } if (rf & 2) {
84
- const ctx_r2 = i0.ɵɵnextContext(2);
104
+ const ctx_r1 = i0.ɵɵnextContext(3);
85
105
  i0.ɵɵadvance(2);
86
- i0.ɵɵrepeater(ctx_r2.templateContents);
106
+ i0.ɵɵrepeater(ctx_r1.templateContents);
87
107
  i0.ɵɵadvance(2);
88
- i0.ɵɵconditional(ctx_r2.isAddingNewContent ? 4 : -1);
108
+ i0.ɵɵconditional(ctx_r1.isAddingNewContent ? 4 : -1);
89
109
  i0.ɵɵadvance();
90
- i0.ɵɵconditional(ctx_r2.config.allowEdit && !ctx_r2.isAddingNewContent ? 5 : -1);
110
+ i0.ɵɵconditional(ctx_r1.config.allowEdit && !ctx_r1.isAddingNewContent ? 5 : -1);
91
111
  } }
92
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_7_Template(rf, ctx) { if (rf & 1) {
93
- const _r8 = i0.ɵɵgetCurrentView();
94
- i0.ɵɵelementStart(0, "mj-dropdown", 44);
95
- 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); });
96
- 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()); });
112
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_7_Template(rf, ctx) { if (rf & 1) {
113
+ const _r9 = i0.ɵɵgetCurrentView();
114
+ i0.ɵɵelementStart(0, "mj-dropdown", 49);
115
+ i0.ɵɵtwoWayListener("ngModelChange", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_7_Template_mj_dropdown_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.currentTemplateContent.TypeID, $event) || (ctx_r1.currentTemplateContent.TypeID = $event); return i0.ɵɵresetView($event); });
116
+ i0.ɵɵlistener("ValueChange", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_7_Template_mj_dropdown_ValueChange_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.onContentTypeChange()); });
97
117
  i0.ɵɵelementEnd();
98
118
  } if (rf & 2) {
99
- const ctx_r2 = i0.ɵɵnextContext(3);
100
- i0.ɵɵtwoWayProperty("ngModel", ctx_r2.currentTemplateContent.TypeID);
101
- i0.ɵɵproperty("Data", ctx_r2.getContentTypeOptionsForContent())("ValuePrimitive", true);
119
+ const ctx_r1 = i0.ɵɵnextContext(4);
120
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.currentTemplateContent.TypeID);
121
+ i0.ɵɵproperty("Data", ctx_r1.getContentTypeOptionsForContent())("ValuePrimitive", true);
102
122
  } }
103
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
104
- i0.ɵɵelementStart(0, "div", 27);
123
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_8_Template(rf, ctx) { if (rf & 1) {
124
+ i0.ɵɵelementStart(0, "div", 32);
105
125
  i0.ɵɵtext(1);
106
126
  i0.ɵɵelementEnd();
107
127
  } if (rf & 2) {
108
- const ctx_r2 = i0.ɵɵnextContext(3);
128
+ const ctx_r1 = i0.ɵɵnextContext(4);
109
129
  i0.ɵɵadvance();
110
- i0.ɵɵtextInterpolate1(" ", ctx_r2.getContentTypeDisplayText(ctx_r2.currentTemplateContent.TypeID), " ");
130
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.getContentTypeDisplayText(ctx_r1.currentTemplateContent.TypeID), " ");
111
131
  } }
112
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
113
- const _r9 = i0.ɵɵgetCurrentView();
114
- i0.ɵɵelementStart(0, "mj-numeric-input", 45);
115
- 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); });
132
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_13_Template(rf, ctx) { if (rf & 1) {
133
+ const _r10 = i0.ɵɵgetCurrentView();
134
+ i0.ɵɵelementStart(0, "mj-numeric-input", 50);
135
+ i0.ɵɵtwoWayListener("ngModelChange", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_13_Template_mj_numeric_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.currentTemplateContent.Priority, $event) || (ctx_r1.currentTemplateContent.Priority = $event); return i0.ɵɵresetView($event); });
116
136
  i0.ɵɵelementEnd();
117
137
  } if (rf & 2) {
118
- const ctx_r2 = i0.ɵɵnextContext(3);
119
- i0.ɵɵtwoWayProperty("ngModel", ctx_r2.currentTemplateContent.Priority);
138
+ const ctx_r1 = i0.ɵɵnextContext(4);
139
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.currentTemplateContent.Priority);
120
140
  i0.ɵɵproperty("Min", 1)("Step", 1)("Format", "n0");
121
141
  } }
122
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_14_Template(rf, ctx) { if (rf & 1) {
123
- i0.ɵɵelementStart(0, "div", 27);
142
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_14_Template(rf, ctx) { if (rf & 1) {
143
+ i0.ɵɵelementStart(0, "div", 32);
124
144
  i0.ɵɵtext(1);
125
145
  i0.ɵɵelementEnd();
126
146
  } if (rf & 2) {
127
- const ctx_r2 = i0.ɵɵnextContext(3);
147
+ const ctx_r1 = i0.ɵɵnextContext(4);
128
148
  i0.ɵɵadvance();
129
- i0.ɵɵtextInterpolate1(" ", ctx_r2.currentTemplateContent.Priority || "-", " ");
149
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.currentTemplateContent.Priority || "-", " ");
130
150
  } }
131
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_19_Template(rf, ctx) { if (rf & 1) {
132
- const _r10 = i0.ɵɵgetCurrentView();
133
- i0.ɵɵelementStart(0, "div", 33)(1, "input", 46);
134
- i0.ɵɵtwoWayListener("ngModelChange", function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_19_Template_input_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r2.currentTemplateContent.IsActive, $event) || (ctx_r2.currentTemplateContent.IsActive = $event); return i0.ɵɵresetView($event); });
151
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_19_Template(rf, ctx) { if (rf & 1) {
152
+ const _r11 = i0.ɵɵgetCurrentView();
153
+ i0.ɵɵelementStart(0, "div", 38)(1, "input", 51);
154
+ i0.ɵɵtwoWayListener("ngModelChange", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_19_Template_input_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.currentTemplateContent.IsActive, $event) || (ctx_r1.currentTemplateContent.IsActive = $event); return i0.ɵɵresetView($event); });
135
155
  i0.ɵɵelementEnd();
136
- i0.ɵɵelementStart(2, "label", 47);
156
+ i0.ɵɵelementStart(2, "label", 52);
137
157
  i0.ɵɵtext(3, " Active ");
138
158
  i0.ɵɵelementEnd()();
139
159
  } if (rf & 2) {
140
- const ctx_r2 = i0.ɵɵnextContext(3);
160
+ const ctx_r1 = i0.ɵɵnextContext(4);
141
161
  i0.ɵɵadvance();
142
- i0.ɵɵtwoWayProperty("ngModel", ctx_r2.currentTemplateContent.IsActive);
162
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.currentTemplateContent.IsActive);
143
163
  } }
144
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_20_Conditional_1_Template(rf, ctx) { if (rf & 1) {
145
- i0.ɵɵelementStart(0, "span", 48);
146
- i0.ɵɵelement(1, "i", 50);
164
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_20_Conditional_1_Template(rf, ctx) { if (rf & 1) {
165
+ i0.ɵɵelementStart(0, "span", 53);
166
+ i0.ɵɵelement(1, "i", 55);
147
167
  i0.ɵɵtext(2, " Active ");
148
168
  i0.ɵɵelementEnd();
149
169
  } }
150
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_20_Conditional_2_Template(rf, ctx) { if (rf & 1) {
151
- i0.ɵɵelementStart(0, "span", 49);
152
- i0.ɵɵelement(1, "i", 51);
170
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_20_Conditional_2_Template(rf, ctx) { if (rf & 1) {
171
+ i0.ɵɵelementStart(0, "span", 54);
172
+ i0.ɵɵelement(1, "i", 56);
153
173
  i0.ɵɵtext(2, " Inactive ");
154
174
  i0.ɵɵelementEnd();
155
175
  } }
156
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_20_Template(rf, ctx) { if (rf & 1) {
157
- i0.ɵɵelementStart(0, "div", 27);
158
- i0.ɵɵconditionalCreate(1, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_20_Conditional_1_Template, 3, 0, "span", 48)(2, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_20_Conditional_2_Template, 3, 0, "span", 49);
176
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_20_Template(rf, ctx) { if (rf & 1) {
177
+ i0.ɵɵelementStart(0, "div", 32);
178
+ i0.ɵɵconditionalCreate(1, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_20_Conditional_1_Template, 3, 0, "span", 53)(2, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_20_Conditional_2_Template, 3, 0, "span", 54);
159
179
  i0.ɵɵelementEnd();
160
180
  } if (rf & 2) {
161
- const ctx_r2 = i0.ɵɵnextContext(3);
181
+ const ctx_r1 = i0.ɵɵnextContext(4);
162
182
  i0.ɵɵadvance();
163
- i0.ɵɵconditional(ctx_r2.currentTemplateContent.IsActive ? 1 : 2);
183
+ i0.ɵɵconditional(ctx_r1.currentTemplateContent.IsActive ? 1 : 2);
164
184
  } }
165
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_27_Template(rf, ctx) { if (rf & 1) {
185
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_27_Template(rf, ctx) { if (rf & 1) {
166
186
  i0.ɵɵtext(0, " New ");
167
187
  } }
168
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_28_Template(rf, ctx) { if (rf & 1) {
188
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_28_Template(rf, ctx) { if (rf & 1) {
169
189
  i0.ɵɵtext(0);
170
190
  } if (rf & 2) {
171
- const ctx_r2 = i0.ɵɵnextContext(3);
172
- i0.ɵɵtextInterpolate1(" ", ctx_r2.getContentTypeDisplayText(ctx_r2.currentTemplateContent.TypeID), " ");
191
+ const ctx_r1 = i0.ɵɵnextContext(4);
192
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.getContentTypeDisplayText(ctx_r1.currentTemplateContent.TypeID), " ");
173
193
  } }
174
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_30_Template(rf, ctx) { if (rf & 1) {
175
- i0.ɵɵelementStart(0, "span", 40);
176
- i0.ɵɵelement(1, "i", 52);
194
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_30_Template(rf, ctx) { if (rf & 1) {
195
+ i0.ɵɵelementStart(0, "span", 45);
196
+ i0.ɵɵelement(1, "i", 57);
177
197
  i0.ɵɵtext(2, " Unsaved changes ");
178
198
  i0.ɵɵelementEnd();
179
199
  } }
180
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_31_Conditional_1_Template(rf, ctx) { if (rf & 1) {
181
- i0.ɵɵelement(0, "i", 54);
200
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_31_Conditional_1_Template(rf, ctx) { if (rf & 1) {
201
+ i0.ɵɵelement(0, "i", 59);
182
202
  i0.ɵɵtext(1, " Running... ");
183
203
  } }
184
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_31_Conditional_2_Template(rf, ctx) { if (rf & 1) {
185
- i0.ɵɵelement(0, "i", 55);
204
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_31_Conditional_2_Template(rf, ctx) { if (rf & 1) {
205
+ i0.ɵɵelement(0, "i", 60);
186
206
  i0.ɵɵtext(1, " Run ");
187
207
  } }
188
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_31_Template(rf, ctx) { if (rf & 1) {
189
- const _r11 = i0.ɵɵgetCurrentView();
190
- i0.ɵɵelementStart(0, "button", 53);
191
- i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_31_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onRunTemplate()); });
192
- i0.ɵɵconditionalCreate(1, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_31_Conditional_1_Template, 2, 0)(2, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_31_Conditional_2_Template, 2, 0);
208
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_31_Template(rf, ctx) { if (rf & 1) {
209
+ const _r12 = i0.ɵɵgetCurrentView();
210
+ i0.ɵɵelementStart(0, "button", 58);
211
+ i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_31_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.onRunTemplate()); });
212
+ i0.ɵɵconditionalCreate(1, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_31_Conditional_1_Template, 2, 0)(2, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_31_Conditional_2_Template, 2, 0);
193
213
  i0.ɵɵelementEnd();
194
214
  } if (rf & 2) {
195
- const ctx_r2 = i0.ɵɵnextContext(3);
196
- i0.ɵɵproperty("disabled", ctx_r2.isRunningTemplate);
215
+ const ctx_r1 = i0.ɵɵnextContext(4);
216
+ i0.ɵɵproperty("disabled", ctx_r1.isRunningTemplate);
197
217
  i0.ɵɵadvance();
198
- i0.ɵɵconditional(ctx_r2.isRunningTemplate ? 1 : 2);
218
+ i0.ɵɵconditional(ctx_r1.isRunningTemplate ? 1 : 2);
199
219
  } }
200
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_9_Template(rf, ctx) { if (rf & 1) {
201
- i0.ɵɵelementStart(0, "div", 60)(1, "div", 62);
202
- i0.ɵɵelement(2, "i", 63);
220
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_9_Template(rf, ctx) { if (rf & 1) {
221
+ i0.ɵɵelementStart(0, "div", 65)(1, "div", 67);
222
+ i0.ɵɵelement(2, "i", 68);
203
223
  i0.ɵɵtext(3, " Template Syntax Quick Reference ");
204
224
  i0.ɵɵelementEnd();
205
- i0.ɵɵelementStart(4, "div", 64)(5, "div")(6, "div", 65)(7, "strong");
225
+ i0.ɵɵelementStart(4, "div", 69)(5, "div")(6, "div", 70)(7, "strong");
206
226
  i0.ɵɵtext(8, "Parameters:");
207
227
  i0.ɵɵelementEnd();
208
228
  i0.ɵɵelement(9, "br");
@@ -216,7 +236,7 @@ function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Cond
216
236
  i0.ɵɵelementStart(16, "code");
217
237
  i0.ɵɵtext(17);
218
238
  i0.ɵɵelementEnd()()();
219
- i0.ɵɵelementStart(18, "div")(19, "div", 65)(20, "strong");
239
+ i0.ɵɵelementStart(18, "div")(19, "div", 70)(20, "strong");
220
240
  i0.ɵɵtext(21, "Conditionals:");
221
241
  i0.ɵɵelementEnd();
222
242
  i0.ɵɵelement(22, "br");
@@ -240,96 +260,96 @@ function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Cond
240
260
  i0.ɵɵadvance(6);
241
261
  i0.ɵɵtextInterpolate2("", "{% for item in items %}", " ... ", "{% endfor %}");
242
262
  } }
243
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_For_8_Template(rf, ctx) { if (rf & 1) {
244
- const _r13 = i0.ɵɵgetCurrentView();
245
- i0.ɵɵelementStart(0, "button", 74);
246
- i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_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); });
247
- i0.ɵɵelement(1, "i", 75);
263
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_8_Template(rf, ctx) { if (rf & 1) {
264
+ const _r14 = i0.ɵɵgetCurrentView();
265
+ i0.ɵɵelementStart(0, "button", 79);
266
+ i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_8_Template_button_click_0_listener() { const categoryGroup_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.activePlaceholderCategory = categoryGroup_r15.category.name); });
267
+ i0.ɵɵelement(1, "i", 80);
248
268
  i0.ɵɵtext(2);
249
- i0.ɵɵelementStart(3, "span", 76);
269
+ i0.ɵɵelementStart(3, "span", 81);
250
270
  i0.ɵɵtext(4);
251
271
  i0.ɵɵelementEnd()();
252
272
  } if (rf & 2) {
253
- const categoryGroup_r14 = ctx.$implicit;
254
- const ctx_r2 = i0.ɵɵnextContext(5);
255
- i0.ɵɵclassProp("active", ctx_r2.activePlaceholderCategory === categoryGroup_r14.category.name);
273
+ const categoryGroup_r15 = ctx.$implicit;
274
+ const ctx_r1 = i0.ɵɵnextContext(6);
275
+ i0.ɵɵclassProp("active", ctx_r1.activePlaceholderCategory === categoryGroup_r15.category.name);
256
276
  i0.ɵɵadvance();
257
- i0.ɵɵclassMap("fa-solid " + categoryGroup_r14.category.icon);
277
+ i0.ɵɵclassMap("fa-solid " + categoryGroup_r15.category.icon);
258
278
  i0.ɵɵadvance();
259
- i0.ɵɵtextInterpolate1(" ", categoryGroup_r14.category.name, " ");
279
+ i0.ɵɵtextInterpolate1(" ", categoryGroup_r15.category.name, " ");
260
280
  i0.ɵɵadvance(2);
261
- i0.ɵɵtextInterpolate1(" ", categoryGroup_r14.placeholders.length, " ");
281
+ i0.ɵɵtextInterpolate1(" ", categoryGroup_r15.placeholders.length, " ");
262
282
  } }
263
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Conditional_8_Template(rf, ctx) { if (rf & 1) {
264
- i0.ɵɵelementStart(0, "div", 85);
283
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Conditional_8_Template(rf, ctx) { if (rf & 1) {
284
+ i0.ɵɵelementStart(0, "div", 90);
265
285
  i0.ɵɵtext(1);
266
286
  i0.ɵɵelementEnd();
267
287
  } if (rf & 2) {
268
- const placeholder_r16 = i0.ɵɵnextContext().$implicit;
288
+ const placeholder_r17 = i0.ɵɵnextContext().$implicit;
269
289
  i0.ɵɵadvance();
270
- i0.ɵɵtextInterpolate(placeholder_r16.description);
290
+ i0.ɵɵtextInterpolate(placeholder_r17.description);
271
291
  } }
272
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Template(rf, ctx) { if (rf & 1) {
273
- const _r15 = i0.ɵɵgetCurrentView();
274
- i0.ɵɵelementStart(0, "div", 79)(1, "div", 80)(2, "div")(3, "div", 81)(4, "code", 82);
292
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Template(rf, ctx) { if (rf & 1) {
293
+ const _r16 = i0.ɵɵgetCurrentView();
294
+ i0.ɵɵelementStart(0, "div", 84)(1, "div", 85)(2, "div")(3, "div", 86)(4, "code", 87);
275
295
  i0.ɵɵtext(5);
276
296
  i0.ɵɵelementEnd();
277
- i0.ɵɵelementStart(6, "button", 83);
278
- i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_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)); });
279
- i0.ɵɵelement(7, "i", 84);
297
+ i0.ɵɵelementStart(6, "button", 88);
298
+ i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Template_button_click_6_listener() { const placeholder_r17 = i0.ɵɵrestoreView(_r16).$implicit; const ctx_r1 = i0.ɵɵnextContext(8); return i0.ɵɵresetView(ctx_r1.copyPlaceholder(placeholder_r17.name)); });
299
+ i0.ɵɵelement(7, "i", 89);
280
300
  i0.ɵɵelementEnd()();
281
- i0.ɵɵconditionalCreate(8, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Conditional_8_Template, 2, 1, "div", 85);
301
+ i0.ɵɵconditionalCreate(8, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Conditional_8_Template, 2, 1, "div", 90);
282
302
  i0.ɵɵelementEnd()()();
283
303
  } if (rf & 2) {
284
- const placeholder_r16 = ctx.$implicit;
304
+ const placeholder_r17 = ctx.$implicit;
285
305
  i0.ɵɵadvance(5);
286
- i0.ɵɵtextInterpolate3("", "{{", " ", placeholder_r16.name, " ", "}}");
306
+ i0.ɵɵtextInterpolate3("", "{{", " ", placeholder_r17.name, " ", "}}");
287
307
  i0.ɵɵadvance(3);
288
- i0.ɵɵconditional(placeholder_r16.description ? 8 : -1);
308
+ i0.ɵɵconditional(placeholder_r17.description ? 8 : -1);
289
309
  } }
290
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_Template(rf, ctx) { if (rf & 1) {
291
- i0.ɵɵelementStart(0, "div", 77);
310
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_11_Conditional_0_Template(rf, ctx) { if (rf & 1) {
311
+ i0.ɵɵelementStart(0, "div", 82);
292
312
  i0.ɵɵelement(1, "i");
293
313
  i0.ɵɵelementStart(2, "h5");
294
314
  i0.ɵɵtext(3);
295
315
  i0.ɵɵelementEnd()();
296
- i0.ɵɵelementStart(4, "div", 78);
297
- i0.ɵɵrepeaterCreate(5, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Template, 9, 4, "div", 79, _forTrack2);
316
+ i0.ɵɵelementStart(4, "div", 83);
317
+ i0.ɵɵrepeaterCreate(5, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_11_Conditional_0_For_6_Template, 9, 4, "div", 84, _forTrack2);
298
318
  i0.ɵɵelementEnd();
299
319
  } if (rf & 2) {
300
- const categoryGroup_r17 = i0.ɵɵnextContext().$implicit;
320
+ const categoryGroup_r18 = i0.ɵɵnextContext().$implicit;
301
321
  i0.ɵɵadvance();
302
- i0.ɵɵclassMap("fa-solid " + categoryGroup_r17.category.icon);
303
- i0.ɵɵstyleProp("color", categoryGroup_r17.category.color);
322
+ i0.ɵɵclassMap("fa-solid " + categoryGroup_r18.category.icon);
323
+ i0.ɵɵstyleProp("color", categoryGroup_r18.category.color);
304
324
  i0.ɵɵadvance(2);
305
- i0.ɵɵtextInterpolate(categoryGroup_r17.category.name);
325
+ i0.ɵɵtextInterpolate(categoryGroup_r18.category.name);
306
326
  i0.ɵɵadvance(2);
307
- i0.ɵɵrepeater(categoryGroup_r17.placeholders);
327
+ i0.ɵɵrepeater(categoryGroup_r18.placeholders);
308
328
  } }
309
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_For_11_Template(rf, ctx) { if (rf & 1) {
310
- i0.ɵɵconditionalCreate(0, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_For_11_Conditional_0_Template, 7, 5);
329
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_11_Template(rf, ctx) { if (rf & 1) {
330
+ i0.ɵɵconditionalCreate(0, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_11_Conditional_0_Template, 7, 5);
311
331
  } if (rf & 2) {
312
- const categoryGroup_r17 = ctx.$implicit;
313
- const ctx_r2 = i0.ɵɵnextContext(5);
314
- i0.ɵɵconditional(ctx_r2.activePlaceholderCategory === categoryGroup_r17.category.name ? 0 : -1);
332
+ const categoryGroup_r18 = ctx.$implicit;
333
+ const ctx_r1 = i0.ɵɵnextContext(6);
334
+ i0.ɵɵconditional(ctx_r1.activePlaceholderCategory === categoryGroup_r18.category.name ? 0 : -1);
315
335
  } }
316
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_Template(rf, ctx) { if (rf & 1) {
317
- i0.ɵɵelementStart(0, "div", 61)(1, "div", 62);
318
- i0.ɵɵelement(2, "i", 58);
336
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_Template(rf, ctx) { if (rf & 1) {
337
+ i0.ɵɵelementStart(0, "div", 66)(1, "div", 67);
338
+ i0.ɵɵelement(2, "i", 63);
319
339
  i0.ɵɵtext(3, " System Placeholders Reference ");
320
340
  i0.ɵɵelementEnd();
321
- i0.ɵɵelementStart(4, "p", 66);
341
+ i0.ɵɵelementStart(4, "p", 71);
322
342
  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. Scoped prompt parts can use the Date & Time, User Context and Environment placeholders, written alone with no filter. A part is not a template: everything else in it is sent as written. ");
323
343
  i0.ɵɵelementEnd();
324
- i0.ɵɵelementStart(6, "div", 67);
325
- i0.ɵɵrepeaterCreate(7, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_For_8_Template, 5, 6, "button", 68, _forTrack1);
344
+ i0.ɵɵelementStart(6, "div", 72);
345
+ i0.ɵɵrepeaterCreate(7, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_8_Template, 5, 6, "button", 73, _forTrack1);
326
346
  i0.ɵɵelementEnd();
327
- i0.ɵɵelementStart(9, "div", 69);
328
- i0.ɵɵrepeaterCreate(10, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_For_11_Template, 1, 1, null, null, _forTrack1);
347
+ i0.ɵɵelementStart(9, "div", 74);
348
+ i0.ɵɵrepeaterCreate(10, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_For_11_Template, 1, 1, null, null, _forTrack1);
329
349
  i0.ɵɵelementEnd();
330
- i0.ɵɵelementStart(12, "div", 70)(13, "div", 71);
331
- i0.ɵɵelement(14, "i", 72);
332
- i0.ɵɵelementStart(15, "div", 73)(16, "strong");
350
+ i0.ɵɵelementStart(12, "div", 75)(13, "div", 76);
351
+ i0.ɵɵelement(14, "i", 77);
352
+ i0.ɵɵelementStart(15, "div", 78)(16, "strong");
333
353
  i0.ɵɵtext(17, "Usage Example:");
334
354
  i0.ɵɵelementEnd();
335
355
  i0.ɵɵtext(18, " To use a system placeholder in your template, simply include it in double curly braces. For example: ");
@@ -337,132 +357,138 @@ function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Cond
337
357
  i0.ɵɵtext(20);
338
358
  i0.ɵɵelementEnd()()()()();
339
359
  } if (rf & 2) {
340
- const ctx_r2 = i0.ɵɵnextContext(4);
360
+ const ctx_r1 = i0.ɵɵnextContext(5);
341
361
  i0.ɵɵadvance(7);
342
- i0.ɵɵrepeater(ctx_r2.placeholderCategories);
362
+ i0.ɵɵrepeater(ctx_r1.placeholderCategories);
343
363
  i0.ɵɵadvance(3);
344
- i0.ɵɵrepeater(ctx_r2.placeholderCategories);
364
+ i0.ɵɵrepeater(ctx_r1.placeholderCategories);
345
365
  i0.ɵɵadvance(10);
346
366
  i0.ɵɵtextInterpolate4("\"Today is ", "{{", " _CURRENT_DATE ", "}}", " and the current user is ", "{{", " _USER_NAME ", "}}", "\"");
347
367
  } }
348
- function TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Template(rf, ctx) { if (rf & 1) {
349
- const _r12 = i0.ɵɵgetCurrentView();
350
- i0.ɵɵelementStart(0, "div", 43)(1, "div", 56)(2, "button", 57);
351
- i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_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"); });
352
- i0.ɵɵelement(3, "i", 37);
368
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Template(rf, ctx) { if (rf & 1) {
369
+ const _r13 = i0.ɵɵgetCurrentView();
370
+ i0.ɵɵelementStart(0, "div", 48)(1, "div", 61)(2, "button", 62);
371
+ i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.activeHelpTab = "syntax"); });
372
+ i0.ɵɵelement(3, "i", 42);
353
373
  i0.ɵɵtext(4, " Template Syntax ");
354
374
  i0.ɵɵelementEnd();
355
- i0.ɵɵelementStart(5, "button", 57);
356
- i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_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"); });
357
- i0.ɵɵelement(6, "i", 58);
375
+ i0.ɵɵelementStart(5, "button", 62);
376
+ i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.activeHelpTab = "placeholders"); });
377
+ i0.ɵɵelement(6, "i", 63);
358
378
  i0.ɵɵtext(7, " System Placeholders ");
359
379
  i0.ɵɵelementEnd()();
360
- i0.ɵɵelementStart(8, "div", 59);
361
- i0.ɵɵconditionalCreate(9, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_9_Template, 31, 7, "div", 60);
362
- i0.ɵɵconditionalCreate(10, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Conditional_10_Template, 21, 4, "div", 61);
380
+ i0.ɵɵelementStart(8, "div", 64);
381
+ i0.ɵɵconditionalCreate(9, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_9_Template, 31, 7, "div", 65);
382
+ i0.ɵɵconditionalCreate(10, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Conditional_10_Template, 21, 4, "div", 66);
363
383
  i0.ɵɵelementEnd()();
364
384
  } if (rf & 2) {
365
- const ctx_r2 = i0.ɵɵnextContext(3);
385
+ const ctx_r1 = i0.ɵɵnextContext(4);
366
386
  i0.ɵɵadvance(2);
367
- i0.ɵɵclassProp("active", ctx_r2.activeHelpTab === "syntax");
387
+ i0.ɵɵclassProp("active", ctx_r1.activeHelpTab === "syntax");
368
388
  i0.ɵɵadvance(3);
369
- i0.ɵɵclassProp("active", ctx_r2.activeHelpTab === "placeholders");
389
+ i0.ɵɵclassProp("active", ctx_r1.activeHelpTab === "placeholders");
370
390
  i0.ɵɵadvance(4);
371
- i0.ɵɵconditional(ctx_r2.activeHelpTab === "syntax" ? 9 : -1);
391
+ i0.ɵɵconditional(ctx_r1.activeHelpTab === "syntax" ? 9 : -1);
372
392
  i0.ɵɵadvance();
373
- i0.ɵɵconditional(ctx_r2.activeHelpTab === "placeholders" ? 10 : -1);
393
+ i0.ɵɵconditional(ctx_r1.activeHelpTab === "placeholders" ? 10 : -1);
374
394
  } }
375
- function TemplateEditorComponent_Conditional_0_Conditional_2_Template(rf, ctx) { if (rf & 1) {
376
- const _r7 = i0.ɵɵgetCurrentView();
377
- i0.ɵɵelementStart(0, "div", 3)(1, "div", 21)(2, "div", 22)(3, "div", 23)(4, "label", 24);
378
- i0.ɵɵelement(5, "i", 25);
395
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
396
+ const _r8 = i0.ɵɵgetCurrentView();
397
+ i0.ɵɵelementStart(0, "div", 8)(1, "div", 26)(2, "div", 27)(3, "div", 28)(4, "label", 29);
398
+ i0.ɵɵelement(5, "i", 30);
379
399
  i0.ɵɵtext(6, " Content Type ");
380
400
  i0.ɵɵelementEnd();
381
- 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);
401
+ i0.ɵɵconditionalCreate(7, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_7_Template, 1, 3, "mj-dropdown", 31)(8, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_8_Template, 2, 1, "div", 32);
382
402
  i0.ɵɵelementEnd();
383
- i0.ɵɵelementStart(9, "div", 23)(10, "label", 28);
384
- i0.ɵɵelement(11, "i", 29);
403
+ i0.ɵɵelementStart(9, "div", 28)(10, "label", 33);
404
+ i0.ɵɵelement(11, "i", 34);
385
405
  i0.ɵɵtext(12, " Priority ");
386
406
  i0.ɵɵelementEnd();
387
- 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);
407
+ i0.ɵɵconditionalCreate(13, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_13_Template, 1, 4, "mj-numeric-input", 35)(14, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_14_Template, 2, 1, "div", 32);
388
408
  i0.ɵɵelementEnd();
389
- i0.ɵɵelementStart(15, "div", 23)(16, "label", 31);
390
- i0.ɵɵelement(17, "i", 32);
409
+ i0.ɵɵelementStart(15, "div", 28)(16, "label", 36);
410
+ i0.ɵɵelement(17, "i", 37);
391
411
  i0.ɵɵtext(18, " Status ");
392
412
  i0.ɵɵelementEnd();
393
- i0.ɵɵconditionalCreate(19, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_19_Template, 4, 1, "div", 33)(20, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_20_Template, 3, 1, "div", 27);
413
+ i0.ɵɵconditionalCreate(19, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_19_Template, 4, 1, "div", 38)(20, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_20_Template, 3, 1, "div", 32);
394
414
  i0.ɵɵelementEnd()()();
395
- i0.ɵɵelementStart(21, "div", 34)(22, "div", 35)(23, "label", 36);
396
- i0.ɵɵelement(24, "i", 37);
415
+ i0.ɵɵelementStart(21, "div", 39)(22, "div", 40)(23, "label", 41);
416
+ i0.ɵɵelement(24, "i", 42);
397
417
  i0.ɵɵtext(25, " Template Content ");
398
- i0.ɵɵelementStart(26, "span", 38);
399
- i0.ɵɵconditionalCreate(27, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_27_Template, 1, 0)(28, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_28_Template, 1, 1);
418
+ i0.ɵɵelementStart(26, "span", 43);
419
+ i0.ɵɵconditionalCreate(27, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_27_Template, 1, 0)(28, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_28_Template, 1, 1);
400
420
  i0.ɵɵelementEnd()();
401
- i0.ɵɵelementStart(29, "div", 39);
402
- i0.ɵɵconditionalCreate(30, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_30_Template, 3, 0, "span", 40);
403
- i0.ɵɵconditionalCreate(31, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_31_Template, 3, 2, "button", 41);
421
+ i0.ɵɵelementStart(29, "div", 44);
422
+ i0.ɵɵconditionalCreate(30, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_30_Template, 3, 0, "span", 45);
423
+ i0.ɵɵconditionalCreate(31, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_31_Template, 3, 2, "button", 46);
404
424
  i0.ɵɵelementEnd()();
405
- i0.ɵɵelementStart(32, "mj-code-editor", 42, 0);
406
- i0.ɵɵlistener("change", function TemplateEditorComponent_Conditional_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)); });
425
+ i0.ɵɵelementStart(32, "mj-code-editor", 47, 0);
426
+ i0.ɵɵlistener("change", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Template_mj_code_editor_change_32_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onTemplateTextChange($event)); });
407
427
  i0.ɵɵelementEnd();
408
- i0.ɵɵconditionalCreate(34, TemplateEditorComponent_Conditional_0_Conditional_2_Conditional_34_Template, 11, 6, "div", 43);
428
+ i0.ɵɵconditionalCreate(34, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Conditional_34_Template, 11, 6, "div", 48);
409
429
  i0.ɵɵelementEnd()();
410
430
  } if (rf & 2) {
411
- const ctx_r2 = i0.ɵɵnextContext(2);
431
+ const ctx_r1 = i0.ɵɵnextContext(3);
412
432
  i0.ɵɵadvance(7);
413
- i0.ɵɵconditional(ctx_r2.config.allowEdit ? 7 : 8);
433
+ i0.ɵɵconditional(ctx_r1.config.allowEdit ? 7 : 8);
414
434
  i0.ɵɵadvance(6);
415
- i0.ɵɵconditional(ctx_r2.config.allowEdit ? 13 : 14);
435
+ i0.ɵɵconditional(ctx_r1.config.allowEdit ? 13 : 14);
416
436
  i0.ɵɵadvance(6);
417
- i0.ɵɵconditional(ctx_r2.config.allowEdit ? 19 : 20);
437
+ i0.ɵɵconditional(ctx_r1.config.allowEdit ? 19 : 20);
418
438
  i0.ɵɵadvance(7);
419
- i0.ɵɵclassProp("new", !ctx_r2.currentTemplateContent.ID)("existing", !!ctx_r2.currentTemplateContent.ID);
439
+ i0.ɵɵclassProp("new", !ctx_r1.currentTemplateContent.ID)("existing", !!ctx_r1.currentTemplateContent.ID);
420
440
  i0.ɵɵadvance();
421
- i0.ɵɵconditional(!ctx_r2.currentTemplateContent.ID ? 27 : 28);
441
+ i0.ɵɵconditional(!ctx_r1.currentTemplateContent.ID ? 27 : 28);
422
442
  i0.ɵɵadvance(3);
423
- i0.ɵɵconditional(!ctx_r2.isAddingNewContent && ctx_r2.hasUnsavedChanges ? 30 : -1);
443
+ i0.ɵɵconditional(!ctx_r1.isAddingNewContent && ctx_r1.hasUnsavedChanges ? 30 : -1);
424
444
  i0.ɵɵadvance();
425
- i0.ɵɵconditional(ctx_r2.template.IsSaved && ctx_r2.currentTemplateContent && ctx_r2.config.showRunButton ? 31 : -1);
445
+ i0.ɵɵconditional(ctx_r1.template.IsSaved && ctx_r1.currentTemplateContent && ctx_r1.config.showRunButton ? 31 : -1);
426
446
  i0.ɵɵadvance();
427
- i0.ɵɵproperty("readonly", !ctx_r2.config.allowEdit)("language", ctx_r2.getEditorLanguage())("languages", ctx_r2.supportedLanguages);
447
+ i0.ɵɵproperty("readonly", !ctx_r1.config.allowEdit)("language", ctx_r1.getEditorLanguage())("languages", ctx_r1.supportedLanguages);
428
448
  i0.ɵɵadvance(2);
429
- i0.ɵɵconditional(!ctx_r2.config.compactMode ? 34 : -1);
449
+ i0.ɵɵconditional(!ctx_r1.config.compactMode ? 34 : -1);
430
450
  } }
431
- function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_6_Template(rf, ctx) { if (rf & 1) {
432
- const _r18 = i0.ɵɵgetCurrentView();
433
- i0.ɵɵelementStart(0, "button", 88);
434
- i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_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()); });
435
- i0.ɵɵelement(1, "i", 20);
451
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
452
+ const _r19 = i0.ɵɵgetCurrentView();
453
+ i0.ɵɵelementStart(0, "button", 93);
454
+ i0.ɵɵlistener("click", function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_2_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.addNewTemplateContent()); });
455
+ i0.ɵɵelement(1, "i", 25);
436
456
  i0.ɵɵtext(2, " Create First Content Version ");
437
457
  i0.ɵɵelementEnd();
438
458
  } }
439
- function TemplateEditorComponent_Conditional_0_Conditional_3_Template(rf, ctx) { if (rf & 1) {
440
- i0.ɵɵelementStart(0, "div", 4);
441
- i0.ɵɵelement(1, "i", 86);
459
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_2_Template(rf, ctx) { if (rf & 1) {
460
+ i0.ɵɵelementStart(0, "div", 9);
461
+ i0.ɵɵelement(1, "i", 91);
442
462
  i0.ɵɵelementStart(2, "h5");
443
463
  i0.ɵɵtext(3, "No Template Content");
444
464
  i0.ɵɵelementEnd();
445
465
  i0.ɵɵelementStart(4, "p");
446
466
  i0.ɵɵtext(5, "Create your first template content version to get started.");
447
467
  i0.ɵɵelementEnd();
448
- i0.ɵɵconditionalCreate(6, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_6_Template, 3, 0, "button", 87);
468
+ i0.ɵɵconditionalCreate(6, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_2_Conditional_6_Template, 3, 0, "button", 92);
449
469
  i0.ɵɵelementEnd();
450
470
  } if (rf & 2) {
451
- const ctx_r2 = i0.ɵɵnextContext(2);
471
+ const ctx_r1 = i0.ɵɵnextContext(3);
452
472
  i0.ɵɵadvance(6);
453
- i0.ɵɵconditional(ctx_r2.config.allowEdit ? 6 : -1);
473
+ i0.ɵɵconditional(ctx_r1.config.allowEdit ? 6 : -1);
474
+ } }
475
+ function TemplateEditorComponent_Conditional_0_Conditional_3_Template(rf, ctx) { if (rf & 1) {
476
+ i0.ɵɵconditionalCreate(0, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_0_Template, 6, 2, "div", 7);
477
+ i0.ɵɵconditionalCreate(1, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_1_Template, 35, 14, "div", 8)(2, TemplateEditorComponent_Conditional_0_Conditional_3_Conditional_2_Template, 7, 1, "div", 9);
478
+ } if (rf & 2) {
479
+ const ctx_r1 = i0.ɵɵnextContext(2);
480
+ i0.ɵɵconditional(ctx_r1.templateContents.length > 0 ? 0 : -1);
481
+ i0.ɵɵadvance();
482
+ i0.ɵɵconditional(ctx_r1.currentTemplateContent ? 1 : 2);
454
483
  } }
455
484
  function TemplateEditorComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
456
485
  i0.ɵɵelementStart(0, "div", 1);
457
- i0.ɵɵconditionalCreate(1, TemplateEditorComponent_Conditional_0_Conditional_1_Template, 6, 2, "div", 2);
458
- i0.ɵɵconditionalCreate(2, TemplateEditorComponent_Conditional_0_Conditional_2_Template, 35, 14, "div", 3)(3, TemplateEditorComponent_Conditional_0_Conditional_3_Template, 7, 1, "div", 4);
486
+ i0.ɵɵconditionalCreate(1, TemplateEditorComponent_Conditional_0_Conditional_1_Template, 1, 0, "mj-loading", 2)(2, TemplateEditorComponent_Conditional_0_Conditional_2_Template, 9, 0, "div", 3)(3, TemplateEditorComponent_Conditional_0_Conditional_3_Template, 3, 2);
459
487
  i0.ɵɵelementEnd();
460
488
  } if (rf & 2) {
461
- const ctx_r2 = i0.ɵɵnextContext();
489
+ const ctx_r1 = i0.ɵɵnextContext();
462
490
  i0.ɵɵadvance();
463
- i0.ɵɵconditional(ctx_r2.templateContents.length > 0 ? 1 : -1);
464
- i0.ɵɵadvance();
465
- i0.ɵɵconditional(ctx_r2.currentTemplateContent ? 2 : 3);
491
+ i0.ɵɵconditional(ctx_r1.ContentsLoadState === "loading" ? 1 : ctx_r1.ContentsLoadState === "failed" ? 2 : 3);
466
492
  } }
467
493
  export class TemplateEditorComponent extends BaseAngularComponent {
468
494
  /** @deprecated Use {@link Template}. */
@@ -614,13 +640,29 @@ export class TemplateEditorComponent extends BaseAngularComponent {
614
640
  this.isUpdatingEditorValue = false;
615
641
  this.destroy$ = new Subject();
616
642
  this.activeTimeouts = [];
643
+ /**
644
+ * Incremented by every LoadTemplateContents() call. A load only applies its rows if it is still
645
+ * the latest one when its awaits resolve, so an older, slower load can never replace the array
646
+ * the user is editing (MJ#4754: the edited rows and the saved rows diverged that way).
647
+ */
648
+ this.loadGeneration = 0;
649
+ /** The Template the most recent load was started for; lets ngOnInit skip a duplicate load. */
650
+ this.loadStartedFor = null;
651
+ /**
652
+ * Where the bound Template's contents are. `TemplateContents` is only the user's real data in
653
+ * 'loaded': while 'loading' it is a placeholder the landing load replaces, and after 'failed' it
654
+ * is empty because the read failed, not because the template has no content. The template and
655
+ * every writer of `TemplateContents` key on this rather than on the array's length.
656
+ */
657
+ this.ContentsLoadState = 'idle';
617
658
  this.elementRef = inject(ElementRef);
618
659
  }
619
660
  async ngOnInit() {
620
661
  this.LoadContentTypes();
621
662
  this.organizePlaceholdersByCategory();
622
663
  this.listenForHostFormEvents();
623
- if (this.Template) {
664
+ // ngOnChanges runs first and has usually started the load for this Template already.
665
+ if (this.Template && this.loadStartedFor !== this.Template) {
624
666
  await this.LoadTemplateContents();
625
667
  }
626
668
  }
@@ -647,13 +689,16 @@ export class TemplateEditorComponent extends BaseAngularComponent {
647
689
  });
648
690
  }
649
691
  async ngOnChanges(changes) {
650
- if (changes['template']) {
692
+ // Hosts bind either the Template input or its deprecated `template` alias; Angular reports
693
+ // the change under whichever name was bound.
694
+ if (changes['Template'] || changes['template']) {
651
695
  // Template input has changed, reload contents
652
696
  if (this.Template) {
653
697
  await this.LoadTemplateContents();
654
698
  }
655
699
  else {
656
700
  // Template cleared, reset state
701
+ this.ContentsLoadState = 'idle';
657
702
  this.TemplateContents = [];
658
703
  this.SelectedContentIndex = 0;
659
704
  this.IsAddingNewContent = false;
@@ -717,43 +762,84 @@ export class TemplateEditorComponent extends BaseAngularComponent {
717
762
  // Initial sync when view is ready
718
763
  this.syncEditorValue();
719
764
  }
765
+ /**
766
+ * (Re)loads the contents of the bound Template and emits them through {@link ContentChange}.
767
+ * This editor owns those rows: a host form folds them into its own save through
768
+ * {@link GetPendingChanges} (or calls {@link SaveTemplateContents}) rather than loading and saving
769
+ * a copy of its own. If several loads overlap, only the latest one applies.
770
+ */
720
771
  async LoadTemplateContents() {
721
- if (this.Template) {
722
- // Reset state first
723
- this.TemplateContents = [];
724
- this.SelectedContentIndex = 0;
725
- this.IsAddingNewContent = false;
726
- this.NewTemplateContent = null;
727
- this.HasUnsavedChanges = false;
728
- if (this.Template.IsSaved && this.Template.ID) {
729
- // Load existing template contents for saved templates
730
- try {
731
- const rv = RunView.FromMetadataProvider(this.ProviderToUse);
732
- const results = await rv.RunView({
733
- EntityName: 'MJ: Template Contents',
734
- ExtraFilter: `TemplateID='${this.Template.ID}'`,
735
- OrderBy: 'Priority ASC, __mj_CreatedAt ASC',
736
- ResultType: 'entity_object'
737
- });
738
- this.TemplateContents = results.Results;
739
- }
740
- catch (error) {
741
- console.error('Error loading template contents:', error);
742
- }
743
- }
744
- // If we have contents but no selection, select the first one
745
- if (this.TemplateContents.length > 0) {
746
- this.SelectedContentIndex = 0;
772
+ const template = this.Template;
773
+ if (!template) {
774
+ return;
775
+ }
776
+ const generation = ++this.loadGeneration;
777
+ this.loadStartedFor = template;
778
+ this.ContentsLoadState = 'loading';
779
+ this.TemplateContents = [];
780
+ this.SelectedContentIndex = 0;
781
+ this.IsAddingNewContent = false;
782
+ this.NewTemplateContent = null;
783
+ this.HasUnsavedChanges = false;
784
+ const loaded = await this.fetchTemplateContents(template);
785
+ if (generation !== this.loadGeneration) {
786
+ return; // superseded by a newer load: its outcome, failure included, is not the user's
787
+ }
788
+ if ('failure' in loaded) {
789
+ // No default row and no empty state over a failed read: either would invite the user to
790
+ // create a row over contents we simply could not see. The template shows a retry instead.
791
+ this.reportLoadFailure(template, loaded.failure);
792
+ this.ContentsLoadState = 'failed';
793
+ // Hosts mirror the rows from ContentChange; tell them the rows they hold are gone.
794
+ this.ContentChange.emit(this.TemplateContents);
795
+ return;
796
+ }
797
+ // A saved template with no rows (or a new template) gets one default row, so the
798
+ // single-content case needs no "add" click.
799
+ let contents = loaded.rows;
800
+ if (contents.length === 0) {
801
+ const defaultContent = await this.buildDefaultTemplateContent(template);
802
+ if (generation !== this.loadGeneration) {
803
+ return;
747
804
  }
748
- // If no template contents exist (either new template or saved template with no content),
749
- // create a default one for single-content optimization
750
- if (this.TemplateContents.length === 0) {
751
- await this.CreateDefaultTemplateContent();
805
+ contents = [defaultContent];
806
+ }
807
+ this.TemplateContents = contents;
808
+ this.ContentsLoadState = 'loaded';
809
+ this.syncEditorValue();
810
+ this.ContentChange.emit(this.TemplateContents);
811
+ }
812
+ reportLoadFailure(template, failure) {
813
+ console.error(`Failed to load template contents for template ${template.ID}: ${failure}`);
814
+ this.notificationService.CreateSimpleNotification(`Failed to load template contents: ${failure}`, 'error', 5000);
815
+ }
816
+ /**
817
+ * Reads the saved contents of a template: no rows for a template that is not saved yet, and the
818
+ * failure message when the read fails. It does not report the failure: only the caller knows
819
+ * whether this read is still the one the screen is waiting for.
820
+ */
821
+ async fetchTemplateContents(template) {
822
+ if (!template.IsSaved || !template.ID) {
823
+ return { rows: [] };
824
+ }
825
+ let failure;
826
+ try {
827
+ const rv = RunView.FromMetadataProvider(this.ProviderToUse);
828
+ const result = await rv.RunView({
829
+ EntityName: 'MJ: Template Contents',
830
+ ExtraFilter: `TemplateID='${EscapeSQLString(template.ID)}'`,
831
+ OrderBy: 'Priority ASC, __mj_CreatedAt ASC',
832
+ ResultType: 'entity_object'
833
+ });
834
+ if (result.Success) {
835
+ return { rows: result.Results };
752
836
  }
753
- // Sync editor value after loading content
754
- this.syncEditorValue();
755
- this.ContentChange.emit(this.TemplateContents);
837
+ failure = result.ErrorMessage || 'unknown error';
838
+ }
839
+ catch (error) {
840
+ failure = error instanceof Error ? error.message : String(error);
756
841
  }
842
+ return { failure };
757
843
  }
758
844
  /** @deprecated Use {@link LoadTemplateContents}. */
759
845
  async loadTemplateContents() {
@@ -771,19 +857,26 @@ export class TemplateEditorComponent extends BaseAngularComponent {
771
857
  return this.RefreshAndDiscardChanges();
772
858
  }
773
859
  async CreateDefaultTemplateContent() {
860
+ if (!this.Template) {
861
+ throw new Error('TemplateEditorComponent.CreateDefaultTemplateContent: no Template is bound');
862
+ }
863
+ this.TemplateContents = [await this.buildDefaultTemplateContent(this.Template)];
864
+ this.SelectedContentIndex = 0;
865
+ // Sync editor value after creating default content
866
+ this.syncEditorValue();
867
+ }
868
+ /** Builds (does not save) the single content row a template starts with. */
869
+ async buildDefaultTemplateContent(template) {
774
870
  const defaultContent = await this._metadata.GetEntityObject('MJ: Template Contents');
775
- defaultContent.TemplateID = this.Template.ID;
871
+ defaultContent.TemplateID = template.ID;
776
872
  defaultContent.Priority = 1;
777
873
  defaultContent.IsActive = true;
778
874
  // Set default to first real content type (skip "Select Type..." if it exists)
779
- const validContentTypes = this.ContentTypeOptions.filter(option => option.value !== '');
875
+ const validContentTypes = this.GetContentTypeOptionsForContent();
780
876
  if (validContentTypes.length > 0) {
781
877
  defaultContent.TypeID = validContentTypes[0].value;
782
878
  }
783
- this.TemplateContents = [defaultContent];
784
- this.SelectedContentIndex = 0;
785
- // Sync editor value after creating default content
786
- this.syncEditorValue();
879
+ return defaultContent;
787
880
  }
788
881
  /** @deprecated Use {@link CreateDefaultTemplateContent}. */
789
882
  async createDefaultTemplateContent() {
@@ -836,9 +929,16 @@ export class TemplateEditorComponent extends BaseAngularComponent {
836
929
  return this.LoadContentTypes();
837
930
  }
838
931
  async AddNewTemplateContent() {
839
- if (!this.config.allowEdit)
932
+ // While a load is in flight (or after it failed) TemplateContents is a placeholder: a row
933
+ // pushed onto it would vanish when the load lands. Re-checked after the await below.
934
+ if (!this.config.allowEdit || this.ContentsLoadState !== 'loaded')
840
935
  return;
841
- this.NewTemplateContent = await this._metadata.GetEntityObject('MJ: Template Contents');
936
+ const generation = this.loadGeneration;
937
+ const newContent = await this._metadata.GetEntityObject('MJ: Template Contents');
938
+ if (this.ContentsLoadState !== 'loaded' || generation !== this.loadGeneration) {
939
+ return;
940
+ }
941
+ this.NewTemplateContent = newContent;
842
942
  this.NewTemplateContent.TemplateID = this.Template.ID;
843
943
  this.NewTemplateContent.Priority = this.TemplateContents.length + 1;
844
944
  this.NewTemplateContent.IsActive = true;
@@ -995,26 +1095,27 @@ export class TemplateEditorComponent extends BaseAngularComponent {
995
1095
  }, 0);
996
1096
  });
997
1097
  }
1098
+ /**
1099
+ * Persists the new and changed content rows — the same instances the user edited here — in one
1100
+ * transaction. Every failure is logged and shown to the user; the caller gets `false`.
1101
+ */
998
1102
  async SaveTemplateContents() {
999
1103
  if (!this.config.allowEdit)
1000
1104
  return false;
1105
+ const template = this.Template;
1106
+ if (!template) {
1107
+ console.error('TemplateEditorComponent.SaveTemplateContents: no Template is bound, nothing to save the contents against');
1108
+ return false;
1109
+ }
1001
1110
  try {
1002
- // Ensure FK is set on all contents, then persist the dirty/new ones atomically
1111
+ // Ensure FK is set on all contents (a new template only has its ID once it is saved),
1112
+ // then persist the dirty/new ones atomically
1003
1113
  for (const content of this.TemplateContents) {
1004
- content.TemplateID = this.Template.ID;
1114
+ content.TemplateID = template.ID;
1005
1115
  }
1006
1116
  const toSave = this.TemplateContents.filter(c => c.Dirty || !c.ID);
1007
- if (toSave.length > 0) {
1008
- const tg = await this._metadata.CreateTransactionGroup();
1009
- for (const content of toSave) {
1010
- content.TransactionGroup = tg;
1011
- await content.Save();
1012
- }
1013
- const success = await tg.Submit();
1014
- if (!success) {
1015
- console.error('Failed to save template contents transaction');
1016
- return false;
1017
- }
1117
+ if (toSave.length > 0 && !(await this.submitTemplateContents(template, toSave))) {
1118
+ return false;
1018
1119
  }
1019
1120
  this.IsAddingNewContent = false;
1020
1121
  this.NewTemplateContent = null;
@@ -1023,10 +1124,48 @@ export class TemplateEditorComponent extends BaseAngularComponent {
1023
1124
  return true;
1024
1125
  }
1025
1126
  catch (error) {
1026
- console.error('Error saving template contents:', error);
1127
+ this.reportSaveFailure(template, error instanceof Error ? error.message : String(error));
1027
1128
  return false;
1028
1129
  }
1029
1130
  }
1131
+ async submitTemplateContents(template, toSave) {
1132
+ const tg = await this._metadata.CreateTransactionGroup();
1133
+ try {
1134
+ for (const content of toSave) {
1135
+ content.TransactionGroup = tg;
1136
+ // Inside a transaction group Save() only queues the row; false here means it was
1137
+ // refused before queueing (e.g. validation).
1138
+ if (!(await content.Save())) {
1139
+ this.reportSaveFailure(template, this.describeContentFailure(content));
1140
+ return false;
1141
+ }
1142
+ }
1143
+ if (await tg.Submit()) {
1144
+ return true;
1145
+ }
1146
+ const failed = toSave.filter(c => c.LatestResult && !c.LatestResult.Success);
1147
+ this.reportSaveFailure(template, failed.length > 0
1148
+ ? failed.map(c => this.describeContentFailure(c)).join('; ')
1149
+ : 'the transaction was rejected');
1150
+ return false;
1151
+ }
1152
+ finally {
1153
+ // A row that keeps this group would send its next Delete() into a completed group, which
1154
+ // reports success without sending anything (the version would come back on reload).
1155
+ for (const content of toSave) {
1156
+ if (content.TransactionGroup === tg) {
1157
+ content.TransactionGroup = null;
1158
+ }
1159
+ }
1160
+ }
1161
+ }
1162
+ describeContentFailure(content) {
1163
+ return `content ${content.ID || '(new)'}: ${content.LatestResult?.CompleteMessage || 'unknown error'}`;
1164
+ }
1165
+ reportSaveFailure(template, detail) {
1166
+ console.error(`Failed to save template contents for template ${template.ID}: ${detail}`);
1167
+ this.notificationService.CreateSimpleNotification(`Failed to save template contents: ${detail}`, 'error', 5000);
1168
+ }
1030
1169
  /**
1031
1170
  * The content rows a HOST FORM should persist inside its own save: every content that is new or
1032
1171
  * dirty, each stamped with the template's ID. Forms that embed this editor (Templates, AI Prompts)
@@ -1148,15 +1287,15 @@ export class TemplateEditorComponent extends BaseAngularComponent {
1148
1287
  } if (rf & 2) {
1149
1288
  let _t;
1150
1289
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.CodeEditor = _t.first);
1151
- } }, inputs: { Template: "Template", template: "template", config: "config" }, outputs: { ContentChange: "ContentChange", contentChange: "contentChange", RunTemplate: "RunTemplate", runTemplate: "runTemplate" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, 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) {
1152
- i0.ɵɵconditionalCreate(0, TemplateEditorComponent_Conditional_0_Template, 4, 2, "div", 1);
1290
+ } }, inputs: { Template: "Template", template: "template", config: "config" }, outputs: { ContentChange: "ContentChange", contentChange: "contentChange", RunTemplate: "RunTemplate", runTemplate: "runTemplate" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 1, vars: 1, consts: [["codeEditor", ""], [1, "template-editor", 2, "height", "100%", "display", "flex", "flex-direction", "column"], ["text", "Loading template contents...", "size", "medium"], [1, "contents-load-failed"], [1, "fa-solid", "fa-triangle-exclamation"], ["type", "button", "mjButton", "", "variant", "secondary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-rotate-right"], [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) {
1291
+ i0.ɵɵconditionalCreate(0, TemplateEditorComponent_Conditional_0_Template, 4, 1, "div", 1);
1153
1292
  } if (rf & 2) {
1154
1293
  i0.ɵɵconditional(ctx.template ? 0 : -1);
1155
- } }, dependencies: [i3.CheckboxControlValueAccessor, i3.NgControlStatus, i3.NgModel, i2.MJDropdownComponent, i2.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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}"] }); }
1294
+ } }, dependencies: [i3.CheckboxControlValueAccessor, i3.NgControlStatus, i3.NgModel, i2.MJButtonDirective, i2.MJDropdownComponent, i2.MJNumericInputComponent, i4.CodeEditorComponent, i5.LoadingComponent], 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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.no-content-state[_ngcontent-%COMP%], \n.contents-load-failed[_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.contents-load-failed[_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.contents-load-failed[_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.contents-load-failed[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n margin-bottom: 20px;\n}\n\n.contents-load-failed[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n}\n\n\n.contents-load-failed[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n opacity: 1;\n}"] }); }
1156
1295
  }
1157
1296
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TemplateEditorComponent, [{
1158
1297
  type: Component,
1159
- 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 Scoped prompt parts can use the Date &amp; Time, User Context and Environment placeholders, written alone with no filter. A part is not a template: everything else in it is sent as written.\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"] }]
1298
+ args: [{ standalone: false, selector: 'mj-template-editor', template: "@if (template) {\n <div class=\"template-editor\" style=\"height: 100%; display: flex; flex-direction: column;\">\n @if (ContentsLoadState === 'loading') {\n <mj-loading text=\"Loading template contents...\" size=\"medium\"></mj-loading>\n } @else if (ContentsLoadState === 'failed') {\n <!-- The read failed: the template's contents are unknown, so neither \"no content\" nor \"create\" -->\n <div class=\"contents-load-failed\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <h5>Template contents could not be loaded</h5>\n <p>Nothing is shown so nothing can be saved over contents that were not read.</p>\n <button type=\"button\" mjButton variant=\"secondary\" size=\"sm\" (click)=\"RefreshAndDiscardChanges()\">\n <i class=\"fa-solid fa-rotate-right\"></i> Retry\n </button>\n </div>\n } @else {\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 <!-- From TypeID (what the Content Type dropdown edits); the view-joined Type field is only refreshed on reload -->\n {{ content.TypeID ? GetContentTypeDisplayText(content.TypeID) : '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 Scoped prompt parts can use the Date &amp; Time, User Context and Environment placeholders, written alone with no filter. A part is not a template: everything else in it is sent as written.\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 }\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, and the failed-read state that must not look like it */\n.no-content-state,\n.contents-load-failed {\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.contents-load-failed > 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.contents-load-failed h5 {\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.no-content-state p,\n.contents-load-failed p {\n color: var(--mj-text-muted);\n margin-bottom: 20px;\n}\n\n.contents-load-failed {\n border-color: var(--mj-status-error);\n}\n\n/* Only the panel's own icon: the Retry button's icon keeps the button's size and colour */\n.contents-load-failed > i {\n color: var(--mj-status-error);\n opacity: 1;\n}\n"] }]
1160
1299
  }], () => [{ type: i1.MJNotificationService }, { type: i2.MJConfirmService }], { Template: [{
1161
1300
  type: Input
1162
1301
  }], template: [{