@memberjunction/ng-dashboards 5.38.0 → 5.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/README.md +14 -7
  2. package/dist/AI/components/agents/agent-configuration.component.js +199 -198
  3. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  4. package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
  5. package/dist/AI/components/analytics/ai-analytics-resource.component.js +20 -17
  6. package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
  7. package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +15 -0
  8. package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -1
  9. package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +166 -58
  10. package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
  11. package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -1
  12. package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +2 -1
  13. package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -1
  14. package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +1 -0
  15. package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -1
  16. package/dist/AI/components/analytics/model-performance/model-performance.component.js +55 -36
  17. package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -1
  18. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +9 -1
  19. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -1
  20. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +158 -117
  21. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -1
  22. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +1 -0
  23. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -1
  24. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +22 -8
  25. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
  26. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +217 -860
  27. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  28. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +1717 -7802
  29. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  30. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts +56 -0
  31. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts.map +1 -0
  32. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js +423 -0
  33. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js.map +1 -0
  34. package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts +70 -0
  35. package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts.map +1 -0
  36. package/dist/AI/components/autotagging/components/classify-item-grid.component.js +308 -0
  37. package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -0
  38. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts +29 -0
  39. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -0
  40. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +186 -0
  41. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -0
  42. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts +69 -0
  43. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts.map +1 -0
  44. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js +278 -0
  45. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js.map +1 -0
  46. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts +73 -0
  47. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts.map +1 -0
  48. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js +393 -0
  49. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js.map +1 -0
  50. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts +122 -0
  51. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts.map +1 -0
  52. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js +908 -0
  53. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js.map +1 -0
  54. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts +87 -0
  55. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts.map +1 -0
  56. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js +475 -0
  57. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js.map +1 -0
  58. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts +29 -0
  59. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts.map +1 -0
  60. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js +208 -0
  61. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js.map +1 -0
  62. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts +21 -0
  63. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts.map +1 -0
  64. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js +70 -0
  65. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js.map +1 -0
  66. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts +333 -0
  67. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -0
  68. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +2125 -0
  69. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -0
  70. package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts +61 -0
  71. package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts.map +1 -0
  72. package/dist/AI/components/autotagging/shared/classify.dryrun.js +78 -0
  73. package/dist/AI/components/autotagging/shared/classify.dryrun.js.map +1 -0
  74. package/dist/AI/components/autotagging/shared/classify.format.d.ts +58 -0
  75. package/dist/AI/components/autotagging/shared/classify.format.d.ts.map +1 -0
  76. package/dist/AI/components/autotagging/shared/classify.format.js +260 -0
  77. package/dist/AI/components/autotagging/shared/classify.format.js.map +1 -0
  78. package/dist/AI/components/autotagging/shared/classify.types.d.ts +319 -0
  79. package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -0
  80. package/dist/AI/components/autotagging/shared/classify.types.js +6 -0
  81. package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -0
  82. package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts +103 -0
  83. package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts.map +1 -0
  84. package/dist/AI/components/autotagging/tabs/health-tab.component.js +571 -0
  85. package/dist/AI/components/autotagging/tabs/health-tab.component.js.map +1 -0
  86. package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts +77 -0
  87. package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts.map +1 -0
  88. package/dist/AI/components/autotagging/tabs/history-tab.component.js +519 -0
  89. package/dist/AI/components/autotagging/tabs/history-tab.component.js.map +1 -0
  90. package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts +107 -0
  91. package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts.map +1 -0
  92. package/dist/AI/components/autotagging/tabs/inbox-tab.component.js +719 -0
  93. package/dist/AI/components/autotagging/tabs/inbox-tab.component.js.map +1 -0
  94. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts +131 -0
  95. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts.map +1 -0
  96. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js +813 -0
  97. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js.map +1 -0
  98. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +177 -0
  99. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -0
  100. package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1465 -0
  101. package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -0
  102. package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts +78 -0
  103. package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts.map +1 -0
  104. package/dist/AI/components/autotagging/tabs/tags-tab.component.js +492 -0
  105. package/dist/AI/components/autotagging/tabs/tags-tab.component.js.map +1 -0
  106. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts +397 -0
  107. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts.map +1 -0
  108. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js +3490 -0
  109. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js.map +1 -0
  110. package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts +56 -0
  111. package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts.map +1 -0
  112. package/dist/AI/components/autotagging/tabs/types-tab.component.js +271 -0
  113. package/dist/AI/components/autotagging/tabs/types-tab.component.js.map +1 -0
  114. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +3 -0
  115. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  116. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +306 -290
  117. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  118. package/dist/AI/components/execution-monitoring.component.js +1 -1
  119. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  120. package/dist/AI/components/models/model-management.component.js +209 -208
  121. package/dist/AI/components/models/model-management.component.js.map +1 -1
  122. package/dist/AI/components/prompts/prompt-management.component.js +130 -128
  123. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  124. package/dist/AI/components/requests/agent-requests-resource.component.js +61 -61
  125. package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
  126. package/dist/AI/components/system/system-configuration.component.js +17 -17
  127. package/dist/AI/components/system/system-configuration.component.js.map +1 -1
  128. package/dist/AI/components/tags/tags-resource.component.d.ts +1 -0
  129. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  130. package/dist/AI/components/tags/tags-resource.component.js +578 -538
  131. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  132. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +3 -0
  133. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  134. package/dist/AI/components/vectors/vector-management-resource.component.js +331 -303
  135. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  136. package/dist/AI/services/ai-instrumentation.service.d.ts +5 -0
  137. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
  138. package/dist/AI/services/ai-instrumentation.service.js +14 -2
  139. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  140. package/dist/AI/services/cache-metrics.d.ts +50 -0
  141. package/dist/AI/services/cache-metrics.d.ts.map +1 -0
  142. package/dist/AI/services/cache-metrics.js +43 -0
  143. package/dist/AI/services/cache-metrics.js.map +1 -0
  144. package/dist/APIKeys/api-applications-panel.component.js +2 -2
  145. package/dist/APIKeys/api-key-create-dialog.component.js +2 -2
  146. package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
  147. package/dist/APIKeys/api-keys-resource.component.js +132 -131
  148. package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
  149. package/dist/Actions/components/actions-overview.component.js +141 -141
  150. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  151. package/dist/Actions/components/execution-monitoring.component.js +15 -15
  152. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  153. package/dist/Actions/components/explorer/action-explorer.component.d.ts +0 -5
  154. package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
  155. package/dist/Actions/components/explorer/action-explorer.component.js +139 -212
  156. package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
  157. package/dist/Admin/admin-data-schema.component.js +2 -2
  158. package/dist/Admin/admin-data-schema.component.js.map +1 -1
  159. package/dist/Admin/admin-dev-tools-resource.component.js +2 -2
  160. package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
  161. package/dist/Admin/admin-identity-access.component.js +2 -2
  162. package/dist/Admin/admin-identity-access.component.js.map +1 -1
  163. package/dist/Admin/admin-monitoring.component.js +2 -2
  164. package/dist/Admin/admin-monitoring.component.js.map +1 -1
  165. package/dist/ApplicationRoles/application-roles-resource.component.js +54 -49
  166. package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
  167. package/dist/Communication/communication-logs-resource.component.d.ts +6 -0
  168. package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
  169. package/dist/Communication/communication-logs-resource.component.js +72 -50
  170. package/dist/Communication/communication-logs-resource.component.js.map +1 -1
  171. package/dist/Communication/communication-monitor-resource.component.js +103 -102
  172. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  173. package/dist/Communication/communication-providers-resource.component.js +52 -51
  174. package/dist/Communication/communication-providers-resource.component.js.map +1 -1
  175. package/dist/Communication/communication-runs-resource.component.js +39 -38
  176. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  177. package/dist/Communication/communication-templates-resource.component.d.ts +6 -0
  178. package/dist/Communication/communication-templates-resource.component.d.ts.map +1 -1
  179. package/dist/Communication/communication-templates-resource.component.js +92 -89
  180. package/dist/Communication/communication-templates-resource.component.js.map +1 -1
  181. package/dist/Credentials/components/credentials-audit-resource.component.js +136 -135
  182. package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
  183. package/dist/Credentials/components/credentials-categories-resource.component.js +155 -152
  184. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  185. package/dist/Credentials/components/credentials-list-resource.component.js +119 -118
  186. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  187. package/dist/Credentials/components/credentials-overview-resource.component.js +129 -128
  188. package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
  189. package/dist/Credentials/components/credentials-types-resource.component.js +107 -106
  190. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  191. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +31 -340
  192. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  193. package/dist/DataExplorer/data-explorer-dashboard.component.js +468 -1958
  194. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  195. package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
  196. package/dist/DataExplorer/data-explorer-resource.component.js +10 -0
  197. package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
  198. package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +1 -1
  199. package/dist/DatabaseDesigner/components/entity-list.component.js +115 -114
  200. package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
  201. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +5 -6
  202. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
  203. package/dist/DatabaseDesigner/database-designer-dashboards.module.js +4 -5
  204. package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
  205. package/dist/DevTools/app-state-inspector.component.js +18 -17
  206. package/dist/DevTools/app-state-inspector.component.js.map +1 -1
  207. package/dist/DevTools/class-registry.component.js +88 -85
  208. package/dist/DevTools/class-registry.component.js.map +1 -1
  209. package/dist/DevTools/event-monitor.component.js +155 -150
  210. package/dist/DevTools/event-monitor.component.js.map +1 -1
  211. package/dist/DevTools/graphql-console.component.js +245 -243
  212. package/dist/DevTools/graphql-console.component.js.map +1 -1
  213. package/dist/DevTools/layout-inspector.component.js +18 -17
  214. package/dist/DevTools/layout-inspector.component.js.map +1 -1
  215. package/dist/EntityAdmin/entity-admin-dashboard.component.js +20 -19
  216. package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
  217. package/dist/Home/home-dashboard.component.js +2 -2
  218. package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
  219. package/dist/Integration/components/activity/activity.component.js +236 -229
  220. package/dist/Integration/components/activity/activity.component.js.map +1 -1
  221. package/dist/Integration/components/connections/connections.component.js +390 -389
  222. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  223. package/dist/Integration/components/overview/overview.component.js +2 -2
  224. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -1
  225. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +14 -11
  226. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
  227. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +27 -2
  228. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -1
  229. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +244 -119
  230. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
  231. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +293 -291
  232. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  233. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +62 -61
  234. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
  235. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts +65 -0
  236. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts.map +1 -0
  237. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js +176 -0
  238. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js.map +1 -0
  239. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts +81 -0
  240. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts.map +1 -0
  241. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js +308 -0
  242. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js.map +1 -0
  243. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts +85 -0
  244. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts.map +1 -0
  245. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js +362 -0
  246. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js.map +1 -0
  247. package/dist/KnowledgeHub/index.d.ts +3 -0
  248. package/dist/KnowledgeHub/index.d.ts.map +1 -1
  249. package/dist/KnowledgeHub/index.js +3 -0
  250. package/dist/KnowledgeHub/index.js.map +1 -1
  251. package/dist/Lists/components/lists-browse-resource.component.d.ts +6 -2
  252. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  253. package/dist/Lists/components/lists-browse-resource.component.js +525 -566
  254. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  255. package/dist/Lists/components/lists-categories-resource.component.js +135 -134
  256. package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
  257. package/dist/Lists/components/lists-my-lists-resource.component.js +199 -198
  258. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  259. package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
  260. package/dist/MCP/mcp-dashboard.component.js +443 -438
  261. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  262. package/dist/QueryBrowser/query-browser-resource.component.js +1 -1
  263. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  264. package/dist/Scheduling/components/scheduling-activity.component.d.ts.map +1 -1
  265. package/dist/Scheduling/components/scheduling-activity.component.js +146 -147
  266. package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
  267. package/dist/Scheduling/components/scheduling-jobs.component.js +76 -75
  268. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  269. package/dist/Scheduling/components/scheduling-overview.component.js +97 -96
  270. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  271. package/dist/Scheduling/scheduling-dashboard.component.js +24 -22
  272. package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
  273. package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts +2 -0
  274. package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
  275. package/dist/Scheduling/services/scheduling-instrumentation.service.js +1 -0
  276. package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
  277. package/dist/Testing/components/testing-dashboard-tab-resource.component.js +1 -1
  278. package/dist/Testing/components/testing-explorer.component.d.ts +14 -4
  279. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  280. package/dist/Testing/components/testing-explorer.component.js +436 -427
  281. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  282. package/dist/Testing/components/testing-runs-resource.component.js +1 -1
  283. package/dist/Testing/components/testing-runs.component.js +116 -115
  284. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  285. package/dist/Testing/testing-dashboard.component.js +6 -7
  286. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  287. package/dist/VersionHistory/components/labels-resource.component.js +173 -172
  288. package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
  289. package/dist/VersionHistory/components/restore-resource.component.d.ts +6 -0
  290. package/dist/VersionHistory/components/restore-resource.component.d.ts.map +1 -1
  291. package/dist/VersionHistory/components/restore-resource.component.js +116 -92
  292. package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
  293. package/dist/ai-dashboards.module.d.ts +57 -35
  294. package/dist/ai-dashboards.module.d.ts.map +1 -1
  295. package/dist/ai-dashboards.module.js +80 -1
  296. package/dist/ai-dashboards.module.js.map +1 -1
  297. package/dist/communication-dashboards.module.d.ts +1 -1
  298. package/dist/communication-dashboards.module.d.ts.map +1 -1
  299. package/dist/communication-dashboards.module.js +7 -1
  300. package/dist/communication-dashboards.module.js.map +1 -1
  301. package/dist/data-explorer-dashboards.module.d.ts +12 -14
  302. package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
  303. package/dist/data-explorer-dashboards.module.js +5 -14
  304. package/dist/data-explorer-dashboards.module.js.map +1 -1
  305. package/dist/public-api.d.ts +3 -0
  306. package/dist/public-api.d.ts.map +1 -1
  307. package/dist/public-api.js +3 -0
  308. package/dist/public-api.js.map +1 -1
  309. package/dist/testing-dashboards.module.d.ts +4 -5
  310. package/dist/testing-dashboards.module.d.ts.map +1 -1
  311. package/dist/testing-dashboards.module.js +7 -5
  312. package/dist/testing-dashboards.module.js.map +1 -1
  313. package/package.json +57 -54
  314. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts +0 -79
  315. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts.map +0 -1
  316. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +0 -195
  317. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +0 -1
  318. package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts +0 -226
  319. package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +0 -1
  320. package/dist/DataExplorer/components/view-selector/view-selector.component.js +0 -861
  321. package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +0 -1
@@ -40,7 +40,7 @@ function SchedulingResourceComponent_Conditional_0_Conditional_4_Template(rf, ct
40
40
  const ctx_r1 = i0.ɵɵnextContext(2);
41
41
  i0.ɵɵproperty("Count", ctx_r1.PausedCount);
42
42
  } }
43
- function SchedulingResourceComponent_Conditional_0_ng_container_23_Template(rf, ctx) { if (rf & 1) {
43
+ function SchedulingResourceComponent_Conditional_0_ng_container_24_Template(rf, ctx) { if (rf & 1) {
44
44
  i0.ɵɵelementContainer(0);
45
45
  } }
46
46
  function SchedulingResourceComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
@@ -52,31 +52,32 @@ function SchedulingResourceComponent_Conditional_0_Template(rf, ctx) { if (rf &
52
52
  i0.ɵɵelementStart(5, "div", 5)(6, "button", 6);
53
53
  i0.ɵɵlistener("click", function SchedulingResourceComponent_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnNewSchedule()); });
54
54
  i0.ɵɵelement(7, "i", 7);
55
- i0.ɵɵtext(8, " New Schedule ");
56
- i0.ɵɵelementEnd()();
57
- i0.ɵɵelementStart(9, "div", 8)(10, "mj-page-search", 9);
58
- i0.ɵɵlistener("ValueChange", function SchedulingResourceComponent_Conditional_0_Template_mj_page_search_ValueChange_10_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.SearchQuery = $event; return i0.ɵɵresetView(ctx_r1.OnSearchChanged()); });
55
+ i0.ɵɵelementStart(8, "span", 8);
56
+ i0.ɵɵtext(9, "New Schedule");
57
+ i0.ɵɵelementEnd()()();
58
+ i0.ɵɵelementStart(10, "div", 9)(11, "mj-page-search", 10);
59
+ i0.ɵɵlistener("ValueChange", function SchedulingResourceComponent_Conditional_0_Template_mj_page_search_ValueChange_11_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.SearchQuery = $event; return i0.ɵɵresetView(ctx_r1.OnSearchChanged()); });
59
60
  i0.ɵɵelementEnd();
60
- i0.ɵɵelementStart(11, "select", 10);
61
- i0.ɵɵtwoWayListener("ngModelChange", function SchedulingResourceComponent_Conditional_0_Template_select_ngModelChange_11_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.StatusFilter, $event) || (ctx_r1.StatusFilter = $event); return i0.ɵɵresetView($event); });
62
- i0.ɵɵlistener("ngModelChange", function SchedulingResourceComponent_Conditional_0_Template_select_ngModelChange_11_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnFilterChanged()); });
63
- i0.ɵɵelementStart(12, "option", 11);
64
- i0.ɵɵtext(13, "All Statuses");
61
+ i0.ɵɵelementStart(12, "select", 11);
62
+ i0.ɵɵtwoWayListener("ngModelChange", function SchedulingResourceComponent_Conditional_0_Template_select_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.StatusFilter, $event) || (ctx_r1.StatusFilter = $event); return i0.ɵɵresetView($event); });
63
+ i0.ɵɵlistener("ngModelChange", function SchedulingResourceComponent_Conditional_0_Template_select_ngModelChange_12_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnFilterChanged()); });
64
+ i0.ɵɵelementStart(13, "option", 12);
65
+ i0.ɵɵtext(14, "All Statuses");
65
66
  i0.ɵɵelementEnd();
66
- i0.ɵɵelementStart(14, "option", 12);
67
- i0.ɵɵtext(15, "Active");
67
+ i0.ɵɵelementStart(15, "option", 13);
68
+ i0.ɵɵtext(16, "Active");
68
69
  i0.ɵɵelementEnd();
69
- i0.ɵɵelementStart(16, "option", 13);
70
- i0.ɵɵtext(17, "Paused");
70
+ i0.ɵɵelementStart(17, "option", 14);
71
+ i0.ɵɵtext(18, "Paused");
71
72
  i0.ɵɵelementEnd();
72
- i0.ɵɵelementStart(18, "option", 14);
73
- i0.ɵɵtext(19, "Disabled");
73
+ i0.ɵɵelementStart(19, "option", 15);
74
+ i0.ɵɵtext(20, "Disabled");
74
75
  i0.ɵɵelementEnd();
75
- i0.ɵɵelementStart(20, "option", 15);
76
- i0.ɵɵtext(21, "Pending");
76
+ i0.ɵɵelementStart(21, "option", 16);
77
+ i0.ɵɵtext(22, "Pending");
77
78
  i0.ɵɵelementEnd()()()();
78
- i0.ɵɵelementStart(22, "mj-page-body");
79
- i0.ɵɵtemplate(23, SchedulingResourceComponent_Conditional_0_ng_container_23_Template, 1, 0, "ng-container", 16);
79
+ i0.ɵɵelementStart(23, "mj-page-body");
80
+ i0.ɵɵtemplate(24, SchedulingResourceComponent_Conditional_0_ng_container_24_Template, 1, 0, "ng-container", 17);
80
81
  i0.ɵɵelementEnd()();
81
82
  } if (rf & 2) {
82
83
  const ctx_r1 = i0.ɵɵnextContext();
@@ -85,7 +86,7 @@ function SchedulingResourceComponent_Conditional_0_Template(rf, ctx) { if (rf &
85
86
  i0.ɵɵconditional(ctx_r1.ActiveCount > 0 ? 3 : -1);
86
87
  i0.ɵɵadvance();
87
88
  i0.ɵɵconditional(ctx_r1.PausedCount > 0 ? 4 : -1);
88
- i0.ɵɵadvance(6);
89
+ i0.ɵɵadvance(7);
89
90
  i0.ɵɵproperty("Value", ctx_r1.SearchQuery);
90
91
  i0.ɵɵadvance();
91
92
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.StatusFilter);
@@ -97,35 +98,35 @@ function SchedulingResourceComponent_Conditional_1_ng_container_17_Template(rf,
97
98
  } }
98
99
  function SchedulingResourceComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
99
100
  const _r4 = i0.ɵɵgetCurrentView();
100
- i0.ɵɵelementStart(0, "div", 17)(1, "input", 18);
101
+ i0.ɵɵelementStart(0, "div", 18)(1, "input", 19);
101
102
  i0.ɵɵtwoWayListener("ngModelChange", function SchedulingResourceComponent_Conditional_1_Template_input_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.SearchQuery, $event) || (ctx_r1.SearchQuery = $event); return i0.ɵɵresetView($event); });
102
103
  i0.ɵɵlistener("ngModelChange", function SchedulingResourceComponent_Conditional_1_Template_input_ngModelChange_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnSearchChanged()); });
103
104
  i0.ɵɵelementEnd();
104
- i0.ɵɵelementStart(2, "select", 10);
105
+ i0.ɵɵelementStart(2, "select", 11);
105
106
  i0.ɵɵtwoWayListener("ngModelChange", function SchedulingResourceComponent_Conditional_1_Template_select_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.StatusFilter, $event) || (ctx_r1.StatusFilter = $event); return i0.ɵɵresetView($event); });
106
107
  i0.ɵɵlistener("ngModelChange", function SchedulingResourceComponent_Conditional_1_Template_select_ngModelChange_2_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnFilterChanged()); });
107
- i0.ɵɵelementStart(3, "option", 11);
108
+ i0.ɵɵelementStart(3, "option", 12);
108
109
  i0.ɵɵtext(4, "All Statuses");
109
110
  i0.ɵɵelementEnd();
110
- i0.ɵɵelementStart(5, "option", 12);
111
+ i0.ɵɵelementStart(5, "option", 13);
111
112
  i0.ɵɵtext(6, "Active");
112
113
  i0.ɵɵelementEnd();
113
- i0.ɵɵelementStart(7, "option", 13);
114
+ i0.ɵɵelementStart(7, "option", 14);
114
115
  i0.ɵɵtext(8, "Paused");
115
116
  i0.ɵɵelementEnd();
116
- i0.ɵɵelementStart(9, "option", 14);
117
+ i0.ɵɵelementStart(9, "option", 15);
117
118
  i0.ɵɵtext(10, "Disabled");
118
119
  i0.ɵɵelementEnd();
119
- i0.ɵɵelementStart(11, "option", 15);
120
+ i0.ɵɵelementStart(11, "option", 16);
120
121
  i0.ɵɵtext(12, "Pending");
121
122
  i0.ɵɵelementEnd()();
122
- i0.ɵɵelement(13, "span", 19);
123
+ i0.ɵɵelement(13, "span", 20);
123
124
  i0.ɵɵelementStart(14, "button", 6);
124
125
  i0.ɵɵlistener("click", function SchedulingResourceComponent_Conditional_1_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnNewSchedule()); });
125
126
  i0.ɵɵelement(15, "i", 7);
126
127
  i0.ɵɵtext(16, " New Schedule ");
127
128
  i0.ɵɵelementEnd()();
128
- i0.ɵɵtemplate(17, SchedulingResourceComponent_Conditional_1_ng_container_17_Template, 1, 0, "ng-container", 16);
129
+ i0.ɵɵtemplate(17, SchedulingResourceComponent_Conditional_1_ng_container_17_Template, 1, 0, "ng-container", 17);
129
130
  } if (rf & 2) {
130
131
  const ctx_r1 = i0.ɵɵnextContext();
131
132
  const schedulingBody_r3 = i0.ɵɵreference(3);
@@ -137,47 +138,47 @@ function SchedulingResourceComponent_Conditional_1_Template(rf, ctx) { if (rf &
137
138
  i0.ɵɵproperty("ngTemplateOutlet", schedulingBody_r3);
138
139
  } }
139
140
  function SchedulingResourceComponent_ng_template_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
140
- i0.ɵɵelementStart(0, "div", 20);
141
- i0.ɵɵelement(1, "mj-loading", 21);
141
+ i0.ɵɵelementStart(0, "div", 21);
142
+ i0.ɵɵelement(1, "mj-loading", 22);
142
143
  i0.ɵɵelementEnd();
143
144
  } }
144
145
  function SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_For_2_For_11_Template(rf, ctx) { if (rf & 1) {
145
- i0.ɵɵelement(0, "span", 44);
146
+ i0.ɵɵelement(0, "span", 45);
146
147
  } if (rf & 2) {
147
148
  const dotClass_r8 = ctx.$implicit;
148
149
  i0.ɵɵclassMap(dotClass_r8);
149
150
  } }
150
151
  function SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_For_2_Template(rf, ctx) { if (rf & 1) {
151
152
  const _r6 = i0.ɵɵgetCurrentView();
152
- i0.ɵɵelementStart(0, "div", 30);
153
+ i0.ɵɵelementStart(0, "div", 31);
153
154
  i0.ɵɵlistener("click", function SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_For_2_Template_div_click_0_listener() { const job_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnEditJob(job_r7)); });
154
- i0.ɵɵelementStart(1, "div", 31);
155
- i0.ɵɵelement(2, "span", 32);
156
- i0.ɵɵelementStart(3, "div", 33)(4, "div", 34);
155
+ i0.ɵɵelementStart(1, "div", 32);
156
+ i0.ɵɵelement(2, "span", 33);
157
+ i0.ɵɵelementStart(3, "div", 34)(4, "div", 35);
157
158
  i0.ɵɵtext(5);
158
159
  i0.ɵɵelementEnd();
159
- i0.ɵɵelementStart(6, "div", 35);
160
- i0.ɵɵelement(7, "i", 36);
160
+ i0.ɵɵelementStart(6, "div", 36);
161
+ i0.ɵɵelement(7, "i", 37);
161
162
  i0.ɵɵtext(8);
162
163
  i0.ɵɵelementEnd()()();
163
- i0.ɵɵelementStart(9, "div", 37);
164
- i0.ɵɵrepeaterCreate(10, SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_For_2_For_11_Template, 1, 2, "span", 38, i0.ɵɵrepeaterTrackByIndex);
165
- i0.ɵɵelementStart(12, "span", 39);
164
+ i0.ɵɵelementStart(9, "div", 38);
165
+ i0.ɵɵrepeaterCreate(10, SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_For_2_For_11_Template, 1, 2, "span", 39, i0.ɵɵrepeaterTrackByIndex);
166
+ i0.ɵɵelementStart(12, "span", 40);
166
167
  i0.ɵɵtext(13, "last 7 runs");
167
168
  i0.ɵɵelementEnd()();
168
- i0.ɵɵelementStart(14, "div", 40)(15, "span", 41);
169
- i0.ɵɵelement(16, "i", 36);
169
+ i0.ɵɵelementStart(14, "div", 41)(15, "span", 42);
170
+ i0.ɵɵelement(16, "i", 37);
170
171
  i0.ɵɵtext(17, " Last: ");
171
172
  i0.ɵɵelementStart(18, "strong");
172
173
  i0.ɵɵtext(19);
173
174
  i0.ɵɵelementEnd()();
174
- i0.ɵɵelementStart(20, "span", 41);
175
- i0.ɵɵelement(21, "i", 42);
175
+ i0.ɵɵelementStart(20, "span", 42);
176
+ i0.ɵɵelement(21, "i", 43);
176
177
  i0.ɵɵelementStart(22, "strong");
177
178
  i0.ɵɵtext(23);
178
179
  i0.ɵɵelementEnd()();
179
- i0.ɵɵelementStart(24, "span", 41);
180
- i0.ɵɵelement(25, "i", 43);
180
+ i0.ɵɵelementStart(24, "span", 42);
181
+ i0.ɵɵelement(25, "i", 44);
181
182
  i0.ɵɵtext(26, " Next: ");
182
183
  i0.ɵɵelementStart(27, "strong");
183
184
  i0.ɵɵtext(28);
@@ -202,8 +203,8 @@ function SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_F
202
203
  i0.ɵɵtextInterpolate(ctx_r1.GetTimeUntil(job_r7.NextRunAt));
203
204
  } }
204
205
  function SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
205
- i0.ɵɵelementStart(0, "div", 22);
206
- i0.ɵɵrepeaterCreate(1, SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_For_2_Template, 29, 15, "div", 29, _forTrack0);
206
+ i0.ɵɵelementStart(0, "div", 23);
207
+ i0.ɵɵrepeaterCreate(1, SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_For_2_Template, 29, 15, "div", 30, _forTrack0);
207
208
  i0.ɵɵelementEnd();
208
209
  } if (rf & 2) {
209
210
  const ctx_r1 = i0.ɵɵnextContext(3);
@@ -211,8 +212,8 @@ function SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_T
211
212
  i0.ɵɵrepeater(ctx_r1.FilteredJobs);
212
213
  } }
213
214
  function SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
214
- i0.ɵɵelementStart(0, "div", 23);
215
- i0.ɵɵelement(1, "i", 45);
215
+ i0.ɵɵelementStart(0, "div", 24);
216
+ i0.ɵɵelement(1, "i", 46);
216
217
  i0.ɵɵelementStart(2, "p");
217
218
  i0.ɵɵtext(3, "No Knowledge Hub schedules found");
218
219
  i0.ɵɵelementEnd();
@@ -222,16 +223,16 @@ function SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_1_T
222
223
  } }
223
224
  function SchedulingResourceComponent_ng_template_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
224
225
  const _r5 = i0.ɵɵgetCurrentView();
225
- i0.ɵɵconditionalCreate(0, SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_Template, 3, 0, "div", 22)(1, SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_1_Template, 6, 0, "div", 23);
226
- i0.ɵɵelementStart(2, "div", 24)(3, "button", 25);
226
+ i0.ɵɵconditionalCreate(0, SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_0_Template, 3, 0, "div", 23)(1, SchedulingResourceComponent_ng_template_2_Conditional_1_Conditional_1_Template, 6, 0, "div", 24);
227
+ i0.ɵɵelementStart(2, "div", 25)(3, "button", 26);
227
228
  i0.ɵɵlistener("click", function SchedulingResourceComponent_ng_template_2_Conditional_1_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.GoToSchedulingApp()); });
228
- i0.ɵɵelement(4, "i", 26);
229
+ i0.ɵɵelement(4, "i", 27);
229
230
  i0.ɵɵtext(5, " Open Scheduling App ");
230
231
  i0.ɵɵelementEnd();
231
- i0.ɵɵelementStart(6, "span", 27);
232
+ i0.ɵɵelementStart(6, "span", 28);
232
233
  i0.ɵɵtext(7, "Manage all scheduled jobs across the system");
233
234
  i0.ɵɵelementEnd()();
234
- i0.ɵɵelementStart(8, "mj-scheduled-job-dialog", 28);
235
+ i0.ɵɵelementStart(8, "mj-scheduled-job-dialog", 29);
235
236
  i0.ɵɵlistener("Close", function SchedulingResourceComponent_ng_template_2_Conditional_1_Template_mj_scheduled_job_dialog_Close_8_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnDialogClosed($event)); });
236
237
  i0.ɵɵelementEnd();
237
238
  } if (rf & 2) {
@@ -241,7 +242,7 @@ function SchedulingResourceComponent_ng_template_2_Conditional_1_Template(rf, ct
241
242
  i0.ɵɵproperty("Visible", ctx_r1.ShowEditDialog)("ScheduledJobID", ctx_r1.EditingJobID);
242
243
  } }
243
244
  function SchedulingResourceComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) {
244
- i0.ɵɵconditionalCreate(0, SchedulingResourceComponent_ng_template_2_Conditional_0_Template, 2, 0, "div", 20)(1, SchedulingResourceComponent_ng_template_2_Conditional_1_Template, 9, 3);
245
+ i0.ɵɵconditionalCreate(0, SchedulingResourceComponent_ng_template_2_Conditional_0_Template, 2, 0, "div", 21)(1, SchedulingResourceComponent_ng_template_2_Conditional_1_Template, 9, 3);
245
246
  } if (rf & 2) {
246
247
  const ctx_r1 = i0.ɵɵnextContext();
247
248
  i0.ɵɵconditional(ctx_r1.IsLoading ? 0 : 1);
@@ -645,8 +646,8 @@ let SchedulingResourceComponent = class SchedulingResourceComponent extends Base
645
646
  return n.toLocaleString();
646
647
  }
647
648
  static ɵfac = /*@__PURE__*/ (() => { let ɵSchedulingResourceComponent_BaseFactory; return function SchedulingResourceComponent_Factory(__ngFactoryType__) { return (ɵSchedulingResourceComponent_BaseFactory || (ɵSchedulingResourceComponent_BaseFactory = i0.ɵɵgetInheritedFactory(SchedulingResourceComponent)))(__ngFactoryType__ || SchedulingResourceComponent); }; })();
648
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SchedulingResourceComponent, selectors: [["app-scheduling-resource"]], inputs: { HideToolbar: "HideToolbar" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [["schedulingBody", ""], ["Title", "Knowledge Pipelines", "Icon", "fa-solid fa-calendar-check", "Subtitle", "Scheduled knowledge ingestion, autotagging, and embedding pipelines"], ["meta", ""], ["Label", "active", "Variant", "success", 3, "Count"], ["Label", "paused", "Variant", "warning", 3, "Count"], ["actions", ""], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-plus"], ["toolbar", ""], ["Placeholder", "Search pipelines...", 3, "ValueChange", "Value"], [1, "mj-input", "kh-toolbar-select", 3, "ngModelChange", "ngModel"], ["value", ""], ["value", "Active"], ["value", "Paused"], ["value", "Disabled"], ["value", "Pending"], [4, "ngTemplateOutlet"], [1, "embedded-controls"], ["type", "text", "placeholder", "Search pipelines...", 1, "mj-input", "embedded-search", 3, "ngModelChange", "ngModel"], [1, "embedded-spacer"], [1, "loading-container"], ["text", "Loading scheduled pipelines..."], [1, "cards-grid"], [1, "empty-state"], [1, "scheduling-app-link"], [1, "btn-secondary", 3, "click"], [1, "fa-solid", "fa-arrow-up-right-from-square"], [1, "link-hint"], [3, "Close", "Visible", "ScheduledJobID"], [1, "job-card", 3, "paused", "disabled"], [1, "job-card", 3, "click"], [1, "card-top"], [1, "status-dot"], [1, "card-title-area"], [1, "card-name"], [1, "card-cron"], [1, "fa-regular", "fa-clock"], [1, "sparkline"], [1, "spark-dot", 3, "class"], [1, "sparkline-label"], [1, "card-stats"], [1, "stat"], [1, "fa-solid", "fa-chart-simple"], [1, "fa-regular", "fa-calendar"], [1, "spark-dot"], [1, "fa-regular", "fa-calendar-xmark"]], template: function SchedulingResourceComponent_Template(rf, ctx) { if (rf & 1) {
649
- i0.ɵɵconditionalCreate(0, SchedulingResourceComponent_Conditional_0_Template, 24, 5, "mj-page-layout");
649
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SchedulingResourceComponent, selectors: [["app-scheduling-resource"]], inputs: { HideToolbar: "HideToolbar" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [["schedulingBody", ""], ["Title", "Knowledge Pipelines", "Icon", "fa-solid fa-calendar-check", "Subtitle", "Scheduled knowledge ingestion, autotagging, and embedding pipelines"], ["meta", ""], ["Label", "active", "Variant", "success", 3, "Count"], ["Label", "paused", "Variant", "warning", 3, "Count"], ["actions", ""], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "action-btn-label"], ["toolbar", ""], ["Placeholder", "Search pipelines...", 3, "ValueChange", "Value"], [1, "mj-input", "kh-toolbar-select", 3, "ngModelChange", "ngModel"], ["value", ""], ["value", "Active"], ["value", "Paused"], ["value", "Disabled"], ["value", "Pending"], [4, "ngTemplateOutlet"], [1, "embedded-controls"], ["type", "text", "placeholder", "Search pipelines...", 1, "mj-input", "embedded-search", 3, "ngModelChange", "ngModel"], [1, "embedded-spacer"], [1, "loading-container"], ["text", "Loading scheduled pipelines..."], [1, "cards-grid"], [1, "empty-state"], [1, "scheduling-app-link"], [1, "btn-secondary", 3, "click"], [1, "fa-solid", "fa-arrow-up-right-from-square"], [1, "link-hint"], [3, "Close", "Visible", "ScheduledJobID"], [1, "job-card", 3, "paused", "disabled"], [1, "job-card", 3, "click"], [1, "card-top"], [1, "status-dot"], [1, "card-title-area"], [1, "card-name"], [1, "card-cron"], [1, "fa-regular", "fa-clock"], [1, "sparkline"], [1, "spark-dot", 3, "class"], [1, "sparkline-label"], [1, "card-stats"], [1, "stat"], [1, "fa-solid", "fa-chart-simple"], [1, "fa-regular", "fa-calendar"], [1, "spark-dot"], [1, "fa-regular", "fa-calendar-xmark"]], template: function SchedulingResourceComponent_Template(rf, ctx) { if (rf & 1) {
650
+ i0.ɵɵconditionalCreate(0, SchedulingResourceComponent_Conditional_0_Template, 25, 5, "mj-page-layout");
650
651
  i0.ɵɵconditionalCreate(1, SchedulingResourceComponent_Conditional_1_Template, 18, 3);
651
652
  i0.ɵɵtemplate(2, SchedulingResourceComponent_ng_template_2_Template, 2, 1, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor);
652
653
  } if (rf & 2) {
@@ -661,7 +662,7 @@ SchedulingResourceComponent = __decorate([
661
662
  export { SchedulingResourceComponent };
662
663
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SchedulingResourceComponent, [{
663
664
  type: Component,
664
- args: [{ standalone: false, selector: 'app-scheduling-resource', template: "@if (!HideToolbar) {\n<mj-page-layout>\n <mj-page-header\n Title=\"Knowledge Pipelines\"\n Icon=\"fa-solid fa-calendar-check\"\n Subtitle=\"Scheduled knowledge ingestion, autotagging, and embedding pipelines\">\n <div meta>\n @if (ActiveCount > 0) {\n <mj-stat-badge [Count]=\"ActiveCount\" Label=\"active\" Variant=\"success\"></mj-stat-badge>\n }\n @if (PausedCount > 0) {\n <mj-stat-badge [Count]=\"PausedCount\" Label=\"paused\" Variant=\"warning\"></mj-stat-badge>\n }\n </div>\n <div actions>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"OnNewSchedule()\">\n <i class=\"fa-solid fa-plus\"></i> New Schedule\n </button>\n </div>\n <div toolbar>\n <mj-page-search\n Placeholder=\"Search pipelines...\"\n [Value]=\"SearchQuery\"\n (ValueChange)=\"SearchQuery = $event; OnSearchChanged()\">\n </mj-page-search>\n <select class=\"mj-input kh-toolbar-select\" [(ngModel)]=\"StatusFilter\" (ngModelChange)=\"OnFilterChanged()\">\n <option value=\"\">All Statuses</option>\n <option value=\"Active\">Active</option>\n <option value=\"Paused\">Paused</option>\n <option value=\"Disabled\">Disabled</option>\n <option value=\"Pending\">Pending</option>\n </select>\n </div>\n </mj-page-header>\n\n <mj-page-body>\n <ng-container *ngTemplateOutlet=\"schedulingBody\"></ng-container>\n </mj-page-body>\n</mj-page-layout>\n}\n@if (HideToolbar) {\n <div class=\"embedded-controls\">\n <input\n type=\"text\"\n class=\"mj-input embedded-search\"\n placeholder=\"Search pipelines...\"\n [(ngModel)]=\"SearchQuery\"\n (ngModelChange)=\"OnSearchChanged()\" />\n <select class=\"mj-input kh-toolbar-select\" [(ngModel)]=\"StatusFilter\" (ngModelChange)=\"OnFilterChanged()\">\n <option value=\"\">All Statuses</option>\n <option value=\"Active\">Active</option>\n <option value=\"Paused\">Paused</option>\n <option value=\"Disabled\">Disabled</option>\n <option value=\"Pending\">Pending</option>\n </select>\n <span class=\"embedded-spacer\"></span>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"OnNewSchedule()\">\n <i class=\"fa-solid fa-plus\"></i> New Schedule\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"schedulingBody\"></ng-container>\n}\n\n<ng-template #schedulingBody>\n@if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading scheduled pipelines...\"></mj-loading>\n </div>\n} @else {\n <!-- Job Cards Grid -->\n @if (FilteredJobs.length > 0) {\n <div class=\"cards-grid\">\n @for (job of FilteredJobs; track job.ID) {\n <div class=\"job-card\"\n [class.paused]=\"job.Status === 'Paused'\"\n [class.disabled]=\"job.Status === 'Disabled'\"\n (click)=\"OnEditJob(job)\">\n <div class=\"card-top\">\n <span class=\"status-dot\"\n [class.dot-active]=\"job.Status === 'Active'\"\n [class.dot-paused]=\"job.Status === 'Paused'\"\n [class.dot-disabled]=\"job.Status === 'Disabled'\"></span>\n <div class=\"card-title-area\">\n <div class=\"card-name\">{{ job.Name }}</div>\n <div class=\"card-cron\">\n <i class=\"fa-regular fa-clock\"></i>\n {{ GetCronDescription(job.CronExpression) }}\n </div>\n </div>\n </div>\n <div class=\"sparkline\">\n @for (dotClass of GetSparkline(job.ID); track $index) {\n <span class=\"spark-dot\" [class]=\"dotClass\"></span>\n }\n <span class=\"sparkline-label\">last 7 runs</span>\n </div>\n <div class=\"card-stats\">\n <span class=\"stat\">\n <i class=\"fa-regular fa-clock\"></i>\n Last: <strong>{{ GetTimeAgo(job.LastRunAt) }}</strong>\n </span>\n <span class=\"stat\">\n <i class=\"fa-solid fa-chart-simple\"></i>\n <strong>{{ GetSuccessRate(job) }}</strong>\n </span>\n <span class=\"stat\">\n <i class=\"fa-regular fa-calendar\"></i>\n Next: <strong>{{ GetTimeUntil(job.NextRunAt) }}</strong>\n </span>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-regular fa-calendar-xmark\"></i>\n <p>No Knowledge Hub schedules found</p>\n <span>Create a new schedule to automate classification and vector sync</span>\n </div>\n }\n\n <!-- Link to full Scheduling App -->\n <div class=\"scheduling-app-link\">\n <button class=\"btn-secondary\" (click)=\"GoToSchedulingApp()\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open Scheduling App\n </button>\n <span class=\"link-hint\">Manage all scheduled jobs across the system</span>\n </div>\n\n <!-- Edit Dialog -->\n <mj-scheduled-job-dialog\n [Visible]=\"ShowEditDialog\"\n [ScheduledJobID]=\"EditingJobID\"\n (Close)=\"OnDialogClosed($event)\">\n </mj-scheduled-job-dialog>\n}\n</ng-template>\n", styles: ["/* \u2500\u2500 Host \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-width: 0;\n}\n\n/* Embedded mode: inline controls row instead of <mj-page-header>. */\n.embedded-controls {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.embedded-search {\n flex: 1;\n max-width: 320px;\n}\n\n.embedded-spacer {\n flex: 1;\n}\n\n/* Status select used in the [toolbar] slot. */\n.kh-toolbar-select {\n width: auto;\n min-width: 140px;\n min-height: 32px;\n padding: 4px 28px 4px 12px;\n font-size: 0.8125rem;\n}\n\n/* \u2500\u2500 Page Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.page-header {\n margin-bottom: 24px;\n}\n.page-header h1 {\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n.page-header p {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n/* \u2500\u2500 Toolbar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.toolbar {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n flex-wrap: wrap;\n}\n.btn-primary {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: var(--mj-radius-sm, 6px);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s;\n white-space: nowrap;\n}\n.btn-primary:hover {\n background: var(--mj-brand-primary-hover);\n}\n.filter-select {\n padding: 7px 32px 7px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm, 6px);\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%2394a3b8'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 10px center;\n cursor: pointer;\n}\n.search-input {\n padding: 7px 12px 7px 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm, 6px);\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n width: 220px;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' fill='%2394a3b8'%3E%3Cpath d='M10 6.5a3.5 3.5 0 11-7 0 3.5 3.5 0 017 0zm-.3 3.9a5.5 5.5 0 111.1-1.1l3.1 3.1a.75.75 0 01-1.1 1.1L9.7 10.4z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: 10px center;\n}\n.search-input::placeholder {\n color: var(--mj-text-muted);\n}\n.toolbar-spacer {\n flex: 1;\n}\n.toolbar-stat {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n.toolbar-stat strong {\n color: var(--mj-text-secondary);\n font-weight: 600;\n}\n\n/* \u2500\u2500 Card Grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.card-grid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 14px;\n margin-bottom: 32px;\n}\n@media (max-width: 1024px) {\n .card-grid { grid-template-columns: repeat(2, 1fr); }\n}\n@media (max-width: 640px) {\n .card-grid { grid-template-columns: 1fr; }\n}\n\n/* \u2500\u2500 Job Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.job-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n padding: 14px 16px;\n box-shadow: var(--mj-shadow-card, 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04));\n position: relative;\n cursor: pointer;\n transition: box-shadow 0.2s, border-color 0.2s;\n height: 132px;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n}\n.job-card:hover {\n box-shadow: var(--mj-shadow-card-hover, 0 4px 12px rgba(0,0,0,0.08), 0 2px 4px rgba(0,0,0,0.04));\n border-color: var(--mj-border-strong);\n}\n.job-card:hover .card-actions {\n opacity: 1;\n}\n.job-card.disabled-card {\n opacity: 0.65;\n}\n\n.card-top {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n.status-dot {\n width: 9px;\n height: 9px;\n border-radius: 50%;\n flex-shrink: 0;\n margin-top: 4px;\n}\n.status-dot.active {\n background: var(--mj-status-success);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 18%, transparent);\n}\n.status-dot.paused {\n background: var(--mj-status-warning);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-warning) 18%, transparent);\n}\n.status-dot.disabled,\n.status-dot.pending,\n.status-dot.expired {\n background: var(--mj-border-strong);\n}\n\n.card-title-area {\n flex: 1;\n min-width: 0;\n}\n.card-title {\n font-size: 13.5px;\n font-weight: 650;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: 1.3;\n}\n.card-cron {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 1px;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.card-cron i {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n/* Stats row */\n.card-stats {\n display: flex;\n align-items: center;\n gap: 16px;\n font-size: 11.5px;\n color: var(--mj-text-muted);\n}\n.card-stat {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.card-stat i {\n font-size: 10px;\n}\n.card-stat .value {\n color: var(--mj-text-secondary);\n font-weight: 600;\n}\n.success-rate {\n font-weight: 700;\n}\n.success-rate.high {\n color: var(--mj-status-success);\n}\n.success-rate.mid {\n color: var(--mj-status-warning);\n}\n\n/* Sparkline */\n.sparkline {\n display: flex;\n align-items: center;\n gap: 3px;\n margin-top: 8px;\n}\n.spark-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n}\n.spark-dot.ok {\n background: color-mix(in srgb, var(--mj-status-success) 65%, transparent);\n}\n.spark-dot.fail {\n background: color-mix(in srgb, var(--mj-status-error) 65%, transparent);\n}\n.spark-dot.skip {\n background: var(--mj-border-default);\n}\n.sparkline-label {\n font-size: 10px;\n color: var(--mj-text-muted);\n margin-left: 4px;\n}\n\n/* Hover actions */\n.card-actions {\n position: absolute;\n top: 10px;\n right: 10px;\n display: flex;\n gap: 6px;\n opacity: 0;\n transition: opacity 0.15s;\n}\n.card-action-btn {\n padding: 4px 10px;\n font-size: 11px;\n font-weight: 600;\n border-radius: 4px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.12s;\n box-shadow: 0 1px 2px rgba(0,0,0,0.06);\n}\n.card-action-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\n}\n.card-action-btn.run-now {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\n}\n.card-action-btn.run-now:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n}\n\n/* Paused/disabled status on card */\n.card-status-label {\n font-weight: 600;\n font-size: 11.5px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.card-status-label.paused {\n color: var(--mj-status-warning);\n}\n.card-status-label.disabled {\n color: var(--mj-text-muted);\n}\n\n/* \u2500\u2500 Section Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 14px;\n}\n.section-header h2 {\n font-size: 15px;\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n.section-header .badge {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n/* \u2500\u2500 Activity Table \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.activity-table {\n width: 100%;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n box-shadow: var(--mj-shadow-card, 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04));\n overflow: hidden;\n}\n.activity-table table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n.activity-table thead th {\n background: var(--mj-bg-surface-card);\n padding: 10px 14px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 11.5px;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n border-bottom: 1px solid var(--mj-border-default);\n}\n.activity-table tbody td {\n padding: 9px 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n}\n.activity-table tbody tr:last-child td {\n border-bottom: none;\n}\n.activity-table tbody tr:hover {\n background: var(--mj-bg-surface-hover);\n}\n.activity-table .job-name-cell {\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n.activity-table .time-cell {\n color: var(--mj-text-secondary);\n font-size: 12.5px;\n}\n.items-cell {\n text-align: right;\n font-weight: 600;\n}\n.items-cell.failed {\n color: var(--mj-status-error);\n}\n\n/* Status badges */\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 10px;\n border-radius: 10px;\n font-size: 11.5px;\n font-weight: 600;\n}\n.status-badge.success {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n.status-badge.failed {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n.status-badge.running {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info);\n}\n.status-badge i {\n font-size: 9px;\n}\n\n/* \u2500\u2500 Loading \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.loading-container {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 60px;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n text-align: center;\n}\n.empty-state i {\n font-size: 40px;\n margin-bottom: 12px;\n}\n.empty-state p {\n font-size: 14px;\n margin-bottom: 4px;\n}\n.empty-state span {\n font-size: 12px;\n}\n\n/* Scheduling App Link */\n.scheduling-app-link {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-top: 20px;\n padding-top: 16px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.btn-secondary {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.btn-secondary:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.link-hint {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n"] }]
665
+ args: [{ standalone: false, selector: 'app-scheduling-resource', template: "@if (!HideToolbar) {\n<mj-page-layout>\n <mj-page-header\n Title=\"Knowledge Pipelines\"\n Icon=\"fa-solid fa-calendar-check\"\n Subtitle=\"Scheduled knowledge ingestion, autotagging, and embedding pipelines\">\n <div meta>\n @if (ActiveCount > 0) {\n <mj-stat-badge [Count]=\"ActiveCount\" Label=\"active\" Variant=\"success\"></mj-stat-badge>\n }\n @if (PausedCount > 0) {\n <mj-stat-badge [Count]=\"PausedCount\" Label=\"paused\" Variant=\"warning\"></mj-stat-badge>\n }\n </div>\n <div actions>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"OnNewSchedule()\">\n <i class=\"fa-solid fa-plus\"></i> <span class=\"action-btn-label\">New Schedule</span>\n </button>\n </div>\n <div toolbar>\n <mj-page-search\n Placeholder=\"Search pipelines...\"\n [Value]=\"SearchQuery\"\n (ValueChange)=\"SearchQuery = $event; OnSearchChanged()\">\n </mj-page-search>\n <select class=\"mj-input kh-toolbar-select\" [(ngModel)]=\"StatusFilter\" (ngModelChange)=\"OnFilterChanged()\">\n <option value=\"\">All Statuses</option>\n <option value=\"Active\">Active</option>\n <option value=\"Paused\">Paused</option>\n <option value=\"Disabled\">Disabled</option>\n <option value=\"Pending\">Pending</option>\n </select>\n </div>\n </mj-page-header>\n\n <mj-page-body>\n <ng-container *ngTemplateOutlet=\"schedulingBody\"></ng-container>\n </mj-page-body>\n</mj-page-layout>\n}\n@if (HideToolbar) {\n <div class=\"embedded-controls\">\n <input\n type=\"text\"\n class=\"mj-input embedded-search\"\n placeholder=\"Search pipelines...\"\n [(ngModel)]=\"SearchQuery\"\n (ngModelChange)=\"OnSearchChanged()\" />\n <select class=\"mj-input kh-toolbar-select\" [(ngModel)]=\"StatusFilter\" (ngModelChange)=\"OnFilterChanged()\">\n <option value=\"\">All Statuses</option>\n <option value=\"Active\">Active</option>\n <option value=\"Paused\">Paused</option>\n <option value=\"Disabled\">Disabled</option>\n <option value=\"Pending\">Pending</option>\n </select>\n <span class=\"embedded-spacer\"></span>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"OnNewSchedule()\">\n <i class=\"fa-solid fa-plus\"></i> New Schedule\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"schedulingBody\"></ng-container>\n}\n\n<ng-template #schedulingBody>\n@if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading scheduled pipelines...\"></mj-loading>\n </div>\n} @else {\n <!-- Job Cards Grid -->\n @if (FilteredJobs.length > 0) {\n <div class=\"cards-grid\">\n @for (job of FilteredJobs; track job.ID) {\n <div class=\"job-card\"\n [class.paused]=\"job.Status === 'Paused'\"\n [class.disabled]=\"job.Status === 'Disabled'\"\n (click)=\"OnEditJob(job)\">\n <div class=\"card-top\">\n <span class=\"status-dot\"\n [class.dot-active]=\"job.Status === 'Active'\"\n [class.dot-paused]=\"job.Status === 'Paused'\"\n [class.dot-disabled]=\"job.Status === 'Disabled'\"></span>\n <div class=\"card-title-area\">\n <div class=\"card-name\">{{ job.Name }}</div>\n <div class=\"card-cron\">\n <i class=\"fa-regular fa-clock\"></i>\n {{ GetCronDescription(job.CronExpression) }}\n </div>\n </div>\n </div>\n <div class=\"sparkline\">\n @for (dotClass of GetSparkline(job.ID); track $index) {\n <span class=\"spark-dot\" [class]=\"dotClass\"></span>\n }\n <span class=\"sparkline-label\">last 7 runs</span>\n </div>\n <div class=\"card-stats\">\n <span class=\"stat\">\n <i class=\"fa-regular fa-clock\"></i>\n Last: <strong>{{ GetTimeAgo(job.LastRunAt) }}</strong>\n </span>\n <span class=\"stat\">\n <i class=\"fa-solid fa-chart-simple\"></i>\n <strong>{{ GetSuccessRate(job) }}</strong>\n </span>\n <span class=\"stat\">\n <i class=\"fa-regular fa-calendar\"></i>\n Next: <strong>{{ GetTimeUntil(job.NextRunAt) }}</strong>\n </span>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-regular fa-calendar-xmark\"></i>\n <p>No Knowledge Hub schedules found</p>\n <span>Create a new schedule to automate classification and vector sync</span>\n </div>\n }\n\n <!-- Link to full Scheduling App -->\n <div class=\"scheduling-app-link\">\n <button class=\"btn-secondary\" (click)=\"GoToSchedulingApp()\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open Scheduling App\n </button>\n <span class=\"link-hint\">Manage all scheduled jobs across the system</span>\n </div>\n\n <!-- Edit Dialog -->\n <mj-scheduled-job-dialog\n [Visible]=\"ShowEditDialog\"\n [ScheduledJobID]=\"EditingJobID\"\n (Close)=\"OnDialogClosed($event)\">\n </mj-scheduled-job-dialog>\n}\n</ng-template>\n", styles: ["/* \u2500\u2500 Host \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-width: 0;\n}\n\n/* Embedded mode: inline controls row instead of <mj-page-header>. */\n.embedded-controls {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.embedded-search {\n flex: 1;\n max-width: 320px;\n}\n\n.embedded-spacer {\n flex: 1;\n}\n\n/* Status select used in the [toolbar] slot. */\n.kh-toolbar-select {\n width: auto;\n min-width: 140px;\n min-height: 32px;\n padding: 4px 28px 4px 12px;\n font-size: 0.8125rem;\n}\n\n/* \u2500\u2500 Page Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.page-header {\n margin-bottom: 24px;\n}\n.page-header h1 {\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n.page-header p {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n/* \u2500\u2500 Toolbar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.toolbar {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n flex-wrap: wrap;\n}\n.btn-primary {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: var(--mj-radius-sm, 6px);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s;\n white-space: nowrap;\n}\n.btn-primary:hover {\n background: var(--mj-brand-primary-hover);\n}\n.filter-select {\n padding: 7px 32px 7px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm, 6px);\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%2394a3b8'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 10px center;\n cursor: pointer;\n}\n.search-input {\n padding: 7px 12px 7px 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm, 6px);\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n width: 220px;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' fill='%2394a3b8'%3E%3Cpath d='M10 6.5a3.5 3.5 0 11-7 0 3.5 3.5 0 017 0zm-.3 3.9a5.5 5.5 0 111.1-1.1l3.1 3.1a.75.75 0 01-1.1 1.1L9.7 10.4z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: 10px center;\n}\n.search-input::placeholder {\n color: var(--mj-text-muted);\n}\n.toolbar-spacer {\n flex: 1;\n}\n.toolbar-stat {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n.toolbar-stat strong {\n color: var(--mj-text-secondary);\n font-weight: 600;\n}\n\n/* \u2500\u2500 Card Grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.card-grid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 14px;\n margin-bottom: 32px;\n}\n@media (max-width: 1024px) {\n .card-grid { grid-template-columns: repeat(2, 1fr); }\n}\n@media (max-width: 640px) {\n .card-grid { grid-template-columns: 1fr; }\n}\n\n/* \u2500\u2500 Job Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.job-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n padding: 14px 16px;\n box-shadow: var(--mj-shadow-card, 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04));\n position: relative;\n cursor: pointer;\n transition: box-shadow 0.2s, border-color 0.2s;\n height: 132px;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n}\n.job-card:hover {\n box-shadow: var(--mj-shadow-card-hover, 0 4px 12px rgba(0,0,0,0.08), 0 2px 4px rgba(0,0,0,0.04));\n border-color: var(--mj-border-strong);\n}\n.job-card:hover .card-actions {\n opacity: 1;\n}\n.job-card.disabled-card {\n opacity: 0.65;\n}\n\n.card-top {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n.status-dot {\n width: 9px;\n height: 9px;\n border-radius: 50%;\n flex-shrink: 0;\n margin-top: 4px;\n}\n.status-dot.active {\n background: var(--mj-status-success);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 18%, transparent);\n}\n.status-dot.paused {\n background: var(--mj-status-warning);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-warning) 18%, transparent);\n}\n.status-dot.disabled,\n.status-dot.pending,\n.status-dot.expired {\n background: var(--mj-border-strong);\n}\n\n.card-title-area {\n flex: 1;\n min-width: 0;\n}\n.card-title {\n font-size: 13.5px;\n font-weight: 650;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: 1.3;\n}\n.card-cron {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 1px;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.card-cron i {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n/* Stats row */\n.card-stats {\n display: flex;\n align-items: center;\n gap: 16px;\n font-size: 11.5px;\n color: var(--mj-text-muted);\n}\n.card-stat {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.card-stat i {\n font-size: 10px;\n}\n.card-stat .value {\n color: var(--mj-text-secondary);\n font-weight: 600;\n}\n.success-rate {\n font-weight: 700;\n}\n.success-rate.high {\n color: var(--mj-status-success);\n}\n.success-rate.mid {\n color: var(--mj-status-warning);\n}\n\n/* Sparkline */\n.sparkline {\n display: flex;\n align-items: center;\n gap: 3px;\n margin-top: 8px;\n}\n.spark-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n}\n.spark-dot.ok {\n background: color-mix(in srgb, var(--mj-status-success) 65%, transparent);\n}\n.spark-dot.fail {\n background: color-mix(in srgb, var(--mj-status-error) 65%, transparent);\n}\n.spark-dot.skip {\n background: var(--mj-border-default);\n}\n.sparkline-label {\n font-size: 10px;\n color: var(--mj-text-muted);\n margin-left: 4px;\n}\n\n/* Hover actions */\n.card-actions {\n position: absolute;\n top: 10px;\n right: 10px;\n display: flex;\n gap: 6px;\n opacity: 0;\n transition: opacity 0.15s;\n}\n.card-action-btn {\n padding: 4px 10px;\n font-size: 11px;\n font-weight: 600;\n border-radius: 4px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.12s;\n box-shadow: 0 1px 2px rgba(0,0,0,0.06);\n}\n.card-action-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\n}\n.card-action-btn.run-now {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\n}\n.card-action-btn.run-now:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n}\n\n/* Paused/disabled status on card */\n.card-status-label {\n font-weight: 600;\n font-size: 11.5px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.card-status-label.paused {\n color: var(--mj-status-warning);\n}\n.card-status-label.disabled {\n color: var(--mj-text-muted);\n}\n\n/* \u2500\u2500 Section Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 14px;\n}\n.section-header h2 {\n font-size: 15px;\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n.section-header .badge {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n/* \u2500\u2500 Activity Table \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.activity-table {\n width: 100%;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n box-shadow: var(--mj-shadow-card, 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04));\n overflow: hidden;\n}\n.activity-table table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n.activity-table thead th {\n background: var(--mj-bg-surface-card);\n padding: 10px 14px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 11.5px;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n border-bottom: 1px solid var(--mj-border-default);\n}\n.activity-table tbody td {\n padding: 9px 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n}\n.activity-table tbody tr:last-child td {\n border-bottom: none;\n}\n.activity-table tbody tr:hover {\n background: var(--mj-bg-surface-hover);\n}\n.activity-table .job-name-cell {\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n.activity-table .time-cell {\n color: var(--mj-text-secondary);\n font-size: 12.5px;\n}\n.items-cell {\n text-align: right;\n font-weight: 600;\n}\n.items-cell.failed {\n color: var(--mj-status-error);\n}\n\n/* Status badges */\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 10px;\n border-radius: 10px;\n font-size: 11.5px;\n font-weight: 600;\n}\n.status-badge.success {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n.status-badge.failed {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n.status-badge.running {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info);\n}\n.status-badge i {\n font-size: 9px;\n}\n\n/* \u2500\u2500 Loading \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.loading-container {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 60px;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n text-align: center;\n}\n.empty-state i {\n font-size: 40px;\n margin-bottom: 12px;\n}\n.empty-state p {\n font-size: 14px;\n margin-bottom: 4px;\n}\n.empty-state span {\n font-size: 12px;\n}\n\n/* Scheduling App Link */\n.scheduling-app-link {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-top: 20px;\n padding-top: 16px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.btn-secondary {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.btn-secondary:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.link-hint {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n"] }]
665
666
  }], null, { HideToolbar: [{
666
667
  type: Input
667
668
  }] }); })();
@@ -1 +1 @@
1
- {"version":3,"file":"scheduling-resource.component.js","sourceRoot":"","sources":["../../../../src/KnowledgeHub/components/scheduling/scheduling-resource.component.ts","../../../../src/KnowledgeHub/components/scheduling/scheduling-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Knowledge Hub Scheduled Pipelines Dashboard Tab\n *\n * Full-page resource component for managing scheduled pipelines within the\n * Knowledge Hub application. Displays job cards in a compact grid, recent\n * activity table, and provides create/edit via the reusable\n * ScheduledJobDialogComponent from @memberjunction/ng-scheduling.\n *\n * Registered as BaseResourceComponent for the Knowledge Hub application.\n */\n\nimport { Component, Input, ChangeDetectorRef, OnDestroy, AfterViewInit, inject } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { ResourceData, MJScheduledJobEntity, MJScheduledJobRunEntity } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { ScheduledJobService, ScheduledJobDialogResult } from '@memberjunction/ng-scheduling';\n\n/** Simple cron-to-English mapping for common patterns */\ninterface CronParts {\n Second: string;\n Minute: string;\n Hour: string;\n DayOfMonth: string;\n Month: string;\n DayOfWeek: string;\n}\n\n@RegisterClass(BaseResourceComponent, 'SchedulingResource')\n@Component({\n standalone: false,\n selector: 'app-scheduling-resource',\n templateUrl: './scheduling-resource.component.html',\n styleUrls: ['./scheduling-resource.component.css'],\n})\nexport class SchedulingResourceComponent extends BaseResourceComponent implements AfterViewInit, OnDestroy {\n /**\n * When true, renders only the body content (no <mj-page-layout> + <mj-page-header>\n * chrome). Used when embedded inside another resource page (e.g. KH Configuration's\n * Scheduling section) so we don't get nested page-layouts that trap click events.\n *\n * Named `HideToolbar` for cross-section consistency with Scheduling/Testing inner\n * components — see plans/explorer-chrome-conventions.md Section 5. The name is\n * narrower than its actual behavior (suppresses entire chrome, not just the toolbar)\n * but matches the documented convention.\n */\n @Input() HideToolbar = false;\n\n private cdr = inject(ChangeDetectorRef);\n protected override navigationService = inject(NavigationService);\n private scheduledJobService = inject(ScheduledJobService);\n protected override destroy$ = new Subject<void>();\n\n // ================================================================\n // Resource overrides\n // ================================================================\n\n async GetResourceDisplayName(_data: ResourceData): Promise<string> {\n return 'Schedules';\n }\n\n async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-clock';\n }\n\n // ================================================================\n // State\n // ================================================================\n\n public IsLoading = true;\n public AllJobs: MJScheduledJobEntity[] = [];\n public FilteredJobs: MJScheduledJobEntity[] = [];\n public RecentRuns: MJScheduledJobRunEntity[] = [];\n public StatusFilter = '';\n public SearchQuery = '';\n\n /** Map of jobID -> last 7 run statuses for sparkline display */\n private sparklineCache = new Map<string, string[]>();\n\n // Edit dialog\n public ShowEditDialog = false;\n public EditingJobID: string | null = null;\n\n // ================================================================\n // Computed\n // ================================================================\n\n public get ActiveCount(): number {\n return this.AllJobs.filter(j => j.Status === 'Active').length;\n }\n\n public get PausedCount(): number {\n return this.AllJobs.filter(j => j.Status === 'Paused').length;\n }\n\n public get DisabledCount(): number {\n return this.AllJobs.filter(j => j.Status === 'Disabled').length;\n }\n\n // ================================================================\n // Lifecycle\n // ================================================================\n\n async ngAfterViewInit(): Promise<void> {\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void {\n super.ngOnDestroy();\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ================================================================\n // Public Methods — Toolbar\n // ================================================================\n\n public OnNewSchedule(): void {\n this.EditingJobID = null;\n this.ShowEditDialog = true;\n this.cdr.detectChanges();\n }\n\n public OnFilterChanged(): void {\n this.applyFilters();\n this.cdr.detectChanges();\n }\n\n public OnSearchChanged(): void {\n this.applyFilters();\n this.cdr.detectChanges();\n }\n\n // ================================================================\n // Public Methods — Card Actions\n // ================================================================\n\n public OnEditJob(job: MJScheduledJobEntity): void {\n this.EditingJobID = job.ID;\n this.ShowEditDialog = true;\n this.cdr.detectChanges();\n }\n\n public async OnRunNow(job: MJScheduledJobEntity): Promise<void> {\n MJNotificationService.Instance.CreateSimpleNotification(\n `Triggering \"${job.Name}\" — this feature requires server-side support.`,\n 'info', 4000\n );\n }\n\n // ================================================================\n // Public Methods — Dialog\n // ================================================================\n\n public async OnDialogClosed(result: ScheduledJobDialogResult): Promise<void> {\n this.ShowEditDialog = false;\n this.EditingJobID = null;\n\n if (result.Saved || result.Deleted) {\n await this.loadData();\n }\n\n this.cdr.detectChanges();\n }\n\n /** Navigate to the full Scheduling application */\n public GoToSchedulingApp(): void {\n const md = this.ProviderToUse;\n const schedulingApp = md.Applications.find(a => a.Name === 'Scheduling');\n if (schedulingApp) {\n this.navigationService.SwitchToApp(schedulingApp.ID);\n } else {\n MJNotificationService.Instance.CreateSimpleNotification(\n 'Scheduling app not found. Check application configuration.',\n 'warning', 3000\n );\n }\n }\n\n // ================================================================\n // Public Methods — Card Display Helpers\n // ================================================================\n\n public GetStatusDotClass(job: MJScheduledJobEntity): string {\n return (job.Status ?? 'pending').toLowerCase();\n }\n\n public GetCronDescription(cron: string): string {\n if (!cron) return 'No schedule';\n const parts = this.parseCron(cron);\n if (!parts) return cron;\n return this.cronToHuman(parts);\n }\n\n public GetSparkline(jobID: string): string[] {\n return this.sparklineCache.get(jobID) ?? [];\n }\n\n public GetTimeAgo(date: Date | null): string {\n if (!date) return 'Never';\n const now = new Date();\n const d = new Date(date);\n const diffMs = now.getTime() - d.getTime();\n return this.formatDuration(diffMs);\n }\n\n public GetTimeUntil(date: Date | null): string {\n if (!date) return '--';\n const now = new Date();\n const d = new Date(date);\n const diffMs = d.getTime() - now.getTime();\n if (diffMs <= 0) return 'Due';\n return this.formatDuration(diffMs);\n }\n\n public GetSuccessRate(job: MJScheduledJobEntity): string {\n if (job.RunCount === 0) return 'N/A';\n return Math.round((job.SuccessCount / job.RunCount) * 100) + '%';\n }\n\n public GetSuccessRateClass(job: MJScheduledJobEntity): string {\n if (job.RunCount === 0) return '';\n const rate = job.SuccessCount / job.RunCount;\n if (rate >= 0.95) return 'high';\n if (rate >= 0.80) return 'mid';\n return '';\n }\n\n public GetDuration(run: MJScheduledJobRunEntity): string {\n if (!run.StartedAt || !run.CompletedAt) return '--';\n const start = new Date(run.StartedAt).getTime();\n const end = new Date(run.CompletedAt).getTime();\n const diffMs = end - start;\n return this.formatDurationShort(diffMs);\n }\n\n public GetItemsProcessed(run: MJScheduledJobRunEntity): string {\n if (!run.Details) return '--';\n try {\n const details = JSON.parse(run.Details) as Record<string, unknown>;\n if (details['ItemsProcessed'] != null) {\n const total = details['TotalItems'] as number | undefined;\n const processed = details['ItemsProcessed'] as number;\n if (run.Status === 'Failed' && total != null) {\n return `${this.formatNumber(processed)} / ${this.formatNumber(total)}`;\n }\n return this.formatNumber(processed);\n }\n } catch {\n // details not parseable\n }\n return '--';\n }\n\n // ================================================================\n // Private Methods\n // ================================================================\n\n private async loadData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.detectChanges();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const [jobsResult, runsResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Scheduled Jobs',\n ExtraFilter: `Name LIKE '%Autotag%' OR Name LIKE '%Vector%' OR Name LIKE '%Content%' OR Name LIKE '%Knowledge%' OR Name LIKE '%Tag%'`,\n OrderBy: 'Name',\n ResultType: 'entity_object',\n },\n {\n EntityName: 'MJ: Scheduled Job Runs',\n ExtraFilter: '',\n OrderBy: 'StartedAt DESC',\n MaxRows: 100,\n ResultType: 'entity_object',\n },\n ]);\n\n if (jobsResult.Success) {\n this.AllJobs = jobsResult.Results as MJScheduledJobEntity[];\n } else {\n this.AllJobs = [];\n }\n\n const allRuns = runsResult.Success\n ? (runsResult.Results as MJScheduledJobRunEntity[])\n : [];\n\n this.RecentRuns = allRuns.slice(0, 10);\n this.buildSparklineCache(allRuns);\n this.applyFilters();\n } catch (error) {\n console.error('[SchedulingResource] Error loading data:', error);\n this.AllJobs = [];\n this.FilteredJobs = [];\n this.RecentRuns = [];\n } finally {\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n private applyFilters(): void {\n let jobs = this.AllJobs;\n\n if (this.StatusFilter) {\n jobs = jobs.filter(j => j.Status === this.StatusFilter);\n }\n\n if (this.SearchQuery.trim()) {\n const query = this.SearchQuery.trim().toLowerCase();\n jobs = jobs.filter(j =>\n j.Name.toLowerCase().includes(query) ||\n (j.Description ?? '').toLowerCase().includes(query)\n );\n }\n\n this.FilteredJobs = jobs;\n }\n\n /**\n * Build sparkline data for each job from the last 7 runs.\n * Each dot is 'ok', 'fail', or 'skip'.\n */\n private buildSparklineCache(allRuns: MJScheduledJobRunEntity[]): void {\n this.sparklineCache.clear();\n\n // Group runs by job ID\n const runsByJob = new Map<string, MJScheduledJobRunEntity[]>();\n for (const run of allRuns) {\n const jobID = run.ScheduledJobID;\n if (!runsByJob.has(jobID)) {\n runsByJob.set(jobID, []);\n }\n runsByJob.get(jobID)!.push(run);\n }\n\n // Build sparkline for each job (up to 7 most recent runs)\n for (const job of this.AllJobs) {\n const runs = runsByJob.get(job.ID) ?? [];\n const last7 = runs.slice(0, 7);\n const dots: string[] = last7.map(r => this.runStatusToDot(r));\n\n // Pad to 7 with 'skip' dots if fewer runs\n while (dots.length < 7) {\n dots.push('skip');\n }\n\n this.sparklineCache.set(job.ID, dots);\n }\n }\n\n private runStatusToDot(run: MJScheduledJobRunEntity): string {\n if (run.Status === 'Completed' && run.Success) return 'ok';\n if (run.Status === 'Failed' || (run.Status === 'Completed' && !run.Success)) return 'fail';\n if (run.Status === 'Running') return 'ok'; // treat in-progress as OK\n return 'skip';\n }\n\n // ================================================================\n // Cron Parsing\n // ================================================================\n\n private parseCron(cron: string): CronParts | null {\n const parts = cron.trim().split(/\\s+/);\n // Support 5-part (no seconds) and 6-part (with seconds) cron\n if (parts.length === 5) {\n return {\n Second: '0',\n Minute: parts[0],\n Hour: parts[1],\n DayOfMonth: parts[2],\n Month: parts[3],\n DayOfWeek: parts[4],\n };\n }\n if (parts.length === 6) {\n return {\n Second: parts[0],\n Minute: parts[1],\n Hour: parts[2],\n DayOfMonth: parts[3],\n Month: parts[4],\n DayOfWeek: parts[5],\n };\n }\n return null;\n }\n\n private cronToHuman(p: CronParts): string {\n // Every N minutes: */N * * * *\n if (p.Minute.startsWith('*/') && p.Hour === '*' && p.DayOfMonth === '*' && p.Month === '*' && p.DayOfWeek === '*') {\n const interval = parseInt(p.Minute.slice(2), 10);\n if (interval === 1) return 'Every minute';\n return `Every ${interval} minutes`;\n }\n\n // Every N hours: 0 */N * * *\n if (p.Minute !== '*' && !p.Minute.includes('/') && p.Hour.startsWith('*/') && p.DayOfMonth === '*') {\n const interval = parseInt(p.Hour.slice(2), 10);\n if (interval === 1) return 'Every hour';\n return `Every ${interval} hours`;\n }\n\n // Specific hour with specific or wildcard day fields\n if (!p.Minute.includes('*') && !p.Minute.includes('/') &&\n !p.Hour.includes('*') && !p.Hour.includes('/') &&\n p.Month === '*') {\n\n const hour = parseInt(p.Hour, 10);\n const minute = parseInt(p.Minute, 10);\n const timeStr = this.formatTime(hour, minute);\n\n // Weekly: specific day of week\n if (p.DayOfWeek !== '*' && p.DayOfMonth === '*') {\n const dayName = this.dayOfWeekName(p.DayOfWeek);\n return `Weekly on ${dayName} at ${timeStr}`;\n }\n\n // Monthly: specific day of month\n if (p.DayOfMonth !== '*' && p.DayOfWeek === '*') {\n return `Monthly on day ${p.DayOfMonth} at ${timeStr}`;\n }\n\n // Daily\n if (p.DayOfMonth === '*' && p.DayOfWeek === '*') {\n return `Daily at ${timeStr}`;\n }\n }\n\n // Fallback: return the raw cron expression\n return `${p.Minute} ${p.Hour} ${p.DayOfMonth} ${p.Month} ${p.DayOfWeek}`;\n }\n\n private formatTime(hour: number, minute: number): string {\n const ampm = hour >= 12 ? 'PM' : 'AM';\n const h = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;\n const m = minute.toString().padStart(2, '0');\n return `${h}:${m} ${ampm}`;\n }\n\n private dayOfWeekName(dow: string): string {\n const names: Record<string, string> = {\n '0': 'Sunday', '1': 'Monday', '2': 'Tuesday',\n '3': 'Wednesday', '4': 'Thursday', '5': 'Friday',\n '6': 'Saturday', '7': 'Sunday',\n 'SUN': 'Sunday', 'MON': 'Monday', 'TUE': 'Tuesday',\n 'WED': 'Wednesday', 'THU': 'Thursday', 'FRI': 'Friday',\n 'SAT': 'Saturday',\n };\n return names[dow.toUpperCase()] ?? dow;\n }\n\n // ================================================================\n // Formatting Helpers\n // ================================================================\n\n private formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d ago`;\n if (hours > 0) return `${hours}h ago`;\n if (minutes > 0) return `${minutes}m ago`;\n return 'Just now';\n }\n\n private formatDurationShort(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n\n if (minutes >= 60) {\n const hours = Math.floor(minutes / 60);\n const remainMinutes = minutes % 60;\n return `${hours}h ${remainMinutes}m`;\n }\n return `${minutes}m ${seconds.toString().padStart(2, '0')}s`;\n }\n\n private formatNumber(n: number): string {\n return n.toLocaleString();\n }\n}\n\n/** Tree-shaking prevention */\nexport function LoadSchedulingResource(): void {\n // Prevents tree-shaking of the component\n}\n","@if (!HideToolbar) {\n<mj-page-layout>\n <mj-page-header\n Title=\"Knowledge Pipelines\"\n Icon=\"fa-solid fa-calendar-check\"\n Subtitle=\"Scheduled knowledge ingestion, autotagging, and embedding pipelines\">\n <div meta>\n @if (ActiveCount > 0) {\n <mj-stat-badge [Count]=\"ActiveCount\" Label=\"active\" Variant=\"success\"></mj-stat-badge>\n }\n @if (PausedCount > 0) {\n <mj-stat-badge [Count]=\"PausedCount\" Label=\"paused\" Variant=\"warning\"></mj-stat-badge>\n }\n </div>\n <div actions>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"OnNewSchedule()\">\n <i class=\"fa-solid fa-plus\"></i> New Schedule\n </button>\n </div>\n <div toolbar>\n <mj-page-search\n Placeholder=\"Search pipelines...\"\n [Value]=\"SearchQuery\"\n (ValueChange)=\"SearchQuery = $event; OnSearchChanged()\">\n </mj-page-search>\n <select class=\"mj-input kh-toolbar-select\" [(ngModel)]=\"StatusFilter\" (ngModelChange)=\"OnFilterChanged()\">\n <option value=\"\">All Statuses</option>\n <option value=\"Active\">Active</option>\n <option value=\"Paused\">Paused</option>\n <option value=\"Disabled\">Disabled</option>\n <option value=\"Pending\">Pending</option>\n </select>\n </div>\n </mj-page-header>\n\n <mj-page-body>\n <ng-container *ngTemplateOutlet=\"schedulingBody\"></ng-container>\n </mj-page-body>\n</mj-page-layout>\n}\n@if (HideToolbar) {\n <div class=\"embedded-controls\">\n <input\n type=\"text\"\n class=\"mj-input embedded-search\"\n placeholder=\"Search pipelines...\"\n [(ngModel)]=\"SearchQuery\"\n (ngModelChange)=\"OnSearchChanged()\" />\n <select class=\"mj-input kh-toolbar-select\" [(ngModel)]=\"StatusFilter\" (ngModelChange)=\"OnFilterChanged()\">\n <option value=\"\">All Statuses</option>\n <option value=\"Active\">Active</option>\n <option value=\"Paused\">Paused</option>\n <option value=\"Disabled\">Disabled</option>\n <option value=\"Pending\">Pending</option>\n </select>\n <span class=\"embedded-spacer\"></span>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"OnNewSchedule()\">\n <i class=\"fa-solid fa-plus\"></i> New Schedule\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"schedulingBody\"></ng-container>\n}\n\n<ng-template #schedulingBody>\n@if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading scheduled pipelines...\"></mj-loading>\n </div>\n} @else {\n <!-- Job Cards Grid -->\n @if (FilteredJobs.length > 0) {\n <div class=\"cards-grid\">\n @for (job of FilteredJobs; track job.ID) {\n <div class=\"job-card\"\n [class.paused]=\"job.Status === 'Paused'\"\n [class.disabled]=\"job.Status === 'Disabled'\"\n (click)=\"OnEditJob(job)\">\n <div class=\"card-top\">\n <span class=\"status-dot\"\n [class.dot-active]=\"job.Status === 'Active'\"\n [class.dot-paused]=\"job.Status === 'Paused'\"\n [class.dot-disabled]=\"job.Status === 'Disabled'\"></span>\n <div class=\"card-title-area\">\n <div class=\"card-name\">{{ job.Name }}</div>\n <div class=\"card-cron\">\n <i class=\"fa-regular fa-clock\"></i>\n {{ GetCronDescription(job.CronExpression) }}\n </div>\n </div>\n </div>\n <div class=\"sparkline\">\n @for (dotClass of GetSparkline(job.ID); track $index) {\n <span class=\"spark-dot\" [class]=\"dotClass\"></span>\n }\n <span class=\"sparkline-label\">last 7 runs</span>\n </div>\n <div class=\"card-stats\">\n <span class=\"stat\">\n <i class=\"fa-regular fa-clock\"></i>\n Last: <strong>{{ GetTimeAgo(job.LastRunAt) }}</strong>\n </span>\n <span class=\"stat\">\n <i class=\"fa-solid fa-chart-simple\"></i>\n <strong>{{ GetSuccessRate(job) }}</strong>\n </span>\n <span class=\"stat\">\n <i class=\"fa-regular fa-calendar\"></i>\n Next: <strong>{{ GetTimeUntil(job.NextRunAt) }}</strong>\n </span>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-regular fa-calendar-xmark\"></i>\n <p>No Knowledge Hub schedules found</p>\n <span>Create a new schedule to automate classification and vector sync</span>\n </div>\n }\n\n <!-- Link to full Scheduling App -->\n <div class=\"scheduling-app-link\">\n <button class=\"btn-secondary\" (click)=\"GoToSchedulingApp()\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open Scheduling App\n </button>\n <span class=\"link-hint\">Manage all scheduled jobs across the system</span>\n </div>\n\n <!-- Edit Dialog -->\n <mj-scheduled-job-dialog\n [Visible]=\"ShowEditDialog\"\n [ScheduledJobID]=\"EditingJobID\"\n (Close)=\"OnDialogClosed($event)\">\n </mj-scheduled-job-dialog>\n}\n</ng-template>\n"]}
1
+ {"version":3,"file":"scheduling-resource.component.js","sourceRoot":"","sources":["../../../../src/KnowledgeHub/components/scheduling/scheduling-resource.component.ts","../../../../src/KnowledgeHub/components/scheduling/scheduling-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Knowledge Hub Scheduled Pipelines Dashboard Tab\n *\n * Full-page resource component for managing scheduled pipelines within the\n * Knowledge Hub application. Displays job cards in a compact grid, recent\n * activity table, and provides create/edit via the reusable\n * ScheduledJobDialogComponent from @memberjunction/ng-scheduling.\n *\n * Registered as BaseResourceComponent for the Knowledge Hub application.\n */\n\nimport { Component, Input, ChangeDetectorRef, OnDestroy, AfterViewInit, inject } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { ResourceData, MJScheduledJobEntity, MJScheduledJobRunEntity } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { ScheduledJobService, ScheduledJobDialogResult } from '@memberjunction/ng-scheduling';\n\n/** Simple cron-to-English mapping for common patterns */\ninterface CronParts {\n Second: string;\n Minute: string;\n Hour: string;\n DayOfMonth: string;\n Month: string;\n DayOfWeek: string;\n}\n\n@RegisterClass(BaseResourceComponent, 'SchedulingResource')\n@Component({\n standalone: false,\n selector: 'app-scheduling-resource',\n templateUrl: './scheduling-resource.component.html',\n styleUrls: ['./scheduling-resource.component.css'],\n})\nexport class SchedulingResourceComponent extends BaseResourceComponent implements AfterViewInit, OnDestroy {\n /**\n * When true, renders only the body content (no <mj-page-layout> + <mj-page-header>\n * chrome). Used when embedded inside another resource page (e.g. KH Configuration's\n * Scheduling section) so we don't get nested page-layouts that trap click events.\n *\n * Named `HideToolbar` for cross-section consistency with Scheduling/Testing inner\n * components — see plans/explorer-chrome-conventions.md Section 5. The name is\n * narrower than its actual behavior (suppresses entire chrome, not just the toolbar)\n * but matches the documented convention.\n */\n @Input() HideToolbar = false;\n\n private cdr = inject(ChangeDetectorRef);\n protected override navigationService = inject(NavigationService);\n private scheduledJobService = inject(ScheduledJobService);\n protected override destroy$ = new Subject<void>();\n\n // ================================================================\n // Resource overrides\n // ================================================================\n\n async GetResourceDisplayName(_data: ResourceData): Promise<string> {\n return 'Schedules';\n }\n\n async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-clock';\n }\n\n // ================================================================\n // State\n // ================================================================\n\n public IsLoading = true;\n public AllJobs: MJScheduledJobEntity[] = [];\n public FilteredJobs: MJScheduledJobEntity[] = [];\n public RecentRuns: MJScheduledJobRunEntity[] = [];\n public StatusFilter = '';\n public SearchQuery = '';\n\n /** Map of jobID -> last 7 run statuses for sparkline display */\n private sparklineCache = new Map<string, string[]>();\n\n // Edit dialog\n public ShowEditDialog = false;\n public EditingJobID: string | null = null;\n\n // ================================================================\n // Computed\n // ================================================================\n\n public get ActiveCount(): number {\n return this.AllJobs.filter(j => j.Status === 'Active').length;\n }\n\n public get PausedCount(): number {\n return this.AllJobs.filter(j => j.Status === 'Paused').length;\n }\n\n public get DisabledCount(): number {\n return this.AllJobs.filter(j => j.Status === 'Disabled').length;\n }\n\n // ================================================================\n // Lifecycle\n // ================================================================\n\n async ngAfterViewInit(): Promise<void> {\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void {\n super.ngOnDestroy();\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ================================================================\n // Public Methods — Toolbar\n // ================================================================\n\n public OnNewSchedule(): void {\n this.EditingJobID = null;\n this.ShowEditDialog = true;\n this.cdr.detectChanges();\n }\n\n public OnFilterChanged(): void {\n this.applyFilters();\n this.cdr.detectChanges();\n }\n\n public OnSearchChanged(): void {\n this.applyFilters();\n this.cdr.detectChanges();\n }\n\n // ================================================================\n // Public Methods — Card Actions\n // ================================================================\n\n public OnEditJob(job: MJScheduledJobEntity): void {\n this.EditingJobID = job.ID;\n this.ShowEditDialog = true;\n this.cdr.detectChanges();\n }\n\n public async OnRunNow(job: MJScheduledJobEntity): Promise<void> {\n MJNotificationService.Instance.CreateSimpleNotification(\n `Triggering \"${job.Name}\" — this feature requires server-side support.`,\n 'info', 4000\n );\n }\n\n // ================================================================\n // Public Methods — Dialog\n // ================================================================\n\n public async OnDialogClosed(result: ScheduledJobDialogResult): Promise<void> {\n this.ShowEditDialog = false;\n this.EditingJobID = null;\n\n if (result.Saved || result.Deleted) {\n await this.loadData();\n }\n\n this.cdr.detectChanges();\n }\n\n /** Navigate to the full Scheduling application */\n public GoToSchedulingApp(): void {\n const md = this.ProviderToUse;\n const schedulingApp = md.Applications.find(a => a.Name === 'Scheduling');\n if (schedulingApp) {\n this.navigationService.SwitchToApp(schedulingApp.ID);\n } else {\n MJNotificationService.Instance.CreateSimpleNotification(\n 'Scheduling app not found. Check application configuration.',\n 'warning', 3000\n );\n }\n }\n\n // ================================================================\n // Public Methods — Card Display Helpers\n // ================================================================\n\n public GetStatusDotClass(job: MJScheduledJobEntity): string {\n return (job.Status ?? 'pending').toLowerCase();\n }\n\n public GetCronDescription(cron: string): string {\n if (!cron) return 'No schedule';\n const parts = this.parseCron(cron);\n if (!parts) return cron;\n return this.cronToHuman(parts);\n }\n\n public GetSparkline(jobID: string): string[] {\n return this.sparklineCache.get(jobID) ?? [];\n }\n\n public GetTimeAgo(date: Date | null): string {\n if (!date) return 'Never';\n const now = new Date();\n const d = new Date(date);\n const diffMs = now.getTime() - d.getTime();\n return this.formatDuration(diffMs);\n }\n\n public GetTimeUntil(date: Date | null): string {\n if (!date) return '--';\n const now = new Date();\n const d = new Date(date);\n const diffMs = d.getTime() - now.getTime();\n if (diffMs <= 0) return 'Due';\n return this.formatDuration(diffMs);\n }\n\n public GetSuccessRate(job: MJScheduledJobEntity): string {\n if (job.RunCount === 0) return 'N/A';\n return Math.round((job.SuccessCount / job.RunCount) * 100) + '%';\n }\n\n public GetSuccessRateClass(job: MJScheduledJobEntity): string {\n if (job.RunCount === 0) return '';\n const rate = job.SuccessCount / job.RunCount;\n if (rate >= 0.95) return 'high';\n if (rate >= 0.80) return 'mid';\n return '';\n }\n\n public GetDuration(run: MJScheduledJobRunEntity): string {\n if (!run.StartedAt || !run.CompletedAt) return '--';\n const start = new Date(run.StartedAt).getTime();\n const end = new Date(run.CompletedAt).getTime();\n const diffMs = end - start;\n return this.formatDurationShort(diffMs);\n }\n\n public GetItemsProcessed(run: MJScheduledJobRunEntity): string {\n if (!run.Details) return '--';\n try {\n const details = JSON.parse(run.Details) as Record<string, unknown>;\n if (details['ItemsProcessed'] != null) {\n const total = details['TotalItems'] as number | undefined;\n const processed = details['ItemsProcessed'] as number;\n if (run.Status === 'Failed' && total != null) {\n return `${this.formatNumber(processed)} / ${this.formatNumber(total)}`;\n }\n return this.formatNumber(processed);\n }\n } catch {\n // details not parseable\n }\n return '--';\n }\n\n // ================================================================\n // Private Methods\n // ================================================================\n\n private async loadData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.detectChanges();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const [jobsResult, runsResult] = await rv.RunViews([\n {\n EntityName: 'MJ: Scheduled Jobs',\n ExtraFilter: `Name LIKE '%Autotag%' OR Name LIKE '%Vector%' OR Name LIKE '%Content%' OR Name LIKE '%Knowledge%' OR Name LIKE '%Tag%'`,\n OrderBy: 'Name',\n ResultType: 'entity_object',\n },\n {\n EntityName: 'MJ: Scheduled Job Runs',\n ExtraFilter: '',\n OrderBy: 'StartedAt DESC',\n MaxRows: 100,\n ResultType: 'entity_object',\n },\n ]);\n\n if (jobsResult.Success) {\n this.AllJobs = jobsResult.Results as MJScheduledJobEntity[];\n } else {\n this.AllJobs = [];\n }\n\n const allRuns = runsResult.Success\n ? (runsResult.Results as MJScheduledJobRunEntity[])\n : [];\n\n this.RecentRuns = allRuns.slice(0, 10);\n this.buildSparklineCache(allRuns);\n this.applyFilters();\n } catch (error) {\n console.error('[SchedulingResource] Error loading data:', error);\n this.AllJobs = [];\n this.FilteredJobs = [];\n this.RecentRuns = [];\n } finally {\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n private applyFilters(): void {\n let jobs = this.AllJobs;\n\n if (this.StatusFilter) {\n jobs = jobs.filter(j => j.Status === this.StatusFilter);\n }\n\n if (this.SearchQuery.trim()) {\n const query = this.SearchQuery.trim().toLowerCase();\n jobs = jobs.filter(j =>\n j.Name.toLowerCase().includes(query) ||\n (j.Description ?? '').toLowerCase().includes(query)\n );\n }\n\n this.FilteredJobs = jobs;\n }\n\n /**\n * Build sparkline data for each job from the last 7 runs.\n * Each dot is 'ok', 'fail', or 'skip'.\n */\n private buildSparklineCache(allRuns: MJScheduledJobRunEntity[]): void {\n this.sparklineCache.clear();\n\n // Group runs by job ID\n const runsByJob = new Map<string, MJScheduledJobRunEntity[]>();\n for (const run of allRuns) {\n const jobID = run.ScheduledJobID;\n if (!runsByJob.has(jobID)) {\n runsByJob.set(jobID, []);\n }\n runsByJob.get(jobID)!.push(run);\n }\n\n // Build sparkline for each job (up to 7 most recent runs)\n for (const job of this.AllJobs) {\n const runs = runsByJob.get(job.ID) ?? [];\n const last7 = runs.slice(0, 7);\n const dots: string[] = last7.map(r => this.runStatusToDot(r));\n\n // Pad to 7 with 'skip' dots if fewer runs\n while (dots.length < 7) {\n dots.push('skip');\n }\n\n this.sparklineCache.set(job.ID, dots);\n }\n }\n\n private runStatusToDot(run: MJScheduledJobRunEntity): string {\n if (run.Status === 'Completed' && run.Success) return 'ok';\n if (run.Status === 'Failed' || (run.Status === 'Completed' && !run.Success)) return 'fail';\n if (run.Status === 'Running') return 'ok'; // treat in-progress as OK\n return 'skip';\n }\n\n // ================================================================\n // Cron Parsing\n // ================================================================\n\n private parseCron(cron: string): CronParts | null {\n const parts = cron.trim().split(/\\s+/);\n // Support 5-part (no seconds) and 6-part (with seconds) cron\n if (parts.length === 5) {\n return {\n Second: '0',\n Minute: parts[0],\n Hour: parts[1],\n DayOfMonth: parts[2],\n Month: parts[3],\n DayOfWeek: parts[4],\n };\n }\n if (parts.length === 6) {\n return {\n Second: parts[0],\n Minute: parts[1],\n Hour: parts[2],\n DayOfMonth: parts[3],\n Month: parts[4],\n DayOfWeek: parts[5],\n };\n }\n return null;\n }\n\n private cronToHuman(p: CronParts): string {\n // Every N minutes: */N * * * *\n if (p.Minute.startsWith('*/') && p.Hour === '*' && p.DayOfMonth === '*' && p.Month === '*' && p.DayOfWeek === '*') {\n const interval = parseInt(p.Minute.slice(2), 10);\n if (interval === 1) return 'Every minute';\n return `Every ${interval} minutes`;\n }\n\n // Every N hours: 0 */N * * *\n if (p.Minute !== '*' && !p.Minute.includes('/') && p.Hour.startsWith('*/') && p.DayOfMonth === '*') {\n const interval = parseInt(p.Hour.slice(2), 10);\n if (interval === 1) return 'Every hour';\n return `Every ${interval} hours`;\n }\n\n // Specific hour with specific or wildcard day fields\n if (!p.Minute.includes('*') && !p.Minute.includes('/') &&\n !p.Hour.includes('*') && !p.Hour.includes('/') &&\n p.Month === '*') {\n\n const hour = parseInt(p.Hour, 10);\n const minute = parseInt(p.Minute, 10);\n const timeStr = this.formatTime(hour, minute);\n\n // Weekly: specific day of week\n if (p.DayOfWeek !== '*' && p.DayOfMonth === '*') {\n const dayName = this.dayOfWeekName(p.DayOfWeek);\n return `Weekly on ${dayName} at ${timeStr}`;\n }\n\n // Monthly: specific day of month\n if (p.DayOfMonth !== '*' && p.DayOfWeek === '*') {\n return `Monthly on day ${p.DayOfMonth} at ${timeStr}`;\n }\n\n // Daily\n if (p.DayOfMonth === '*' && p.DayOfWeek === '*') {\n return `Daily at ${timeStr}`;\n }\n }\n\n // Fallback: return the raw cron expression\n return `${p.Minute} ${p.Hour} ${p.DayOfMonth} ${p.Month} ${p.DayOfWeek}`;\n }\n\n private formatTime(hour: number, minute: number): string {\n const ampm = hour >= 12 ? 'PM' : 'AM';\n const h = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;\n const m = minute.toString().padStart(2, '0');\n return `${h}:${m} ${ampm}`;\n }\n\n private dayOfWeekName(dow: string): string {\n const names: Record<string, string> = {\n '0': 'Sunday', '1': 'Monday', '2': 'Tuesday',\n '3': 'Wednesday', '4': 'Thursday', '5': 'Friday',\n '6': 'Saturday', '7': 'Sunday',\n 'SUN': 'Sunday', 'MON': 'Monday', 'TUE': 'Tuesday',\n 'WED': 'Wednesday', 'THU': 'Thursday', 'FRI': 'Friday',\n 'SAT': 'Saturday',\n };\n return names[dow.toUpperCase()] ?? dow;\n }\n\n // ================================================================\n // Formatting Helpers\n // ================================================================\n\n private formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d ago`;\n if (hours > 0) return `${hours}h ago`;\n if (minutes > 0) return `${minutes}m ago`;\n return 'Just now';\n }\n\n private formatDurationShort(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n\n if (minutes >= 60) {\n const hours = Math.floor(minutes / 60);\n const remainMinutes = minutes % 60;\n return `${hours}h ${remainMinutes}m`;\n }\n return `${minutes}m ${seconds.toString().padStart(2, '0')}s`;\n }\n\n private formatNumber(n: number): string {\n return n.toLocaleString();\n }\n}\n\n/** Tree-shaking prevention */\nexport function LoadSchedulingResource(): void {\n // Prevents tree-shaking of the component\n}\n","@if (!HideToolbar) {\n<mj-page-layout>\n <mj-page-header\n Title=\"Knowledge Pipelines\"\n Icon=\"fa-solid fa-calendar-check\"\n Subtitle=\"Scheduled knowledge ingestion, autotagging, and embedding pipelines\">\n <div meta>\n @if (ActiveCount > 0) {\n <mj-stat-badge [Count]=\"ActiveCount\" Label=\"active\" Variant=\"success\"></mj-stat-badge>\n }\n @if (PausedCount > 0) {\n <mj-stat-badge [Count]=\"PausedCount\" Label=\"paused\" Variant=\"warning\"></mj-stat-badge>\n }\n </div>\n <div actions>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"OnNewSchedule()\">\n <i class=\"fa-solid fa-plus\"></i> <span class=\"action-btn-label\">New Schedule</span>\n </button>\n </div>\n <div toolbar>\n <mj-page-search\n Placeholder=\"Search pipelines...\"\n [Value]=\"SearchQuery\"\n (ValueChange)=\"SearchQuery = $event; OnSearchChanged()\">\n </mj-page-search>\n <select class=\"mj-input kh-toolbar-select\" [(ngModel)]=\"StatusFilter\" (ngModelChange)=\"OnFilterChanged()\">\n <option value=\"\">All Statuses</option>\n <option value=\"Active\">Active</option>\n <option value=\"Paused\">Paused</option>\n <option value=\"Disabled\">Disabled</option>\n <option value=\"Pending\">Pending</option>\n </select>\n </div>\n </mj-page-header>\n\n <mj-page-body>\n <ng-container *ngTemplateOutlet=\"schedulingBody\"></ng-container>\n </mj-page-body>\n</mj-page-layout>\n}\n@if (HideToolbar) {\n <div class=\"embedded-controls\">\n <input\n type=\"text\"\n class=\"mj-input embedded-search\"\n placeholder=\"Search pipelines...\"\n [(ngModel)]=\"SearchQuery\"\n (ngModelChange)=\"OnSearchChanged()\" />\n <select class=\"mj-input kh-toolbar-select\" [(ngModel)]=\"StatusFilter\" (ngModelChange)=\"OnFilterChanged()\">\n <option value=\"\">All Statuses</option>\n <option value=\"Active\">Active</option>\n <option value=\"Paused\">Paused</option>\n <option value=\"Disabled\">Disabled</option>\n <option value=\"Pending\">Pending</option>\n </select>\n <span class=\"embedded-spacer\"></span>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"OnNewSchedule()\">\n <i class=\"fa-solid fa-plus\"></i> New Schedule\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"schedulingBody\"></ng-container>\n}\n\n<ng-template #schedulingBody>\n@if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading scheduled pipelines...\"></mj-loading>\n </div>\n} @else {\n <!-- Job Cards Grid -->\n @if (FilteredJobs.length > 0) {\n <div class=\"cards-grid\">\n @for (job of FilteredJobs; track job.ID) {\n <div class=\"job-card\"\n [class.paused]=\"job.Status === 'Paused'\"\n [class.disabled]=\"job.Status === 'Disabled'\"\n (click)=\"OnEditJob(job)\">\n <div class=\"card-top\">\n <span class=\"status-dot\"\n [class.dot-active]=\"job.Status === 'Active'\"\n [class.dot-paused]=\"job.Status === 'Paused'\"\n [class.dot-disabled]=\"job.Status === 'Disabled'\"></span>\n <div class=\"card-title-area\">\n <div class=\"card-name\">{{ job.Name }}</div>\n <div class=\"card-cron\">\n <i class=\"fa-regular fa-clock\"></i>\n {{ GetCronDescription(job.CronExpression) }}\n </div>\n </div>\n </div>\n <div class=\"sparkline\">\n @for (dotClass of GetSparkline(job.ID); track $index) {\n <span class=\"spark-dot\" [class]=\"dotClass\"></span>\n }\n <span class=\"sparkline-label\">last 7 runs</span>\n </div>\n <div class=\"card-stats\">\n <span class=\"stat\">\n <i class=\"fa-regular fa-clock\"></i>\n Last: <strong>{{ GetTimeAgo(job.LastRunAt) }}</strong>\n </span>\n <span class=\"stat\">\n <i class=\"fa-solid fa-chart-simple\"></i>\n <strong>{{ GetSuccessRate(job) }}</strong>\n </span>\n <span class=\"stat\">\n <i class=\"fa-regular fa-calendar\"></i>\n Next: <strong>{{ GetTimeUntil(job.NextRunAt) }}</strong>\n </span>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-regular fa-calendar-xmark\"></i>\n <p>No Knowledge Hub schedules found</p>\n <span>Create a new schedule to automate classification and vector sync</span>\n </div>\n }\n\n <!-- Link to full Scheduling App -->\n <div class=\"scheduling-app-link\">\n <button class=\"btn-secondary\" (click)=\"GoToSchedulingApp()\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open Scheduling App\n </button>\n <span class=\"link-hint\">Manage all scheduled jobs across the system</span>\n </div>\n\n <!-- Edit Dialog -->\n <mj-scheduled-job-dialog\n [Visible]=\"ShowEditDialog\"\n [ScheduledJobID]=\"EditingJobID\"\n (Close)=\"OnDialogClosed($event)\">\n </mj-scheduled-job-dialog>\n}\n</ng-template>\n"]}