@memberjunction/ng-dashboards 5.38.0 → 5.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/README.md +14 -7
  2. package/dist/AI/components/agents/agent-configuration.component.js +199 -198
  3. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  4. package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
  5. package/dist/AI/components/analytics/ai-analytics-resource.component.js +20 -17
  6. package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
  7. package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +15 -0
  8. package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -1
  9. package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +166 -58
  10. package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
  11. package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -1
  12. package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +2 -1
  13. package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -1
  14. package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +1 -0
  15. package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -1
  16. package/dist/AI/components/analytics/model-performance/model-performance.component.js +55 -36
  17. package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -1
  18. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +9 -1
  19. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -1
  20. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +158 -117
  21. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -1
  22. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +1 -0
  23. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -1
  24. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +22 -8
  25. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
  26. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +89 -856
  27. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  28. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +1353 -7841
  29. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  30. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts +87 -0
  31. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts.map +1 -0
  32. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js +475 -0
  33. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js.map +1 -0
  34. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts +29 -0
  35. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts.map +1 -0
  36. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js +208 -0
  37. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js.map +1 -0
  38. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts +21 -0
  39. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts.map +1 -0
  40. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js +70 -0
  41. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js.map +1 -0
  42. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts +235 -0
  43. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -0
  44. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +1735 -0
  45. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -0
  46. package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts +61 -0
  47. package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts.map +1 -0
  48. package/dist/AI/components/autotagging/shared/classify.dryrun.js +78 -0
  49. package/dist/AI/components/autotagging/shared/classify.dryrun.js.map +1 -0
  50. package/dist/AI/components/autotagging/shared/classify.format.d.ts +43 -0
  51. package/dist/AI/components/autotagging/shared/classify.format.d.ts.map +1 -0
  52. package/dist/AI/components/autotagging/shared/classify.format.js +209 -0
  53. package/dist/AI/components/autotagging/shared/classify.format.js.map +1 -0
  54. package/dist/AI/components/autotagging/shared/classify.types.d.ts +276 -0
  55. package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -0
  56. package/dist/AI/components/autotagging/shared/classify.types.js +6 -0
  57. package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -0
  58. package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts +103 -0
  59. package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts.map +1 -0
  60. package/dist/AI/components/autotagging/tabs/health-tab.component.js +571 -0
  61. package/dist/AI/components/autotagging/tabs/health-tab.component.js.map +1 -0
  62. package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts +40 -0
  63. package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts.map +1 -0
  64. package/dist/AI/components/autotagging/tabs/history-tab.component.js +402 -0
  65. package/dist/AI/components/autotagging/tabs/history-tab.component.js.map +1 -0
  66. package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts +107 -0
  67. package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts.map +1 -0
  68. package/dist/AI/components/autotagging/tabs/inbox-tab.component.js +719 -0
  69. package/dist/AI/components/autotagging/tabs/inbox-tab.component.js.map +1 -0
  70. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts +122 -0
  71. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts.map +1 -0
  72. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js +752 -0
  73. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js.map +1 -0
  74. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +166 -0
  75. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -0
  76. package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1384 -0
  77. package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -0
  78. package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts +70 -0
  79. package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts.map +1 -0
  80. package/dist/AI/components/autotagging/tabs/tags-tab.component.js +448 -0
  81. package/dist/AI/components/autotagging/tabs/tags-tab.component.js.map +1 -0
  82. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts +397 -0
  83. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts.map +1 -0
  84. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js +3490 -0
  85. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js.map +1 -0
  86. package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts +47 -0
  87. package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts.map +1 -0
  88. package/dist/AI/components/autotagging/tabs/types-tab.component.js +220 -0
  89. package/dist/AI/components/autotagging/tabs/types-tab.component.js.map +1 -0
  90. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +293 -289
  91. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  92. package/dist/AI/components/models/model-management.component.js +209 -208
  93. package/dist/AI/components/models/model-management.component.js.map +1 -1
  94. package/dist/AI/components/prompts/prompt-management.component.js +130 -128
  95. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  96. package/dist/AI/components/requests/agent-requests-resource.component.js +61 -61
  97. package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
  98. package/dist/AI/components/system/system-configuration.component.js +17 -17
  99. package/dist/AI/components/system/system-configuration.component.js.map +1 -1
  100. package/dist/AI/components/tags/tags-resource.component.js +550 -532
  101. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  102. package/dist/AI/components/vectors/vector-management-resource.component.js +1 -1
  103. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  104. package/dist/AI/services/ai-instrumentation.service.d.ts +5 -0
  105. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
  106. package/dist/AI/services/ai-instrumentation.service.js +14 -2
  107. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  108. package/dist/AI/services/cache-metrics.d.ts +50 -0
  109. package/dist/AI/services/cache-metrics.d.ts.map +1 -0
  110. package/dist/AI/services/cache-metrics.js +43 -0
  111. package/dist/AI/services/cache-metrics.js.map +1 -0
  112. package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
  113. package/dist/APIKeys/api-keys-resource.component.js +132 -131
  114. package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
  115. package/dist/Actions/components/actions-overview.component.js +141 -141
  116. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  117. package/dist/Actions/components/execution-monitoring.component.js +15 -15
  118. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  119. package/dist/Actions/components/explorer/action-explorer.component.d.ts +0 -5
  120. package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
  121. package/dist/Actions/components/explorer/action-explorer.component.js +139 -212
  122. package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
  123. package/dist/Admin/admin-data-schema.component.js +2 -2
  124. package/dist/Admin/admin-data-schema.component.js.map +1 -1
  125. package/dist/Admin/admin-dev-tools-resource.component.js +2 -2
  126. package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
  127. package/dist/Admin/admin-identity-access.component.js +2 -2
  128. package/dist/Admin/admin-identity-access.component.js.map +1 -1
  129. package/dist/Admin/admin-monitoring.component.js +2 -2
  130. package/dist/Admin/admin-monitoring.component.js.map +1 -1
  131. package/dist/ApplicationRoles/application-roles-resource.component.js +54 -49
  132. package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
  133. package/dist/Communication/communication-logs-resource.component.d.ts +6 -0
  134. package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
  135. package/dist/Communication/communication-logs-resource.component.js +72 -50
  136. package/dist/Communication/communication-logs-resource.component.js.map +1 -1
  137. package/dist/Communication/communication-monitor-resource.component.js +103 -102
  138. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  139. package/dist/Communication/communication-providers-resource.component.js +52 -51
  140. package/dist/Communication/communication-providers-resource.component.js.map +1 -1
  141. package/dist/Communication/communication-runs-resource.component.js +39 -38
  142. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  143. package/dist/Communication/communication-templates-resource.component.d.ts +6 -0
  144. package/dist/Communication/communication-templates-resource.component.d.ts.map +1 -1
  145. package/dist/Communication/communication-templates-resource.component.js +92 -89
  146. package/dist/Communication/communication-templates-resource.component.js.map +1 -1
  147. package/dist/Credentials/components/credentials-audit-resource.component.js +136 -135
  148. package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
  149. package/dist/Credentials/components/credentials-categories-resource.component.js +155 -152
  150. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  151. package/dist/Credentials/components/credentials-list-resource.component.js +119 -118
  152. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  153. package/dist/Credentials/components/credentials-overview-resource.component.js +129 -128
  154. package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
  155. package/dist/Credentials/components/credentials-types-resource.component.js +107 -106
  156. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  157. package/dist/DataExplorer/data-explorer-dashboard.component.js +2 -2
  158. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  159. package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +1 -1
  160. package/dist/DatabaseDesigner/components/entity-list.component.js +115 -114
  161. package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
  162. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +5 -6
  163. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
  164. package/dist/DatabaseDesigner/database-designer-dashboards.module.js +4 -5
  165. package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
  166. package/dist/DevTools/app-state-inspector.component.js +18 -17
  167. package/dist/DevTools/app-state-inspector.component.js.map +1 -1
  168. package/dist/DevTools/class-registry.component.js +88 -85
  169. package/dist/DevTools/class-registry.component.js.map +1 -1
  170. package/dist/DevTools/event-monitor.component.js +155 -150
  171. package/dist/DevTools/event-monitor.component.js.map +1 -1
  172. package/dist/DevTools/graphql-console.component.js +245 -243
  173. package/dist/DevTools/graphql-console.component.js.map +1 -1
  174. package/dist/DevTools/layout-inspector.component.js +18 -17
  175. package/dist/DevTools/layout-inspector.component.js.map +1 -1
  176. package/dist/EntityAdmin/entity-admin-dashboard.component.js +20 -19
  177. package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
  178. package/dist/Home/home-dashboard.component.js +2 -2
  179. package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
  180. package/dist/Integration/components/activity/activity.component.js +236 -229
  181. package/dist/Integration/components/activity/activity.component.js.map +1 -1
  182. package/dist/Integration/components/connections/connections.component.js +390 -389
  183. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  184. package/dist/Integration/components/overview/overview.component.js +2 -2
  185. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +2 -2
  186. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
  187. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +45 -44
  188. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
  189. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +293 -291
  190. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  191. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +62 -61
  192. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
  193. package/dist/Lists/components/lists-browse-resource.component.d.ts +6 -2
  194. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  195. package/dist/Lists/components/lists-browse-resource.component.js +525 -566
  196. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  197. package/dist/Lists/components/lists-categories-resource.component.js +135 -134
  198. package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
  199. package/dist/Lists/components/lists-my-lists-resource.component.js +199 -198
  200. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  201. package/dist/MCP/mcp-dashboard.component.js +443 -438
  202. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  203. package/dist/Scheduling/components/scheduling-activity.component.d.ts.map +1 -1
  204. package/dist/Scheduling/components/scheduling-activity.component.js +146 -147
  205. package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
  206. package/dist/Scheduling/components/scheduling-jobs.component.js +76 -75
  207. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  208. package/dist/Scheduling/components/scheduling-overview.component.js +97 -96
  209. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  210. package/dist/Scheduling/scheduling-dashboard.component.js +24 -22
  211. package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
  212. package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts +2 -0
  213. package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
  214. package/dist/Scheduling/services/scheduling-instrumentation.service.js +1 -0
  215. package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
  216. package/dist/Testing/components/testing-dashboard-tab-resource.component.js +1 -1
  217. package/dist/Testing/components/testing-explorer.component.d.ts +14 -4
  218. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  219. package/dist/Testing/components/testing-explorer.component.js +436 -427
  220. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  221. package/dist/Testing/components/testing-runs-resource.component.js +1 -1
  222. package/dist/Testing/components/testing-runs.component.js +116 -115
  223. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  224. package/dist/Testing/testing-dashboard.component.js +6 -7
  225. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  226. package/dist/VersionHistory/components/labels-resource.component.js +173 -172
  227. package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
  228. package/dist/VersionHistory/components/restore-resource.component.d.ts +6 -0
  229. package/dist/VersionHistory/components/restore-resource.component.d.ts.map +1 -1
  230. package/dist/VersionHistory/components/restore-resource.component.js +116 -92
  231. package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
  232. package/dist/ai-dashboards.module.d.ts +47 -35
  233. package/dist/ai-dashboards.module.d.ts.map +1 -1
  234. package/dist/ai-dashboards.module.js +40 -1
  235. package/dist/ai-dashboards.module.js.map +1 -1
  236. package/dist/communication-dashboards.module.d.ts +1 -1
  237. package/dist/communication-dashboards.module.d.ts.map +1 -1
  238. package/dist/communication-dashboards.module.js +7 -1
  239. package/dist/communication-dashboards.module.js.map +1 -1
  240. package/dist/testing-dashboards.module.d.ts +4 -5
  241. package/dist/testing-dashboards.module.d.ts.map +1 -1
  242. package/dist/testing-dashboards.module.js +7 -5
  243. package/dist/testing-dashboards.module.js.map +1 -1
  244. package/package.json +55 -54
@@ -13,74 +13,52 @@ import * as i1 from "@memberjunction/ng-shared";
13
13
  import * as i2 from "@memberjunction/ng-shared-generic";
14
14
  import * as i3 from "@memberjunction/ng-ui-components";
15
15
  import * as i4 from "@angular/common";
16
- function CommunicationTemplatesResourceComponent_Conditional_8_For_2_Template(rf, ctx) { if (rf & 1) {
17
- const _r3 = i0.ɵɵgetCurrentView();
18
- i0.ɵɵelementStart(0, "mj-filter-chip", 10);
19
- i0.ɵɵlistener("Clicked", function CommunicationTemplatesResourceComponent_Conditional_8_For_2_Template_mj_filter_chip_Clicked_0_listener() { const cat_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onCategoryFilter(cat_r4)); });
20
- i0.ɵɵelementEnd();
21
- } if (rf & 2) {
22
- const cat_r4 = ctx.$implicit;
23
- const ctx_r1 = i0.ɵɵnextContext(2);
24
- i0.ɵɵproperty("Label", cat_r4)("Count", ctx_r1.getCategoryCount(cat_r4))("Active", ctx_r1.categoryFilter === cat_r4);
25
- } }
26
- function CommunicationTemplatesResourceComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
27
- const _r1 = i0.ɵɵgetCurrentView();
28
- i0.ɵɵelementStart(0, "mj-filter-chip", 8);
29
- i0.ɵɵlistener("Clicked", function CommunicationTemplatesResourceComponent_Conditional_8_Template_mj_filter_chip_Clicked_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCategoryFilter("")); });
30
- i0.ɵɵelementEnd();
31
- i0.ɵɵrepeaterCreate(1, CommunicationTemplatesResourceComponent_Conditional_8_For_2_Template, 1, 3, "mj-filter-chip", 9, i0.ɵɵrepeaterTrackByIdentity);
32
- } if (rf & 2) {
33
- const ctx_r1 = i0.ɵɵnextContext();
34
- i0.ɵɵproperty("Count", ctx_r1.allTemplates.length)("Active", ctx_r1.categoryFilter === "");
35
- i0.ɵɵadvance();
36
- i0.ɵɵrepeater(ctx_r1.categories);
37
- } }
38
- function CommunicationTemplatesResourceComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
39
- i0.ɵɵelementStart(0, "div", 6);
16
+ function CommunicationTemplatesResourceComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
17
+ i0.ɵɵelementStart(0, "div", 9);
40
18
  i0.ɵɵelement(1, "mj-loading", 11);
41
19
  i0.ɵɵelementEnd();
42
20
  } }
43
- function CommunicationTemplatesResourceComponent_Conditional_11_For_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
21
+ function CommunicationTemplatesResourceComponent_Conditional_13_For_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
44
22
  i0.ɵɵelementStart(0, "div", 21);
45
23
  i0.ɵɵtext(1);
46
24
  i0.ɵɵelementEnd();
47
25
  } if (rf & 2) {
48
- const card_r6 = i0.ɵɵnextContext().$implicit;
26
+ const card_r2 = i0.ɵɵnextContext().$implicit;
49
27
  i0.ɵɵadvance();
50
- i0.ɵɵtextInterpolate1(" ", card_r6.Entity.Description, " ");
28
+ i0.ɵɵtextInterpolate1(" ", card_r2.Entity.Description, " ");
51
29
  } }
52
- function CommunicationTemplatesResourceComponent_Conditional_11_For_2_For_13_Template(rf, ctx) { if (rf & 1) {
30
+ function CommunicationTemplatesResourceComponent_Conditional_13_For_2_For_13_Template(rf, ctx) { if (rf & 1) {
53
31
  i0.ɵɵelementStart(0, "span", 24);
54
32
  i0.ɵɵelement(1, "i");
55
33
  i0.ɵɵtext(2);
56
34
  i0.ɵɵelementEnd();
57
35
  } if (rf & 2) {
58
- const ct_r7 = ctx.$implicit;
59
- const ctx_r1 = i0.ɵɵnextContext(3);
36
+ const ct_r4 = ctx.$implicit;
37
+ const ctx_r2 = i0.ɵɵnextContext(3);
60
38
  i0.ɵɵadvance();
61
- i0.ɵɵclassMap(ctx_r1.getContentTypeIcon(ct_r7));
39
+ i0.ɵɵclassMap(ctx_r2.getContentTypeIcon(ct_r4));
62
40
  i0.ɵɵadvance();
63
- i0.ɵɵtextInterpolate1(" ", ct_r7, " ");
41
+ i0.ɵɵtextInterpolate1(" ", ct_r4, " ");
64
42
  } }
65
- function CommunicationTemplatesResourceComponent_Conditional_11_For_2_Conditional_14_Template(rf, ctx) { if (rf & 1) {
43
+ function CommunicationTemplatesResourceComponent_Conditional_13_For_2_Conditional_14_Template(rf, ctx) { if (rf & 1) {
66
44
  i0.ɵɵelementStart(0, "span", 25);
67
45
  i0.ɵɵtext(1, " No content ");
68
46
  i0.ɵɵelementEnd();
69
47
  } }
70
- function CommunicationTemplatesResourceComponent_Conditional_11_For_2_Conditional_15_Template(rf, ctx) { if (rf & 1) {
48
+ function CommunicationTemplatesResourceComponent_Conditional_13_For_2_Conditional_15_Template(rf, ctx) { if (rf & 1) {
71
49
  i0.ɵɵelementStart(0, "div", 26);
72
50
  i0.ɵɵtext(1);
73
51
  i0.ɵɵpipe(2, "date");
74
52
  i0.ɵɵelementEnd();
75
53
  } if (rf & 2) {
76
- const card_r6 = i0.ɵɵnextContext().$implicit;
54
+ const card_r2 = i0.ɵɵnextContext().$implicit;
77
55
  i0.ɵɵadvance();
78
- i0.ɵɵtextInterpolate1(" Updated ", i0.ɵɵpipeBind2(2, 1, card_r6.LastUpdated, "mediumDate"), " ");
56
+ i0.ɵɵtextInterpolate1(" Updated ", i0.ɵɵpipeBind2(2, 1, card_r2.LastUpdated, "mediumDate"), " ");
79
57
  } }
80
- function CommunicationTemplatesResourceComponent_Conditional_11_For_2_Template(rf, ctx) { if (rf & 1) {
81
- const _r5 = i0.ɵɵgetCurrentView();
58
+ function CommunicationTemplatesResourceComponent_Conditional_13_For_2_Template(rf, ctx) { if (rf & 1) {
59
+ const _r1 = i0.ɵɵgetCurrentView();
82
60
  i0.ɵɵelementStart(0, "div", 14);
83
- i0.ɵɵlistener("click", function CommunicationTemplatesResourceComponent_Conditional_11_For_2_Template_div_click_0_listener() { const card_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.openTemplate(card_r6.Entity)); });
61
+ i0.ɵɵlistener("click", function CommunicationTemplatesResourceComponent_Conditional_13_For_2_Template_div_click_0_listener() { const card_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.openTemplate(card_r2.Entity)); });
84
62
  i0.ɵɵelementStart(1, "div", 15)(2, "div", 16);
85
63
  i0.ɵɵelement(3, "i", 17);
86
64
  i0.ɵɵelementEnd();
@@ -90,46 +68,46 @@ function CommunicationTemplatesResourceComponent_Conditional_11_For_2_Template(r
90
68
  i0.ɵɵelementStart(7, "div", 20);
91
69
  i0.ɵɵtext(8);
92
70
  i0.ɵɵelementEnd()()();
93
- i0.ɵɵconditionalCreate(9, CommunicationTemplatesResourceComponent_Conditional_11_For_2_Conditional_9_Template, 2, 1, "div", 21);
71
+ i0.ɵɵconditionalCreate(9, CommunicationTemplatesResourceComponent_Conditional_13_For_2_Conditional_9_Template, 2, 1, "div", 21);
94
72
  i0.ɵɵelementStart(10, "div", 22)(11, "div", 23);
95
- i0.ɵɵrepeaterCreate(12, CommunicationTemplatesResourceComponent_Conditional_11_For_2_For_13_Template, 3, 3, "span", 24, i0.ɵɵrepeaterTrackByIdentity);
96
- i0.ɵɵconditionalCreate(14, CommunicationTemplatesResourceComponent_Conditional_11_For_2_Conditional_14_Template, 2, 0, "span", 25);
73
+ i0.ɵɵrepeaterCreate(12, CommunicationTemplatesResourceComponent_Conditional_13_For_2_For_13_Template, 3, 3, "span", 24, i0.ɵɵrepeaterTrackByIdentity);
74
+ i0.ɵɵconditionalCreate(14, CommunicationTemplatesResourceComponent_Conditional_13_For_2_Conditional_14_Template, 2, 0, "span", 25);
97
75
  i0.ɵɵelementEnd();
98
- i0.ɵɵconditionalCreate(15, CommunicationTemplatesResourceComponent_Conditional_11_For_2_Conditional_15_Template, 3, 4, "div", 26);
76
+ i0.ɵɵconditionalCreate(15, CommunicationTemplatesResourceComponent_Conditional_13_For_2_Conditional_15_Template, 3, 4, "div", 26);
99
77
  i0.ɵɵelementEnd()();
100
78
  } if (rf & 2) {
101
- const card_r6 = ctx.$implicit;
79
+ const card_r2 = ctx.$implicit;
102
80
  i0.ɵɵadvance(6);
103
- i0.ɵɵtextInterpolate(card_r6.Entity.Name);
81
+ i0.ɵɵtextInterpolate(card_r2.Entity.Name);
104
82
  i0.ɵɵadvance(2);
105
- i0.ɵɵtextInterpolate(card_r6.CategoryName);
83
+ i0.ɵɵtextInterpolate(card_r2.CategoryName);
106
84
  i0.ɵɵadvance();
107
- i0.ɵɵconditional(card_r6.Entity.Description ? 9 : -1);
85
+ i0.ɵɵconditional(card_r2.Entity.Description ? 9 : -1);
108
86
  i0.ɵɵadvance(3);
109
- i0.ɵɵrepeater(card_r6.ContentTypes);
87
+ i0.ɵɵrepeater(card_r2.ContentTypes);
110
88
  i0.ɵɵadvance(2);
111
- i0.ɵɵconditional(card_r6.ContentTypes.length === 0 ? 14 : -1);
89
+ i0.ɵɵconditional(card_r2.ContentTypes.length === 0 ? 14 : -1);
112
90
  i0.ɵɵadvance();
113
- i0.ɵɵconditional(card_r6.LastUpdated ? 15 : -1);
91
+ i0.ɵɵconditional(card_r2.LastUpdated ? 15 : -1);
114
92
  } }
115
- function CommunicationTemplatesResourceComponent_Conditional_11_Conditional_3_Template(rf, ctx) { if (rf & 1) {
93
+ function CommunicationTemplatesResourceComponent_Conditional_13_Conditional_3_Template(rf, ctx) { if (rf & 1) {
116
94
  i0.ɵɵelementStart(0, "div", 13);
117
95
  i0.ɵɵelement(1, "i", 17);
118
96
  i0.ɵɵelementStart(2, "p");
119
97
  i0.ɵɵtext(3, "No templates found matching your criteria");
120
98
  i0.ɵɵelementEnd()();
121
99
  } }
122
- function CommunicationTemplatesResourceComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
123
- i0.ɵɵelementStart(0, "div", 7);
124
- i0.ɵɵrepeaterCreate(1, CommunicationTemplatesResourceComponent_Conditional_11_For_2_Template, 16, 5, "div", 12, i0.ɵɵrepeaterTrackByIdentity);
125
- i0.ɵɵconditionalCreate(3, CommunicationTemplatesResourceComponent_Conditional_11_Conditional_3_Template, 4, 0, "div", 13);
100
+ function CommunicationTemplatesResourceComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
101
+ i0.ɵɵelementStart(0, "div", 10);
102
+ i0.ɵɵrepeaterCreate(1, CommunicationTemplatesResourceComponent_Conditional_13_For_2_Template, 16, 5, "div", 12, i0.ɵɵrepeaterTrackByIdentity);
103
+ i0.ɵɵconditionalCreate(3, CommunicationTemplatesResourceComponent_Conditional_13_Conditional_3_Template, 4, 0, "div", 13);
126
104
  i0.ɵɵelementEnd();
127
105
  } if (rf & 2) {
128
- const ctx_r1 = i0.ɵɵnextContext();
106
+ const ctx_r2 = i0.ɵɵnextContext();
129
107
  i0.ɵɵadvance();
130
- i0.ɵɵrepeater(ctx_r1.filteredTemplates);
108
+ i0.ɵɵrepeater(ctx_r2.filteredTemplates);
131
109
  i0.ɵɵadvance(2);
132
- i0.ɵɵconditional(ctx_r1.filteredTemplates.length === 0 ? 3 : -1);
110
+ i0.ɵɵconditional(ctx_r2.filteredTemplates.length === 0 ? 3 : -1);
133
111
  } }
134
112
  let CommunicationTemplatesResourceComponent = class CommunicationTemplatesResourceComponent extends BaseResourceComponent {
135
113
  cdr;
@@ -211,6 +189,30 @@ let CommunicationTemplatesResourceComponent = class CommunicationTemplatesResour
211
189
  this.categoryFilter = category;
212
190
  this.applyFilter();
213
191
  }
192
+ // -- Concise chrome: Category lives behind the one Filter popover ---------
193
+ get filterFields() {
194
+ return [{
195
+ key: 'category',
196
+ type: 'chips',
197
+ label: 'Category',
198
+ chipOptions: [
199
+ { text: 'All', value: '' },
200
+ ...this.categories.map(c => ({ text: c, value: c })),
201
+ ],
202
+ }];
203
+ }
204
+ get filterValues() {
205
+ return { category: this.categoryFilter };
206
+ }
207
+ get ActiveFilterCount() {
208
+ return this.categoryFilter ? 1 : 0;
209
+ }
210
+ onFilterValuesChange(values) {
211
+ this.onCategoryFilter(values['category'] ?? '');
212
+ }
213
+ resetFilters() {
214
+ this.onCategoryFilter('');
215
+ }
214
216
  applyFilter() {
215
217
  let filtered = this.allTemplates;
216
218
  if (this.categoryFilter) {
@@ -249,26 +251,32 @@ let CommunicationTemplatesResourceComponent = class CommunicationTemplatesResour
249
251
  return 'fa-solid fa-file-lines';
250
252
  }
251
253
  static ɵfac = function CommunicationTemplatesResourceComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CommunicationTemplatesResourceComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.NavigationService)); };
252
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CommunicationTemplatesResourceComponent, selectors: [["mj-communication-templates-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 12, vars: 2, consts: [["Title", "Templates", "Icon", "fa-solid fa-file-lines", "Subtitle", "Manage reusable message templates"], ["actions", ""], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-plus"], ["toolbar", ""], ["Placeholder", "Search templates...", 3, "ValueChange"], [1, "loading-state"], [1, "templates-grid"], ["Label", "All", 3, "Clicked", "Count", "Active"], [3, "Label", "Count", "Active"], [3, "Clicked", "Label", "Count", "Active"], ["text", "Loading templates..."], [1, "template-card"], [1, "empty-state"], [1, "template-card", 3, "click"], [1, "template-card-header"], [1, "template-icon"], [1, "fa-solid", "fa-file-lines"], [1, "template-title-area"], [1, "template-name"], [1, "template-category"], [1, "template-description"], [1, "template-meta"], [1, "template-content-types"], [1, "content-type-chip"], [1, "content-type-chip", "empty"], [1, "template-updated"]], template: function CommunicationTemplatesResourceComponent_Template(rf, ctx) { if (rf & 1) {
254
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CommunicationTemplatesResourceComponent, selectors: [["mj-communication-templates-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 14, vars: 5, consts: [["Title", "Templates", "Icon", "fa-solid fa-file-lines", "Subtitle", "Manage reusable message templates"], ["actions", ""], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "action-btn-label"], ["toolbar", ""], ["Placeholder", "Search templates...", 3, "ValueChange"], [3, "ClearAllRequested", "ActiveCount", "ShowClearAll"], [3, "ValuesChange", "Reset", "Fields", "Values"], [1, "loading-state"], [1, "templates-grid"], ["text", "Loading templates..."], [1, "template-card"], [1, "empty-state"], [1, "template-card", 3, "click"], [1, "template-card-header"], [1, "template-icon"], [1, "fa-solid", "fa-file-lines"], [1, "template-title-area"], [1, "template-name"], [1, "template-category"], [1, "template-description"], [1, "template-meta"], [1, "template-content-types"], [1, "content-type-chip"], [1, "content-type-chip", "empty"], [1, "template-updated"]], template: function CommunicationTemplatesResourceComponent_Template(rf, ctx) { if (rf & 1) {
253
255
  i0.ɵɵelementStart(0, "mj-page-layout")(1, "mj-page-header", 0)(2, "div", 1)(3, "button", 2);
254
256
  i0.ɵɵlistener("click", function CommunicationTemplatesResourceComponent_Template_button_click_3_listener() { return ctx.addNewTemplate(); });
255
257
  i0.ɵɵelement(4, "i", 3);
256
- i0.ɵɵtext(5, " New Template ");
257
- i0.ɵɵelementEnd()();
258
- i0.ɵɵelementStart(6, "div", 4)(7, "mj-page-search", 5);
259
- i0.ɵɵlistener("ValueChange", function CommunicationTemplatesResourceComponent_Template_mj_page_search_ValueChange_7_listener($event) { return ctx.onSearchValue($event); });
258
+ i0.ɵɵelementStart(5, "span", 4);
259
+ i0.ɵɵtext(6, "New Template");
260
+ i0.ɵɵelementEnd()()();
261
+ i0.ɵɵelementStart(7, "div", 5)(8, "mj-page-search", 6);
262
+ i0.ɵɵlistener("ValueChange", function CommunicationTemplatesResourceComponent_Template_mj_page_search_ValueChange_8_listener($event) { return ctx.onSearchValue($event); });
260
263
  i0.ɵɵelementEnd();
261
- i0.ɵɵconditionalCreate(8, CommunicationTemplatesResourceComponent_Conditional_8_Template, 3, 2);
262
- i0.ɵɵelementEnd()();
263
- i0.ɵɵelementStart(9, "mj-page-body");
264
- i0.ɵɵconditionalCreate(10, CommunicationTemplatesResourceComponent_Conditional_10_Template, 2, 0, "div", 6)(11, CommunicationTemplatesResourceComponent_Conditional_11_Template, 4, 1, "div", 7);
264
+ i0.ɵɵelementStart(9, "mj-filter-popover", 7);
265
+ i0.ɵɵlistener("ClearAllRequested", function CommunicationTemplatesResourceComponent_Template_mj_filter_popover_ClearAllRequested_9_listener() { return ctx.resetFilters(); });
266
+ i0.ɵɵelementStart(10, "mj-filter-panel", 8);
267
+ i0.ɵɵlistener("ValuesChange", function CommunicationTemplatesResourceComponent_Template_mj_filter_panel_ValuesChange_10_listener($event) { return ctx.onFilterValuesChange($event); })("Reset", function CommunicationTemplatesResourceComponent_Template_mj_filter_panel_Reset_10_listener() { return ctx.resetFilters(); });
268
+ i0.ɵɵelementEnd()()()();
269
+ i0.ɵɵelementStart(11, "mj-page-body");
270
+ i0.ɵɵconditionalCreate(12, CommunicationTemplatesResourceComponent_Conditional_12_Template, 2, 0, "div", 9)(13, CommunicationTemplatesResourceComponent_Conditional_13_Template, 4, 1, "div", 10);
265
271
  i0.ɵɵelementEnd()();
266
272
  } if (rf & 2) {
267
- i0.ɵɵadvance(8);
268
- i0.ɵɵconditional(!ctx.isLoading ? 8 : -1);
273
+ i0.ɵɵadvance(9);
274
+ i0.ɵɵproperty("ActiveCount", ctx.ActiveFilterCount)("ShowClearAll", ctx.ActiveFilterCount > 0);
275
+ i0.ɵɵadvance();
276
+ i0.ɵɵproperty("Fields", ctx.filterFields)("Values", ctx.filterValues);
269
277
  i0.ɵɵadvance(2);
270
- i0.ɵɵconditional(ctx.isLoading ? 10 : 11);
271
- } }, dependencies: [i2.LoadingComponent, i3.MJButtonDirective, i3.MJPageHeaderComponent, i3.MJPageLayoutComponent, i3.MJPageBodyComponent, i3.MJPageSearchComponent, i3.MJFilterChipComponent, i4.DatePipe], styles: [".loading-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n \n\n .templates-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 2px 8px var(--mj-shadow-md);\n border-color: var(--mj-border-strong);\n }\n\n .template-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon[_ngcontent-%COMP%] {\n width: 40px; height: 40px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n .template-name[_ngcontent-%COMP%] {\n font-size: 14px; font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n }\n\n .template-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n }\n .content-type-chip.empty[_ngcontent-%COMP%] {\n font-style: italic;\n }\n .template-updated[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n \n\n .empty-state[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mj-text-muted);\n }\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] { margin: 0; font-size: 13px; }"] });
278
+ i0.ɵɵconditional(ctx.isLoading ? 12 : 13);
279
+ } }, dependencies: [i2.LoadingComponent, i3.MJButtonDirective, i3.MJPageHeaderComponent, i3.MJPageLayoutComponent, i3.MJPageBodyComponent, i3.MJPageSearchComponent, i3.MJFilterPopoverComponent, i3.MJFilterPanelComponent, i4.DatePipe], styles: [".loading-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n \n\n .templates-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 2px 8px var(--mj-shadow-md);\n border-color: var(--mj-border-strong);\n }\n\n .template-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon[_ngcontent-%COMP%] {\n width: 40px; height: 40px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n .template-name[_ngcontent-%COMP%] {\n font-size: 14px; font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n }\n\n .template-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n }\n .content-type-chip.empty[_ngcontent-%COMP%] {\n font-style: italic;\n }\n .template-updated[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n \n\n .empty-state[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mj-text-muted);\n }\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] { margin: 0; font-size: 13px; }"] });
272
280
  };
273
281
  CommunicationTemplatesResourceComponent = __decorate([
274
282
  RegisterClass(BaseResourceComponent, 'CommunicationTemplatesResource')
@@ -281,7 +289,7 @@ export { CommunicationTemplatesResourceComponent };
281
289
  <mj-page-header Title="Templates" Icon="fa-solid fa-file-lines" Subtitle="Manage reusable message templates">
282
290
  <div actions>
283
291
  <button mjButton variant="primary" size="sm" (click)="addNewTemplate()">
284
- <i class="fa-solid fa-plus"></i> New Template
292
+ <i class="fa-solid fa-plus"></i> <span class="action-btn-label">New Template</span>
285
293
  </button>
286
294
  </div>
287
295
  <div toolbar>
@@ -289,22 +297,17 @@ export { CommunicationTemplatesResourceComponent };
289
297
  Placeholder="Search templates..."
290
298
  (ValueChange)="onSearchValue($event)">
291
299
  </mj-page-search>
292
- @if (!isLoading) {
293
- <mj-filter-chip
294
- Label="All"
295
- [Count]="allTemplates.length"
296
- [Active]="categoryFilter === ''"
297
- (Clicked)="onCategoryFilter('')">
298
- </mj-filter-chip>
299
- @for (cat of categories; track cat) {
300
- <mj-filter-chip
301
- [Label]="cat"
302
- [Count]="getCategoryCount(cat)"
303
- [Active]="categoryFilter === cat"
304
- (Clicked)="onCategoryFilter(cat)">
305
- </mj-filter-chip>
306
- }
307
- }
300
+ <mj-filter-popover
301
+ [ActiveCount]="ActiveFilterCount"
302
+ [ShowClearAll]="ActiveFilterCount > 0"
303
+ (ClearAllRequested)="resetFilters()">
304
+ <mj-filter-panel
305
+ [Fields]="filterFields"
306
+ [Values]="filterValues"
307
+ (ValuesChange)="onFilterValuesChange($event)"
308
+ (Reset)="resetFilters()">
309
+ </mj-filter-panel>
310
+ </mj-filter-popover>
308
311
  </div>
309
312
  </mj-page-header>
310
313
 
@@ -364,5 +367,5 @@ export { CommunicationTemplatesResourceComponent };
364
367
  </mj-page-layout>
365
368
  `, styles: ["\n .loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n /* GRID */\n .templates-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card:hover {\n box-shadow: 0 2px 8px var(--mj-shadow-md);\n border-color: var(--mj-border-strong);\n }\n\n .template-card-header {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon {\n width: 40px; height: 40px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area { flex: 1; min-width: 0; }\n .template-name {\n font-size: 14px; font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n }\n\n .template-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n }\n .content-type-chip.empty {\n font-style: italic;\n }\n .template-updated {\n font-size: 10px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n /* EMPTY STATE */\n .empty-state {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mj-text-muted);\n }\n .empty-state i { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state p { margin: 0; font-size: 13px; }\n "] }]
366
369
  }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.NavigationService }], null); })();
367
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CommunicationTemplatesResourceComponent, { className: "CommunicationTemplatesResourceComponent", filePath: "src/Communication/communication-templates-resource.component.ts", lineNumber: 206 }); })();
370
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CommunicationTemplatesResourceComponent, { className: "CommunicationTemplatesResourceComponent", filePath: "src/Communication/communication-templates-resource.component.ts", lineNumber: 202 }); })();
368
371
  //# sourceMappingURL=communication-templates-resource.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"communication-templates-resource.component.js","sourceRoot":"","sources":["../../src/Communication/communication-templates-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { ResourceData, MJTemplateEntity, MJTemplateContentEntity } from '@memberjunction/core-entities';\nimport { RegisterClass , UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { Metadata, RunView, CompositeKey } from '@memberjunction/core';\n\ninterface TemplateCardData {\n Entity: MJTemplateEntity;\n ContentTypes: string[];\n LastUpdated: Date | null;\n CategoryName: string;\n}\n@RegisterClass(BaseResourceComponent, 'CommunicationTemplatesResource')\n@Component({\n standalone: false,\n selector: 'mj-communication-templates-resource',\n template: `\n <mj-page-layout>\n <mj-page-header Title=\"Templates\" Icon=\"fa-solid fa-file-lines\" Subtitle=\"Manage reusable message templates\">\n <div actions>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"addNewTemplate()\">\n <i class=\"fa-solid fa-plus\"></i> New Template\n </button>\n </div>\n <div toolbar>\n <mj-page-search\n Placeholder=\"Search templates...\"\n (ValueChange)=\"onSearchValue($event)\">\n </mj-page-search>\n @if (!isLoading) {\n <mj-filter-chip\n Label=\"All\"\n [Count]=\"allTemplates.length\"\n [Active]=\"categoryFilter === ''\"\n (Clicked)=\"onCategoryFilter('')\">\n </mj-filter-chip>\n @for (cat of categories; track cat) {\n <mj-filter-chip\n [Label]=\"cat\"\n [Count]=\"getCategoryCount(cat)\"\n [Active]=\"categoryFilter === cat\"\n (Clicked)=\"onCategoryFilter(cat)\">\n </mj-filter-chip>\n }\n }\n </div>\n </mj-page-header>\n\n <mj-page-body>\n @if (isLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading templates...\"></mj-loading>\n </div>\n } @else {\n <div class=\"templates-grid\">\n @for (card of filteredTemplates; track card) {\n <div class=\"template-card\" (click)=\"openTemplate(card.Entity)\">\n <div class=\"template-card-header\">\n <div class=\"template-icon\">\n <i class=\"fa-solid fa-file-lines\"></i>\n </div>\n <div class=\"template-title-area\">\n <div class=\"template-name\">{{card.Entity.Name}}</div>\n <div class=\"template-category\">{{card.CategoryName}}</div>\n </div>\n </div>\n @if (card.Entity.Description) {\n <div class=\"template-description\">\n {{card.Entity.Description}}\n </div>\n }\n <div class=\"template-meta\">\n <div class=\"template-content-types\">\n @for (ct of card.ContentTypes; track ct) {\n <span class=\"content-type-chip\">\n <i [class]=\"getContentTypeIcon(ct)\"></i> {{ct}}\n </span>\n }\n @if (card.ContentTypes.length === 0) {\n <span class=\"content-type-chip empty\">\n No content\n </span>\n }\n </div>\n @if (card.LastUpdated) {\n <div class=\"template-updated\">\n Updated {{card.LastUpdated | date:'mediumDate'}}\n </div>\n }\n </div>\n </div>\n }\n @if (filteredTemplates.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-file-lines\"></i>\n <p>No templates found matching your criteria</p>\n </div>\n }\n </div>\n }\n </mj-page-body>\n </mj-page-layout>\n `,\n styles: [`\n .loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n /* GRID */\n .templates-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card:hover {\n box-shadow: 0 2px 8px var(--mj-shadow-md);\n border-color: var(--mj-border-strong);\n }\n\n .template-card-header {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon {\n width: 40px; height: 40px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area { flex: 1; min-width: 0; }\n .template-name {\n font-size: 14px; font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n }\n\n .template-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n }\n .content-type-chip.empty {\n font-style: italic;\n }\n .template-updated {\n font-size: 10px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n /* EMPTY STATE */\n .empty-state {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mj-text-muted);\n }\n .empty-state i { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state p { margin: 0; font-size: 13px; }\n `]\n})\nexport class CommunicationTemplatesResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public allTemplates: TemplateCardData[] = [];\n public filteredTemplates: TemplateCardData[] = [];\n public categories: string[] = [];\n public categoryFilter = '';\n public isLoading = false;\n private searchTerm = '';\n\n constructor(private cdr: ChangeDetectorRef, private navService: NavigationService) {\n super();\n }\n\n async ngOnInit(): Promise<void> {\n super.ngOnInit();\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void {\n super.ngOnDestroy();\n }\n\n public async loadData(): Promise<void> {\n try {\n this.isLoading = true;\n this.cdr.detectChanges();\n\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const [templatesResult, contentsResult] = await Promise.all([\n rv.RunView<MJTemplateEntity>({\n EntityName: 'MJ: Templates',\n OrderBy: 'Name ASC',\n ResultType: 'entity_object'\n }),\n rv.RunView<MJTemplateContentEntity>({\n EntityName: 'MJ: Template Contents',\n ResultType: 'entity_object'\n })\n ]);\n\n if (templatesResult.Success) {\n const contents = contentsResult.Success ? contentsResult.Results : [];\n this.allTemplates = templatesResult.Results.map(t => this.buildTemplateCard(t, contents));\n this.categories = this.extractCategories(this.allTemplates);\n this.applyFilter();\n }\n } catch (error) {\n console.error('Error loading templates:', error);\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n private buildTemplateCard(template: MJTemplateEntity, allContents: MJTemplateContentEntity[]): TemplateCardData {\n const templateContents = allContents.filter(c => UUIDsEqual(c.TemplateID, template.ID));\n const contentTypes = [...new Set(templateContents.map(c => c.TypeID ? 'Content' : 'Text'))];\n const category = template.Category || 'Uncategorized';\n const lastUpdated = template.Get('__mj_UpdatedAt') as Date | null;\n\n return {\n Entity: template,\n ContentTypes: contentTypes.length > 0 ? contentTypes : [],\n LastUpdated: lastUpdated,\n CategoryName: category\n };\n }\n\n private extractCategories(cards: TemplateCardData[]): string[] {\n const cats = new Set(cards.map(c => c.CategoryName));\n return Array.from(cats).sort();\n }\n\n public getCategoryCount(category: string): number {\n return this.allTemplates.filter(t => t.CategoryName === category).length;\n }\n\n public onSearchValue(value: string): void {\n this.searchTerm = (value ?? '').toLowerCase();\n this.applyFilter();\n }\n\n public onCategoryFilter(category: string): void {\n this.categoryFilter = category;\n this.applyFilter();\n }\n\n private applyFilter(): void {\n let filtered = this.allTemplates;\n\n if (this.categoryFilter) {\n filtered = filtered.filter(t => t.CategoryName === this.categoryFilter);\n }\n\n if (this.searchTerm) {\n filtered = filtered.filter(t =>\n t.Entity.Name?.toLowerCase().includes(this.searchTerm) ||\n t.Entity.Description?.toLowerCase().includes(this.searchTerm) ||\n t.CategoryName.toLowerCase().includes(this.searchTerm)\n );\n }\n\n this.filteredTemplates = filtered;\n this.cdr.detectChanges();\n }\n\n public openTemplate(template: MJTemplateEntity): void {\n const pk = new CompositeKey();\n pk.LoadFromEntityInfoAndRecord(this.ProviderToUse.Entities.find(e => e.Name === 'MJ: Templates')!, template);\n this.navService.OpenEntityRecord('MJ: Templates', pk);\n }\n\n public addNewTemplate(): void {\n this.navService.OpenEntityRecord('MJ: Templates', new CompositeKey());\n }\n\n public getContentTypeIcon(type: string): string {\n const t = type.toLowerCase();\n if (t.includes('html')) return 'fa-solid fa-code';\n if (t.includes('text') || t.includes('plain')) return 'fa-solid fa-align-left';\n if (t.includes('sms')) return 'fa-solid fa-comment-sms';\n return 'fa-solid fa-file';\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Templates';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-file-lines';\n }\n}\n"]}
1
+ {"version":3,"file":"communication-templates-resource.component.js","sourceRoot":"","sources":["../../src/Communication/communication-templates-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { ResourceData, MJTemplateEntity, MJTemplateContentEntity } from '@memberjunction/core-entities';\nimport { RegisterClass , UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { Metadata, RunView, CompositeKey } from '@memberjunction/core';\nimport { FilterFieldConfig } from '@memberjunction/ng-ui-components';\n\ninterface TemplateCardData {\n Entity: MJTemplateEntity;\n ContentTypes: string[];\n LastUpdated: Date | null;\n CategoryName: string;\n}\n@RegisterClass(BaseResourceComponent, 'CommunicationTemplatesResource')\n@Component({\n standalone: false,\n selector: 'mj-communication-templates-resource',\n template: `\n <mj-page-layout>\n <mj-page-header Title=\"Templates\" Icon=\"fa-solid fa-file-lines\" Subtitle=\"Manage reusable message templates\">\n <div actions>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"addNewTemplate()\">\n <i class=\"fa-solid fa-plus\"></i> <span class=\"action-btn-label\">New Template</span>\n </button>\n </div>\n <div toolbar>\n <mj-page-search\n Placeholder=\"Search templates...\"\n (ValueChange)=\"onSearchValue($event)\">\n </mj-page-search>\n <mj-filter-popover\n [ActiveCount]=\"ActiveFilterCount\"\n [ShowClearAll]=\"ActiveFilterCount > 0\"\n (ClearAllRequested)=\"resetFilters()\">\n <mj-filter-panel\n [Fields]=\"filterFields\"\n [Values]=\"filterValues\"\n (ValuesChange)=\"onFilterValuesChange($event)\"\n (Reset)=\"resetFilters()\">\n </mj-filter-panel>\n </mj-filter-popover>\n </div>\n </mj-page-header>\n\n <mj-page-body>\n @if (isLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading templates...\"></mj-loading>\n </div>\n } @else {\n <div class=\"templates-grid\">\n @for (card of filteredTemplates; track card) {\n <div class=\"template-card\" (click)=\"openTemplate(card.Entity)\">\n <div class=\"template-card-header\">\n <div class=\"template-icon\">\n <i class=\"fa-solid fa-file-lines\"></i>\n </div>\n <div class=\"template-title-area\">\n <div class=\"template-name\">{{card.Entity.Name}}</div>\n <div class=\"template-category\">{{card.CategoryName}}</div>\n </div>\n </div>\n @if (card.Entity.Description) {\n <div class=\"template-description\">\n {{card.Entity.Description}}\n </div>\n }\n <div class=\"template-meta\">\n <div class=\"template-content-types\">\n @for (ct of card.ContentTypes; track ct) {\n <span class=\"content-type-chip\">\n <i [class]=\"getContentTypeIcon(ct)\"></i> {{ct}}\n </span>\n }\n @if (card.ContentTypes.length === 0) {\n <span class=\"content-type-chip empty\">\n No content\n </span>\n }\n </div>\n @if (card.LastUpdated) {\n <div class=\"template-updated\">\n Updated {{card.LastUpdated | date:'mediumDate'}}\n </div>\n }\n </div>\n </div>\n }\n @if (filteredTemplates.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-file-lines\"></i>\n <p>No templates found matching your criteria</p>\n </div>\n }\n </div>\n }\n </mj-page-body>\n </mj-page-layout>\n `,\n styles: [`\n .loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n /* GRID */\n .templates-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card:hover {\n box-shadow: 0 2px 8px var(--mj-shadow-md);\n border-color: var(--mj-border-strong);\n }\n\n .template-card-header {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon {\n width: 40px; height: 40px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area { flex: 1; min-width: 0; }\n .template-name {\n font-size: 14px; font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n }\n\n .template-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n }\n .content-type-chip.empty {\n font-style: italic;\n }\n .template-updated {\n font-size: 10px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n /* EMPTY STATE */\n .empty-state {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mj-text-muted);\n }\n .empty-state i { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state p { margin: 0; font-size: 13px; }\n `]\n})\nexport class CommunicationTemplatesResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public allTemplates: TemplateCardData[] = [];\n public filteredTemplates: TemplateCardData[] = [];\n public categories: string[] = [];\n public categoryFilter = '';\n public isLoading = false;\n private searchTerm = '';\n\n constructor(private cdr: ChangeDetectorRef, private navService: NavigationService) {\n super();\n }\n\n async ngOnInit(): Promise<void> {\n super.ngOnInit();\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void {\n super.ngOnDestroy();\n }\n\n public async loadData(): Promise<void> {\n try {\n this.isLoading = true;\n this.cdr.detectChanges();\n\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const [templatesResult, contentsResult] = await Promise.all([\n rv.RunView<MJTemplateEntity>({\n EntityName: 'MJ: Templates',\n OrderBy: 'Name ASC',\n ResultType: 'entity_object'\n }),\n rv.RunView<MJTemplateContentEntity>({\n EntityName: 'MJ: Template Contents',\n ResultType: 'entity_object'\n })\n ]);\n\n if (templatesResult.Success) {\n const contents = contentsResult.Success ? contentsResult.Results : [];\n this.allTemplates = templatesResult.Results.map(t => this.buildTemplateCard(t, contents));\n this.categories = this.extractCategories(this.allTemplates);\n this.applyFilter();\n }\n } catch (error) {\n console.error('Error loading templates:', error);\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n private buildTemplateCard(template: MJTemplateEntity, allContents: MJTemplateContentEntity[]): TemplateCardData {\n const templateContents = allContents.filter(c => UUIDsEqual(c.TemplateID, template.ID));\n const contentTypes = [...new Set(templateContents.map(c => c.TypeID ? 'Content' : 'Text'))];\n const category = template.Category || 'Uncategorized';\n const lastUpdated = template.Get('__mj_UpdatedAt') as Date | null;\n\n return {\n Entity: template,\n ContentTypes: contentTypes.length > 0 ? contentTypes : [],\n LastUpdated: lastUpdated,\n CategoryName: category\n };\n }\n\n private extractCategories(cards: TemplateCardData[]): string[] {\n const cats = new Set(cards.map(c => c.CategoryName));\n return Array.from(cats).sort();\n }\n\n public getCategoryCount(category: string): number {\n return this.allTemplates.filter(t => t.CategoryName === category).length;\n }\n\n public onSearchValue(value: string): void {\n this.searchTerm = (value ?? '').toLowerCase();\n this.applyFilter();\n }\n\n public onCategoryFilter(category: string): void {\n this.categoryFilter = category;\n this.applyFilter();\n }\n\n // -- Concise chrome: Category lives behind the one Filter popover ---------\n\n public get filterFields(): FilterFieldConfig[] {\n return [{\n key: 'category',\n type: 'chips',\n label: 'Category',\n chipOptions: [\n { text: 'All', value: '' },\n ...this.categories.map(c => ({ text: c, value: c })),\n ],\n }];\n }\n\n public get filterValues(): Record<string, unknown> {\n return { category: this.categoryFilter };\n }\n\n public get ActiveFilterCount(): number {\n return this.categoryFilter ? 1 : 0;\n }\n\n public onFilterValuesChange(values: Record<string, unknown>): void {\n this.onCategoryFilter((values['category'] as string) ?? '');\n }\n\n public resetFilters(): void {\n this.onCategoryFilter('');\n }\n\n private applyFilter(): void {\n let filtered = this.allTemplates;\n\n if (this.categoryFilter) {\n filtered = filtered.filter(t => t.CategoryName === this.categoryFilter);\n }\n\n if (this.searchTerm) {\n filtered = filtered.filter(t =>\n t.Entity.Name?.toLowerCase().includes(this.searchTerm) ||\n t.Entity.Description?.toLowerCase().includes(this.searchTerm) ||\n t.CategoryName.toLowerCase().includes(this.searchTerm)\n );\n }\n\n this.filteredTemplates = filtered;\n this.cdr.detectChanges();\n }\n\n public openTemplate(template: MJTemplateEntity): void {\n const pk = new CompositeKey();\n pk.LoadFromEntityInfoAndRecord(this.ProviderToUse.Entities.find(e => e.Name === 'MJ: Templates')!, template);\n this.navService.OpenEntityRecord('MJ: Templates', pk);\n }\n\n public addNewTemplate(): void {\n this.navService.OpenEntityRecord('MJ: Templates', new CompositeKey());\n }\n\n public getContentTypeIcon(type: string): string {\n const t = type.toLowerCase();\n if (t.includes('html')) return 'fa-solid fa-code';\n if (t.includes('text') || t.includes('plain')) return 'fa-solid fa-align-left';\n if (t.includes('sms')) return 'fa-solid fa-comment-sms';\n return 'fa-solid fa-file';\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Templates';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-file-lines';\n }\n}\n"]}