@memberjunction/ng-core-entity-forms 6.2.0-edge.2 → 6.2.0-edge.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-header.panel.d.ts.map +1 -1
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-header.panel.js +9 -5
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-header.panel.js.map +1 -1
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-overview.panel.d.ts +4 -0
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-overview.panel.d.ts.map +1 -1
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-overview.panel.js +67 -36
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-overview.panel.js.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts +5 -0
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js +13 -9
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +1 -0
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
- package/dist/lib/custom/Companies/company-header.panel.d.ts.map +1 -1
- package/dist/lib/custom/Companies/company-header.panel.js +9 -5
- package/dist/lib/custom/Companies/company-header.panel.js.map +1 -1
- package/dist/lib/custom/Companies/company-overview.panel.d.ts +4 -0
- package/dist/lib/custom/Companies/company-overview.panel.d.ts.map +1 -1
- package/dist/lib/custom/Companies/company-overview.panel.js +68 -37
- package/dist/lib/custom/Companies/company-overview.panel.js.map +1 -1
- package/dist/lib/custom/Conversations/conversation-header.panel.d.ts.map +1 -1
- package/dist/lib/custom/Conversations/conversation-header.panel.js +9 -5
- package/dist/lib/custom/Conversations/conversation-header.panel.js.map +1 -1
- package/dist/lib/custom/Conversations/conversation-overview.panel.d.ts +25 -4
- package/dist/lib/custom/Conversations/conversation-overview.panel.d.ts.map +1 -1
- package/dist/lib/custom/Conversations/conversation-overview.panel.js +212 -90
- package/dist/lib/custom/Conversations/conversation-overview.panel.js.map +1 -1
- package/dist/lib/custom/Employees/employee-header.panel.d.ts.map +1 -1
- package/dist/lib/custom/Employees/employee-header.panel.js +9 -5
- package/dist/lib/custom/Employees/employee-header.panel.js.map +1 -1
- package/dist/lib/custom/Employees/employee-overview.panel.d.ts +4 -0
- package/dist/lib/custom/Employees/employee-overview.panel.d.ts.map +1 -1
- package/dist/lib/custom/Employees/employee-overview.panel.js +68 -37
- package/dist/lib/custom/Employees/employee-overview.panel.js.map +1 -1
- package/dist/lib/custom/Entities/entity-form.component.d.ts +8 -0
- package/dist/lib/custom/Entities/entity-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Entities/entity-form.component.js +19 -4
- package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
- package/dist/lib/custom/Files/file-form.component.d.ts +5 -5
- package/dist/lib/custom/Files/file-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Files/file-form.component.js +227 -157
- package/dist/lib/custom/Files/file-form.component.js.map +1 -1
- package/dist/lib/custom/Files/file-form.logic.d.ts +24 -0
- package/dist/lib/custom/Files/file-form.logic.d.ts.map +1 -0
- package/dist/lib/custom/Files/file-form.logic.js +57 -0
- package/dist/lib/custom/Files/file-form.logic.js.map +1 -0
- package/dist/lib/custom/HierarchyPanels/hierarchy-form-panels.d.ts.map +1 -1
- package/dist/lib/custom/HierarchyPanels/hierarchy-form-panels.js +60 -45
- package/dist/lib/custom/HierarchyPanels/hierarchy-form-panels.js.map +1 -1
- package/dist/lib/custom/Lists/list-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Lists/list-form.component.js +4 -2
- package/dist/lib/custom/Lists/list-form.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.js +3 -2
- package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
- package/dist/lib/custom/Rubrics/rubric-form.component.js +1 -1
- package/dist/lib/custom/Rubrics/rubric-form.component.js.map +1 -1
- package/dist/lib/custom/SearchScopes/searchscope-form.component.d.ts.map +1 -1
- package/dist/lib/custom/SearchScopes/searchscope-form.component.js +1 -0
- package/dist/lib/custom/SearchScopes/searchscope-form.component.js.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.js +3 -2
- package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +1 -0
- package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.js +1 -0
- package/dist/lib/custom/Tests/test-run-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.js +1 -0
- package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-run-form.component.js +1 -0
- package/dist/lib/custom/Tests/test-suite-run-form.component.js.map +1 -1
- package/dist/lib/custom/Users/user-header.panel.d.ts.map +1 -1
- package/dist/lib/custom/Users/user-header.panel.js +9 -5
- package/dist/lib/custom/Users/user-header.panel.js.map +1 -1
- package/dist/lib/custom/Users/user-overview.panel.d.ts +4 -0
- package/dist/lib/custom/Users/user-overview.panel.d.ts.map +1 -1
- package/dist/lib/custom/Users/user-overview.panel.js +64 -33
- package/dist/lib/custom/Users/user-overview.panel.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.d.ts +34 -0
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.d.ts.map +1 -0
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.js +33 -0
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.js.map +1 -0
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts +3 -0
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +261 -242
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +1 -0
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts +35 -34
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +6 -2
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js +98 -44
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentArtifactType/mjaiagentartifacttype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentArtifactType/mjaiagentartifacttype.form.component.js +5 -9
- package/dist/lib/generated/Entities/MJAIAgentArtifactType/mjaiagentartifacttype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentNoteType/mjaiagentnotetype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentNoteType/mjaiagentnotetype.form.component.js +15 -18
- package/dist/lib/generated/Entities/MJAIAgentNoteType/mjaiagentnotetype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentPrompt/mjaiagentprompt.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentPrompt/mjaiagentprompt.form.component.js +5 -9
- package/dist/lib/generated/Entities/MJAIAgentPrompt/mjaiagentprompt.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.js +27 -9
- package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentSessionBridge/mjaiagentsessionbridge.form.component.js +17 -15
- package/dist/lib/generated/Entities/MJAIAgentSessionBridge/mjaiagentsessionbridge.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIBridgeProvider/mjaibridgeprovider.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIBridgeProvider/mjaibridgeprovider.form.component.js +25 -7
- package/dist/lib/generated/Entities/MJAIBridgeProvider/mjaibridgeprovider.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIResultCache/mjairesultcache.form.component.js +12 -14
- package/dist/lib/generated/Entities/MJAIResultCache/mjairesultcache.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCommunicationLog/mjcommunicationlog.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJCommunicationLog/mjcommunicationlog.form.component.js +5 -9
- package/dist/lib/generated/Entities/MJCommunicationLog/mjcommunicationlog.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCompanyIntegrationRunAPILog/mjcompanyintegrationrunapilog.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJCompanyIntegrationRunAPILog/mjcompanyintegrationrunapilog.form.component.js +5 -9
- package/dist/lib/generated/Entities/MJCompanyIntegrationRunAPILog/mjcompanyintegrationrunapilog.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJComponent/mjcomponent.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJComponent/mjcomponent.form.component.js +26 -8
- package/dist/lib/generated/Entities/MJComponent/mjcomponent.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentItemAttribute/mjcontentitemattribute.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentItemAttribute/mjcontentitemattribute.form.component.js +4 -7
- package/dist/lib/generated/Entities/MJContentItemAttribute/mjcontentitemattribute.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentSourceParam/mjcontentsourceparam.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentSourceParam/mjcontentsourceparam.form.component.js +4 -7
- package/dist/lib/generated/Entities/MJContentSourceParam/mjcontentsourceparam.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js +49 -13
- package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJConversationArtifactPermission/mjconversationartifactpermission.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJConversationArtifactPermission/mjconversationartifactpermission.form.component.js +5 -9
- package/dist/lib/generated/Entities/MJConversationArtifactPermission/mjconversationartifactpermission.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJConversationBranch/mjconversationbranch.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJConversationBranch/mjconversationbranch.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJConversationBranch/mjconversationbranch.form.component.js +111 -0
- package/dist/lib/generated/Entities/MJConversationBranch/mjconversationbranch.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.js +73 -75
- package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js +34 -16
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEmployeeRole/mjemployeerole.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEmployeeRole/mjemployeerole.form.component.js +5 -9
- package/dist/lib/generated/Entities/MJEmployeeRole/mjemployeerole.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +169 -97
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityCommunicationField/mjentitycommunicationfield.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityCommunicationField/mjentitycommunicationfield.form.component.js +8 -11
- package/dist/lib/generated/Entities/MJEntityCommunicationField/mjentitycommunicationfield.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityDocumentType/mjentitydocumenttype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityDocumentType/mjentitydocumenttype.form.component.js +15 -18
- package/dist/lib/generated/Entities/MJEntityDocumentType/mjentitydocumenttype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityFormContribution/mjentityformcontribution.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJEntityFormContribution/mjentityformcontribution.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJEntityFormContribution/mjentityformcontribution.form.component.js +148 -0
- package/dist/lib/generated/Entities/MJEntityFormContribution/mjentityformcontribution.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJEnvironment/mjenvironment.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEnvironment/mjenvironment.form.component.js +53 -56
- package/dist/lib/generated/Entities/MJEnvironment/mjenvironment.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJInteraction/mjinteraction.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJInteraction/mjinteraction.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJInteraction/mjinteraction.form.component.js +161 -0
- package/dist/lib/generated/Entities/MJInteraction/mjinteraction.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJInteractionEvent/mjinteractionevent.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJInteractionEvent/mjinteractionevent.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJInteractionEvent/mjinteractionevent.form.component.js +78 -0
- package/dist/lib/generated/Entities/MJInteractionEvent/mjinteractionevent.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJInteractionLink/mjinteractionlink.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJInteractionLink/mjinteractionlink.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJInteractionLink/mjinteractionlink.form.component.js +68 -0
- package/dist/lib/generated/Entities/MJInteractionLink/mjinteractionlink.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJInteractionOffer/mjinteractionoffer.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJInteractionOffer/mjinteractionoffer.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJInteractionOffer/mjinteractionoffer.form.component.js +100 -0
- package/dist/lib/generated/Entities/MJInteractionOffer/mjinteractionoffer.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMeeting/mjmeeting.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMeeting/mjmeeting.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMeeting/mjmeeting.form.component.js +119 -0
- package/dist/lib/generated/Entities/MJMeeting/mjmeeting.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMeetingParticipant/mjmeetingparticipant.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMeetingParticipant/mjmeetingparticipant.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMeetingParticipant/mjmeetingparticipant.form.component.js +92 -0
- package/dist/lib/generated/Entities/MJMeetingParticipant/mjmeetingparticipant.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJNumberPool/mjnumberpool.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJNumberPool/mjnumberpool.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJNumberPool/mjnumberpool.form.component.js +87 -0
- package/dist/lib/generated/Entities/MJNumberPool/mjnumberpool.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJPhoneNumber/mjphonenumber.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJPhoneNumber/mjphonenumber.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJPhoneNumber/mjphonenumber.form.component.js +129 -0
- package/dist/lib/generated/Entities/MJPhoneNumber/mjphonenumber.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJQueryPermission/mjquerypermission.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJQueryPermission/mjquerypermission.form.component.js +5 -9
- package/dist/lib/generated/Entities/MJQueryPermission/mjquerypermission.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRecommendationItem/mjrecommendationitem.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJRecommendationItem/mjrecommendationitem.form.component.js +8 -11
- package/dist/lib/generated/Entities/MJRecommendationItem/mjrecommendationitem.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJResourceType/mjresourcetype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJResourceType/mjresourcetype.form.component.js +36 -40
- package/dist/lib/generated/Entities/MJResourceType/mjresourcetype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js +39 -21
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRowLevelSecurityFilter/mjrowlevelsecurityfilter.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJRowLevelSecurityFilter/mjrowlevelsecurityfilter.form.component.js +45 -48
- package/dist/lib/generated/Entities/MJRowLevelSecurityFilter/mjrowlevelsecurityfilter.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJScopedNotificationConfig/mjscopednotificationconfig.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJScopedNotificationConfig/mjscopednotificationconfig.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJScopedNotificationConfig/mjscopednotificationconfig.form.component.js +106 -0
- package/dist/lib/generated/Entities/MJScopedNotificationConfig/mjscopednotificationconfig.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJTemplateContentType/mjtemplatecontenttype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTemplateContentType/mjtemplatecontenttype.form.component.js +15 -18
- package/dist/lib/generated/Entities/MJTemplateContentType/mjtemplatecontenttype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +822 -676
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJUserNotificationType/mjusernotificationtype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJUserNotificationType/mjusernotificationtype.form.component.js +24 -6
- package/dist/lib/generated/Entities/MJUserNotificationType/mjusernotificationtype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJVersionLabelItem/mjversionlabelitem.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJVersionLabelItem/mjversionlabelitem.form.component.js +5 -9
- package/dist/lib/generated/Entities/MJVersionLabelItem/mjversionlabelitem.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJWorkQueueDeduplication/mjworkqueuededuplication.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJWorkQueueDeduplication/mjworkqueuededuplication.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueDeduplication/mjworkqueuededuplication.form.component.js +64 -0
- package/dist/lib/generated/Entities/MJWorkQueueDeduplication/mjworkqueuededuplication.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueDelivery/mjworkqueuedelivery.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJWorkQueueDelivery/mjworkqueuedelivery.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueDelivery/mjworkqueuedelivery.form.component.js +94 -0
- package/dist/lib/generated/Entities/MJWorkQueueDelivery/mjworkqueuedelivery.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueMessage/mjworkqueuemessage.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJWorkQueueMessage/mjworkqueuemessage.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueMessage/mjworkqueuemessage.form.component.js +91 -0
- package/dist/lib/generated/Entities/MJWorkQueueMessage/mjworkqueuemessage.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueSubscription/mjworkqueuesubscription.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJWorkQueueSubscription/mjworkqueuesubscription.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueSubscription/mjworkqueuesubscription.form.component.js +105 -0
- package/dist/lib/generated/Entities/MJWorkQueueSubscription/mjworkqueuesubscription.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueTopic/mjworkqueuetopic.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJWorkQueueTopic/mjworkqueuetopic.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueTopic/mjworkqueuetopic.form.component.js +129 -0
- package/dist/lib/generated/Entities/MJWorkQueueTopic/mjworkqueuetopic.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueTransport/mjworkqueuetransport.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJWorkQueueTransport/mjworkqueuetransport.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJWorkQueueTransport/mjworkqueuetransport.form.component.js +85 -0
- package/dist/lib/generated/Entities/MJWorkQueueTransport/mjworkqueuetransport.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJWorkspace/mjworkspace.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJWorkspace/mjworkspace.form.component.js +17 -20
- package/dist/lib/generated/Entities/MJWorkspace/mjworkspace.form.component.js.map +1 -1
- package/dist/lib/generated/generated-forms.module.d.ts +448 -431
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +63 -12
- package/dist/lib/generated/generated-forms.module.js.map +1 -1
- package/dist/lib/panels/ai-agents/agent-realtime.panel.d.ts +7 -1
- package/dist/lib/panels/ai-agents/agent-realtime.panel.d.ts.map +1 -1
- package/dist/lib/panels/ai-agents/agent-realtime.panel.js +89 -43
- package/dist/lib/panels/ai-agents/agent-realtime.panel.js.map +1 -1
- package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.js +3 -3
- package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.js.map +1 -1
- package/dist/lib/panels/content-sources/tag-pipeline-configuration.panel.js +5 -5
- package/dist/lib/panels/content-sources/tag-pipeline-configuration.panel.js.map +1 -1
- package/dist/lib/panels/content-sources/website-crawler-settings.panel.js +4 -4
- package/dist/lib/panels/content-sources/website-crawler-settings.panel.js.map +1 -1
- package/dist/lib/panels/form-chrome/entity-relationship-form-role.panel.js +3 -3
- package/dist/lib/panels/form-chrome/entity-relationship-form-role.panel.js.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.panel.js +4 -4
- package/dist/lib/panels/model-predictions/model-prediction.panel.js.map +1 -1
- package/package.json +48 -47
|
@@ -405,7 +405,7 @@ function ModelPredictionPanel_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
|
405
405
|
i0.ɵɵelementEnd()();
|
|
406
406
|
} if (rf & 2) {
|
|
407
407
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
408
|
-
i0.ɵɵproperty("Form", ctx_r3.FormComponent)("FormContext", ctx_r3.FormContext)("BadgeCount", ctx_r3.Cards.length);
|
|
408
|
+
i0.ɵɵproperty("Order", ctx_r3.DisplayOrder)("Form", ctx_r3.FormComponent)("FormContext", ctx_r3.FormContext)("BadgeCount", ctx_r3.Cards.length);
|
|
409
409
|
i0.ɵɵadvance();
|
|
410
410
|
i0.ɵɵconditional(ctx_r3.Cards.length > 0 ? 1 : -1);
|
|
411
411
|
i0.ɵɵadvance(7);
|
|
@@ -764,8 +764,8 @@ let ModelPredictionPanel = class ModelPredictionPanel extends BaseFormPanel {
|
|
|
764
764
|
return this.FormComponent?.ProviderToUse?.CurrentUser ?? new Metadata().CurrentUser;
|
|
765
765
|
}
|
|
766
766
|
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵModelPredictionPanel_BaseFactory; return function ModelPredictionPanel_Factory(__ngFactoryType__) { return (ɵModelPredictionPanel_BaseFactory || (ɵModelPredictionPanel_BaseFactory = i0.ɵɵgetInheritedFactory(ModelPredictionPanel)))(__ngFactoryType__ || ModelPredictionPanel); }; })(); }
|
|
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,
|
|
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, "Order", "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, 9, "mj-collapsible-panel", 0);
|
|
769
769
|
} if (rf & 2) {
|
|
770
770
|
i0.ɵɵconditional(ctx.HasPredictions ? 0 : -1);
|
|
771
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}"] }); }
|
|
@@ -784,7 +784,7 @@ ModelPredictionPanel = __decorate([
|
|
|
784
784
|
export { ModelPredictionPanel };
|
|
785
785
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ModelPredictionPanel, [{
|
|
786
786
|
type: Component,
|
|
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"] }]
|
|
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 [Order]=\"DisplayOrder\"\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"] }]
|
|
788
788
|
}], null, null); })();
|
|
789
789
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ModelPredictionPanel, { className: "ModelPredictionPanel", filePath: "src/lib/panels/model-predictions/model-prediction.panel.ts", lineNumber: 101 }); })();
|
|
790
790
|
/** Tree-shake guard — call this from the consuming module's loader. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-prediction.panel.js","sourceRoot":"","sources":["../../../../src/lib/panels/model-predictions/model-prediction.panel.ts","../../../../src/lib/panels/model-predictions/model-prediction.panel.html"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, OnInit, inject } from '@angular/core';\nimport { RegisterClassEx } from '@memberjunction/global';\nimport { BaseFormPanel } from '@memberjunction/ng-base-forms';\nimport { CompositeKey, LogError, Metadata, RunView } from '@memberjunction/core';\nimport { MJMLModelEntity, MJMLModelScoringBindingEntity, MJProcessRunDetailEntity } from '@memberjunction/core-entities';\nimport {\n OutcomeBand,\n resolveOutcomeConfig,\n resolveOutcomeStyle,\n resolveScoreBand,\n} from '@memberjunction/predictive-studio-core';\nimport {\n ModelHistorySummary,\n PredictionBand,\n PredictionDriver,\n PredictionHistoryItem,\n BandFor,\n FilterHistoryByModel,\n FormatLastScored,\n FormatValue,\n GaugePct,\n GetDistinctModelsFromHistory,\n ParseDrivers,\n ParseHistoryItem,\n ResolveLabel,\n ToNumber,\n ValueKind,\n} from './model-prediction.logic';\n\n/**\n * A fully-resolved, entity-agnostic prediction card view-model. One per active\n * scoring binding on the current record's entity.\n */\nexport interface PredictionCard {\n /** Binding ID — used as the @for track key. */\n BindingId: string;\n /** Model ID — used to cross-link with prediction history. */\n modelId: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined\n /** Human label for the prediction (model target → bound column → fallback). */\n Label: string;\n /** True when the model is a 0–1 probability we can render as a gauge. */\n IsProbability: boolean;\n /** True for regression models showing a raw numeric value. */\n IsNumeric: boolean;\n /** True for classification models showing a class label. */\n IsClass: boolean;\n /** Pre-formatted primary value string (\"72%\", \"1,240.5\", \"Renewing\", \"—\"). */\n DisplayValue: string;\n /** 0–100 fill for the probability gauge (only meaningful when isProbability). */\n GaugePct: number;\n /** Neutral band for the gauge segment styling (only meaningful when isProbability). */\n Band: PredictionBand | null;\n /** Resolved semantic status band from outcomeConfig */\n StatusBand: OutcomeBand | null;\n /** Human-readable status label (e.g. \"Low Risk\", \"High\") */\n StatusLabel: string | null;\n /** Semantic badge color: 'green' | 'amber' | 'red' | 'blue' | 'gray' */\n BadgeColor: 'green' | 'amber' | 'red' | 'blue' | 'gray';\n /** FontAwesome icon class (e.g. 'fa-circle-check', 'fa-triangle-exclamation') */\n BadgeIcon: string | null;\n /** Top feature-importance drivers, or empty when unavailable. */\n Drivers: PredictionDriver[];\n /** Provenance: \"Pipeline Name v3\". */\n Provenance: string;\n /** \"Last scored\" timestamp string, or null when unavailable. */\n LastScored: string | null;\n}\n\n/**\n * Model Prediction panel — an **entity-agnostic** form panel that surfaces any\n * predictions a trained ML model has written onto the current record via a\n * `MJ: ML Model Scoring Bindings` row.\n *\n * It registers against the `'*'` wildcard entity, so it mounts on EVERY entity\n * form — but renders **nothing** unless the record's entity has at least one\n * active scoring binding. The 99% of forms with no model see an invisible,\n * one-RunView-cheap panel.\n *\n * Driven entirely by metadata (bindings + models); there is no entity-specific,\n * domain-specific, or \"renewal/risk\"-specific logic anywhere. Members/renewal\n * is only ever a test example.\n *\n * Self-mounts via the `after-fields` slot. Reusable as a plain component too\n * (composition) by binding `[Record]` + `[FormComponent]`.\n */\n@RegisterClassEx(BaseFormPanel, {\n key: 'model-predictions:model-prediction',\n skipNullKeyWarning: true,\n metadata: {\n entity: '*', // wildcard — appears on every entity form, self-hides when N/A\n slot: 'after-fields',\n sortKey: 40,\n },\n})\n@Component({\n standalone: false,\n selector: 'mj-model-prediction-panel',\n templateUrl: './model-prediction.panel.html',\n styleUrls: ['./model-prediction.panel.css'],\n})\nexport class ModelPredictionPanel extends BaseFormPanel implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n\n /** The resolved cards to render. Empty → panel renders nothing. */\n public Cards: PredictionCard[] = [];\n /** True once the binding lookup has completed (success or empty). */\n public Loaded = false;\n /** Resolved models by ID for lineage and history decoration. */\n public ModelsById: Map<string, MJMLModelEntity> = new Map();\n\n /** @deprecated Use {@link ModelsById}. */\n public get modelsById(): Map<string, MJMLModelEntity> {\n return this.ModelsById;\n }\n /** @deprecated Use {@link ModelsById}. */\n public set modelsById(value: Map<string, MJMLModelEntity>) {\n this.ModelsById = value;\n }\n /** Historical prediction runs for this record across models. */\n public HistoryItems: PredictionHistoryItem[] = [];\n /** Loading flag for historical predictions lookup. */\n public LoadingHistory = false;\n /** Whether the prediction history section is expanded in the template. */\n public ShowHistorySection = false;\n /** Selected model ID for history filtering (null = all models). */\n public SelectedModelId: string | null = null;\n /** Expanded history item ID for in-place inspection of payload & drivers. */\n public ExpandedHistoryItemId: string | null = null;\n /** Entity-ID we last loaded cards for, to avoid redundant lookups. */\n private loadedForEntityId: string | null = null;\n\n public async ngOnInit(): Promise<void> {\n await this.loadCards();\n }\n\n /** True when there is at least one card or history item to show — gates the whole template. */\n public get HasPredictions(): boolean {\n return this.Cards.length > 0 || this.HistoryItems.length > 0;\n }\n\n /** Filtered history items based on currently selected model. */\n public get FilteredHistory(): PredictionHistoryItem[] {\n return FilterHistoryByModel(this.HistoryItems, this.SelectedModelId);\n }\n\n /** Distinct models in prediction history with counts. */\n public get ModelSummaries(): ModelHistorySummary[] {\n return GetDistinctModelsFromHistory(this.HistoryItems);\n }\n\n /**\n * Look up active scoring bindings for THIS record's entity and build a card\n * per binding. Idempotent + cheap: a single RunView (cached by the server),\n * skipped entirely when we've already loaded for this entity.\n */\n private async loadCards(): Promise<void> {\n const entityId = this.Record?.EntityInfo?.ID ?? null;\n if (!entityId) {\n this.Loaded = true;\n return;\n }\n if (entityId === this.loadedForEntityId) {\n return; // already resolved for this entity\n }\n this.loadedForEntityId = entityId;\n\n try {\n const bindings = await this.loadBindingsForEntity(entityId);\n if (bindings.length === 0) {\n this.Cards = [];\n } else {\n const models = await this.loadModelsForBindings(bindings);\n this.ModelsById = models;\n this.Cards = this.buildCards(bindings, models);\n }\n // Preload history in the background for this record\n void this.LoadHistory();\n } catch (e) {\n LogError(`[ModelPredictionPanel] Failed to load predictions: ${e instanceof Error ? e.message : String(e)}`);\n this.Cards = [];\n } finally {\n this.Loaded = true;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Load historical prediction runs for this specific record across all models.\n */\n public async LoadHistory(): Promise<void> {\n const entityId = this.Record?.EntityInfo?.ID ?? null;\n const pkVal = this.Record?.FirstPrimaryKey?.Value; // first-pk-ok: Target entity single PK value for RecordID filter\n const recordId = pkVal != null ? String(pkVal) : '';\n if (!entityId || !recordId) {\n this.HistoryItems = [];\n this.cdr.markForCheck();\n return;\n }\n\n this.LoadingHistory = true;\n this.cdr.markForCheck();\n try {\n const rv = this.runView();\n const result = await rv.RunView<MJProcessRunDetailEntity>(\n {\n EntityName: 'MJ: Process Run Details',\n ExtraFilter: `EntityID='${entityId}' AND RecordID='${recordId}'`,\n OrderBy: 'CompletedAt DESC',\n MaxRows: 50,\n ResultType: 'entity_object',\n },\n this.contextUser(),\n );\n\n if (!result.Success) {\n LogError(`[ModelPredictionPanel] Failed to load prediction history: ${result.ErrorMessage}`);\n this.HistoryItems = [];\n return;\n }\n\n const rawDetails = result.Results ?? [];\n if (rawDetails.length === 0) {\n this.HistoryItems = [];\n return;\n }\n\n // Ensure any models referenced in historical payloads are loaded\n await this.ensureModelsLoadedForHistory(rawDetails);\n\n this.HistoryItems = rawDetails.map(d => ParseHistoryItem({\n ID: d.ID,\n ProcessRunID: d.ProcessRunID,\n Status: d.Status,\n CompletedAt: d.CompletedAt,\n ResultPayload: d.ResultPayload,\n ErrorMessage: d.ErrorMessage,\n }, this.ModelsById));\n } catch (e) {\n LogError(`[ModelPredictionPanel] Error loading prediction history: ${e instanceof Error ? e.message : String(e)}`);\n this.HistoryItems = [];\n } finally {\n this.LoadingHistory = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Select a model ID filter for history (null = all models).\n */\n public SelectModelFilter(modelId: string | null): void {\n this.SelectedModelId = modelId;\n this.cdr.markForCheck();\n }\n\n /**\n * Toggle the prediction history section.\n */\n public ToggleHistorySection(): void {\n this.ShowHistorySection = !this.ShowHistorySection;\n this.cdr.markForCheck();\n if (this.ShowHistorySection && this.HistoryItems.length === 0 && !this.LoadingHistory) {\n void this.LoadHistory();\n }\n }\n\n /**\n * Focus prediction history on a specific model from a card action.\n */\n public OpenHistoryForModel(modelId: string, event?: MouseEvent): void {\n event?.stopPropagation();\n this.ShowHistorySection = true;\n this.SelectedModelId = modelId;\n this.cdr.markForCheck();\n if (this.HistoryItems.length === 0 && !this.LoadingHistory) {\n void this.LoadHistory();\n }\n }\n\n /**\n * Toggle inline inspection drawer for a prediction history row.\n */\n public ToggleHistoryDetails(item: PredictionHistoryItem, event?: MouseEvent): void {\n event?.stopPropagation();\n this.ExpandedHistoryItemId = this.ExpandedHistoryItemId === item.id ? null : item.id;\n this.cdr.markForCheck();\n }\n\n /**\n * Drill down into the underlying MJ: Process Run Details record in Explorer.\n */\n public DrilldownToPredictionRecord(item: PredictionHistoryItem, event?: MouseEvent): void {\n event?.stopPropagation();\n if (this.FormComponent?.OnFormNavigate) {\n this.FormComponent.OnFormNavigate({\n Kind: 'record',\n EntityName: 'MJ: Process Run Details',\n PrimaryKey: CompositeKey.FromID(item.id),\n OpenInNewTab: event ? (event.ctrlKey || event.metaKey) : true,\n });\n }\n }\n\n /** Active scoring bindings whose target entity is the current record's entity. */\n private async loadBindingsForEntity(entityId: string): Promise<MJMLModelScoringBindingEntity[]> {\n const rv = this.runView();\n const result = await rv.RunView<MJMLModelScoringBindingEntity>(\n {\n EntityName: 'MJ: ML Model Scoring Bindings',\n ExtraFilter: `TargetEntityID='${entityId}' AND TargetColumn IS NOT NULL`,\n OrderBy: '__mj_CreatedAt ASC',\n ResultType: 'entity_object',\n },\n this.contextUser(),\n );\n if (!result.Success) {\n LogError(`[ModelPredictionPanel] Binding lookup failed: ${result.ErrorMessage}`);\n return [];\n }\n return result.Results ?? [];\n }\n\n /** Load the distinct models referenced by the bindings, keyed by model ID. */\n private async loadModelsForBindings(\n bindings: MJMLModelScoringBindingEntity[],\n ): Promise<Map<string, MJMLModelEntity>> {\n const modelIds = [...new Set(bindings.map(b => b.MLModelID).filter((id): id is string => !!id))];\n const byId = new Map<string, MJMLModelEntity>();\n if (modelIds.length === 0) {\n return byId;\n }\n const inList = modelIds.map(id => `'${id}'`).join(',');\n const rv = this.runView();\n const result = await rv.RunView<MJMLModelEntity>(\n {\n EntityName: 'MJ: ML Models',\n ExtraFilter: `ID IN (${inList})`,\n ResultType: 'entity_object',\n },\n this.contextUser(),\n );\n if (!result.Success) {\n LogError(`[ModelPredictionPanel] Model lookup failed: ${result.ErrorMessage}`);\n return byId;\n }\n for (const model of result.Results ?? []) {\n byId.set(model.ID, model);\n }\n return byId;\n }\n\n /** Ensure models found in process run detail payloads are loaded for metadata decoration. */\n private async ensureModelsLoadedForHistory(details: MJProcessRunDetailEntity[]): Promise<void> {\n const missingModelIds: string[] = [];\n for (const d of details) {\n if (!d.ResultPayload) continue;\n try {\n const parsed: unknown = JSON.parse(d.ResultPayload);\n if (parsed && typeof parsed === 'object') {\n const rec = parsed as Record<string, unknown>;\n const out = (rec['output'] && typeof rec['output'] === 'object' ? rec['output'] : rec) as Record<string, unknown>;\n const mid = typeof out['modelId'] === 'string' ? out['modelId'] : null;\n if (mid && !this.ModelsById.has(mid) && !missingModelIds.includes(mid)) {\n missingModelIds.push(mid);\n }\n }\n } catch {\n // Ignore parse errors\n }\n }\n\n if (missingModelIds.length === 0) return;\n\n const inList = missingModelIds.map(id => `'${id}'`).join(',');\n const rv = this.runView();\n const result = await rv.RunView<MJMLModelEntity>(\n {\n EntityName: 'MJ: ML Models',\n ExtraFilter: `ID IN (${inList})`,\n ResultType: 'entity_object',\n },\n this.contextUser(),\n );\n if (result.Success && result.Results) {\n for (const model of result.Results) {\n this.ModelsById.set(model.ID, model);\n }\n }\n }\n\n /** Map each binding (+ its model) to a display card. Skips bindings whose model is missing. */\n private buildCards(\n bindings: MJMLModelScoringBindingEntity[],\n models: Map<string, MJMLModelEntity>,\n ): PredictionCard[] {\n const cards: PredictionCard[] = [];\n for (const binding of bindings) {\n const model = binding.MLModelID ? models.get(binding.MLModelID) : undefined;\n if (!model) {\n continue;\n }\n cards.push(this.buildCard(binding, model));\n }\n return cards;\n }\n\n /** Build one card from a binding + model + the record's bound-column value. */\n private buildCard(binding: MJMLModelScoringBindingEntity, model: MJMLModelEntity): PredictionCard {\n // The column name is data-driven (from the binding), so reading it\n // dynamically via Get() is the legitimate use of the dynamic accessor.\n const rawValue = binding.TargetColumn ? this.Record.Get(binding.TargetColumn) : null;\n const numeric = ToNumber(rawValue);\n const kind = ValueKind(model.ProblemType, numeric);\n\n const outcomeConfig = resolveOutcomeConfig({\n Lineage: model.Lineage,\n TargetVariable: model.TargetVariable,\n ProblemType: model.ProblemType,\n });\n\n let statusBand: OutcomeBand | null = null;\n let badgeColor: 'green' | 'amber' | 'red' | 'blue' | 'gray' = 'gray';\n let badgeIcon: string | null = null;\n let statusLabel: string | null = null;\n\n if (numeric != null) {\n statusBand = resolveScoreBand(numeric, outcomeConfig);\n if (statusBand) {\n badgeColor = statusBand.BadgeColor;\n badgeIcon = statusBand.Icon ?? null;\n statusLabel = statusBand.Label;\n }\n } else if (kind === 'class' && typeof rawValue === 'string') {\n const style = resolveOutcomeStyle(rawValue, outcomeConfig);\n badgeColor = style.BadgeColor;\n badgeIcon = style.Icon ?? null;\n statusLabel = style.DisplayLabel ?? rawValue;\n }\n\n return {\n BindingId: binding.ID,\n modelId: model.ID,\n Label: ResolveLabel(model.TargetVariable, binding.TargetColumn),\n IsProbability: kind === 'probability',\n IsNumeric: kind === 'numeric',\n IsClass: kind === 'class',\n DisplayValue: FormatValue(rawValue, numeric, kind),\n GaugePct: kind === 'probability' && numeric != null ? GaugePct(numeric) : 0,\n Band: kind === 'probability' && numeric != null ? BandFor(numeric) : null,\n StatusBand: statusBand,\n StatusLabel: statusLabel,\n BadgeColor: badgeColor,\n BadgeIcon: badgeIcon,\n Drivers: ParseDrivers(model.FeatureImportance),\n Provenance: `${model.Pipeline} v${model.Version}`,\n LastScored: FormatLastScored(binding.LastScoredAt),\n };\n }\n\n /** RunView scoped to the form's provider when available (multi-provider safe). */\n private runView(): RunView {\n const provider = this.FormComponent?.ProviderToUse;\n return provider ? RunView.FromMetadataProvider(provider) : new RunView();\n }\n\n /** Context user for server-side scoping — the form provider's current user. */\n private contextUser() {\n return this.FormComponent?.ProviderToUse?.CurrentUser ?? new Metadata().CurrentUser;\n }\n}\n\n/** Tree-shake guard — call this from the consuming module's loader. */\nexport function LoadModelPredictionPanel(): void { /* no-op marker */ }\n","<!--\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 — 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\">·</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 === '—'\">\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 — 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) — 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…\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"]}
|
|
1
|
+
{"version":3,"file":"model-prediction.panel.js","sourceRoot":"","sources":["../../../../src/lib/panels/model-predictions/model-prediction.panel.ts","../../../../src/lib/panels/model-predictions/model-prediction.panel.html"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, OnInit, inject } from '@angular/core';\nimport { RegisterClassEx } from '@memberjunction/global';\nimport { BaseFormPanel } from '@memberjunction/ng-base-forms';\nimport { CompositeKey, LogError, Metadata, RunView } from '@memberjunction/core';\nimport { MJMLModelEntity, MJMLModelScoringBindingEntity, MJProcessRunDetailEntity } from '@memberjunction/core-entities';\nimport {\n OutcomeBand,\n resolveOutcomeConfig,\n resolveOutcomeStyle,\n resolveScoreBand,\n} from '@memberjunction/predictive-studio-core';\nimport {\n ModelHistorySummary,\n PredictionBand,\n PredictionDriver,\n PredictionHistoryItem,\n BandFor,\n FilterHistoryByModel,\n FormatLastScored,\n FormatValue,\n GaugePct,\n GetDistinctModelsFromHistory,\n ParseDrivers,\n ParseHistoryItem,\n ResolveLabel,\n ToNumber,\n ValueKind,\n} from './model-prediction.logic';\n\n/**\n * A fully-resolved, entity-agnostic prediction card view-model. One per active\n * scoring binding on the current record's entity.\n */\nexport interface PredictionCard {\n /** Binding ID — used as the @for track key. */\n BindingId: string;\n /** Model ID — used to cross-link with prediction history. */\n modelId: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined\n /** Human label for the prediction (model target → bound column → fallback). */\n Label: string;\n /** True when the model is a 0–1 probability we can render as a gauge. */\n IsProbability: boolean;\n /** True for regression models showing a raw numeric value. */\n IsNumeric: boolean;\n /** True for classification models showing a class label. */\n IsClass: boolean;\n /** Pre-formatted primary value string (\"72%\", \"1,240.5\", \"Renewing\", \"—\"). */\n DisplayValue: string;\n /** 0–100 fill for the probability gauge (only meaningful when isProbability). */\n GaugePct: number;\n /** Neutral band for the gauge segment styling (only meaningful when isProbability). */\n Band: PredictionBand | null;\n /** Resolved semantic status band from outcomeConfig */\n StatusBand: OutcomeBand | null;\n /** Human-readable status label (e.g. \"Low Risk\", \"High\") */\n StatusLabel: string | null;\n /** Semantic badge color: 'green' | 'amber' | 'red' | 'blue' | 'gray' */\n BadgeColor: 'green' | 'amber' | 'red' | 'blue' | 'gray';\n /** FontAwesome icon class (e.g. 'fa-circle-check', 'fa-triangle-exclamation') */\n BadgeIcon: string | null;\n /** Top feature-importance drivers, or empty when unavailable. */\n Drivers: PredictionDriver[];\n /** Provenance: \"Pipeline Name v3\". */\n Provenance: string;\n /** \"Last scored\" timestamp string, or null when unavailable. */\n LastScored: string | null;\n}\n\n/**\n * Model Prediction panel — an **entity-agnostic** form panel that surfaces any\n * predictions a trained ML model has written onto the current record via a\n * `MJ: ML Model Scoring Bindings` row.\n *\n * It registers against the `'*'` wildcard entity, so it mounts on EVERY entity\n * form — but renders **nothing** unless the record's entity has at least one\n * active scoring binding. The 99% of forms with no model see an invisible,\n * one-RunView-cheap panel.\n *\n * Driven entirely by metadata (bindings + models); there is no entity-specific,\n * domain-specific, or \"renewal/risk\"-specific logic anywhere. Members/renewal\n * is only ever a test example.\n *\n * Self-mounts via the `after-fields` slot. Reusable as a plain component too\n * (composition) by binding `[Record]` + `[FormComponent]`.\n */\n@RegisterClassEx(BaseFormPanel, {\n key: 'model-predictions:model-prediction',\n skipNullKeyWarning: true,\n metadata: {\n entity: '*', // wildcard — appears on every entity form, self-hides when N/A\n slot: 'after-fields',\n sortKey: 40,\n },\n})\n@Component({\n standalone: false,\n selector: 'mj-model-prediction-panel',\n templateUrl: './model-prediction.panel.html',\n styleUrls: ['./model-prediction.panel.css'],\n})\nexport class ModelPredictionPanel extends BaseFormPanel implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n\n /** The resolved cards to render. Empty → panel renders nothing. */\n public Cards: PredictionCard[] = [];\n /** True once the binding lookup has completed (success or empty). */\n public Loaded = false;\n /** Resolved models by ID for lineage and history decoration. */\n public ModelsById: Map<string, MJMLModelEntity> = new Map();\n\n /** @deprecated Use {@link ModelsById}. */\n public get modelsById(): Map<string, MJMLModelEntity> {\n return this.ModelsById;\n }\n /** @deprecated Use {@link ModelsById}. */\n public set modelsById(value: Map<string, MJMLModelEntity>) {\n this.ModelsById = value;\n }\n /** Historical prediction runs for this record across models. */\n public HistoryItems: PredictionHistoryItem[] = [];\n /** Loading flag for historical predictions lookup. */\n public LoadingHistory = false;\n /** Whether the prediction history section is expanded in the template. */\n public ShowHistorySection = false;\n /** Selected model ID for history filtering (null = all models). */\n public SelectedModelId: string | null = null;\n /** Expanded history item ID for in-place inspection of payload & drivers. */\n public ExpandedHistoryItemId: string | null = null;\n /** Entity-ID we last loaded cards for, to avoid redundant lookups. */\n private loadedForEntityId: string | null = null;\n\n public async ngOnInit(): Promise<void> {\n await this.loadCards();\n }\n\n /** True when there is at least one card or history item to show — gates the whole template. */\n public get HasPredictions(): boolean {\n return this.Cards.length > 0 || this.HistoryItems.length > 0;\n }\n\n /** Filtered history items based on currently selected model. */\n public get FilteredHistory(): PredictionHistoryItem[] {\n return FilterHistoryByModel(this.HistoryItems, this.SelectedModelId);\n }\n\n /** Distinct models in prediction history with counts. */\n public get ModelSummaries(): ModelHistorySummary[] {\n return GetDistinctModelsFromHistory(this.HistoryItems);\n }\n\n /**\n * Look up active scoring bindings for THIS record's entity and build a card\n * per binding. Idempotent + cheap: a single RunView (cached by the server),\n * skipped entirely when we've already loaded for this entity.\n */\n private async loadCards(): Promise<void> {\n const entityId = this.Record?.EntityInfo?.ID ?? null;\n if (!entityId) {\n this.Loaded = true;\n return;\n }\n if (entityId === this.loadedForEntityId) {\n return; // already resolved for this entity\n }\n this.loadedForEntityId = entityId;\n\n try {\n const bindings = await this.loadBindingsForEntity(entityId);\n if (bindings.length === 0) {\n this.Cards = [];\n } else {\n const models = await this.loadModelsForBindings(bindings);\n this.ModelsById = models;\n this.Cards = this.buildCards(bindings, models);\n }\n // Preload history in the background for this record\n void this.LoadHistory();\n } catch (e) {\n LogError(`[ModelPredictionPanel] Failed to load predictions: ${e instanceof Error ? e.message : String(e)}`);\n this.Cards = [];\n } finally {\n this.Loaded = true;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Load historical prediction runs for this specific record across all models.\n */\n public async LoadHistory(): Promise<void> {\n const entityId = this.Record?.EntityInfo?.ID ?? null;\n const pkVal = this.Record?.FirstPrimaryKey?.Value; // first-pk-ok: Target entity single PK value for RecordID filter\n const recordId = pkVal != null ? String(pkVal) : '';\n if (!entityId || !recordId) {\n this.HistoryItems = [];\n this.cdr.markForCheck();\n return;\n }\n\n this.LoadingHistory = true;\n this.cdr.markForCheck();\n try {\n const rv = this.runView();\n const result = await rv.RunView<MJProcessRunDetailEntity>(\n {\n EntityName: 'MJ: Process Run Details',\n ExtraFilter: `EntityID='${entityId}' AND RecordID='${recordId}'`,\n OrderBy: 'CompletedAt DESC',\n MaxRows: 50,\n ResultType: 'entity_object',\n },\n this.contextUser(),\n );\n\n if (!result.Success) {\n LogError(`[ModelPredictionPanel] Failed to load prediction history: ${result.ErrorMessage}`);\n this.HistoryItems = [];\n return;\n }\n\n const rawDetails = result.Results ?? [];\n if (rawDetails.length === 0) {\n this.HistoryItems = [];\n return;\n }\n\n // Ensure any models referenced in historical payloads are loaded\n await this.ensureModelsLoadedForHistory(rawDetails);\n\n this.HistoryItems = rawDetails.map(d => ParseHistoryItem({\n ID: d.ID,\n ProcessRunID: d.ProcessRunID,\n Status: d.Status,\n CompletedAt: d.CompletedAt,\n ResultPayload: d.ResultPayload,\n ErrorMessage: d.ErrorMessage,\n }, this.ModelsById));\n } catch (e) {\n LogError(`[ModelPredictionPanel] Error loading prediction history: ${e instanceof Error ? e.message : String(e)}`);\n this.HistoryItems = [];\n } finally {\n this.LoadingHistory = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Select a model ID filter for history (null = all models).\n */\n public SelectModelFilter(modelId: string | null): void {\n this.SelectedModelId = modelId;\n this.cdr.markForCheck();\n }\n\n /**\n * Toggle the prediction history section.\n */\n public ToggleHistorySection(): void {\n this.ShowHistorySection = !this.ShowHistorySection;\n this.cdr.markForCheck();\n if (this.ShowHistorySection && this.HistoryItems.length === 0 && !this.LoadingHistory) {\n void this.LoadHistory();\n }\n }\n\n /**\n * Focus prediction history on a specific model from a card action.\n */\n public OpenHistoryForModel(modelId: string, event?: MouseEvent): void {\n event?.stopPropagation();\n this.ShowHistorySection = true;\n this.SelectedModelId = modelId;\n this.cdr.markForCheck();\n if (this.HistoryItems.length === 0 && !this.LoadingHistory) {\n void this.LoadHistory();\n }\n }\n\n /**\n * Toggle inline inspection drawer for a prediction history row.\n */\n public ToggleHistoryDetails(item: PredictionHistoryItem, event?: MouseEvent): void {\n event?.stopPropagation();\n this.ExpandedHistoryItemId = this.ExpandedHistoryItemId === item.id ? null : item.id;\n this.cdr.markForCheck();\n }\n\n /**\n * Drill down into the underlying MJ: Process Run Details record in Explorer.\n */\n public DrilldownToPredictionRecord(item: PredictionHistoryItem, event?: MouseEvent): void {\n event?.stopPropagation();\n if (this.FormComponent?.OnFormNavigate) {\n this.FormComponent.OnFormNavigate({\n Kind: 'record',\n EntityName: 'MJ: Process Run Details',\n PrimaryKey: CompositeKey.FromID(item.id),\n OpenInNewTab: event ? (event.ctrlKey || event.metaKey) : true,\n });\n }\n }\n\n /** Active scoring bindings whose target entity is the current record's entity. */\n private async loadBindingsForEntity(entityId: string): Promise<MJMLModelScoringBindingEntity[]> {\n const rv = this.runView();\n const result = await rv.RunView<MJMLModelScoringBindingEntity>(\n {\n EntityName: 'MJ: ML Model Scoring Bindings',\n ExtraFilter: `TargetEntityID='${entityId}' AND TargetColumn IS NOT NULL`,\n OrderBy: '__mj_CreatedAt ASC',\n ResultType: 'entity_object',\n },\n this.contextUser(),\n );\n if (!result.Success) {\n LogError(`[ModelPredictionPanel] Binding lookup failed: ${result.ErrorMessage}`);\n return [];\n }\n return result.Results ?? [];\n }\n\n /** Load the distinct models referenced by the bindings, keyed by model ID. */\n private async loadModelsForBindings(\n bindings: MJMLModelScoringBindingEntity[],\n ): Promise<Map<string, MJMLModelEntity>> {\n const modelIds = [...new Set(bindings.map(b => b.MLModelID).filter((id): id is string => !!id))];\n const byId = new Map<string, MJMLModelEntity>();\n if (modelIds.length === 0) {\n return byId;\n }\n const inList = modelIds.map(id => `'${id}'`).join(',');\n const rv = this.runView();\n const result = await rv.RunView<MJMLModelEntity>(\n {\n EntityName: 'MJ: ML Models',\n ExtraFilter: `ID IN (${inList})`,\n ResultType: 'entity_object',\n },\n this.contextUser(),\n );\n if (!result.Success) {\n LogError(`[ModelPredictionPanel] Model lookup failed: ${result.ErrorMessage}`);\n return byId;\n }\n for (const model of result.Results ?? []) {\n byId.set(model.ID, model);\n }\n return byId;\n }\n\n /** Ensure models found in process run detail payloads are loaded for metadata decoration. */\n private async ensureModelsLoadedForHistory(details: MJProcessRunDetailEntity[]): Promise<void> {\n const missingModelIds: string[] = [];\n for (const d of details) {\n if (!d.ResultPayload) continue;\n try {\n const parsed: unknown = JSON.parse(d.ResultPayload);\n if (parsed && typeof parsed === 'object') {\n const rec = parsed as Record<string, unknown>;\n const out = (rec['output'] && typeof rec['output'] === 'object' ? rec['output'] : rec) as Record<string, unknown>;\n const mid = typeof out['modelId'] === 'string' ? out['modelId'] : null;\n if (mid && !this.ModelsById.has(mid) && !missingModelIds.includes(mid)) {\n missingModelIds.push(mid);\n }\n }\n } catch {\n // Ignore parse errors\n }\n }\n\n if (missingModelIds.length === 0) return;\n\n const inList = missingModelIds.map(id => `'${id}'`).join(',');\n const rv = this.runView();\n const result = await rv.RunView<MJMLModelEntity>(\n {\n EntityName: 'MJ: ML Models',\n ExtraFilter: `ID IN (${inList})`,\n ResultType: 'entity_object',\n },\n this.contextUser(),\n );\n if (result.Success && result.Results) {\n for (const model of result.Results) {\n this.ModelsById.set(model.ID, model);\n }\n }\n }\n\n /** Map each binding (+ its model) to a display card. Skips bindings whose model is missing. */\n private buildCards(\n bindings: MJMLModelScoringBindingEntity[],\n models: Map<string, MJMLModelEntity>,\n ): PredictionCard[] {\n const cards: PredictionCard[] = [];\n for (const binding of bindings) {\n const model = binding.MLModelID ? models.get(binding.MLModelID) : undefined;\n if (!model) {\n continue;\n }\n cards.push(this.buildCard(binding, model));\n }\n return cards;\n }\n\n /** Build one card from a binding + model + the record's bound-column value. */\n private buildCard(binding: MJMLModelScoringBindingEntity, model: MJMLModelEntity): PredictionCard {\n // The column name is data-driven (from the binding), so reading it\n // dynamically via Get() is the legitimate use of the dynamic accessor.\n const rawValue = binding.TargetColumn ? this.Record.Get(binding.TargetColumn) : null;\n const numeric = ToNumber(rawValue);\n const kind = ValueKind(model.ProblemType, numeric);\n\n const outcomeConfig = resolveOutcomeConfig({\n Lineage: model.Lineage,\n TargetVariable: model.TargetVariable,\n ProblemType: model.ProblemType,\n });\n\n let statusBand: OutcomeBand | null = null;\n let badgeColor: 'green' | 'amber' | 'red' | 'blue' | 'gray' = 'gray';\n let badgeIcon: string | null = null;\n let statusLabel: string | null = null;\n\n if (numeric != null) {\n statusBand = resolveScoreBand(numeric, outcomeConfig);\n if (statusBand) {\n badgeColor = statusBand.BadgeColor;\n badgeIcon = statusBand.Icon ?? null;\n statusLabel = statusBand.Label;\n }\n } else if (kind === 'class' && typeof rawValue === 'string') {\n const style = resolveOutcomeStyle(rawValue, outcomeConfig);\n badgeColor = style.BadgeColor;\n badgeIcon = style.Icon ?? null;\n statusLabel = style.DisplayLabel ?? rawValue;\n }\n\n return {\n BindingId: binding.ID,\n modelId: model.ID,\n Label: ResolveLabel(model.TargetVariable, binding.TargetColumn),\n IsProbability: kind === 'probability',\n IsNumeric: kind === 'numeric',\n IsClass: kind === 'class',\n DisplayValue: FormatValue(rawValue, numeric, kind),\n GaugePct: kind === 'probability' && numeric != null ? GaugePct(numeric) : 0,\n Band: kind === 'probability' && numeric != null ? BandFor(numeric) : null,\n StatusBand: statusBand,\n StatusLabel: statusLabel,\n BadgeColor: badgeColor,\n BadgeIcon: badgeIcon,\n Drivers: ParseDrivers(model.FeatureImportance),\n Provenance: `${model.Pipeline} v${model.Version}`,\n LastScored: FormatLastScored(binding.LastScoredAt),\n };\n }\n\n /** RunView scoped to the form's provider when available (multi-provider safe). */\n private runView(): RunView {\n const provider = this.FormComponent?.ProviderToUse;\n return provider ? RunView.FromMetadataProvider(provider) : new RunView();\n }\n\n /** Context user for server-side scoping — the form provider's current user. */\n private contextUser() {\n return this.FormComponent?.ProviderToUse?.CurrentUser ?? new Metadata().CurrentUser;\n }\n}\n\n/** Tree-shake guard — call this from the consuming module's loader. */\nexport function LoadModelPredictionPanel(): void { /* no-op marker */ }\n","<!--\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 — no entity-specific or domain-specific markup.\n-->\n@if (HasPredictions) {\n <mj-collapsible-panel\n SectionKey=\"modelPredictions\"\n [Order]=\"DisplayOrder\"\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\">·</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 === '—'\">\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 — 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) — 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…\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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-core-entity-forms",
|
|
3
|
-
"version": "6.2.0-edge.
|
|
3
|
+
"version": "6.2.0-edge.4",
|
|
4
4
|
"description": "MemberJunction Core Entity Angular Forms",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@angular/compiler": "21.2.22",
|
|
15
15
|
"@angular/compiler-cli": "21.2.22",
|
|
16
|
-
"@memberjunction/ng-test-utils": "6.2.0-edge.
|
|
16
|
+
"@memberjunction/ng-test-utils": "6.2.0-edge.4"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"@angular/cdk": "^21.2.14",
|
|
@@ -25,51 +25,52 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@codemirror/language": "^6.12.4",
|
|
27
27
|
"@codemirror/language-data": "^6.5.2",
|
|
28
|
-
"@memberjunction/actions-base": "6.2.0-edge.
|
|
29
|
-
"@memberjunction/ai": "6.2.0-edge.
|
|
30
|
-
"@memberjunction/ai-core-plus": "6.2.0-edge.
|
|
31
|
-
"@memberjunction/ai-engine-base": "6.2.0-edge.
|
|
32
|
-
"@memberjunction/core": "6.2.0-edge.
|
|
33
|
-
"@memberjunction/core-entities": "6.2.0-edge.
|
|
34
|
-
"@memberjunction/feature-pipelines": "6.2.0-edge.
|
|
35
|
-
"@memberjunction/global": "6.2.0-edge.
|
|
36
|
-
"@memberjunction/graphql-dataprovider": "6.2.0-edge.
|
|
37
|
-
"@memberjunction/ng-action-gallery": "6.2.0-edge.
|
|
38
|
-
"@memberjunction/ng-actions": "6.2.0-edge.
|
|
39
|
-
"@memberjunction/ng-agents": "6.2.0-edge.
|
|
40
|
-
"@memberjunction/ng-
|
|
41
|
-
"@memberjunction/ng-
|
|
42
|
-
"@memberjunction/ng-base-
|
|
43
|
-
"@memberjunction/ng-base-
|
|
44
|
-
"@memberjunction/ng-
|
|
45
|
-
"@memberjunction/ng-
|
|
46
|
-
"@memberjunction/ng-
|
|
47
|
-
"@memberjunction/ng-entity-
|
|
48
|
-
"@memberjunction/ng-
|
|
49
|
-
"@memberjunction/ng-
|
|
50
|
-
"@memberjunction/ng-
|
|
51
|
-
"@memberjunction/ng-
|
|
52
|
-
"@memberjunction/ng-
|
|
53
|
-
"@memberjunction/ng-
|
|
54
|
-
"@memberjunction/ng-
|
|
55
|
-
"@memberjunction/ng-
|
|
56
|
-
"@memberjunction/ng-record-
|
|
57
|
-
"@memberjunction/ng-
|
|
58
|
-
"@memberjunction/ng-
|
|
59
|
-
"@memberjunction/ng-
|
|
60
|
-
"@memberjunction/ng-
|
|
61
|
-
"@memberjunction/ng-shared
|
|
62
|
-
"@memberjunction/ng-
|
|
63
|
-
"@memberjunction/ng-
|
|
64
|
-
"@memberjunction/ng-
|
|
65
|
-
"@memberjunction/ng-
|
|
66
|
-
"@memberjunction/ng-
|
|
67
|
-
"@memberjunction/ng-
|
|
68
|
-
"@memberjunction/ng-
|
|
69
|
-
"@memberjunction/
|
|
70
|
-
"@memberjunction/
|
|
71
|
-
"@memberjunction/
|
|
72
|
-
"@memberjunction/
|
|
28
|
+
"@memberjunction/actions-base": "6.2.0-edge.4",
|
|
29
|
+
"@memberjunction/ai": "6.2.0-edge.4",
|
|
30
|
+
"@memberjunction/ai-core-plus": "6.2.0-edge.4",
|
|
31
|
+
"@memberjunction/ai-engine-base": "6.2.0-edge.4",
|
|
32
|
+
"@memberjunction/core": "6.2.0-edge.4",
|
|
33
|
+
"@memberjunction/core-entities": "6.2.0-edge.4",
|
|
34
|
+
"@memberjunction/feature-pipelines": "6.2.0-edge.4",
|
|
35
|
+
"@memberjunction/global": "6.2.0-edge.4",
|
|
36
|
+
"@memberjunction/graphql-dataprovider": "6.2.0-edge.4",
|
|
37
|
+
"@memberjunction/ng-action-gallery": "6.2.0-edge.4",
|
|
38
|
+
"@memberjunction/ng-actions": "6.2.0-edge.4",
|
|
39
|
+
"@memberjunction/ng-agents": "6.2.0-edge.4",
|
|
40
|
+
"@memberjunction/ng-artifacts": "6.2.0-edge.4",
|
|
41
|
+
"@memberjunction/ng-ai-test-harness": "6.2.0-edge.4",
|
|
42
|
+
"@memberjunction/ng-base-application": "6.2.0-edge.4",
|
|
43
|
+
"@memberjunction/ng-base-forms": "6.2.0-edge.4",
|
|
44
|
+
"@memberjunction/ng-base-types": "6.2.0-edge.4",
|
|
45
|
+
"@memberjunction/ng-code-editor": "6.2.0-edge.4",
|
|
46
|
+
"@memberjunction/ng-deep-diff": "6.2.0-edge.4",
|
|
47
|
+
"@memberjunction/ng-entity-relationship-diagram": "6.2.0-edge.4",
|
|
48
|
+
"@memberjunction/ng-entity-viewer": "6.2.0-edge.4",
|
|
49
|
+
"@memberjunction/ng-flow-editor": "6.2.0-edge.4",
|
|
50
|
+
"@memberjunction/ng-hierarchy-tree": "6.2.0-edge.4",
|
|
51
|
+
"@memberjunction/ng-join-grid": "6.2.0-edge.4",
|
|
52
|
+
"@memberjunction/ng-link-directives": "6.2.0-edge.4",
|
|
53
|
+
"@memberjunction/ng-list-management": "6.2.0-edge.4",
|
|
54
|
+
"@memberjunction/ng-markdown": "6.2.0-edge.4",
|
|
55
|
+
"@memberjunction/ng-notifications": "6.2.0-edge.4",
|
|
56
|
+
"@memberjunction/ng-record-clone": "6.2.0-edge.4",
|
|
57
|
+
"@memberjunction/ng-record-process-studio": "6.2.0-edge.4",
|
|
58
|
+
"@memberjunction/ng-rubrics": "6.2.0-edge.4",
|
|
59
|
+
"@memberjunction/ng-resource-permissions": "6.2.0-edge.4",
|
|
60
|
+
"@memberjunction/ng-search": "6.2.0-edge.4",
|
|
61
|
+
"@memberjunction/ng-shared": "6.2.0-edge.4",
|
|
62
|
+
"@memberjunction/ng-shared-generic": "6.2.0-edge.4",
|
|
63
|
+
"@memberjunction/ng-tabstrip": "6.2.0-edge.4",
|
|
64
|
+
"@memberjunction/ng-task-graph-editor": "6.2.0-edge.4",
|
|
65
|
+
"@memberjunction/ng-testing": "6.2.0-edge.4",
|
|
66
|
+
"@memberjunction/ng-timeline": "6.2.0-edge.4",
|
|
67
|
+
"@memberjunction/ng-trees": "6.2.0-edge.4",
|
|
68
|
+
"@memberjunction/ng-ui-components": "6.2.0-edge.4",
|
|
69
|
+
"@memberjunction/ng-versions": "6.2.0-edge.4",
|
|
70
|
+
"@memberjunction/predictive-studio-core": "6.2.0-edge.4",
|
|
71
|
+
"@memberjunction/record-cloning-base": "6.2.0-edge.4",
|
|
72
|
+
"@memberjunction/rubrics-base": "6.2.0-edge.4",
|
|
73
|
+
"@memberjunction/templates-base-types": "6.2.0-edge.4",
|
|
73
74
|
"@types/d3": "^7.4.3",
|
|
74
75
|
"ag-grid-angular": "^35.0.1",
|
|
75
76
|
"ag-grid-community": "^35.0.1",
|