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