@memberjunction/ng-dashboards 6.2.0-edge.2 → 6.2.0-edge.4

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 (229) hide show
  1. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.d.ts +4 -3
  2. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.d.ts.map +1 -1
  3. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.js +8 -5
  4. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.js.map +1 -1
  5. package/dist/AI/components/duplicates/compare-value.component.d.ts +67 -0
  6. package/dist/AI/components/duplicates/compare-value.component.d.ts.map +1 -0
  7. package/dist/AI/components/duplicates/compare-value.component.js +168 -0
  8. package/dist/AI/components/duplicates/compare-value.component.js.map +1 -0
  9. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +49 -3
  10. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  11. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +287 -169
  12. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  13. package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts +77 -0
  14. package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts.map +1 -0
  15. package/dist/AI/components/duplicates/duplicate-detection-run-scope.js +116 -0
  16. package/dist/AI/components/duplicates/duplicate-detection-run-scope.js.map +1 -0
  17. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts +1 -0
  18. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
  19. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +16 -4
  20. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
  21. package/dist/AI/components/tags/tags-resource.component.d.ts +2 -0
  22. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  23. package/dist/AI/components/tags/tags-resource.component.js +12 -6
  24. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  25. package/dist/AI/components/vectors/vector-index-auto.d.ts +29 -0
  26. package/dist/AI/components/vectors/vector-index-auto.d.ts.map +1 -0
  27. package/dist/AI/components/vectors/vector-index-auto.js +59 -0
  28. package/dist/AI/components/vectors/vector-index-auto.js.map +1 -0
  29. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +9 -0
  30. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  31. package/dist/AI/components/vectors/vector-management-resource.component.js +65 -20
  32. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  33. package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
  34. package/dist/Actions/components/actions-overview.component.js +7 -3
  35. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  36. package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
  37. package/dist/Actions/components/categories-list-view.component.js +3 -2
  38. package/dist/Actions/components/categories-list-view.component.js.map +1 -1
  39. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
  40. package/dist/ComponentStudio/component-studio-dashboard.component.js +1 -0
  41. package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
  42. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts +0 -3
  43. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts.map +1 -1
  44. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +5 -14
  45. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js.map +1 -1
  46. package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
  47. package/dist/ComponentStudio/components/artifact-load-dialog.component.js +1 -0
  48. package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
  49. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
  50. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +1 -0
  51. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
  52. package/dist/ComponentStudio/components/form-override-dialog.component.d.ts +12 -1
  53. package/dist/ComponentStudio/components/form-override-dialog.component.d.ts.map +1 -1
  54. package/dist/ComponentStudio/components/form-override-dialog.component.js +128 -81
  55. package/dist/ComponentStudio/components/form-override-dialog.component.js.map +1 -1
  56. package/dist/Credentials/components/credentials-list-resource.component.d.ts +2 -0
  57. package/dist/Credentials/components/credentials-list-resource.component.d.ts.map +1 -1
  58. package/dist/Credentials/components/credentials-list-resource.component.js +12 -10
  59. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  60. package/dist/DashboardBrowser/dashboard-browser-agent-context.d.ts +14 -43
  61. package/dist/DashboardBrowser/dashboard-browser-agent-context.d.ts.map +1 -1
  62. package/dist/DashboardBrowser/dashboard-browser-agent-context.js +6 -29
  63. package/dist/DashboardBrowser/dashboard-browser-agent-context.js.map +1 -1
  64. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts +174 -321
  65. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
  66. package/dist/DashboardBrowser/dashboard-browser-resource.component.js +522 -1195
  67. package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
  68. package/dist/DashboardBrowser/dashboard-library-filter.d.ts +116 -0
  69. package/dist/DashboardBrowser/dashboard-library-filter.d.ts.map +1 -0
  70. package/dist/DashboardBrowser/dashboard-library-filter.js +277 -0
  71. package/dist/DashboardBrowser/dashboard-library-filter.js.map +1 -0
  72. package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts +1 -1
  73. package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
  74. package/dist/DashboardBrowser/dashboards-agent-tools.d.ts +26 -0
  75. package/dist/DashboardBrowser/dashboards-agent-tools.d.ts.map +1 -0
  76. package/dist/DashboardBrowser/dashboards-agent-tools.js +32 -0
  77. package/dist/DashboardBrowser/dashboards-agent-tools.js.map +1 -0
  78. package/dist/DashboardBrowser/dashboards-categories-resource.component.d.ts +58 -0
  79. package/dist/DashboardBrowser/dashboards-categories-resource.component.d.ts.map +1 -0
  80. package/dist/DashboardBrowser/dashboards-categories-resource.component.js +391 -0
  81. package/dist/DashboardBrowser/dashboards-categories-resource.component.js.map +1 -0
  82. package/dist/DashboardBrowser/dashboards-categories.helpers.d.ts +37 -0
  83. package/dist/DashboardBrowser/dashboards-categories.helpers.d.ts.map +1 -0
  84. package/dist/DashboardBrowser/dashboards-categories.helpers.js +68 -0
  85. package/dist/DashboardBrowser/dashboards-categories.helpers.js.map +1 -0
  86. package/dist/DashboardEditor/dashboard-editor.component.d.ts +295 -0
  87. package/dist/DashboardEditor/dashboard-editor.component.d.ts.map +1 -0
  88. package/dist/DashboardEditor/dashboard-editor.component.js +1022 -0
  89. package/dist/DashboardEditor/dashboard-editor.component.js.map +1 -0
  90. package/dist/DashboardEditor/dashboard-editor.types.d.ts +23 -0
  91. package/dist/DashboardEditor/dashboard-editor.types.d.ts.map +1 -0
  92. package/dist/DashboardEditor/dashboard-editor.types.js +3 -0
  93. package/dist/DashboardEditor/dashboard-editor.types.js.map +1 -0
  94. package/dist/DashboardEditor/dashboard-viewer-factory.d.ts +11 -0
  95. package/dist/DashboardEditor/dashboard-viewer-factory.d.ts.map +1 -0
  96. package/dist/DashboardEditor/dashboard-viewer-factory.js +17 -0
  97. package/dist/DashboardEditor/dashboard-viewer-factory.js.map +1 -0
  98. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +30 -0
  99. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  100. package/dist/DataExplorer/data-explorer-dashboard.component.js +349 -232
  101. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  102. package/dist/DataExplorer/services/explorer-state.service.d.ts +1 -1
  103. package/dist/DataExplorer/services/explorer-state.service.js +2 -5
  104. package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
  105. package/dist/FormBuilder/form-builder-resource.component.d.ts +0 -14
  106. package/dist/FormBuilder/form-builder-resource.component.d.ts.map +1 -1
  107. package/dist/FormBuilder/form-builder-resource.component.js +7 -29
  108. package/dist/FormBuilder/form-builder-resource.component.js.map +1 -1
  109. package/dist/Home/home-agent-context.d.ts +29 -10
  110. package/dist/Home/home-agent-context.d.ts.map +1 -1
  111. package/dist/Home/home-agent-context.js +50 -24
  112. package/dist/Home/home-agent-context.js.map +1 -1
  113. package/dist/Home/home-dashboard-switcher.component.d.ts +95 -0
  114. package/dist/Home/home-dashboard-switcher.component.d.ts.map +1 -0
  115. package/dist/Home/home-dashboard-switcher.component.js +442 -0
  116. package/dist/Home/home-dashboard-switcher.component.js.map +1 -0
  117. package/dist/Home/home-dashboard.component.d.ts +330 -17
  118. package/dist/Home/home-dashboard.component.d.ts.map +1 -1
  119. package/dist/Home/home-dashboard.component.js +1702 -1014
  120. package/dist/Home/home-dashboard.component.js.map +1 -1
  121. package/dist/Home/home-menus.d.ts +38 -0
  122. package/dist/Home/home-menus.d.ts.map +1 -0
  123. package/dist/Home/home-menus.js +53 -0
  124. package/dist/Home/home-menus.js.map +1 -0
  125. package/dist/Home/home-pinned-dashboards.d.ts +33 -0
  126. package/dist/Home/home-pinned-dashboards.d.ts.map +1 -0
  127. package/dist/Home/home-pinned-dashboards.js +76 -0
  128. package/dist/Home/home-pinned-dashboards.js.map +1 -0
  129. package/dist/PredictiveStudio/components/ps-production.component.d.ts +5 -1
  130. package/dist/PredictiveStudio/components/ps-production.component.d.ts.map +1 -1
  131. package/dist/PredictiveStudio/components/ps-production.component.js +64 -41
  132. package/dist/PredictiveStudio/components/ps-production.component.js.map +1 -1
  133. package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
  134. package/dist/QueryBrowser/query-browser-resource.component.js +3 -2
  135. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  136. package/dist/RealtimeRecordings/realtime-recordings-dashboard.component.js +2 -2
  137. package/dist/RealtimeRecordings/realtime-recordings-dashboard.component.js.map +1 -1
  138. package/dist/TelephonyOperations/telephony-operations-agent-context.d.ts +107 -0
  139. package/dist/TelephonyOperations/telephony-operations-agent-context.d.ts.map +1 -0
  140. package/dist/TelephonyOperations/telephony-operations-agent-context.js +216 -0
  141. package/dist/TelephonyOperations/telephony-operations-agent-context.js.map +1 -0
  142. package/dist/TelephonyOperations/telephony-operations-dashboard.component.d.ts +58 -0
  143. package/dist/TelephonyOperations/telephony-operations-dashboard.component.d.ts.map +1 -0
  144. package/dist/TelephonyOperations/telephony-operations-dashboard.component.js +812 -0
  145. package/dist/TelephonyOperations/telephony-operations-dashboard.component.js.map +1 -0
  146. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  147. package/dist/Testing/components/testing-explorer.component.js +7 -7
  148. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  149. package/dist/WorkQueue/components/work-queue-bindings.component.d.ts +37 -0
  150. package/dist/WorkQueue/components/work-queue-bindings.component.d.ts.map +1 -0
  151. package/dist/WorkQueue/components/work-queue-bindings.component.js +210 -0
  152. package/dist/WorkQueue/components/work-queue-bindings.component.js.map +1 -0
  153. package/dist/WorkQueue/components/work-queue-dead-letters.component.d.ts +70 -0
  154. package/dist/WorkQueue/components/work-queue-dead-letters.component.d.ts.map +1 -0
  155. package/dist/WorkQueue/components/work-queue-dead-letters.component.js +496 -0
  156. package/dist/WorkQueue/components/work-queue-dead-letters.component.js.map +1 -0
  157. package/dist/WorkQueue/components/work-queue-discard-dialog.component.d.ts +22 -0
  158. package/dist/WorkQueue/components/work-queue-discard-dialog.component.d.ts.map +1 -0
  159. package/dist/WorkQueue/components/work-queue-discard-dialog.component.js +99 -0
  160. package/dist/WorkQueue/components/work-queue-discard-dialog.component.js.map +1 -0
  161. package/dist/WorkQueue/components/work-queue-overview.component.d.ts +29 -0
  162. package/dist/WorkQueue/components/work-queue-overview.component.d.ts.map +1 -0
  163. package/dist/WorkQueue/components/work-queue-overview.component.js +278 -0
  164. package/dist/WorkQueue/components/work-queue-overview.component.js.map +1 -0
  165. package/dist/WorkQueue/components/work-queue-partitions.component.d.ts +59 -0
  166. package/dist/WorkQueue/components/work-queue-partitions.component.d.ts.map +1 -0
  167. package/dist/WorkQueue/components/work-queue-partitions.component.js +359 -0
  168. package/dist/WorkQueue/components/work-queue-partitions.component.js.map +1 -0
  169. package/dist/WorkQueue/services/work-queue-operator.service.d.ts +22 -0
  170. package/dist/WorkQueue/services/work-queue-operator.service.d.ts.map +1 -0
  171. package/dist/WorkQueue/services/work-queue-operator.service.js +44 -0
  172. package/dist/WorkQueue/services/work-queue-operator.service.js.map +1 -0
  173. package/dist/WorkQueue/work-queue-agent-context.d.ts +67 -0
  174. package/dist/WorkQueue/work-queue-agent-context.d.ts.map +1 -0
  175. package/dist/WorkQueue/work-queue-agent-context.js +119 -0
  176. package/dist/WorkQueue/work-queue-agent-context.js.map +1 -0
  177. package/dist/WorkQueue/work-queue-dashboard.component.d.ts +94 -0
  178. package/dist/WorkQueue/work-queue-dashboard.component.d.ts.map +1 -0
  179. package/dist/WorkQueue/work-queue-dashboard.component.js +545 -0
  180. package/dist/WorkQueue/work-queue-dashboard.component.js.map +1 -0
  181. package/dist/WorkQueue/work-queue-types.d.ts +40 -0
  182. package/dist/WorkQueue/work-queue-types.d.ts.map +1 -0
  183. package/dist/WorkQueue/work-queue-types.js +2 -0
  184. package/dist/WorkQueue/work-queue-types.js.map +1 -0
  185. package/dist/ai-dashboards.module.d.ts +21 -20
  186. package/dist/ai-dashboards.module.d.ts.map +1 -1
  187. package/dist/ai-dashboards.module.js +4 -1
  188. package/dist/ai-dashboards.module.js.map +1 -1
  189. package/dist/core-dashboards.module.d.ts +69 -61
  190. package/dist/core-dashboards.module.d.ts.map +1 -1
  191. package/dist/core-dashboards.module.js +29 -2
  192. package/dist/core-dashboards.module.js.map +1 -1
  193. package/dist/data-explorer-dashboards.module.d.ts +1 -1
  194. package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
  195. package/dist/data-explorer-dashboards.module.js +3 -1
  196. package/dist/data-explorer-dashboards.module.js.map +1 -1
  197. package/dist/module.d.ts +14 -13
  198. package/dist/module.d.ts.map +1 -1
  199. package/dist/module.js +7 -0
  200. package/dist/module.js.map +1 -1
  201. package/dist/public-api.d.ts +6 -0
  202. package/dist/public-api.d.ts.map +1 -1
  203. package/dist/public-api.js +9 -0
  204. package/dist/public-api.js.map +1 -1
  205. package/dist/shared/dashboard-library-changes.d.ts +23 -0
  206. package/dist/shared/dashboard-library-changes.d.ts.map +1 -0
  207. package/dist/shared/dashboard-library-changes.js +26 -0
  208. package/dist/shared/dashboard-library-changes.js.map +1 -0
  209. package/dist/shared/dashboard-owner-names.d.ts +17 -0
  210. package/dist/shared/dashboard-owner-names.d.ts.map +1 -0
  211. package/dist/shared/dashboard-owner-names.js +65 -0
  212. package/dist/shared/dashboard-owner-names.js.map +1 -0
  213. package/dist/shared/dashboard-recents.d.ts +34 -0
  214. package/dist/shared/dashboard-recents.d.ts.map +1 -0
  215. package/dist/shared/dashboard-recents.js +87 -0
  216. package/dist/shared/dashboard-recents.js.map +1 -0
  217. package/dist/shared/dashboards-app-install.d.ts +59 -0
  218. package/dist/shared/dashboards-app-install.d.ts.map +1 -0
  219. package/dist/shared/dashboards-app-install.js +97 -0
  220. package/dist/shared/dashboards-app-install.js.map +1 -0
  221. package/dist/shared/dashboards-app.helpers.d.ts +42 -0
  222. package/dist/shared/dashboards-app.helpers.d.ts.map +1 -0
  223. package/dist/shared/dashboards-app.helpers.js +143 -0
  224. package/dist/shared/dashboards-app.helpers.js.map +1 -0
  225. package/dist/work-queue-dashboards.module.d.ts +23 -0
  226. package/dist/work-queue-dashboards.module.d.ts.map +1 -0
  227. package/dist/work-queue-dashboards.module.js +92 -0
  228. package/dist/work-queue-dashboards.module.js.map +1 -0
  229. package/package.json +73 -66
@@ -1 +1 @@
1
- {"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Public API Surface of dashboards\n */\n\n// Dashboards\nexport * from './EntityAdmin/entity-admin-dashboard.component';\nexport * from './ComponentStudio';\nexport * from './Scheduling/scheduling-dashboard.component';\nexport * from './Testing/testing-dashboard.component';\nexport * from './DataExplorer';\nexport * from './Communication/communication-dashboard.component';\nexport * from './Credentials';\nexport * from './SystemDiagnostics';\nexport * from './ThemeStudio/theme-studio-dashboard.component';\nexport * from './ThemeStudio/theme-studio-resource.component';\nexport * from './ThemeStudio/theme-manager-dashboard.component';\nexport * from './ThemeStudio/theme-manager-resource.component';\nexport * from './DevTools';\nexport * from './Admin';\nexport * from './Lists';\n\n// Export AI components as resources (BaseResourceComponent-based)\nexport {\n ExecutionMonitoringComponent,\n PromptManagementComponent,\n AgentConfigurationComponent,\n ModelManagementComponent,\n SystemConfigurationComponent,\n KPICardComponent,\n LiveExecutionWidgetComponent,\n TimeSeriesChartComponent,\n PerformanceHeatmapComponent,\n AgentRequestsResourceComponent,\n AutotaggingPipelineResourceComponent,\n TagsResourceComponent,\n LoadTagsResource,\n VectorManagementResourceComponent,\n DuplicateDetectionResourceComponent,\n AIAnalyticsResourceComponent,\n LoadAIAnalyticsResource,\n AnalyticsFilterBarComponent,\n AIOverviewHubComponent,\n LoadAIOverviewHub,\n AnalyticsExecutiveSummaryComponent,\n LoadAnalyticsExecutiveSummary,\n AnalyticsPromptRunsComponent,\n LoadAnalyticsPromptRuns,\n AnalyticsAgentRunsComponent,\n LoadAnalyticsAgentRuns,\n AnalyticsModelPerformanceComponent,\n LoadAnalyticsModelPerformance,\n AnalyticsCostBudgetComponent,\n LoadAnalyticsCostBudget,\n AnalyticsErrorAnalysisComponent,\n LoadAnalyticsErrorAnalysis,\n AnalyticsUsagePatternsComponent,\n LoadAnalyticsUsagePatterns,\n UsageExplorerComponent,\n LoadUsageExplorer\n} from './AI/index';\n\n// Knowledge Hub components\nexport {\n KnowledgeConfigResourceComponent,\n LoadKnowledgeConfigResource\n} from './KnowledgeHub/components/config/knowledge-config-resource.component';\nexport { SearchResultDetailComponent } from './KnowledgeHub/components/results-detail/search-result-detail.component';\nexport {\n ClusterVisualizationResourceComponent,\n LoadClusterVisualizationResource\n} from './KnowledgeHub/components/clusters/cluster-visualization-resource.component';\nexport {\n VisualizeResourceComponent,\n LoadVisualizeResource\n} from './KnowledgeHub/components/visualize/visualize-resource.component';\nexport { TagCloudComponent } from './KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component';\nexport { RecordDrilldownComponent } from './KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component';\nexport {\n AnalyticsResourceComponent,\n LoadAnalyticsResource\n} from './KnowledgeHub/components/analytics/analytics-resource.component';\nexport {\n FeaturePipelinesResourceComponent,\n LoadFeaturePipelinesResource\n} from './KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component';\n\n// Archiving components\nexport {\n ArchiveConfigResourceComponent,\n LoadArchiveConfigResource\n} from './Archiving/components/archive-config-resource.component';\nexport {\n ArchiveRunsResourceComponent,\n LoadArchiveRunsResource\n} from './Archiving/components/archive-runs-resource.component';\n\n// Export Actions components as resources (BaseResourceComponent-based)\nexport {\n ActionsOverviewComponent,\n CodeManagementComponent,\n EntityIntegrationComponent,\n SecurityPermissionsComponent,\n // Action Explorer components\n ActionExplorerComponent,\n ActionTreePanelComponent,\n ActionBreadcrumbComponent,\n ActionCardComponent,\n ActionListItemComponent,\n NewCategoryPanelComponent,\n NewActionPanelComponent,\n // State service\n ActionExplorerStateService\n} from './Actions';\n\n// Re-export Actions ExecutionMonitoringComponent (renamed to avoid conflict with AI version)\nexport { ActionExecutionMonitoringComponent } from './Actions/components/execution-monitoring.component';\n\n// Export Scheduling components as resources (BaseResourceComponent-based)\nexport {\n SchedulingOverviewResourceComponent,\n SchedulingJobsResourceComponent,\n SchedulingActivityResourceComponent\n} from './Scheduling/components';\n\n// Export Communication components as resources\nexport {\n CommunicationMonitorResourceComponent\n} from './Communication/communication-monitor-resource.component';\nexport {\n CommunicationLogsResourceComponent\n} from './Communication/communication-logs-resource.component';\nexport {\n CommunicationProvidersResourceComponent\n} from './Communication/communication-providers-resource.component';\nexport {\n CommunicationRunsResourceComponent\n} from './Communication/communication-runs-resource.component';\nexport {\n CommunicationTemplatesResourceComponent\n} from './Communication/communication-templates-resource.component';\nexport {\n CommunicationsNewMessageResource,\n LoadCommunicationsNewMessageResource\n} from './Communication/communication-new-message-resource.component';\n\n// Export Testing components as resources (BaseResourceComponent-based)\nexport {\n TestingDashboardTabResourceComponent,\n TestingRunsResourceComponent,\n TestingAnalyticsResourceComponent,\n TestingReviewResourceComponent,\n TestingExplorerResourceComponent\n} from './Testing/components';\n\n// Query Browser\nexport {\n QueryBrowserResourceComponent\n} from './QueryBrowser/query-browser-resource.component';\n\n// Dashboard Browser\nexport {\n DashboardBrowserResourceComponent\n} from './DashboardBrowser/dashboard-browser-resource.component';\nexport {\n DashboardShareDialogComponent,\n ShareDialogResult\n} from './DashboardBrowser/dashboard-share-dialog.component';\n\n// Home Application and Dashboard\nexport { HomeApplication } from './Home/home-application';\nexport { HomeDashboardComponent } from './Home/home-dashboard.component';\n\n// Application Roles\nexport { ApplicationRolesResourceComponent, LoadApplicationRolesResource } from './ApplicationRoles/application-roles-resource.component';\n\n// Realtime Recordings — review & replay recorded realtime sessions (audio + transcript)\nexport { RealtimeRecordingsDashboardComponent, LoadRealtimeRecordingsDashboard } from './RealtimeRecordings/realtime-recordings-dashboard.component';\n\n// Permissions admin — three independent resource tabs (Phase 2a/b/c — unified permissions)\nexport {\n PermissionsUserAccessResourceComponent,\n LoadPermissionsUserAccessResource,\n} from './Permissions/user-access-resource.component';\nexport {\n PermissionsResourceAccessResourceComponent,\n LoadPermissionsResourceAccessResource,\n} from './Permissions/resource-access-resource.component';\nexport {\n PermissionsAuditLogResourceComponent,\n LoadPermissionsAuditLogResource,\n} from './Permissions/audit-log-resource.component';\n\n// API Keys\nexport { APIKeysResourceComponent } from './APIKeys/api-keys-resource.component';\nexport { APIKeyCreateDialogComponent, APIKeyCreateResult } from './APIKeys/api-key-create-dialog.component';\nexport { APIKeyEditPanelComponent } from './APIKeys/api-key-edit-panel.component';\nexport { APIKeyListComponent, APIKeyFilter } from './APIKeys/api-key-list.component';\nexport { APIApplicationsPanelComponent } from './APIKeys/api-applications-panel.component';\nexport { APIScopesPanelComponent } from './APIKeys/api-scopes-panel.component';\nexport { APIUsagePanelComponent } from './APIKeys/api-usage-panel.component';\n\n// MCP (Model Context Protocol)\nexport * from './MCP';\n\n// Version History Dashboard Components\nexport * from './VersionHistory';\n\n// Integration Dashboard\nexport * from './Integration';\n\n// NOTE: DashboardsModule (backward-compatible wrapper that imports ALL feature modules) is\n// intentionally not re-exported from the barrel to enable ESBuild code splitting.\n// Consumers who need it: import { DashboardsModule } from '@memberjunction/ng-dashboards/module'\n\n// Feature modules for lazy loading\nexport * from './core-dashboards.module';\nexport * from './ai-dashboards.module';\nexport * from './actions-dashboards.module';\nexport * from './testing-dashboards.module';\nexport * from './scheduling-dashboards.module';\nexport * from './rubrics-dashboards.module';\nexport * from './communication-dashboards.module';\nexport * from './credentials-dashboards.module';\nexport * from './data-explorer-dashboards.module';\nexport * from './lists-dashboards.module';\nexport * from './routines-dashboards.module';\nexport * from './component-studio-dashboards.module';\nexport * from './predictive-studio-dashboards.module';\n\n// Workflows app — the workflow list, the Create Workflow front door, and the run history (D18/D19).\nexport * from './workflows-dashboards.module';\nexport * from './Workflows/workflows-dashboard.component';\nexport * from './Workflows/components/create-workflow.component';\nexport * from './Workflows/components/workflows-resource.component';\nexport * from './Workflows/components/workflow-runs-resource.component';\nexport * from './Workflows/workflows.types';\nexport { PredictiveStudioEngine } from './PredictiveStudio/engine/predictive-studio.engine';\nexport * from './DatabaseDesigner/database-designer-dashboards.module';\nexport { DatabaseDesignerDashboardComponent, LoadDatabaseDesignerDashboard } from './DatabaseDesigner/components/database-designer-dashboard.component';\nexport * from './shared/shared-dashboard-widgets.module';\nexport * from './archiving-dashboards.module';\n\n// Routines app — schedule AI agents to run on a cron cadence\nexport { UserRoutinesResourceComponent, LoadUserRoutinesResource } from './UserRoutines/user-routines-resource.component';\n"]}
1
+ {"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,aAAa;AACb,cAAc,gDAAgD,CAAC;AAC/D,cAAc,mBAAmB,CAAC;AAClC,cAAc,6CAA6C,CAAC;AAC5D,cAAc,uCAAuC,CAAC;AACtD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mDAAmD,CAAC;AAClE,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gDAAgD,CAAC;AAC/D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,iDAAiD,CAAC;AAChE,cAAc,gDAAgD,CAAC;AAC/D,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AAExB,kEAAkE;AAClE,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,EACzB,2BAA2B,EAC3B,wBAAwB,EACxB,4BAA4B,EAC5B,gBAAgB,EAChB,4BAA4B,EAC5B,wBAAwB,EACxB,2BAA2B,EAC3B,8BAA8B,EAC9B,oCAAoC,EACpC,qBAAqB,EACrB,gBAAgB,EAChB,iCAAiC,EACjC,mCAAmC,EACnC,4BAA4B,EAC5B,uBAAuB,EACvB,2BAA2B,EAC3B,sBAAsB,EACtB,iBAAiB,EACjB,kCAAkC,EAClC,6BAA6B,EAC7B,4BAA4B,EAC5B,uBAAuB,EACvB,2BAA2B,EAC3B,sBAAsB,EACtB,kCAAkC,EAClC,6BAA6B,EAC7B,4BAA4B,EAC5B,uBAAuB,EACvB,+BAA+B,EAC/B,0BAA0B,EAC1B,+BAA+B,EAC/B,0BAA0B,EAC1B,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,2BAA2B;AAC3B,OAAO,EACL,gCAAgC,EAChC,2BAA2B,EAC5B,MAAM,sEAAsE,CAAC;AAC9E,OAAO,EAAE,2BAA2B,EAAE,MAAM,yEAAyE,CAAC;AACtH,OAAO,EACL,qCAAqC,EACrC,gCAAgC,EACjC,MAAM,6EAA6E,CAAC;AACrF,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACtB,MAAM,kEAAkE,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mEAAmE,CAAC;AACtG,OAAO,EAAE,wBAAwB,EAAE,MAAM,iFAAiF,CAAC;AAC3H,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACtB,MAAM,kEAAkE,CAAC;AAC1E,OAAO,EACL,iCAAiC,EACjC,4BAA4B,EAC7B,MAAM,kFAAkF,CAAC;AAE1F,uBAAuB;AACvB,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EAC1B,MAAM,0DAA0D,CAAC;AAClE,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACxB,MAAM,wDAAwD,CAAC;AAEhE,uEAAuE;AACvE,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,EAC1B,4BAA4B;AAC5B,6BAA6B;AAC7B,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,EACnB,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB;AACvB,gBAAgB;AAChB,0BAA0B,EAC3B,MAAM,WAAW,CAAC;AAEnB,6FAA6F;AAC7F,OAAO,EAAE,kCAAkC,EAAE,MAAM,qDAAqD,CAAC;AAEzG,0EAA0E;AAC1E,OAAO,EACL,mCAAmC,EACnC,+BAA+B,EAC/B,mCAAmC,EACpC,MAAM,yBAAyB,CAAC;AAEjC,+CAA+C;AAC/C,OAAO,EACL,qCAAqC,EACtC,MAAM,0DAA0D,CAAC;AAClE,OAAO,EACL,kCAAkC,EACnC,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EACL,uCAAuC,EACxC,MAAM,4DAA4D,CAAC;AACpE,OAAO,EACL,kCAAkC,EACnC,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EACL,uCAAuC,EACxC,MAAM,4DAA4D,CAAC;AACpE,OAAO,EACL,gCAAgC,EAChC,oCAAoC,EACrC,MAAM,8DAA8D,CAAC;AAEtE,uEAAuE;AACvE,OAAO,EACL,oCAAoC,EACpC,4BAA4B,EAC5B,iCAAiC,EACjC,8BAA8B,EAC9B,gCAAgC,EACjC,MAAM,sBAAsB,CAAC;AAE9B,gBAAgB;AAChB,OAAO,EACL,6BAA6B,EAC9B,MAAM,iDAAiD,CAAC;AAEzD,oBAAoB;AACpB,OAAO,EACL,iCAAiC,EAClC,MAAM,yDAAyD,CAAC;AACjE,OAAO,EACL,6BAA6B,EAE9B,MAAM,qDAAqD,CAAC;AAE7D,gFAAgF;AAChF,OAAO,EAAE,qCAAqC,EAAE,gCAAgC,EAAE,MAAM,6DAA6D,CAAC;AACtJ,cAAc,iCAAiC,CAAC;AAEhD,iCAAiC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,oBAAoB;AACpB,OAAO,EAAE,iCAAiC,EAAE,4BAA4B,EAAE,MAAM,yDAAyD,CAAC;AAE1I,wFAAwF;AACxF,OAAO,EAAE,oCAAoC,EAAE,+BAA+B,EAAE,MAAM,8DAA8D,CAAC;AAErJ,qCAAqC;AACrC,OAAO,EAAE,qCAAqC,EAAE,MAAM,gEAAgE,CAAC;AACvH,cAAc,0DAA0D,CAAC;AAEzE,2FAA2F;AAC3F,OAAO,EACH,sCAAsC,EACtC,iCAAiC,GACpC,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACH,0CAA0C,EAC1C,qCAAqC,GACxC,MAAM,kDAAkD,CAAC;AAC1D,OAAO,EACH,oCAAoC,EACpC,+BAA+B,GAClC,MAAM,4CAA4C,CAAC;AAEpD,WAAW;AACX,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,2BAA2B,EAAsB,MAAM,2CAA2C,CAAC;AAC5G,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAgB,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,6BAA6B,EAAE,MAAM,4CAA4C,CAAC;AAC3F,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAE7E,+BAA+B;AAC/B,cAAc,OAAO,CAAC;AAEtB,uCAAuC;AACvC,cAAc,kBAAkB,CAAC;AAEjC,wBAAwB;AACxB,cAAc,eAAe,CAAC;AAE9B,2FAA2F;AAC3F,kFAAkF;AAClF,iGAAiG;AAEjG,mCAAmC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AAEtD,oGAAoG;AACpG,cAAc,+BAA+B,CAAC;AAC9C,cAAc,2CAA2C,CAAC;AAC1D,cAAc,kDAAkD,CAAC;AACjE,cAAc,qDAAqD,CAAC;AACpE,cAAc,yDAAyD,CAAC;AACxE,cAAc,6BAA6B,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oDAAoD,CAAC;AAC5F,cAAc,wDAAwD,CAAC;AACvE,OAAO,EAAE,kCAAkC,EAAE,6BAA6B,EAAE,MAAM,qEAAqE,CAAC;AACxJ,cAAc,0CAA0C,CAAC;AACzD,cAAc,+BAA+B,CAAC;AAE9C,wFAAwF;AACxF,cAAc,gCAAgC,CAAC;AAC/C,OAAO,EAAE,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AAEzF,6DAA6D;AAC7D,OAAO,EAAE,6BAA6B,EAAE,wBAAwB,EAAE,MAAM,iDAAiD,CAAC","sourcesContent":["/*\n * Public API Surface of dashboards\n */\n\n// Dashboards\nexport * from './EntityAdmin/entity-admin-dashboard.component';\nexport * from './ComponentStudio';\nexport * from './Scheduling/scheduling-dashboard.component';\nexport * from './Testing/testing-dashboard.component';\nexport * from './DataExplorer';\nexport * from './Communication/communication-dashboard.component';\nexport * from './Credentials';\nexport * from './SystemDiagnostics';\nexport * from './ThemeStudio/theme-studio-dashboard.component';\nexport * from './ThemeStudio/theme-studio-resource.component';\nexport * from './ThemeStudio/theme-manager-dashboard.component';\nexport * from './ThemeStudio/theme-manager-resource.component';\nexport * from './DevTools';\nexport * from './Admin';\nexport * from './Lists';\n\n// Export AI components as resources (BaseResourceComponent-based)\nexport {\n ExecutionMonitoringComponent,\n PromptManagementComponent,\n AgentConfigurationComponent,\n ModelManagementComponent,\n SystemConfigurationComponent,\n KPICardComponent,\n LiveExecutionWidgetComponent,\n TimeSeriesChartComponent,\n PerformanceHeatmapComponent,\n AgentRequestsResourceComponent,\n AutotaggingPipelineResourceComponent,\n TagsResourceComponent,\n LoadTagsResource,\n VectorManagementResourceComponent,\n DuplicateDetectionResourceComponent,\n AIAnalyticsResourceComponent,\n LoadAIAnalyticsResource,\n AnalyticsFilterBarComponent,\n AIOverviewHubComponent,\n LoadAIOverviewHub,\n AnalyticsExecutiveSummaryComponent,\n LoadAnalyticsExecutiveSummary,\n AnalyticsPromptRunsComponent,\n LoadAnalyticsPromptRuns,\n AnalyticsAgentRunsComponent,\n LoadAnalyticsAgentRuns,\n AnalyticsModelPerformanceComponent,\n LoadAnalyticsModelPerformance,\n AnalyticsCostBudgetComponent,\n LoadAnalyticsCostBudget,\n AnalyticsErrorAnalysisComponent,\n LoadAnalyticsErrorAnalysis,\n AnalyticsUsagePatternsComponent,\n LoadAnalyticsUsagePatterns,\n UsageExplorerComponent,\n LoadUsageExplorer\n} from './AI/index';\n\n// Knowledge Hub components\nexport {\n KnowledgeConfigResourceComponent,\n LoadKnowledgeConfigResource\n} from './KnowledgeHub/components/config/knowledge-config-resource.component';\nexport { SearchResultDetailComponent } from './KnowledgeHub/components/results-detail/search-result-detail.component';\nexport {\n ClusterVisualizationResourceComponent,\n LoadClusterVisualizationResource\n} from './KnowledgeHub/components/clusters/cluster-visualization-resource.component';\nexport {\n VisualizeResourceComponent,\n LoadVisualizeResource\n} from './KnowledgeHub/components/visualize/visualize-resource.component';\nexport { TagCloudComponent } from './KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component';\nexport { RecordDrilldownComponent } from './KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component';\nexport {\n AnalyticsResourceComponent,\n LoadAnalyticsResource\n} from './KnowledgeHub/components/analytics/analytics-resource.component';\nexport {\n FeaturePipelinesResourceComponent,\n LoadFeaturePipelinesResource\n} from './KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component';\n\n// Archiving components\nexport {\n ArchiveConfigResourceComponent,\n LoadArchiveConfigResource\n} from './Archiving/components/archive-config-resource.component';\nexport {\n ArchiveRunsResourceComponent,\n LoadArchiveRunsResource\n} from './Archiving/components/archive-runs-resource.component';\n\n// Export Actions components as resources (BaseResourceComponent-based)\nexport {\n ActionsOverviewComponent,\n CodeManagementComponent,\n EntityIntegrationComponent,\n SecurityPermissionsComponent,\n // Action Explorer components\n ActionExplorerComponent,\n ActionTreePanelComponent,\n ActionBreadcrumbComponent,\n ActionCardComponent,\n ActionListItemComponent,\n NewCategoryPanelComponent,\n NewActionPanelComponent,\n // State service\n ActionExplorerStateService\n} from './Actions';\n\n// Re-export Actions ExecutionMonitoringComponent (renamed to avoid conflict with AI version)\nexport { ActionExecutionMonitoringComponent } from './Actions/components/execution-monitoring.component';\n\n// Export Scheduling components as resources (BaseResourceComponent-based)\nexport {\n SchedulingOverviewResourceComponent,\n SchedulingJobsResourceComponent,\n SchedulingActivityResourceComponent\n} from './Scheduling/components';\n\n// Export Communication components as resources\nexport {\n CommunicationMonitorResourceComponent\n} from './Communication/communication-monitor-resource.component';\nexport {\n CommunicationLogsResourceComponent\n} from './Communication/communication-logs-resource.component';\nexport {\n CommunicationProvidersResourceComponent\n} from './Communication/communication-providers-resource.component';\nexport {\n CommunicationRunsResourceComponent\n} from './Communication/communication-runs-resource.component';\nexport {\n CommunicationTemplatesResourceComponent\n} from './Communication/communication-templates-resource.component';\nexport {\n CommunicationsNewMessageResource,\n LoadCommunicationsNewMessageResource\n} from './Communication/communication-new-message-resource.component';\n\n// Export Testing components as resources (BaseResourceComponent-based)\nexport {\n TestingDashboardTabResourceComponent,\n TestingRunsResourceComponent,\n TestingAnalyticsResourceComponent,\n TestingReviewResourceComponent,\n TestingExplorerResourceComponent\n} from './Testing/components';\n\n// Query Browser\nexport {\n QueryBrowserResourceComponent\n} from './QueryBrowser/query-browser-resource.component';\n\n// Dashboard Browser\nexport {\n DashboardBrowserResourceComponent\n} from './DashboardBrowser/dashboard-browser-resource.component';\nexport {\n DashboardShareDialogComponent,\n ShareDialogResult\n} from './DashboardBrowser/dashboard-share-dialog.component';\n\n// Dashboards app pages (the Library is DashboardBrowserResourceComponent above)\nexport { DashboardsCategoriesResourceComponent, LoadDashboardsCategoriesResource } from './DashboardBrowser/dashboards-categories-resource.component';\nexport * from './shared/dashboards-app.helpers';\n\n// Home Application and Dashboard\nexport { HomeApplication } from './Home/home-application';\nexport { HomeDashboardComponent } from './Home/home-dashboard.component';\n\n// Application Roles\nexport { ApplicationRolesResourceComponent, LoadApplicationRolesResource } from './ApplicationRoles/application-roles-resource.component';\n\n// Realtime Recordings — review & replay recorded realtime sessions (audio + transcript)\nexport { RealtimeRecordingsDashboardComponent, LoadRealtimeRecordingsDashboard } from './RealtimeRecordings/realtime-recordings-dashboard.component';\n\n// Telephony & Interaction Operations\nexport { TelephonyOperationsDashboardComponent } from './TelephonyOperations/telephony-operations-dashboard.component';\nexport * from './TelephonyOperations/telephony-operations-agent-context';\n\n// Permissions admin — three independent resource tabs (Phase 2a/b/c — unified permissions)\nexport {\n PermissionsUserAccessResourceComponent,\n LoadPermissionsUserAccessResource,\n} from './Permissions/user-access-resource.component';\nexport {\n PermissionsResourceAccessResourceComponent,\n LoadPermissionsResourceAccessResource,\n} from './Permissions/resource-access-resource.component';\nexport {\n PermissionsAuditLogResourceComponent,\n LoadPermissionsAuditLogResource,\n} from './Permissions/audit-log-resource.component';\n\n// API Keys\nexport { APIKeysResourceComponent } from './APIKeys/api-keys-resource.component';\nexport { APIKeyCreateDialogComponent, APIKeyCreateResult } from './APIKeys/api-key-create-dialog.component';\nexport { APIKeyEditPanelComponent } from './APIKeys/api-key-edit-panel.component';\nexport { APIKeyListComponent, APIKeyFilter } from './APIKeys/api-key-list.component';\nexport { APIApplicationsPanelComponent } from './APIKeys/api-applications-panel.component';\nexport { APIScopesPanelComponent } from './APIKeys/api-scopes-panel.component';\nexport { APIUsagePanelComponent } from './APIKeys/api-usage-panel.component';\n\n// MCP (Model Context Protocol)\nexport * from './MCP';\n\n// Version History Dashboard Components\nexport * from './VersionHistory';\n\n// Integration Dashboard\nexport * from './Integration';\n\n// NOTE: DashboardsModule (backward-compatible wrapper that imports ALL feature modules) is\n// intentionally not re-exported from the barrel to enable ESBuild code splitting.\n// Consumers who need it: import { DashboardsModule } from '@memberjunction/ng-dashboards/module'\n\n// Feature modules for lazy loading\nexport * from './core-dashboards.module';\nexport * from './ai-dashboards.module';\nexport * from './actions-dashboards.module';\nexport * from './testing-dashboards.module';\nexport * from './scheduling-dashboards.module';\nexport * from './rubrics-dashboards.module';\nexport * from './communication-dashboards.module';\nexport * from './credentials-dashboards.module';\nexport * from './data-explorer-dashboards.module';\nexport * from './lists-dashboards.module';\nexport * from './routines-dashboards.module';\nexport * from './component-studio-dashboards.module';\nexport * from './predictive-studio-dashboards.module';\n\n// Workflows app — the workflow list, the Create Workflow front door, and the run history (D18/D19).\nexport * from './workflows-dashboards.module';\nexport * from './Workflows/workflows-dashboard.component';\nexport * from './Workflows/components/create-workflow.component';\nexport * from './Workflows/components/workflows-resource.component';\nexport * from './Workflows/components/workflow-runs-resource.component';\nexport * from './Workflows/workflows.types';\nexport { PredictiveStudioEngine } from './PredictiveStudio/engine/predictive-studio.engine';\nexport * from './DatabaseDesigner/database-designer-dashboards.module';\nexport { DatabaseDesignerDashboardComponent, LoadDatabaseDesignerDashboard } from './DatabaseDesigner/components/database-designer-dashboard.component';\nexport * from './shared/shared-dashboard-widgets.module';\nexport * from './archiving-dashboards.module';\n\n// Work Queue app — operator dashboard over the WorkQueue.* remote operations (spec 09b)\nexport * from './work-queue-dashboards.module';\nexport { WorkQueueDashboardComponent } from './WorkQueue/work-queue-dashboard.component';\n\n// Routines app — schedule AI agents to run on a cron cadence\nexport { UserRoutinesResourceComponent, LoadUserRoutinesResource } from './UserRoutines/user-routines-resource.component';\n"]}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @fileoverview The change signal that the Dashboards app pages (Library, Categories) use to
3
+ * re-read the DashboardEngine cache and re-render.
4
+ *
5
+ * DashboardEngine updates its arrays in place and emits DataChange$ for saves and deletes made in
6
+ * this browser, for changes other sessions make (remote invalidation), and for full reloads. Explorer
7
+ * keeps these pages alive as cached tabs, so each page watches the signal instead of keeping a copy
8
+ * that goes stale. One user action can emit several events (a transaction, a reload of every entity
9
+ * set), so the signal emits at most once per task.
10
+ */
11
+ import type { EngineDataChangeEvent } from '@memberjunction/core';
12
+ import { Observable } from 'rxjs';
13
+ /** The DashboardEngine entities whose changes can alter a dashboard list, the category tree or a permission. */
14
+ export declare const DASHBOARD_LIBRARY_ENTITY_NAMES: readonly string[];
15
+ /** The part of DashboardEngine the change signal reads. DashboardEngine satisfies it. */
16
+ export interface DashboardLibrarySource {
17
+ readonly DataChange$: Observable<EngineDataChangeEvent>;
18
+ }
19
+ /** True when an engine change event is for one of the library entities. */
20
+ export declare function IsDashboardLibraryChange(event: EngineDataChangeEvent): boolean;
21
+ /** Emits after `source` changes a library entity set; a burst of changes emits once, after the current task. */
22
+ export declare function ObserveDashboardLibraryChanges(source?: DashboardLibrarySource): Observable<void>;
23
+ //# sourceMappingURL=dashboard-library-changes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-library-changes.d.ts","sourceRoot":"","sources":["../../src/shared/dashboard-library-changes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAGlC,gHAAgH;AAChH,eAAO,MAAM,8BAA8B,EAAE,SAAS,MAAM,EAM3D,CAAC;AAEF,yFAAyF;AACzF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,qBAAqB,CAAC,CAAC;CACzD;AAED,2EAA2E;AAC3E,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAE9E;AAED,gHAAgH;AAChH,wBAAgB,8BAA8B,CAAC,MAAM,GAAE,sBAAiD,GAAG,UAAU,CAAC,IAAI,CAAC,CAE1H"}
@@ -0,0 +1,26 @@
1
+ import { DashboardEngine } from '@memberjunction/core-entities';
2
+ import { auditTime, filter, map } from 'rxjs/operators';
3
+ /** The DashboardEngine entities whose changes can alter a dashboard list, the category tree or a permission. */
4
+ export const DASHBOARD_LIBRARY_ENTITY_NAMES = [
5
+ 'MJ: Dashboards',
6
+ 'MJ: Dashboard Categories',
7
+ 'MJ: Dashboard Permissions',
8
+ 'MJ: Dashboard Category Permissions',
9
+ 'MJ: Dashboard Category Links',
10
+ ];
11
+ /** True when an engine change event is for one of the library entities. */
12
+ export function IsDashboardLibraryChange(event) {
13
+ return isChangeFor(event, DASHBOARD_LIBRARY_ENTITY_NAMES);
14
+ }
15
+ /** Emits after `source` changes a library entity set; a burst of changes emits once, after the current task. */
16
+ export function ObserveDashboardLibraryChanges(source = DashboardEngine.Instance) {
17
+ return observeChanges(source, IsDashboardLibraryChange);
18
+ }
19
+ function isChangeFor(event, entityNames) {
20
+ const entityName = (event.config.EntityName ?? '').trim().toLowerCase();
21
+ return entityNames.some(name => name.toLowerCase() === entityName);
22
+ }
23
+ function observeChanges(source, counts) {
24
+ return source.DataChange$.pipe(filter(counts), auditTime(0), map(() => undefined));
25
+ }
26
+ //# sourceMappingURL=dashboard-library-changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-library-changes.js","sourceRoot":"","sources":["../../src/shared/dashboard-library-changes.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAExD,gHAAgH;AAChH,MAAM,CAAC,MAAM,8BAA8B,GAAsB;IAC/D,gBAAgB;IAChB,0BAA0B;IAC1B,2BAA2B;IAC3B,oCAAoC;IACpC,8BAA8B;CAC/B,CAAC;AAOF,2EAA2E;AAC3E,MAAM,UAAU,wBAAwB,CAAC,KAA4B;IACnE,OAAO,WAAW,CAAC,KAAK,EAAE,8BAA8B,CAAC,CAAC;AAC5D,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,8BAA8B,CAAC,SAAiC,eAAe,CAAC,QAAQ;IACtG,OAAO,cAAc,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,WAAW,CAAC,KAA4B,EAAE,WAA8B;IAC/E,MAAM,UAAU,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxE,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,cAAc,CAAC,MAA8B,EAAE,MAAiD;IACvG,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAC5B,MAAM,CAAC,MAAM,CAAC,EACd,SAAS,CAAC,CAAC,CAAC,EACZ,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CACrB,CAAC;AACJ,CAAC","sourcesContent":["/**\n * @fileoverview The change signal that the Dashboards app pages (Library, Categories) use to\n * re-read the DashboardEngine cache and re-render.\n *\n * DashboardEngine updates its arrays in place and emits DataChange$ for saves and deletes made in\n * this browser, for changes other sessions make (remote invalidation), and for full reloads. Explorer\n * keeps these pages alive as cached tabs, so each page watches the signal instead of keeping a copy\n * that goes stale. One user action can emit several events (a transaction, a reload of every entity\n * set), so the signal emits at most once per task.\n */\nimport type { EngineDataChangeEvent } from '@memberjunction/core';\nimport { DashboardEngine } from '@memberjunction/core-entities';\nimport { Observable } from 'rxjs';\nimport { auditTime, filter, map } from 'rxjs/operators';\n\n/** The DashboardEngine entities whose changes can alter a dashboard list, the category tree or a permission. */\nexport const DASHBOARD_LIBRARY_ENTITY_NAMES: readonly string[] = [\n 'MJ: Dashboards',\n 'MJ: Dashboard Categories',\n 'MJ: Dashboard Permissions',\n 'MJ: Dashboard Category Permissions',\n 'MJ: Dashboard Category Links',\n];\n\n/** The part of DashboardEngine the change signal reads. DashboardEngine satisfies it. */\nexport interface DashboardLibrarySource {\n readonly DataChange$: Observable<EngineDataChangeEvent>;\n}\n\n/** True when an engine change event is for one of the library entities. */\nexport function IsDashboardLibraryChange(event: EngineDataChangeEvent): boolean {\n return isChangeFor(event, DASHBOARD_LIBRARY_ENTITY_NAMES);\n}\n\n/** Emits after `source` changes a library entity set; a burst of changes emits once, after the current task. */\nexport function ObserveDashboardLibraryChanges(source: DashboardLibrarySource = DashboardEngine.Instance): Observable<void> {\n return observeChanges(source, IsDashboardLibraryChange);\n}\n\nfunction isChangeFor(event: EngineDataChangeEvent, entityNames: readonly string[]): boolean {\n const entityName = (event.config.EntityName ?? '').trim().toLowerCase();\n return entityNames.some(name => name.toLowerCase() === entityName);\n}\n\nfunction observeChanges(source: DashboardLibrarySource, counts: (event: EngineDataChangeEvent) => boolean): Observable<void> {\n return source.DataChange$.pipe(\n filter(counts),\n auditTime(0),\n map(() => undefined)\n );\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import type { IMetadataProvider } from '@memberjunction/core';
2
+ import type { MJDashboardEntity, MJUserEntity } from '@memberjunction/core-entities';
3
+ /** The user fields an owner name is made from. FirstName and LastName can be null. */
4
+ export type DashboardOwnerRow = Pick<MJUserEntity, 'ID' | 'Name' | 'FirstName' | 'LastName'>;
5
+ /** The owner text of the user's own dashboards. */
6
+ export declare const OWN_DASHBOARD_OWNER_LABEL = "You";
7
+ /** A user's display name: first and last name, else the user name without an e-mail domain. */
8
+ export declare function UserDisplayName(user: Pick<DashboardOwnerRow, 'Name' | 'FirstName' | 'LastName'>): string;
9
+ /** A user name, or the part before the @ when the name is an e-mail. */
10
+ export declare function NameWithoutEmailDomain(name: string | null | undefined): string;
11
+ /** The owners of `dashboards` other than the current user that `known` lacks: normalized ids, each once. */
12
+ export declare function OwnerIdsToLoad(dashboards: readonly Pick<MJDashboardEntity, 'UserID'>[], currentUserId: string, known: ReadonlyMap<string, string>): string[];
13
+ /** Reads the display names of `ownerIds` in one RunView, keyed by normalized id. Empty on failure. */
14
+ export declare function LoadDashboardOwnerNames(provider: IMetadataProvider, ownerIds: readonly string[]): Promise<Map<string, string>>;
15
+ /** Each dashboard's owner text, keyed by dashboard ID: "You", the owner's name, or the name part of the User field. */
16
+ export declare function BuildOwnerLabels(dashboards: readonly Pick<MJDashboardEntity, 'ID' | 'UserID' | 'User'>[], currentUserId: string, ownerNames: ReadonlyMap<string, string>): Map<string, string>;
17
+ //# sourceMappingURL=dashboard-owner-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-owner-names.d.ts","sourceRoot":"","sources":["../../src/shared/dashboard-owner-names.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGrF,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC,CAAC;AAE7F,mDAAmD;AACnD,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAE/C,+FAA+F;AAC/F,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC,GAAG,MAAM,CAMxG;AAED,wEAAwE;AACxE,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAI9E;AAED,4GAA4G;AAC5G,wBAAgB,cAAc,CAC5B,UAAU,EAAE,SAAS,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,EAAE,EACxD,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,MAAM,EAAE,CAOV;AAED,sGAAsG;AACtG,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAepI;AAED,uHAAuH;AACvH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,SAAS,IAAI,CAAC,iBAAiB,EAAE,IAAI,GAAG,QAAQ,GAAG,MAAM,CAAC,EAAE,EACxE,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CASrB"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @fileoverview The owner text of a dashboard card: "You" for the user's own dashboards, else the
3
+ * owner's first and last name, else the owner's user name without an e-mail domain. Names come from
4
+ * one MJ: Users read of the owners' ids.
5
+ */
6
+ import { LogError, RunView } from '@memberjunction/core';
7
+ import { EscapeSQLString, NormalizeUUID, UUIDsEqual } from '@memberjunction/global';
8
+ /** The owner text of the user's own dashboards. */
9
+ export const OWN_DASHBOARD_OWNER_LABEL = 'You';
10
+ /** A user's display name: first and last name, else the user name without an e-mail domain. */
11
+ export function UserDisplayName(user) {
12
+ const fullName = [user.FirstName, user.LastName]
13
+ .map(part => part?.trim() ?? '')
14
+ .filter(part => part.length > 0)
15
+ .join(' ');
16
+ return fullName || NameWithoutEmailDomain(user.Name);
17
+ }
18
+ /** A user name, or the part before the @ when the name is an e-mail. */
19
+ export function NameWithoutEmailDomain(name) {
20
+ const trimmed = name?.trim() ?? '';
21
+ const at = trimmed.indexOf('@');
22
+ return at > 0 ? trimmed.slice(0, at) : trimmed;
23
+ }
24
+ /** The owners of `dashboards` other than the current user that `known` lacks: normalized ids, each once. */
25
+ export function OwnerIdsToLoad(dashboards, currentUserId, known) {
26
+ const ids = new Set();
27
+ for (const dashboard of dashboards) {
28
+ const id = NormalizeUUID(dashboard.UserID);
29
+ if (id && !UUIDsEqual(id, currentUserId) && !known.has(id))
30
+ ids.add(id);
31
+ }
32
+ return [...ids];
33
+ }
34
+ /** Reads the display names of `ownerIds` in one RunView, keyed by normalized id. Empty on failure. */
35
+ export async function LoadDashboardOwnerNames(provider, ownerIds) {
36
+ const names = new Map();
37
+ if (ownerIds.length === 0)
38
+ return names;
39
+ const result = await RunView.FromMetadataProvider(provider).RunView({
40
+ EntityName: 'MJ: Users',
41
+ ExtraFilter: `ID IN (${ownerIds.map(id => `'${EscapeSQLString(id)}'`).join(', ')})`,
42
+ Fields: ['ID', 'Name', 'FirstName', 'LastName'],
43
+ ResultType: 'simple',
44
+ });
45
+ if (!result.Success) {
46
+ LogError(`Dashboard owners could not be read: ${result.ErrorMessage}`);
47
+ return names;
48
+ }
49
+ for (const row of result.Results)
50
+ names.set(NormalizeUUID(row.ID), UserDisplayName(row));
51
+ return names;
52
+ }
53
+ /** Each dashboard's owner text, keyed by dashboard ID: "You", the owner's name, or the name part of the User field. */
54
+ export function BuildOwnerLabels(dashboards, currentUserId, ownerNames) {
55
+ const labels = new Map();
56
+ for (const dashboard of dashboards) {
57
+ const label = UUIDsEqual(dashboard.UserID, currentUserId)
58
+ ? OWN_DASHBOARD_OWNER_LABEL
59
+ : ownerNames.get(NormalizeUUID(dashboard.UserID)) || NameWithoutEmailDomain(dashboard.User);
60
+ if (label)
61
+ labels.set(dashboard.ID, label);
62
+ }
63
+ return labels;
64
+ }
65
+ //# sourceMappingURL=dashboard-owner-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-owner-names.js","sourceRoot":"","sources":["../../src/shared/dashboard-owner-names.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview The owner text of a dashboard card: \"You\" for the user's own dashboards, else the\n * owner's first and last name, else the owner's user name without an e-mail domain. Names come from\n * one MJ: Users read of the owners' ids.\n */\nimport { LogError, RunView } from '@memberjunction/core';\nimport type { IMetadataProvider } from '@memberjunction/core';\nimport type { MJDashboardEntity, MJUserEntity } from '@memberjunction/core-entities';\nimport { EscapeSQLString, NormalizeUUID, UUIDsEqual } from '@memberjunction/global';\n\n/** The user fields an owner name is made from. FirstName and LastName can be null. */\nexport type DashboardOwnerRow = Pick<MJUserEntity, 'ID' | 'Name' | 'FirstName' | 'LastName'>;\n\n/** The owner text of the user's own dashboards. */\nexport const OWN_DASHBOARD_OWNER_LABEL = 'You';\n\n/** A user's display name: first and last name, else the user name without an e-mail domain. */\nexport function UserDisplayName(user: Pick<DashboardOwnerRow, 'Name' | 'FirstName' | 'LastName'>): string {\n const fullName = [user.FirstName, user.LastName]\n .map(part => part?.trim() ?? '')\n .filter(part => part.length > 0)\n .join(' ');\n return fullName || NameWithoutEmailDomain(user.Name);\n}\n\n/** A user name, or the part before the @ when the name is an e-mail. */\nexport function NameWithoutEmailDomain(name: string | null | undefined): string {\n const trimmed = name?.trim() ?? '';\n const at = trimmed.indexOf('@');\n return at > 0 ? trimmed.slice(0, at) : trimmed;\n}\n\n/** The owners of `dashboards` other than the current user that `known` lacks: normalized ids, each once. */\nexport function OwnerIdsToLoad(\n dashboards: readonly Pick<MJDashboardEntity, 'UserID'>[],\n currentUserId: string,\n known: ReadonlyMap<string, string>\n): string[] {\n const ids = new Set<string>();\n for (const dashboard of dashboards) {\n const id = NormalizeUUID(dashboard.UserID);\n if (id && !UUIDsEqual(id, currentUserId) && !known.has(id)) ids.add(id);\n }\n return [...ids];\n}\n\n/** Reads the display names of `ownerIds` in one RunView, keyed by normalized id. Empty on failure. */\nexport async function LoadDashboardOwnerNames(provider: IMetadataProvider, ownerIds: readonly string[]): Promise<Map<string, string>> {\n const names = new Map<string, string>();\n if (ownerIds.length === 0) return names;\n const result = await RunView.FromMetadataProvider(provider).RunView<DashboardOwnerRow>({\n EntityName: 'MJ: Users',\n ExtraFilter: `ID IN (${ownerIds.map(id => `'${EscapeSQLString(id)}'`).join(', ')})`,\n Fields: ['ID', 'Name', 'FirstName', 'LastName'],\n ResultType: 'simple',\n });\n if (!result.Success) {\n LogError(`Dashboard owners could not be read: ${result.ErrorMessage}`);\n return names;\n }\n for (const row of result.Results) names.set(NormalizeUUID(row.ID), UserDisplayName(row));\n return names;\n}\n\n/** Each dashboard's owner text, keyed by dashboard ID: \"You\", the owner's name, or the name part of the User field. */\nexport function BuildOwnerLabels(\n dashboards: readonly Pick<MJDashboardEntity, 'ID' | 'UserID' | 'User'>[],\n currentUserId: string,\n ownerNames: ReadonlyMap<string, string>\n): Map<string, string> {\n const labels = new Map<string, string>();\n for (const dashboard of dashboards) {\n const label = UUIDsEqual(dashboard.UserID, currentUserId)\n ? OWN_DASHBOARD_OWNER_LABEL\n : ownerNames.get(NormalizeUUID(dashboard.UserID)) || NameWithoutEmailDomain(dashboard.User);\n if (label) labels.set(dashboard.ID, label);\n }\n return labels;\n}\n"]}
@@ -0,0 +1,34 @@
1
+ import type { IMetadataProvider } from '@memberjunction/core';
2
+ import { Observable } from 'rxjs';
3
+ /** The entity whose record logs are dashboard opens. */
4
+ export declare const DASHBOARDS_ENTITY_NAME = "MJ: Dashboards";
5
+ /** A record log, as far as dashboard recents need it. A simple RunView row can carry `LatestAt` as text. */
6
+ export interface DashboardRecordLog {
7
+ RecordID: string;
8
+ LatestAt: Date | string;
9
+ }
10
+ /**
11
+ * The record ids of `logs`, most recently opened first, each id once (compared with UUIDsEqual,
12
+ * keeping the newest), at most `maxItems` of them. Logs without a record id are skipped.
13
+ */
14
+ export declare function OrderRecentDashboardIds(logs: ReadonlyArray<DashboardRecordLog>, maxItems?: number): string[];
15
+ /**
16
+ * Loads the ids of the dashboards the current user of `provider` opened, most recent first, at most
17
+ * `maxItems` (all of them when omitted), with one query of the user's MJ: User Record Logs for the
18
+ * MJ: Dashboards entity. Returns an empty list when the metadata has no MJ: Dashboards entity, there
19
+ * is no current user, or the query fails or throws (for example when the user cannot read the record
20
+ * logs, or the server cannot be reached). A failed or thrown read is logged; it never rejects.
21
+ */
22
+ export declare function LoadRecentDashboardIds(provider: IMetadataProvider, maxItems?: number): Promise<string[]>;
23
+ /**
24
+ * Emits the ids of the dashboards the current user opened (see {@link LoadRecentDashboardIds}) each
25
+ * time `trigger` emits, read again each time. A read that a newer emission overtakes is dropped.
26
+ * With the default `load`, a read that fails or throws gives an empty list, so the stream keeps running.
27
+ *
28
+ * @param provider The provider whose metadata and current user the read uses.
29
+ * @param trigger Emits when the list can have changed, for example RecentAccessService.RecentItems,
30
+ * which emits after a dashboard open is logged.
31
+ * @param load Reads the ids. The default is {@link LoadRecentDashboardIds}.
32
+ */
33
+ export declare function ObserveRecentDashboardIds(provider: IMetadataProvider, trigger: Observable<unknown>, load?: (provider: IMetadataProvider) => Promise<string[]>): Observable<string[]>;
34
+ //# sourceMappingURL=dashboard-recents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-recents.d.ts","sourceRoot":"","sources":["../../src/shared/dashboard-recents.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EAAQ,UAAU,EAAE,MAAM,MAAM,CAAC;AAGxC,wDAAwD;AACxD,eAAO,MAAM,sBAAsB,mBAAmB,CAAC;AAIvD,4GAA4G;AAC5G,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,EAAE,QAAQ,GAAE,MAAiC,GAAG,MAAM,EAAE,CAYtI;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAuB9G;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,EAC5B,IAAI,GAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,MAAM,EAAE,CAA0B,GAChF,UAAU,CAAC,MAAM,EAAE,CAAC,CAEtB"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @fileoverview The user's recently opened dashboards, for the Library (its order and Recently
3
+ * opened).
4
+ *
5
+ * The list comes from a query of the user's MJ: User Record Logs for the MJ: Dashboards entity, so it
6
+ * lists every dashboard the user opened, not only the dashboards among the latest records of any
7
+ * entity. Record logs are not cached, so the list is read again each time it can have changed.
8
+ *
9
+ * Opening a dashboard saves a record log (RecentAccessService.LogAccess). The service then reloads its
10
+ * recent items and emits RecentItems, after the log is saved. ObserveRecentDashboardIds reads the list
11
+ * again each time its trigger emits, so a caller that passes RecentItems shows the new open.
12
+ */
13
+ import { LogError, RunView } from '@memberjunction/core';
14
+ import { EscapeSQLString, UUIDsEqual } from '@memberjunction/global';
15
+ import { from } from 'rxjs';
16
+ import { switchMap } from 'rxjs/operators';
17
+ /** The entity whose record logs are dashboard opens. */
18
+ export const DASHBOARDS_ENTITY_NAME = 'MJ: Dashboards';
19
+ const USER_RECORD_LOGS_ENTITY_NAME = 'MJ: User Record Logs';
20
+ /**
21
+ * The record ids of `logs`, most recently opened first, each id once (compared with UUIDsEqual,
22
+ * keeping the newest), at most `maxItems` of them. Logs without a record id are skipped.
23
+ */
24
+ export function OrderRecentDashboardIds(logs, maxItems = Number.POSITIVE_INFINITY) {
25
+ const newestFirst = [...logs].sort((a, b) => timeOf(b.LatestAt) - timeOf(a.LatestAt));
26
+ const ids = [];
27
+ for (const log of newestFirst) {
28
+ if (ids.length >= maxItems) {
29
+ break;
30
+ }
31
+ if (log.RecordID && !ids.some(id => UUIDsEqual(id, log.RecordID))) {
32
+ ids.push(log.RecordID);
33
+ }
34
+ }
35
+ return ids;
36
+ }
37
+ /**
38
+ * Loads the ids of the dashboards the current user of `provider` opened, most recent first, at most
39
+ * `maxItems` (all of them when omitted), with one query of the user's MJ: User Record Logs for the
40
+ * MJ: Dashboards entity. Returns an empty list when the metadata has no MJ: Dashboards entity, there
41
+ * is no current user, or the query fails or throws (for example when the user cannot read the record
42
+ * logs, or the server cannot be reached). A failed or thrown read is logged; it never rejects.
43
+ */
44
+ export async function LoadRecentDashboardIds(provider, maxItems) {
45
+ const dashboardsEntity = provider.EntityByName(DASHBOARDS_ENTITY_NAME);
46
+ const user = provider.CurrentUser;
47
+ if (!dashboardsEntity || !user) {
48
+ return [];
49
+ }
50
+ try {
51
+ const result = await RunView.FromMetadataProvider(provider).RunView({
52
+ EntityName: USER_RECORD_LOGS_ENTITY_NAME,
53
+ ExtraFilter: `UserID='${EscapeSQLString(user.ID)}' AND EntityID='${EscapeSQLString(dashboardsEntity.ID)}'`,
54
+ OrderBy: 'LatestAt DESC',
55
+ Fields: ['RecordID', 'LatestAt'],
56
+ ResultType: 'simple',
57
+ });
58
+ if (!result.Success) {
59
+ LogError(`Recently opened dashboards could not be read: ${result.ErrorMessage}`);
60
+ return [];
61
+ }
62
+ return OrderRecentDashboardIds(result.Results, maxItems);
63
+ }
64
+ catch (error) {
65
+ LogError(`Recently opened dashboards could not be read: ${error instanceof Error ? error.message : String(error)}`);
66
+ return [];
67
+ }
68
+ }
69
+ /**
70
+ * Emits the ids of the dashboards the current user opened (see {@link LoadRecentDashboardIds}) each
71
+ * time `trigger` emits, read again each time. A read that a newer emission overtakes is dropped.
72
+ * With the default `load`, a read that fails or throws gives an empty list, so the stream keeps running.
73
+ *
74
+ * @param provider The provider whose metadata and current user the read uses.
75
+ * @param trigger Emits when the list can have changed, for example RecentAccessService.RecentItems,
76
+ * which emits after a dashboard open is logged.
77
+ * @param load Reads the ids. The default is {@link LoadRecentDashboardIds}.
78
+ */
79
+ export function ObserveRecentDashboardIds(provider, trigger, load = LoadRecentDashboardIds) {
80
+ return trigger.pipe(switchMap(() => from(load(provider))));
81
+ }
82
+ /** Milliseconds since the epoch, or 0 for a missing or invalid date. */
83
+ function timeOf(value) {
84
+ const time = new Date(value).getTime();
85
+ return Number.isNaN(time) ? 0 : time;
86
+ }
87
+ //# sourceMappingURL=dashboard-recents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-recents.js","sourceRoot":"","sources":["../../src/shared/dashboard-recents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,IAAI,EAAc,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,wDAAwD;AACxD,MAAM,CAAC,MAAM,sBAAsB,GAAG,gBAAgB,CAAC;AAEvD,MAAM,4BAA4B,GAAG,sBAAsB,CAAC;AAQ5D;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAuC,EAAE,WAAmB,MAAM,CAAC,iBAAiB;IAC1H,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtF,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,IAAI,GAAG,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM;QACR,CAAC;QACD,IAAI,GAAG,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YAClE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,QAA2B,EAAE,QAAiB;IACzF,MAAM,gBAAgB,GAAG,QAAQ,CAAC,YAAY,CAAC,sBAAsB,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC;IAClC,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAqB;YACtF,UAAU,EAAE,4BAA4B;YACxC,WAAW,EAAE,WAAW,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,mBAAmB,eAAe,CAAC,gBAAgB,CAAC,EAAE,CAAC,GAAG;YAC1G,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;YAChC,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,QAAQ,CAAC,iDAAiD,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;YACjF,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,uBAAuB,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,QAAQ,CAAC,iDAAiD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACpH,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,yBAAyB,CACvC,QAA2B,EAC3B,OAA4B,EAC5B,OAA2D,sBAAsB;IAEjF,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,wEAAwE;AACxE,SAAS,MAAM,CAAC,KAAoB;IAClC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;IACvC,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC","sourcesContent":["/**\n * @fileoverview The user's recently opened dashboards, for the Library (its order and Recently\n * opened).\n *\n * The list comes from a query of the user's MJ: User Record Logs for the MJ: Dashboards entity, so it\n * lists every dashboard the user opened, not only the dashboards among the latest records of any\n * entity. Record logs are not cached, so the list is read again each time it can have changed.\n *\n * Opening a dashboard saves a record log (RecentAccessService.LogAccess). The service then reloads its\n * recent items and emits RecentItems, after the log is saved. ObserveRecentDashboardIds reads the list\n * again each time its trigger emits, so a caller that passes RecentItems shows the new open.\n */\nimport { LogError, RunView } from '@memberjunction/core';\nimport type { IMetadataProvider } from '@memberjunction/core';\nimport { EscapeSQLString, UUIDsEqual } from '@memberjunction/global';\nimport { from, Observable } from 'rxjs';\nimport { switchMap } from 'rxjs/operators';\n\n/** The entity whose record logs are dashboard opens. */\nexport const DASHBOARDS_ENTITY_NAME = 'MJ: Dashboards';\n\nconst USER_RECORD_LOGS_ENTITY_NAME = 'MJ: User Record Logs';\n\n/** A record log, as far as dashboard recents need it. A simple RunView row can carry `LatestAt` as text. */\nexport interface DashboardRecordLog {\n RecordID: string;\n LatestAt: Date | string;\n}\n\n/**\n * The record ids of `logs`, most recently opened first, each id once (compared with UUIDsEqual,\n * keeping the newest), at most `maxItems` of them. Logs without a record id are skipped.\n */\nexport function OrderRecentDashboardIds(logs: ReadonlyArray<DashboardRecordLog>, maxItems: number = Number.POSITIVE_INFINITY): string[] {\n const newestFirst = [...logs].sort((a, b) => timeOf(b.LatestAt) - timeOf(a.LatestAt));\n const ids: string[] = [];\n for (const log of newestFirst) {\n if (ids.length >= maxItems) {\n break;\n }\n if (log.RecordID && !ids.some(id => UUIDsEqual(id, log.RecordID))) {\n ids.push(log.RecordID);\n }\n }\n return ids;\n}\n\n/**\n * Loads the ids of the dashboards the current user of `provider` opened, most recent first, at most\n * `maxItems` (all of them when omitted), with one query of the user's MJ: User Record Logs for the\n * MJ: Dashboards entity. Returns an empty list when the metadata has no MJ: Dashboards entity, there\n * is no current user, or the query fails or throws (for example when the user cannot read the record\n * logs, or the server cannot be reached). A failed or thrown read is logged; it never rejects.\n */\nexport async function LoadRecentDashboardIds(provider: IMetadataProvider, maxItems?: number): Promise<string[]> {\n const dashboardsEntity = provider.EntityByName(DASHBOARDS_ENTITY_NAME);\n const user = provider.CurrentUser;\n if (!dashboardsEntity || !user) {\n return [];\n }\n try {\n const result = await RunView.FromMetadataProvider(provider).RunView<DashboardRecordLog>({\n EntityName: USER_RECORD_LOGS_ENTITY_NAME,\n ExtraFilter: `UserID='${EscapeSQLString(user.ID)}' AND EntityID='${EscapeSQLString(dashboardsEntity.ID)}'`,\n OrderBy: 'LatestAt DESC',\n Fields: ['RecordID', 'LatestAt'],\n ResultType: 'simple',\n });\n if (!result.Success) {\n LogError(`Recently opened dashboards could not be read: ${result.ErrorMessage}`);\n return [];\n }\n return OrderRecentDashboardIds(result.Results, maxItems);\n } catch (error) {\n LogError(`Recently opened dashboards could not be read: ${error instanceof Error ? error.message : String(error)}`);\n return [];\n }\n}\n\n/**\n * Emits the ids of the dashboards the current user opened (see {@link LoadRecentDashboardIds}) each\n * time `trigger` emits, read again each time. A read that a newer emission overtakes is dropped.\n * With the default `load`, a read that fails or throws gives an empty list, so the stream keeps running.\n *\n * @param provider The provider whose metadata and current user the read uses.\n * @param trigger Emits when the list can have changed, for example RecentAccessService.RecentItems,\n * which emits after a dashboard open is logged.\n * @param load Reads the ids. The default is {@link LoadRecentDashboardIds}.\n */\nexport function ObserveRecentDashboardIds(\n provider: IMetadataProvider,\n trigger: Observable<unknown>,\n load: (provider: IMetadataProvider) => Promise<string[]> = LoadRecentDashboardIds\n): Observable<string[]> {\n return trigger.pipe(switchMap(() => from(load(provider))));\n}\n\n/** Milliseconds since the epoch, or 0 for a missing or invalid date. */\nfunction timeOf(value: Date | string): number {\n const time = new Date(value).getTime();\n return Number.isNaN(time) ? 0 : time;\n}\n"]}
@@ -0,0 +1,59 @@
1
+ import type { UserApplicationAccessStatus } from '@memberjunction/core-entities';
2
+ /**
3
+ * UserInfoEngine setting that records the one-time automatic install of the Dashboards app.
4
+ * The value is 'true' when set.
5
+ */
6
+ export declare const DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY = "Dashboards.AppAutoInstalled";
7
+ /**
8
+ * How long one install step (the install, or the marker save) may take. A step that takes longer
9
+ * counts as failed, so the install queue moves on and its callers are not held.
10
+ */
11
+ export declare const DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS = 5000;
12
+ /** What the install paths know about the Dashboards app and the current user. */
13
+ export interface DashboardsAppInstallState {
14
+ /** An Active application named Dashboards exists in metadata. */
15
+ AppExists: boolean;
16
+ /** The user's access to the app: role authorization, then the UserApplication row. Ignored when AppExists is false. */
17
+ Access: UserApplicationAccessStatus;
18
+ /** The one-time automatic install is recorded for the user. */
19
+ AutoInstallRecorded: boolean;
20
+ }
21
+ /** The operations the install paths call. `dashboards-app.helpers.ts` builds them from ApplicationManager and UserInfoEngine. */
22
+ export interface DashboardsAppInstallOperations {
23
+ /** The current state, or null when the user's app data cannot be read. */
24
+ ReadState(): DashboardsAppInstallState | null;
25
+ /** Installs or re-enables the app for the user and refreshes the user's app list. Resolves true on success. */
26
+ Install(): Promise<boolean>;
27
+ /** Saves the one-time automatic-install marker. Resolves true on success. */
28
+ RecordAutoInstall(): Promise<boolean>;
29
+ }
30
+ /** What a Home load does about the Dashboards app. */
31
+ export type DashboardsAppAutoInstallAction = 'install' | 'skip';
32
+ /** What a user click that goes to the Dashboards app does before it navigates. */
33
+ export type DashboardsAppExplicitInstallAction = 'open' | 'install' | 'unavailable';
34
+ /**
35
+ * The automatic path installs only for a user with no UserApplication row for the app and no
36
+ * recorded install. An inactive row means the user removed the app, so it is left alone.
37
+ */
38
+ export declare function DecideDashboardsAppAutoInstall(state: DashboardsAppInstallState): DashboardsAppAutoInstallAction;
39
+ /**
40
+ * The explicit path ignores the marker: a missing or removed app is installed, an active one
41
+ * opens, and a missing or unauthorized app is unavailable.
42
+ */
43
+ export declare function DecideDashboardsAppExplicitInstall(state: DashboardsAppInstallState): DashboardsAppExplicitInstallAction;
44
+ /**
45
+ * Automatic path (Home load). Installs the app when {@link DecideDashboardsAppAutoInstall} says so,
46
+ * then records the marker. The marker is written only after a successful install, so a failed or
47
+ * timed-out install is retried on the next load. Each step waits at most
48
+ * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.
49
+ * @returns true when this call installed the app.
50
+ */
51
+ export declare function RunDashboardsAppAutoInstall(operations: DashboardsAppInstallOperations): Promise<boolean>;
52
+ /**
53
+ * Explicit path (a user click that goes to the app). Installs the app when it is missing or
54
+ * removed, and records the marker if it is not set yet. Each step waits at most
55
+ * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.
56
+ * @returns true when the user has the app active afterwards, so the caller can navigate.
57
+ */
58
+ export declare function RunDashboardsAppExplicitInstall(operations: DashboardsAppInstallOperations): Promise<boolean>;
59
+ //# sourceMappingURL=dashboards-app-install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboards-app-install.d.ts","sourceRoot":"","sources":["../../src/shared/dashboards-app-install.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAEjF;;;GAGG;AACH,eAAO,MAAM,uCAAuC,gCAAgC,CAAC;AAErF;;;GAGG;AACH,eAAO,MAAM,sCAAsC,OAAO,CAAC;AAE3D,iFAAiF;AACjF,MAAM,WAAW,yBAAyB;IACxC,iEAAiE;IACjE,SAAS,EAAE,OAAO,CAAC;IACnB,uHAAuH;IACvH,MAAM,EAAE,2BAA2B,CAAC;IACpC,+DAA+D;IAC/D,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,iIAAiI;AACjI,MAAM,WAAW,8BAA8B;IAC7C,0EAA0E;IAC1E,SAAS,IAAI,yBAAyB,GAAG,IAAI,CAAC;IAC9C,+GAA+G;IAC/G,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,6EAA6E;IAC7E,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CACvC;AAED,sDAAsD;AACtD,MAAM,MAAM,8BAA8B,GAAG,SAAS,GAAG,MAAM,CAAC;AAEhE,kFAAkF;AAClF,MAAM,MAAM,kCAAkC,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAEpF;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,yBAAyB,GAAG,8BAA8B,CAG/G;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,yBAAyB,GAAG,kCAAkC,CAKvH;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,8BAA8B,GAAG,OAAO,CAAC,OAAO,CAAC,CAYxG;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,UAAU,EAAE,8BAA8B,GAAG,OAAO,CAAC,OAAO,CAAC,CAkB5G"}
@@ -0,0 +1,97 @@
1
+ import { LogError } from '@memberjunction/core';
2
+ /**
3
+ * UserInfoEngine setting that records the one-time automatic install of the Dashboards app.
4
+ * The value is 'true' when set.
5
+ */
6
+ export const DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY = 'Dashboards.AppAutoInstalled';
7
+ /**
8
+ * How long one install step (the install, or the marker save) may take. A step that takes longer
9
+ * counts as failed, so the install queue moves on and its callers are not held.
10
+ */
11
+ export const DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS = 5000;
12
+ /**
13
+ * The automatic path installs only for a user with no UserApplication row for the app and no
14
+ * recorded install. An inactive row means the user removed the app, so it is left alone.
15
+ */
16
+ export function DecideDashboardsAppAutoInstall(state) {
17
+ const install = state.AppExists && state.Access === 'not_installed' && !state.AutoInstallRecorded;
18
+ return install ? 'install' : 'skip';
19
+ }
20
+ /**
21
+ * The explicit path ignores the marker: a missing or removed app is installed, an active one
22
+ * opens, and a missing or unauthorized app is unavailable.
23
+ */
24
+ export function DecideDashboardsAppExplicitInstall(state) {
25
+ if (!state.AppExists || state.Access === 'not_authorized') {
26
+ return 'unavailable';
27
+ }
28
+ return state.Access === 'installed_active' ? 'open' : 'install';
29
+ }
30
+ /**
31
+ * Automatic path (Home load). Installs the app when {@link DecideDashboardsAppAutoInstall} says so,
32
+ * then records the marker. The marker is written only after a successful install, so a failed or
33
+ * timed-out install is retried on the next load. Each step waits at most
34
+ * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.
35
+ * @returns true when this call installed the app.
36
+ */
37
+ export function RunDashboardsAppAutoInstall(operations) {
38
+ return runOneAtATime(async () => {
39
+ const state = operations.ReadState();
40
+ if (!state || DecideDashboardsAppAutoInstall(state) === 'skip') {
41
+ return false;
42
+ }
43
+ if (!(await withStepTimeout(operations.Install(), 'the install'))) {
44
+ return false;
45
+ }
46
+ await withStepTimeout(operations.RecordAutoInstall(), 'the marker save');
47
+ return true;
48
+ });
49
+ }
50
+ /**
51
+ * Explicit path (a user click that goes to the app). Installs the app when it is missing or
52
+ * removed, and records the marker if it is not set yet. Each step waits at most
53
+ * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.
54
+ * @returns true when the user has the app active afterwards, so the caller can navigate.
55
+ */
56
+ export function RunDashboardsAppExplicitInstall(operations) {
57
+ return runOneAtATime(async () => {
58
+ const state = operations.ReadState();
59
+ if (!state) {
60
+ return false;
61
+ }
62
+ const action = DecideDashboardsAppExplicitInstall(state);
63
+ if (action !== 'install') {
64
+ return action === 'open';
65
+ }
66
+ if (!(await withStepTimeout(operations.Install(), 'the install'))) {
67
+ return false;
68
+ }
69
+ if (!state.AutoInstallRecorded) {
70
+ await withStepTimeout(operations.RecordAutoInstall(), 'the marker save');
71
+ }
72
+ return true;
73
+ });
74
+ }
75
+ /**
76
+ * Resolves with the step's result, or with false when the step does not settle within
77
+ * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}. A timed-out step is logged and keeps running in
78
+ * the background, but nothing waits for it. The timer is cleared when the step settles first.
79
+ */
80
+ function withStepTimeout(step, stepName) {
81
+ let timer;
82
+ const timedOut = new Promise((resolve) => {
83
+ timer = setTimeout(() => {
84
+ LogError(`Dashboards app install: ${stepName} did not finish within ${DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS} ms, so it counts as failed`);
85
+ resolve(false);
86
+ }, DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS);
87
+ });
88
+ return Promise.race([step, timedOut]).finally(() => clearTimeout(timer));
89
+ }
90
+ let installQueue = Promise.resolve();
91
+ /** Runs install work one call at a time, so each call reads the state the previous call left. */
92
+ function runOneAtATime(work) {
93
+ const run = installQueue.then(work);
94
+ installQueue = run.catch(() => undefined);
95
+ return run;
96
+ }
97
+ //# sourceMappingURL=dashboards-app-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboards-app-install.js","sourceRoot":"","sources":["../../src/shared/dashboards-app-install.ts"],"names":[],"mappings":"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","sourcesContent":["import { LogError } from '@memberjunction/core';\nimport type { UserApplicationAccessStatus } from '@memberjunction/core-entities';\n\n/**\n * UserInfoEngine setting that records the one-time automatic install of the Dashboards app.\n * The value is 'true' when set.\n */\nexport const DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY = 'Dashboards.AppAutoInstalled';\n\n/**\n * How long one install step (the install, or the marker save) may take. A step that takes longer\n * counts as failed, so the install queue moves on and its callers are not held.\n */\nexport const DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS = 5000;\n\n/** What the install paths know about the Dashboards app and the current user. */\nexport interface DashboardsAppInstallState {\n /** An Active application named Dashboards exists in metadata. */\n AppExists: boolean;\n /** The user's access to the app: role authorization, then the UserApplication row. Ignored when AppExists is false. */\n Access: UserApplicationAccessStatus;\n /** The one-time automatic install is recorded for the user. */\n AutoInstallRecorded: boolean;\n}\n\n/** The operations the install paths call. `dashboards-app.helpers.ts` builds them from ApplicationManager and UserInfoEngine. */\nexport interface DashboardsAppInstallOperations {\n /** The current state, or null when the user's app data cannot be read. */\n ReadState(): DashboardsAppInstallState | null;\n /** Installs or re-enables the app for the user and refreshes the user's app list. Resolves true on success. */\n Install(): Promise<boolean>;\n /** Saves the one-time automatic-install marker. Resolves true on success. */\n RecordAutoInstall(): Promise<boolean>;\n}\n\n/** What a Home load does about the Dashboards app. */\nexport type DashboardsAppAutoInstallAction = 'install' | 'skip';\n\n/** What a user click that goes to the Dashboards app does before it navigates. */\nexport type DashboardsAppExplicitInstallAction = 'open' | 'install' | 'unavailable';\n\n/**\n * The automatic path installs only for a user with no UserApplication row for the app and no\n * recorded install. An inactive row means the user removed the app, so it is left alone.\n */\nexport function DecideDashboardsAppAutoInstall(state: DashboardsAppInstallState): DashboardsAppAutoInstallAction {\n const install = state.AppExists && state.Access === 'not_installed' && !state.AutoInstallRecorded;\n return install ? 'install' : 'skip';\n}\n\n/**\n * The explicit path ignores the marker: a missing or removed app is installed, an active one\n * opens, and a missing or unauthorized app is unavailable.\n */\nexport function DecideDashboardsAppExplicitInstall(state: DashboardsAppInstallState): DashboardsAppExplicitInstallAction {\n if (!state.AppExists || state.Access === 'not_authorized') {\n return 'unavailable';\n }\n return state.Access === 'installed_active' ? 'open' : 'install';\n}\n\n/**\n * Automatic path (Home load). Installs the app when {@link DecideDashboardsAppAutoInstall} says so,\n * then records the marker. The marker is written only after a successful install, so a failed or\n * timed-out install is retried on the next load. Each step waits at most\n * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.\n * @returns true when this call installed the app.\n */\nexport function RunDashboardsAppAutoInstall(operations: DashboardsAppInstallOperations): Promise<boolean> {\n return runOneAtATime(async () => {\n const state = operations.ReadState();\n if (!state || DecideDashboardsAppAutoInstall(state) === 'skip') {\n return false;\n }\n if (!(await withStepTimeout(operations.Install(), 'the install'))) {\n return false;\n }\n await withStepTimeout(operations.RecordAutoInstall(), 'the marker save');\n return true;\n });\n}\n\n/**\n * Explicit path (a user click that goes to the app). Installs the app when it is missing or\n * removed, and records the marker if it is not set yet. Each step waits at most\n * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.\n * @returns true when the user has the app active afterwards, so the caller can navigate.\n */\nexport function RunDashboardsAppExplicitInstall(operations: DashboardsAppInstallOperations): Promise<boolean> {\n return runOneAtATime(async () => {\n const state = operations.ReadState();\n if (!state) {\n return false;\n }\n const action = DecideDashboardsAppExplicitInstall(state);\n if (action !== 'install') {\n return action === 'open';\n }\n if (!(await withStepTimeout(operations.Install(), 'the install'))) {\n return false;\n }\n if (!state.AutoInstallRecorded) {\n await withStepTimeout(operations.RecordAutoInstall(), 'the marker save');\n }\n return true;\n });\n}\n\n/**\n * Resolves with the step's result, or with false when the step does not settle within\n * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}. A timed-out step is logged and keeps running in\n * the background, but nothing waits for it. The timer is cleared when the step settles first.\n */\nfunction withStepTimeout(step: Promise<boolean>, stepName: string): Promise<boolean> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<boolean>((resolve) => {\n timer = setTimeout(() => {\n LogError(`Dashboards app install: ${stepName} did not finish within ${DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS} ms, so it counts as failed`);\n resolve(false);\n }, DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS);\n });\n return Promise.race([step, timedOut]).finally(() => clearTimeout(timer));\n}\n\nlet installQueue: Promise<unknown> = Promise.resolve();\n\n/** Runs install work one call at a time, so each call reads the state the previous call left. */\nfunction runOneAtATime<T>(work: () => Promise<T>): Promise<T> {\n const run = installQueue.then(work);\n installQueue = run.catch(() => undefined);\n return run;\n}\n"]}