@memberjunction/ng-core-entity-forms 6.2.0 → 6.3.0-edge.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -6
- 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 +3 -3
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-header.panel.js.map +1 -1
- package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.d.ts +12 -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 +293 -230
- package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/add-action-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts +11 -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 +862 -812
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js +2 -2
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts +12 -0
- 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 +821 -763
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
- package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.js +2 -2
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts +10 -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 +700 -605
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.d.ts +10 -0
- package/dist/lib/custom/Actions/action-execution-log-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.js +223 -175
- package/dist/lib/custom/Actions/action-execution-log-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.d.ts +10 -0
- package/dist/lib/custom/Actions/action-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.js +502 -453
- package/dist/lib/custom/Actions/action-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 +3 -3
- package/dist/lib/custom/Companies/company-header.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 +3 -3
- package/dist/lib/custom/Conversations/conversation-header.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 +3 -3
- package/dist/lib/custom/Employees/employee-header.panel.js.map +1 -1
- package/dist/lib/custom/Entities/entity-form.component.d.ts +15 -0
- package/dist/lib/custom/Entities/entity-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Entities/entity-form.component.js +836 -801
- package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
- package/dist/lib/custom/EntityActions/entityaction.form.component.js +2 -2
- package/dist/lib/custom/Files/file-form.component.js +2 -2
- package/dist/lib/custom/Lists/list-form.component.d.ts +5 -0
- package/dist/lib/custom/Lists/list-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Lists/list-form.component.js +355 -338
- package/dist/lib/custom/Lists/list-form.component.js.map +1 -1
- package/dist/lib/custom/MLModels/ml-model-form.component.js +3 -3
- package/dist/lib/custom/MLModels/ml-model-form.component.js.map +1 -1
- package/dist/lib/custom/MLModels/ml-model-view-models.d.ts +17 -35
- package/dist/lib/custom/MLModels/ml-model-view-models.d.ts.map +1 -1
- package/dist/lib/custom/MLModels/ml-model-view-models.js +55 -54
- package/dist/lib/custom/MLModels/ml-model-view-models.js.map +1 -1
- package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts +7 -99
- package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts.map +1 -1
- package/dist/lib/custom/MLModels/ps-model-detail.component.js +124 -303
- package/dist/lib/custom/MLModels/ps-model-detail.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.d.ts +9 -0
- package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.js +493 -444
- package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-run-dialog.component.js +2 -2
- package/dist/lib/custom/Templates/template-param-dialog.component.js +2 -2
- package/dist/lib/custom/Templates/templates-form.component.d.ts +9 -0
- package/dist/lib/custom/Templates/templates-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.js +118 -74
- package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.d.ts +5 -0
- package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +471 -451
- package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.d.ts +5 -0
- package/dist/lib/custom/Tests/test-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.js +312 -289
- package/dist/lib/custom/Tests/test-run-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts +5 -0
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.js +697 -677
- 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 +5 -0
- 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 +453 -433
- 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 +3 -3
- package/dist/lib/custom/Users/user-header.panel.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.d.ts +2 -2
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.js +30 -13
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts +23 -0
- 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 +276 -216
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +7 -1
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js +32 -14
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.js +119 -95
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJComment/mjcomment.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJComment/mjcomment.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJComment/mjcomment.form.component.js +124 -0
- package/dist/lib/generated/Entities/MJComment/mjcomment.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJCommentType/mjcommenttype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJCommentType/mjcommenttype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJCommentType/mjcommenttype.form.component.js +99 -0
- package/dist/lib/generated/Entities/MJCommentType/mjcommenttype.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js +2 -2
- package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJConversationType/mjconversationtype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJConversationType/mjconversationtype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJConversationType/mjconversationtype.form.component.js +95 -0
- package/dist/lib/generated/Entities/MJConversationType/mjconversationtype.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJDocumentSequenceCounter/mjdocumentsequencecounter.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJDocumentSequenceCounter/mjdocumentsequencecounter.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJDocumentSequenceCounter/mjdocumentsequencecounter.form.component.js +60 -0
- package/dist/lib/generated/Entities/MJDocumentSequenceCounter/mjdocumentsequencecounter.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +124 -106
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityFieldValue/mjentityfieldvalue.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityFieldValue/mjentityfieldvalue.form.component.js +12 -4
- package/dist/lib/generated/Entities/MJEntityFieldValue/mjentityfieldvalue.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityOrganicKey/mjentityorganickey.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityOrganicKey/mjentityorganickey.form.component.js +19 -11
- package/dist/lib/generated/Entities/MJEntityOrganicKey/mjentityorganickey.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityUniqueKey/mjentityuniquekey.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJEntityUniqueKey/mjentityuniquekey.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJEntityUniqueKey/mjentityuniquekey.form.component.js +62 -0
- package/dist/lib/generated/Entities/MJEntityUniqueKey/mjentityuniquekey.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js +26 -12
- package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFieldSuggestion/mjfieldsuggestion.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJFieldSuggestion/mjfieldsuggestion.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJFieldSuggestion/mjfieldsuggestion.form.component.js +140 -0
- package/dist/lib/generated/Entities/MJFieldSuggestion/mjfieldsuggestion.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js +69 -15
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFileStorageProvider/mjfilestorageprovider.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJFileStorageProvider/mjfilestorageprovider.form.component.js +31 -13
- package/dist/lib/generated/Entities/MJFileStorageProvider/mjfilestorageprovider.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMLEvaluationProtocol/mjmlevaluationprotocol.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMLEvaluationProtocol/mjmlevaluationprotocol.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMLEvaluationProtocol/mjmlevaluationprotocol.form.component.js +205 -0
- package/dist/lib/generated/Entities/MJMLEvaluationProtocol/mjmlevaluationprotocol.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMLModel/mjmlmodel.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJMLModel/mjmlmodel.form.component.js +24 -6
- package/dist/lib/generated/Entities/MJMLModel/mjmlmodel.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMLPredictionUnit/mjmlpredictionunit.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMLPredictionUnit/mjmlpredictionunit.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMLPredictionUnit/mjmlpredictionunit.form.component.js +173 -0
- package/dist/lib/generated/Entities/MJMLPredictionUnit/mjmlpredictionunit.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMLTrainingPipeline/mjmltrainingpipeline.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJMLTrainingPipeline/mjmltrainingpipeline.form.component.js +46 -24
- package/dist/lib/generated/Entities/MJMLTrainingPipeline/mjmltrainingpipeline.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMLTrainingRun/mjmltrainingrun.form.component.js +22 -14
- package/dist/lib/generated/Entities/MJMLTrainingRun/mjmltrainingrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMLTrainingSnapshot/mjmltrainingsnapshot.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMLTrainingSnapshot/mjmltrainingsnapshot.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMLTrainingSnapshot/mjmltrainingsnapshot.form.component.js +175 -0
- package/dist/lib/generated/Entities/MJMLTrainingSnapshot/mjmltrainingsnapshot.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJQueryField/mjqueryfield.form.component.js +8 -6
- package/dist/lib/generated/Entities/MJQueryField/mjqueryfield.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 +44 -36
- package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTask/mjtask.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTask/mjtask.form.component.js +54 -32
- package/dist/lib/generated/Entities/MJTask/mjtask.form.component.js.map +1 -1
- package/dist/lib/generated/generated-forms.module.d.ts +452 -443
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +27 -0
- package/dist/lib/generated/generated-forms.module.js.map +1 -1
- package/dist/lib/panels/feature-values/feature-values.panel.js +1 -1
- package/dist/lib/panels/feature-values/feature-values.panel.js.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.logic.js.map +1 -1
- package/dist/lib/shared/components/template-editor.component.js +2 -2
- package/dist/lib/shared/phone-hero.d.ts +17 -0
- package/dist/lib/shared/phone-hero.d.ts.map +1 -0
- package/dist/lib/shared/phone-hero.js +30 -0
- package/dist/lib/shared/phone-hero.js.map +1 -0
- package/dist/lib/shared/phone-sections-state.d.ts +28 -0
- package/dist/lib/shared/phone-sections-state.d.ts.map +1 -0
- package/dist/lib/shared/phone-sections-state.js +38 -0
- package/dist/lib/shared/phone-sections-state.js.map +1 -0
- package/package.json +50 -50
|
@@ -5,13 +5,13 @@ import { MJButtonDirective } from '@memberjunction/ng-ui-components';
|
|
|
5
5
|
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
6
6
|
import { PredictiveStudioPromoteModelOperation, } from '@memberjunction/core-entities';
|
|
7
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
|
+
import { PS_FEATURE_DOMINANCE_THRESHOLD, FormatMetricValue, HumanizeFeatureName, MaxFeatureImportance, MetricsToDisplay, ModelImportanceView, OverfitGap, ParseFeatureImportance, ParseMetrics, PrimaryModelScore, TrainScoreIsInnerCv, } from './ml-model-view-models';
|
|
9
9
|
import * as i0 from "@angular/core";
|
|
10
10
|
import * as i1 from "@angular/forms";
|
|
11
11
|
const _forTrack0 = ($index, $item) => $item.key;
|
|
12
12
|
const _forTrack1 = ($index, $item) => $item.name;
|
|
13
13
|
function PSModelDetailComponent_Conditional_1_For_19_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
14
|
-
i0.ɵɵelement(0, "i",
|
|
14
|
+
i0.ɵɵelement(0, "i", 29);
|
|
15
15
|
} }
|
|
16
16
|
function PSModelDetailComponent_Conditional_1_For_19_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
17
17
|
i0.ɵɵtext(0);
|
|
@@ -20,30 +20,30 @@ function PSModelDetailComponent_Conditional_1_For_19_Conditional_3_Template(rf,
|
|
|
20
20
|
i0.ɵɵtextInterpolate1(" ", $index_r1 + 1, " ");
|
|
21
21
|
} }
|
|
22
22
|
function PSModelDetailComponent_Conditional_1_For_19_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
23
|
-
i0.ɵɵelement(0, "span",
|
|
23
|
+
i0.ɵɵelement(0, "span", 30);
|
|
24
24
|
} }
|
|
25
25
|
function PSModelDetailComponent_Conditional_1_For_19_Template(rf, ctx) { if (rf & 1) {
|
|
26
|
-
i0.ɵɵelementStart(0, "div",
|
|
27
|
-
i0.ɵɵconditionalCreate(2, PSModelDetailComponent_Conditional_1_For_19_Conditional_2_Template, 1, 0, "i",
|
|
26
|
+
i0.ɵɵelementStart(0, "div", 27)(1, "span", 28);
|
|
27
|
+
i0.ɵɵconditionalCreate(2, PSModelDetailComponent_Conditional_1_For_19_Conditional_2_Template, 1, 0, "i", 29)(3, PSModelDetailComponent_Conditional_1_For_19_Conditional_3_Template, 1, 1);
|
|
28
28
|
i0.ɵɵelementEnd();
|
|
29
29
|
i0.ɵɵtext(4);
|
|
30
30
|
i0.ɵɵelementEnd();
|
|
31
|
-
i0.ɵɵconditionalCreate(5, PSModelDetailComponent_Conditional_1_For_19_Conditional_5_Template, 1, 0, "span",
|
|
31
|
+
i0.ɵɵconditionalCreate(5, PSModelDetailComponent_Conditional_1_For_19_Conditional_5_Template, 1, 0, "span", 30);
|
|
32
32
|
} if (rf & 2) {
|
|
33
33
|
const step_r2 = ctx.$implicit;
|
|
34
34
|
const ɵ$index_35_r3 = ctx.$index;
|
|
35
35
|
const ɵ$count_35_r4 = ctx.$count;
|
|
36
36
|
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
37
|
-
i0.ɵɵclassProp("done", ctx_r4.
|
|
37
|
+
i0.ɵɵclassProp("done", ctx_r4.StepState(step_r2) === "done")("curr", ctx_r4.StepState(step_r2) === "curr");
|
|
38
38
|
i0.ɵɵadvance(2);
|
|
39
|
-
i0.ɵɵconditional(ctx_r4.
|
|
39
|
+
i0.ɵɵconditional(ctx_r4.StepState(step_r2) === "done" ? 2 : 3);
|
|
40
40
|
i0.ɵɵadvance(2);
|
|
41
41
|
i0.ɵɵtextInterpolate1(" ", step_r2, " ");
|
|
42
42
|
i0.ɵɵadvance();
|
|
43
43
|
i0.ɵɵconditional(!(ɵ$index_35_r3 === ɵ$count_35_r4 - 1) ? 5 : -1);
|
|
44
44
|
} }
|
|
45
45
|
function PSModelDetailComponent_Conditional_1_Conditional_44_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
46
|
-
i0.ɵɵelementStart(0, "div",
|
|
46
|
+
i0.ɵɵelementStart(0, "div", 31)(1, "span", 16);
|
|
47
47
|
i0.ɵɵtext(2);
|
|
48
48
|
i0.ɵɵelementEnd();
|
|
49
49
|
i0.ɵɵelementStart(3, "strong");
|
|
@@ -57,16 +57,16 @@ function PSModelDetailComponent_Conditional_1_Conditional_44_For_2_Template(rf,
|
|
|
57
57
|
i0.ɵɵtextInterpolate(s_r6.value);
|
|
58
58
|
} }
|
|
59
59
|
function PSModelDetailComponent_Conditional_1_Conditional_44_Template(rf, ctx) { if (rf & 1) {
|
|
60
|
-
i0.ɵɵelementStart(0, "div",
|
|
61
|
-
i0.ɵɵrepeaterCreate(1, PSModelDetailComponent_Conditional_1_Conditional_44_For_2_Template, 5, 2, "div",
|
|
60
|
+
i0.ɵɵelementStart(0, "div", 22);
|
|
61
|
+
i0.ɵɵrepeaterCreate(1, PSModelDetailComponent_Conditional_1_Conditional_44_For_2_Template, 5, 2, "div", 31, _forTrack0);
|
|
62
62
|
i0.ɵɵelementEnd();
|
|
63
63
|
} if (rf & 2) {
|
|
64
64
|
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
65
65
|
i0.ɵɵadvance();
|
|
66
|
-
i0.ɵɵrepeater(ctx_r4.
|
|
66
|
+
i0.ɵɵrepeater(ctx_r4.SecondaryMetrics);
|
|
67
67
|
} }
|
|
68
68
|
function PSModelDetailComponent_Conditional_1_Conditional_45_Template(rf, ctx) { if (rf & 1) {
|
|
69
|
-
i0.ɵɵelementStart(0, "div",
|
|
69
|
+
i0.ɵɵelementStart(0, "div", 23);
|
|
70
70
|
i0.ɵɵtext(1, "No secondary metrics recorded for this model.");
|
|
71
71
|
i0.ɵɵelementEnd();
|
|
72
72
|
} }
|
|
@@ -81,12 +81,12 @@ function PSModelDetailComponent_Conditional_1_Conditional_46_Template(rf, ctx) {
|
|
|
81
81
|
} if (rf & 2) {
|
|
82
82
|
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
83
83
|
i0.ɵɵadvance(3);
|
|
84
|
-
i0.ɵɵtextInterpolate(ctx_r4.
|
|
84
|
+
i0.ɵɵtextInterpolate(ctx_r4.GapText);
|
|
85
85
|
i0.ɵɵadvance();
|
|
86
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r4.
|
|
86
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r4.GapVerdict, ". ");
|
|
87
87
|
} }
|
|
88
88
|
function PSModelDetailComponent_Conditional_1_Conditional_51_Template(rf, ctx) { if (rf & 1) {
|
|
89
|
-
i0.ɵɵelementStart(0, "span",
|
|
89
|
+
i0.ɵɵelementStart(0, "span", 24);
|
|
90
90
|
i0.ɵɵtext(1);
|
|
91
91
|
i0.ɵɵelementEnd();
|
|
92
92
|
} if (rf & 2) {
|
|
@@ -95,13 +95,13 @@ function PSModelDetailComponent_Conditional_1_Conditional_51_Template(rf, ctx) {
|
|
|
95
95
|
i0.ɵɵtextInterpolate(ctx_r4.ImportanceCaption);
|
|
96
96
|
} }
|
|
97
97
|
function PSModelDetailComponent_Conditional_1_Conditional_53_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
98
|
-
i0.ɵɵelementStart(0, "div",
|
|
98
|
+
i0.ɵɵelementStart(0, "div", 32)(1, "span", 33);
|
|
99
99
|
i0.ɵɵtext(2);
|
|
100
100
|
i0.ɵɵelementEnd();
|
|
101
|
-
i0.ɵɵelementStart(3, "div",
|
|
101
|
+
i0.ɵɵelementStart(3, "div", 34);
|
|
102
102
|
i0.ɵɵelement(4, "span");
|
|
103
103
|
i0.ɵɵelementEnd();
|
|
104
|
-
i0.ɵɵelementStart(5, "span",
|
|
104
|
+
i0.ɵɵelementStart(5, "span", 35);
|
|
105
105
|
i0.ɵɵtext(6);
|
|
106
106
|
i0.ɵɵelementEnd()();
|
|
107
107
|
} if (rf & 2) {
|
|
@@ -117,13 +117,13 @@ function PSModelDetailComponent_Conditional_1_Conditional_53_For_1_Template(rf,
|
|
|
117
117
|
i0.ɵɵtextInterpolate(f_r7.value);
|
|
118
118
|
} }
|
|
119
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",
|
|
120
|
+
i0.ɵɵrepeaterCreate(0, PSModelDetailComponent_Conditional_1_Conditional_53_For_1_Template, 7, 7, "div", 32, _forTrack1);
|
|
121
121
|
} if (rf & 2) {
|
|
122
122
|
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
123
123
|
i0.ɵɵrepeater(ctx_r4.DisplayedImportance);
|
|
124
124
|
} }
|
|
125
125
|
function PSModelDetailComponent_Conditional_1_Conditional_54_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
126
|
-
i0.ɵɵelementStart(0, "div",
|
|
126
|
+
i0.ɵɵelementStart(0, "div", 36);
|
|
127
127
|
i0.ɵɵtext(1);
|
|
128
128
|
i0.ɵɵelementEnd();
|
|
129
129
|
} if (rf & 2) {
|
|
@@ -132,12 +132,12 @@ function PSModelDetailComponent_Conditional_1_Conditional_54_Conditional_0_Templ
|
|
|
132
132
|
i0.ɵɵtextInterpolate(ctx_r4.ImportanceHiddenNote);
|
|
133
133
|
} }
|
|
134
134
|
function PSModelDetailComponent_Conditional_1_Conditional_54_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
135
|
-
i0.ɵɵelementStart(0, "div",
|
|
135
|
+
i0.ɵɵelementStart(0, "div", 37);
|
|
136
136
|
i0.ɵɵtext(1, "No feature-importance data was recorded for this model.");
|
|
137
137
|
i0.ɵɵelementEnd();
|
|
138
138
|
} }
|
|
139
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",
|
|
140
|
+
i0.ɵɵconditionalCreate(0, PSModelDetailComponent_Conditional_1_Conditional_54_Conditional_0_Template, 2, 1, "div", 36)(1, PSModelDetailComponent_Conditional_1_Conditional_54_Conditional_1_Template, 2, 0, "div", 37);
|
|
141
141
|
} if (rf & 2) {
|
|
142
142
|
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
143
143
|
i0.ɵɵconditional(ctx_r4.ImportanceHidden ? 0 : 1);
|
|
@@ -154,7 +154,7 @@ function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_3_Condi
|
|
|
154
154
|
} if (rf & 2) {
|
|
155
155
|
const ctx_r4 = i0.ɵɵnextContext(4);
|
|
156
156
|
i0.ɵɵadvance(4);
|
|
157
|
-
i0.ɵɵtextInterpolate(ctx_r4.
|
|
157
|
+
i0.ɵɵtextInterpolate(ctx_r4.DominanceThreshold);
|
|
158
158
|
} }
|
|
159
159
|
function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
160
160
|
i0.ɵɵelementStart(0, "strong");
|
|
@@ -174,12 +174,12 @@ function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_3_Condi
|
|
|
174
174
|
i0.ɵɵadvance(4);
|
|
175
175
|
i0.ɵɵtextInterpolate2("", ctx_r4.TopFeatureName, " at ", ctx_r4.TopFeatureValue);
|
|
176
176
|
i0.ɵɵadvance(3);
|
|
177
|
-
i0.ɵɵtextInterpolate(ctx_r4.
|
|
177
|
+
i0.ɵɵtextInterpolate(ctx_r4.DominanceThreshold);
|
|
178
178
|
} }
|
|
179
179
|
function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
180
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",
|
|
182
|
-
i0.ɵɵelement(3, "i",
|
|
181
|
+
i0.ɵɵelementStart(2, "div", 39);
|
|
182
|
+
i0.ɵɵelement(3, "i", 40);
|
|
183
183
|
i0.ɵɵtext(4, " Sign-off with a reason is required to publish this model. ");
|
|
184
184
|
i0.ɵɵelementEnd();
|
|
185
185
|
} if (rf & 2) {
|
|
@@ -198,7 +198,7 @@ function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Condi
|
|
|
198
198
|
} if (rf & 2) {
|
|
199
199
|
const ctx_r4 = i0.ɵɵnextContext(4);
|
|
200
200
|
i0.ɵɵadvance(4);
|
|
201
|
-
i0.ɵɵtextInterpolate(ctx_r4.
|
|
201
|
+
i0.ɵɵtextInterpolate(ctx_r4.DominanceThreshold);
|
|
202
202
|
} }
|
|
203
203
|
function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
204
204
|
i0.ɵɵelementStart(0, "strong");
|
|
@@ -218,12 +218,12 @@ function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Condi
|
|
|
218
218
|
i0.ɵɵadvance(4);
|
|
219
219
|
i0.ɵɵtextInterpolate2("", ctx_r4.TopFeatureName, " at ", ctx_r4.TopFeatureValue);
|
|
220
220
|
i0.ɵɵadvance(3);
|
|
221
|
-
i0.ɵɵtextInterpolate(ctx_r4.
|
|
221
|
+
i0.ɵɵtextInterpolate(ctx_r4.DominanceThreshold);
|
|
222
222
|
} }
|
|
223
223
|
function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
224
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",
|
|
226
|
-
i0.ɵɵelement(3, "i",
|
|
225
|
+
i0.ɵɵelementStart(2, "div", 39);
|
|
226
|
+
i0.ɵɵelement(3, "i", 29);
|
|
227
227
|
i0.ɵɵtext(4, " Sign-off required before any Validated \u2192 Published promotion. ");
|
|
228
228
|
i0.ɵɵelementEnd();
|
|
229
229
|
} if (rf & 2) {
|
|
@@ -231,7 +231,7 @@ function PSModelDetailComponent_Conditional_1_Conditional_55_Conditional_4_Templ
|
|
|
231
231
|
i0.ɵɵconditional(ctx_r4.ImportanceHidden ? 0 : 1);
|
|
232
232
|
} }
|
|
233
233
|
function PSModelDetailComponent_Conditional_1_Conditional_55_Template(rf, ctx) { if (rf & 1) {
|
|
234
|
-
i0.ɵɵelementStart(0, "div",
|
|
234
|
+
i0.ɵɵelementStart(0, "div", 38);
|
|
235
235
|
i0.ɵɵelement(1, "i");
|
|
236
236
|
i0.ɵɵelementStart(2, "div");
|
|
237
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);
|
|
@@ -246,118 +246,118 @@ function PSModelDetailComponent_Conditional_1_Conditional_55_Template(rf, ctx) {
|
|
|
246
246
|
} }
|
|
247
247
|
function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
248
248
|
const _r8 = i0.ɵɵgetCurrentView();
|
|
249
|
-
i0.ɵɵelementStart(0, "button",
|
|
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.
|
|
251
|
-
i0.ɵɵelement(1, "i",
|
|
249
|
+
i0.ɵɵelementStart(0, "button", 46);
|
|
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", 47);
|
|
252
252
|
i0.ɵɵtext(2, " Mark Validated ");
|
|
253
253
|
i0.ɵɵelementEnd();
|
|
254
254
|
} }
|
|
255
255
|
function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
256
256
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
257
|
-
i0.ɵɵelementStart(0, "button",
|
|
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.
|
|
259
|
-
i0.ɵɵelement(1, "i",
|
|
257
|
+
i0.ɵɵelementStart(0, "button", 48);
|
|
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", 49);
|
|
260
260
|
i0.ɵɵtext(2, " Promote to Published ");
|
|
261
261
|
i0.ɵɵelementEnd();
|
|
262
262
|
} }
|
|
263
263
|
function PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
264
264
|
const _r10 = i0.ɵɵgetCurrentView();
|
|
265
|
-
i0.ɵɵelementStart(0, "button",
|
|
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.
|
|
267
|
-
i0.ɵɵelement(1, "i",
|
|
265
|
+
i0.ɵɵelementStart(0, "button", 50);
|
|
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", 51);
|
|
268
268
|
i0.ɵɵtext(2, " Archive ");
|
|
269
269
|
i0.ɵɵelementEnd();
|
|
270
270
|
} }
|
|
271
271
|
function PSModelDetailComponent_Conditional_1_Conditional_56_Template(rf, ctx) { if (rf & 1) {
|
|
272
|
-
i0.ɵɵelementStart(0, "div", 2)(1, "div",
|
|
272
|
+
i0.ɵɵelementStart(0, "div", 2)(1, "div", 41)(2, "span", 42);
|
|
273
273
|
i0.ɵɵtext(3);
|
|
274
274
|
i0.ɵɵelementEnd();
|
|
275
|
-
i0.ɵɵconditionalCreate(4, PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_4_Template, 3, 0, "button",
|
|
276
|
-
i0.ɵɵconditionalCreate(5, PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_5_Template, 3, 0, "button",
|
|
277
|
-
i0.ɵɵconditionalCreate(6, PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_6_Template, 3, 0, "button",
|
|
275
|
+
i0.ɵɵconditionalCreate(4, PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_4_Template, 3, 0, "button", 43);
|
|
276
|
+
i0.ɵɵconditionalCreate(5, PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_5_Template, 3, 0, "button", 44);
|
|
277
|
+
i0.ɵɵconditionalCreate(6, PSModelDetailComponent_Conditional_1_Conditional_56_Conditional_6_Template, 3, 0, "button", 45);
|
|
278
278
|
i0.ɵɵelementEnd()();
|
|
279
279
|
} if (rf & 2) {
|
|
280
280
|
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
281
281
|
i0.ɵɵadvance(3);
|
|
282
|
-
i0.ɵɵtextInterpolate(ctx_r4.
|
|
282
|
+
i0.ɵɵtextInterpolate(ctx_r4.ActionHint);
|
|
283
283
|
i0.ɵɵadvance();
|
|
284
|
-
i0.ɵɵconditional(ctx_r4.
|
|
284
|
+
i0.ɵɵconditional(ctx_r4.CanValidate ? 4 : -1);
|
|
285
285
|
i0.ɵɵadvance();
|
|
286
|
-
i0.ɵɵconditional(ctx_r4.
|
|
286
|
+
i0.ɵɵconditional(ctx_r4.CanPublish ? 5 : -1);
|
|
287
287
|
i0.ɵɵadvance();
|
|
288
|
-
i0.ɵɵconditional(ctx_r4.
|
|
288
|
+
i0.ɵɵconditional(ctx_r4.CanArchive ? 6 : -1);
|
|
289
289
|
} }
|
|
290
290
|
function PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
291
291
|
const _r12 = i0.ɵɵgetCurrentView();
|
|
292
|
-
i0.ɵɵelementStart(0, "div",
|
|
292
|
+
i0.ɵɵelementStart(0, "div", 58)(1, "label");
|
|
293
293
|
i0.ɵɵtext(2);
|
|
294
294
|
i0.ɵɵelementEnd();
|
|
295
|
-
i0.ɵɵelementStart(3, "textarea",
|
|
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.
|
|
295
|
+
i0.ɵɵelementStart(3, "textarea", 65);
|
|
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); });
|
|
297
297
|
i0.ɵɵelementEnd()();
|
|
298
298
|
} if (rf & 2) {
|
|
299
299
|
const ctx_r4 = i0.ɵɵnextContext(3);
|
|
300
300
|
i0.ɵɵadvance(2);
|
|
301
|
-
i0.ɵɵtextInterpolate2(" ", ctx_r4.
|
|
301
|
+
i0.ɵɵtextInterpolate2(" ", ctx_r4.Pending.leakageFlagged ? "Leakage sign-off reason" : "Reason (optional)", " ", ctx_r4.Pending.leakageFlagged ? " *" : "", " ");
|
|
302
302
|
i0.ɵɵadvance();
|
|
303
|
-
i0.ɵɵtwoWayProperty("ngModel", ctx_r4.
|
|
304
|
-
i0.ɵɵproperty("placeholder", ctx_r4.
|
|
303
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r4.PendingReason);
|
|
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);
|
|
305
305
|
} }
|
|
306
306
|
function PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
307
|
-
i0.ɵɵelement(0, "i",
|
|
307
|
+
i0.ɵɵelement(0, "i", 61);
|
|
308
308
|
} }
|
|
309
309
|
function PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
310
310
|
i0.ɵɵelement(0, "i");
|
|
311
311
|
} if (rf & 2) {
|
|
312
312
|
const ctx_r4 = i0.ɵɵnextContext(3);
|
|
313
|
-
i0.ɵɵclassMap(ctx_r4.
|
|
313
|
+
i0.ɵɵclassMap(ctx_r4.PendingIcon);
|
|
314
314
|
} }
|
|
315
315
|
function PSModelDetailComponent_Conditional_1_Conditional_57_Template(rf, ctx) { if (rf & 1) {
|
|
316
316
|
const _r11 = i0.ɵɵgetCurrentView();
|
|
317
|
-
i0.ɵɵelementStart(0, "div",
|
|
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.
|
|
319
|
-
i0.ɵɵelementStart(1, "div",
|
|
317
|
+
i0.ɵɵelementStart(0, "div", 52);
|
|
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", 53);
|
|
320
320
|
i0.ɵɵlistener("click", function PSModelDetailComponent_Conditional_1_Conditional_57_Template_div_click_1_listener($event) { return $event.stopPropagation(); });
|
|
321
|
-
i0.ɵɵelementStart(2, "div",
|
|
321
|
+
i0.ɵɵelementStart(2, "div", 54)(3, "span", 55);
|
|
322
322
|
i0.ɵɵelement(4, "i");
|
|
323
323
|
i0.ɵɵelementEnd();
|
|
324
324
|
i0.ɵɵelementStart(5, "h3");
|
|
325
325
|
i0.ɵɵtext(6);
|
|
326
326
|
i0.ɵɵelementEnd()();
|
|
327
|
-
i0.ɵɵelementStart(7, "div",
|
|
328
|
-
i0.ɵɵelement(8, "div",
|
|
329
|
-
i0.ɵɵconditionalCreate(9, PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_9_Template, 4, 5, "div",
|
|
327
|
+
i0.ɵɵelementStart(7, "div", 56);
|
|
328
|
+
i0.ɵɵelement(8, "div", 57);
|
|
329
|
+
i0.ɵɵconditionalCreate(9, PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_9_Template, 4, 5, "div", 58);
|
|
330
330
|
i0.ɵɵelementEnd();
|
|
331
|
-
i0.ɵɵelementStart(10, "div",
|
|
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.
|
|
333
|
-
i0.ɵɵconditionalCreate(12, PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_12_Template, 1, 0, "i",
|
|
331
|
+
i0.ɵɵelementStart(10, "div", 59)(11, "button", 60);
|
|
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", 61)(13, PSModelDetailComponent_Conditional_1_Conditional_57_Conditional_13_Template, 1, 2, "i", 62);
|
|
334
334
|
i0.ɵɵtext(14);
|
|
335
335
|
i0.ɵɵelementEnd();
|
|
336
|
-
i0.ɵɵelement(15, "span",
|
|
337
|
-
i0.ɵɵelementStart(16, "button",
|
|
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.
|
|
336
|
+
i0.ɵɵelement(15, "span", 63);
|
|
337
|
+
i0.ɵɵelementStart(16, "button", 64);
|
|
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()); });
|
|
339
339
|
i0.ɵɵtext(17, " Cancel ");
|
|
340
340
|
i0.ɵɵelementEnd()()()();
|
|
341
341
|
} if (rf & 2) {
|
|
342
342
|
const ctx_r4 = i0.ɵɵnextContext(2);
|
|
343
343
|
i0.ɵɵadvance(2);
|
|
344
|
-
i0.ɵɵclassProp("warn", ctx_r4.
|
|
344
|
+
i0.ɵɵclassProp("warn", ctx_r4.PendingVariant === "warn")("danger", ctx_r4.PendingVariant === "danger");
|
|
345
345
|
i0.ɵɵadvance(2);
|
|
346
|
-
i0.ɵɵclassMap(ctx_r4.
|
|
346
|
+
i0.ɵɵclassMap(ctx_r4.PendingIcon);
|
|
347
347
|
i0.ɵɵadvance(2);
|
|
348
|
-
i0.ɵɵtextInterpolate(ctx_r4.
|
|
348
|
+
i0.ɵɵtextInterpolate(ctx_r4.PendingTitle);
|
|
349
349
|
i0.ɵɵadvance(2);
|
|
350
|
-
i0.ɵɵproperty("innerHTML", ctx_r4.
|
|
350
|
+
i0.ɵɵproperty("innerHTML", ctx_r4.PendingMessage, i0.ɵɵsanitizeHtml);
|
|
351
351
|
i0.ɵɵadvance();
|
|
352
|
-
i0.ɵɵconditional(ctx_r4.
|
|
352
|
+
i0.ɵɵconditional(ctx_r4.Pending.leakageFlagged || ctx_r4.Pending.targetStatus === "Archived" ? 9 : -1);
|
|
353
353
|
i0.ɵɵadvance(2);
|
|
354
|
-
i0.ɵɵproperty("variant", ctx_r4.
|
|
354
|
+
i0.ɵɵproperty("variant", ctx_r4.PendingVariant === "danger" ? "danger" : "primary")("disabled", ctx_r4.Busy || ctx_r4.Pending.leakageFlagged && !ctx_r4.PendingReason.trim());
|
|
355
355
|
i0.ɵɵadvance();
|
|
356
|
-
i0.ɵɵconditional(ctx_r4.
|
|
356
|
+
i0.ɵɵconditional(ctx_r4.Busy ? 12 : 13);
|
|
357
357
|
i0.ɵɵadvance(2);
|
|
358
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r4.
|
|
358
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r4.PendingConfirmLabel, " ");
|
|
359
359
|
i0.ɵɵadvance(2);
|
|
360
|
-
i0.ɵɵproperty("disabled", ctx_r4.
|
|
360
|
+
i0.ɵɵproperty("disabled", ctx_r4.Busy);
|
|
361
361
|
} }
|
|
362
362
|
function PSModelDetailComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
363
363
|
i0.ɵɵelementStart(0, "div", 2)(1, "div", 3)(2, "div", 4);
|
|
@@ -395,10 +395,10 @@ function PSModelDetailComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
|
395
395
|
i0.ɵɵelementStart(33, "div", 19);
|
|
396
396
|
i0.ɵɵtext(34);
|
|
397
397
|
i0.ɵɵelementEnd();
|
|
398
|
-
i0.ɵɵelementStart(35, "div",
|
|
399
|
-
i0.ɵɵtext(36
|
|
398
|
+
i0.ɵɵelementStart(35, "div", 20);
|
|
399
|
+
i0.ɵɵtext(36);
|
|
400
400
|
i0.ɵɵelementEnd()();
|
|
401
|
-
i0.ɵɵelementStart(37, "div",
|
|
401
|
+
i0.ɵɵelementStart(37, "div", 21)(38, "div", 12);
|
|
402
402
|
i0.ɵɵtext(39);
|
|
403
403
|
i0.ɵɵelementEnd();
|
|
404
404
|
i0.ɵɵelementStart(40, "div", 19);
|
|
@@ -407,46 +407,48 @@ function PSModelDetailComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
|
407
407
|
i0.ɵɵelementStart(42, "div", 16);
|
|
408
408
|
i0.ɵɵtext(43, "out-of-sample \u2022 the honest number");
|
|
409
409
|
i0.ɵɵelementEnd()()();
|
|
410
|
-
i0.ɵɵconditionalCreate(44, PSModelDetailComponent_Conditional_1_Conditional_44_Template, 3, 0, "div",
|
|
410
|
+
i0.ɵɵconditionalCreate(44, PSModelDetailComponent_Conditional_1_Conditional_44_Template, 3, 0, "div", 22)(45, PSModelDetailComponent_Conditional_1_Conditional_45_Template, 2, 0, "div", 23);
|
|
411
411
|
i0.ɵɵconditionalCreate(46, PSModelDetailComponent_Conditional_1_Conditional_46_Template, 5, 2, "div", 14);
|
|
412
412
|
i0.ɵɵelementEnd()();
|
|
413
413
|
i0.ɵɵelementStart(47, "div", 2)(48, "div", 15)(49, "h3");
|
|
414
414
|
i0.ɵɵtext(50, "Feature Importance");
|
|
415
415
|
i0.ɵɵelementEnd();
|
|
416
|
-
i0.ɵɵconditionalCreate(51, PSModelDetailComponent_Conditional_1_Conditional_51_Template, 2, 1, "span",
|
|
416
|
+
i0.ɵɵconditionalCreate(51, PSModelDetailComponent_Conditional_1_Conditional_51_Template, 2, 1, "span", 24);
|
|
417
417
|
i0.ɵɵelementEnd();
|
|
418
418
|
i0.ɵɵelementStart(52, "div", 11);
|
|
419
419
|
i0.ɵɵconditionalCreate(53, PSModelDetailComponent_Conditional_1_Conditional_53_Template, 2, 0)(54, PSModelDetailComponent_Conditional_1_Conditional_54_Template, 2, 1);
|
|
420
420
|
i0.ɵɵelementEnd()();
|
|
421
|
-
i0.ɵɵconditionalCreate(55, PSModelDetailComponent_Conditional_1_Conditional_55_Template, 5, 7, "div",
|
|
421
|
+
i0.ɵɵconditionalCreate(55, PSModelDetailComponent_Conditional_1_Conditional_55_Template, 5, 7, "div", 25);
|
|
422
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",
|
|
423
|
+
i0.ɵɵconditionalCreate(57, PSModelDetailComponent_Conditional_1_Conditional_57_Template, 18, 14, "div", 26);
|
|
424
424
|
} if (rf & 2) {
|
|
425
425
|
const ctx_r4 = i0.ɵɵnextContext();
|
|
426
426
|
i0.ɵɵadvance(6);
|
|
427
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r4.
|
|
427
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r4.ModelDisplayName, " ");
|
|
428
428
|
i0.ɵɵadvance(2);
|
|
429
|
-
i0.ɵɵtextInterpolate1("v", ctx_r4.
|
|
429
|
+
i0.ɵɵtextInterpolate1("v", ctx_r4.Model.Version);
|
|
430
430
|
i0.ɵɵadvance(2);
|
|
431
|
-
i0.ɵɵtextInterpolate2(" ", ctx_r4.
|
|
431
|
+
i0.ɵɵtextInterpolate2(" ", ctx_r4.Model.Algorithm || "Model", "", ctx_r4.TargetSuffix, " \u2022 immutable snapshot ");
|
|
432
432
|
i0.ɵɵadvance();
|
|
433
|
-
i0.ɵɵclassMap(ctx_r4.
|
|
433
|
+
i0.ɵɵclassMap(ctx_r4.StatusBadgeClass(ctx_r4.Model.Status));
|
|
434
434
|
i0.ɵɵadvance();
|
|
435
|
-
i0.ɵɵtextInterpolate(ctx_r4.
|
|
435
|
+
i0.ɵɵtextInterpolate(ctx_r4.Model.Status);
|
|
436
436
|
i0.ɵɵadvance(6);
|
|
437
|
-
i0.ɵɵrepeater(ctx_r4.
|
|
437
|
+
i0.ɵɵrepeater(ctx_r4.LifecycleSteps);
|
|
438
438
|
i0.ɵɵadvance(14);
|
|
439
|
-
i0.ɵɵtextInterpolate1("Train ", ctx_r4.
|
|
439
|
+
i0.ɵɵtextInterpolate1("Train ", ctx_r4.PrimaryScoreLabel);
|
|
440
440
|
i0.ɵɵadvance(2);
|
|
441
|
-
i0.ɵɵtextInterpolate(ctx_r4.
|
|
442
|
-
i0.ɵɵadvance(5);
|
|
443
|
-
i0.ɵɵtextInterpolate1("Holdout ", ctx_r4.primaryScoreLabel);
|
|
441
|
+
i0.ɵɵtextInterpolate(ctx_r4.TrainPrimaryScore);
|
|
444
442
|
i0.ɵɵadvance(2);
|
|
445
|
-
i0.ɵɵtextInterpolate(ctx_r4.
|
|
443
|
+
i0.ɵɵtextInterpolate(ctx_r4.TrainScoreCaption);
|
|
446
444
|
i0.ɵɵadvance(3);
|
|
447
|
-
i0.ɵɵ
|
|
445
|
+
i0.ɵɵtextInterpolate1("Holdout ", ctx_r4.PrimaryScoreLabel);
|
|
448
446
|
i0.ɵɵadvance(2);
|
|
449
|
-
i0.ɵɵ
|
|
447
|
+
i0.ɵɵtextInterpolate(ctx_r4.HoldoutPrimaryScore);
|
|
448
|
+
i0.ɵɵadvance(3);
|
|
449
|
+
i0.ɵɵconditional(ctx_r4.SecondaryMetrics.length > 0 ? 44 : 45);
|
|
450
|
+
i0.ɵɵadvance(2);
|
|
451
|
+
i0.ɵɵconditional(ctx_r4.GapText ? 46 : -1);
|
|
450
452
|
i0.ɵɵadvance(5);
|
|
451
453
|
i0.ɵɵconditional(!ctx_r4.ImportanceHidden ? 51 : -1);
|
|
452
454
|
i0.ɵɵadvance(2);
|
|
@@ -454,18 +456,18 @@ function PSModelDetailComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
|
454
456
|
i0.ɵɵadvance(2);
|
|
455
457
|
i0.ɵɵconditional(ctx_r4.Importance.length > 0 ? 55 : -1);
|
|
456
458
|
i0.ɵɵadvance();
|
|
457
|
-
i0.ɵɵconditional(ctx_r4.
|
|
459
|
+
i0.ɵɵconditional(ctx_r4.ShowActions ? 56 : -1);
|
|
458
460
|
i0.ɵɵadvance();
|
|
459
|
-
i0.ɵɵconditional(ctx_r4.
|
|
461
|
+
i0.ɵɵconditional(ctx_r4.Pending ? 57 : -1);
|
|
460
462
|
} }
|
|
461
463
|
function PSModelDetailComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
462
|
-
i0.ɵɵelementStart(0, "div", 1)(1, "span",
|
|
464
|
+
i0.ɵɵelementStart(0, "div", 1)(1, "span", 66);
|
|
463
465
|
i0.ɵɵelement(2, "i", 5);
|
|
464
466
|
i0.ɵɵelementEnd();
|
|
465
467
|
i0.ɵɵelementStart(3, "h3");
|
|
466
468
|
i0.ɵɵtext(4, "No Model Selected");
|
|
467
469
|
i0.ɵɵelementEnd();
|
|
468
|
-
i0.ɵɵelementStart(5, "p",
|
|
470
|
+
i0.ɵɵelementStart(5, "p", 67);
|
|
469
471
|
i0.ɵɵtext(6, "Select an ML Model from the list to inspect its configuration and metrics.");
|
|
470
472
|
i0.ɵɵelementEnd()();
|
|
471
473
|
} }
|
|
@@ -478,7 +480,7 @@ function PSModelDetailComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
|
478
480
|
* Renders:
|
|
479
481
|
* - Identity & immutable snapshot badge
|
|
480
482
|
* - Progressive 4-stage lifecycle stepper (Draft → Validated → Published → Archived)
|
|
481
|
-
* -
|
|
483
|
+
* - Train (inner-CV estimate, or in-sample for older models) vs out-of-sample holdout performance cards and overfit gap check
|
|
482
484
|
* - Key feature importance rankings with single-feature dominance warnings
|
|
483
485
|
* - Target leakage gate verification and required sign-off rationale capture
|
|
484
486
|
* - Remote Operation lifecycle promotion (Validate, Publish, Archive)
|
|
@@ -490,14 +492,6 @@ export class PSModelDetailComponent {
|
|
|
490
492
|
this.CurrentUser = null;
|
|
491
493
|
this.ShowActions = true;
|
|
492
494
|
this.StatusChanged = new EventEmitter();
|
|
493
|
-
/**
|
|
494
|
-
* @deprecated Use {@link StatusChanged}.
|
|
495
|
-
*
|
|
496
|
-
* The same emitter under the old binding name, so a template still binding
|
|
497
|
-
* (statusChanged) keeps working. Must stay AFTER StatusChanged: class fields
|
|
498
|
-
* initialise in order, and the other way round this captures undefined.
|
|
499
|
-
*/
|
|
500
|
-
this.statusChanged = this.StatusChanged;
|
|
501
495
|
this.cdr = inject(ChangeDetectorRef);
|
|
502
496
|
this.notifications = inject(MJNotificationService);
|
|
503
497
|
this.LifecycleSteps = ['Draft', 'Validated', 'Published', 'Archived'];
|
|
@@ -511,70 +505,6 @@ export class PSModelDetailComponent {
|
|
|
511
505
|
/** The note shown in place of hidden importance. */
|
|
512
506
|
this.ImportanceHiddenNote = ImportanceDisplay.HiddenNote;
|
|
513
507
|
}
|
|
514
|
-
/** @deprecated Use {@link Model}. */
|
|
515
|
-
set model(value) {
|
|
516
|
-
this.Model = value;
|
|
517
|
-
}
|
|
518
|
-
/** @deprecated Use {@link Model}. */
|
|
519
|
-
get model() {
|
|
520
|
-
return this.Model;
|
|
521
|
-
}
|
|
522
|
-
/** @deprecated Use {@link Provider}. */
|
|
523
|
-
set provider(value) {
|
|
524
|
-
this.Provider = value;
|
|
525
|
-
}
|
|
526
|
-
/** @deprecated Use {@link Provider}. */
|
|
527
|
-
get provider() {
|
|
528
|
-
return this.Provider;
|
|
529
|
-
}
|
|
530
|
-
/** @deprecated Use {@link CurrentUser}. */
|
|
531
|
-
set currentUser(value) {
|
|
532
|
-
this.CurrentUser = value;
|
|
533
|
-
}
|
|
534
|
-
/** @deprecated Use {@link CurrentUser}. */
|
|
535
|
-
get currentUser() {
|
|
536
|
-
return this.CurrentUser;
|
|
537
|
-
}
|
|
538
|
-
/** @deprecated Use {@link ShowActions}. */
|
|
539
|
-
set showActions(value) {
|
|
540
|
-
this.ShowActions = value;
|
|
541
|
-
}
|
|
542
|
-
/** @deprecated Use {@link ShowActions}. */
|
|
543
|
-
get showActions() {
|
|
544
|
-
return this.ShowActions;
|
|
545
|
-
}
|
|
546
|
-
/** @deprecated Use {@link LifecycleSteps}. */
|
|
547
|
-
get lifecycleSteps() {
|
|
548
|
-
return this.LifecycleSteps;
|
|
549
|
-
}
|
|
550
|
-
/** @deprecated Use {@link DominanceThreshold}. */
|
|
551
|
-
get dominanceThreshold() {
|
|
552
|
-
return this.DominanceThreshold;
|
|
553
|
-
}
|
|
554
|
-
/** @deprecated Use {@link Pending}. */
|
|
555
|
-
get pending() {
|
|
556
|
-
return this.Pending;
|
|
557
|
-
}
|
|
558
|
-
/** @deprecated Use {@link Pending}. */
|
|
559
|
-
set pending(value) {
|
|
560
|
-
this.Pending = value;
|
|
561
|
-
}
|
|
562
|
-
/** @deprecated Use {@link PendingReason}. */
|
|
563
|
-
get pendingReason() {
|
|
564
|
-
return this.PendingReason;
|
|
565
|
-
}
|
|
566
|
-
/** @deprecated Use {@link PendingReason}. */
|
|
567
|
-
set pendingReason(value) {
|
|
568
|
-
this.PendingReason = value;
|
|
569
|
-
}
|
|
570
|
-
/** @deprecated Use {@link Busy}. */
|
|
571
|
-
get busy() {
|
|
572
|
-
return this.Busy;
|
|
573
|
-
}
|
|
574
|
-
/** @deprecated Use {@link Busy}. */
|
|
575
|
-
set busy(value) {
|
|
576
|
-
this.Busy = value;
|
|
577
|
-
}
|
|
578
508
|
get ModelDisplayName() {
|
|
579
509
|
if (this.displayName)
|
|
580
510
|
return this.displayName;
|
|
@@ -582,10 +512,6 @@ export class PSModelDetailComponent {
|
|
|
582
512
|
return '';
|
|
583
513
|
return this.Model.Pipeline || (this.Model.Algorithm ? `${this.Model.Algorithm} Model` : 'ML Model');
|
|
584
514
|
}
|
|
585
|
-
/** @deprecated Use {@link ModelDisplayName}. */
|
|
586
|
-
get modelDisplayName() {
|
|
587
|
-
return this.ModelDisplayName;
|
|
588
|
-
}
|
|
589
515
|
// ── Badges & Lifecycle Stepper ──
|
|
590
516
|
StatusBadgeClass(status) {
|
|
591
517
|
switch ((status ?? '').toLowerCase()) {
|
|
@@ -601,10 +527,6 @@ export class PSModelDetailComponent {
|
|
|
601
527
|
return 'gray';
|
|
602
528
|
}
|
|
603
529
|
}
|
|
604
|
-
/** @deprecated Use {@link StatusBadgeClass}. */
|
|
605
|
-
statusBadgeClass(status) {
|
|
606
|
-
return this.StatusBadgeClass(status);
|
|
607
|
-
}
|
|
608
530
|
StepState(step) {
|
|
609
531
|
const order = ['Draft', 'Validated', 'Published', 'Archived'];
|
|
610
532
|
const currIdx = order.indexOf(this.Model?.Status ?? 'Draft');
|
|
@@ -615,28 +537,23 @@ export class PSModelDetailComponent {
|
|
|
615
537
|
return 'curr';
|
|
616
538
|
return 'todo';
|
|
617
539
|
}
|
|
618
|
-
/** @deprecated Use {@link StepState}. */
|
|
619
|
-
stepState(step) {
|
|
620
|
-
return this.StepState(step);
|
|
621
|
-
}
|
|
622
540
|
get TargetSuffix() {
|
|
623
541
|
const target = this.Model?.TargetVariable;
|
|
624
542
|
return target ? ` · predicts ${target}` : '';
|
|
625
543
|
}
|
|
626
|
-
/** @deprecated Use {@link TargetSuffix}. */
|
|
627
|
-
get targetSuffix() {
|
|
628
|
-
return this.TargetSuffix;
|
|
629
|
-
}
|
|
630
544
|
// ── Metrics & Performance Derivations ──
|
|
631
545
|
get PrimaryScoreLabel() {
|
|
632
546
|
if (!this.Model)
|
|
633
547
|
return 'Score';
|
|
634
548
|
const score = PrimaryModelScore(this.Model);
|
|
635
|
-
return score?.label ?? '
|
|
549
|
+
return score?.label ?? 'Score';
|
|
636
550
|
}
|
|
637
|
-
/**
|
|
638
|
-
|
|
639
|
-
|
|
551
|
+
/**
|
|
552
|
+
* What the train tile's number is: for a model trained under an Evaluation Protocol, the inner cross-validation
|
|
553
|
+
* estimate on the development rows; for an older model, its in-sample training score. Optimistic either way.
|
|
554
|
+
*/
|
|
555
|
+
get TrainScoreCaption() {
|
|
556
|
+
return TrainScoreIsInnerCv(this.Model?.Lineage) ? 'inner-CV estimate • optimistic' : 'in-sample • optimistic';
|
|
640
557
|
}
|
|
641
558
|
get TrainPrimaryScore() {
|
|
642
559
|
if (!this.Model)
|
|
@@ -646,11 +563,8 @@ export class PSModelDetailComponent {
|
|
|
646
563
|
if (score && trainMetrics[score.key] != null) {
|
|
647
564
|
return FormatMetricValue(score.key, trainMetrics[score.key]);
|
|
648
565
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
/** @deprecated Use {@link TrainPrimaryScore}. */
|
|
652
|
-
get trainPrimaryScore() {
|
|
653
|
-
return this.TrainPrimaryScore;
|
|
566
|
+
// No value of the primary metric: say so, never another metric's number under the primary metric's title.
|
|
567
|
+
return '—';
|
|
654
568
|
}
|
|
655
569
|
get HoldoutPrimaryScore() {
|
|
656
570
|
if (!this.Model)
|
|
@@ -660,24 +574,17 @@ export class PSModelDetailComponent {
|
|
|
660
574
|
if (score && holdoutMetrics[score.key] != null) {
|
|
661
575
|
return FormatMetricValue(score.key, holdoutMetrics[score.key]);
|
|
662
576
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
/** @deprecated Use {@link HoldoutPrimaryScore}. */
|
|
666
|
-
get holdoutPrimaryScore() {
|
|
667
|
-
return this.HoldoutPrimaryScore;
|
|
577
|
+
// No value of the primary metric: say so, never another metric's number under the primary metric's title.
|
|
578
|
+
return '—';
|
|
668
579
|
}
|
|
669
580
|
get SecondaryMetrics() {
|
|
670
581
|
if (!this.Model)
|
|
671
582
|
return [];
|
|
672
583
|
const score = PrimaryModelScore(this.Model);
|
|
673
584
|
const primaryKey = score?.key;
|
|
585
|
+
// holdout only: the bar sits under the "Holdout = held-out test fold" heading with unqualified labels
|
|
674
586
|
const holdout = MetricsToDisplay(ParseMetrics(this.Model.HoldoutMetrics), { excludeAuc: false });
|
|
675
|
-
|
|
676
|
-
return primaryKey ? all.filter((m) => m.key !== primaryKey) : all.filter((m) => m.key !== 'AUC');
|
|
677
|
-
}
|
|
678
|
-
/** @deprecated Use {@link SecondaryMetrics}. */
|
|
679
|
-
get secondaryMetrics() {
|
|
680
|
-
return this.SecondaryMetrics;
|
|
587
|
+
return primaryKey ? holdout.filter((m) => m.key !== primaryKey) : holdout.filter((m) => m.key !== 'AUC');
|
|
681
588
|
}
|
|
682
589
|
get GapText() {
|
|
683
590
|
if (!this.Model)
|
|
@@ -685,10 +592,6 @@ export class PSModelDetailComponent {
|
|
|
685
592
|
const gap = OverfitGap(this.Model);
|
|
686
593
|
return gap == null ? '' : Math.abs(gap).toFixed(3);
|
|
687
594
|
}
|
|
688
|
-
/** @deprecated Use {@link GapText}. */
|
|
689
|
-
get gapText() {
|
|
690
|
-
return this.GapText;
|
|
691
|
-
}
|
|
692
595
|
get GapVerdict() {
|
|
693
596
|
if (!this.Model)
|
|
694
597
|
return '';
|
|
@@ -697,10 +600,6 @@ export class PSModelDetailComponent {
|
|
|
697
600
|
return '';
|
|
698
601
|
return gap > 0.1 ? 'is wide — watch for overfitting' : 'is within tolerance — no overfitting flag';
|
|
699
602
|
}
|
|
700
|
-
/** @deprecated Use {@link GapVerdict}. */
|
|
701
|
-
get gapVerdict() {
|
|
702
|
-
return this.GapVerdict;
|
|
703
|
-
}
|
|
704
603
|
get cachedImportance() {
|
|
705
604
|
if (!this.Model)
|
|
706
605
|
return { allBars: [], displayedBars: [] };
|
|
@@ -721,10 +620,6 @@ export class PSModelDetailComponent {
|
|
|
721
620
|
get Importance() {
|
|
722
621
|
return this.cachedImportance.allBars;
|
|
723
622
|
}
|
|
724
|
-
/** @deprecated Use {@link Importance}. */
|
|
725
|
-
get importance() {
|
|
726
|
-
return this.Importance;
|
|
727
|
-
}
|
|
728
623
|
/**
|
|
729
624
|
* The importance bars shown in the Feature Importance card (empty for split / impurity importance). Cached on the
|
|
730
625
|
* Lineage JSON (which holds the stored importance kind) and the importance JSON, so the parse runs once per model and
|
|
@@ -743,56 +638,28 @@ export class PSModelDetailComponent {
|
|
|
743
638
|
const n = this.Importance.length;
|
|
744
639
|
return n === 0 ? 'no data' : `normalized · top ${n}`;
|
|
745
640
|
}
|
|
746
|
-
/** @deprecated Use {@link ImportanceCaption}. */
|
|
747
|
-
get importanceCaption() {
|
|
748
|
-
return this.ImportanceCaption;
|
|
749
|
-
}
|
|
750
641
|
get TopFeatureName() {
|
|
751
642
|
return this.Importance[0]?.name ?? '—';
|
|
752
643
|
}
|
|
753
|
-
/** @deprecated Use {@link TopFeatureName}. */
|
|
754
|
-
get topFeatureName() {
|
|
755
|
-
return this.TopFeatureName;
|
|
756
|
-
}
|
|
757
644
|
get TopFeatureValue() {
|
|
758
645
|
return this.Importance[0]?.value ?? '—';
|
|
759
646
|
}
|
|
760
|
-
/** @deprecated Use {@link TopFeatureValue}. */
|
|
761
|
-
get topFeatureValue() {
|
|
762
|
-
return this.TopFeatureValue;
|
|
763
|
-
}
|
|
764
647
|
get LeakageFlagged() {
|
|
765
648
|
if (!this.Model)
|
|
766
649
|
return false;
|
|
767
650
|
const max = MaxFeatureImportance(this.Model.FeatureImportance);
|
|
768
651
|
return max != null && max >= PS_FEATURE_DOMINANCE_THRESHOLD;
|
|
769
652
|
}
|
|
770
|
-
/** @deprecated Use {@link LeakageFlagged}. */
|
|
771
|
-
get leakageFlagged() {
|
|
772
|
-
return this.LeakageFlagged;
|
|
773
|
-
}
|
|
774
653
|
// ── Actions & Promotion Flow ──
|
|
775
654
|
get CanValidate() {
|
|
776
655
|
return this.Model?.Status === 'Draft';
|
|
777
656
|
}
|
|
778
|
-
/** @deprecated Use {@link CanValidate}. */
|
|
779
|
-
get canValidate() {
|
|
780
|
-
return this.CanValidate;
|
|
781
|
-
}
|
|
782
657
|
get CanPublish() {
|
|
783
658
|
return this.Model?.Status === 'Validated';
|
|
784
659
|
}
|
|
785
|
-
/** @deprecated Use {@link CanPublish}. */
|
|
786
|
-
get canPublish() {
|
|
787
|
-
return this.CanPublish;
|
|
788
|
-
}
|
|
789
660
|
get CanArchive() {
|
|
790
661
|
return this.Model?.Status === 'Published' || this.Model?.Status === 'Validated';
|
|
791
662
|
}
|
|
792
|
-
/** @deprecated Use {@link CanArchive}. */
|
|
793
|
-
get canArchive() {
|
|
794
|
-
return this.CanArchive;
|
|
795
|
-
}
|
|
796
663
|
get ActionHint() {
|
|
797
664
|
switch (this.Model?.Status) {
|
|
798
665
|
case 'Draft':
|
|
@@ -807,10 +674,6 @@ export class PSModelDetailComponent {
|
|
|
807
674
|
return '';
|
|
808
675
|
}
|
|
809
676
|
}
|
|
810
|
-
/** @deprecated Use {@link ActionHint}. */
|
|
811
|
-
get actionHint() {
|
|
812
|
-
return this.ActionHint;
|
|
813
|
-
}
|
|
814
677
|
RequestPromote(targetStatus) {
|
|
815
678
|
if (!this.Model)
|
|
816
679
|
return;
|
|
@@ -823,10 +686,6 @@ export class PSModelDetailComponent {
|
|
|
823
686
|
};
|
|
824
687
|
this.cdr.markForCheck();
|
|
825
688
|
}
|
|
826
|
-
/** @deprecated Use {@link RequestPromote}. */
|
|
827
|
-
requestPromote(targetStatus) {
|
|
828
|
-
return this.RequestPromote(targetStatus);
|
|
829
|
-
}
|
|
830
689
|
CancelPromote() {
|
|
831
690
|
if (this.Busy)
|
|
832
691
|
return;
|
|
@@ -834,37 +693,21 @@ export class PSModelDetailComponent {
|
|
|
834
693
|
this.PendingReason = '';
|
|
835
694
|
this.cdr.markForCheck();
|
|
836
695
|
}
|
|
837
|
-
/** @deprecated Use {@link CancelPromote}. */
|
|
838
|
-
cancelPromote() {
|
|
839
|
-
return this.CancelPromote();
|
|
840
|
-
}
|
|
841
696
|
get PendingTitle() {
|
|
842
697
|
if (!this.Pending)
|
|
843
698
|
return '';
|
|
844
699
|
return this.Pending.targetStatus === 'Archived' ? 'Archive model' : `Promote to ${this.Pending.targetStatus}`;
|
|
845
700
|
}
|
|
846
|
-
/** @deprecated Use {@link PendingTitle}. */
|
|
847
|
-
get pendingTitle() {
|
|
848
|
-
return this.PendingTitle;
|
|
849
|
-
}
|
|
850
701
|
get PendingIcon() {
|
|
851
702
|
if (!this.Pending)
|
|
852
703
|
return 'fa-solid fa-check';
|
|
853
704
|
return this.Pending.targetStatus === 'Archived' ? 'fa-solid fa-box-archive' : 'fa-solid fa-arrow-up';
|
|
854
705
|
}
|
|
855
|
-
/** @deprecated Use {@link PendingIcon}. */
|
|
856
|
-
get pendingIcon() {
|
|
857
|
-
return this.PendingIcon;
|
|
858
|
-
}
|
|
859
706
|
get PendingConfirmLabel() {
|
|
860
707
|
if (!this.Pending)
|
|
861
708
|
return 'Confirm';
|
|
862
709
|
return this.Pending.targetStatus === 'Archived' ? 'Archive' : `Promote to ${this.Pending.targetStatus}`;
|
|
863
710
|
}
|
|
864
|
-
/** @deprecated Use {@link PendingConfirmLabel}. */
|
|
865
|
-
get pendingConfirmLabel() {
|
|
866
|
-
return this.PendingConfirmLabel;
|
|
867
|
-
}
|
|
868
711
|
get PendingVariant() {
|
|
869
712
|
if (!this.Pending)
|
|
870
713
|
return 'info';
|
|
@@ -872,10 +715,6 @@ export class PSModelDetailComponent {
|
|
|
872
715
|
return 'warn';
|
|
873
716
|
return this.Pending.leakageFlagged ? 'warn' : 'info';
|
|
874
717
|
}
|
|
875
|
-
/** @deprecated Use {@link PendingVariant}. */
|
|
876
|
-
get pendingVariant() {
|
|
877
|
-
return this.PendingVariant;
|
|
878
|
-
}
|
|
879
718
|
get PendingMessage() {
|
|
880
719
|
if (!this.Pending)
|
|
881
720
|
return '';
|
|
@@ -888,10 +727,6 @@ export class PSModelDetailComponent {
|
|
|
888
727
|
}
|
|
889
728
|
return `Promote <strong>${name}</strong> to <strong>${this.Pending.targetStatus}</strong>? This changes only the lifecycle state — the trained weights never change.`;
|
|
890
729
|
}
|
|
891
|
-
/** @deprecated Use {@link PendingMessage}. */
|
|
892
|
-
get pendingMessage() {
|
|
893
|
-
return this.PendingMessage;
|
|
894
|
-
}
|
|
895
730
|
async ConfirmPromote(reason) {
|
|
896
731
|
if (!this.Pending || this.Busy || !this.Model)
|
|
897
732
|
return;
|
|
@@ -926,10 +761,6 @@ export class PSModelDetailComponent {
|
|
|
926
761
|
this.cdr.markForCheck();
|
|
927
762
|
}
|
|
928
763
|
}
|
|
929
|
-
/** @deprecated Use {@link ConfirmPromote}. */
|
|
930
|
-
async confirmPromote(reason) {
|
|
931
|
-
return this.ConfirmPromote(reason);
|
|
932
|
-
}
|
|
933
764
|
escapeHtml(value) {
|
|
934
765
|
return value
|
|
935
766
|
.replace(/&/g, '&')
|
|
@@ -938,40 +769,30 @@ export class PSModelDetailComponent {
|
|
|
938
769
|
.replace(/"/g, '"');
|
|
939
770
|
}
|
|
940
771
|
static { this.ɵfac = function PSModelDetailComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PSModelDetailComponent)(); }; }
|
|
941
|
-
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PSModelDetailComponent, selectors: [["ps-model-detail"]], inputs: { Model: "Model",
|
|
772
|
+
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PSModelDetailComponent, selectors: [["ps-model-detail"]], inputs: { Model: "Model", Provider: "Provider", CurrentUser: "CurrentUser", ShowActions: "ShowActions", displayName: "displayName" }, outputs: { 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"], ["data-testid", "ps-train-caption", 1, "ps-muted", "ps-small"], [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) {
|
|
942
773
|
i0.ɵɵelementStart(0, "div", 0);
|
|
943
|
-
i0.ɵɵconditionalCreate(1, PSModelDetailComponent_Conditional_1_Template, 58,
|
|
774
|
+
i0.ɵɵconditionalCreate(1, PSModelDetailComponent_Conditional_1_Template, 58, 19)(2, PSModelDetailComponent_Conditional_2_Template, 7, 0, "div", 1);
|
|
944
775
|
i0.ɵɵelementEnd();
|
|
945
776
|
} if (rf & 2) {
|
|
946
777
|
i0.ɵɵadvance();
|
|
947
|
-
i0.ɵɵconditional(ctx.
|
|
778
|
+
i0.ɵɵconditional(ctx.Model ? 1 : 2);
|
|
948
779
|
} }, dependencies: [CommonModule, FormsModule, i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel, MJButtonDirective], styles: ["\n\n.ps-model-detail[_ngcontent-%COMP%] {\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\n.ps-model-detail[_ngcontent-%COMP%] .ps-row[_ngcontent-%COMP%] { display: flex; gap: 16px; }\n.ps-model-detail[_ngcontent-%COMP%] .ps-col[_ngcontent-%COMP%] { display: flex; flex-direction: column; gap: 16px; }\n.ps-model-detail[_ngcontent-%COMP%] .ps-spacer[_ngcontent-%COMP%] { flex: 1; }\n.ps-model-detail[_ngcontent-%COMP%] .ps-muted[_ngcontent-%COMP%] { color: var(--mj-text-muted); }\n.ps-model-detail[_ngcontent-%COMP%] .ps-small[_ngcontent-%COMP%] { font-size: 12.5px; }\n.ps-model-detail[_ngcontent-%COMP%] .ps-mono[_ngcontent-%COMP%] { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-model-detail[_ngcontent-%COMP%] .ps-section-title[_ngcontent-%COMP%] {\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\n.ps-model-detail[_ngcontent-%COMP%] .ps-card[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-card-head[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-card-head[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 14.5px;\n margin: 0;\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-card-body[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n\n.ps-model-detail[_ngcontent-%COMP%] .ps-badge[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-badge.gray[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken, #f3f4f6); color: var(--mj-text-secondary); }\n.ps-model-detail[_ngcontent-%COMP%] .ps-badge.blue[_ngcontent-%COMP%] { background: var(--mj-status-info-bg, #eff6ff); color: var(--mj-status-info-text, #1d4ed8); }\n.ps-model-detail[_ngcontent-%COMP%] .ps-badge.green[_ngcontent-%COMP%] { background: var(--mj-status-success-bg, #f0fdf4); color: var(--mj-status-success-text, #15803d); }\n.ps-model-detail[_ngcontent-%COMP%] .ps-badge.amber[_ngcontent-%COMP%] { background: var(--mj-status-warning-bg, #fffbeb); color: var(--mj-status-warning-text, #b45309); }\n.ps-model-detail[_ngcontent-%COMP%] .ps-badge.red[_ngcontent-%COMP%] { background: var(--mj-status-error-bg, #fef2f2); color: var(--mj-status-error-text, #b91c1c); }\n\n.ps-model-detail[_ngcontent-%COMP%] .ps-tag[_ngcontent-%COMP%] {\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\n.ps-model-detail[_ngcontent-%COMP%] .dh[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n}\n.ps-model-detail[_ngcontent-%COMP%] .big-ico[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .dh[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .dh[_ngcontent-%COMP%] .sub[_ngcontent-%COMP%] {\n margin-top: 2px;\n}\n\n\n.ps-model-detail[_ngcontent-%COMP%] .ps-stepper[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-step[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-step.curr[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-step.done[_ngcontent-%COMP%] {\n color: var(--mj-status-success, #15803d);\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-step[_ngcontent-%COMP%] .pip[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-step.curr[_ngcontent-%COMP%] .pip[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n font-weight: 700;\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-step.done[_ngcontent-%COMP%] .pip[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-stepper[_ngcontent-%COMP%] .ln[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 16px;\n height: 2px;\n background: var(--mj-border-default);\n}\n\n\n.ps-model-detail[_ngcontent-%COMP%] .metric-pair[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n}\n@media (max-width: 640px) {\n .ps-model-detail[_ngcontent-%COMP%] .metric-pair[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n.ps-model-detail[_ngcontent-%COMP%] .mtile[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .mtile[_ngcontent-%COMP%] .v[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 720;\n color: var(--mj-text-primary);\n letter-spacing: -.02em;\n}\n.ps-model-detail[_ngcontent-%COMP%] .mtile.honest[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .mtile.honest[_ngcontent-%COMP%] .v[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.ps-model-detail[_ngcontent-%COMP%] .stat-bar[_ngcontent-%COMP%] {\n display: flex;\n gap: 10px;\n margin-top: 14px;\n flex-wrap: wrap;\n}\n.ps-model-detail[_ngcontent-%COMP%] .stat-bar[_ngcontent-%COMP%] .b[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .stat-bar[_ngcontent-%COMP%] .b[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n font-size: 15px;\n}\n\n\n.ps-model-detail[_ngcontent-%COMP%] .ps-fbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 8px;\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-fbar[_ngcontent-%COMP%] .name[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-fbar[_ngcontent-%COMP%] .track[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-fbar[_ngcontent-%COMP%] .track[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 999px;\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-fbar[_ngcontent-%COMP%] .track[_ngcontent-%COMP%] span.warn[_ngcontent-%COMP%] {\n background: var(--mj-status-warning, #d98213);\n}\n\n\n.ps-model-detail[_ngcontent-%COMP%] .ps-callout[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-callout.gate[_ngcontent-%COMP%] {\n align-items: flex-start;\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-callout.gate[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n margin-top: 2px;\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-callout.success[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-callout.warn[_ngcontent-%COMP%] {\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\n.ps-model-detail[_ngcontent-%COMP%] .ps-modal-backdrop[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-modal[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-modal-head[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-modal-head[_ngcontent-%COMP%] .ico[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-modal-head.warn[_ngcontent-%COMP%] .ico[_ngcontent-%COMP%] {\n background: var(--mj-status-warning, #d98213);\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-modal-head.danger[_ngcontent-%COMP%] .ico[_ngcontent-%COMP%] {\n background: var(--mj-status-error, #b91c1c);\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-modal-head[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-modal-body[_ngcontent-%COMP%] {\n padding: 20px;\n font-size: 13.5px;\n line-height: 1.5;\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-modal-foot[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n.ps-model-detail[_ngcontent-%COMP%] .ps-input[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .ps-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}"], changeDetection: 0 }); }
|
|
949
780
|
}
|
|
950
781
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PSModelDetailComponent, [{
|
|
951
782
|
type: Component,
|
|
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"] }]
|
|
783
|
+
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\" data-testid=\"ps-train-caption\">{{ TrainScoreCaption }}</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"] }]
|
|
953
784
|
}], null, { Model: [{
|
|
954
785
|
type: Input
|
|
955
|
-
}], model: [{
|
|
956
|
-
type: Input
|
|
957
786
|
}], Provider: [{
|
|
958
787
|
type: Input
|
|
959
|
-
}], provider: [{
|
|
960
|
-
type: Input
|
|
961
788
|
}], CurrentUser: [{
|
|
962
789
|
type: Input
|
|
963
|
-
}], currentUser: [{
|
|
964
|
-
type: Input
|
|
965
790
|
}], ShowActions: [{
|
|
966
791
|
type: Input
|
|
967
|
-
}], showActions: [{
|
|
968
|
-
type: Input
|
|
969
792
|
}], StatusChanged: [{
|
|
970
793
|
type: Output
|
|
971
|
-
}], statusChanged: [{
|
|
972
|
-
type: Output
|
|
973
794
|
}], displayName: [{
|
|
974
795
|
type: Input
|
|
975
796
|
}] }); })();
|
|
976
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PSModelDetailComponent, { className: "PSModelDetailComponent", filePath: "src/lib/custom/MLModels/ps-model-detail.component.ts", lineNumber:
|
|
797
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PSModelDetailComponent, { className: "PSModelDetailComponent", filePath: "src/lib/custom/MLModels/ps-model-detail.component.ts", lineNumber: 68 }); })();
|
|
977
798
|
//# sourceMappingURL=ps-model-detail.component.js.map
|