@memberjunction/ng-core-entity-forms 6.2.0-edge.4 → 6.2.0-edge.6
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/AIAgentSessions/ai-agent-session-form.component.d.ts +2 -0
- package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js +103 -95
- package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts +13 -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 +37 -17
- 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 +9 -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 +193 -178
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
- package/dist/lib/custom/AIPromptRuns/prompt-run-data-capture-note.component.d.ts +48 -0
- package/dist/lib/custom/AIPromptRuns/prompt-run-data-capture-note.component.d.ts.map +1 -0
- package/dist/lib/custom/AIPromptRuns/prompt-run-data-capture-note.component.js +195 -0
- package/dist/lib/custom/AIPromptRuns/prompt-run-data-capture-note.component.js.map +1 -0
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts +2 -0
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +345 -323
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.d.ts +2 -0
- package/dist/lib/custom/Actions/action-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.js +29 -11
- package/dist/lib/custom/Actions/action-form.component.js.map +1 -1
- package/dist/lib/custom/EntityActions/entityaction.form.component.d.ts +2 -0
- package/dist/lib/custom/EntityActions/entityaction.form.component.d.ts.map +1 -1
- package/dist/lib/custom/EntityActions/entityaction.form.component.js +2 -0
- package/dist/lib/custom/EntityActions/entityaction.form.component.js.map +1 -1
- package/dist/lib/custom/MLModels/ml-model-view-models.d.ts +11 -4
- package/dist/lib/custom/MLModels/ml-model-view-models.d.ts.map +1 -1
- package/dist/lib/custom/MLModels/ml-model-view-models.js +14 -0
- package/dist/lib/custom/MLModels/ml-model-view-models.js.map +1 -1
- package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts +15 -0
- package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts.map +1 -1
- package/dist/lib/custom/MLModels/ps-model-detail.component.js +186 -92
- package/dist/lib/custom/MLModels/ps-model-detail.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.d.ts +2 -0
- package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.js +2 -0
- package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
- package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts.map +1 -1
- package/dist/lib/custom/RecordProcesses/record-process-form.component.js +6 -3
- package/dist/lib/custom/RecordProcesses/record-process-form.component.js.map +1 -1
- package/dist/lib/custom/SearchScopes/searchscope-form.component.d.ts +3 -3
- package/dist/lib/custom/SearchScopes/searchscope-form.component.d.ts.map +1 -1
- package/dist/lib/custom/SearchScopes/searchscope-form.component.js +5 -7
- package/dist/lib/custom/SearchScopes/searchscope-form.component.js.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.d.ts +19 -1
- package/dist/lib/custom/Templates/templates-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.js +20 -27
- package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/entity-link-pill.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/entity-link-pill.component.js +14 -6
- package/dist/lib/custom/Tests/entity-link-pill.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js +8 -8
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.d.ts +37 -5
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js +155 -79
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts +8 -0
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js +59 -8
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts +34 -9
- 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 +281 -150
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/run-tree-timeline-projection.js +3 -1
- package/dist/lib/custom/ai-agent-run/run-tree-timeline-projection.js.map +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts +82 -80
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +10 -0
- 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 +65 -47
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js +17 -17
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRunStep/mjaiagentrunstep.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRunStep/mjaiagentrunstep.form.component.js +64 -24
- package/dist/lib/generated/Entities/MJAIAgentRunStep/mjaiagentrunstep.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.js +74 -52
- package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentSessionRecordingShard/mjaiagentsessionrecordingshard.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJAIAgentSessionRecordingShard/mjaiagentsessionrecordingshard.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJAIAgentSessionRecordingShard/mjaiagentsessionrecordingshard.form.component.js +86 -0
- package/dist/lib/generated/Entities/MJAIAgentSessionRecordingShard/mjaiagentsessionrecordingshard.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJAIAgentUserPolicy/mjaiagentuserpolicy.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJAIAgentUserPolicy/mjaiagentuserpolicy.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJAIAgentUserPolicy/mjaiagentuserpolicy.form.component.js +132 -0
- package/dist/lib/generated/Entities/MJAIAgentUserPolicy/mjaiagentuserpolicy.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJAIBridgeAgentIdentity/mjaibridgeagentidentity.form.component.js +12 -10
- package/dist/lib/generated/Entities/MJAIBridgeAgentIdentity/mjaibridgeagentidentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js +86 -32
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPersona/mjaipersona.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIPersona/mjaipersona.form.component.js +25 -7
- package/dist/lib/generated/Entities/MJAIPersona/mjaipersona.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js +180 -160
- package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJActionParam/mjactionparam.form.component.js +16 -14
- package/dist/lib/generated/Entities/MJActionParam/mjactionparam.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJArchiveConfiguration/mjarchiveconfiguration.form.component.js +23 -21
- package/dist/lib/generated/Entities/MJArchiveConfiguration/mjarchiveconfiguration.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJArchiveRun/mjarchiverun.form.component.js +21 -19
- package/dist/lib/generated/Entities/MJArchiveRun/mjarchiverun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCalendarEventLink/mjcalendareventlink.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJCalendarEventLink/mjcalendareventlink.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJCalendarEventLink/mjcalendareventlink.form.component.js +74 -0
- package/dist/lib/generated/Entities/MJCalendarEventLink/mjcalendareventlink.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJCalendarSyncState/mjcalendarsyncstate.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJCalendarSyncState/mjcalendarsyncstate.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJCalendarSyncState/mjcalendarsyncstate.form.component.js +64 -0
- package/dist/lib/generated/Entities/MJCalendarSyncState/mjcalendarsyncstate.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJCommunicationProvider/mjcommunicationprovider.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJCommunicationProvider/mjcommunicationprovider.form.component.js +77 -21
- package/dist/lib/generated/Entities/MJCommunicationProvider/mjcommunicationprovider.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCompanyIntegration/mjcompanyintegration.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJCompanyIntegration/mjcompanyintegration.form.component.js +28 -10
- package/dist/lib/generated/Entities/MJCompanyIntegration/mjcompanyintegration.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCompanyIntegrationObject/mjcompanyintegrationobject.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJCompanyIntegrationObject/mjcompanyintegrationobject.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJCompanyIntegrationObject/mjcompanyintegrationobject.form.component.js +189 -0
- package/dist/lib/generated/Entities/MJCompanyIntegrationObject/mjcompanyintegrationobject.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJCompanyIntegrationObjectField/mjcompanyintegrationobjectfield.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJCompanyIntegrationObjectField/mjcompanyintegrationobjectfield.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJCompanyIntegrationObjectField/mjcompanyintegrationobjectfield.form.component.js +116 -0
- package/dist/lib/generated/Entities/MJCompanyIntegrationObjectField/mjcompanyintegrationobjectfield.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJComponent/mjcomponent.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJComponent/mjcomponent.form.component.js +51 -35
- package/dist/lib/generated/Entities/MJComponent/mjcomponent.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentFileType/mjcontentfiletype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentFileType/mjcontentfiletype.form.component.js +36 -18
- package/dist/lib/generated/Entities/MJContentFileType/mjcontentfiletype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentItem/mjcontentitem.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentItem/mjcontentitem.form.component.js +74 -60
- package/dist/lib/generated/Entities/MJContentItem/mjcontentitem.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentItemChunk/mjcontentitemchunk.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentItemChunk/mjcontentitemchunk.form.component.js +30 -32
- package/dist/lib/generated/Entities/MJContentItemChunk/mjcontentitemchunk.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentSource/mjcontentsource.form.component.js +43 -35
- package/dist/lib/generated/Entities/MJContentSource/mjcontentsource.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentType/mjcontenttype.form.component.js +21 -19
- package/dist/lib/generated/Entities/MJContentType/mjcontenttype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.js +69 -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 +35 -17
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJDashboard/mjdashboard.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJDashboard/mjdashboard.form.component.js +45 -29
- package/dist/lib/generated/Entities/MJDashboard/mjdashboard.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJDuplicateRun/mjduplicaterun.form.component.js +19 -17
- package/dist/lib/generated/Entities/MJDuplicateRun/mjduplicaterun.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 +128 -92
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityAlternateBaseView/mjentityalternatebaseview.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJEntityAlternateBaseView/mjentityalternatebaseview.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJEntityAlternateBaseView/mjentityalternatebaseview.form.component.js +129 -0
- package/dist/lib/generated/Entities/MJEntityAlternateBaseView/mjentityalternatebaseview.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.js +27 -9
- package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFeaturePipelineVersion/mjfeaturepipelineversion.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJFeaturePipelineVersion/mjfeaturepipelineversion.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJFeaturePipelineVersion/mjfeaturepipelineversion.form.component.js +130 -0
- package/dist/lib/generated/Entities/MJFeaturePipelineVersion/mjfeaturepipelineversion.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js +26 -14
- package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.js +23 -19
- package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js +30 -12
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJIntegration/mjintegration.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJIntegration/mjintegration.form.component.js +26 -8
- package/dist/lib/generated/Entities/MJIntegration/mjintegration.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.js +24 -6
- package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJIntegrationObjectField/mjintegrationobjectfield.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJIntegrationObjectField/mjintegrationobjectfield.form.component.js +25 -6
- package/dist/lib/generated/Entities/MJIntegrationObjectField/mjintegrationobjectfield.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js +29 -27
- package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.js +17 -15
- package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js +73 -59
- package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJQueryEntity/mjqueryentity.form.component.js +10 -8
- package/dist/lib/generated/Entities/MJQueryEntity/mjqueryentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJQueryParameter/mjqueryparameter.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJQueryParameter/mjqueryparameter.form.component.js +12 -4
- package/dist/lib/generated/Entities/MJQueryParameter/mjqueryparameter.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js +27 -9
- package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTest/mjtest.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTest/mjtest.form.component.js +24 -6
- package/dist/lib/generated/Entities/MJTest/mjtest.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTestRun/mjtestrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTestRun/mjtestrun.form.component.js +29 -11
- package/dist/lib/generated/Entities/MJTestRun/mjtestrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTheme/mjtheme.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTheme/mjtheme.form.component.js +13 -3
- package/dist/lib/generated/Entities/MJTheme/mjtheme.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 +256 -130
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJUserRoutine/mjuserroutine.form.component.js +31 -25
- package/dist/lib/generated/Entities/MJUserRoutine/mjuserroutine.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.js +50 -38
- package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.js.map +1 -1
- package/dist/lib/generated/generated-forms.module.d.ts +446 -438
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +24 -0
- package/dist/lib/generated/generated-forms.module.js.map +1 -1
- package/dist/lib/panels/feature-values/feature-values.logic.d.ts +55 -0
- package/dist/lib/panels/feature-values/feature-values.logic.d.ts.map +1 -0
- package/dist/lib/panels/feature-values/feature-values.logic.js +88 -0
- package/dist/lib/panels/feature-values/feature-values.logic.js.map +1 -0
- package/dist/lib/panels/feature-values/feature-values.panel.d.ts +39 -0
- package/dist/lib/panels/feature-values/feature-values.panel.d.ts.map +1 -0
- package/dist/lib/panels/feature-values/feature-values.panel.js +303 -0
- package/dist/lib/panels/feature-values/feature-values.panel.js.map +1 -0
- package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts +10 -0
- package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.logic.js +15 -1
- package/dist/lib/panels/model-predictions/model-prediction.logic.js.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts +4 -0
- package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.panel.js +77 -61
- package/dist/lib/panels/model-predictions/model-prediction.panel.js.map +1 -1
- package/dist/lib/shared/components/template-editor.component.d.ts +37 -0
- package/dist/lib/shared/components/template-editor.component.d.ts.map +1 -1
- package/dist/lib/shared/components/template-editor.component.js +425 -286
- package/dist/lib/shared/components/template-editor.component.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +48 -48
|
@@ -4,7 +4,8 @@ import { FormsModule } from '@angular/forms';
|
|
|
4
4
|
import { MJButtonDirective } from '@memberjunction/ng-ui-components';
|
|
5
5
|
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
6
6
|
import { PredictiveStudioPromoteModelOperation, } from '@memberjunction/core-entities';
|
|
7
|
-
import {
|
|
7
|
+
import { ImportanceDisplay } from '@memberjunction/predictive-studio-core';
|
|
8
|
+
import { PS_FEATURE_DOMINANCE_THRESHOLD, FormatMetricValue, HumanizeFeatureName, MaxFeatureImportance, MetricsToDisplay, ModelImportanceView, OverfitGap, ParseFeatureImportance, ParseMetrics, PrimaryModelScore, } from './ml-model-view-models';
|
|
8
9
|
import * as i0 from "@angular/core";
|
|
9
10
|
import * as i1 from "@angular/forms";
|
|
10
11
|
const _forTrack0 = ($index, $item) => $item.key;
|
|
@@ -84,7 +85,16 @@ function PSModelDetailComponent_Conditional_1_Conditional_46_Template(rf, ctx) {
|
|
|
84
85
|
i0.ɵɵadvance();
|
|
85
86
|
i0.ɵɵtextInterpolate1(" ", ctx_r4.gapVerdict, ". ");
|
|
86
87
|
} }
|
|
87
|
-
function
|
|
88
|
+
function PSModelDetailComponent_Conditional_1_Conditional_51_Template(rf, ctx) { if (rf & 1) {
|
|
89
|
+
i0.ɵɵelementStart(0, "span", 23);
|
|
90
|
+
i0.ɵɵtext(1);
|
|
91
|
+
i0.ɵɵelementEnd();
|
|
92
|
+
} if (rf & 2) {
|
|
93
|
+
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
94
|
+
i0.ɵɵadvance();
|
|
95
|
+
i0.ɵɵtextInterpolate(ctx_r4.ImportanceCaption);
|
|
96
|
+
} }
|
|
97
|
+
function PSModelDetailComponent_Conditional_1_Conditional_53_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
88
98
|
i0.ɵɵelementStart(0, "div", 31)(1, "span", 32);
|
|
89
99
|
i0.ɵɵtext(2);
|
|
90
100
|
i0.ɵɵelementEnd();
|
|
@@ -106,18 +116,47 @@ function PSModelDetailComponent_Conditional_1_Conditional_54_For_1_Template(rf,
|
|
|
106
116
|
i0.ɵɵadvance(2);
|
|
107
117
|
i0.ɵɵtextInterpolate(f_r7.value);
|
|
108
118
|
} }
|
|
109
|
-
function
|
|
110
|
-
i0.ɵɵrepeaterCreate(0,
|
|
119
|
+
function PSModelDetailComponent_Conditional_1_Conditional_53_Template(rf, ctx) { if (rf & 1) {
|
|
120
|
+
i0.ɵɵrepeaterCreate(0, PSModelDetailComponent_Conditional_1_Conditional_53_For_1_Template, 7, 7, "div", 31, _forTrack1);
|
|
111
121
|
} if (rf & 2) {
|
|
112
122
|
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
113
|
-
i0.ɵɵrepeater(ctx_r4.
|
|
123
|
+
i0.ɵɵrepeater(ctx_r4.DisplayedImportance);
|
|
114
124
|
} }
|
|
115
|
-
function
|
|
116
|
-
i0.ɵɵelementStart(0, "div",
|
|
125
|
+
function PSModelDetailComponent_Conditional_1_Conditional_54_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
126
|
+
i0.ɵɵelementStart(0, "div", 35);
|
|
127
|
+
i0.ɵɵtext(1);
|
|
128
|
+
i0.ɵɵelementEnd();
|
|
129
|
+
} if (rf & 2) {
|
|
130
|
+
const ctx_r4 = i0.ɵɵnextContext(3);
|
|
131
|
+
i0.ɵɵadvance();
|
|
132
|
+
i0.ɵɵtextInterpolate(ctx_r4.ImportanceHiddenNote);
|
|
133
|
+
} }
|
|
134
|
+
function PSModelDetailComponent_Conditional_1_Conditional_54_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
135
|
+
i0.ɵɵelementStart(0, "div", 36);
|
|
117
136
|
i0.ɵɵtext(1, "No feature-importance data was recorded for this model.");
|
|
118
137
|
i0.ɵɵelementEnd();
|
|
119
138
|
} }
|
|
120
|
-
function
|
|
139
|
+
function PSModelDetailComponent_Conditional_1_Conditional_54_Template(rf, ctx) { if (rf & 1) {
|
|
140
|
+
i0.ɵɵconditionalCreate(0, PSModelDetailComponent_Conditional_1_Conditional_54_Conditional_0_Template, 2, 1, "div", 35)(1, PSModelDetailComponent_Conditional_1_Conditional_54_Conditional_1_Template, 2, 0, "div", 36);
|
|
141
|
+
} if (rf & 2) {
|
|
142
|
+
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
143
|
+
i0.ɵɵconditional(ctx_r4.ImportanceHidden ? 0 : 1);
|
|
144
|
+
} }
|
|
145
|
+
function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
146
|
+
i0.ɵɵelementStart(0, "strong");
|
|
147
|
+
i0.ɵɵtext(1, "Leakage flag raised.");
|
|
148
|
+
i0.ɵɵelementEnd();
|
|
149
|
+
i0.ɵɵtext(2, " A single feature's split share is at or above the ");
|
|
150
|
+
i0.ɵɵelementStart(3, "strong");
|
|
151
|
+
i0.ɵɵtext(4);
|
|
152
|
+
i0.ɵɵelementEnd();
|
|
153
|
+
i0.ɵɵtext(5, " dominance threshold. ");
|
|
154
|
+
} if (rf & 2) {
|
|
155
|
+
const ctx_r4 = i0.ɵɵnextContext(4);
|
|
156
|
+
i0.ɵɵadvance(4);
|
|
157
|
+
i0.ɵɵtextInterpolate(ctx_r4.dominanceThreshold);
|
|
158
|
+
} }
|
|
159
|
+
function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
121
160
|
i0.ɵɵelementStart(0, "strong");
|
|
122
161
|
i0.ɵɵtext(1, "Leakage flag raised.");
|
|
123
162
|
i0.ɵɵelementEnd();
|
|
@@ -130,18 +169,38 @@ function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_3_Templ
|
|
|
130
169
|
i0.ɵɵtext(7);
|
|
131
170
|
i0.ɵɵelementEnd();
|
|
132
171
|
i0.ɵɵtext(8, " dominance threshold. ");
|
|
133
|
-
|
|
134
|
-
i0.ɵɵ
|
|
135
|
-
i0.ɵɵ
|
|
172
|
+
} if (rf & 2) {
|
|
173
|
+
const ctx_r4 = i0.ɵɵnextContext(4);
|
|
174
|
+
i0.ɵɵadvance(4);
|
|
175
|
+
i0.ɵɵtextInterpolate2("", ctx_r4.TopFeatureName, " at ", ctx_r4.TopFeatureValue);
|
|
176
|
+
i0.ɵɵadvance(3);
|
|
177
|
+
i0.ɵɵtextInterpolate(ctx_r4.dominanceThreshold);
|
|
178
|
+
} }
|
|
179
|
+
function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
180
|
+
i0.ɵɵconditionalCreate(0, PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_3_Conditional_0_Template, 6, 1)(1, PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_3_Conditional_1_Template, 9, 3);
|
|
181
|
+
i0.ɵɵelementStart(2, "div", 38);
|
|
182
|
+
i0.ɵɵelement(3, "i", 39);
|
|
183
|
+
i0.ɵɵtext(4, " Sign-off with a reason is required to publish this model. ");
|
|
136
184
|
i0.ɵɵelementEnd();
|
|
137
185
|
} if (rf & 2) {
|
|
138
186
|
const ctx_r4 = i0.ɵɵnextContext(3);
|
|
187
|
+
i0.ɵɵconditional(ctx_r4.ImportanceHidden ? 0 : 1);
|
|
188
|
+
} }
|
|
189
|
+
function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
190
|
+
i0.ɵɵelementStart(0, "strong");
|
|
191
|
+
i0.ɵɵtext(1, "Leakage gate clear.");
|
|
192
|
+
i0.ɵɵelementEnd();
|
|
193
|
+
i0.ɵɵtext(2, " No single feature's split share is at or above the ");
|
|
194
|
+
i0.ɵɵelementStart(3, "strong");
|
|
195
|
+
i0.ɵɵtext(4);
|
|
196
|
+
i0.ɵɵelementEnd();
|
|
197
|
+
i0.ɵɵtext(5, " dominance threshold. ");
|
|
198
|
+
} if (rf & 2) {
|
|
199
|
+
const ctx_r4 = i0.ɵɵnextContext(4);
|
|
139
200
|
i0.ɵɵadvance(4);
|
|
140
|
-
i0.ɵɵtextInterpolate2("", ctx_r4.topFeatureName, " at ", ctx_r4.topFeatureValue);
|
|
141
|
-
i0.ɵɵadvance(3);
|
|
142
201
|
i0.ɵɵtextInterpolate(ctx_r4.dominanceThreshold);
|
|
143
202
|
} }
|
|
144
|
-
function
|
|
203
|
+
function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
145
204
|
i0.ɵɵelementStart(0, "strong");
|
|
146
205
|
i0.ɵɵtext(1, "Leakage gate clear.");
|
|
147
206
|
i0.ɵɵelementEnd();
|
|
@@ -154,62 +213,68 @@ function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_4_Templ
|
|
|
154
213
|
i0.ɵɵtext(7);
|
|
155
214
|
i0.ɵɵelementEnd();
|
|
156
215
|
i0.ɵɵtext(8, " dominance threshold. ");
|
|
157
|
-
i0.ɵɵelementStart(9, "div", 36);
|
|
158
|
-
i0.ɵɵelement(10, "i", 28);
|
|
159
|
-
i0.ɵɵtext(11, " Sign-off required before any Validated \u2192 Published promotion. ");
|
|
160
|
-
i0.ɵɵelementEnd();
|
|
161
216
|
} if (rf & 2) {
|
|
162
|
-
const ctx_r4 = i0.ɵɵnextContext(
|
|
217
|
+
const ctx_r4 = i0.ɵɵnextContext(4);
|
|
163
218
|
i0.ɵɵadvance(4);
|
|
164
|
-
i0.ɵɵtextInterpolate2("", ctx_r4.
|
|
219
|
+
i0.ɵɵtextInterpolate2("", ctx_r4.TopFeatureName, " at ", ctx_r4.TopFeatureValue);
|
|
165
220
|
i0.ɵɵadvance(3);
|
|
166
221
|
i0.ɵɵtextInterpolate(ctx_r4.dominanceThreshold);
|
|
167
222
|
} }
|
|
168
|
-
function
|
|
169
|
-
i0.ɵɵ
|
|
223
|
+
function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
224
|
+
i0.ɵɵconditionalCreate(0, PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Conditional_0_Template, 6, 1)(1, PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Conditional_1_Template, 9, 3);
|
|
225
|
+
i0.ɵɵelementStart(2, "div", 38);
|
|
226
|
+
i0.ɵɵelement(3, "i", 28);
|
|
227
|
+
i0.ɵɵtext(4, " Sign-off required before any Validated \u2192 Published promotion. ");
|
|
228
|
+
i0.ɵɵelementEnd();
|
|
229
|
+
} if (rf & 2) {
|
|
230
|
+
const ctx_r4 = i0.ɵɵnextContext(3);
|
|
231
|
+
i0.ɵɵconditional(ctx_r4.ImportanceHidden ? 0 : 1);
|
|
232
|
+
} }
|
|
233
|
+
function PSModelDetailComponent_Conditional_1_Conditional_55_Template(rf, ctx) { if (rf & 1) {
|
|
234
|
+
i0.ɵɵelementStart(0, "div", 37);
|
|
170
235
|
i0.ɵɵelement(1, "i");
|
|
171
236
|
i0.ɵɵelementStart(2, "div");
|
|
172
|
-
i0.ɵɵconditionalCreate(3,
|
|
237
|
+
i0.ɵɵconditionalCreate(3, PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_3_Template, 5, 1)(4, PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Template, 5, 1);
|
|
173
238
|
i0.ɵɵelementEnd()();
|
|
174
239
|
} if (rf & 2) {
|
|
175
240
|
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
176
|
-
i0.ɵɵclassProp("success", !ctx_r4.
|
|
241
|
+
i0.ɵɵclassProp("success", !ctx_r4.LeakageFlagged)("warn", ctx_r4.LeakageFlagged);
|
|
177
242
|
i0.ɵɵadvance();
|
|
178
|
-
i0.ɵɵclassMap(ctx_r4.
|
|
243
|
+
i0.ɵɵclassMap(ctx_r4.LeakageFlagged ? "fa-solid fa-triangle-exclamation" : "fa-solid fa-shield-halved");
|
|
179
244
|
i0.ɵɵadvance(2);
|
|
180
|
-
i0.ɵɵconditional(ctx_r4.
|
|
245
|
+
i0.ɵɵconditional(ctx_r4.LeakageFlagged ? 3 : 4);
|
|
181
246
|
} }
|
|
182
|
-
function
|
|
247
|
+
function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
183
248
|
const _r8 = i0.ɵɵgetCurrentView();
|
|
184
|
-
i0.ɵɵelementStart(0, "button",
|
|
185
|
-
i0.ɵɵlistener("click", function
|
|
186
|
-
i0.ɵɵelement(1, "i",
|
|
249
|
+
i0.ɵɵelementStart(0, "button", 45);
|
|
250
|
+
i0.ɵɵlistener("click", function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r4 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r4.requestPromote("Validated")); });
|
|
251
|
+
i0.ɵɵelement(1, "i", 46);
|
|
187
252
|
i0.ɵɵtext(2, " Mark Validated ");
|
|
188
253
|
i0.ɵɵelementEnd();
|
|
189
254
|
} }
|
|
190
|
-
function
|
|
255
|
+
function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
191
256
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
192
|
-
i0.ɵɵelementStart(0, "button",
|
|
193
|
-
i0.ɵɵlistener("click", function
|
|
194
|
-
i0.ɵɵelement(1, "i",
|
|
257
|
+
i0.ɵɵelementStart(0, "button", 47);
|
|
258
|
+
i0.ɵɵlistener("click", function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r4 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r4.requestPromote("Published")); });
|
|
259
|
+
i0.ɵɵelement(1, "i", 48);
|
|
195
260
|
i0.ɵɵtext(2, " Promote to Published ");
|
|
196
261
|
i0.ɵɵelementEnd();
|
|
197
262
|
} }
|
|
198
|
-
function
|
|
263
|
+
function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
199
264
|
const _r10 = i0.ɵɵgetCurrentView();
|
|
200
|
-
i0.ɵɵelementStart(0, "button",
|
|
201
|
-
i0.ɵɵlistener("click", function
|
|
202
|
-
i0.ɵɵelement(1, "i",
|
|
265
|
+
i0.ɵɵelementStart(0, "button", 49);
|
|
266
|
+
i0.ɵɵlistener("click", function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r4 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r4.requestPromote("Archived")); });
|
|
267
|
+
i0.ɵɵelement(1, "i", 50);
|
|
203
268
|
i0.ɵɵtext(2, " Archive ");
|
|
204
269
|
i0.ɵɵelementEnd();
|
|
205
270
|
} }
|
|
206
|
-
function
|
|
207
|
-
i0.ɵɵelementStart(0, "div", 2)(1, "div",
|
|
271
|
+
function PSModelDetailComponent_Conditional_1_Conditional_56_Template(rf, ctx) { if (rf & 1) {
|
|
272
|
+
i0.ɵɵelementStart(0, "div", 2)(1, "div", 40)(2, "span", 41);
|
|
208
273
|
i0.ɵɵtext(3);
|
|
209
274
|
i0.ɵɵelementEnd();
|
|
210
|
-
i0.ɵɵconditionalCreate(4,
|
|
211
|
-
i0.ɵɵconditionalCreate(5,
|
|
212
|
-
i0.ɵɵconditionalCreate(6,
|
|
275
|
+
i0.ɵɵconditionalCreate(4, PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_4_Template, 3, 0, "button", 42);
|
|
276
|
+
i0.ɵɵconditionalCreate(5, PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_5_Template, 3, 0, "button", 43);
|
|
277
|
+
i0.ɵɵconditionalCreate(6, PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_6_Template, 3, 0, "button", 44);
|
|
213
278
|
i0.ɵɵelementEnd()();
|
|
214
279
|
} if (rf & 2) {
|
|
215
280
|
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
@@ -222,13 +287,13 @@ function PSModelDetailComponent_Conditional_1_Conditional_57_Template(rf, ctx) {
|
|
|
222
287
|
i0.ɵɵadvance();
|
|
223
288
|
i0.ɵɵconditional(ctx_r4.canArchive ? 6 : -1);
|
|
224
289
|
} }
|
|
225
|
-
function
|
|
290
|
+
function PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
226
291
|
const _r12 = i0.ɵɵgetCurrentView();
|
|
227
|
-
i0.ɵɵelementStart(0, "div",
|
|
292
|
+
i0.ɵɵelementStart(0, "div", 57)(1, "label");
|
|
228
293
|
i0.ɵɵtext(2);
|
|
229
294
|
i0.ɵɵelementEnd();
|
|
230
|
-
i0.ɵɵelementStart(3, "textarea",
|
|
231
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
295
|
+
i0.ɵɵelementStart(3, "textarea", 64);
|
|
296
|
+
i0.ɵɵtwoWayListener("ngModelChange", function PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_9_Template_textarea_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r4 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r4.pendingReason, $event) || (ctx_r4.pendingReason = $event); return i0.ɵɵresetView($event); });
|
|
232
297
|
i0.ɵɵelementEnd()();
|
|
233
298
|
} if (rf & 2) {
|
|
234
299
|
const ctx_r4 = i0.ɵɵnextContext(3);
|
|
@@ -238,39 +303,39 @@ function PSModelDetailComponent_Conditional_1_Conditional_58_Conditional_9_Templ
|
|
|
238
303
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r4.pendingReason);
|
|
239
304
|
i0.ɵɵproperty("placeholder", ctx_r4.pending.leakageFlagged ? "Explain why this model is safe to publish despite the leakage flag\u2026" : "Add an optional note for the record\u2026")("disabled", ctx_r4.busy);
|
|
240
305
|
} }
|
|
241
|
-
function
|
|
242
|
-
i0.ɵɵelement(0, "i",
|
|
306
|
+
function PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
307
|
+
i0.ɵɵelement(0, "i", 60);
|
|
243
308
|
} }
|
|
244
|
-
function
|
|
309
|
+
function PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
245
310
|
i0.ɵɵelement(0, "i");
|
|
246
311
|
} if (rf & 2) {
|
|
247
312
|
const ctx_r4 = i0.ɵɵnextContext(3);
|
|
248
313
|
i0.ɵɵclassMap(ctx_r4.pendingIcon);
|
|
249
314
|
} }
|
|
250
|
-
function
|
|
315
|
+
function PSModelDetailComponent_Conditional_1_Conditional_57_Template(rf, ctx) { if (rf & 1) {
|
|
251
316
|
const _r11 = i0.ɵɵgetCurrentView();
|
|
252
|
-
i0.ɵɵelementStart(0, "div",
|
|
253
|
-
i0.ɵɵlistener("click", function
|
|
254
|
-
i0.ɵɵelementStart(1, "div",
|
|
255
|
-
i0.ɵɵlistener("click", function
|
|
256
|
-
i0.ɵɵelementStart(2, "div",
|
|
317
|
+
i0.ɵɵelementStart(0, "div", 51);
|
|
318
|
+
i0.ɵɵlistener("click", function PSModelDetailComponent_Conditional_1_Conditional_57_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r4 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r4.cancelPromote()); });
|
|
319
|
+
i0.ɵɵelementStart(1, "div", 52);
|
|
320
|
+
i0.ɵɵlistener("click", function PSModelDetailComponent_Conditional_1_Conditional_57_Template_div_click_1_listener($event) { return $event.stopPropagation(); });
|
|
321
|
+
i0.ɵɵelementStart(2, "div", 53)(3, "span", 54);
|
|
257
322
|
i0.ɵɵelement(4, "i");
|
|
258
323
|
i0.ɵɵelementEnd();
|
|
259
324
|
i0.ɵɵelementStart(5, "h3");
|
|
260
325
|
i0.ɵɵtext(6);
|
|
261
326
|
i0.ɵɵelementEnd()();
|
|
262
|
-
i0.ɵɵelementStart(7, "div",
|
|
263
|
-
i0.ɵɵelement(8, "div",
|
|
264
|
-
i0.ɵɵconditionalCreate(9,
|
|
327
|
+
i0.ɵɵelementStart(7, "div", 55);
|
|
328
|
+
i0.ɵɵelement(8, "div", 56);
|
|
329
|
+
i0.ɵɵconditionalCreate(9, PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_9_Template, 4, 5, "div", 57);
|
|
265
330
|
i0.ɵɵelementEnd();
|
|
266
|
-
i0.ɵɵelementStart(10, "div",
|
|
267
|
-
i0.ɵɵlistener("click", function
|
|
268
|
-
i0.ɵɵconditionalCreate(12,
|
|
331
|
+
i0.ɵɵelementStart(10, "div", 58)(11, "button", 59);
|
|
332
|
+
i0.ɵɵlistener("click", function PSModelDetailComponent_Conditional_1_Conditional_57_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r11); const ctx_r4 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r4.confirmPromote(ctx_r4.pendingReason.trim())); });
|
|
333
|
+
i0.ɵɵconditionalCreate(12, PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_12_Template, 1, 0, "i", 60)(13, PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_13_Template, 1, 2, "i", 61);
|
|
269
334
|
i0.ɵɵtext(14);
|
|
270
335
|
i0.ɵɵelementEnd();
|
|
271
|
-
i0.ɵɵelement(15, "span",
|
|
272
|
-
i0.ɵɵelementStart(16, "button",
|
|
273
|
-
i0.ɵɵlistener("click", function
|
|
336
|
+
i0.ɵɵelement(15, "span", 62);
|
|
337
|
+
i0.ɵɵelementStart(16, "button", 63);
|
|
338
|
+
i0.ɵɵlistener("click", function PSModelDetailComponent_Conditional_1_Conditional_57_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r11); const ctx_r4 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r4.cancelPromote()); });
|
|
274
339
|
i0.ɵɵtext(17, " Cancel ");
|
|
275
340
|
i0.ɵɵelementEnd()()()();
|
|
276
341
|
} if (rf & 2) {
|
|
@@ -348,15 +413,14 @@ function PSModelDetailComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
|
348
413
|
i0.ɵɵelementStart(47, "div", 2)(48, "div", 15)(49, "h3");
|
|
349
414
|
i0.ɵɵtext(50, "Feature Importance");
|
|
350
415
|
i0.ɵɵelementEnd();
|
|
351
|
-
i0.ɵɵ
|
|
352
|
-
i0.ɵɵ
|
|
353
|
-
i0.ɵɵ
|
|
354
|
-
i0.ɵɵ
|
|
355
|
-
i0.ɵɵconditionalCreate(54, PSModelDetailComponent_Conditional_1_Conditional_54_Template, 2, 0)(55, PSModelDetailComponent_Conditional_1_Conditional_55_Template, 2, 0, "div", 23);
|
|
416
|
+
i0.ɵɵconditionalCreate(51, PSModelDetailComponent_Conditional_1_Conditional_51_Template, 2, 1, "span", 23);
|
|
417
|
+
i0.ɵɵelementEnd();
|
|
418
|
+
i0.ɵɵelementStart(52, "div", 11);
|
|
419
|
+
i0.ɵɵconditionalCreate(53, PSModelDetailComponent_Conditional_1_Conditional_53_Template, 2, 0)(54, PSModelDetailComponent_Conditional_1_Conditional_54_Template, 2, 1);
|
|
356
420
|
i0.ɵɵelementEnd()();
|
|
357
|
-
i0.ɵɵconditionalCreate(
|
|
358
|
-
i0.ɵɵconditionalCreate(
|
|
359
|
-
i0.ɵɵconditionalCreate(
|
|
421
|
+
i0.ɵɵconditionalCreate(55, PSModelDetailComponent_Conditional_1_Conditional_55_Template, 5, 7, "div", 24);
|
|
422
|
+
i0.ɵɵconditionalCreate(56, PSModelDetailComponent_Conditional_1_Conditional_56_Template, 7, 4, "div", 2);
|
|
423
|
+
i0.ɵɵconditionalCreate(57, PSModelDetailComponent_Conditional_1_Conditional_57_Template, 18, 14, "div", 25);
|
|
360
424
|
} if (rf & 2) {
|
|
361
425
|
const ctx_r4 = i0.ɵɵnextContext();
|
|
362
426
|
i0.ɵɵadvance(6);
|
|
@@ -383,25 +447,25 @@ function PSModelDetailComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
|
383
447
|
i0.ɵɵconditional(ctx_r4.secondaryMetrics.length > 0 ? 44 : 45);
|
|
384
448
|
i0.ɵɵadvance(2);
|
|
385
449
|
i0.ɵɵconditional(ctx_r4.gapText ? 46 : -1);
|
|
386
|
-
i0.ɵɵadvance(
|
|
387
|
-
i0.ɵɵ
|
|
450
|
+
i0.ɵɵadvance(5);
|
|
451
|
+
i0.ɵɵconditional(!ctx_r4.ImportanceHidden ? 51 : -1);
|
|
388
452
|
i0.ɵɵadvance(2);
|
|
389
|
-
i0.ɵɵconditional(ctx_r4.
|
|
453
|
+
i0.ɵɵconditional(ctx_r4.DisplayedImportance.length > 0 ? 53 : 54);
|
|
390
454
|
i0.ɵɵadvance(2);
|
|
391
|
-
i0.ɵɵconditional(ctx_r4.
|
|
455
|
+
i0.ɵɵconditional(ctx_r4.Importance.length > 0 ? 55 : -1);
|
|
392
456
|
i0.ɵɵadvance();
|
|
393
|
-
i0.ɵɵconditional(ctx_r4.showActions ?
|
|
457
|
+
i0.ɵɵconditional(ctx_r4.showActions ? 56 : -1);
|
|
394
458
|
i0.ɵɵadvance();
|
|
395
|
-
i0.ɵɵconditional(ctx_r4.pending ?
|
|
459
|
+
i0.ɵɵconditional(ctx_r4.pending ? 57 : -1);
|
|
396
460
|
} }
|
|
397
461
|
function PSModelDetailComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
398
|
-
i0.ɵɵelementStart(0, "div", 1)(1, "span",
|
|
462
|
+
i0.ɵɵelementStart(0, "div", 1)(1, "span", 65);
|
|
399
463
|
i0.ɵɵelement(2, "i", 5);
|
|
400
464
|
i0.ɵɵelementEnd();
|
|
401
465
|
i0.ɵɵelementStart(3, "h3");
|
|
402
466
|
i0.ɵɵtext(4, "No Model Selected");
|
|
403
467
|
i0.ɵɵelementEnd();
|
|
404
|
-
i0.ɵɵelementStart(5, "p",
|
|
468
|
+
i0.ɵɵelementStart(5, "p", 66);
|
|
405
469
|
i0.ɵɵtext(6, "Select an ML Model from the list to inspect its configuration and metrics.");
|
|
406
470
|
i0.ɵɵelementEnd()();
|
|
407
471
|
} }
|
|
@@ -441,6 +505,11 @@ export class PSModelDetailComponent {
|
|
|
441
505
|
this.Pending = null;
|
|
442
506
|
this.PendingReason = '';
|
|
443
507
|
this.Busy = false;
|
|
508
|
+
// ── Feature Importance & Leakage Gate ──
|
|
509
|
+
/** Cached parsed and displayed importance bars for the last (Lineage JSON, importance JSON) pair. */
|
|
510
|
+
this.importanceCache = null;
|
|
511
|
+
/** The note shown in place of hidden importance. */
|
|
512
|
+
this.ImportanceHiddenNote = ImportanceDisplay.HiddenNote;
|
|
444
513
|
}
|
|
445
514
|
/** @deprecated Use {@link Model}. */
|
|
446
515
|
set model(value) {
|
|
@@ -632,19 +701,44 @@ export class PSModelDetailComponent {
|
|
|
632
701
|
get gapVerdict() {
|
|
633
702
|
return this.GapVerdict;
|
|
634
703
|
}
|
|
635
|
-
|
|
636
|
-
get Importance() {
|
|
704
|
+
get cachedImportance() {
|
|
637
705
|
if (!this.Model)
|
|
638
|
-
return [];
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
706
|
+
return { allBars: [], displayedBars: [] };
|
|
707
|
+
const key = `${this.Model.Lineage}\u0000${this.Model.FeatureImportance}`;
|
|
708
|
+
if (this.importanceCache?.key !== key) {
|
|
709
|
+
const allBars = ParseFeatureImportance(this.Model.FeatureImportance, 6).map((b) => ({
|
|
710
|
+
...b,
|
|
711
|
+
name: HumanizeFeatureName(b.name),
|
|
712
|
+
}));
|
|
713
|
+
const displayedBars = ModelImportanceView.DisplayedFeatureImportance(this.Model.Lineage, this.Model.FeatureImportance, 6).map((b) => ({
|
|
714
|
+
...b,
|
|
715
|
+
name: HumanizeFeatureName(b.name),
|
|
716
|
+
}));
|
|
717
|
+
this.importanceCache = { key, allBars, displayedBars };
|
|
718
|
+
}
|
|
719
|
+
return this.importanceCache;
|
|
720
|
+
}
|
|
721
|
+
get Importance() {
|
|
722
|
+
return this.cachedImportance.allBars;
|
|
643
723
|
}
|
|
644
724
|
/** @deprecated Use {@link Importance}. */
|
|
645
725
|
get importance() {
|
|
646
726
|
return this.Importance;
|
|
647
727
|
}
|
|
728
|
+
/**
|
|
729
|
+
* The importance bars shown in the Feature Importance card (empty for split / impurity importance). Cached on the
|
|
730
|
+
* Lineage JSON (which holds the stored importance kind) and the importance JSON, so the parse runs once per model and
|
|
731
|
+
* again whenever either value changes
|
|
732
|
+
* (coding standards §7: getters Angular bindings hit).
|
|
733
|
+
*/
|
|
734
|
+
get DisplayedImportance() {
|
|
735
|
+
return this.cachedImportance.displayedBars;
|
|
736
|
+
}
|
|
737
|
+
/** True when the model has importance data that is hidden because of its kind. */
|
|
738
|
+
get ImportanceHidden() {
|
|
739
|
+
return this.Importance.length > 0 && this.DisplayedImportance.length === 0;
|
|
740
|
+
}
|
|
741
|
+
/** The Feature Importance card's caption. The template hides it when {@link ImportanceHidden}, along with the bars. */
|
|
648
742
|
get ImportanceCaption() {
|
|
649
743
|
const n = this.Importance.length;
|
|
650
744
|
return n === 0 ? 'no data' : `normalized · top ${n}`;
|
|
@@ -844,9 +938,9 @@ export class PSModelDetailComponent {
|
|
|
844
938
|
.replace(/"/g, '"');
|
|
845
939
|
}
|
|
846
940
|
static { this.ɵfac = function PSModelDetailComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PSModelDetailComponent)(); }; }
|
|
847
|
-
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PSModelDetailComponent, selectors: [["ps-model-detail"]], inputs: { Model: "Model", model: "model", Provider: "Provider", provider: "provider", CurrentUser: "CurrentUser", currentUser: "currentUser", ShowActions: "ShowActions", showActions: "showActions", displayName: "displayName" }, outputs: { StatusChanged: "StatusChanged", statusChanged: "statusChanged" }, decls: 3, vars: 1, consts: [["data-testid", "ps-model-detail", 1, "ps-model-detail"], [1, "ps-empty", 2, "padding", "32px", "text-align", "center"], [1, "ps-card"], [1, "ps-card-body", "dh"], [1, "big-ico"], [1, "fa-solid", "fa-cube"], [2, "flex", "1", "min-width", "0"], ["data-testid", "ps-registry-detail-name"], [1, "ps-tag", "ps-mono"], [1, "ps-muted", "ps-small", "sub"], [1, "ps-badge"], [1, "ps-card-body"], [1, "ps-section-title"], [1, "ps-stepper"], [1, "ps-small", "ps-muted", 2, "margin-top", "10px"], [1, "ps-card-head"], [1, "ps-muted", "ps-small"], [1, "metric-pair"], [1, "mtile"], [1, "v"], [1, "mtile", "honest"], [1, "stat-bar"], [1, "ps-small", "ps-muted", 2, "margin-top", "6px"], [
|
|
941
|
+
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PSModelDetailComponent, selectors: [["ps-model-detail"]], inputs: { Model: "Model", model: "model", Provider: "Provider", provider: "provider", CurrentUser: "CurrentUser", currentUser: "currentUser", ShowActions: "ShowActions", showActions: "showActions", displayName: "displayName" }, outputs: { StatusChanged: "StatusChanged", statusChanged: "statusChanged" }, decls: 3, vars: 1, consts: [["data-testid", "ps-model-detail", 1, "ps-model-detail"], [1, "ps-empty", 2, "padding", "32px", "text-align", "center"], [1, "ps-card"], [1, "ps-card-body", "dh"], [1, "big-ico"], [1, "fa-solid", "fa-cube"], [2, "flex", "1", "min-width", "0"], ["data-testid", "ps-registry-detail-name"], [1, "ps-tag", "ps-mono"], [1, "ps-muted", "ps-small", "sub"], [1, "ps-badge"], [1, "ps-card-body"], [1, "ps-section-title"], [1, "ps-stepper"], [1, "ps-small", "ps-muted", 2, "margin-top", "10px"], [1, "ps-card-head"], [1, "ps-muted", "ps-small"], [1, "metric-pair"], [1, "mtile"], [1, "v"], [1, "mtile", "honest"], [1, "stat-bar"], [1, "ps-small", "ps-muted", 2, "margin-top", "6px"], ["data-testid", "ps-importance-caption", 1, "ps-muted", "ps-small"], ["data-testid", "ps-leakage-gate", 1, "ps-callout", "gate", 3, "success", "warn"], [1, "ps-modal-backdrop"], [1, "ps-step"], [1, "pip"], [1, "fa-solid", "fa-check"], [1, "ln"], [1, "b"], [1, "ps-fbar"], [1, "name", "ps-small", 3, "title"], [1, "track"], [1, "ps-mono"], ["data-testid", "ps-importance-hidden", 1, "ps-small", "ps-muted"], [1, "ps-small", "ps-muted"], ["data-testid", "ps-leakage-gate", 1, "ps-callout", "gate"], [1, "ps-small", 2, "margin-top", "6px"], [1, "fa-solid", "fa-pen"], [1, "ps-card-body", "ps-row", 2, "align-items", "center", "flex-wrap", "wrap", "gap", "8px"], [1, "ps-muted", "ps-small", 2, "flex", "1"], ["mjButton", "", "variant", "secondary", "size", "sm", "data-testid", "ps-registry-validate"], ["mjButton", "", "variant", "primary", "size", "sm", "data-testid", "ps-registry-promote"], ["mjButton", "", "variant", "secondary", "size", "sm", "data-testid", "ps-registry-archive"], ["mjButton", "", "variant", "secondary", "size", "sm", "data-testid", "ps-registry-validate", 3, "click"], [1, "fa-solid", "fa-circle-check"], ["mjButton", "", "variant", "primary", "size", "sm", "data-testid", "ps-registry-promote", 3, "click"], [1, "fa-solid", "fa-arrow-up"], ["mjButton", "", "variant", "secondary", "size", "sm", "data-testid", "ps-registry-archive", 3, "click"], [1, "fa-solid", "fa-box-archive"], [1, "ps-modal-backdrop", 3, "click"], ["data-testid", "ps-confirm-modal", 1, "ps-modal", 3, "click"], [1, "ps-modal-head"], [1, "ico"], [1, "ps-modal-body"], [3, "innerHTML"], [1, "ps-field", 2, "margin-top", "12px"], [1, "ps-modal-foot"], ["mjButton", "", "size", "sm", 3, "click", "variant", "disabled"], [1, "fa-solid", "fa-circle-notch", "fa-spin"], [3, "class"], [1, "ps-spacer", 2, "flex", "1"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click", "disabled"], ["rows", "3", 1, "ps-input", 3, "ngModelChange", "ngModel", "placeholder", "disabled"], [1, "ps-empty-ico"], [1, "ps-muted"]], template: function PSModelDetailComponent_Template(rf, ctx) { if (rf & 1) {
|
|
848
942
|
i0.ɵɵelementStart(0, "div", 0);
|
|
849
|
-
i0.ɵɵconditionalCreate(1, PSModelDetailComponent_Conditional_1_Template,
|
|
943
|
+
i0.ɵɵconditionalCreate(1, PSModelDetailComponent_Conditional_1_Template, 58, 18)(2, PSModelDetailComponent_Conditional_2_Template, 7, 0, "div", 1);
|
|
850
944
|
i0.ɵɵelementEnd();
|
|
851
945
|
} if (rf & 2) {
|
|
852
946
|
i0.ɵɵadvance();
|
|
@@ -855,7 +949,7 @@ export class PSModelDetailComponent {
|
|
|
855
949
|
}
|
|
856
950
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PSModelDetailComponent, [{
|
|
857
951
|
type: Component,
|
|
858
|
-
args: [{ standalone: true, selector: 'ps-model-detail', imports: [CommonModule, FormsModule, MJButtonDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ps-model-detail\" data-testid=\"ps-model-detail\">\n @if (model) {\n <!-- 1. Header Card -->\n <div class=\"ps-card\">\n <div class=\"ps-card-body dh\">\n <div class=\"big-ico\"><i class=\"fa-solid fa-cube\"></i></div>\n <div style=\"flex:1;min-width:0;\">\n <h2 data-testid=\"ps-registry-detail-name\">\n {{ modelDisplayName }}\n <span class=\"ps-tag ps-mono\">v{{ model.Version }}</span>\n </h2>\n <div class=\"ps-muted ps-small sub\">\n {{ model.Algorithm || 'Model' }}{{ targetSuffix }} • immutable snapshot\n </div>\n </div>\n <span class=\"ps-badge\" [class]=\"statusBadgeClass(model.Status)\">{{ model.Status }}</span>\n </div>\n </div>\n\n <!-- 2. Lifecycle Stepper -->\n <div class=\"ps-card\">\n <div class=\"ps-card-body\">\n <div class=\"ps-section-title\">Lifecycle</div>\n <div class=\"ps-stepper\">\n @for (step of lifecycleSteps; track step; let last = $last) {\n <div class=\"ps-step\" [class.done]=\"stepState(step) === 'done'\" [class.curr]=\"stepState(step) === 'curr'\">\n <span class=\"pip\">\n @if (stepState(step) === 'done') {\n <i class=\"fa-solid fa-check\"></i>\n } @else {\n {{ $index + 1 }}\n }\n </span>\n {{ step }}\n </div>\n @if (!last) {\n <span class=\"ln\"></span>\n }\n }\n </div>\n <div class=\"ps-small ps-muted\" style=\"margin-top:10px\">\n Models are immutable once registered; promotion only changes lifecycle state, never weights.\n </div>\n </div>\n </div>\n\n <!-- 3. Performance Metrics -->\n <div class=\"ps-card\">\n <div class=\"ps-card-head\">\n <h3>Performance</h3>\n <span class=\"ps-muted ps-small\">Holdout = held-out test fold, never seen in training</span>\n </div>\n <div class=\"ps-card-body\">\n <div class=\"metric-pair\">\n <div class=\"mtile\">\n <div class=\"ps-section-title\">Train {{ primaryScoreLabel }}</div>\n <div class=\"v\">{{ trainPrimaryScore }}</div>\n <div class=\"ps-muted ps-small\">in-sample • optimistic</div>\n </div>\n <div class=\"mtile honest\">\n <div class=\"ps-section-title\">Holdout {{ primaryScoreLabel }}</div>\n <div class=\"v\">{{ holdoutPrimaryScore }}</div>\n <div class=\"ps-muted ps-small\">out-of-sample • the honest number</div>\n </div>\n </div>\n\n @if (secondaryMetrics.length > 0) {\n <div class=\"stat-bar\">\n @for (s of secondaryMetrics; track s.key) {\n <div class=\"b\">\n <span class=\"ps-muted ps-small\">{{ s.label }}</span>\n <strong>{{ s.value }}</strong>\n </div>\n }\n </div>\n } @else {\n <div class=\"ps-small ps-muted\" style=\"margin-top:6px\">No secondary metrics recorded for this model.</div>\n }\n\n @if (gapText) {\n <div class=\"ps-small ps-muted\" style=\"margin-top:10px\">\n Train\u2013holdout gap of <strong>{{ gapText }}</strong> {{ gapVerdict }}.\n </div>\n }\n </div>\n </div>\n\n <!-- 4. Feature Importance -->\n <div class=\"ps-card\">\n <div class=\"ps-card-head\">\n <h3>Feature Importance</h3>\n <span class=\"ps-muted ps-small\">{{ importanceCaption }}</span>\n </div>\n <div class=\"ps-card-body\">\n @if (importance.length > 0) {\n @for (f of importance; track f.name) {\n <div class=\"ps-fbar\">\n <span class=\"name ps-small\" [title]=\"f.name\">{{ f.name }}</span>\n <div class=\"track\">\n <span [class.warn]=\"f.warning\" [style.width.%]=\"f.pct\"></span>\n </div>\n <span class=\"ps-mono\">{{ f.value }}</span>\n </div>\n }\n } @else {\n <div class=\"ps-small ps-muted\">No feature-importance data was recorded for this model.</div>\n }\n </div>\n </div>\n\n <!-- 5. Leakage Sign-Off Gate -->\n @if (importance.length > 0) {\n <div class=\"ps-callout gate\" [class.success]=\"!leakageFlagged\" [class.warn]=\"leakageFlagged\">\n <i [class]=\"leakageFlagged ? 'fa-solid fa-triangle-exclamation' : 'fa-solid fa-shield-halved'\"></i>\n <div>\n @if (leakageFlagged) {\n <strong>Leakage flag raised.</strong> A single feature dominates \u2014 top importance is\n <strong>{{ topFeatureName }} at {{ topFeatureValue }}</strong>, at/above the\n <strong>{{ dominanceThreshold }}</strong> dominance threshold.\n <div class=\"ps-small\" style=\"margin-top:6px\">\n <i class=\"fa-solid fa-pen\"></i> Sign-off with a reason is required to publish this model.\n </div>\n } @else {\n <strong>Leakage gate clear.</strong> No single feature dominates \u2014 top importance is\n <strong>{{ topFeatureName }} at {{ topFeatureValue }}</strong>, below the\n <strong>{{ dominanceThreshold }}</strong> dominance threshold.\n <div class=\"ps-small\" style=\"margin-top:6px\">\n <i class=\"fa-solid fa-check\"></i> Sign-off required before any Validated → Published promotion.\n </div>\n }\n </div>\n </div>\n }\n\n <!-- 6. Lifecycle Actions -->\n @if (showActions) {\n <div class=\"ps-card\">\n <div class=\"ps-card-body ps-row\" style=\"align-items:center;flex-wrap:wrap;gap:8px\">\n <span class=\"ps-muted ps-small\" style=\"flex:1\">{{ actionHint }}</span>\n @if (canValidate) {\n <button mjButton variant=\"secondary\" size=\"sm\" data-testid=\"ps-registry-validate\" (click)=\"requestPromote('Validated')\">\n <i class=\"fa-solid fa-circle-check\"></i> Mark Validated\n </button>\n }\n @if (canPublish) {\n <button mjButton variant=\"primary\" size=\"sm\" data-testid=\"ps-registry-promote\" (click)=\"requestPromote('Published')\">\n <i class=\"fa-solid fa-arrow-up\"></i> Promote to Published\n </button>\n }\n @if (canArchive) {\n <button mjButton variant=\"secondary\" size=\"sm\" data-testid=\"ps-registry-archive\" (click)=\"requestPromote('Archived')\">\n <i class=\"fa-solid fa-box-archive\"></i> Archive\n </button>\n }\n </div>\n </div>\n }\n\n <!-- 7. Confirm Promotion Modal -->\n @if (pending) {\n <div class=\"ps-modal-backdrop\" (click)=\"cancelPromote()\">\n <div class=\"ps-modal\" (click)=\"$event.stopPropagation()\" data-testid=\"ps-confirm-modal\">\n <div class=\"ps-modal-head\" [class.warn]=\"pendingVariant === 'warn'\" [class.danger]=\"pendingVariant === 'danger'\">\n <span class=\"ico\"><i [class]=\"pendingIcon\"></i></span>\n <h3>{{ pendingTitle }}</h3>\n </div>\n <div class=\"ps-modal-body\">\n <div [innerHTML]=\"pendingMessage\"></div>\n @if (pending.leakageFlagged || pending.targetStatus === 'Archived') {\n <div class=\"ps-field\" style=\"margin-top:12px\">\n <label>\n {{ pending.leakageFlagged ? 'Leakage sign-off reason' : 'Reason (optional)' }}\n {{ pending.leakageFlagged ? ' *' : '' }}\n </label>\n <textarea\n class=\"ps-input\"\n rows=\"3\"\n [(ngModel)]=\"pendingReason\"\n [placeholder]=\"pending.leakageFlagged ? 'Explain why this model is safe to publish despite the leakage flag\u2026' : 'Add an optional note for the record\u2026'\"\n [disabled]=\"busy\"></textarea>\n </div>\n }\n </div>\n <div class=\"ps-modal-foot\">\n <button\n mjButton\n [variant]=\"pendingVariant === 'danger' ? 'danger' : 'primary'\"\n size=\"sm\"\n [disabled]=\"busy || (pending.leakageFlagged && !pendingReason.trim())\"\n (click)=\"confirmPromote(pendingReason.trim())\">\n @if (busy) {\n <i class=\"fa-solid fa-circle-notch fa-spin\"></i>\n } @else {\n <i [class]=\"pendingIcon\"></i>\n }\n {{ pendingConfirmLabel }}\n </button>\n <span class=\"ps-spacer\" style=\"flex:1\"></span>\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"busy\" (click)=\"cancelPromote()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n } @else {\n <div class=\"ps-empty\" style=\"padding: 32px; text-align: center;\">\n <span class=\"ps-empty-ico\"><i class=\"fa-solid fa-cube\"></i></span>\n <h3>No Model Selected</h3>\n <p class=\"ps-muted\">Select an ML Model from the list to inspect its configuration and metrics.</p>\n </div>\n }\n</div>\n", styles: ["/* PSModelDetailComponent Styles \u2014 Design Token Compliant */\n\n.ps-model-detail {\n display: flex;\n flex-direction: column;\n gap: 16px;\n width: 100%;\n color: var(--mj-text-primary);\n background: transparent;\n font-family: inherit;\n}\n\n/* ---- generic helpers ---- */\n.ps-model-detail .ps-row { display: flex; gap: 16px; }\n.ps-model-detail .ps-col { display: flex; flex-direction: column; gap: 16px; }\n.ps-model-detail .ps-spacer { flex: 1; }\n.ps-model-detail .ps-muted { color: var(--mj-text-muted); }\n.ps-model-detail .ps-small { font-size: 12.5px; }\n.ps-model-detail .ps-mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-model-detail .ps-section-title {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: .06em;\n color: var(--mj-text-muted);\n margin: 4px 0 2px;\n font-weight: 700;\n}\n\n/* ---- cards ---- */\n.ps-model-detail .ps-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n.ps-model-detail .ps-card-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n}\n.ps-model-detail .ps-card-head h3 {\n font-size: 14.5px;\n margin: 0;\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n.ps-model-detail .ps-card-body {\n padding: 16px;\n}\n\n/* ---- badges & tags ---- */\n.ps-model-detail .ps-badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 3px 10px;\n border-radius: 999px;\n font-size: 11.5px;\n font-weight: 650;\n line-height: 1.5;\n}\n.ps-model-detail .ps-badge.gray { background: var(--mj-bg-surface-sunken, #f3f4f6); color: var(--mj-text-secondary); }\n.ps-model-detail .ps-badge.blue { background: var(--mj-status-info-bg, #eff6ff); color: var(--mj-status-info-text, #1d4ed8); }\n.ps-model-detail .ps-badge.green { background: var(--mj-status-success-bg, #f0fdf4); color: var(--mj-status-success-text, #15803d); }\n.ps-model-detail .ps-badge.amber { background: var(--mj-status-warning-bg, #fffbeb); color: var(--mj-status-warning-text, #b45309); }\n.ps-model-detail .ps-badge.red { background: var(--mj-status-error-bg, #fef2f2); color: var(--mj-status-error-text, #b91c1c); }\n\n.ps-model-detail .ps-tag {\n display: inline-flex;\n align-items: center;\n padding: 2px 7px;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 600;\n background: var(--mj-bg-surface-sunken, #f3f4f6);\n color: var(--mj-text-secondary);\n}\n\n/* ---- detail header ---- */\n.ps-model-detail .dh {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n.ps-model-detail .big-ico {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: grid;\n place-items: center;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 20px;\n flex: 0 0 auto;\n}\n.ps-model-detail .dh h2 {\n font-size: 18px;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n font-weight: 700;\n}\n.ps-model-detail .dh .sub {\n margin-top: 2px;\n}\n\n/* ---- stepper ---- */\n.ps-model-detail .ps-stepper {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n.ps-model-detail .ps-step {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-muted);\n}\n.ps-model-detail .ps-step.curr {\n color: var(--mj-text-primary);\n}\n.ps-model-detail .ps-step.done {\n color: var(--mj-status-success, #15803d);\n}\n.ps-model-detail .ps-step .pip {\n width: 22px;\n height: 22px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n font-size: 11px;\n border: 1.5px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n}\n.ps-model-detail .ps-step.curr .pip {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n font-weight: 700;\n}\n.ps-model-detail .ps-step.done .pip {\n background: var(--mj-status-success, #15803d);\n border-color: var(--mj-status-success, #15803d);\n color: var(--mj-text-inverse);\n}\n.ps-model-detail .ps-stepper .ln {\n flex: 1;\n min-width: 16px;\n height: 2px;\n background: var(--mj-border-default);\n}\n\n/* ---- performance metrics ---- */\n.ps-model-detail .metric-pair {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n}\n@media (max-width: 640px) {\n .ps-model-detail .metric-pair {\n grid-template-columns: 1fr;\n }\n}\n.ps-model-detail .mtile {\n border: 1px solid var(--mj-border-default);\n border-radius: 9px;\n padding: 14px;\n background: var(--mj-bg-surface);\n}\n.ps-model-detail .mtile .v {\n font-size: 28px;\n font-weight: 720;\n color: var(--mj-text-primary);\n letter-spacing: -.02em;\n}\n.ps-model-detail .mtile.honest {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 6%, var(--mj-bg-surface));\n}\n.ps-model-detail .mtile.honest .v {\n color: var(--mj-brand-primary);\n}\n\n.ps-model-detail .stat-bar {\n display: flex;\n gap: 10px;\n margin-top: 14px;\n flex-wrap: wrap;\n}\n.ps-model-detail .stat-bar .b {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 8px 12px;\n border: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n border-radius: 8px;\n flex: 1;\n min-width: 90px;\n}\n.ps-model-detail .stat-bar .b strong {\n color: var(--mj-text-primary);\n font-size: 15px;\n}\n\n/* ---- feature importance bars ---- */\n.ps-model-detail .ps-fbar {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 8px;\n}\n.ps-model-detail .ps-fbar .name {\n width: 170px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n flex-shrink: 0;\n color: var(--mj-text-secondary);\n}\n.ps-model-detail .ps-fbar .track {\n flex: 1;\n height: 8px;\n background: var(--mj-bg-surface-sunken, #f3f4f6);\n border-radius: 999px;\n overflow: hidden;\n}\n.ps-model-detail .ps-fbar .track span {\n display: block;\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 999px;\n}\n.ps-model-detail .ps-fbar .track span.warn {\n background: var(--mj-status-warning, #d98213);\n}\n\n/* ---- leakage gate callout ---- */\n.ps-model-detail .ps-callout {\n display: flex;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n}\n.ps-model-detail .ps-callout.gate {\n align-items: flex-start;\n}\n.ps-model-detail .ps-callout.gate i {\n font-size: 20px;\n margin-top: 2px;\n}\n.ps-model-detail .ps-callout.success {\n background: var(--mj-status-success-bg, #f0fdf4);\n border-color: color-mix(in srgb, var(--mj-status-success) 25%, transparent);\n color: var(--mj-status-success-text, #15803d);\n}\n.ps-model-detail .ps-callout.warn {\n background: var(--mj-status-warning-bg, #fffbeb);\n border-color: color-mix(in srgb, var(--mj-status-warning) 25%, transparent);\n color: var(--mj-status-warning-text, #b45309);\n}\n\n/* ---- confirmation modal ---- */\n.ps-model-detail .ps-modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.45);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n}\n.ps-model-detail .ps-modal {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n width: 100%;\n max-width: 480px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n}\n.ps-model-detail .ps-modal-head {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n}\n.ps-model-detail .ps-modal-head .ico {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n display: grid;\n place-items: center;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 15px;\n}\n.ps-model-detail .ps-modal-head.warn .ico {\n background: var(--mj-status-warning, #d98213);\n}\n.ps-model-detail .ps-modal-head.danger .ico {\n background: var(--mj-status-error, #b91c1c);\n}\n.ps-model-detail .ps-modal-head h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n}\n.ps-model-detail .ps-modal-body {\n padding: 20px;\n font-size: 13.5px;\n line-height: 1.5;\n}\n.ps-model-detail .ps-modal-foot {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n background: var(--mj-bg-surface-sunken, #f9fafb);\n}\n.ps-model-detail .ps-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ps-model-detail .ps-field label {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n.ps-model-detail .ps-input {\n width: 100%;\n padding: 8px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-family: inherit;\n font-size: 13px;\n resize: vertical;\n}\n.ps-model-detail .ps-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n"] }]
|
|
952
|
+
args: [{ standalone: true, selector: 'ps-model-detail', imports: [CommonModule, FormsModule, MJButtonDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ps-model-detail\" data-testid=\"ps-model-detail\">\n @if (model) {\n <!-- 1. Header Card -->\n <div class=\"ps-card\">\n <div class=\"ps-card-body dh\">\n <div class=\"big-ico\"><i class=\"fa-solid fa-cube\"></i></div>\n <div style=\"flex:1;min-width:0;\">\n <h2 data-testid=\"ps-registry-detail-name\">\n {{ modelDisplayName }}\n <span class=\"ps-tag ps-mono\">v{{ model.Version }}</span>\n </h2>\n <div class=\"ps-muted ps-small sub\">\n {{ model.Algorithm || 'Model' }}{{ targetSuffix }} • immutable snapshot\n </div>\n </div>\n <span class=\"ps-badge\" [class]=\"statusBadgeClass(model.Status)\">{{ model.Status }}</span>\n </div>\n </div>\n\n <!-- 2. Lifecycle Stepper -->\n <div class=\"ps-card\">\n <div class=\"ps-card-body\">\n <div class=\"ps-section-title\">Lifecycle</div>\n <div class=\"ps-stepper\">\n @for (step of lifecycleSteps; track step; let last = $last) {\n <div class=\"ps-step\" [class.done]=\"stepState(step) === 'done'\" [class.curr]=\"stepState(step) === 'curr'\">\n <span class=\"pip\">\n @if (stepState(step) === 'done') {\n <i class=\"fa-solid fa-check\"></i>\n } @else {\n {{ $index + 1 }}\n }\n </span>\n {{ step }}\n </div>\n @if (!last) {\n <span class=\"ln\"></span>\n }\n }\n </div>\n <div class=\"ps-small ps-muted\" style=\"margin-top:10px\">\n Models are immutable once registered; promotion only changes lifecycle state, never weights.\n </div>\n </div>\n </div>\n\n <!-- 3. Performance Metrics -->\n <div class=\"ps-card\">\n <div class=\"ps-card-head\">\n <h3>Performance</h3>\n <span class=\"ps-muted ps-small\">Holdout = held-out test fold, never seen in training</span>\n </div>\n <div class=\"ps-card-body\">\n <div class=\"metric-pair\">\n <div class=\"mtile\">\n <div class=\"ps-section-title\">Train {{ primaryScoreLabel }}</div>\n <div class=\"v\">{{ trainPrimaryScore }}</div>\n <div class=\"ps-muted ps-small\">in-sample • optimistic</div>\n </div>\n <div class=\"mtile honest\">\n <div class=\"ps-section-title\">Holdout {{ primaryScoreLabel }}</div>\n <div class=\"v\">{{ holdoutPrimaryScore }}</div>\n <div class=\"ps-muted ps-small\">out-of-sample • the honest number</div>\n </div>\n </div>\n\n @if (secondaryMetrics.length > 0) {\n <div class=\"stat-bar\">\n @for (s of secondaryMetrics; track s.key) {\n <div class=\"b\">\n <span class=\"ps-muted ps-small\">{{ s.label }}</span>\n <strong>{{ s.value }}</strong>\n </div>\n }\n </div>\n } @else {\n <div class=\"ps-small ps-muted\" style=\"margin-top:6px\">No secondary metrics recorded for this model.</div>\n }\n\n @if (gapText) {\n <div class=\"ps-small ps-muted\" style=\"margin-top:10px\">\n Train\u2013holdout gap of <strong>{{ gapText }}</strong> {{ gapVerdict }}.\n </div>\n }\n </div>\n </div>\n\n <!-- 4. Feature Importance -->\n <div class=\"ps-card\">\n <div class=\"ps-card-head\">\n <h3>Feature Importance</h3>\n @if (!ImportanceHidden) {\n <span class=\"ps-muted ps-small\" data-testid=\"ps-importance-caption\">{{ ImportanceCaption }}</span>\n }\n </div>\n <div class=\"ps-card-body\">\n @if (DisplayedImportance.length > 0) {\n @for (f of DisplayedImportance; track f.name) {\n <div class=\"ps-fbar\">\n <span class=\"name ps-small\" [title]=\"f.name\">{{ f.name }}</span>\n <div class=\"track\">\n <span [class.warn]=\"f.warning\" [style.width.%]=\"f.pct\"></span>\n </div>\n <span class=\"ps-mono\">{{ f.value }}</span>\n </div>\n }\n } @else {\n @if (ImportanceHidden) {\n <div class=\"ps-small ps-muted\" data-testid=\"ps-importance-hidden\">{{ ImportanceHiddenNote }}</div>\n } @else {\n <div class=\"ps-small ps-muted\">No feature-importance data was recorded for this model.</div>\n }\n }\n </div>\n </div>\n\n <!-- 5. Leakage Sign-Off Gate -->\n @if (Importance.length > 0) {\n <div class=\"ps-callout gate\" data-testid=\"ps-leakage-gate\" [class.success]=\"!LeakageFlagged\" [class.warn]=\"LeakageFlagged\">\n <i [class]=\"LeakageFlagged ? 'fa-solid fa-triangle-exclamation' : 'fa-solid fa-shield-halved'\"></i>\n <div>\n @if (LeakageFlagged) {\n @if (ImportanceHidden) {\n <strong>Leakage flag raised.</strong> A single feature's split share is at or above the\n <strong>{{ dominanceThreshold }}</strong> dominance threshold.\n } @else {\n <strong>Leakage flag raised.</strong> A single feature dominates \u2014 top importance is\n <strong>{{ TopFeatureName }} at {{ TopFeatureValue }}</strong>, at/above the\n <strong>{{ dominanceThreshold }}</strong> dominance threshold.\n }\n <div class=\"ps-small\" style=\"margin-top:6px\">\n <i class=\"fa-solid fa-pen\"></i> Sign-off with a reason is required to publish this model.\n </div>\n } @else {\n @if (ImportanceHidden) {\n <strong>Leakage gate clear.</strong> No single feature's split share is at or above the\n <strong>{{ dominanceThreshold }}</strong> dominance threshold.\n } @else {\n <strong>Leakage gate clear.</strong> No single feature dominates \u2014 top importance is\n <strong>{{ TopFeatureName }} at {{ TopFeatureValue }}</strong>, below the\n <strong>{{ dominanceThreshold }}</strong> dominance threshold.\n }\n <div class=\"ps-small\" style=\"margin-top:6px\">\n <i class=\"fa-solid fa-check\"></i> Sign-off required before any Validated → Published promotion.\n </div>\n }\n </div>\n </div>\n }\n\n <!-- 6. Lifecycle Actions -->\n @if (showActions) {\n <div class=\"ps-card\">\n <div class=\"ps-card-body ps-row\" style=\"align-items:center;flex-wrap:wrap;gap:8px\">\n <span class=\"ps-muted ps-small\" style=\"flex:1\">{{ actionHint }}</span>\n @if (canValidate) {\n <button mjButton variant=\"secondary\" size=\"sm\" data-testid=\"ps-registry-validate\" (click)=\"requestPromote('Validated')\">\n <i class=\"fa-solid fa-circle-check\"></i> Mark Validated\n </button>\n }\n @if (canPublish) {\n <button mjButton variant=\"primary\" size=\"sm\" data-testid=\"ps-registry-promote\" (click)=\"requestPromote('Published')\">\n <i class=\"fa-solid fa-arrow-up\"></i> Promote to Published\n </button>\n }\n @if (canArchive) {\n <button mjButton variant=\"secondary\" size=\"sm\" data-testid=\"ps-registry-archive\" (click)=\"requestPromote('Archived')\">\n <i class=\"fa-solid fa-box-archive\"></i> Archive\n </button>\n }\n </div>\n </div>\n }\n\n <!-- 7. Confirm Promotion Modal -->\n @if (pending) {\n <div class=\"ps-modal-backdrop\" (click)=\"cancelPromote()\">\n <div class=\"ps-modal\" (click)=\"$event.stopPropagation()\" data-testid=\"ps-confirm-modal\">\n <div class=\"ps-modal-head\" [class.warn]=\"pendingVariant === 'warn'\" [class.danger]=\"pendingVariant === 'danger'\">\n <span class=\"ico\"><i [class]=\"pendingIcon\"></i></span>\n <h3>{{ pendingTitle }}</h3>\n </div>\n <div class=\"ps-modal-body\">\n <div [innerHTML]=\"pendingMessage\"></div>\n @if (pending.leakageFlagged || pending.targetStatus === 'Archived') {\n <div class=\"ps-field\" style=\"margin-top:12px\">\n <label>\n {{ pending.leakageFlagged ? 'Leakage sign-off reason' : 'Reason (optional)' }}\n {{ pending.leakageFlagged ? ' *' : '' }}\n </label>\n <textarea\n class=\"ps-input\"\n rows=\"3\"\n [(ngModel)]=\"pendingReason\"\n [placeholder]=\"pending.leakageFlagged ? 'Explain why this model is safe to publish despite the leakage flag\u2026' : 'Add an optional note for the record\u2026'\"\n [disabled]=\"busy\"></textarea>\n </div>\n }\n </div>\n <div class=\"ps-modal-foot\">\n <button\n mjButton\n [variant]=\"pendingVariant === 'danger' ? 'danger' : 'primary'\"\n size=\"sm\"\n [disabled]=\"busy || (pending.leakageFlagged && !pendingReason.trim())\"\n (click)=\"confirmPromote(pendingReason.trim())\">\n @if (busy) {\n <i class=\"fa-solid fa-circle-notch fa-spin\"></i>\n } @else {\n <i [class]=\"pendingIcon\"></i>\n }\n {{ pendingConfirmLabel }}\n </button>\n <span class=\"ps-spacer\" style=\"flex:1\"></span>\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"busy\" (click)=\"cancelPromote()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n } @else {\n <div class=\"ps-empty\" style=\"padding: 32px; text-align: center;\">\n <span class=\"ps-empty-ico\"><i class=\"fa-solid fa-cube\"></i></span>\n <h3>No Model Selected</h3>\n <p class=\"ps-muted\">Select an ML Model from the list to inspect its configuration and metrics.</p>\n </div>\n }\n</div>\n", styles: ["/* PSModelDetailComponent Styles \u2014 Design Token Compliant */\n\n.ps-model-detail {\n display: flex;\n flex-direction: column;\n gap: 16px;\n width: 100%;\n color: var(--mj-text-primary);\n background: transparent;\n font-family: inherit;\n}\n\n/* ---- generic helpers ---- */\n.ps-model-detail .ps-row { display: flex; gap: 16px; }\n.ps-model-detail .ps-col { display: flex; flex-direction: column; gap: 16px; }\n.ps-model-detail .ps-spacer { flex: 1; }\n.ps-model-detail .ps-muted { color: var(--mj-text-muted); }\n.ps-model-detail .ps-small { font-size: 12.5px; }\n.ps-model-detail .ps-mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-model-detail .ps-section-title {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: .06em;\n color: var(--mj-text-muted);\n margin: 4px 0 2px;\n font-weight: 700;\n}\n\n/* ---- cards ---- */\n.ps-model-detail .ps-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n.ps-model-detail .ps-card-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n}\n.ps-model-detail .ps-card-head h3 {\n font-size: 14.5px;\n margin: 0;\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n.ps-model-detail .ps-card-body {\n padding: 16px;\n}\n\n/* ---- badges & tags ---- */\n.ps-model-detail .ps-badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 3px 10px;\n border-radius: 999px;\n font-size: 11.5px;\n font-weight: 650;\n line-height: 1.5;\n}\n.ps-model-detail .ps-badge.gray { background: var(--mj-bg-surface-sunken, #f3f4f6); color: var(--mj-text-secondary); }\n.ps-model-detail .ps-badge.blue { background: var(--mj-status-info-bg, #eff6ff); color: var(--mj-status-info-text, #1d4ed8); }\n.ps-model-detail .ps-badge.green { background: var(--mj-status-success-bg, #f0fdf4); color: var(--mj-status-success-text, #15803d); }\n.ps-model-detail .ps-badge.amber { background: var(--mj-status-warning-bg, #fffbeb); color: var(--mj-status-warning-text, #b45309); }\n.ps-model-detail .ps-badge.red { background: var(--mj-status-error-bg, #fef2f2); color: var(--mj-status-error-text, #b91c1c); }\n\n.ps-model-detail .ps-tag {\n display: inline-flex;\n align-items: center;\n padding: 2px 7px;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 600;\n background: var(--mj-bg-surface-sunken, #f3f4f6);\n color: var(--mj-text-secondary);\n}\n\n/* ---- detail header ---- */\n.ps-model-detail .dh {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n.ps-model-detail .big-ico {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: grid;\n place-items: center;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 20px;\n flex: 0 0 auto;\n}\n.ps-model-detail .dh h2 {\n font-size: 18px;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n font-weight: 700;\n}\n.ps-model-detail .dh .sub {\n margin-top: 2px;\n}\n\n/* ---- stepper ---- */\n.ps-model-detail .ps-stepper {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n.ps-model-detail .ps-step {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-muted);\n}\n.ps-model-detail .ps-step.curr {\n color: var(--mj-text-primary);\n}\n.ps-model-detail .ps-step.done {\n color: var(--mj-status-success, #15803d);\n}\n.ps-model-detail .ps-step .pip {\n width: 22px;\n height: 22px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n font-size: 11px;\n border: 1.5px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n}\n.ps-model-detail .ps-step.curr .pip {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n font-weight: 700;\n}\n.ps-model-detail .ps-step.done .pip {\n background: var(--mj-status-success, #15803d);\n border-color: var(--mj-status-success, #15803d);\n color: var(--mj-text-inverse);\n}\n.ps-model-detail .ps-stepper .ln {\n flex: 1;\n min-width: 16px;\n height: 2px;\n background: var(--mj-border-default);\n}\n\n/* ---- performance metrics ---- */\n.ps-model-detail .metric-pair {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n}\n@media (max-width: 640px) {\n .ps-model-detail .metric-pair {\n grid-template-columns: 1fr;\n }\n}\n.ps-model-detail .mtile {\n border: 1px solid var(--mj-border-default);\n border-radius: 9px;\n padding: 14px;\n background: var(--mj-bg-surface);\n}\n.ps-model-detail .mtile .v {\n font-size: 28px;\n font-weight: 720;\n color: var(--mj-text-primary);\n letter-spacing: -.02em;\n}\n.ps-model-detail .mtile.honest {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 6%, var(--mj-bg-surface));\n}\n.ps-model-detail .mtile.honest .v {\n color: var(--mj-brand-primary);\n}\n\n.ps-model-detail .stat-bar {\n display: flex;\n gap: 10px;\n margin-top: 14px;\n flex-wrap: wrap;\n}\n.ps-model-detail .stat-bar .b {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 8px 12px;\n border: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n border-radius: 8px;\n flex: 1;\n min-width: 90px;\n}\n.ps-model-detail .stat-bar .b strong {\n color: var(--mj-text-primary);\n font-size: 15px;\n}\n\n/* ---- feature importance bars ---- */\n.ps-model-detail .ps-fbar {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 8px;\n}\n.ps-model-detail .ps-fbar .name {\n width: 170px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n flex-shrink: 0;\n color: var(--mj-text-secondary);\n}\n.ps-model-detail .ps-fbar .track {\n flex: 1;\n height: 8px;\n background: var(--mj-bg-surface-sunken, #f3f4f6);\n border-radius: 999px;\n overflow: hidden;\n}\n.ps-model-detail .ps-fbar .track span {\n display: block;\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 999px;\n}\n.ps-model-detail .ps-fbar .track span.warn {\n background: var(--mj-status-warning, #d98213);\n}\n\n/* ---- leakage gate callout ---- */\n.ps-model-detail .ps-callout {\n display: flex;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n}\n.ps-model-detail .ps-callout.gate {\n align-items: flex-start;\n}\n.ps-model-detail .ps-callout.gate i {\n font-size: 20px;\n margin-top: 2px;\n}\n.ps-model-detail .ps-callout.success {\n background: var(--mj-status-success-bg, #f0fdf4);\n border-color: color-mix(in srgb, var(--mj-status-success) 25%, transparent);\n color: var(--mj-status-success-text, #15803d);\n}\n.ps-model-detail .ps-callout.warn {\n background: var(--mj-status-warning-bg, #fffbeb);\n border-color: color-mix(in srgb, var(--mj-status-warning) 25%, transparent);\n color: var(--mj-status-warning-text, #b45309);\n}\n\n/* ---- confirmation modal ---- */\n.ps-model-detail .ps-modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.45);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n}\n.ps-model-detail .ps-modal {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n width: 100%;\n max-width: 480px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n}\n.ps-model-detail .ps-modal-head {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n}\n.ps-model-detail .ps-modal-head .ico {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n display: grid;\n place-items: center;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 15px;\n}\n.ps-model-detail .ps-modal-head.warn .ico {\n background: var(--mj-status-warning, #d98213);\n}\n.ps-model-detail .ps-modal-head.danger .ico {\n background: var(--mj-status-error, #b91c1c);\n}\n.ps-model-detail .ps-modal-head h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n}\n.ps-model-detail .ps-modal-body {\n padding: 20px;\n font-size: 13.5px;\n line-height: 1.5;\n}\n.ps-model-detail .ps-modal-foot {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n background: var(--mj-bg-surface-sunken, #f9fafb);\n}\n.ps-model-detail .ps-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ps-model-detail .ps-field label {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n.ps-model-detail .ps-input {\n width: 100%;\n padding: 8px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-family: inherit;\n font-size: 13px;\n resize: vertical;\n}\n.ps-model-detail .ps-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n"] }]
|
|
859
953
|
}], null, { Model: [{
|
|
860
954
|
type: Input
|
|
861
955
|
}], model: [{
|
|
@@ -879,5 +973,5 @@ export class PSModelDetailComponent {
|
|
|
879
973
|
}], displayName: [{
|
|
880
974
|
type: Input
|
|
881
975
|
}] }); })();
|
|
882
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PSModelDetailComponent, { className: "PSModelDetailComponent", filePath: "src/lib/custom/MLModels/ps-model-detail.component.ts", lineNumber:
|
|
976
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PSModelDetailComponent, { className: "PSModelDetailComponent", filePath: "src/lib/custom/MLModels/ps-model-detail.component.ts", lineNumber: 67 }); })();
|
|
883
977
|
//# sourceMappingURL=ps-model-detail.component.js.map
|