@memberjunction/ng-dashboards 6.2.0-edge.6 → 6.2.0-edge.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +23 -16
  2. package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js +2 -2
  3. package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js.map +1 -1
  4. package/dist/AI/components/analytics/realtime/realtime-management.component.d.ts.map +1 -1
  5. package/dist/AI/components/analytics/realtime/realtime-management.component.js +3 -1
  6. package/dist/AI/components/analytics/realtime/realtime-management.component.js.map +1 -1
  7. package/dist/AI/components/analytics/realtime/realtime-overview.component.d.ts +1 -1
  8. package/dist/AI/components/analytics/realtime/realtime-overview.component.js +3 -3
  9. package/dist/AI/components/analytics/realtime/realtime-overview.component.js.map +1 -1
  10. package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts +6 -4
  11. package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts.map +1 -1
  12. package/dist/AI/components/analytics/realtime/realtime-session-data.js +8 -2
  13. package/dist/AI/components/analytics/realtime/realtime-session-data.js.map +1 -1
  14. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +6 -6
  15. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  16. package/dist/AI/components/autotagging/components/classify-item-grid.component.js +1 -1
  17. package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -1
  18. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -1
  19. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +1 -0
  20. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -1
  21. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -1
  22. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +1 -0
  23. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -1
  24. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -1
  25. package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1 -0
  26. package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -1
  27. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  28. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +1 -0
  29. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  30. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +2 -2
  31. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  32. package/dist/AI/components/tags/tags-resource.component.js +3 -2
  33. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  34. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  35. package/dist/AI/components/vectors/vector-management-resource.component.js +12 -6
  36. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  37. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
  38. package/dist/AI/services/ai-instrumentation.service.js +4 -2
  39. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  40. package/dist/Actions/action-result-code.d.ts +80 -0
  41. package/dist/Actions/action-result-code.d.ts.map +1 -0
  42. package/dist/Actions/action-result-code.js +163 -0
  43. package/dist/Actions/action-result-code.js.map +1 -0
  44. package/dist/Actions/components/actions-overview.component.d.ts +8 -0
  45. package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
  46. package/dist/Actions/components/actions-overview.component.js +12 -9
  47. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  48. package/dist/Actions/components/execution-monitoring.component.d.ts +29 -9
  49. package/dist/Actions/components/execution-monitoring.component.d.ts.map +1 -1
  50. package/dist/Actions/components/execution-monitoring.component.js +65 -42
  51. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  52. package/dist/Actions/components/explorer/action-card.component.d.ts.map +1 -1
  53. package/dist/Actions/components/explorer/action-card.component.js +5 -4
  54. package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
  55. package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts +92 -130
  56. package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts.map +1 -1
  57. package/dist/ChiefOfStaff/chief-of-staff-agent-context.js +189 -274
  58. package/dist/ChiefOfStaff/chief-of-staff-agent-context.js.map +1 -1
  59. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.d.ts +29 -0
  60. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.d.ts.map +1 -0
  61. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.js +666 -0
  62. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.js.map +1 -0
  63. package/dist/ChiefOfStaff/chief-of-staff-governance.component.d.ts +56 -0
  64. package/dist/ChiefOfStaff/chief-of-staff-governance.component.d.ts.map +1 -0
  65. package/dist/ChiefOfStaff/chief-of-staff-governance.component.js +515 -0
  66. package/dist/ChiefOfStaff/chief-of-staff-governance.component.js.map +1 -0
  67. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.d.ts +14 -0
  68. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.d.ts.map +1 -0
  69. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.js +39 -0
  70. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.js.map +1 -0
  71. package/dist/ChiefOfStaff/chief-of-staff-overview.component.d.ts +17 -0
  72. package/dist/ChiefOfStaff/chief-of-staff-overview.component.d.ts.map +1 -0
  73. package/dist/ChiefOfStaff/chief-of-staff-overview.component.js +485 -0
  74. package/dist/ChiefOfStaff/chief-of-staff-overview.component.js.map +1 -0
  75. package/dist/ChiefOfStaff/chief-of-staff-page-base.d.ts +139 -0
  76. package/dist/ChiefOfStaff/chief-of-staff-page-base.d.ts.map +1 -0
  77. package/dist/ChiefOfStaff/chief-of-staff-page-base.js +602 -0
  78. package/dist/ChiefOfStaff/chief-of-staff-page-base.js.map +1 -0
  79. package/dist/ChiefOfStaff/index.d.ts +4 -1
  80. package/dist/ChiefOfStaff/index.d.ts.map +1 -1
  81. package/dist/ChiefOfStaff/index.js +4 -1
  82. package/dist/ChiefOfStaff/index.js.map +1 -1
  83. package/dist/Communication/communication-monitor-resource.component.js +3 -3
  84. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  85. package/dist/Communication/communication-runs-resource.component.js +3 -3
  86. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  87. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
  88. package/dist/ComponentStudio/component-studio-dashboard.component.js +1 -0
  89. package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
  90. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
  91. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +2 -1
  92. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
  93. package/dist/ComponentStudio/services/component-version.service.d.ts.map +1 -1
  94. package/dist/ComponentStudio/services/component-version.service.js +3 -0
  95. package/dist/ComponentStudio/services/component-version.service.js.map +1 -1
  96. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +21 -2
  97. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  98. package/dist/DataExplorer/data-explorer-dashboard.component.js +32 -5
  99. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  100. package/dist/DevTools/graphql-console.component.js +2 -2
  101. package/dist/DevTools/lazy-module-status.component.js +2 -2
  102. package/dist/FormBuilder/form-builder-resource.component.d.ts.map +1 -1
  103. package/dist/FormBuilder/form-builder-resource.component.js +5 -0
  104. package/dist/FormBuilder/form-builder-resource.component.js.map +1 -1
  105. package/dist/Integration/components/connections/connections.component.js +2 -2
  106. package/dist/Integration/services/integration-data.service.d.ts +1 -1
  107. package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
  108. package/dist/Integration/services/integration-data.service.js +4 -3
  109. package/dist/Integration/services/integration-data.service.js.map +1 -1
  110. package/dist/Lists/components/lists-browse-resource.component.js +1 -1
  111. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  112. package/dist/Lists/components/lists-my-lists-resource.component.js +1 -1
  113. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  114. package/dist/LoginStudio/login-studio-resource.component.d.ts.map +1 -1
  115. package/dist/LoginStudio/login-studio-resource.component.js +1 -0
  116. package/dist/LoginStudio/login-studio-resource.component.js.map +1 -1
  117. package/dist/PredictiveStudio/components/ps-experiments.component.d.ts.map +1 -1
  118. package/dist/PredictiveStudio/components/ps-experiments.component.js +1 -0
  119. package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
  120. package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js +2 -2
  121. package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts.map +1 -1
  122. package/dist/PredictiveStudio/components/ps-predictions-grid.component.js +3 -0
  123. package/dist/PredictiveStudio/components/ps-predictions-grid.component.js.map +1 -1
  124. package/dist/PredictiveStudio/engine/predictive-studio.engine.d.ts.map +1 -1
  125. package/dist/PredictiveStudio/engine/predictive-studio.engine.js +1 -0
  126. package/dist/PredictiveStudio/engine/predictive-studio.engine.js.map +1 -1
  127. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
  128. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +1 -0
  129. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
  130. package/dist/QueryBrowser/query-browser-resource.component.d.ts +26 -0
  131. package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
  132. package/dist/QueryBrowser/query-browser-resource.component.js +375 -252
  133. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  134. package/dist/UserRoutines/user-routines-resource.component.d.ts +8 -1
  135. package/dist/UserRoutines/user-routines-resource.component.d.ts.map +1 -1
  136. package/dist/UserRoutines/user-routines-resource.component.js +22 -4
  137. package/dist/UserRoutines/user-routines-resource.component.js.map +1 -1
  138. package/dist/VersionHistory/components/diff-resource.component.d.ts.map +1 -1
  139. package/dist/VersionHistory/components/diff-resource.component.js +1 -0
  140. package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
  141. package/dist/VideoStudio/components/vs-archetype-editor.component.d.ts +162 -0
  142. package/dist/VideoStudio/components/vs-archetype-editor.component.d.ts.map +1 -0
  143. package/dist/VideoStudio/components/vs-archetype-editor.component.js +1105 -0
  144. package/dist/VideoStudio/components/vs-archetype-editor.component.js.map +1 -0
  145. package/dist/VideoStudio/components/vs-audio-options.component.d.ts +27 -0
  146. package/dist/VideoStudio/components/vs-audio-options.component.d.ts.map +1 -0
  147. package/dist/VideoStudio/components/vs-audio-options.component.js +119 -0
  148. package/dist/VideoStudio/components/vs-audio-options.component.js.map +1 -0
  149. package/dist/VideoStudio/components/vs-copilot-panel.component.d.ts +105 -0
  150. package/dist/VideoStudio/components/vs-copilot-panel.component.d.ts.map +1 -0
  151. package/dist/VideoStudio/components/vs-copilot-panel.component.js +560 -0
  152. package/dist/VideoStudio/components/vs-copilot-panel.component.js.map +1 -0
  153. package/dist/VideoStudio/components/vs-production-brief.component.d.ts +163 -0
  154. package/dist/VideoStudio/components/vs-production-brief.component.d.ts.map +1 -0
  155. package/dist/VideoStudio/components/vs-production-brief.component.js +1054 -0
  156. package/dist/VideoStudio/components/vs-production-brief.component.js.map +1 -0
  157. package/dist/VideoStudio/components/vs-setup-health-card.component.d.ts +43 -0
  158. package/dist/VideoStudio/components/vs-setup-health-card.component.d.ts.map +1 -0
  159. package/dist/VideoStudio/components/vs-setup-health-card.component.js +412 -0
  160. package/dist/VideoStudio/components/vs-setup-health-card.component.js.map +1 -0
  161. package/dist/VideoStudio/components/vs-studio-slide-in.component.d.ts +73 -0
  162. package/dist/VideoStudio/components/vs-studio-slide-in.component.d.ts.map +1 -0
  163. package/dist/VideoStudio/components/vs-studio-slide-in.component.js +271 -0
  164. package/dist/VideoStudio/components/vs-studio-slide-in.component.js.map +1 -0
  165. package/dist/VideoStudio/index.d.ts +12 -0
  166. package/dist/VideoStudio/index.d.ts.map +1 -0
  167. package/dist/VideoStudio/index.js +12 -0
  168. package/dist/VideoStudio/index.js.map +1 -0
  169. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.d.ts +118 -0
  170. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.d.ts.map +1 -0
  171. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.js +964 -0
  172. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.js.map +1 -0
  173. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.d.ts +70 -0
  174. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.d.ts.map +1 -0
  175. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.js +600 -0
  176. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.js.map +1 -0
  177. package/dist/VideoStudio/resources/video-studio-productions-resource.component.d.ts +182 -0
  178. package/dist/VideoStudio/resources/video-studio-productions-resource.component.d.ts.map +1 -0
  179. package/dist/VideoStudio/resources/video-studio-productions-resource.component.js +1481 -0
  180. package/dist/VideoStudio/resources/video-studio-productions-resource.component.js.map +1 -0
  181. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.d.ts +102 -0
  182. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.d.ts.map +1 -0
  183. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.js +240 -0
  184. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.js.map +1 -0
  185. package/dist/VideoStudio/video-studio-agent-context.d.ts +495 -0
  186. package/dist/VideoStudio/video-studio-agent-context.d.ts.map +1 -0
  187. package/dist/VideoStudio/video-studio-agent-context.js +992 -0
  188. package/dist/VideoStudio/video-studio-agent-context.js.map +1 -0
  189. package/dist/ai-dashboards.module.d.ts +25 -22
  190. package/dist/ai-dashboards.module.d.ts.map +1 -1
  191. package/dist/ai-dashboards.module.js +23 -7
  192. package/dist/ai-dashboards.module.js.map +1 -1
  193. package/dist/module.d.ts +13 -12
  194. package/dist/module.d.ts.map +1 -1
  195. package/dist/module.js +7 -0
  196. package/dist/module.js.map +1 -1
  197. package/dist/public-api.d.ts +7 -1
  198. package/dist/public-api.d.ts.map +1 -1
  199. package/dist/public-api.js +9 -2
  200. package/dist/public-api.js.map +1 -1
  201. package/dist/shared/action-scheduled-job.d.ts.map +1 -1
  202. package/dist/shared/action-scheduled-job.js +2 -0
  203. package/dist/shared/action-scheduled-job.js.map +1 -1
  204. package/dist/video-studio-dashboards.module.d.ts +40 -0
  205. package/dist/video-studio-dashboards.module.d.ts.map +1 -0
  206. package/dist/video-studio-dashboards.module.js +159 -0
  207. package/dist/video-studio-dashboards.module.js.map +1 -0
  208. package/package.json +77 -71
  209. package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts +0 -195
  210. package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts.map +0 -1
  211. package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js +0 -2910
  212. package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js.map +0 -1
@@ -0,0 +1,602 @@
1
+ import { ChangeDetectorRef, Directive, inject } from '@angular/core';
2
+ import { Subject } from 'rxjs';
3
+ import { debounceTime, filter, takeUntil } from 'rxjs/operators';
4
+ import { CompositeKey, LogError, RunView } from '@memberjunction/core';
5
+ import { MJEnvironmentEntityExtended, } from '@memberjunction/core-entities';
6
+ import { UUIDMap, MJGlobal, EscapeSQLString } from '@memberjunction/global';
7
+ import { GraphQLActionClient } from '@memberjunction/graphql-dataprovider';
8
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
9
+ import { ApplicationManager } from '@memberjunction/ng-base-application';
10
+ import { MJNotificationService } from '@memberjunction/ng-notifications';
11
+ import { AIEngineBase } from '@memberjunction/ai-engine-base';
12
+ import { BuildChiefOfStaffAgentContext, BuildChiefOfStaffScopeFilters, BuildGovernanceSummary, BuildPolicyDraftFromEntity, CalculateChiefOfStaffMetrics, CHIEF_OF_STAFF_AGENT_NAME, CHIEF_OF_STAFF_APP_NAME, CHIEF_OF_STAFF_PAGE_ICONS, CHIEF_OF_STAFF_PAGE_LABELS, CHIEF_OF_STAFF_PAGES, ChiefOfStaffDisplayName, FormatEmailDraftForClipboard, IsApprovalRequest, IsSpentOneShotRoutine, ParseEmailApprovalPayload, RoutineDisplayStatus, SortRoutinesForDisplay, ValidateChiefOfStaffPageParam, } from './chief-of-staff-agent-context';
13
+ import { IsChiefOfStaffEntityChange } from './chief-of-staff-live-refresh';
14
+ import * as i0 from "@angular/core";
15
+ /**
16
+ * Shared base of the Chief of Staff application's pages. Each page is its own nav item
17
+ * (Overview, Approvals & Wakes, Governance) and its own resource component; this class holds
18
+ * what they share: the user's policy, wake routines and approval requests, the request and
19
+ * routine actions, the briefing reader, live reload and the agent context.
20
+ *
21
+ * Other apps add pages to the Chief of Staff application as nav items, through `NavItem.*`
22
+ * application settings; they do not extend this class.
23
+ */
24
+ export class BaseChiefOfStaffPage extends BaseResourceComponent {
25
+ cdr = inject(ChangeDetectorRef);
26
+ appManager = inject(ApplicationManager);
27
+ destroy$ = new Subject();
28
+ IsLoading = true;
29
+ BusyRequestID = null;
30
+ BusyRoutineID = null;
31
+ FeedbackBanner = null;
32
+ /** Filters requests and routines on pages that show a search box. */
33
+ SearchText = '';
34
+ PolicyEntity = null;
35
+ /** The policy as the pages show it; the Governance page edits it. */
36
+ DraftPolicy = BuildPolicyDraftFromEntity(null);
37
+ Routines = [];
38
+ Requests = [];
39
+ Metrics = CalculateChiefOfStaffMetrics([], []);
40
+ SelectedRequest = null;
41
+ ShowRequestDialog = false;
42
+ // ── Briefing reader: a wake routine's conversation, read without leaving the page ────
43
+ /** The routine whose briefings the reader shows; null while the reader is closed. */
44
+ BriefingRoutine = null;
45
+ /** The routine's conversation ID, bound to the embedded chat area. */
46
+ BriefingConversationId = null;
47
+ /** The conversation entity when it could be loaded (title, pinned agent); the chat area loads messages by ID either way. */
48
+ BriefingConversation = null;
49
+ /** Resolved once per load from the agent's metadata name; null until LoadChiefOfStaffData has run. */
50
+ chiefOfStaffAgentId = null;
51
+ get ChiefOfStaffDisplayName() {
52
+ return ChiefOfStaffDisplayName(this.DraftPolicy);
53
+ }
54
+ /** Approval requests awaiting a decision, filtered by the search text. */
55
+ get PendingRequests() {
56
+ const search = this.SearchText.trim().toLowerCase();
57
+ return this.Requests.filter((r) => {
58
+ if (r.Status !== 'Requested' || !IsApprovalRequest(r)) {
59
+ return false;
60
+ }
61
+ if (!search) {
62
+ return true;
63
+ }
64
+ return (r.Request ?? '').toLowerCase().includes(search);
65
+ });
66
+ }
67
+ /** Routines in display order: next wake first, unscheduled next, spent one-shots last. */
68
+ get SortedRoutines() {
69
+ return SortRoutinesForDisplay(this.Routines);
70
+ }
71
+ /** Routines that still have something ahead of them: everything but spent one-shots. */
72
+ get UpcomingRoutines() {
73
+ return this.SortedRoutines.filter((r) => !IsSpentOneShotRoutine(r));
74
+ }
75
+ /** 'Fired' for a spent one-shot, otherwise the routine's Status. */
76
+ RoutineStatusLabel(routine) {
77
+ return RoutineDisplayStatus(routine);
78
+ }
79
+ IsSpentRoutine(routine) {
80
+ return IsSpentOneShotRoutine(routine);
81
+ }
82
+ async ngOnInit() {
83
+ super.ngOnInit();
84
+ this.OnPageInit();
85
+ await this.LoadChiefOfStaffData();
86
+ this.navigationService.SetAgentClientTools(this, [...this.coreAgentTools(), ...this.PageAgentTools()]);
87
+ this.navigationService.ResourceReattached$.pipe(filter((c) => c === this), takeUntil(this.destroy$)).subscribe(() => this.publishAgentContext());
88
+ this.subscribeToLiveEntityChanges();
89
+ this.NotifyLoadComplete();
90
+ }
91
+ ngOnDestroy() {
92
+ super.ngOnDestroy();
93
+ this.destroy$.next();
94
+ this.destroy$.complete();
95
+ }
96
+ async GetResourceDisplayName(_data) {
97
+ return CHIEF_OF_STAFF_PAGE_LABELS[this.Page];
98
+ }
99
+ async GetResourceIconClass(_data) {
100
+ return CHIEF_OF_STAFF_PAGE_ICONS[this.Page];
101
+ }
102
+ /** Runs before the first load; a page reads its query params here. */
103
+ OnPageInit() {
104
+ // default: nothing
105
+ }
106
+ /** Runs after every load, before the agent context is published. */
107
+ OnDataLoaded() {
108
+ // default: nothing
109
+ }
110
+ /** Client tools only this page offers, added to the shared ones. */
111
+ PageAgentTools() {
112
+ return [];
113
+ }
114
+ /** A change arrived while the tab was detached; reload once when it is shown again. */
115
+ liveReloadPending = false;
116
+ /**
117
+ * Reloads the page when an entity it shows changes anywhere. MJAPI broadcasts every save
118
+ * and delete to browsers, including saves made by server-side code (a wake run creating an
119
+ * approval request or a run row), and the client raises each as a `remote-invalidate`
120
+ * BaseEntity event. A burst of events is one reload. A detached tab does not reload in the
121
+ * background; it reloads once when it is shown again.
122
+ */
123
+ subscribeToLiveEntityChanges() {
124
+ MJGlobal.Instance.GetEventListener(false).pipe(filter((event) => IsChiefOfStaffEntityChange(event)), debounceTime(750), takeUntil(this.destroy$)).subscribe(() => {
125
+ if (this.navigationService.IsResourceDetached(this)) {
126
+ this.liveReloadPending = true;
127
+ return;
128
+ }
129
+ void this.LoadChiefOfStaffData();
130
+ });
131
+ this.navigationService.ResourceReattached$.pipe(filter((c) => c === this && this.liveReloadPending), takeUntil(this.destroy$)).subscribe(() => {
132
+ this.liveReloadPending = false;
133
+ void this.LoadChiefOfStaffData();
134
+ });
135
+ }
136
+ async LoadChiefOfStaffData() {
137
+ this.IsLoading = true;
138
+ this.cdr.markForCheck();
139
+ try {
140
+ const rv = RunView.FromMetadataProvider(this.ProviderToUse);
141
+ const currentUserId = this.ProviderToUse.CurrentUser?.ID;
142
+ if (!currentUserId) {
143
+ // Every query is user-scoped; without a user there is nothing safe to show.
144
+ this.showBanner('error', 'No signed-in user is available; the Chief of Staff cannot load.');
145
+ return;
146
+ }
147
+ const chiefOfStaffAgentId = await this.resolveChiefOfStaffAgentId();
148
+ if (!chiefOfStaffAgentId) {
149
+ this.showBanner('error', `The "${CHIEF_OF_STAFF_AGENT_NAME}" agent is not installed in this environment.`);
150
+ return;
151
+ }
152
+ this.chiefOfStaffAgentId = chiefOfStaffAgentId;
153
+ const scope = BuildChiefOfStaffScopeFilters(currentUserId, chiefOfStaffAgentId);
154
+ const viewParams = [
155
+ {
156
+ EntityName: 'MJ: AI Agent User Policies',
157
+ ExtraFilter: scope.Policy,
158
+ OrderBy: '__mj_UpdatedAt DESC',
159
+ ResultType: 'entity_object',
160
+ },
161
+ {
162
+ EntityName: 'MJ: User Routines',
163
+ ExtraFilter: scope.Routines,
164
+ OrderBy: 'NextRunAt ASC, Name ASC',
165
+ ResultType: 'entity_object',
166
+ },
167
+ {
168
+ EntityName: 'MJ: AI Agent Requests',
169
+ ExtraFilter: scope.Requests,
170
+ OrderBy: 'Priority DESC, RequestedAt DESC',
171
+ MaxRows: 100,
172
+ ResultType: 'entity_object',
173
+ },
174
+ ];
175
+ const [policyRes, routineRes, requestRes] = await rv.RunViews(viewParams);
176
+ const policies = policyRes?.Success
177
+ ? policyRes.Results
178
+ : [];
179
+ this.PolicyEntity = policies.length > 0 ? policies[0] : null;
180
+ this.DraftPolicy = BuildPolicyDraftFromEntity(this.PolicyEntity);
181
+ this.Routines = routineRes?.Success
182
+ ? routineRes.Results
183
+ : [];
184
+ this.emailDraftsByRequest.Clear();
185
+ this.Requests = requestRes?.Success
186
+ ? requestRes.Results
187
+ : [];
188
+ this.recalculateMetrics();
189
+ this.OnDataLoaded();
190
+ }
191
+ catch (err) {
192
+ const msg = err instanceof Error ? err.message : String(err);
193
+ this.showBanner('error', `Failed to load Chief of Staff data: ${msg}`);
194
+ }
195
+ finally {
196
+ this.IsLoading = false;
197
+ this.publishAgentContext();
198
+ this.cdr.markForCheck();
199
+ }
200
+ }
201
+ recalculateMetrics() {
202
+ this.Metrics = CalculateChiefOfStaffMetrics(this.Routines.map((r) => this.toRoutineSummary(r)), this.Requests.map((r) => this.toRequestSummary(r)));
203
+ }
204
+ toRoutineSummary(r) {
205
+ return {
206
+ ID: r.ID,
207
+ Name: r.Name,
208
+ Status: r.Status,
209
+ ScheduleMode: r.ScheduleMode,
210
+ CronExpression: r.CronExpression,
211
+ NextRunAt: r.NextRunAt,
212
+ LastRunAt: r.LastRunAt,
213
+ LastRunStatus: r.LastRunStatus,
214
+ };
215
+ }
216
+ toRequestSummary(req) {
217
+ return {
218
+ ID: req.ID,
219
+ Request: req.Request,
220
+ Status: req.Status,
221
+ Priority: req.Priority,
222
+ RequestedAt: req.RequestedAt,
223
+ ExpiresAt: req.ExpiresAt,
224
+ RequestType: req.RequestType,
225
+ RequestTypeID: req.RequestTypeID,
226
+ };
227
+ }
228
+ /**
229
+ * Looks the Chief of Staff agent up by name through the AI engine's cached agents, so the
230
+ * pages carry no hardcoded agent id and follow whichever provider they are embedded under.
231
+ */
232
+ async resolveChiefOfStaffAgentId() {
233
+ const engine = AIEngineBase.GetProviderInstance(this.ProviderToUse, AIEngineBase);
234
+ await engine.EnsureLoaded(this.ProviderToUse.CurrentUser, this.ProviderToUse);
235
+ const agent = engine.GetAgentByName(CHIEF_OF_STAFF_AGENT_NAME);
236
+ return agent?.ID ?? null;
237
+ }
238
+ actionIdsByName = new Map();
239
+ /** The ID of a core action, looked up by name once per page instance. */
240
+ async resolveActionIdByName(actionName) {
241
+ const cached = this.actionIdsByName.get(actionName);
242
+ if (cached) {
243
+ return cached;
244
+ }
245
+ try {
246
+ const rv = RunView.FromMetadataProvider(this.ProviderToUse);
247
+ const result = await rv.RunView({
248
+ EntityName: 'MJ: Actions',
249
+ ExtraFilter: `Name = '${EscapeSQLString(actionName)}'`,
250
+ Fields: ['ID'],
251
+ MaxRows: 1,
252
+ SkipTotalRowCount: true,
253
+ ResultType: 'simple',
254
+ });
255
+ if (result.Success && result.Results && result.Results.length > 0) {
256
+ this.actionIdsByName.set(actionName, result.Results[0].ID);
257
+ return result.Results[0].ID;
258
+ }
259
+ return null;
260
+ }
261
+ catch (err) {
262
+ const msg = err instanceof Error ? err.message : String(err);
263
+ LogError(`Chief of Staff: failed to resolve '${actionName}' action: ${msg}`);
264
+ return null;
265
+ }
266
+ }
267
+ // =========================================================================
268
+ // Navigation between the Chief of Staff pages
269
+ // =========================================================================
270
+ /** Opens another Chief of Staff page through its nav item. */
271
+ OpenPage(page) {
272
+ const app = this.appManager.GetAppByName(CHIEF_OF_STAFF_APP_NAME);
273
+ void this.navigationService.OpenNavItemByName(CHIEF_OF_STAFF_PAGE_LABELS[page], undefined, app?.ID);
274
+ }
275
+ // =========================================================================
276
+ // Briefings: where a wake routine's replies live
277
+ // =========================================================================
278
+ //
279
+ // A wake writes its reply into the routine's own conversation, which is application-scoped
280
+ // and therefore never in the chat sidebar. The conversation is created on the routine's first
281
+ // run, so a routine that has not run yet has nothing to open.
282
+ /** True when the routine has run at least once and so has a conversation to read. */
283
+ CanOpenBriefing(routine) {
284
+ return !!routine.ConversationID;
285
+ }
286
+ /**
287
+ * Opens the routine's conversation in the Chat app. The ID goes in the query params as well
288
+ * as the nav item configuration: an already-open Chat tab is reused and reacts only to a
289
+ * query-param change.
290
+ */
291
+ OpenRoutineBriefing(routine, event) {
292
+ event?.stopPropagation();
293
+ const conversationId = routine.ConversationID;
294
+ if (!conversationId) {
295
+ return;
296
+ }
297
+ const chatApp = this.appManager.GetAppByName('Chat');
298
+ if (!chatApp) {
299
+ MJNotificationService.Instance.CreateSimpleNotification('The Chat app is not installed, so this briefing cannot be opened there', 'error', 4000);
300
+ return;
301
+ }
302
+ void this.navigationService.OpenNavItemByName('Conversations', { conversationId }, chatApp.ID, { queryParams: { conversationId } });
303
+ }
304
+ /** Opens the slide-in reader on the routine's conversation without leaving the page. */
305
+ async OpenBriefingReader(routine, event) {
306
+ event?.stopPropagation();
307
+ const conversationId = routine.ConversationID;
308
+ if (!conversationId) {
309
+ return;
310
+ }
311
+ this.BriefingRoutine = routine;
312
+ this.BriefingConversationId = conversationId;
313
+ this.BriefingConversation = await this.loadBriefingConversation(conversationId);
314
+ this.cdr.markForCheck();
315
+ }
316
+ CloseBriefingReader() {
317
+ this.BriefingRoutine = null;
318
+ this.BriefingConversationId = null;
319
+ this.BriefingConversation = null;
320
+ this.cdr.markForCheck();
321
+ }
322
+ get IsBriefingReaderOpen() {
323
+ return this.BriefingConversationId != null;
324
+ }
325
+ /** The environment the embedded chat area reads under. */
326
+ get BriefingEnvironmentId() {
327
+ return this.BriefingConversation?.EnvironmentID ?? MJEnvironmentEntityExtended.DefaultEnvironmentID;
328
+ }
329
+ /** The application the routine conversation is filed under, so the chat area stays in that scope. */
330
+ get BriefingApplicationId() {
331
+ return this.BriefingConversation?.ApplicationID ?? null;
332
+ }
333
+ /** The conversation entity, or null when it cannot be read; the reader still works by ID. */
334
+ async loadBriefingConversation(conversationId) {
335
+ const p = this.ProviderToUse;
336
+ const conversation = await p.GetEntityObject('MJ: Conversations', p.CurrentUser);
337
+ return await conversation.Load(conversationId) ? conversation : null;
338
+ }
339
+ OpenRoutineEntityRecord(routineId, event) {
340
+ event?.stopPropagation();
341
+ this.navigationService.OpenEntityRecord('MJ: User Routines', CompositeKey.FromID(routineId));
342
+ }
343
+ // =========================================================================
344
+ // Approvals & Requests Actions
345
+ // =========================================================================
346
+ OpenRequestDetail(request) {
347
+ this.SelectedRequest = request;
348
+ this.ShowRequestDialog = true;
349
+ this.cdr.markForCheck();
350
+ }
351
+ emailDraftsByRequest = new UUIDMap();
352
+ /** The outbound email an approval request carries, or null when the request is not an email. */
353
+ EmailDraftFor(request) {
354
+ const cached = this.emailDraftsByRequest.Get(request.ID);
355
+ if (cached !== undefined) {
356
+ return cached;
357
+ }
358
+ const draft = ParseEmailApprovalPayload(request.Comments);
359
+ this.emailDraftsByRequest.Set(request.ID, draft);
360
+ return draft;
361
+ }
362
+ /** Copies the draft as plain text (headers, blank line, body) for pasting into a mail client. */
363
+ async CopyEmailDraft(request, event) {
364
+ event?.stopPropagation();
365
+ const draft = this.EmailDraftFor(request);
366
+ if (!draft) {
367
+ return;
368
+ }
369
+ const text = FormatEmailDraftForClipboard(draft);
370
+ try {
371
+ await navigator.clipboard.writeText(text);
372
+ this.showBanner('success', `Copied the email to ${draft.To} to the clipboard.`);
373
+ }
374
+ catch (err) {
375
+ const msg = err instanceof Error ? err.message : String(err);
376
+ this.showBanner('error', `Could not copy to the clipboard: ${msg}`);
377
+ }
378
+ }
379
+ OnRequestDialogClose(result) {
380
+ this.ShowRequestDialog = false;
381
+ this.SelectedRequest = null;
382
+ if (result.Success) {
383
+ void this.LoadChiefOfStaffData();
384
+ }
385
+ else {
386
+ this.cdr.markForCheck();
387
+ }
388
+ }
389
+ async QuickRespondToRequest(request, decision, event) {
390
+ event.stopPropagation();
391
+ if (this.BusyRequestID) {
392
+ return;
393
+ }
394
+ this.BusyRequestID = request.ID;
395
+ this.cdr.markForCheck();
396
+ try {
397
+ const currentUserId = this.ProviderToUse.CurrentUser?.ID ?? null;
398
+ request.Status = decision;
399
+ request.RespondedAt = new Date();
400
+ request.ResponseSource = 'Dashboard';
401
+ if (currentUserId) {
402
+ request.ResponseByUserID = currentUserId;
403
+ }
404
+ request.Response = `${decision} via the Chief of Staff app`;
405
+ const saved = await request.Save();
406
+ if (saved) {
407
+ this.showBanner('success', `Request marked as ${decision}.`);
408
+ this.recalculateMetrics();
409
+ this.publishAgentContext();
410
+ }
411
+ else {
412
+ const errText = request.LatestResult?.CompleteMessage ?? 'Failed to save request decision.';
413
+ this.showBanner('error', errText);
414
+ }
415
+ }
416
+ catch (err) {
417
+ const msg = err instanceof Error ? err.message : String(err);
418
+ this.showBanner('error', `Failed to update request: ${msg}`);
419
+ }
420
+ finally {
421
+ this.BusyRequestID = null;
422
+ this.cdr.markForCheck();
423
+ }
424
+ }
425
+ // =========================================================================
426
+ // Wake Routines Actions
427
+ // =========================================================================
428
+ async TriggerWakeNow(routine, event) {
429
+ event?.stopPropagation();
430
+ if (this.BusyRoutineID) {
431
+ return;
432
+ }
433
+ this.BusyRoutineID = routine.ID;
434
+ this.cdr.markForCheck();
435
+ try {
436
+ // Run the routine out of schedule. Setting NextRunAt to now would make the dispatcher
437
+ // CLAIM it, and a claimed one-shot (a reminder) is spent: it fires now and never again.
438
+ // The action runs it without touching the schedule; the run row and the routine's
439
+ // conversation then update through the live refresh.
440
+ const actionId = await this.resolveActionIdByName('Run User Routine Now');
441
+ if (!actionId) {
442
+ this.showBanner('error', "The 'Run User Routine Now' action is not installed; push metadata/actions and restart MJAPI.");
443
+ return;
444
+ }
445
+ const actionClient = new GraphQLActionClient(this.ProviderToUse);
446
+ const result = await actionClient.RunAction(actionId, [
447
+ { Name: 'RoutineID', Value: routine.ID, Type: 'Input' },
448
+ ]);
449
+ if (result.Success) {
450
+ const keeps = routine.NextRunAt ? ' Its scheduled wake is unchanged.' : '';
451
+ this.showBanner('success', `Running "${routine.Name}" now. The result lands in its conversation and a notification.${keeps}`);
452
+ }
453
+ else {
454
+ this.showBanner('error', result.Message || `Could not run "${routine.Name}".`);
455
+ }
456
+ }
457
+ catch (err) {
458
+ const msg = err instanceof Error ? err.message : String(err);
459
+ this.showBanner('error', `Failed to trigger wake: ${msg}`);
460
+ }
461
+ finally {
462
+ this.BusyRoutineID = null;
463
+ this.cdr.markForCheck();
464
+ }
465
+ }
466
+ async ToggleRoutineStatus(routine, event) {
467
+ event?.stopPropagation();
468
+ if (this.BusyRoutineID) {
469
+ return;
470
+ }
471
+ this.BusyRoutineID = routine.ID;
472
+ this.cdr.markForCheck();
473
+ try {
474
+ const nextStatus = routine.Status === 'Active' ? 'Paused' : 'Active';
475
+ routine.Status = nextStatus;
476
+ const saved = await routine.Save();
477
+ if (saved) {
478
+ this.showBanner('success', `Routine "${routine.Name}" is now ${nextStatus}.`);
479
+ this.recalculateMetrics();
480
+ this.publishAgentContext();
481
+ }
482
+ else {
483
+ const errText = routine.LatestResult?.CompleteMessage ?? 'Failed to update routine status.';
484
+ this.showBanner('error', errText);
485
+ }
486
+ }
487
+ catch (err) {
488
+ const msg = err instanceof Error ? err.message : String(err);
489
+ this.showBanner('error', `Failed to update routine: ${msg}`);
490
+ }
491
+ finally {
492
+ this.BusyRoutineID = null;
493
+ this.cdr.markForCheck();
494
+ }
495
+ }
496
+ // =========================================================================
497
+ // Banner
498
+ // =========================================================================
499
+ DismissBanner() {
500
+ this.FeedbackBanner = null;
501
+ this.cdr.markForCheck();
502
+ }
503
+ showBanner(type, message) {
504
+ this.FeedbackBanner = { Type: type, Message: message };
505
+ this.cdr.markForCheck();
506
+ }
507
+ // =========================================================================
508
+ // UI Formatting Helpers
509
+ // =========================================================================
510
+ GetPriorityTierLabel(priority) {
511
+ if (priority >= 76)
512
+ return 'Critical';
513
+ if (priority >= 51)
514
+ return 'High';
515
+ if (priority >= 26)
516
+ return 'Normal';
517
+ return 'Low';
518
+ }
519
+ GetPriorityTierClass(priority) {
520
+ if (priority >= 76)
521
+ return 'priority-critical';
522
+ if (priority >= 51)
523
+ return 'priority-high';
524
+ if (priority >= 26)
525
+ return 'priority-normal';
526
+ return 'priority-low';
527
+ }
528
+ IsRequestExpired(request) {
529
+ if (!request.ExpiresAt)
530
+ return false;
531
+ const expires = request.ExpiresAt instanceof Date ? request.ExpiresAt : new Date(request.ExpiresAt);
532
+ return expires.getTime() < Date.now();
533
+ }
534
+ // =========================================================================
535
+ // Agent Context & Client Tools
536
+ // =========================================================================
537
+ publishAgentContext() {
538
+ if (this.navigationService.IsResourceDetached(this)) {
539
+ return;
540
+ }
541
+ const context = BuildChiefOfStaffAgentContext({
542
+ Page: this.Page,
543
+ SearchText: this.SearchText,
544
+ Metrics: this.Metrics,
545
+ Governance: BuildGovernanceSummary(this.DraftPolicy, this.PolicyEntity !== null),
546
+ Routines: this.Routines.map((r) => this.toRoutineSummary(r)),
547
+ PendingRequests: this.PendingRequests.map((r) => this.toRequestSummary(r)),
548
+ });
549
+ this.navigationService.SetAgentContext(this, context);
550
+ }
551
+ coreAgentTools() {
552
+ return [
553
+ {
554
+ Name: 'OpenChiefOfStaffPage',
555
+ Description: "Open one of the Chief of Staff app's pages: 'overview', 'approvals-wakes' or 'governance'.",
556
+ ParameterSchema: {
557
+ type: 'object',
558
+ properties: {
559
+ page: {
560
+ type: 'string',
561
+ enum: [...CHIEF_OF_STAFF_PAGES],
562
+ description: 'Target page',
563
+ },
564
+ },
565
+ required: ['page'],
566
+ },
567
+ Handler: async (params) => {
568
+ const check = ValidateChiefOfStaffPageParam(params['page']);
569
+ if (!check.ok) {
570
+ return check.result;
571
+ }
572
+ this.OpenPage(check.value);
573
+ return { Success: true, Data: { Page: check.value } };
574
+ },
575
+ },
576
+ {
577
+ Name: 'RefreshChiefOfStaff',
578
+ Description: 'Reload pending approvals, wake routines and the governance policy from the server.',
579
+ ParameterSchema: {
580
+ type: 'object',
581
+ properties: {},
582
+ },
583
+ Handler: async () => {
584
+ await this.LoadChiefOfStaffData();
585
+ return {
586
+ Success: true,
587
+ Data: {
588
+ PendingApprovalCount: this.Metrics.PendingApprovalCount,
589
+ ActiveWakeRoutineCount: this.Metrics.ActiveWakeRoutineCount,
590
+ },
591
+ };
592
+ },
593
+ },
594
+ ];
595
+ }
596
+ static ɵfac = /*@__PURE__*/ (() => { let ɵBaseChiefOfStaffPage_BaseFactory; return function BaseChiefOfStaffPage_Factory(__ngFactoryType__) { return (ɵBaseChiefOfStaffPage_BaseFactory || (ɵBaseChiefOfStaffPage_BaseFactory = i0.ɵɵgetInheritedFactory(BaseChiefOfStaffPage)))(__ngFactoryType__ || BaseChiefOfStaffPage); }; })();
597
+ static ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: BaseChiefOfStaffPage, features: [i0.ɵɵInheritDefinitionFeature] });
598
+ }
599
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BaseChiefOfStaffPage, [{
600
+ type: Directive
601
+ }], null, null); })();
602
+ //# sourceMappingURL=chief-of-staff-page-base.js.map