@memberjunction/ng-dashboards 5.35.0 → 5.36.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 (159) hide show
  1. package/dist/AI/components/agents/agent-configuration.component.js +3 -3
  2. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  3. package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts +22 -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 +157 -137
  6. package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
  7. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +28 -0
  8. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  9. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +2075 -2068
  10. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  11. package/dist/AI/components/models/model-management.component.js +4 -4
  12. package/dist/AI/components/models/model-management.component.js.map +1 -1
  13. package/dist/AI/components/prompts/prompt-management.component.js +3 -3
  14. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  15. package/dist/AI/components/tags/tags-resource.component.d.ts +15 -0
  16. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  17. package/dist/AI/components/tags/tags-resource.component.js +1411 -1424
  18. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  19. package/dist/APIKeys/api-keys-resource.component.d.ts +12 -8
  20. package/dist/APIKeys/api-keys-resource.component.d.ts.map +1 -1
  21. package/dist/APIKeys/api-keys-resource.component.js +329 -371
  22. package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
  23. package/dist/Actions/components/actions-overview.component.js +137 -142
  24. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  25. package/dist/Actions/components/execution-monitoring.component.js +111 -116
  26. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  27. package/dist/Admin/admin-data-schema.component.js +13 -65
  28. package/dist/Admin/admin-data-schema.component.js.map +1 -1
  29. package/dist/Admin/admin-dev-tools-resource.component.js +13 -65
  30. package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
  31. package/dist/Admin/admin-identity-access.component.js +13 -65
  32. package/dist/Admin/admin-identity-access.component.js.map +1 -1
  33. package/dist/Admin/admin-monitoring.component.js +13 -65
  34. package/dist/Admin/admin-monitoring.component.js.map +1 -1
  35. package/dist/Admin/base-admin-container.component.d.ts +9 -7
  36. package/dist/Admin/base-admin-container.component.d.ts.map +1 -1
  37. package/dist/Admin/base-admin-container.component.js +26 -17
  38. package/dist/Admin/base-admin-container.component.js.map +1 -1
  39. package/dist/ApplicationRoles/application-roles-resource.component.js +74 -67
  40. package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
  41. package/dist/Communication/communication-new-message-resource.component.d.ts +93 -0
  42. package/dist/Communication/communication-new-message-resource.component.d.ts.map +1 -0
  43. package/dist/Communication/communication-new-message-resource.component.js +661 -0
  44. package/dist/Communication/communication-new-message-resource.component.js.map +1 -0
  45. package/dist/Credentials/components/credentials-categories-resource.component.js +152 -159
  46. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  47. package/dist/Credentials/components/credentials-types-resource.component.js +151 -155
  48. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  49. package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +20 -21
  50. package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js.map +1 -1
  51. package/dist/DatabaseDesigner/components/entity-list.component.d.ts +2 -0
  52. package/dist/DatabaseDesigner/components/entity-list.component.d.ts.map +1 -1
  53. package/dist/DatabaseDesigner/components/entity-list.component.js +131 -125
  54. package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
  55. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +1 -1
  56. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
  57. package/dist/DatabaseDesigner/database-designer-dashboards.module.js +7 -1
  58. package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
  59. package/dist/DevTools/app-state-inspector.component.d.ts +5 -0
  60. package/dist/DevTools/app-state-inspector.component.d.ts.map +1 -1
  61. package/dist/DevTools/app-state-inspector.component.js +46 -72
  62. package/dist/DevTools/app-state-inspector.component.js.map +1 -1
  63. package/dist/DevTools/class-registry.component.js +88 -100
  64. package/dist/DevTools/class-registry.component.js.map +1 -1
  65. package/dist/DevTools/event-monitor.component.js +158 -168
  66. package/dist/DevTools/event-monitor.component.js.map +1 -1
  67. package/dist/DevTools/graphql-console.component.js +257 -264
  68. package/dist/DevTools/graphql-console.component.js.map +1 -1
  69. package/dist/DevTools/layout-inspector.component.d.ts +5 -0
  70. package/dist/DevTools/layout-inspector.component.d.ts.map +1 -1
  71. package/dist/DevTools/layout-inspector.component.js +46 -64
  72. package/dist/DevTools/layout-inspector.component.js.map +1 -1
  73. package/dist/DevTools/lazy-module-status.component.js +75 -84
  74. package/dist/DevTools/lazy-module-status.component.js.map +1 -1
  75. package/dist/DevTools/settings-explorer.component.js +76 -85
  76. package/dist/DevTools/settings-explorer.component.js.map +1 -1
  77. package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts +2 -0
  78. package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts.map +1 -1
  79. package/dist/EntityAdmin/entity-admin-dashboard.component.js +7 -3
  80. package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
  81. package/dist/Integration/components/activity/activity.component.js +97 -99
  82. package/dist/Integration/components/activity/activity.component.js.map +1 -1
  83. package/dist/Integration/components/connections/connections.component.js +842 -855
  84. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  85. package/dist/Integration/components/pipelines/pipelines.component.js +502 -517
  86. package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
  87. package/dist/Integration/components/schedules/schedules.component.js +78 -89
  88. package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
  89. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts +5 -0
  90. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -1
  91. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +1120 -1128
  92. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
  93. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +11 -0
  94. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -1
  95. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +606 -661
  96. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  97. package/dist/Lists/components/lists-browse-resource.component.d.ts +102 -0
  98. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  99. package/dist/Lists/components/lists-browse-resource.component.js +1179 -504
  100. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  101. package/dist/Lists/components/lists-operations-resource.component.d.ts +133 -3
  102. package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
  103. package/dist/Lists/components/lists-operations-resource.component.js +1527 -327
  104. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  105. package/dist/Lists/components/lists-shared-with-me-resource.component.d.ts +29 -0
  106. package/dist/Lists/components/lists-shared-with-me-resource.component.d.ts.map +1 -0
  107. package/dist/Lists/components/lists-shared-with-me-resource.component.js +77 -0
  108. package/dist/Lists/components/lists-shared-with-me-resource.component.js.map +1 -0
  109. package/dist/Lists/components/venn-diagram/venn-diagram.component.d.ts +6 -0
  110. package/dist/Lists/components/venn-diagram/venn-diagram.component.d.ts.map +1 -1
  111. package/dist/Lists/components/venn-diagram/venn-diagram.component.js +35 -7
  112. package/dist/Lists/components/venn-diagram/venn-diagram.component.js.map +1 -1
  113. package/dist/Lists/index.d.ts +1 -0
  114. package/dist/Lists/index.d.ts.map +1 -1
  115. package/dist/Lists/index.js +1 -0
  116. package/dist/Lists/index.js.map +1 -1
  117. package/dist/Lists/services/list-set-operations.service.d.ts +93 -2
  118. package/dist/Lists/services/list-set-operations.service.d.ts.map +1 -1
  119. package/dist/Lists/services/list-set-operations.service.js +236 -10
  120. package/dist/Lists/services/list-set-operations.service.js.map +1 -1
  121. package/dist/MCP/mcp-dashboard.component.js +19 -19
  122. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  123. package/dist/Scheduling/scheduling-dashboard.component.js +58 -60
  124. package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
  125. package/dist/SystemDiagnostics/system-diagnostics.component.d.ts +13 -3
  126. package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
  127. package/dist/SystemDiagnostics/system-diagnostics.component.js +1007 -1252
  128. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  129. package/dist/Testing/components/testing-explorer.component.d.ts +31 -6
  130. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  131. package/dist/Testing/components/testing-explorer.component.js +543 -629
  132. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  133. package/dist/Testing/testing-dashboard.component.js +50 -49
  134. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  135. package/dist/ai-dashboards.module.d.ts +1 -1
  136. package/dist/ai-dashboards.module.d.ts.map +1 -1
  137. package/dist/ai-dashboards.module.js +16 -1
  138. package/dist/ai-dashboards.module.js.map +1 -1
  139. package/dist/communication-dashboards.module.d.ts +9 -7
  140. package/dist/communication-dashboards.module.d.ts.map +1 -1
  141. package/dist/communication-dashboards.module.js +13 -4
  142. package/dist/communication-dashboards.module.js.map +1 -1
  143. package/dist/core-dashboards.module.d.ts +1 -1
  144. package/dist/core-dashboards.module.d.ts.map +1 -1
  145. package/dist/core-dashboards.module.js +16 -1
  146. package/dist/core-dashboards.module.js.map +1 -1
  147. package/dist/lists-dashboards.module.d.ts +10 -9
  148. package/dist/lists-dashboards.module.d.ts.map +1 -1
  149. package/dist/lists-dashboards.module.js +13 -2
  150. package/dist/lists-dashboards.module.js.map +1 -1
  151. package/dist/public-api.d.ts +1 -0
  152. package/dist/public-api.d.ts.map +1 -1
  153. package/dist/public-api.js +1 -0
  154. package/dist/public-api.js.map +1 -1
  155. package/dist/testing-dashboards.module.d.ts +1 -1
  156. package/dist/testing-dashboards.module.d.ts.map +1 -1
  157. package/dist/testing-dashboards.module.js +13 -1
  158. package/dist/testing-dashboards.module.js.map +1 -1
  159. package/package.json +53 -52
@@ -0,0 +1,661 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Component } from '@angular/core';
8
+ import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
9
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
10
+ import { RunView } from '@memberjunction/core';
11
+ import { ActionEngineBase } from '@memberjunction/actions-base';
12
+ import * as i0 from "@angular/core";
13
+ import * as i1 from "@memberjunction/ng-notifications";
14
+ import * as i2 from "@angular/forms";
15
+ import * as i3 from "@memberjunction/ng-shared-generic";
16
+ import * as i4 from "@memberjunction/ng-list-management";
17
+ const _forTrack0 = ($index, $item) => $item.ID;
18
+ function CommunicationsNewMessageResource_Conditional_8_Template(rf, ctx) { if (rf & 1) {
19
+ i0.ɵɵelement(0, "i", 16);
20
+ i0.ɵɵtext(1, " Previewing\u2026 ");
21
+ } }
22
+ function CommunicationsNewMessageResource_Conditional_9_Template(rf, ctx) { if (rf & 1) {
23
+ i0.ɵɵelement(0, "i", 17);
24
+ i0.ɵɵtext(1, " Preview Audience ");
25
+ } }
26
+ function CommunicationsNewMessageResource_Conditional_11_Template(rf, ctx) { if (rf & 1) {
27
+ i0.ɵɵelement(0, "i", 16);
28
+ i0.ɵɵtext(1, " Sending\u2026 ");
29
+ } }
30
+ function CommunicationsNewMessageResource_Conditional_12_Template(rf, ctx) { if (rf & 1) {
31
+ i0.ɵɵelement(0, "i", 18);
32
+ i0.ɵɵtext(1, " Send ");
33
+ } }
34
+ function CommunicationsNewMessageResource_Conditional_20_Template(rf, ctx) { if (rf & 1) {
35
+ i0.ɵɵelement(0, "mj-loading", 12);
36
+ } }
37
+ function CommunicationsNewMessageResource_Conditional_21_For_6_Template(rf, ctx) { if (rf & 1) {
38
+ i0.ɵɵelementStart(0, "option", 21);
39
+ i0.ɵɵtext(1);
40
+ i0.ɵɵelementEnd();
41
+ } if (rf & 2) {
42
+ const p_r3 = ctx.$implicit;
43
+ i0.ɵɵproperty("ngValue", p_r3.ID);
44
+ i0.ɵɵadvance();
45
+ i0.ɵɵtextInterpolate(p_r3.Name);
46
+ } }
47
+ function CommunicationsNewMessageResource_Conditional_21_Conditional_7_For_6_Template(rf, ctx) { if (rf & 1) {
48
+ i0.ɵɵelementStart(0, "option", 21);
49
+ i0.ɵɵtext(1);
50
+ i0.ɵɵelementEnd();
51
+ } if (rf & 2) {
52
+ const mt_r5 = ctx.$implicit;
53
+ i0.ɵɵproperty("ngValue", mt_r5.ID);
54
+ i0.ɵɵadvance();
55
+ i0.ɵɵtextInterpolate(mt_r5.Name);
56
+ } }
57
+ function CommunicationsNewMessageResource_Conditional_21_Conditional_7_Template(rf, ctx) { if (rf & 1) {
58
+ const _r4 = i0.ɵɵgetCurrentView();
59
+ i0.ɵɵelementStart(0, "label", 19);
60
+ i0.ɵɵtext(1, "Message type");
61
+ i0.ɵɵelementEnd();
62
+ i0.ɵɵelementStart(2, "select", 20);
63
+ i0.ɵɵtwoWayListener("ngModelChange", function CommunicationsNewMessageResource_Conditional_21_Conditional_7_Template_select_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedMessageTypeID, $event) || (ctx_r1.selectedMessageTypeID = $event); return i0.ɵɵresetView($event); });
64
+ i0.ɵɵelementStart(3, "option", 21);
65
+ i0.ɵɵtext(4, "Select a message type\u2026");
66
+ i0.ɵɵelementEnd();
67
+ i0.ɵɵrepeaterCreate(5, CommunicationsNewMessageResource_Conditional_21_Conditional_7_For_6_Template, 2, 2, "option", 21, _forTrack0);
68
+ i0.ɵɵelementEnd();
69
+ } if (rf & 2) {
70
+ const ctx_r1 = i0.ɵɵnextContext(2);
71
+ i0.ɵɵadvance(2);
72
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedMessageTypeID);
73
+ i0.ɵɵadvance();
74
+ i0.ɵɵproperty("ngValue", null);
75
+ i0.ɵɵadvance(2);
76
+ i0.ɵɵrepeater(ctx_r1.filteredMessageTypes);
77
+ } }
78
+ function CommunicationsNewMessageResource_Conditional_21_Template(rf, ctx) { if (rf & 1) {
79
+ const _r1 = i0.ɵɵgetCurrentView();
80
+ i0.ɵɵelementStart(0, "label", 19);
81
+ i0.ɵɵtext(1, "Channel");
82
+ i0.ɵɵelementEnd();
83
+ i0.ɵɵelementStart(2, "select", 20);
84
+ i0.ɵɵtwoWayListener("ngModelChange", function CommunicationsNewMessageResource_Conditional_21_Template_select_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedProviderID, $event) || (ctx_r1.selectedProviderID = $event); return i0.ɵɵresetView($event); });
85
+ i0.ɵɵlistener("ngModelChange", function CommunicationsNewMessageResource_Conditional_21_Template_select_ngModelChange_2_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onProviderChange()); });
86
+ i0.ɵɵelementStart(3, "option", 21);
87
+ i0.ɵɵtext(4, "Select a channel\u2026");
88
+ i0.ɵɵelementEnd();
89
+ i0.ɵɵrepeaterCreate(5, CommunicationsNewMessageResource_Conditional_21_For_6_Template, 2, 2, "option", 21, _forTrack0);
90
+ i0.ɵɵelementEnd();
91
+ i0.ɵɵconditionalCreate(7, CommunicationsNewMessageResource_Conditional_21_Conditional_7_Template, 7, 2);
92
+ i0.ɵɵelementStart(8, "label", 19);
93
+ i0.ɵɵtext(9, "From");
94
+ i0.ɵɵelementEnd();
95
+ i0.ɵɵelementStart(10, "input", 22);
96
+ i0.ɵɵtwoWayListener("ngModelChange", function CommunicationsNewMessageResource_Conditional_21_Template_input_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.fromAddress, $event) || (ctx_r1.fromAddress = $event); return i0.ɵɵresetView($event); });
97
+ i0.ɵɵelementEnd();
98
+ i0.ɵɵelementStart(11, "label", 19);
99
+ i0.ɵɵtext(12, "Subject");
100
+ i0.ɵɵelementEnd();
101
+ i0.ɵɵelementStart(13, "input", 23);
102
+ i0.ɵɵtwoWayListener("ngModelChange", function CommunicationsNewMessageResource_Conditional_21_Template_input_ngModelChange_13_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.subject, $event) || (ctx_r1.subject = $event); return i0.ɵɵresetView($event); });
103
+ i0.ɵɵelementEnd();
104
+ i0.ɵɵelementStart(14, "label", 19);
105
+ i0.ɵɵtext(15, "Body");
106
+ i0.ɵɵelementEnd();
107
+ i0.ɵɵelementStart(16, "textarea", 24);
108
+ i0.ɵɵtwoWayListener("ngModelChange", function CommunicationsNewMessageResource_Conditional_21_Template_textarea_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.body, $event) || (ctx_r1.body = $event); return i0.ɵɵresetView($event); });
109
+ i0.ɵɵelementEnd();
110
+ } if (rf & 2) {
111
+ const ctx_r1 = i0.ɵɵnextContext();
112
+ i0.ɵɵadvance(2);
113
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedProviderID);
114
+ i0.ɵɵadvance();
115
+ i0.ɵɵproperty("ngValue", null);
116
+ i0.ɵɵadvance(2);
117
+ i0.ɵɵrepeater(ctx_r1.providers);
118
+ i0.ɵɵadvance(2);
119
+ i0.ɵɵconditional(ctx_r1.filteredMessageTypes.length > 0 ? 7 : -1);
120
+ i0.ɵɵadvance(3);
121
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.fromAddress);
122
+ i0.ɵɵadvance(3);
123
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.subject);
124
+ i0.ɵɵadvance(3);
125
+ i0.ɵɵproperty("placeholder", i0.ɵɵinterpolate1("Hi ", "{{FirstName}}", ",..."));
126
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.body);
127
+ } }
128
+ function CommunicationsNewMessageResource_Conditional_29_Template(rf, ctx) { if (rf & 1) {
129
+ const _r6 = i0.ɵɵgetCurrentView();
130
+ i0.ɵɵelementStart(0, "label", 25);
131
+ i0.ɵɵtext(1, "Recipient field");
132
+ i0.ɵɵelementEnd();
133
+ i0.ɵɵelementStart(2, "input", 26);
134
+ i0.ɵɵtwoWayListener("ngModelChange", function CommunicationsNewMessageResource_Conditional_29_Template_input_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.recipientField, $event) || (ctx_r1.recipientField = $event); return i0.ɵɵresetView($event); });
135
+ i0.ɵɵelementEnd();
136
+ i0.ɵɵelementStart(3, "p", 27);
137
+ i0.ɵɵtext(4, " Field on the audience entity that holds the recipient address. Records with no value will be skipped. ");
138
+ i0.ɵɵelementEnd();
139
+ } if (rf & 2) {
140
+ const ctx_r1 = i0.ɵɵnextContext();
141
+ i0.ɵɵadvance(2);
142
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.recipientField);
143
+ } }
144
+ function CommunicationsNewMessageResource_Conditional_30_Conditional_11_Template(rf, ctx) { if (rf & 1) {
145
+ i0.ɵɵelementStart(0, "div", 33)(1, "span", 30);
146
+ i0.ɵɵtext(2);
147
+ i0.ɵɵelementEnd();
148
+ i0.ɵɵelementStart(3, "span", 31);
149
+ i0.ɵɵtext(4);
150
+ i0.ɵɵelementEnd()();
151
+ } if (rf & 2) {
152
+ const ctx_r1 = i0.ɵɵnextContext(2);
153
+ i0.ɵɵadvance(2);
154
+ i0.ɵɵtextInterpolate1("Skipped (missing ", ctx_r1.recipientField || "recipient", ")");
155
+ i0.ɵɵadvance(2);
156
+ i0.ɵɵtextInterpolate(ctx_r1.audienceSummary.SkippedCount);
157
+ } }
158
+ function CommunicationsNewMessageResource_Conditional_30_Template(rf, ctx) { if (rf & 1) {
159
+ i0.ɵɵelementStart(0, "div", 28)(1, "div", 29)(2, "span", 30);
160
+ i0.ɵɵtext(3, "Total audience");
161
+ i0.ɵɵelementEnd();
162
+ i0.ɵɵelementStart(4, "span", 31);
163
+ i0.ɵɵtext(5);
164
+ i0.ɵɵelementEnd()();
165
+ i0.ɵɵelementStart(6, "div", 32)(7, "span", 30);
166
+ i0.ɵɵtext(8, "Will receive");
167
+ i0.ɵɵelementEnd();
168
+ i0.ɵɵelementStart(9, "span", 31);
169
+ i0.ɵɵtext(10);
170
+ i0.ɵɵelementEnd()();
171
+ i0.ɵɵconditionalCreate(11, CommunicationsNewMessageResource_Conditional_30_Conditional_11_Template, 5, 2, "div", 33);
172
+ i0.ɵɵelementStart(12, "div", 34)(13, "span", 30);
173
+ i0.ɵɵtext(14, "Entity");
174
+ i0.ɵɵelementEnd();
175
+ i0.ɵɵelementStart(15, "span", 31);
176
+ i0.ɵɵtext(16);
177
+ i0.ɵɵelementEnd()()();
178
+ } if (rf & 2) {
179
+ const ctx_r1 = i0.ɵɵnextContext();
180
+ i0.ɵɵclassProp("summary-block--has-skips", ctx_r1.audienceSummary.SkippedCount > 0);
181
+ i0.ɵɵadvance(5);
182
+ i0.ɵɵtextInterpolate(ctx_r1.audienceSummary.TotalAudienceSize);
183
+ i0.ɵɵadvance(5);
184
+ i0.ɵɵtextInterpolate(ctx_r1.audienceSummary.WillReceiveCount);
185
+ i0.ɵɵadvance();
186
+ i0.ɵɵconditional(ctx_r1.audienceSummary.SkippedCount > 0 ? 11 : -1);
187
+ i0.ɵɵadvance(5);
188
+ i0.ɵɵtextInterpolate(ctx_r1.audienceSummary.EntityName);
189
+ } }
190
+ let CommunicationsNewMessageResource = class CommunicationsNewMessageResource extends BaseResourceComponent {
191
+ cdr;
192
+ notificationService;
193
+ // BaseResourceComponent already exposes a protected `destroy$` Subject.
194
+ // Don't re-declare it here — the import is kept only for the rxjs type.
195
+ // (See base class comment.)
196
+ // Local lifecycle goes through super.ngOnDestroy().
197
+ // Channel state
198
+ loadingProviders = true;
199
+ providers = [];
200
+ messageTypes = [];
201
+ selectedProviderID = null;
202
+ selectedMessageTypeID = null;
203
+ // Message state
204
+ fromAddress = '';
205
+ subject = '';
206
+ body = '';
207
+ // Audience state
208
+ audienceSource = null;
209
+ recipientField = '';
210
+ audienceSummary = null;
211
+ // Action IDs — looked up lazily on first use to avoid an extra RunView
212
+ // on every page open. Cached for the session.
213
+ resolveAudienceActionID = null;
214
+ sendToAudienceActionID = null;
215
+ isResolvingAudience = false;
216
+ isSending = false;
217
+ constructor(cdr, notificationService) {
218
+ super();
219
+ this.cdr = cdr;
220
+ this.notificationService = notificationService;
221
+ }
222
+ async ngOnInit() {
223
+ super.ngOnInit();
224
+ await this.loadChannelMetadata();
225
+ this.NotifyLoadComplete();
226
+ }
227
+ ngOnDestroy() {
228
+ super.ngOnDestroy();
229
+ }
230
+ get filteredMessageTypes() {
231
+ if (!this.selectedProviderID)
232
+ return [];
233
+ return this.messageTypes.filter((mt) => mt.CommunicationProviderID === this.selectedProviderID);
234
+ }
235
+ get selectedProvider() {
236
+ return this.providers.find((p) => UUIDsEqual(p.ID, this.selectedProviderID)) ?? null;
237
+ }
238
+ get selectedMessageType() {
239
+ return this.messageTypes.find((mt) => UUIDsEqual(mt.ID, this.selectedMessageTypeID)) ?? null;
240
+ }
241
+ get canPreview() {
242
+ return !!this.audienceSource && this.recipientField.trim().length > 0;
243
+ }
244
+ get canSend() {
245
+ return this.canPreview
246
+ && !!this.selectedProviderID
247
+ && !!this.selectedMessageTypeID
248
+ && this.fromAddress.trim().length > 0;
249
+ }
250
+ onProviderChange() {
251
+ this.selectedMessageTypeID = null;
252
+ }
253
+ onAudienceSourceChange(source) {
254
+ this.audienceSource = source;
255
+ this.audienceSummary = null;
256
+ }
257
+ /**
258
+ * Preview the audience without sending — calls "Send To Audience" with
259
+ * PreviewOnly=true. Surfaces the same total/will-receive/skipped tile
260
+ * mockup 21 shows. Cheaper than `Resolve Audience` for our purposes
261
+ * because it also evaluates the recipient-field skip rule.
262
+ */
263
+ async onPreviewAudience() {
264
+ if (!this.canPreview)
265
+ return;
266
+ this.isResolvingAudience = true;
267
+ this.audienceSummary = null;
268
+ this.cdr.detectChanges();
269
+ try {
270
+ const actionID = await this.getSendToAudienceActionID();
271
+ if (!actionID) {
272
+ this.notificationService.CreateSimpleNotification("Couldn't find the 'Send To Audience' action — make sure CodeGen has run.", 'error', 5000);
273
+ return;
274
+ }
275
+ const result = await this.invokeAction(actionID, {
276
+ Source: JSON.stringify(this.audienceSource),
277
+ RecipientField: this.recipientField.trim(),
278
+ ProviderName: this.selectedProvider?.Name ?? 'Preview',
279
+ ProviderMessageTypeName: this.selectedMessageType?.Name ?? 'Preview',
280
+ From: this.fromAddress || 'preview@local',
281
+ Subject: this.subject,
282
+ Body: this.body,
283
+ PreviewOnly: 'true',
284
+ });
285
+ const data = this.parseResultData(result);
286
+ this.audienceSummary = {
287
+ TotalAudienceSize: this.coerceNumber(data['TotalAudienceSize']),
288
+ WillReceiveCount: this.coerceNumber(data['WillReceiveCount']),
289
+ SkippedCount: this.coerceNumber(data['SkippedCount']),
290
+ EntityName: this.audienceSource ? this.describeSource(this.audienceSource) : '',
291
+ };
292
+ }
293
+ catch (e) {
294
+ const message = e instanceof Error ? e.message : String(e);
295
+ this.notificationService.CreateSimpleNotification(`Preview failed: ${message}`, 'error', 5000);
296
+ }
297
+ finally {
298
+ this.isResolvingAudience = false;
299
+ this.cdr.detectChanges();
300
+ }
301
+ }
302
+ async onSend() {
303
+ if (!this.canSend)
304
+ return;
305
+ this.isSending = true;
306
+ this.cdr.detectChanges();
307
+ try {
308
+ const actionID = await this.getSendToAudienceActionID();
309
+ if (!actionID) {
310
+ this.notificationService.CreateSimpleNotification("Couldn't find the 'Send To Audience' action — make sure CodeGen has run.", 'error', 5000);
311
+ return;
312
+ }
313
+ const result = await this.invokeAction(actionID, {
314
+ Source: JSON.stringify(this.audienceSource),
315
+ RecipientField: this.recipientField.trim(),
316
+ ProviderName: this.selectedProvider.Name,
317
+ ProviderMessageTypeName: this.selectedMessageType.Name,
318
+ From: this.fromAddress,
319
+ Subject: this.subject,
320
+ Body: this.body,
321
+ PreviewOnly: 'false',
322
+ });
323
+ const data = this.parseResultData(result);
324
+ const sent = this.coerceNumber(data['WillReceiveCount']) - this.coerceNumber(data['FailedCount']);
325
+ const failed = this.coerceNumber(data['FailedCount']);
326
+ const skipped = this.coerceNumber(data['SkippedCount']);
327
+ const okOverall = result.Success === true && failed === 0;
328
+ this.notificationService.CreateSimpleNotification(okOverall
329
+ ? `Sent ${sent} message(s)${skipped > 0 ? ` (${skipped} skipped)` : ''}`
330
+ : `Sent with errors: ${sent} sent, ${failed} failed, ${skipped} skipped`, okOverall ? 'success' : 'warning', okOverall ? 3000 : 7000);
331
+ }
332
+ catch (e) {
333
+ const message = e instanceof Error ? e.message : String(e);
334
+ this.notificationService.CreateSimpleNotification(`Send failed: ${message}`, 'error', 5000);
335
+ }
336
+ finally {
337
+ this.isSending = false;
338
+ this.cdr.detectChanges();
339
+ }
340
+ }
341
+ // -----------------------------------------------------------------
342
+ // Internals
343
+ // -----------------------------------------------------------------
344
+ /**
345
+ * One RunView pair on init: providers + their message types. Cached on
346
+ * the component for the session — we don't go back to the DB on every
347
+ * channel selection. Use RunViews (plural) so it's a single round trip.
348
+ */
349
+ async loadChannelMetadata() {
350
+ this.loadingProviders = true;
351
+ try {
352
+ const rv = RunView.FromMetadataProvider(this.ProviderToUse);
353
+ const [providersResult, messageTypesResult] = await rv.RunViews([
354
+ {
355
+ EntityName: 'MJ: Communication Providers',
356
+ ExtraFilter: "Status='Active'",
357
+ OrderBy: 'Name',
358
+ ResultType: 'simple',
359
+ },
360
+ {
361
+ EntityName: 'MJ: Communication Provider Message Types',
362
+ ExtraFilter: "Status='Active'",
363
+ OrderBy: 'Name',
364
+ ResultType: 'simple',
365
+ },
366
+ ]);
367
+ this.providers = (providersResult.Success ? providersResult.Results ?? [] : []);
368
+ this.messageTypes = (messageTypesResult.Success ? messageTypesResult.Results ?? [] : []);
369
+ }
370
+ catch (e) {
371
+ const message = e instanceof Error ? e.message : String(e);
372
+ this.notificationService.CreateSimpleNotification(`Failed to load channels: ${message}`, 'error', 5000);
373
+ }
374
+ finally {
375
+ this.loadingProviders = false;
376
+ this.cdr.detectChanges();
377
+ }
378
+ }
379
+ async getSendToAudienceActionID() {
380
+ if (this.sendToAudienceActionID)
381
+ return this.sendToAudienceActionID;
382
+ // Read from the cached ActionEngineBase singleton rather than a
383
+ // fresh RunView. Config() is idempotent — short-circuits if the
384
+ // engine has already loaded — so calling it on every Preview/Send
385
+ // is effectively free after the first invocation.
386
+ const engine = ActionEngineBase.Instance;
387
+ await engine.Config(false, this.ProviderToUse.CurrentUser, this.ProviderToUse);
388
+ const match = engine.Actions?.find((a) => a.Name === 'Send To Audience');
389
+ this.sendToAudienceActionID = match?.ID ?? null;
390
+ return this.sendToAudienceActionID;
391
+ }
392
+ /**
393
+ * Invoke an Action via the RunAction GraphQL mutation. Same pattern as
394
+ * the Action Test Harness — kept inline here so the resource component
395
+ * stays self-contained.
396
+ */
397
+ async invokeAction(actionID, params) {
398
+ const provider = this.ProviderToUse;
399
+ const query = `
400
+ mutation RunAction($input: RunActionInput!) {
401
+ RunAction(input: $input) {
402
+ Success
403
+ Message
404
+ ResultCode
405
+ ResultData
406
+ }
407
+ }
408
+ `;
409
+ const actionParams = Object.entries(params).map(([Name, Value]) => ({
410
+ Name, Value, Type: 'string',
411
+ }));
412
+ const variables = { input: { ActionID: actionID, Params: actionParams, SkipActionLog: false } };
413
+ const gqlResult = await provider.ExecuteGQL(query, variables);
414
+ if (!gqlResult?.RunAction) {
415
+ throw new Error('RunAction returned no result');
416
+ }
417
+ return gqlResult.RunAction;
418
+ }
419
+ parseResultData(result) {
420
+ if (!result.ResultData)
421
+ return {};
422
+ try {
423
+ const parsed = JSON.parse(result.ResultData);
424
+ // RunAction returns either an object or an array of {Name,Value}.
425
+ if (Array.isArray(parsed)) {
426
+ const out = {};
427
+ for (const item of parsed) {
428
+ if (item && typeof item === 'object' && 'Name' in item && 'Value' in item) {
429
+ out[String(item.Name)] = item.Value;
430
+ }
431
+ }
432
+ return out;
433
+ }
434
+ return parsed;
435
+ }
436
+ catch {
437
+ return {};
438
+ }
439
+ }
440
+ coerceNumber(v) {
441
+ if (typeof v === 'number')
442
+ return v;
443
+ if (typeof v === 'string') {
444
+ const n = Number(v);
445
+ return isNaN(n) ? 0 : n;
446
+ }
447
+ return 0;
448
+ }
449
+ describeSource(s) {
450
+ switch (s.kind) {
451
+ case 'list': return 'List';
452
+ case 'view': return 'User View';
453
+ case 'adhoc': return s.entityName;
454
+ }
455
+ }
456
+ async GetResourceDisplayName(_data) { return 'New Communication'; }
457
+ async GetResourceIconClass(_data) { return 'fa-solid fa-pen-to-square'; }
458
+ static ɵfac = function CommunicationsNewMessageResource_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CommunicationsNewMessageResource)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.MJNotificationService)); };
459
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CommunicationsNewMessageResource, selectors: [["mj-communications-new-message-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 31, vars: 9, consts: [[1, "new-message-resource"], [1, "page-header"], [1, "title-block"], [1, "fa-solid", "fa-message"], [1, "header-actions"], [1, "action-btn", 3, "click", "disabled"], [1, "action-btn", "action-btn--primary", 3, "click", "disabled"], [1, "layout-grid"], [1, "panel"], [1, "panel-header"], [1, "fa-solid", "fa-envelope"], [1, "panel-body"], ["text", "Loading channels...", "size", "small"], [1, "fa-solid", "fa-bullseye"], [3, "SourceChange", "Provider", "Source"], [1, "summary-block", 3, "summary-block--has-skips"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-eye"], [1, "fa-solid", "fa-paper-plane"], [1, "field-label"], [1, "mj-input", "mj-select", 3, "ngModelChange", "ngModel"], [3, "ngValue"], ["type", "text", "placeholder", "sender@example.com", 1, "mj-input", 3, "ngModelChange", "ngModel"], ["type", "text", "placeholder", "Message subject", 1, "mj-input", 3, "ngModelChange", "ngModel"], ["rows", "10", 1, "mj-input", "mj-textarea", 3, "ngModelChange", "ngModel", "placeholder"], [1, "field-label", "field-label--spaced"], ["type", "text", "placeholder", "e.g. Email", 1, "mj-input", 3, "ngModelChange", "ngModel"], [1, "field-hint"], [1, "summary-block"], [1, "summary-row"], [1, "summary-label"], [1, "summary-value"], [1, "summary-row", "summary-row--will-receive"], [1, "summary-row", "summary-row--skipped"], [1, "summary-row", "summary-row--entity"]], template: function CommunicationsNewMessageResource_Template(rf, ctx) { if (rf & 1) {
460
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2);
461
+ i0.ɵɵelement(3, "i", 3);
462
+ i0.ɵɵelementStart(4, "h2");
463
+ i0.ɵɵtext(5, "New Communication");
464
+ i0.ɵɵelementEnd()();
465
+ i0.ɵɵelementStart(6, "div", 4)(7, "button", 5);
466
+ i0.ɵɵlistener("click", function CommunicationsNewMessageResource_Template_button_click_7_listener() { return ctx.onPreviewAudience(); });
467
+ i0.ɵɵconditionalCreate(8, CommunicationsNewMessageResource_Conditional_8_Template, 2, 0)(9, CommunicationsNewMessageResource_Conditional_9_Template, 2, 0);
468
+ i0.ɵɵelementEnd();
469
+ i0.ɵɵelementStart(10, "button", 6);
470
+ i0.ɵɵlistener("click", function CommunicationsNewMessageResource_Template_button_click_10_listener() { return ctx.onSend(); });
471
+ i0.ɵɵconditionalCreate(11, CommunicationsNewMessageResource_Conditional_11_Template, 2, 0)(12, CommunicationsNewMessageResource_Conditional_12_Template, 2, 0);
472
+ i0.ɵɵelementEnd()()();
473
+ i0.ɵɵelementStart(13, "div", 7)(14, "div", 8)(15, "div", 9);
474
+ i0.ɵɵelement(16, "i", 10);
475
+ i0.ɵɵelementStart(17, "h3");
476
+ i0.ɵɵtext(18, "Message");
477
+ i0.ɵɵelementEnd()();
478
+ i0.ɵɵelementStart(19, "div", 11);
479
+ i0.ɵɵconditionalCreate(20, CommunicationsNewMessageResource_Conditional_20_Template, 1, 0, "mj-loading", 12)(21, CommunicationsNewMessageResource_Conditional_21_Template, 17, 8);
480
+ i0.ɵɵelementEnd()();
481
+ i0.ɵɵelementStart(22, "div", 8)(23, "div", 9);
482
+ i0.ɵɵelement(24, "i", 13);
483
+ i0.ɵɵelementStart(25, "h3");
484
+ i0.ɵɵtext(26, "Audience");
485
+ i0.ɵɵelementEnd()();
486
+ i0.ɵɵelementStart(27, "div", 11)(28, "mj-audience-source-picker", 14);
487
+ i0.ɵɵlistener("SourceChange", function CommunicationsNewMessageResource_Template_mj_audience_source_picker_SourceChange_28_listener($event) { return ctx.onAudienceSourceChange($event); });
488
+ i0.ɵɵelementEnd();
489
+ i0.ɵɵconditionalCreate(29, CommunicationsNewMessageResource_Conditional_29_Template, 5, 1);
490
+ i0.ɵɵconditionalCreate(30, CommunicationsNewMessageResource_Conditional_30_Template, 17, 6, "div", 15);
491
+ i0.ɵɵelementEnd()()()();
492
+ } if (rf & 2) {
493
+ i0.ɵɵadvance(7);
494
+ i0.ɵɵproperty("disabled", !ctx.canPreview || ctx.isResolvingAudience || ctx.isSending);
495
+ i0.ɵɵadvance();
496
+ i0.ɵɵconditional(ctx.isResolvingAudience ? 8 : 9);
497
+ i0.ɵɵadvance(2);
498
+ i0.ɵɵproperty("disabled", !ctx.canSend || ctx.isResolvingAudience || ctx.isSending);
499
+ i0.ɵɵadvance();
500
+ i0.ɵɵconditional(ctx.isSending ? 11 : 12);
501
+ i0.ɵɵadvance(9);
502
+ i0.ɵɵconditional(ctx.loadingProviders ? 20 : 21);
503
+ i0.ɵɵadvance(8);
504
+ i0.ɵɵproperty("Provider", ctx.Provider)("Source", ctx.audienceSource);
505
+ i0.ɵɵadvance();
506
+ i0.ɵɵconditional(ctx.audienceSource ? 29 : -1);
507
+ i0.ɵɵadvance();
508
+ i0.ɵɵconditional(ctx.audienceSummary ? 30 : -1);
509
+ } }, dependencies: [i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.LoadingComponent, i4.AudienceSourcePickerComponent], styles: [".new-message-resource[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 16px 24px;\n height: 100%;\n overflow: auto;\n }\n .page-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n }\n .title-block[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 12px; }\n .title-block[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 20px; color: var(--mj-brand-primary); }\n .title-block[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] { margin: 0; font-size: 18px; font-weight: 600; color: var(--mj-text-primary); }\n .header-actions[_ngcontent-%COMP%] { display: flex; gap: 8px; }\n .action-btn[_ngcontent-%COMP%] {\n padding: 8px 14px;\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 13px;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n .action-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n }\n .action-btn[_ngcontent-%COMP%]:disabled { opacity: 0.55; cursor: not-allowed; }\n .action-btn--primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n }\n .action-btn--primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n }\n\n .layout-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 380px;\n gap: 16px;\n align-items: start;\n }\n @media (max-width: 1024px) {\n .layout-grid[_ngcontent-%COMP%] { grid-template-columns: 1fr; }\n }\n\n .panel[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n .panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n }\n .panel-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-text-secondary); }\n .panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n .panel-body[_ngcontent-%COMP%] { padding: 16px; }\n\n .field-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n margin: 12px 0 6px;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n }\n .field-label--spaced[_ngcontent-%COMP%] { margin-top: 20px; }\n .field-hint[_ngcontent-%COMP%] {\n font-size: 11.5px;\n color: var(--mj-text-muted);\n margin: 6px 0 0;\n }\n\n .summary-block[_ngcontent-%COMP%] {\n margin-top: 20px;\n padding: 12px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n }\n .summary-block--has-skips[_ngcontent-%COMP%] {\n border-color: var(--mj-status-warning);\n background: color-mix(in srgb, var(--mj-status-warning) 6%, var(--mj-bg-surface-card));\n }\n .summary-row[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n gap: 16px;\n font-size: 13px;\n padding: 4px 0;\n }\n .summary-row[_ngcontent-%COMP%] + .summary-row[_ngcontent-%COMP%] { border-top: 1px solid var(--mj-border-subtle); }\n .summary-label[_ngcontent-%COMP%] { color: var(--mj-text-secondary); }\n .summary-value[_ngcontent-%COMP%] { font-weight: 600; color: var(--mj-text-primary); }\n .summary-row--will-receive[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] { color: var(--mj-status-success); }\n .summary-row--skipped[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] { color: var(--mj-status-warning); }\n .summary-row--entity[_ngcontent-%COMP%] .summary-label[_ngcontent-%COMP%], \n .summary-row--entity[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 11.5px;\n color: var(--mj-text-muted);\n font-weight: 500;\n }"] });
510
+ };
511
+ CommunicationsNewMessageResource = __decorate([
512
+ RegisterClass(BaseResourceComponent, 'CommunicationsNewMessageResource')
513
+ ], CommunicationsNewMessageResource);
514
+ export { CommunicationsNewMessageResource };
515
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CommunicationsNewMessageResource, [{
516
+ type: Component,
517
+ args: [{ standalone: false, selector: 'mj-communications-new-message-resource', template: `
518
+ <div class="new-message-resource">
519
+ <div class="page-header">
520
+ <div class="title-block">
521
+ <i class="fa-solid fa-message"></i>
522
+ <h2>New Communication</h2>
523
+ </div>
524
+ <div class="header-actions">
525
+ <button
526
+ class="action-btn"
527
+ (click)="onPreviewAudience()"
528
+ [disabled]="!canPreview || isResolvingAudience || isSending">
529
+ @if (isResolvingAudience) {
530
+ <i class="fa-solid fa-spinner fa-spin"></i> Previewing…
531
+ } @else {
532
+ <i class="fa-solid fa-eye"></i> Preview Audience
533
+ }
534
+ </button>
535
+ <button
536
+ class="action-btn action-btn--primary"
537
+ (click)="onSend()"
538
+ [disabled]="!canSend || isResolvingAudience || isSending">
539
+ @if (isSending) {
540
+ <i class="fa-solid fa-spinner fa-spin"></i> Sending…
541
+ } @else {
542
+ <i class="fa-solid fa-paper-plane"></i> Send
543
+ }
544
+ </button>
545
+ </div>
546
+ </div>
547
+
548
+ <div class="layout-grid">
549
+ <!-- Message panel -->
550
+ <div class="panel">
551
+ <div class="panel-header">
552
+ <i class="fa-solid fa-envelope"></i>
553
+ <h3>Message</h3>
554
+ </div>
555
+ <div class="panel-body">
556
+ @if (loadingProviders) {
557
+ <mj-loading text="Loading channels..." size="small"></mj-loading>
558
+ } @else {
559
+ <label class="field-label">Channel</label>
560
+ <select
561
+ class="mj-input mj-select"
562
+ [(ngModel)]="selectedProviderID"
563
+ (ngModelChange)="onProviderChange()">
564
+ <option [ngValue]="null">Select a channel…</option>
565
+ @for (p of providers; track p.ID) {
566
+ <option [ngValue]="p.ID">{{ p.Name }}</option>
567
+ }
568
+ </select>
569
+
570
+ @if (filteredMessageTypes.length > 0) {
571
+ <label class="field-label">Message type</label>
572
+ <select class="mj-input mj-select" [(ngModel)]="selectedMessageTypeID">
573
+ <option [ngValue]="null">Select a message type…</option>
574
+ @for (mt of filteredMessageTypes; track mt.ID) {
575
+ <option [ngValue]="mt.ID">{{ mt.Name }}</option>
576
+ }
577
+ </select>
578
+ }
579
+
580
+ <label class="field-label">From</label>
581
+ <input
582
+ class="mj-input"
583
+ type="text"
584
+ [(ngModel)]="fromAddress"
585
+ placeholder="sender@example.com" />
586
+
587
+ <label class="field-label">Subject</label>
588
+ <input
589
+ class="mj-input"
590
+ type="text"
591
+ [(ngModel)]="subject"
592
+ placeholder="Message subject" />
593
+
594
+ <label class="field-label">Body</label>
595
+ <textarea
596
+ class="mj-input mj-textarea"
597
+ [(ngModel)]="body"
598
+ rows="10"
599
+ placeholder="Hi {{ '{{FirstName}}' }},..."></textarea>
600
+ }
601
+ </div>
602
+ </div>
603
+
604
+ <!-- Audience panel -->
605
+ <div class="panel">
606
+ <div class="panel-header">
607
+ <i class="fa-solid fa-bullseye"></i>
608
+ <h3>Audience</h3>
609
+ </div>
610
+ <div class="panel-body">
611
+ <mj-audience-source-picker
612
+ [Provider]="Provider"
613
+ [Source]="audienceSource"
614
+ (SourceChange)="onAudienceSourceChange($event)">
615
+ </mj-audience-source-picker>
616
+
617
+ @if (audienceSource) {
618
+ <label class="field-label field-label--spaced">Recipient field</label>
619
+ <input
620
+ class="mj-input"
621
+ type="text"
622
+ [(ngModel)]="recipientField"
623
+ placeholder="e.g. Email" />
624
+ <p class="field-hint">
625
+ Field on the audience entity that holds the recipient address.
626
+ Records with no value will be skipped.
627
+ </p>
628
+ }
629
+
630
+ @if (audienceSummary) {
631
+ <div class="summary-block" [class.summary-block--has-skips]="audienceSummary.SkippedCount > 0">
632
+ <div class="summary-row">
633
+ <span class="summary-label">Total audience</span>
634
+ <span class="summary-value">{{ audienceSummary.TotalAudienceSize }}</span>
635
+ </div>
636
+ <div class="summary-row summary-row--will-receive">
637
+ <span class="summary-label">Will receive</span>
638
+ <span class="summary-value">{{ audienceSummary.WillReceiveCount }}</span>
639
+ </div>
640
+ @if (audienceSummary.SkippedCount > 0) {
641
+ <div class="summary-row summary-row--skipped">
642
+ <span class="summary-label">Skipped (missing {{ recipientField || 'recipient' }})</span>
643
+ <span class="summary-value">{{ audienceSummary.SkippedCount }}</span>
644
+ </div>
645
+ }
646
+ <div class="summary-row summary-row--entity">
647
+ <span class="summary-label">Entity</span>
648
+ <span class="summary-value">{{ audienceSummary.EntityName }}</span>
649
+ </div>
650
+ </div>
651
+ }
652
+ </div>
653
+ </div>
654
+ </div>
655
+ </div>
656
+ `, styles: ["\n .new-message-resource {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 16px 24px;\n height: 100%;\n overflow: auto;\n }\n .page-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n }\n .title-block { display: flex; align-items: center; gap: 12px; }\n .title-block i { font-size: 20px; color: var(--mj-brand-primary); }\n .title-block h2 { margin: 0; font-size: 18px; font-weight: 600; color: var(--mj-text-primary); }\n .header-actions { display: flex; gap: 8px; }\n .action-btn {\n padding: 8px 14px;\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 13px;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n .action-btn:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n }\n .action-btn:disabled { opacity: 0.55; cursor: not-allowed; }\n .action-btn--primary {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n }\n .action-btn--primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n }\n\n .layout-grid {\n display: grid;\n grid-template-columns: 1fr 380px;\n gap: 16px;\n align-items: start;\n }\n @media (max-width: 1024px) {\n .layout-grid { grid-template-columns: 1fr; }\n }\n\n .panel {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n .panel-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n }\n .panel-header i { color: var(--mj-text-secondary); }\n .panel-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n .panel-body { padding: 16px; }\n\n .field-label {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n margin: 12px 0 6px;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n }\n .field-label--spaced { margin-top: 20px; }\n .field-hint {\n font-size: 11.5px;\n color: var(--mj-text-muted);\n margin: 6px 0 0;\n }\n\n .summary-block {\n margin-top: 20px;\n padding: 12px 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n }\n .summary-block--has-skips {\n border-color: var(--mj-status-warning);\n background: color-mix(in srgb, var(--mj-status-warning) 6%, var(--mj-bg-surface-card));\n }\n .summary-row {\n display: flex;\n justify-content: space-between;\n gap: 16px;\n font-size: 13px;\n padding: 4px 0;\n }\n .summary-row + .summary-row { border-top: 1px solid var(--mj-border-subtle); }\n .summary-label { color: var(--mj-text-secondary); }\n .summary-value { font-weight: 600; color: var(--mj-text-primary); }\n .summary-row--will-receive .summary-value { color: var(--mj-status-success); }\n .summary-row--skipped .summary-value { color: var(--mj-status-warning); }\n .summary-row--entity .summary-label,\n .summary-row--entity .summary-value {\n font-size: 11.5px;\n color: var(--mj-text-muted);\n font-weight: 500;\n }\n "] }]
657
+ }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.MJNotificationService }], null); })();
658
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CommunicationsNewMessageResource, { className: "CommunicationsNewMessageResource", filePath: "src/Communication/communication-new-message-resource.component.ts", lineNumber: 311 }); })();
659
+ /** Tree-shaking prevention */
660
+ export function LoadCommunicationsNewMessageResource() { }
661
+ //# sourceMappingURL=communication-new-message-resource.component.js.map