@memberjunction/ng-core-entity-forms 6.1.4 → 6.2.0-edge.1

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 (327) hide show
  1. package/README.md +22 -0
  2. package/dist/lib/custom/AIAgentCategories/ai-agent-category-overview.panel.d.ts +1 -1
  3. package/dist/lib/custom/AIAgentCategories/ai-agent-category-overview.panel.js +2 -2
  4. package/dist/lib/custom/AIAgentCategories/ai-agent-category-overview.panel.js.map +1 -1
  5. package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js.map +1 -1
  6. package/dist/lib/custom/AIAgents/add-action-dialog.component.d.ts +90 -16
  7. package/dist/lib/custom/AIAgents/add-action-dialog.component.d.ts.map +1 -1
  8. package/dist/lib/custom/AIAgents/add-action-dialog.component.js +218 -70
  9. package/dist/lib/custom/AIAgents/add-action-dialog.component.js.map +1 -1
  10. package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.d.ts +80 -16
  11. package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.d.ts.map +1 -1
  12. package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js +146 -46
  13. package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js.map +1 -1
  14. package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts +329 -27
  15. package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
  16. package/dist/lib/custom/AIAgents/ai-agent-form.component.js +794 -262
  17. package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
  18. package/dist/lib/custom/AIAgents/ai-agent-management.service.d.ts +76 -0
  19. package/dist/lib/custom/AIAgents/ai-agent-management.service.d.ts.map +1 -1
  20. package/dist/lib/custom/AIAgents/ai-agent-management.service.js +77 -33
  21. package/dist/lib/custom/AIAgents/ai-agent-management.service.js.map +1 -1
  22. package/dist/lib/custom/AIAgents/create-prompt-dialog.component.d.ts +69 -15
  23. package/dist/lib/custom/AIAgents/create-prompt-dialog.component.d.ts.map +1 -1
  24. package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js +182 -74
  25. package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js.map +1 -1
  26. package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.d.ts +105 -25
  27. package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.d.ts.map +1 -1
  28. package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js +272 -112
  29. package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js.map +1 -1
  30. package/dist/lib/custom/AIAgents/new-agent-dialog.component.d.ts +32 -6
  31. package/dist/lib/custom/AIAgents/new-agent-dialog.component.d.ts.map +1 -1
  32. package/dist/lib/custom/AIAgents/new-agent-dialog.component.js +71 -19
  33. package/dist/lib/custom/AIAgents/new-agent-dialog.component.js.map +1 -1
  34. package/dist/lib/custom/AIAgents/new-agent-dialog.service.d.ts +10 -0
  35. package/dist/lib/custom/AIAgents/new-agent-dialog.service.d.ts.map +1 -1
  36. package/dist/lib/custom/AIAgents/new-agent-dialog.service.js +27 -7
  37. package/dist/lib/custom/AIAgents/new-agent-dialog.service.js.map +1 -1
  38. package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.d.ts +65 -15
  39. package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.d.ts.map +1 -1
  40. package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js +152 -52
  41. package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js.map +1 -1
  42. package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.d.ts +81 -15
  43. package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.d.ts.map +1 -1
  44. package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js +145 -45
  45. package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js.map +1 -1
  46. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.d.ts +71 -17
  47. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.d.ts.map +1 -1
  48. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js +175 -67
  49. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js.map +1 -1
  50. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts +173 -27
  51. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
  52. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +385 -93
  53. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
  54. package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.d.ts +64 -4
  55. package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.d.ts.map +1 -1
  56. package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.js +129 -29
  57. package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.js.map +1 -1
  58. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts +260 -27
  59. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts.map +1 -1
  60. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +686 -238
  61. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
  62. package/dist/lib/custom/AIPrompts/ai-prompt-management.service.d.ts +10 -0
  63. package/dist/lib/custom/AIPrompts/ai-prompt-management.service.d.ts.map +1 -1
  64. package/dist/lib/custom/AIPrompts/ai-prompt-management.service.js +17 -9
  65. package/dist/lib/custom/AIPrompts/ai-prompt-management.service.js.map +1 -1
  66. package/dist/lib/custom/AIPrompts/template-selector-dialog.component.d.ts +74 -16
  67. package/dist/lib/custom/AIPrompts/template-selector-dialog.component.d.ts.map +1 -1
  68. package/dist/lib/custom/AIPrompts/template-selector-dialog.component.js +174 -58
  69. package/dist/lib/custom/AIPrompts/template-selector-dialog.component.js.map +1 -1
  70. package/dist/lib/custom/Actions/action-execution-log-form.component.d.ts +108 -14
  71. package/dist/lib/custom/Actions/action-execution-log-form.component.d.ts.map +1 -1
  72. package/dist/lib/custom/Actions/action-execution-log-form.component.js +258 -70
  73. package/dist/lib/custom/Actions/action-execution-log-form.component.js.map +1 -1
  74. package/dist/lib/custom/Actions/action-form.component.d.ts +198 -14
  75. package/dist/lib/custom/Actions/action-form.component.d.ts.map +1 -1
  76. package/dist/lib/custom/Actions/action-form.component.js +387 -107
  77. package/dist/lib/custom/Actions/action-form.component.js.map +1 -1
  78. package/dist/lib/custom/BridgeProviders/bridge-provider-features.d.ts +12 -6
  79. package/dist/lib/custom/BridgeProviders/bridge-provider-features.d.ts.map +1 -1
  80. package/dist/lib/custom/BridgeProviders/bridge-provider-features.js +41 -29
  81. package/dist/lib/custom/BridgeProviders/bridge-provider-features.js.map +1 -1
  82. package/dist/lib/custom/BridgeProviders/bridge-provider-form.component.js +14 -14
  83. package/dist/lib/custom/BridgeProviders/bridge-provider-form.component.js.map +1 -1
  84. package/dist/lib/custom/Companies/company-overview.panel.d.ts +1 -1
  85. package/dist/lib/custom/Companies/company-overview.panel.js +2 -2
  86. package/dist/lib/custom/Companies/company-overview.panel.js.map +1 -1
  87. package/dist/lib/custom/Conversations/conversation-overview.panel.d.ts +1 -1
  88. package/dist/lib/custom/Conversations/conversation-overview.panel.js +2 -2
  89. package/dist/lib/custom/Conversations/conversation-overview.panel.js.map +1 -1
  90. package/dist/lib/custom/Employees/employee-overview.panel.d.ts +1 -1
  91. package/dist/lib/custom/Employees/employee-overview.panel.js +2 -2
  92. package/dist/lib/custom/Employees/employee-overview.panel.js.map +1 -1
  93. package/dist/lib/custom/Entities/entity-form.component.d.ts +209 -28
  94. package/dist/lib/custom/Entities/entity-form.component.d.ts.map +1 -1
  95. package/dist/lib/custom/Entities/entity-form.component.js +494 -138
  96. package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
  97. package/dist/lib/custom/EntityActions/entityaction.form.component.d.ts +5 -1
  98. package/dist/lib/custom/EntityActions/entityaction.form.component.d.ts.map +1 -1
  99. package/dist/lib/custom/EntityActions/entityaction.form.component.js +10 -2
  100. package/dist/lib/custom/EntityActions/entityaction.form.component.js.map +1 -1
  101. package/dist/lib/custom/Files/file-form.component.d.ts +1 -1
  102. package/dist/lib/custom/Files/file-form.component.js +2 -2
  103. package/dist/lib/custom/Files/file-form.component.js.map +1 -1
  104. package/dist/lib/custom/Lists/list-form.component.d.ts +300 -36
  105. package/dist/lib/custom/Lists/list-form.component.d.ts.map +1 -1
  106. package/dist/lib/custom/Lists/list-form.component.js +664 -208
  107. package/dist/lib/custom/Lists/list-form.component.js.map +1 -1
  108. package/dist/lib/custom/MLModels/ml-model-form.component.d.ts +27 -0
  109. package/dist/lib/custom/MLModels/ml-model-form.component.d.ts.map +1 -0
  110. package/dist/lib/custom/MLModels/ml-model-form.component.js +193 -0
  111. package/dist/lib/custom/MLModels/ml-model-form.component.js.map +1 -0
  112. package/dist/lib/custom/MLModels/ml-model-view-models.d.ts +75 -0
  113. package/dist/lib/custom/MLModels/ml-model-view-models.d.ts.map +1 -0
  114. package/dist/lib/custom/MLModels/ml-model-view-models.js +244 -0
  115. package/dist/lib/custom/MLModels/ml-model-view-models.js.map +1 -0
  116. package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts +173 -0
  117. package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts.map +1 -0
  118. package/dist/lib/custom/MLModels/ps-model-detail.component.js +883 -0
  119. package/dist/lib/custom/MLModels/ps-model-detail.component.js.map +1 -0
  120. package/dist/lib/custom/Queries/query-form.component.d.ts +201 -26
  121. package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
  122. package/dist/lib/custom/Queries/query-form.component.js +429 -109
  123. package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
  124. package/dist/lib/custom/Queries/query-run-dialog.component.d.ts +107 -14
  125. package/dist/lib/custom/Queries/query-run-dialog.component.d.ts.map +1 -1
  126. package/dist/lib/custom/Queries/query-run-dialog.component.js +249 -79
  127. package/dist/lib/custom/Queries/query-run-dialog.component.js.map +1 -1
  128. package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts +133 -7
  129. package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts.map +1 -1
  130. package/dist/lib/custom/RecordProcesses/record-process-form.component.js +1268 -19
  131. package/dist/lib/custom/RecordProcesses/record-process-form.component.js.map +1 -1
  132. package/dist/lib/custom/SearchScopes/searchscope-form.component.d.ts +1 -1
  133. package/dist/lib/custom/SearchScopes/searchscope-form.component.js +4 -4
  134. package/dist/lib/custom/SearchScopes/searchscope-form.component.js.map +1 -1
  135. package/dist/lib/custom/SessionBridges/session-bridge-form.component.js.map +1 -1
  136. package/dist/lib/custom/Templates/template-param-dialog.component.d.ts +77 -13
  137. package/dist/lib/custom/Templates/template-param-dialog.component.d.ts.map +1 -1
  138. package/dist/lib/custom/Templates/template-param-dialog.component.js +196 -78
  139. package/dist/lib/custom/Templates/template-param-dialog.component.js.map +1 -1
  140. package/dist/lib/custom/Templates/template-params-grid.component.d.ts +49 -7
  141. package/dist/lib/custom/Templates/template-params-grid.component.d.ts.map +1 -1
  142. package/dist/lib/custom/Templates/template-params-grid.component.js +132 -44
  143. package/dist/lib/custom/Templates/template-params-grid.component.js.map +1 -1
  144. package/dist/lib/custom/Templates/templates-form.component.d.ts +142 -17
  145. package/dist/lib/custom/Templates/templates-form.component.d.ts.map +1 -1
  146. package/dist/lib/custom/Templates/templates-form.component.js +333 -113
  147. package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
  148. package/dist/lib/custom/Tests/entity-link-pill.component.d.ts +24 -4
  149. package/dist/lib/custom/Tests/entity-link-pill.component.d.ts.map +1 -1
  150. package/dist/lib/custom/Tests/entity-link-pill.component.js +64 -20
  151. package/dist/lib/custom/Tests/entity-link-pill.component.js.map +1 -1
  152. package/dist/lib/custom/Tests/test-form.component.d.ts +217 -27
  153. package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
  154. package/dist/lib/custom/Tests/test-form.component.js +549 -169
  155. package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
  156. package/dist/lib/custom/Tests/test-run-checks.d.ts +2 -0
  157. package/dist/lib/custom/Tests/test-run-checks.d.ts.map +1 -1
  158. package/dist/lib/custom/Tests/test-run-checks.js +5 -1
  159. package/dist/lib/custom/Tests/test-run-checks.js.map +1 -1
  160. package/dist/lib/custom/Tests/test-run-feedback-form.component.d.ts +2 -0
  161. package/dist/lib/custom/Tests/test-run-feedback-form.component.d.ts.map +1 -1
  162. package/dist/lib/custom/Tests/test-run-feedback-form.component.js +5 -1
  163. package/dist/lib/custom/Tests/test-run-feedback-form.component.js.map +1 -1
  164. package/dist/lib/custom/Tests/test-run-form.component.d.ts +146 -18
  165. package/dist/lib/custom/Tests/test-run-form.component.d.ts.map +1 -1
  166. package/dist/lib/custom/Tests/test-run-form.component.js +362 -106
  167. package/dist/lib/custom/Tests/test-run-form.component.js.map +1 -1
  168. package/dist/lib/custom/Tests/test-suite-form.component.d.ts +390 -47
  169. package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
  170. package/dist/lib/custom/Tests/test-suite-form.component.js +1015 -343
  171. package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
  172. package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts +214 -26
  173. package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts.map +1 -1
  174. package/dist/lib/custom/Tests/test-suite-run-form.component.js +535 -159
  175. package/dist/lib/custom/Tests/test-suite-run-form.component.js.map +1 -1
  176. package/dist/lib/custom/Users/user-overview.panel.d.ts +1 -1
  177. package/dist/lib/custom/Users/user-overview.panel.js +2 -2
  178. package/dist/lib/custom/Users/user-overview.panel.js.map +1 -1
  179. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts +208 -29
  180. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts.map +1 -1
  181. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +446 -138
  182. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -1
  183. package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.d.ts +6 -0
  184. package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.d.ts.map +1 -1
  185. package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.js +16 -4
  186. package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.js.map +1 -1
  187. package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.d.ts +50 -6
  188. package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.d.ts.map +1 -1
  189. package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js +84 -12
  190. package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js.map +1 -1
  191. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.d.ts +89 -5
  192. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.d.ts.map +1 -1
  193. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js +216 -70
  194. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js.map +1 -1
  195. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.d.ts +62 -3
  196. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.d.ts.map +1 -1
  197. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.js +140 -42
  198. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.js.map +1 -1
  199. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts +81 -10
  200. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts.map +1 -1
  201. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js +165 -37
  202. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js.map +1 -1
  203. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts +121 -14
  204. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
  205. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +287 -79
  206. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
  207. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.d.ts +101 -15
  208. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.d.ts.map +1 -1
  209. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.js +281 -97
  210. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.js.map +1 -1
  211. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.d.ts +43 -25
  212. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.d.ts.map +1 -1
  213. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.js +100 -64
  214. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.js.map +1 -1
  215. package/dist/lib/custom/ai-agent-run/flow/constellation.component.d.ts +14 -2
  216. package/dist/lib/custom/ai-agent-run/flow/constellation.component.d.ts.map +1 -1
  217. package/dist/lib/custom/ai-agent-run/flow/constellation.component.js +71 -53
  218. package/dist/lib/custom/ai-agent-run/flow/constellation.component.js.map +1 -1
  219. package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.d.ts +14 -2
  220. package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.d.ts.map +1 -1
  221. package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.js +70 -52
  222. package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.js.map +1 -1
  223. package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.d.ts +8 -0
  224. package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.d.ts.map +1 -1
  225. package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.js +22 -6
  226. package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.js.map +1 -1
  227. package/dist/lib/custom/ai-agent-run/flow/flowchart.component.d.ts +24 -2
  228. package/dist/lib/custom/ai-agent-run/flow/flowchart.component.d.ts.map +1 -1
  229. package/dist/lib/custom/ai-agent-run/flow/flowchart.component.js +91 -59
  230. package/dist/lib/custom/ai-agent-run/flow/flowchart.component.js.map +1 -1
  231. package/dist/lib/custom/ai-agent-run/flow/pan-zoom.d.ts +10 -2
  232. package/dist/lib/custom/ai-agent-run/flow/pan-zoom.d.ts.map +1 -1
  233. package/dist/lib/custom/ai-agent-run/flow/pan-zoom.js +33 -17
  234. package/dist/lib/custom/ai-agent-run/flow/pan-zoom.js.map +1 -1
  235. package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.d.ts +2 -0
  236. package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.d.ts.map +1 -1
  237. package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.js +34 -30
  238. package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.js.map +1 -1
  239. package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.d.ts +14 -2
  240. package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.d.ts.map +1 -1
  241. package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.js +69 -51
  242. package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.js.map +1 -1
  243. package/dist/lib/custom/custom-forms.module.d.ts +32 -30
  244. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
  245. package/dist/lib/custom/custom-forms.module.js +21 -4
  246. package/dist/lib/custom/custom-forms.module.js.map +1 -1
  247. package/dist/lib/custom/shared/entity-selector-dialog.component.d.ts +38 -12
  248. package/dist/lib/custom/shared/entity-selector-dialog.component.d.ts.map +1 -1
  249. package/dist/lib/custom/shared/entity-selector-dialog.component.js +103 -51
  250. package/dist/lib/custom/shared/entity-selector-dialog.component.js.map +1 -1
  251. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.d.ts.map +1 -1
  252. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js +62 -26
  253. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js.map +1 -1
  254. package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.d.ts.map +1 -1
  255. package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js +59 -51
  256. package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js.map +1 -1
  257. package/dist/lib/generated/Entities/MJAIVendor/mjaivendor.form.component.js +76 -74
  258. package/dist/lib/generated/Entities/MJAIVendor/mjaivendor.form.component.js.map +1 -1
  259. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.d.ts.map +1 -1
  260. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js +33 -15
  261. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js.map +1 -1
  262. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
  263. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +100 -82
  264. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
  265. package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js +24 -20
  266. package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js.map +1 -1
  267. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.d.ts +10 -0
  268. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.d.ts.map +1 -0
  269. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js +122 -0
  270. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js.map +1 -0
  271. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.d.ts +10 -0
  272. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.d.ts.map +1 -0
  273. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.js +125 -0
  274. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.js.map +1 -0
  275. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.d.ts.map +1 -1
  276. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js +23 -5
  277. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js.map +1 -1
  278. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.d.ts.map +1 -1
  279. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.js +25 -6
  280. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.js.map +1 -1
  281. package/dist/lib/generated/Entities/MJProject/mjproject.form.component.js +27 -25
  282. package/dist/lib/generated/Entities/MJProject/mjproject.form.component.js.map +1 -1
  283. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.d.ts.map +1 -1
  284. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js +11 -15
  285. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js.map +1 -1
  286. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.d.ts.map +1 -1
  287. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js +43 -7
  288. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js.map +1 -1
  289. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.d.ts.map +1 -1
  290. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +155 -119
  291. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
  292. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.d.ts +10 -0
  293. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.d.ts.map +1 -0
  294. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.js +78 -0
  295. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.js.map +1 -0
  296. package/dist/lib/generated/generated-forms.module.d.ts +240 -237
  297. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  298. package/dist/lib/generated/generated-forms.module.js +11 -2
  299. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  300. package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.d.ts +5 -1
  301. package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.d.ts.map +1 -1
  302. package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.js +11 -3
  303. package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.js.map +1 -1
  304. package/dist/lib/panels/content-sources/tag-pipeline-configuration.panel.d.ts +2 -0
  305. package/dist/lib/panels/content-sources/tag-pipeline-configuration.panel.d.ts.map +1 -1
  306. package/dist/lib/panels/content-sources/tag-pipeline-configuration.panel.js +16 -12
  307. package/dist/lib/panels/content-sources/tag-pipeline-configuration.panel.js.map +1 -1
  308. package/dist/lib/panels/content-sources/website-crawler-settings.panel.d.ts +1 -1
  309. package/dist/lib/panels/content-sources/website-crawler-settings.panel.js +2 -2
  310. package/dist/lib/panels/content-sources/website-crawler-settings.panel.js.map +1 -1
  311. package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts +122 -1
  312. package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts.map +1 -1
  313. package/dist/lib/panels/model-predictions/model-prediction.logic.js +236 -11
  314. package/dist/lib/panels/model-predictions/model-prediction.logic.js.map +1 -1
  315. package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts +72 -13
  316. package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts.map +1 -1
  317. package/dist/lib/panels/model-predictions/model-prediction.panel.js +577 -78
  318. package/dist/lib/panels/model-predictions/model-prediction.panel.js.map +1 -1
  319. package/dist/lib/shared/components/template-editor.component.d.ts +133 -14
  320. package/dist/lib/shared/components/template-editor.component.d.ts.map +1 -1
  321. package/dist/lib/shared/components/template-editor.component.js +322 -124
  322. package/dist/lib/shared/components/template-editor.component.js.map +1 -1
  323. package/dist/public-api.d.ts +4 -0
  324. package/dist/public-api.d.ts.map +1 -1
  325. package/dist/public-api.js +4 -0
  326. package/dist/public-api.js.map +1 -1
  327. package/package.json +43 -41
@@ -4,32 +4,56 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Component } from '@angular/core';
7
+ import { ChangeDetectorRef, Component, inject } from '@angular/core';
8
8
  import { RegisterClassEx } from '@memberjunction/global';
9
9
  import { BaseFormPanel } from '@memberjunction/ng-base-forms';
10
- import { LogError, Metadata, RunView } from '@memberjunction/core';
11
- import { bandFor, formatLastScored, formatValue, gaugePct, parseDrivers, resolveLabel, toNumber, valueKind, } from './model-prediction.logic';
10
+ import { CompositeKey, LogError, Metadata, RunView } from '@memberjunction/core';
11
+ import { resolveOutcomeConfig, resolveOutcomeStyle, resolveScoreBand, } from '@memberjunction/predictive-studio-core';
12
+ import { BandFor, FilterHistoryByModel, FormatLastScored, FormatValue, GaugePct, GetDistinctModelsFromHistory, ParseDrivers, ParseHistoryItem, ResolveLabel, ToNumber, ValueKind, } from './model-prediction.logic';
12
13
  import * as i0 from "@angular/core";
13
14
  import * as i1 from "@memberjunction/ng-base-forms";
14
- const _forTrack0 = ($index, $item) => $item.bindingId;
15
+ import * as i2 from "@angular/common";
16
+ const _forTrack0 = ($index, $item) => $item.BindingId;
15
17
  const _forTrack1 = ($index, $item) => $item.name;
16
- function ModelPredictionPanel_Conditional_0_For_3_Conditional_8_Template(rf, ctx) { if (rf & 1) {
17
- i0.ɵɵelementStart(0, "span", 11);
18
+ const _forTrack2 = ($index, $item) => $item.id;
19
+ const _forTrack3 = ($index, $item) => $item.modelId;
20
+ function ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
21
+ i0.ɵɵelementStart(0, "span", 21);
18
22
  i0.ɵɵtext(1, "\u00B7");
19
23
  i0.ɵɵelementEnd();
20
- i0.ɵɵelementStart(2, "span", 12);
24
+ i0.ɵɵelementStart(2, "span", 22);
21
25
  i0.ɵɵtext(3);
22
26
  i0.ɵɵelementEnd();
23
27
  } if (rf & 2) {
24
- const card_r1 = i0.ɵɵnextContext().$implicit;
28
+ const card_r3 = i0.ɵɵnextContext().$implicit;
25
29
  i0.ɵɵadvance(3);
26
- i0.ɵɵtextInterpolate1("Scored ", card_r1.lastScored);
30
+ i0.ɵɵtextInterpolate1("Scored ", card_r3.LastScored);
27
31
  } }
28
- function ModelPredictionPanel_Conditional_0_For_3_Conditional_12_Template(rf, ctx) { if (rf & 1) {
29
- i0.ɵɵelementStart(0, "div", 9)(1, "div", 13);
30
- i0.ɵɵelement(2, "div", 14);
32
+ function ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_16_Conditional_1_Template(rf, ctx) { if (rf & 1) {
33
+ i0.ɵɵelement(0, "i");
34
+ } if (rf & 2) {
35
+ const card_r3 = i0.ɵɵnextContext(2).$implicit;
36
+ i0.ɵɵclassMap("fa-solid " + card_r3.BadgeIcon);
37
+ } }
38
+ function ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_16_Template(rf, ctx) { if (rf & 1) {
39
+ i0.ɵɵelementStart(0, "span", 23);
40
+ i0.ɵɵconditionalCreate(1, ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_16_Conditional_1_Template, 1, 2, "i", 24);
41
+ i0.ɵɵelementStart(2, "span");
42
+ i0.ɵɵtext(3);
43
+ i0.ɵɵelementEnd()();
44
+ } if (rf & 2) {
45
+ const card_r3 = i0.ɵɵnextContext().$implicit;
46
+ i0.ɵɵclassMap("mpp-badge-" + card_r3.BadgeColor);
47
+ i0.ɵɵadvance();
48
+ i0.ɵɵconditional(card_r3.BadgeIcon ? 1 : -1);
49
+ i0.ɵɵadvance(2);
50
+ i0.ɵɵtextInterpolate(card_r3.StatusLabel);
51
+ } }
52
+ function ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_17_Template(rf, ctx) { if (rf & 1) {
53
+ i0.ɵɵelementStart(0, "div", 19)(1, "div", 25);
54
+ i0.ɵɵelement(2, "div", 26);
31
55
  i0.ɵɵelementEnd();
32
- i0.ɵɵelementStart(3, "div", 15)(4, "span");
56
+ i0.ɵɵelementStart(3, "div", 27)(4, "span");
33
57
  i0.ɵɵtext(5, "0%");
34
58
  i0.ɵɵelementEnd();
35
59
  i0.ɵɵelementStart(6, "span");
@@ -39,83 +63,357 @@ function ModelPredictionPanel_Conditional_0_For_3_Conditional_12_Template(rf, ct
39
63
  i0.ɵɵtext(9, "100%");
40
64
  i0.ɵɵelementEnd()()();
41
65
  } if (rf & 2) {
42
- const card_r1 = i0.ɵɵnextContext().$implicit;
43
- i0.ɵɵattribute("aria-label", card_r1.label + " " + card_r1.displayValue + ", " + card_r1.band + " band");
66
+ const card_r3 = i0.ɵɵnextContext().$implicit;
67
+ i0.ɵɵattribute("aria-label", card_r3.Label + " " + card_r3.DisplayValue + (card_r3.StatusLabel ? ", " + card_r3.StatusLabel : ""));
44
68
  i0.ɵɵadvance(2);
45
- i0.ɵɵstyleProp("width", card_r1.gaugePct, "%");
46
- i0.ɵɵclassProp("mpp-band-low", card_r1.band === "low")("mpp-band-mid", card_r1.band === "mid")("mpp-band-high", card_r1.band === "high");
69
+ i0.ɵɵclassMap("mpp-color-" + card_r3.BadgeColor);
70
+ i0.ɵɵstyleProp("width", card_r3.GaugePct, "%");
71
+ i0.ɵɵclassProp("mpp-band-low", card_r3.Band === "low")("mpp-band-mid", card_r3.Band === "mid")("mpp-band-high", card_r3.Band === "high");
47
72
  } }
48
- function ModelPredictionPanel_Conditional_0_For_3_Conditional_13_For_5_Template(rf, ctx) { if (rf & 1) {
49
- i0.ɵɵelementStart(0, "div", 18)(1, "span", 19);
73
+ function ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_18_For_5_Template(rf, ctx) { if (rf & 1) {
74
+ i0.ɵɵelementStart(0, "div", 30)(1, "span", 31);
50
75
  i0.ɵɵtext(2);
51
76
  i0.ɵɵelementEnd();
52
- i0.ɵɵelementStart(3, "span", 20);
53
- i0.ɵɵelement(4, "span", 21);
77
+ i0.ɵɵelementStart(3, "span", 32);
78
+ i0.ɵɵelement(4, "span", 33);
54
79
  i0.ɵɵelementEnd()();
55
80
  } if (rf & 2) {
56
- const driver_r2 = ctx.$implicit;
81
+ const driver_r5 = ctx.$implicit;
57
82
  i0.ɵɵadvance();
58
- i0.ɵɵproperty("title", driver_r2.name);
83
+ i0.ɵɵproperty("title", driver_r5.name);
59
84
  i0.ɵɵadvance();
60
- i0.ɵɵtextInterpolate(driver_r2.name);
85
+ i0.ɵɵtextInterpolate(driver_r5.name);
61
86
  i0.ɵɵadvance(2);
62
- i0.ɵɵstyleProp("width", driver_r2.relativePct, "%");
87
+ i0.ɵɵstyleProp("width", driver_r5.RelativePct, "%");
63
88
  } }
64
- function ModelPredictionPanel_Conditional_0_For_3_Conditional_13_Template(rf, ctx) { if (rf & 1) {
65
- i0.ɵɵelementStart(0, "div", 10)(1, "div", 16);
66
- i0.ɵɵelement(2, "i", 17);
89
+ function ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_18_Template(rf, ctx) { if (rf & 1) {
90
+ i0.ɵɵelementStart(0, "div", 20)(1, "div", 28);
91
+ i0.ɵɵelement(2, "i", 29);
67
92
  i0.ɵɵtext(3, " Top drivers ");
68
93
  i0.ɵɵelementEnd();
69
- i0.ɵɵrepeaterCreate(4, ModelPredictionPanel_Conditional_0_For_3_Conditional_13_For_5_Template, 5, 4, "div", 18, _forTrack1);
94
+ i0.ɵɵrepeaterCreate(4, ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_18_For_5_Template, 5, 4, "div", 30, _forTrack1);
70
95
  i0.ɵɵelementEnd();
71
96
  } if (rf & 2) {
72
- const card_r1 = i0.ɵɵnextContext().$implicit;
97
+ const card_r3 = i0.ɵɵnextContext().$implicit;
73
98
  i0.ɵɵadvance(4);
74
- i0.ɵɵrepeater(card_r1.drivers);
99
+ i0.ɵɵrepeater(card_r3.Drivers);
100
+ } }
101
+ function ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
102
+ const _r2 = i0.ɵɵgetCurrentView();
103
+ i0.ɵɵelementStart(0, "div", 9)(1, "div", 10)(2, "div", 11)(3, "div", 12);
104
+ i0.ɵɵtext(4);
105
+ i0.ɵɵelementEnd();
106
+ i0.ɵɵelementStart(5, "div", 13);
107
+ i0.ɵɵelement(6, "i", 14);
108
+ i0.ɵɵelementStart(7, "span");
109
+ i0.ɵɵtext(8);
110
+ i0.ɵɵelementEnd();
111
+ i0.ɵɵconditionalCreate(9, ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_9_Template, 4, 1);
112
+ i0.ɵɵelementEnd()();
113
+ i0.ɵɵelementStart(10, "button", 15);
114
+ i0.ɵɵlistener("click", function ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Template_button_click_10_listener($event) { const card_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r3.OpenHistoryForModel(card_r3.modelId, $event)); });
115
+ i0.ɵɵelement(11, "i", 5);
116
+ i0.ɵɵtext(12, " History ");
117
+ i0.ɵɵelementEnd()();
118
+ i0.ɵɵelementStart(13, "div", 16)(14, "span", 17);
119
+ i0.ɵɵtext(15);
120
+ i0.ɵɵelementEnd();
121
+ i0.ɵɵconditionalCreate(16, ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_16_Template, 4, 4, "span", 18);
122
+ i0.ɵɵelementEnd();
123
+ i0.ɵɵconditionalCreate(17, ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_17_Template, 10, 11, "div", 19);
124
+ i0.ɵɵconditionalCreate(18, ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Conditional_18_Template, 6, 0, "div", 20);
125
+ i0.ɵɵelementEnd();
126
+ } if (rf & 2) {
127
+ const card_r3 = ctx.$implicit;
128
+ i0.ɵɵadvance(4);
129
+ i0.ɵɵtextInterpolate(card_r3.Label);
130
+ i0.ɵɵadvance(4);
131
+ i0.ɵɵtextInterpolate(card_r3.Provenance);
132
+ i0.ɵɵadvance();
133
+ i0.ɵɵconditional(card_r3.LastScored ? 9 : -1);
134
+ i0.ɵɵadvance(5);
135
+ i0.ɵɵclassProp("mpp-value-muted", card_r3.DisplayValue === "\u2014");
136
+ i0.ɵɵadvance();
137
+ i0.ɵɵtextInterpolate1(" ", card_r3.DisplayValue, " ");
138
+ i0.ɵɵadvance();
139
+ i0.ɵɵconditional(card_r3.StatusLabel ? 16 : -1);
140
+ i0.ɵɵadvance();
141
+ i0.ɵɵconditional(card_r3.IsProbability ? 17 : -1);
142
+ i0.ɵɵadvance();
143
+ i0.ɵɵconditional(card_r3.Drivers.length > 0 ? 18 : -1);
144
+ } }
145
+ function ModelPredictionPanel_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
146
+ i0.ɵɵelementStart(0, "div", 1);
147
+ i0.ɵɵrepeaterCreate(1, ModelPredictionPanel_Conditional_0_Conditional_1_For_2_Template, 19, 9, "div", 9, _forTrack0);
148
+ i0.ɵɵelementEnd();
149
+ } if (rf & 2) {
150
+ const ctx_r3 = i0.ɵɵnextContext(2);
151
+ i0.ɵɵadvance();
152
+ i0.ɵɵrepeater(ctx_r3.Cards);
153
+ } }
154
+ function ModelPredictionPanel_Conditional_0_Conditional_8_Template(rf, ctx) { if (rf & 1) {
155
+ i0.ɵɵelementStart(0, "span", 6);
156
+ i0.ɵɵtext(1);
157
+ i0.ɵɵelementEnd();
158
+ } if (rf & 2) {
159
+ const ctx_r3 = i0.ɵɵnextContext(2);
160
+ i0.ɵɵadvance();
161
+ i0.ɵɵtextInterpolate(ctx_r3.HistoryItems.length);
162
+ } }
163
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_1_Template(rf, ctx) { if (rf & 1) {
164
+ i0.ɵɵelementStart(0, "div", 34);
165
+ i0.ɵɵelement(1, "i", 36);
166
+ i0.ɵɵtext(2, " Loading prediction history\u2026 ");
167
+ i0.ɵɵelementEnd();
168
+ } }
169
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_2_Template(rf, ctx) { if (rf & 1) {
170
+ i0.ɵɵelementStart(0, "div", 35);
171
+ i0.ɵɵtext(1, " No historical prediction runs recorded for this record yet. ");
172
+ i0.ɵɵelementEnd();
173
+ } }
174
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_Conditional_0_For_4_Template(rf, ctx) { if (rf & 1) {
175
+ const _r7 = i0.ɵɵgetCurrentView();
176
+ i0.ɵɵelementStart(0, "button", 41);
177
+ i0.ɵɵlistener("click", function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_Conditional_0_For_4_Template_button_click_0_listener() { const mod_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r3 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r3.SelectModelFilter(mod_r8.modelId)); });
178
+ i0.ɵɵtext(1);
179
+ i0.ɵɵelementEnd();
180
+ } if (rf & 2) {
181
+ const mod_r8 = ctx.$implicit;
182
+ const ctx_r3 = i0.ɵɵnextContext(5);
183
+ i0.ɵɵclassProp("active", ctx_r3.SelectedModelId === mod_r8.modelId);
184
+ i0.ɵɵadvance();
185
+ i0.ɵɵtextInterpolate2(" ", mod_r8.ModelName, " (", mod_r8.count, ") ");
186
+ } }
187
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
188
+ const _r6 = i0.ɵɵgetCurrentView();
189
+ i0.ɵɵelementStart(0, "div", 37)(1, "button", 41);
190
+ i0.ɵɵlistener("click", function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_Conditional_0_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r3.SelectModelFilter(null)); });
191
+ i0.ɵɵtext(2);
192
+ i0.ɵɵelementEnd();
193
+ i0.ɵɵrepeaterCreate(3, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_Conditional_0_For_4_Template, 2, 4, "button", 42, _forTrack3);
194
+ i0.ɵɵelementEnd();
195
+ } if (rf & 2) {
196
+ const ctx_r3 = i0.ɵɵnextContext(4);
197
+ i0.ɵɵadvance();
198
+ i0.ɵɵclassProp("active", ctx_r3.SelectedModelId === null || ctx_r3.SelectedModelId === "ALL");
199
+ i0.ɵɵadvance();
200
+ i0.ɵɵtextInterpolate1(" All Models (", ctx_r3.HistoryItems.length, ") ");
201
+ i0.ɵɵadvance();
202
+ i0.ɵɵrepeater(ctx_r3.ModelSummaries);
75
203
  } }
76
- function ModelPredictionPanel_Conditional_0_For_3_Template(rf, ctx) { if (rf & 1) {
77
- i0.ɵɵelementStart(0, "div", 2)(1, "div", 3)(2, "div", 4);
204
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_12_Template(rf, ctx) { if (rf & 1) {
205
+ i0.ɵɵelementStart(0, "span", 51);
206
+ i0.ɵɵtext(1);
207
+ i0.ɵɵpipe(2, "number");
208
+ i0.ɵɵelementEnd();
209
+ } if (rf & 2) {
210
+ const item_r10 = i0.ɵɵnextContext().$implicit;
211
+ i0.ɵɵadvance();
212
+ i0.ɵɵtextInterpolate1("(", i0.ɵɵpipeBind2(2, 1, item_r10.NumericValue * 100, "1.0-1"), "%)");
213
+ } }
214
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_13_Conditional_1_Template(rf, ctx) { if (rf & 1) {
215
+ i0.ɵɵelement(0, "i");
216
+ } if (rf & 2) {
217
+ const item_r10 = i0.ɵɵnextContext(2).$implicit;
218
+ i0.ɵɵclassMap("fa-solid " + item_r10.BadgeIcon);
219
+ } }
220
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_13_Template(rf, ctx) { if (rf & 1) {
221
+ i0.ɵɵelementStart(0, "span", 60);
222
+ i0.ɵɵconditionalCreate(1, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_13_Conditional_1_Template, 1, 2, "i", 24);
223
+ i0.ɵɵelementStart(2, "span");
224
+ i0.ɵɵtext(3);
225
+ i0.ɵɵelementEnd()();
226
+ } if (rf & 2) {
227
+ const item_r10 = i0.ɵɵnextContext().$implicit;
228
+ i0.ɵɵclassMap("mpp-badge-" + item_r10.BadgeColor);
229
+ i0.ɵɵadvance();
230
+ i0.ɵɵconditional(item_r10.BadgeIcon ? 1 : -1);
231
+ i0.ɵɵadvance(2);
232
+ i0.ɵɵtextInterpolate(item_r10.StatusLabel);
233
+ } }
234
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_24_Conditional_3_Template(rf, ctx) { if (rf & 1) {
235
+ i0.ɵɵelementStart(0, "div", 63)(1, "strong");
236
+ i0.ɵɵtext(2, "Error:");
237
+ i0.ɵɵelementEnd();
78
238
  i0.ɵɵtext(3);
79
239
  i0.ɵɵelementEnd();
80
- i0.ɵɵelementStart(4, "div", 5);
81
- i0.ɵɵelement(5, "i", 6);
82
- i0.ɵɵelementStart(6, "span");
83
- i0.ɵɵtext(7);
240
+ } if (rf & 2) {
241
+ const item_r10 = i0.ɵɵnextContext(2).$implicit;
242
+ i0.ɵɵadvance(3);
243
+ i0.ɵɵtextInterpolate1(" ", item_r10.ErrorMessage, " ");
244
+ } }
245
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_24_Conditional_4_For_6_Template(rf, ctx) { if (rf & 1) {
246
+ i0.ɵɵelementStart(0, "div", 71)(1, "span", 72);
247
+ i0.ɵɵtext(2);
248
+ i0.ɵɵelementEnd();
249
+ i0.ɵɵelementStart(3, "span", 32);
250
+ i0.ɵɵelement(4, "span", 33);
251
+ i0.ɵɵelementEnd()();
252
+ } if (rf & 2) {
253
+ const d_r11 = ctx.$implicit;
254
+ i0.ɵɵadvance(2);
255
+ i0.ɵɵtextInterpolate(d_r11.name);
256
+ i0.ɵɵadvance(2);
257
+ i0.ɵɵstyleProp("width", d_r11.RelativePct, "%");
258
+ } }
259
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_24_Conditional_4_Template(rf, ctx) { if (rf & 1) {
260
+ i0.ɵɵelementStart(0, "div", 64)(1, "div", 66);
261
+ i0.ɵɵelement(2, "i", 69);
262
+ i0.ɵɵtext(3, " Attributed Drivers");
263
+ i0.ɵɵelementEnd();
264
+ i0.ɵɵelementStart(4, "div", 70);
265
+ i0.ɵɵrepeaterCreate(5, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_24_Conditional_4_For_6_Template, 5, 3, "div", 71, _forTrack1);
266
+ i0.ɵɵelementEnd()();
267
+ } if (rf & 2) {
268
+ const item_r10 = i0.ɵɵnextContext(2).$implicit;
269
+ i0.ɵɵadvance(5);
270
+ i0.ɵɵrepeater(item_r10.Drivers);
271
+ } }
272
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_24_Template(rf, ctx) { if (rf & 1) {
273
+ i0.ɵɵelementStart(0, "tr", 59)(1, "td", 61)(2, "div", 62);
274
+ i0.ɵɵconditionalCreate(3, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_24_Conditional_3_Template, 4, 1, "div", 63);
275
+ i0.ɵɵconditionalCreate(4, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_24_Conditional_4_Template, 7, 0, "div", 64);
276
+ i0.ɵɵelementStart(5, "div", 65)(6, "div", 66);
277
+ i0.ɵɵelement(7, "i", 67);
278
+ i0.ɵɵtext(8, " Result Payload");
279
+ i0.ɵɵelementEnd();
280
+ i0.ɵɵelementStart(9, "pre", 68);
281
+ i0.ɵɵtext(10);
282
+ i0.ɵɵpipe(11, "json");
283
+ i0.ɵɵelementEnd()()()()();
284
+ } if (rf & 2) {
285
+ const item_r10 = i0.ɵɵnextContext().$implicit;
286
+ i0.ɵɵadvance(3);
287
+ i0.ɵɵconditional(item_r10.ErrorMessage ? 3 : -1);
288
+ i0.ɵɵadvance();
289
+ i0.ɵɵconditional(item_r10.Drivers.length > 0 ? 4 : -1);
290
+ i0.ɵɵadvance(6);
291
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(11, 3, item_r10.RawPayload));
292
+ } }
293
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Template(rf, ctx) { if (rf & 1) {
294
+ const _r9 = i0.ɵɵgetCurrentView();
295
+ i0.ɵɵelementStart(0, "tr", 43)(1, "td", 44);
296
+ i0.ɵɵtext(2);
297
+ i0.ɵɵelementEnd();
298
+ i0.ɵɵelementStart(3, "td", 45)(4, "div", 46);
299
+ i0.ɵɵtext(5);
84
300
  i0.ɵɵelementEnd();
85
- i0.ɵɵconditionalCreate(8, ModelPredictionPanel_Conditional_0_For_3_Conditional_8_Template, 4, 1);
301
+ i0.ɵɵelementStart(6, "div", 47);
302
+ i0.ɵɵtext(7);
86
303
  i0.ɵɵelementEnd()();
87
- i0.ɵɵelementStart(9, "div", 7)(10, "span", 8);
304
+ i0.ɵɵelementStart(8, "td", 48)(9, "div", 49)(10, "span", 50);
88
305
  i0.ɵɵtext(11);
306
+ i0.ɵɵelementEnd();
307
+ i0.ɵɵconditionalCreate(12, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_12_Template, 3, 4, "span", 51);
308
+ i0.ɵɵconditionalCreate(13, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_13_Template, 4, 4, "span", 52);
309
+ i0.ɵɵelementEnd()();
310
+ i0.ɵɵelementStart(14, "td", 53)(15, "span", 54);
311
+ i0.ɵɵtext(16);
89
312
  i0.ɵɵelementEnd()();
90
- i0.ɵɵconditionalCreate(12, ModelPredictionPanel_Conditional_0_For_3_Conditional_12_Template, 10, 9, "div", 9);
91
- i0.ɵɵconditionalCreate(13, ModelPredictionPanel_Conditional_0_For_3_Conditional_13_Template, 6, 0, "div", 10);
313
+ i0.ɵɵelementStart(17, "td", 55)(18, "button", 56);
314
+ i0.ɵɵlistener("click", function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Template_button_click_18_listener($event) { const item_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r3.ToggleHistoryDetails(item_r10, $event)); });
315
+ i0.ɵɵelement(19, "i");
316
+ i0.ɵɵtext(20);
92
317
  i0.ɵɵelementEnd();
318
+ i0.ɵɵelementStart(21, "button", 57);
319
+ i0.ɵɵlistener("click", function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Template_button_click_21_listener($event) { const item_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r3.DrilldownToPredictionRecord(item_r10, $event)); });
320
+ i0.ɵɵelement(22, "i", 58);
321
+ i0.ɵɵtext(23, " Open Row ");
322
+ i0.ɵɵelementEnd()()();
323
+ i0.ɵɵconditionalCreate(24, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Conditional_24_Template, 12, 5, "tr", 59);
93
324
  } if (rf & 2) {
94
- const card_r1 = ctx.$implicit;
325
+ const item_r10 = ctx.$implicit;
326
+ const ctx_r3 = i0.ɵɵnextContext(4);
327
+ i0.ɵɵclassProp("expanded", ctx_r3.ExpandedHistoryItemId === item_r10.id);
328
+ i0.ɵɵadvance(2);
329
+ i0.ɵɵtextInterpolate(item_r10.FormattedTime);
95
330
  i0.ɵɵadvance(3);
96
- i0.ɵɵtextInterpolate(card_r1.label);
331
+ i0.ɵɵtextInterpolate(item_r10.ModelName);
332
+ i0.ɵɵadvance(2);
333
+ i0.ɵɵtextInterpolate(item_r10.Provenance);
97
334
  i0.ɵɵadvance(4);
98
- i0.ɵɵtextInterpolate(card_r1.provenance);
335
+ i0.ɵɵtextInterpolate(item_r10.DisplayValue);
99
336
  i0.ɵɵadvance();
100
- i0.ɵɵconditional(card_r1.lastScored ? 8 : -1);
337
+ i0.ɵɵconditional(item_r10.PredictedClass && item_r10.NumericValue != null && item_r10.IsProbability ? 12 : -1);
338
+ i0.ɵɵadvance();
339
+ i0.ɵɵconditional(item_r10.StatusLabel ? 13 : -1);
340
+ i0.ɵɵadvance(2);
341
+ i0.ɵɵclassMap("mpp-status-" + item_r10.status.toLowerCase());
342
+ i0.ɵɵadvance();
343
+ i0.ɵɵtextInterpolate1(" ", item_r10.status, " ");
101
344
  i0.ɵɵadvance(2);
102
- i0.ɵɵclassProp("mpp-value-muted", card_r1.displayValue === "\u2014");
345
+ i0.ɵɵproperty("title", ctx_r3.ExpandedHistoryItemId === item_r10.id ? "Hide details" : "Inspect payload & drivers");
103
346
  i0.ɵɵadvance();
104
- i0.ɵɵtextInterpolate1(" ", card_r1.displayValue, " ");
347
+ i0.ɵɵclassMap(ctx_r3.ExpandedHistoryItemId === item_r10.id ? "fa-solid fa-chevron-up" : "fa-solid fa-code");
105
348
  i0.ɵɵadvance();
106
- i0.ɵɵconditional(card_r1.isProbability ? 12 : -1);
349
+ i0.ɵɵtextInterpolate1(" ", ctx_r3.ExpandedHistoryItemId === item_r10.id ? "Close" : "Inspect", " ");
350
+ i0.ɵɵadvance(4);
351
+ i0.ɵɵconditional(ctx_r3.ExpandedHistoryItemId === item_r10.id ? 24 : -1);
352
+ } }
353
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_Template(rf, ctx) { if (rf & 1) {
354
+ i0.ɵɵconditionalCreate(0, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_Conditional_0_Template, 5, 3, "div", 37);
355
+ i0.ɵɵelementStart(1, "div", 38)(2, "table", 39)(3, "thead")(4, "tr")(5, "th");
356
+ i0.ɵɵtext(6, "Date");
357
+ i0.ɵɵelementEnd();
358
+ i0.ɵɵelementStart(7, "th");
359
+ i0.ɵɵtext(8, "Model");
360
+ i0.ɵɵelementEnd();
361
+ i0.ɵɵelementStart(9, "th");
362
+ i0.ɵɵtext(10, "Prediction");
363
+ i0.ɵɵelementEnd();
364
+ i0.ɵɵelementStart(11, "th");
365
+ i0.ɵɵtext(12, "Status");
366
+ i0.ɵɵelementEnd();
367
+ i0.ɵɵelementStart(13, "th", 40);
368
+ i0.ɵɵtext(14, "Actions");
369
+ i0.ɵɵelementEnd()()();
370
+ i0.ɵɵelementStart(15, "tbody");
371
+ i0.ɵɵrepeaterCreate(16, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_For_17_Template, 25, 16, null, null, _forTrack2);
372
+ i0.ɵɵelementEnd()()();
373
+ } if (rf & 2) {
374
+ const ctx_r3 = i0.ɵɵnextContext(3);
375
+ i0.ɵɵconditional(ctx_r3.ModelSummaries.length > 1 ? 0 : -1);
376
+ i0.ɵɵadvance(16);
377
+ i0.ɵɵrepeater(ctx_r3.FilteredHistory);
378
+ } }
379
+ function ModelPredictionPanel_Conditional_0_Conditional_11_Template(rf, ctx) { if (rf & 1) {
380
+ i0.ɵɵelementStart(0, "div", 8);
381
+ i0.ɵɵconditionalCreate(1, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_1_Template, 3, 0, "div", 34)(2, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_2_Template, 2, 0, "div", 35)(3, ModelPredictionPanel_Conditional_0_Conditional_11_Conditional_3_Template, 18, 1);
382
+ i0.ɵɵelementEnd();
383
+ } if (rf & 2) {
384
+ const ctx_r3 = i0.ɵɵnextContext(2);
107
385
  i0.ɵɵadvance();
108
- i0.ɵɵconditional(card_r1.drivers.length > 0 ? 13 : -1);
386
+ i0.ɵɵconditional(ctx_r3.LoadingHistory ? 1 : ctx_r3.HistoryItems.length === 0 ? 2 : 3);
109
387
  } }
110
388
  function ModelPredictionPanel_Conditional_0_Template(rf, ctx) { if (rf & 1) {
111
- i0.ɵɵelementStart(0, "mj-collapsible-panel", 0)(1, "div", 1);
112
- i0.ɵɵrepeaterCreate(2, ModelPredictionPanel_Conditional_0_For_3_Template, 14, 8, "div", 2, _forTrack0);
389
+ const _r1 = i0.ɵɵgetCurrentView();
390
+ i0.ɵɵelementStart(0, "mj-collapsible-panel", 0);
391
+ i0.ɵɵconditionalCreate(1, ModelPredictionPanel_Conditional_0_Conditional_1_Template, 3, 0, "div", 1);
392
+ i0.ɵɵelementStart(2, "div", 2)(3, "div", 3);
393
+ i0.ɵɵlistener("click", function ModelPredictionPanel_Conditional_0_Template_div_click_3_listener() { i0.ɵɵrestoreView(_r1); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.ToggleHistorySection()); });
394
+ i0.ɵɵelementStart(4, "div", 4);
395
+ i0.ɵɵelement(5, "i", 5);
396
+ i0.ɵɵelementStart(6, "span");
397
+ i0.ɵɵtext(7, "Prediction History");
398
+ i0.ɵɵelementEnd();
399
+ i0.ɵɵconditionalCreate(8, ModelPredictionPanel_Conditional_0_Conditional_8_Template, 2, 1, "span", 6);
400
+ i0.ɵɵelementEnd();
401
+ i0.ɵɵelementStart(9, "div", 7);
402
+ i0.ɵɵelement(10, "i");
403
+ i0.ɵɵelementEnd()();
404
+ i0.ɵɵconditionalCreate(11, ModelPredictionPanel_Conditional_0_Conditional_11_Template, 4, 1, "div", 8);
113
405
  i0.ɵɵelementEnd()();
114
406
  } if (rf & 2) {
115
- const ctx_r2 = i0.ɵɵnextContext();
116
- i0.ɵɵproperty("Form", ctx_r2.FormComponent)("FormContext", ctx_r2.FormContext)("BadgeCount", ctx_r2.Cards.length);
407
+ const ctx_r3 = i0.ɵɵnextContext();
408
+ i0.ɵɵproperty("Form", ctx_r3.FormComponent)("FormContext", ctx_r3.FormContext)("BadgeCount", ctx_r3.Cards.length);
409
+ i0.ɵɵadvance();
410
+ i0.ɵɵconditional(ctx_r3.Cards.length > 0 ? 1 : -1);
411
+ i0.ɵɵadvance(7);
412
+ i0.ɵɵconditional(ctx_r3.HistoryItems.length > 0 ? 8 : -1);
117
413
  i0.ɵɵadvance(2);
118
- i0.ɵɵrepeater(ctx_r2.Cards);
414
+ i0.ɵɵclassMap(ctx_r3.ShowHistorySection ? "fa-solid fa-chevron-up" : "fa-solid fa-chevron-down");
415
+ i0.ɵɵadvance();
416
+ i0.ɵɵconditional(ctx_r3.ShowHistorySection ? 11 : -1);
119
417
  } }
120
418
  /**
121
419
  * Model Prediction panel — an **entity-agnostic** form panel that surfaces any
@@ -137,19 +435,48 @@ function ModelPredictionPanel_Conditional_0_Template(rf, ctx) { if (rf & 1) {
137
435
  let ModelPredictionPanel = class ModelPredictionPanel extends BaseFormPanel {
138
436
  constructor() {
139
437
  super(...arguments);
438
+ this.cdr = inject(ChangeDetectorRef);
140
439
  /** The resolved cards to render. Empty → panel renders nothing. */
141
440
  this.Cards = [];
142
441
  /** True once the binding lookup has completed (success or empty). */
143
442
  this.Loaded = false;
443
+ /** Resolved models by ID for lineage and history decoration. */
444
+ this.ModelsById = new Map();
445
+ /** Historical prediction runs for this record across models. */
446
+ this.HistoryItems = [];
447
+ /** Loading flag for historical predictions lookup. */
448
+ this.LoadingHistory = false;
449
+ /** Whether the prediction history section is expanded in the template. */
450
+ this.ShowHistorySection = false;
451
+ /** Selected model ID for history filtering (null = all models). */
452
+ this.SelectedModelId = null;
453
+ /** Expanded history item ID for in-place inspection of payload & drivers. */
454
+ this.ExpandedHistoryItemId = null;
144
455
  /** Entity-ID we last loaded cards for, to avoid redundant lookups. */
145
456
  this.loadedForEntityId = null;
146
457
  }
458
+ /** @deprecated Use {@link ModelsById}. */
459
+ get modelsById() {
460
+ return this.ModelsById;
461
+ }
462
+ /** @deprecated Use {@link ModelsById}. */
463
+ set modelsById(value) {
464
+ this.ModelsById = value;
465
+ }
147
466
  async ngOnInit() {
148
467
  await this.loadCards();
149
468
  }
150
- /** True when there is at least one card to show — gates the whole template. */
469
+ /** True when there is at least one card or history item to show — gates the whole template. */
151
470
  get HasPredictions() {
152
- return this.Cards.length > 0;
471
+ return this.Cards.length > 0 || this.HistoryItems.length > 0;
472
+ }
473
+ /** Filtered history items based on currently selected model. */
474
+ get FilteredHistory() {
475
+ return FilterHistoryByModel(this.HistoryItems, this.SelectedModelId);
476
+ }
477
+ /** Distinct models in prediction history with counts. */
478
+ get ModelSummaries() {
479
+ return GetDistinctModelsFromHistory(this.HistoryItems);
153
480
  }
154
481
  /**
155
482
  * Look up active scoring bindings for THIS record's entity and build a card
@@ -170,11 +497,14 @@ let ModelPredictionPanel = class ModelPredictionPanel extends BaseFormPanel {
170
497
  const bindings = await this.loadBindingsForEntity(entityId);
171
498
  if (bindings.length === 0) {
172
499
  this.Cards = [];
173
- this.Loaded = true;
174
- return;
175
500
  }
176
- const models = await this.loadModelsForBindings(bindings);
177
- this.Cards = this.buildCards(bindings, models);
501
+ else {
502
+ const models = await this.loadModelsForBindings(bindings);
503
+ this.ModelsById = models;
504
+ this.Cards = this.buildCards(bindings, models);
505
+ }
506
+ // Preload history in the background for this record
507
+ void this.LoadHistory();
178
508
  }
179
509
  catch (e) {
180
510
  LogError(`[ModelPredictionPanel] Failed to load predictions: ${e instanceof Error ? e.message : String(e)}`);
@@ -182,6 +512,111 @@ let ModelPredictionPanel = class ModelPredictionPanel extends BaseFormPanel {
182
512
  }
183
513
  finally {
184
514
  this.Loaded = true;
515
+ this.cdr.markForCheck();
516
+ }
517
+ }
518
+ /**
519
+ * Load historical prediction runs for this specific record across all models.
520
+ */
521
+ async LoadHistory() {
522
+ const entityId = this.Record?.EntityInfo?.ID ?? null;
523
+ const pkVal = this.Record?.FirstPrimaryKey?.Value; // first-pk-ok: Target entity single PK value for RecordID filter
524
+ const recordId = pkVal != null ? String(pkVal) : '';
525
+ if (!entityId || !recordId) {
526
+ this.HistoryItems = [];
527
+ this.cdr.markForCheck();
528
+ return;
529
+ }
530
+ this.LoadingHistory = true;
531
+ this.cdr.markForCheck();
532
+ try {
533
+ const rv = this.runView();
534
+ const result = await rv.RunView({
535
+ EntityName: 'MJ: Process Run Details',
536
+ ExtraFilter: `EntityID='${entityId}' AND RecordID='${recordId}'`,
537
+ OrderBy: 'CompletedAt DESC',
538
+ MaxRows: 50,
539
+ ResultType: 'entity_object',
540
+ }, this.contextUser());
541
+ if (!result.Success) {
542
+ LogError(`[ModelPredictionPanel] Failed to load prediction history: ${result.ErrorMessage}`);
543
+ this.HistoryItems = [];
544
+ return;
545
+ }
546
+ const rawDetails = result.Results ?? [];
547
+ if (rawDetails.length === 0) {
548
+ this.HistoryItems = [];
549
+ return;
550
+ }
551
+ // Ensure any models referenced in historical payloads are loaded
552
+ await this.ensureModelsLoadedForHistory(rawDetails);
553
+ this.HistoryItems = rawDetails.map(d => ParseHistoryItem({
554
+ ID: d.ID,
555
+ ProcessRunID: d.ProcessRunID,
556
+ Status: d.Status,
557
+ CompletedAt: d.CompletedAt,
558
+ ResultPayload: d.ResultPayload,
559
+ ErrorMessage: d.ErrorMessage,
560
+ }, this.ModelsById));
561
+ }
562
+ catch (e) {
563
+ LogError(`[ModelPredictionPanel] Error loading prediction history: ${e instanceof Error ? e.message : String(e)}`);
564
+ this.HistoryItems = [];
565
+ }
566
+ finally {
567
+ this.LoadingHistory = false;
568
+ this.cdr.markForCheck();
569
+ }
570
+ }
571
+ /**
572
+ * Select a model ID filter for history (null = all models).
573
+ */
574
+ SelectModelFilter(modelId) {
575
+ this.SelectedModelId = modelId;
576
+ this.cdr.markForCheck();
577
+ }
578
+ /**
579
+ * Toggle the prediction history section.
580
+ */
581
+ ToggleHistorySection() {
582
+ this.ShowHistorySection = !this.ShowHistorySection;
583
+ this.cdr.markForCheck();
584
+ if (this.ShowHistorySection && this.HistoryItems.length === 0 && !this.LoadingHistory) {
585
+ void this.LoadHistory();
586
+ }
587
+ }
588
+ /**
589
+ * Focus prediction history on a specific model from a card action.
590
+ */
591
+ OpenHistoryForModel(modelId, event) {
592
+ event?.stopPropagation();
593
+ this.ShowHistorySection = true;
594
+ this.SelectedModelId = modelId;
595
+ this.cdr.markForCheck();
596
+ if (this.HistoryItems.length === 0 && !this.LoadingHistory) {
597
+ void this.LoadHistory();
598
+ }
599
+ }
600
+ /**
601
+ * Toggle inline inspection drawer for a prediction history row.
602
+ */
603
+ ToggleHistoryDetails(item, event) {
604
+ event?.stopPropagation();
605
+ this.ExpandedHistoryItemId = this.ExpandedHistoryItemId === item.id ? null : item.id;
606
+ this.cdr.markForCheck();
607
+ }
608
+ /**
609
+ * Drill down into the underlying MJ: Process Run Details record in Explorer.
610
+ */
611
+ DrilldownToPredictionRecord(item, event) {
612
+ event?.stopPropagation();
613
+ if (this.FormComponent?.OnFormNavigate) {
614
+ this.FormComponent.OnFormNavigate({
615
+ Kind: 'record',
616
+ EntityName: 'MJ: Process Run Details',
617
+ PrimaryKey: CompositeKey.FromID(item.id),
618
+ OpenInNewTab: event ? (event.ctrlKey || event.metaKey) : true,
619
+ });
185
620
  }
186
621
  }
187
622
  /** Active scoring bindings whose target entity is the current record's entity. */
@@ -222,6 +657,42 @@ let ModelPredictionPanel = class ModelPredictionPanel extends BaseFormPanel {
222
657
  }
223
658
  return byId;
224
659
  }
660
+ /** Ensure models found in process run detail payloads are loaded for metadata decoration. */
661
+ async ensureModelsLoadedForHistory(details) {
662
+ const missingModelIds = [];
663
+ for (const d of details) {
664
+ if (!d.ResultPayload)
665
+ continue;
666
+ try {
667
+ const parsed = JSON.parse(d.ResultPayload);
668
+ if (parsed && typeof parsed === 'object') {
669
+ const rec = parsed;
670
+ const out = (rec['output'] && typeof rec['output'] === 'object' ? rec['output'] : rec);
671
+ const mid = typeof out['modelId'] === 'string' ? out['modelId'] : null;
672
+ if (mid && !this.ModelsById.has(mid) && !missingModelIds.includes(mid)) {
673
+ missingModelIds.push(mid);
674
+ }
675
+ }
676
+ }
677
+ catch {
678
+ // Ignore parse errors
679
+ }
680
+ }
681
+ if (missingModelIds.length === 0)
682
+ return;
683
+ const inList = missingModelIds.map(id => `'${id}'`).join(',');
684
+ const rv = this.runView();
685
+ const result = await rv.RunView({
686
+ EntityName: 'MJ: ML Models',
687
+ ExtraFilter: `ID IN (${inList})`,
688
+ ResultType: 'entity_object',
689
+ }, this.contextUser());
690
+ if (result.Success && result.Results) {
691
+ for (const model of result.Results) {
692
+ this.ModelsById.set(model.ID, model);
693
+ }
694
+ }
695
+ }
225
696
  /** Map each binding (+ its model) to a display card. Skips bindings whose model is missing. */
226
697
  buildCards(bindings, models) {
227
698
  const cards = [];
@@ -239,20 +710,48 @@ let ModelPredictionPanel = class ModelPredictionPanel extends BaseFormPanel {
239
710
  // The column name is data-driven (from the binding), so reading it
240
711
  // dynamically via Get() is the legitimate use of the dynamic accessor.
241
712
  const rawValue = binding.TargetColumn ? this.Record.Get(binding.TargetColumn) : null;
242
- const numeric = toNumber(rawValue);
243
- const kind = valueKind(model.ProblemType, numeric);
713
+ const numeric = ToNumber(rawValue);
714
+ const kind = ValueKind(model.ProblemType, numeric);
715
+ const outcomeConfig = resolveOutcomeConfig({
716
+ Lineage: model.Lineage,
717
+ TargetVariable: model.TargetVariable,
718
+ ProblemType: model.ProblemType,
719
+ });
720
+ let statusBand = null;
721
+ let badgeColor = 'gray';
722
+ let badgeIcon = null;
723
+ let statusLabel = null;
724
+ if (numeric != null) {
725
+ statusBand = resolveScoreBand(numeric, outcomeConfig);
726
+ if (statusBand) {
727
+ badgeColor = statusBand.BadgeColor;
728
+ badgeIcon = statusBand.Icon ?? null;
729
+ statusLabel = statusBand.Label;
730
+ }
731
+ }
732
+ else if (kind === 'class' && typeof rawValue === 'string') {
733
+ const style = resolveOutcomeStyle(rawValue, outcomeConfig);
734
+ badgeColor = style.BadgeColor;
735
+ badgeIcon = style.Icon ?? null;
736
+ statusLabel = style.DisplayLabel ?? rawValue;
737
+ }
244
738
  return {
245
- bindingId: binding.ID,
246
- label: resolveLabel(model.TargetVariable, binding.TargetColumn),
247
- isProbability: kind === 'probability',
248
- isNumeric: kind === 'numeric',
249
- isClass: kind === 'class',
250
- displayValue: formatValue(rawValue, numeric, kind),
251
- gaugePct: kind === 'probability' && numeric != null ? gaugePct(numeric) : 0,
252
- band: kind === 'probability' && numeric != null ? bandFor(numeric) : null,
253
- drivers: parseDrivers(model.FeatureImportance),
254
- provenance: `${model.Pipeline} v${model.Version}`,
255
- lastScored: formatLastScored(binding.LastScoredAt),
739
+ BindingId: binding.ID,
740
+ modelId: model.ID,
741
+ Label: ResolveLabel(model.TargetVariable, binding.TargetColumn),
742
+ IsProbability: kind === 'probability',
743
+ IsNumeric: kind === 'numeric',
744
+ IsClass: kind === 'class',
745
+ DisplayValue: FormatValue(rawValue, numeric, kind),
746
+ GaugePct: kind === 'probability' && numeric != null ? GaugePct(numeric) : 0,
747
+ Band: kind === 'probability' && numeric != null ? BandFor(numeric) : null,
748
+ StatusBand: statusBand,
749
+ StatusLabel: statusLabel,
750
+ BadgeColor: badgeColor,
751
+ BadgeIcon: badgeIcon,
752
+ Drivers: ParseDrivers(model.FeatureImportance),
753
+ Provenance: `${model.Pipeline} v${model.Version}`,
754
+ LastScored: FormatLastScored(binding.LastScoredAt),
256
755
  };
257
756
  }
258
757
  /** RunView scoped to the form's provider when available (multi-provider safe). */
@@ -265,11 +764,11 @@ let ModelPredictionPanel = class ModelPredictionPanel extends BaseFormPanel {
265
764
  return this.FormComponent?.ProviderToUse?.CurrentUser ?? new Metadata().CurrentUser;
266
765
  }
267
766
  static { this.ɵfac = /*@__PURE__*/ (() => { let ɵModelPredictionPanel_BaseFactory; return function ModelPredictionPanel_Factory(__ngFactoryType__) { return (ɵModelPredictionPanel_BaseFactory || (ɵModelPredictionPanel_BaseFactory = i0.ɵɵgetInheritedFactory(ModelPredictionPanel)))(__ngFactoryType__ || ModelPredictionPanel); }; })(); }
268
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ModelPredictionPanel, selectors: [["mj-model-prediction-panel"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [["SectionKey", "modelPredictions", "SectionName", "Model Predictions", "Icon", "fa-solid fa-wand-magic-sparkles", 3, "Form", "FormContext", "BadgeCount"], [1, "mpp-cards"], [1, "mpp-card"], [1, "mpp-card-head"], [1, "mpp-label"], [1, "mpp-provenance"], ["aria-hidden", "true", 1, "fa-solid", "fa-diagram-project", "mpp-prov-icon"], [1, "mpp-value-row"], [1, "mpp-value"], ["role", "img", 1, "mpp-gauge"], [1, "mpp-drivers"], ["aria-hidden", "true", 1, "mpp-dot"], [1, "mpp-scored"], [1, "mpp-gauge-track"], [1, "mpp-gauge-fill"], [1, "mpp-gauge-scale"], [1, "mpp-drivers-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-ranking-star"], [1, "mpp-driver"], [1, "mpp-driver-name", 3, "title"], [1, "mpp-driver-bar-track"], [1, "mpp-driver-bar-fill"]], template: function ModelPredictionPanel_Template(rf, ctx) { if (rf & 1) {
269
- i0.ɵɵconditionalCreate(0, ModelPredictionPanel_Conditional_0_Template, 4, 3, "mj-collapsible-panel", 0);
767
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ModelPredictionPanel, selectors: [["mj-model-prediction-panel"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [["SectionKey", "modelPredictions", "SectionName", "Model Predictions", "Icon", "fa-solid fa-wand-magic-sparkles", 3, "Form", "FormContext", "BadgeCount"], [1, "mpp-cards"], [1, "mpp-history-section"], ["role", "button", "tabindex", "0", 1, "mpp-history-header", 3, "click"], [1, "mpp-history-title"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "mpp-history-badge"], [1, "mpp-history-chevron"], [1, "mpp-history-body"], [1, "mpp-card"], [1, "mpp-card-head"], [1, "mpp-head-left"], [1, "mpp-label"], [1, "mpp-provenance"], ["aria-hidden", "true", 1, "fa-solid", "fa-diagram-project", "mpp-prov-icon"], ["type", "button", "title", "View prediction history for this model", 1, "mpp-card-history-btn", 3, "click"], [1, "mpp-value-row"], [1, "mpp-value"], [1, "mpp-status-badge", 3, "class"], ["role", "img", 1, "mpp-gauge"], [1, "mpp-drivers"], ["aria-hidden", "true", 1, "mpp-dot"], [1, "mpp-scored"], [1, "mpp-status-badge"], [3, "class"], [1, "mpp-gauge-track"], [1, "mpp-gauge-fill"], [1, "mpp-gauge-scale"], [1, "mpp-drivers-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-ranking-star"], [1, "mpp-driver"], [1, "mpp-driver-name", 3, "title"], [1, "mpp-driver-bar-track"], [1, "mpp-driver-bar-fill"], [1, "mpp-history-loading"], [1, "mpp-history-empty"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "mpp-model-filters"], [1, "mpp-history-table-wrap"], [1, "mpp-history-table"], [1, "actions-th"], ["type", "button", 1, "mpp-filter-pill", 3, "click"], ["type", "button", 1, "mpp-filter-pill", 3, "active"], [1, "mpp-history-row"], [1, "mpp-col-date"], [1, "mpp-col-model"], [1, "mpp-history-model-name"], [1, "mpp-history-model-prov"], [1, "mpp-col-pred"], [1, "mpp-pred-cell"], [1, "mpp-history-pred-val"], [1, "mpp-history-pred-sub"], [1, "mpp-status-badge", "mpp-badge-sm", 3, "class"], [1, "mpp-col-status"], [1, "mpp-status-pill"], [1, "mpp-col-actions"], ["type", "button", 1, "mpp-action-btn", 3, "click", "title"], ["type", "button", "title", "Open underlying Process Run Detail record in Explorer", 1, "mpp-action-btn", "mpp-action-drilldown", 3, "click"], [1, "fa-solid", "fa-arrow-up-right-from-square"], [1, "mpp-history-detail-row"], [1, "mpp-status-badge", "mpp-badge-sm"], ["colspan", "5"], [1, "mpp-history-detail-pane"], [1, "mpp-detail-error"], [1, "mpp-detail-drivers"], [1, "mpp-detail-payload"], [1, "mpp-detail-subtitle"], [1, "fa-solid", "fa-file-code"], [1, "mpp-payload-pre"], [1, "fa-solid", "fa-ranking-star"], [1, "mpp-detail-driver-list"], [1, "mpp-detail-driver-item"], [1, "mpp-driver-name"]], template: function ModelPredictionPanel_Template(rf, ctx) { if (rf & 1) {
768
+ i0.ɵɵconditionalCreate(0, ModelPredictionPanel_Conditional_0_Template, 12, 8, "mj-collapsible-panel", 0);
270
769
  } if (rf & 2) {
271
770
  i0.ɵɵconditional(ctx.HasPredictions ? 0 : -1);
272
- } }, dependencies: [i1.MjCollapsiblePanelComponent], styles: ["\n\n\n\n\n.mpp-cards[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 4px 2px;\n}\n\n.mpp-card[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-card);\n padding: 14px 16px;\n}\n\n\n.mpp-card-head[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n.mpp-label[_ngcontent-%COMP%] {\n font-size: 0.95rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mpp-provenance[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n.mpp-prov-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.mpp-dot[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n}\n\n\n.mpp-value-row[_ngcontent-%COMP%] {\n margin: 2px 0 10px;\n}\n\n.mpp-value[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n font-weight: 700;\n line-height: 1.1;\n color: var(--mj-text-primary);\n font-variant-numeric: tabular-nums;\n}\n\n.mpp-value-muted[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n\n.mpp-gauge[_ngcontent-%COMP%] {\n margin-bottom: 4px;\n}\n\n.mpp-gauge-track[_ngcontent-%COMP%] {\n position: relative;\n height: 10px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n.mpp-gauge-fill[_ngcontent-%COMP%] {\n height: 100%;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n}\n\n\n.mpp-band-low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 55%, transparent);\n}\n.mpp-band-mid[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 78%, transparent);\n}\n.mpp-band-high[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.mpp-gauge-scale[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n margin-top: 4px;\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n\n.mpp-drivers[_ngcontent-%COMP%] {\n margin-top: 12px;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n}\n\n.mpp-drivers-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.72rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.mpp-driver[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: minmax(80px, 38%) 1fr;\n align-items: center;\n gap: 10px;\n margin-bottom: 6px;\n}\n\n.mpp-driver-name[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.mpp-driver-bar-track[_ngcontent-%COMP%] {\n display: block;\n height: 7px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n.mpp-driver-bar-fill[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n border-radius: var(--mj-radius-full, 9999px);\n background: color-mix(in srgb, var(--mj-brand-primary) 70%, transparent);\n transition: width 0.3s ease;\n}"] }); }
771
+ } }, dependencies: [i1.MjCollapsiblePanelComponent, i2.JsonPipe, i2.DecimalPipe], styles: ["\n\n\n\n\n.mpp-cards[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 4px 2px;\n}\n\n.mpp-card[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-card);\n padding: 14px 16px;\n}\n\n\n.mpp-card-head[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n.mpp-label[_ngcontent-%COMP%] {\n font-size: 0.95rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mpp-provenance[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n.mpp-prov-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.mpp-dot[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n}\n\n\n.mpp-value-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 2px 0 10px;\n}\n\n\n.mpp-status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 2px 8px;\n font-size: 0.75rem;\n font-weight: 600;\n border-radius: var(--mj-radius-full, 9999px);\n line-height: 1.3;\n}\n\n.mpp-badge-sm[_ngcontent-%COMP%] {\n padding: 1px 6px;\n font-size: 0.7rem;\n}\n\n.mpp-badge-green[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success, #16a34a) 15%, transparent);\n color: var(--mj-status-success, #16a34a);\n}\n\n.mpp-badge-red[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-danger, #dc2626) 15%, transparent);\n color: var(--mj-status-danger, #dc2626);\n}\n\n.mpp-badge-amber[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning, #d97706) 15%, transparent);\n color: var(--mj-status-warning, #d97706);\n}\n\n.mpp-badge-blue[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-info, #2563eb) 15%, transparent);\n color: var(--mj-status-info, #2563eb);\n}\n\n.mpp-badge-gray[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.mpp-pred-cell[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n\n.mpp-value[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n font-weight: 700;\n line-height: 1.1;\n color: var(--mj-text-primary);\n font-variant-numeric: tabular-nums;\n}\n\n.mpp-value-muted[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n\n.mpp-gauge[_ngcontent-%COMP%] {\n margin-bottom: 4px;\n}\n\n.mpp-gauge-track[_ngcontent-%COMP%] {\n position: relative;\n height: 10px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n.mpp-gauge-fill[_ngcontent-%COMP%] {\n height: 100%;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n}\n\n\n.mpp-band-low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 55%, transparent);\n}\n.mpp-band-mid[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 78%, transparent);\n}\n.mpp-band-high[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n\n.mpp-gauge-fill.mpp-color-green[_ngcontent-%COMP%] {\n background: var(--mj-status-success, #16a34a);\n}\n.mpp-gauge-fill.mpp-color-red[_ngcontent-%COMP%] {\n background: var(--mj-status-danger, #dc2626);\n}\n.mpp-gauge-fill.mpp-color-amber[_ngcontent-%COMP%] {\n background: var(--mj-status-warning, #d97706);\n}\n.mpp-gauge-fill.mpp-color-blue[_ngcontent-%COMP%] {\n background: var(--mj-status-info, #2563eb);\n}\n.mpp-gauge-fill.mpp-color-gray[_ngcontent-%COMP%] {\n background: var(--mj-text-muted);\n}\n\n.mpp-gauge-scale[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n margin-top: 4px;\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n\n.mpp-drivers[_ngcontent-%COMP%] {\n margin-top: 12px;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n}\n\n.mpp-drivers-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.72rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.mpp-driver[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: minmax(80px, 38%) 1fr;\n align-items: center;\n gap: 10px;\n margin-bottom: 6px;\n}\n\n.mpp-driver-name[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.mpp-driver-bar-track[_ngcontent-%COMP%] {\n display: block;\n height: 7px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n.mpp-driver-bar-fill[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n border-radius: var(--mj-radius-full, 9999px);\n background: color-mix(in srgb, var(--mj-brand-primary) 70%, transparent);\n transition: width 0.3s ease;\n}\n\n\n.mpp-head-left[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.mpp-card-history-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 3px 8px;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm, 4px);\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.mpp-card-history-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n\n.mpp-history-section[_ngcontent-%COMP%] {\n margin-top: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-card);\n overflow: hidden;\n}\n\n.mpp-history-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 14px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n}\n\n.mpp-history-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.mpp-history-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mpp-history-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.mpp-history-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 6px;\n font-size: 0.7rem;\n font-weight: 600;\n border-radius: 999px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n}\n\n.mpp-history-chevron[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n}\n\n.mpp-history-body[_ngcontent-%COMP%] {\n padding: 12px 14px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.mpp-history-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n padding: 8px 0;\n}\n\n.mpp-history-empty[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n padding: 8px 0;\n}\n\n\n.mpp-model-filters[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.mpp-filter-pill[_ngcontent-%COMP%] {\n padding: 3px 10px;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.mpp-filter-pill[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n border-color: var(--mj-border-hover, var(--mj-brand-primary));\n}\n\n.mpp-filter-pill.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n border-color: var(--mj-brand-primary);\n}\n\n\n.mpp-history-table-wrap[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.mpp-history-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.8rem;\n}\n\n.mpp-history-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n padding: 6px 8px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.mpp-history-table[_ngcontent-%COMP%] th.actions-th[_ngcontent-%COMP%] {\n text-align: right;\n}\n\n.mpp-history-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 8px;\n border-bottom: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n vertical-align: middle;\n}\n\n.mpp-history-row[_ngcontent-%COMP%]:hover td[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-hover);\n}\n\n.mpp-history-row.expanded[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n}\n\n.mpp-col-date[_ngcontent-%COMP%] {\n white-space: nowrap;\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.mpp-col-model[_ngcontent-%COMP%] {\n min-width: 140px;\n}\n\n.mpp-history-model-name[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mpp-history-model-prov[_ngcontent-%COMP%] {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n}\n\n.mpp-col-pred[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n.mpp-history-pred-val[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mpp-history-pred-sub[_ngcontent-%COMP%] {\n margin-left: 4px;\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n}\n\n\n.mpp-status-pill[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 1px 7px;\n font-size: 0.7rem;\n font-weight: 600;\n border-radius: 999px;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.mpp-status-succeeded[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success, #16a34a) 15%, transparent);\n color: var(--mj-status-success, #16a34a);\n}\n\n.mpp-status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-danger, #dc2626) 15%, transparent);\n color: var(--mj-status-danger, #dc2626);\n}\n\n.mpp-status-pending[_ngcontent-%COMP%], \n.mpp-status-skipped[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n\n.mpp-col-actions[_ngcontent-%COMP%] {\n text-align: right;\n white-space: nowrap;\n}\n\n.mpp-action-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 7px;\n font-size: 0.72rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm, 4px);\n cursor: pointer;\n margin-left: 4px;\n transition: all 0.15s ease;\n}\n\n.mpp-action-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n border-color: var(--mj-border-hover, var(--mj-brand-primary));\n}\n\n.mpp-action-drilldown[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.mpp-action-drilldown[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n border-color: var(--mj-brand-primary);\n}\n\n\n.mpp-history-detail-row[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 0;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.mpp-history-detail-pane[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.mpp-detail-subtitle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.72rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n margin-bottom: 6px;\n}\n\n.mpp-detail-error[_ngcontent-%COMP%] {\n font-size: 0.78rem;\n color: var(--mj-status-danger, #dc2626);\n background: color-mix(in srgb, var(--mj-status-danger, #dc2626) 8%, transparent);\n padding: 6px 10px;\n border-radius: var(--mj-radius-sm, 4px);\n}\n\n.mpp-detail-driver-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n max-width: 380px;\n}\n\n.mpp-detail-driver-item[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: minmax(80px, 45%) 1fr;\n align-items: center;\n gap: 8px;\n}\n\n.mpp-detail-payload[_ngcontent-%COMP%] {\n margin-top: 2px;\n}\n\n.mpp-payload-pre[_ngcontent-%COMP%] {\n margin: 0;\n padding: 8px 10px;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.72rem;\n line-height: 1.4;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm, 4px);\n overflow-x: auto;\n max-height: 200px;\n color: var(--mj-text-primary);\n}"] }); }
273
772
  };
274
773
  ModelPredictionPanel = __decorate([
275
774
  RegisterClassEx(BaseFormPanel, {
@@ -285,9 +784,9 @@ ModelPredictionPanel = __decorate([
285
784
  export { ModelPredictionPanel };
286
785
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ModelPredictionPanel, [{
287
786
  type: Component,
288
- args: [{ standalone: false, selector: 'mj-model-prediction-panel', template: "<!--\n Entity-agnostic model-prediction panel. Renders NOTHING unless the current\n record's entity has active scoring bindings (HasPredictions gate). Driven\n entirely by metadata \u2014 no entity-specific or domain-specific markup.\n-->\n@if (HasPredictions) {\n <mj-collapsible-panel\n SectionKey=\"modelPredictions\"\n SectionName=\"Model Predictions\"\n Icon=\"fa-solid fa-wand-magic-sparkles\"\n [Form]=\"FormComponent\"\n [FormContext]=\"FormContext\"\n [BadgeCount]=\"Cards.length\">\n\n <div class=\"mpp-cards\">\n @for (card of Cards; track card.bindingId) {\n <div class=\"mpp-card\">\n\n <!-- Header: label + provenance -->\n <div class=\"mpp-card-head\">\n <div class=\"mpp-label\">{{ card.label }}</div>\n <div class=\"mpp-provenance\">\n <i class=\"fa-solid fa-diagram-project mpp-prov-icon\" aria-hidden=\"true\"></i>\n <span>{{ card.provenance }}</span>\n @if (card.lastScored) {\n <span class=\"mpp-dot\" aria-hidden=\"true\">\u00B7</span>\n <span class=\"mpp-scored\">Scored {{ card.lastScored }}</span>\n }\n </div>\n </div>\n\n <!-- Value -->\n <div class=\"mpp-value-row\">\n <span class=\"mpp-value\" [class.mpp-value-muted]=\"card.displayValue === '\u2014'\">\n {{ card.displayValue }}\n </span>\n </div>\n\n <!-- Probability gauge \u2014 neutral 3-band tercile. No moral direction. -->\n @if (card.isProbability) {\n <div class=\"mpp-gauge\" role=\"img\"\n [attr.aria-label]=\"card.label + ' ' + card.displayValue + ', ' + card.band + ' band'\">\n <div class=\"mpp-gauge-track\">\n <div class=\"mpp-gauge-fill\"\n [class.mpp-band-low]=\"card.band === 'low'\"\n [class.mpp-band-mid]=\"card.band === 'mid'\"\n [class.mpp-band-high]=\"card.band === 'high'\"\n [style.width.%]=\"card.gaugePct\"></div>\n </div>\n <div class=\"mpp-gauge-scale\">\n <span>0%</span>\n <span>50%</span>\n <span>100%</span>\n </div>\n </div>\n }\n\n <!-- Top drivers (feature importance) \u2014 omitted cleanly when unavailable -->\n @if (card.drivers.length > 0) {\n <div class=\"mpp-drivers\">\n <div class=\"mpp-drivers-title\">\n <i class=\"fa-solid fa-ranking-star\" aria-hidden=\"true\"></i>\n Top drivers\n </div>\n @for (driver of card.drivers; track driver.name) {\n <div class=\"mpp-driver\">\n <span class=\"mpp-driver-name\" [title]=\"driver.name\">{{ driver.name }}</span>\n <span class=\"mpp-driver-bar-track\">\n <span class=\"mpp-driver-bar-fill\" [style.width.%]=\"driver.relativePct\"></span>\n </span>\n </div>\n }\n </div>\n }\n\n </div>\n }\n </div>\n\n </mj-collapsible-panel>\n}\n", styles: ["/* Entity-agnostic model-prediction panel.\n Design-token-clean: every color is a --mj-* semantic token. The gauge bands\n are intentionally NEUTRAL \u2014 they encode position on the value axis (low/mid/high)\n via opacity of a single brand color, never green=good / red=bad. */\n\n.mpp-cards {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 4px 2px;\n}\n\n.mpp-card {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-card);\n padding: 14px 16px;\n}\n\n/* ---- Header ---- */\n.mpp-card-head {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n.mpp-label {\n font-size: 0.95rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mpp-provenance {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n.mpp-prov-icon {\n color: var(--mj-brand-primary);\n}\n\n.mpp-dot {\n color: var(--mj-text-disabled);\n}\n\n/* ---- Primary value ---- */\n.mpp-value-row {\n margin: 2px 0 10px;\n}\n\n.mpp-value {\n font-size: 1.75rem;\n font-weight: 700;\n line-height: 1.1;\n color: var(--mj-text-primary);\n font-variant-numeric: tabular-nums;\n}\n\n.mpp-value-muted {\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n/* ---- Gauge (neutral tercile) ---- */\n.mpp-gauge {\n margin-bottom: 4px;\n}\n\n.mpp-gauge-track {\n position: relative;\n height: 10px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n.mpp-gauge-fill {\n height: 100%;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n}\n\n/* Band shading: same brand hue, varied opacity = neutral position cue only. */\n.mpp-band-low {\n background: color-mix(in srgb, var(--mj-brand-primary) 55%, transparent);\n}\n.mpp-band-mid {\n background: color-mix(in srgb, var(--mj-brand-primary) 78%, transparent);\n}\n.mpp-band-high {\n background: var(--mj-brand-primary);\n}\n\n.mpp-gauge-scale {\n display: flex;\n justify-content: space-between;\n margin-top: 4px;\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n/* ---- Drivers ---- */\n.mpp-drivers {\n margin-top: 12px;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n}\n\n.mpp-drivers-title {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.72rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.mpp-driver {\n display: grid;\n grid-template-columns: minmax(80px, 38%) 1fr;\n align-items: center;\n gap: 10px;\n margin-bottom: 6px;\n}\n\n.mpp-driver-name {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.mpp-driver-bar-track {\n display: block;\n height: 7px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n.mpp-driver-bar-fill {\n display: block;\n height: 100%;\n border-radius: var(--mj-radius-full, 9999px);\n background: color-mix(in srgb, var(--mj-brand-primary) 70%, transparent);\n transition: width 0.3s ease;\n}\n"] }]
787
+ args: [{ standalone: false, selector: 'mj-model-prediction-panel', template: "<!--\n Entity-agnostic model-prediction panel. Renders NOTHING unless the current\n record's entity has active scoring bindings or historical prediction runs.\n Driven entirely by metadata \u2014 no entity-specific or domain-specific markup.\n-->\n@if (HasPredictions) {\n <mj-collapsible-panel\n SectionKey=\"modelPredictions\"\n SectionName=\"Model Predictions\"\n Icon=\"fa-solid fa-wand-magic-sparkles\"\n [Form]=\"FormComponent\"\n [FormContext]=\"FormContext\"\n [BadgeCount]=\"Cards.length\">\n\n <!-- Active prediction cards -->\n @if (Cards.length > 0) {\n <div class=\"mpp-cards\">\n @for (card of Cards; track card.BindingId) {\n <div class=\"mpp-card\">\n\n <!-- Header: label + provenance + history button -->\n <div class=\"mpp-card-head\">\n <div class=\"mpp-head-left\">\n <div class=\"mpp-label\">{{ card.Label }}</div>\n <div class=\"mpp-provenance\">\n <i class=\"fa-solid fa-diagram-project mpp-prov-icon\" aria-hidden=\"true\"></i>\n <span>{{ card.Provenance }}</span>\n @if (card.LastScored) {\n <span class=\"mpp-dot\" aria-hidden=\"true\">\u00B7</span>\n <span class=\"mpp-scored\">Scored {{ card.LastScored }}</span>\n }\n </div>\n </div>\n <button type=\"button\" \n class=\"mpp-card-history-btn\" \n (click)=\"OpenHistoryForModel(card.modelId, $event)\" \n title=\"View prediction history for this model\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i> History\n </button>\n </div>\n\n <!-- Value -->\n <div class=\"mpp-value-row\">\n <span class=\"mpp-value\" [class.mpp-value-muted]=\"card.DisplayValue === '\u2014'\">\n {{ card.DisplayValue }}\n </span>\n @if (card.StatusLabel) {\n <span class=\"mpp-status-badge\" [class]=\"'mpp-badge-' + card.BadgeColor\">\n @if (card.BadgeIcon) {\n <i [class]=\"'fa-solid ' + card.BadgeIcon\"></i>\n }\n <span>{{ card.StatusLabel }}</span>\n </span>\n }\n </div>\n\n <!-- Probability gauge \u2014 semantic color matching outcome polarity -->\n @if (card.IsProbability) {\n <div class=\"mpp-gauge\" role=\"img\"\n [attr.aria-label]=\"card.Label + ' ' + card.DisplayValue + (card.StatusLabel ? ', ' + card.StatusLabel : '')\">\n <div class=\"mpp-gauge-track\">\n <div class=\"mpp-gauge-fill\"\n [class.mpp-band-low]=\"card.Band === 'low'\"\n [class.mpp-band-mid]=\"card.Band === 'mid'\"\n [class.mpp-band-high]=\"card.Band === 'high'\"\n [class]=\"'mpp-color-' + card.BadgeColor\"\n [style.width.%]=\"card.GaugePct\"></div>\n </div>\n <div class=\"mpp-gauge-scale\">\n <span>0%</span>\n <span>50%</span>\n <span>100%</span>\n </div>\n </div>\n }\n\n <!-- Top drivers (feature importance) \u2014 omitted cleanly when unavailable -->\n @if (card.Drivers.length > 0) {\n <div class=\"mpp-drivers\">\n <div class=\"mpp-drivers-title\">\n <i class=\"fa-solid fa-ranking-star\" aria-hidden=\"true\"></i>\n Top drivers\n </div>\n @for (driver of card.Drivers; track driver.name) {\n <div class=\"mpp-driver\">\n <span class=\"mpp-driver-name\" [title]=\"driver.name\">{{ driver.name }}</span>\n <span class=\"mpp-driver-bar-track\">\n <span class=\"mpp-driver-bar-fill\" [style.width.%]=\"driver.RelativePct\"></span>\n </span>\n </div>\n }\n </div>\n }\n\n </div>\n }\n </div>\n }\n\n <!-- Prediction History Section -->\n <div class=\"mpp-history-section\">\n <div class=\"mpp-history-header\" (click)=\"ToggleHistorySection()\" role=\"button\" tabindex=\"0\">\n <div class=\"mpp-history-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n <span>Prediction History</span>\n @if (HistoryItems.length > 0) {\n <span class=\"mpp-history-badge\">{{ HistoryItems.length }}</span>\n }\n </div>\n <div class=\"mpp-history-chevron\">\n <i [class]=\"ShowHistorySection ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </div>\n </div>\n\n @if (ShowHistorySection) {\n <div class=\"mpp-history-body\">\n @if (LoadingHistory) {\n <div class=\"mpp-history-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading prediction history\u2026\n </div>\n } @else if (HistoryItems.length === 0) {\n <div class=\"mpp-history-empty\">\n No historical prediction runs recorded for this record yet.\n </div>\n } @else {\n <!-- Multi-model filter tabs if multiple models present -->\n @if (ModelSummaries.length > 1) {\n <div class=\"mpp-model-filters\">\n <button type=\"button\" \n class=\"mpp-filter-pill\" \n [class.active]=\"SelectedModelId === null || SelectedModelId === 'ALL'\"\n (click)=\"SelectModelFilter(null)\">\n All Models ({{ HistoryItems.length }})\n </button>\n @for (mod of ModelSummaries; track mod.modelId) {\n <button type=\"button\" \n class=\"mpp-filter-pill\" \n [class.active]=\"SelectedModelId === mod.modelId\"\n (click)=\"SelectModelFilter(mod.modelId)\">\n {{ mod.ModelName }} ({{ mod.count }})\n </button>\n }\n </div>\n }\n\n <!-- History table -->\n <div class=\"mpp-history-table-wrap\">\n <table class=\"mpp-history-table\">\n <thead>\n <tr>\n <th>Date</th>\n <th>Model</th>\n <th>Prediction</th>\n <th>Status</th>\n <th class=\"actions-th\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (item of FilteredHistory; track item.id) {\n <tr class=\"mpp-history-row\" [class.expanded]=\"ExpandedHistoryItemId === item.id\">\n <td class=\"mpp-col-date\">{{ item.FormattedTime }}</td>\n <td class=\"mpp-col-model\">\n <div class=\"mpp-history-model-name\">{{ item.ModelName }}</div>\n <div class=\"mpp-history-model-prov\">{{ item.Provenance }}</div>\n </td>\n <td class=\"mpp-col-pred\">\n <div class=\"mpp-pred-cell\">\n <span class=\"mpp-history-pred-val\">{{ item.DisplayValue }}</span>\n @if (item.PredictedClass && item.NumericValue != null && item.IsProbability) {\n <span class=\"mpp-history-pred-sub\">({{ (item.NumericValue * 100) | number:'1.0-1' }}%)</span>\n }\n @if (item.StatusLabel) {\n <span class=\"mpp-status-badge mpp-badge-sm\" [class]=\"'mpp-badge-' + item.BadgeColor\">\n @if (item.BadgeIcon) {\n <i [class]=\"'fa-solid ' + item.BadgeIcon\"></i>\n }\n <span>{{ item.StatusLabel }}</span>\n </span>\n }\n </div>\n </td>\n <td class=\"mpp-col-status\">\n <span class=\"mpp-status-pill\" [class]=\"'mpp-status-' + item.status.toLowerCase()\">\n {{ item.status }}\n </span>\n </td>\n <td class=\"mpp-col-actions\">\n <button type=\"button\" \n class=\"mpp-action-btn\"\n (click)=\"ToggleHistoryDetails(item, $event)\" \n [title]=\"ExpandedHistoryItemId === item.id ? 'Hide details' : 'Inspect payload & drivers'\">\n <i [class]=\"ExpandedHistoryItemId === item.id ? 'fa-solid fa-chevron-up' : 'fa-solid fa-code'\"></i>\n {{ ExpandedHistoryItemId === item.id ? 'Close' : 'Inspect' }}\n </button>\n <button type=\"button\" \n class=\"mpp-action-btn mpp-action-drilldown\"\n (click)=\"DrilldownToPredictionRecord(item, $event)\"\n title=\"Open underlying Process Run Detail record in Explorer\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open Row\n </button>\n </td>\n </tr>\n @if (ExpandedHistoryItemId === item.id) {\n <tr class=\"mpp-history-detail-row\">\n <td colspan=\"5\">\n <div class=\"mpp-history-detail-pane\">\n @if (item.ErrorMessage) {\n <div class=\"mpp-detail-error\">\n <strong>Error:</strong> {{ item.ErrorMessage }}\n </div>\n }\n @if (item.Drivers.length > 0) {\n <div class=\"mpp-detail-drivers\">\n <div class=\"mpp-detail-subtitle\"><i class=\"fa-solid fa-ranking-star\"></i> Attributed Drivers</div>\n <div class=\"mpp-detail-driver-list\">\n @for (d of item.Drivers; track d.name) {\n <div class=\"mpp-detail-driver-item\">\n <span class=\"mpp-driver-name\">{{ d.name }}</span>\n <span class=\"mpp-driver-bar-track\">\n <span class=\"mpp-driver-bar-fill\" [style.width.%]=\"d.RelativePct\"></span>\n </span>\n </div>\n }\n </div>\n </div>\n }\n <div class=\"mpp-detail-payload\">\n <div class=\"mpp-detail-subtitle\"><i class=\"fa-solid fa-file-code\"></i> Result Payload</div>\n <pre class=\"mpp-payload-pre\">{{ item.RawPayload | json }}</pre>\n </div>\n </div>\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n }\n </div>\n\n </mj-collapsible-panel>\n}\n", styles: ["/* Entity-agnostic model-prediction panel.\n Design-token-clean: every color is a --mj-* semantic token. The gauge bands\n are intentionally NEUTRAL \u2014 they encode position on the value axis (low/mid/high)\n via opacity of a single brand color, never green=good / red=bad. */\n\n.mpp-cards {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 4px 2px;\n}\n\n.mpp-card {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-card);\n padding: 14px 16px;\n}\n\n/* ---- Header ---- */\n.mpp-card-head {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n.mpp-label {\n font-size: 0.95rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mpp-provenance {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n.mpp-prov-icon {\n color: var(--mj-brand-primary);\n}\n\n.mpp-dot {\n color: var(--mj-text-disabled);\n}\n\n/* ---- Primary value ---- */\n.mpp-value-row {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 2px 0 10px;\n}\n\n/* ---- Status Badge ---- */\n.mpp-status-badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 2px 8px;\n font-size: 0.75rem;\n font-weight: 600;\n border-radius: var(--mj-radius-full, 9999px);\n line-height: 1.3;\n}\n\n.mpp-badge-sm {\n padding: 1px 6px;\n font-size: 0.7rem;\n}\n\n.mpp-badge-green {\n background: color-mix(in srgb, var(--mj-status-success, #16a34a) 15%, transparent);\n color: var(--mj-status-success, #16a34a);\n}\n\n.mpp-badge-red {\n background: color-mix(in srgb, var(--mj-status-danger, #dc2626) 15%, transparent);\n color: var(--mj-status-danger, #dc2626);\n}\n\n.mpp-badge-amber {\n background: color-mix(in srgb, var(--mj-status-warning, #d97706) 15%, transparent);\n color: var(--mj-status-warning, #d97706);\n}\n\n.mpp-badge-blue {\n background: color-mix(in srgb, var(--mj-status-info, #2563eb) 15%, transparent);\n color: var(--mj-status-info, #2563eb);\n}\n\n.mpp-badge-gray {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.mpp-pred-cell {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n\n.mpp-value {\n font-size: 1.75rem;\n font-weight: 700;\n line-height: 1.1;\n color: var(--mj-text-primary);\n font-variant-numeric: tabular-nums;\n}\n\n.mpp-value-muted {\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n/* ---- Gauge (neutral tercile) ---- */\n.mpp-gauge {\n margin-bottom: 4px;\n}\n\n.mpp-gauge-track {\n position: relative;\n height: 10px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n.mpp-gauge-fill {\n height: 100%;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n}\n\n/* Band shading: same brand hue, varied opacity = neutral position cue only. */\n.mpp-band-low {\n background: color-mix(in srgb, var(--mj-brand-primary) 55%, transparent);\n}\n.mpp-band-mid {\n background: color-mix(in srgb, var(--mj-brand-primary) 78%, transparent);\n}\n.mpp-band-high {\n background: var(--mj-brand-primary);\n}\n\n/* Outcome polarity gauge fill colors */\n.mpp-gauge-fill.mpp-color-green {\n background: var(--mj-status-success, #16a34a);\n}\n.mpp-gauge-fill.mpp-color-red {\n background: var(--mj-status-danger, #dc2626);\n}\n.mpp-gauge-fill.mpp-color-amber {\n background: var(--mj-status-warning, #d97706);\n}\n.mpp-gauge-fill.mpp-color-blue {\n background: var(--mj-status-info, #2563eb);\n}\n.mpp-gauge-fill.mpp-color-gray {\n background: var(--mj-text-muted);\n}\n\n.mpp-gauge-scale {\n display: flex;\n justify-content: space-between;\n margin-top: 4px;\n font-size: 0.68rem;\n color: var(--mj-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n/* ---- Drivers ---- */\n.mpp-drivers {\n margin-top: 12px;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n}\n\n.mpp-drivers-title {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.72rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.mpp-driver {\n display: grid;\n grid-template-columns: minmax(80px, 38%) 1fr;\n align-items: center;\n gap: 10px;\n margin-bottom: 6px;\n}\n\n.mpp-driver-name {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.mpp-driver-bar-track {\n display: block;\n height: 7px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n.mpp-driver-bar-fill {\n display: block;\n height: 100%;\n border-radius: var(--mj-radius-full, 9999px);\n background: color-mix(in srgb, var(--mj-brand-primary) 70%, transparent);\n transition: width 0.3s ease;\n}\n\n/* ---- Card History Action Button ---- */\n.mpp-head-left {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.mpp-card-history-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 3px 8px;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm, 4px);\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.mpp-card-history-btn:hover {\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n/* ---- Prediction History Section ---- */\n.mpp-history-section {\n margin-top: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-card);\n overflow: hidden;\n}\n\n.mpp-history-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 14px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n}\n\n.mpp-history-header:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.mpp-history-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mpp-history-title i {\n color: var(--mj-brand-primary);\n}\n\n.mpp-history-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 6px;\n font-size: 0.7rem;\n font-weight: 600;\n border-radius: 999px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n}\n\n.mpp-history-chevron {\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n}\n\n.mpp-history-body {\n padding: 12px 14px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.mpp-history-loading {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n padding: 8px 0;\n}\n\n.mpp-history-empty {\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n padding: 8px 0;\n}\n\n/* ---- Multi-Model Filter Tabs ---- */\n.mpp-model-filters {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.mpp-filter-pill {\n padding: 3px 10px;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.mpp-filter-pill:hover {\n color: var(--mj-text-primary);\n border-color: var(--mj-border-hover, var(--mj-brand-primary));\n}\n\n.mpp-filter-pill.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n border-color: var(--mj-brand-primary);\n}\n\n/* ---- History Table ---- */\n.mpp-history-table-wrap {\n overflow-x: auto;\n}\n\n.mpp-history-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.8rem;\n}\n\n.mpp-history-table th {\n text-align: left;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n padding: 6px 8px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.mpp-history-table th.actions-th {\n text-align: right;\n}\n\n.mpp-history-table td {\n padding: 8px;\n border-bottom: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n vertical-align: middle;\n}\n\n.mpp-history-row:hover td {\n background: var(--mj-bg-surface-hover);\n}\n\n.mpp-history-row.expanded td {\n background: var(--mj-bg-surface-sunken);\n}\n\n.mpp-col-date {\n white-space: nowrap;\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.mpp-col-model {\n min-width: 140px;\n}\n\n.mpp-history-model-name {\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mpp-history-model-prov {\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n}\n\n.mpp-col-pred {\n white-space: nowrap;\n}\n\n.mpp-history-pred-val {\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mpp-history-pred-sub {\n margin-left: 4px;\n font-size: 0.72rem;\n color: var(--mj-text-muted);\n}\n\n/* Status Pill */\n.mpp-status-pill {\n display: inline-block;\n padding: 1px 7px;\n font-size: 0.7rem;\n font-weight: 600;\n border-radius: 999px;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.mpp-status-succeeded {\n background: color-mix(in srgb, var(--mj-status-success, #16a34a) 15%, transparent);\n color: var(--mj-status-success, #16a34a);\n}\n\n.mpp-status-failed {\n background: color-mix(in srgb, var(--mj-status-danger, #dc2626) 15%, transparent);\n color: var(--mj-status-danger, #dc2626);\n}\n\n.mpp-status-pending,\n.mpp-status-skipped {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n/* Actions in History Row */\n.mpp-col-actions {\n text-align: right;\n white-space: nowrap;\n}\n\n.mpp-action-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 7px;\n font-size: 0.72rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm, 4px);\n cursor: pointer;\n margin-left: 4px;\n transition: all 0.15s ease;\n}\n\n.mpp-action-btn:hover {\n color: var(--mj-text-primary);\n border-color: var(--mj-border-hover, var(--mj-brand-primary));\n}\n\n.mpp-action-drilldown {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.mpp-action-drilldown:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n border-color: var(--mj-brand-primary);\n}\n\n/* Inspection Drawer */\n.mpp-history-detail-row td {\n padding: 0;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.mpp-history-detail-pane {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.mpp-detail-subtitle {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.72rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n margin-bottom: 6px;\n}\n\n.mpp-detail-error {\n font-size: 0.78rem;\n color: var(--mj-status-danger, #dc2626);\n background: color-mix(in srgb, var(--mj-status-danger, #dc2626) 8%, transparent);\n padding: 6px 10px;\n border-radius: var(--mj-radius-sm, 4px);\n}\n\n.mpp-detail-driver-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n max-width: 380px;\n}\n\n.mpp-detail-driver-item {\n display: grid;\n grid-template-columns: minmax(80px, 45%) 1fr;\n align-items: center;\n gap: 8px;\n}\n\n.mpp-detail-payload {\n margin-top: 2px;\n}\n\n.mpp-payload-pre {\n margin: 0;\n padding: 8px 10px;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.72rem;\n line-height: 1.4;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm, 4px);\n overflow-x: auto;\n max-height: 200px;\n color: var(--mj-text-primary);\n}\n"] }]
289
788
  }], null, null); })();
290
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ModelPredictionPanel, { className: "ModelPredictionPanel", filePath: "src/lib/panels/model-predictions/model-prediction.panel.ts", lineNumber: 80 }); })();
789
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ModelPredictionPanel, { className: "ModelPredictionPanel", filePath: "src/lib/panels/model-predictions/model-prediction.panel.ts", lineNumber: 101 }); })();
291
790
  /** Tree-shake guard — call this from the consuming module's loader. */
292
791
  export function LoadModelPredictionPanel() { }
293
792
  //# sourceMappingURL=model-prediction.panel.js.map