@memberjunction/ng-core-entity-forms 6.1.3 → 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.
Files changed (73) hide show
  1. package/README.md +22 -0
  2. package/dist/lib/custom/MLModels/ml-model-form.component.d.ts +27 -0
  3. package/dist/lib/custom/MLModels/ml-model-form.component.d.ts.map +1 -0
  4. package/dist/lib/custom/MLModels/ml-model-form.component.js +193 -0
  5. package/dist/lib/custom/MLModels/ml-model-form.component.js.map +1 -0
  6. package/dist/lib/custom/MLModels/ml-model-view-models.d.ts +44 -0
  7. package/dist/lib/custom/MLModels/ml-model-view-models.d.ts.map +1 -0
  8. package/dist/lib/custom/MLModels/ml-model-view-models.js +208 -0
  9. package/dist/lib/custom/MLModels/ml-model-view-models.js.map +1 -0
  10. package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts +76 -0
  11. package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts.map +1 -0
  12. package/dist/lib/custom/MLModels/ps-model-detail.component.js +693 -0
  13. package/dist/lib/custom/MLModels/ps-model-detail.component.js.map +1 -0
  14. package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts +27 -7
  15. package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts.map +1 -1
  16. package/dist/lib/custom/RecordProcesses/record-process-form.component.js +496 -19
  17. package/dist/lib/custom/RecordProcesses/record-process-form.component.js.map +1 -1
  18. package/dist/lib/custom/custom-forms.module.d.ts +32 -30
  19. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
  20. package/dist/lib/custom/custom-forms.module.js +21 -4
  21. package/dist/lib/custom/custom-forms.module.js.map +1 -1
  22. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.d.ts.map +1 -1
  23. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js +62 -26
  24. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js.map +1 -1
  25. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.d.ts.map +1 -1
  26. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js +33 -15
  27. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js.map +1 -1
  28. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
  29. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +100 -82
  30. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
  31. package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js +24 -20
  32. package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js.map +1 -1
  33. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.d.ts +10 -0
  34. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.d.ts.map +1 -0
  35. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js +122 -0
  36. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js.map +1 -0
  37. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.d.ts +10 -0
  38. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.d.ts.map +1 -0
  39. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.js +125 -0
  40. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.js.map +1 -0
  41. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.d.ts.map +1 -1
  42. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js +23 -5
  43. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js.map +1 -1
  44. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.d.ts.map +1 -1
  45. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.js +25 -6
  46. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.js.map +1 -1
  47. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.d.ts.map +1 -1
  48. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js +11 -15
  49. package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js.map +1 -1
  50. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.d.ts.map +1 -1
  51. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js +43 -7
  52. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js.map +1 -1
  53. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.d.ts +10 -0
  54. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.d.ts.map +1 -0
  55. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.js +78 -0
  56. package/dist/lib/generated/Entities/MJWebSearchProvider/mjwebsearchprovider.form.component.js.map +1 -0
  57. package/dist/lib/generated/generated-forms.module.d.ts +240 -237
  58. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  59. package/dist/lib/generated/generated-forms.module.js +11 -2
  60. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  61. package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts +95 -0
  62. package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts.map +1 -1
  63. package/dist/lib/panels/model-predictions/model-prediction.logic.js +173 -0
  64. package/dist/lib/panels/model-predictions/model-prediction.logic.js.map +1 -1
  65. package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts +57 -2
  66. package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts.map +1 -1
  67. package/dist/lib/panels/model-predictions/model-prediction.panel.js +555 -64
  68. package/dist/lib/panels/model-predictions/model-prediction.panel.js.map +1 -1
  69. package/dist/public-api.d.ts +4 -0
  70. package/dist/public-api.d.ts.map +1 -1
  71. package/dist/public-api.js +4 -0
  72. package/dist/public-api.js.map +1 -1
  73. package/package.json +42 -41
package/README.md CHANGED
@@ -480,3 +480,25 @@ Virtual entities are defined by setting the `IsVirtualEntity` flag in the entity
480
480
  For more information on virtual entities and implementation, see:
481
481
  - [Virtual Entities Documentation](../../../MJCore/docs/virtual-entities.md)
482
482
 
483
+ ## Predictive Studio Intelligence Panel (`ModelPredictionPanel`)
484
+
485
+ The `ModelPredictionPanel` is a reusable, high-performance form panel that embeds MemberJunction Predictive Studio machine learning insights directly into entity record forms.
486
+
487
+ ### Features
488
+
489
+ - **Score Badges & Risk Levels**: Prominently displays the latest prediction value, confidence interval, and qualitative risk/propensity tier (Low, Medium, High, Critical) with semantic status styling.
490
+ - **Key Drivers & Feature Impacts**: Visualizes the top positive and negative contributing factors for the prediction, showing operators *why* the model scored the record the way it did.
491
+ - **Historical Prediction Timeline**: Graphically tracks how predictions have evolved across past inference cycles, allowing users to spot improving or deteriorating trends.
492
+ - **Two-Way Predictive Studio Deep Linking**:
493
+ - Clicking the model badge or header navigates directly to the model's cockpit in **Predictive Studio** with the active model and evaluation context preselected.
494
+ - Origin crumbs track provenance so operators can jump from record to model and back seamlessly.
495
+
496
+ ### Usage in Custom Record Forms
497
+
498
+ ```typescript
499
+ import { ModelPredictionPanel } from '@memberjunction/ng-core-entity-forms';
500
+
501
+ // In custom entity form template or panel configuration:
502
+ // <mj-model-prediction-panel [entity]="recordEntity" [recordId]="record.ID" />
503
+ ```
504
+
@@ -0,0 +1,27 @@
1
+ import { OnInit } from '@angular/core';
2
+ import { BaseFormPolicy, FormChromeContext, FormChromeSpec } from '@memberjunction/ng-base-forms';
3
+ import { MJMLModelFormComponent } from '../../generated/Entities/MJMLModel/mjmlmodel.form.component';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * Custom form override for `MJ: ML Models` (priority 100).
7
+ * Presents the ML Model in a left-nav experience with:
8
+ * - Lead panel: "Overview & Lifecycle" (<ps-model-detail>)
9
+ * - Details card: Model Identity & Status, Schema & Configuration, Training & Performance
10
+ * - Related grids: ML Training Runs, ML Model Scoring Bindings
11
+ * - More folder: System Metadata
12
+ */
13
+ export declare class MLModelFormComponentExtended extends MJMLModelFormComponent implements OnInit {
14
+ ngOnInit(): Promise<void>;
15
+ static ɵfac: i0.ɵɵFactoryDeclaration<MLModelFormComponentExtended, never>;
16
+ static ɵcmp: i0.ɵɵComponentDeclaration<MLModelFormComponentExtended, "mj-ml-model-form-extended", never, {}, {}, never, never, false, never>;
17
+ }
18
+ /**
19
+ * Policy ensuring that the Overview & Lifecycle panel sits as the lead group
20
+ * before the Details group on the left-nav rail.
21
+ */
22
+ export declare class MLModelFormPolicy extends BaseFormPolicy {
23
+ DecorateChrome(spec: FormChromeSpec, _ctx: FormChromeContext): FormChromeSpec;
24
+ }
25
+ /** Tree-shaking guard so the override and policy register with the ClassFactory. */
26
+ export declare function LoadMLModelFormComponentExtended(): void;
27
+ //# sourceMappingURL=ml-model-form.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ml-model-form.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/custom/MLModels/ml-model-form.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAqB,cAAc,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACrH,OAAO,EAAE,sBAAsB,EAAE,MAAM,6DAA6D,CAAC;;AAErG;;;;;;;GAOG;AACH,qBAOa,4BAA6B,SAAQ,sBAAuB,YAAW,MAAM;IACvE,QAAQ;yCADd,4BAA4B;2CAA5B,4BAA4B;CAaxC;AAED;;;GAGG;AACH,qBACa,iBAAkB,SAAQ,cAAc;IACjC,cAAc,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,iBAAiB,GAAG,cAAc;CAYhG;AAED,oFAAoF;AACpF,wBAAgB,gCAAgC,IAAI,IAAI,CAGvD"}
@@ -0,0 +1,193 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Component } from '@angular/core';
8
+ import { RegisterClass, RegisterClassEx } from '@memberjunction/global';
9
+ import { BaseFormComponent, BaseFormPolicy } from '@memberjunction/ng-base-forms';
10
+ import { MJMLModelFormComponent } from '../../generated/Entities/MJMLModel/mjmlmodel.form.component';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "./ps-model-detail.component";
13
+ import * as i2 from "@memberjunction/ng-base-forms";
14
+ function MLModelFormComponentExtended_Conditional_0_Conditional_29_Template(rf, ctx) { if (rf & 1) {
15
+ const _r3 = i0.ɵɵgetCurrentView();
16
+ i0.ɵɵelementStart(0, "div")(1, "mj-explorer-entity-data-grid", 32);
17
+ i0.ɵɵlistener("Navigate", function MLModelFormComponentExtended_Conditional_0_Conditional_29_Template_mj_explorer_entity_data_grid_Navigate_1_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnFormNavigate($event)); })("AfterDataLoad", function MLModelFormComponentExtended_Conditional_0_Conditional_29_Template_mj_explorer_entity_data_grid_AfterDataLoad_1_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SetSectionRowCount("mJMLTrainingRuns", $event.totalRowCount)); });
18
+ i0.ɵɵelementEnd()();
19
+ } if (rf & 2) {
20
+ const ctx_r1 = i0.ɵɵnextContext(2);
21
+ i0.ɵɵadvance();
22
+ i0.ɵɵproperty("Params", ctx_r1.BuildRelationshipViewParamsByEntityName("MJ: ML Training Runs", "ResultingModelID"))("NewRecordValues", ctx_r1.NewRecordValues("MJ: ML Training Runs", "ResultingModelID"))("AllowLoad", ctx_r1.IsSectionExpanded("mJMLTrainingRuns"))("ShowToolbar", true);
23
+ } }
24
+ function MLModelFormComponentExtended_Conditional_0_Conditional_31_Template(rf, ctx) { if (rf & 1) {
25
+ const _r4 = i0.ɵɵgetCurrentView();
26
+ i0.ɵɵelementStart(0, "div")(1, "mj-explorer-entity-data-grid", 32);
27
+ i0.ɵɵlistener("Navigate", function MLModelFormComponentExtended_Conditional_0_Conditional_31_Template_mj_explorer_entity_data_grid_Navigate_1_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnFormNavigate($event)); })("AfterDataLoad", function MLModelFormComponentExtended_Conditional_0_Conditional_31_Template_mj_explorer_entity_data_grid_AfterDataLoad_1_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SetSectionRowCount("mJMLModelScoringBindings", $event.totalRowCount)); });
28
+ i0.ɵɵelementEnd()();
29
+ } if (rf & 2) {
30
+ const ctx_r1 = i0.ɵɵnextContext(2);
31
+ i0.ɵɵadvance();
32
+ i0.ɵɵproperty("Params", ctx_r1.BuildRelationshipViewParamsByEntityName("MJ: ML Model Scoring Bindings", "MLModelID"))("NewRecordValues", ctx_r1.NewRecordValues("MJ: ML Model Scoring Bindings", "MLModelID"))("AllowLoad", ctx_r1.IsSectionExpanded("mJMLModelScoringBindings"))("ShowToolbar", true);
33
+ } }
34
+ function MLModelFormComponentExtended_Conditional_0_Template(rf, ctx) { if (rf & 1) {
35
+ const _r1 = i0.ɵɵgetCurrentView();
36
+ i0.ɵɵelementStart(0, "mj-record-form-container", 1);
37
+ i0.ɵɵlistener("Navigate", function MLModelFormComponentExtended_Conditional_0_Template_mj_record_form_container_Navigate_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnFormNavigate($event)); })("DeleteRequested", function MLModelFormComponentExtended_Conditional_0_Template_mj_record_form_container_DeleteRequested_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnDeleteRequested()); })("FavoriteToggled", function MLModelFormComponentExtended_Conditional_0_Template_mj_record_form_container_FavoriteToggled_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnFavoriteToggled()); })("HistoryRequested", function MLModelFormComponentExtended_Conditional_0_Template_mj_record_form_container_HistoryRequested_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnHistoryRequested()); })("ListManagementRequested", function MLModelFormComponentExtended_Conditional_0_Template_mj_record_form_container_ListManagementRequested_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnListManagementRequested()); });
38
+ i0.ɵɵelement(1, "mj-form-panel-slot", 2);
39
+ i0.ɵɵelementStart(2, "mj-collapsible-panel", 3)(3, "div", 4);
40
+ i0.ɵɵelement(4, "ps-model-detail", 5);
41
+ i0.ɵɵelementEnd()();
42
+ i0.ɵɵelementStart(5, "mj-collapsible-panel", 6);
43
+ i0.ɵɵelement(6, "mj-form-field", 7)(7, "mj-form-field", 8)(8, "mj-form-field", 9)(9, "mj-form-field", 10)(10, "mj-form-field", 11)(11, "mj-form-field", 12);
44
+ i0.ɵɵelementEnd();
45
+ i0.ɵɵelementStart(12, "mj-collapsible-panel", 13);
46
+ i0.ɵɵelement(13, "mj-form-field", 14)(14, "mj-form-field", 15)(15, "mj-form-field", 16)(16, "mj-form-field", 17);
47
+ i0.ɵɵelementEnd();
48
+ i0.ɵɵelementStart(17, "mj-collapsible-panel", 18);
49
+ i0.ɵɵelement(18, "mj-form-field", 19)(19, "mj-form-field", 20)(20, "mj-form-field", 21)(21, "mj-form-field", 22)(22, "mj-form-field", 23)(23, "mj-form-field", 24);
50
+ i0.ɵɵelementEnd();
51
+ i0.ɵɵelementStart(24, "mj-collapsible-panel", 25);
52
+ i0.ɵɵelement(25, "mj-form-field", 26)(26, "mj-form-field", 27);
53
+ i0.ɵɵelementEnd();
54
+ i0.ɵɵelement(27, "mj-form-panel-slot", 28);
55
+ i0.ɵɵelementStart(28, "mj-collapsible-panel", 29);
56
+ i0.ɵɵconditionalCreate(29, MLModelFormComponentExtended_Conditional_0_Conditional_29_Template, 2, 4, "div");
57
+ i0.ɵɵelementEnd();
58
+ i0.ɵɵelementStart(30, "mj-collapsible-panel", 30);
59
+ i0.ɵɵconditionalCreate(31, MLModelFormComponentExtended_Conditional_0_Conditional_31_Template, 2, 4, "div");
60
+ i0.ɵɵelementEnd();
61
+ i0.ɵɵelement(32, "mj-form-panel-slot", 31);
62
+ i0.ɵɵelementEnd();
63
+ } if (rf & 2) {
64
+ const ctx_r1 = i0.ɵɵnextContext();
65
+ i0.ɵɵproperty("Record", ctx_r1.record)("FormComponent", ctx_r1);
66
+ i0.ɵɵadvance();
67
+ i0.ɵɵproperty("Entity", i0.ɵɵinterpolate(ctx_r1.record.EntityInfo.Name))("Record", ctx_r1.record)("FormComponent", ctx_r1)("FormContext", ctx_r1.formContext);
68
+ i0.ɵɵadvance();
69
+ i0.ɵɵproperty("Form", ctx_r1)("FormContext", ctx_r1.formContext)("DefaultExpanded", true);
70
+ i0.ɵɵadvance(2);
71
+ i0.ɵɵproperty("model", ctx_r1.record)("provider", ctx_r1.ProviderToUse)("currentUser", ctx_r1.ProviderToUse.CurrentUser ?? null);
72
+ i0.ɵɵadvance();
73
+ i0.ɵɵproperty("Form", ctx_r1)("FormContext", ctx_r1.formContext);
74
+ i0.ɵɵadvance();
75
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
76
+ i0.ɵɵadvance();
77
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
78
+ i0.ɵɵadvance();
79
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
80
+ i0.ɵɵadvance();
81
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
82
+ i0.ɵɵadvance();
83
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
84
+ i0.ɵɵadvance();
85
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
86
+ i0.ɵɵadvance();
87
+ i0.ɵɵproperty("Form", ctx_r1)("FormContext", ctx_r1.formContext);
88
+ i0.ɵɵadvance();
89
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
90
+ i0.ɵɵadvance();
91
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
92
+ i0.ɵɵadvance();
93
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
94
+ i0.ɵɵadvance();
95
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
96
+ i0.ɵɵadvance();
97
+ i0.ɵɵproperty("Form", ctx_r1)("FormContext", ctx_r1.formContext);
98
+ i0.ɵɵadvance();
99
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
100
+ i0.ɵɵadvance();
101
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
102
+ i0.ɵɵadvance();
103
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
104
+ i0.ɵɵadvance();
105
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
106
+ i0.ɵɵadvance();
107
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
108
+ i0.ɵɵadvance();
109
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
110
+ i0.ɵɵadvance();
111
+ i0.ɵɵproperty("Form", ctx_r1)("FormContext", ctx_r1.formContext);
112
+ i0.ɵɵadvance();
113
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
114
+ i0.ɵɵadvance();
115
+ i0.ɵɵproperty("Record", ctx_r1.record)("ShowLabel", true)("EditMode", ctx_r1.EditMode)("FormContext", ctx_r1.formContext);
116
+ i0.ɵɵadvance();
117
+ i0.ɵɵproperty("Entity", i0.ɵɵinterpolate(ctx_r1.record.EntityInfo.Name))("Record", ctx_r1.record)("FormComponent", ctx_r1)("FormContext", ctx_r1.formContext);
118
+ i0.ɵɵadvance();
119
+ i0.ɵɵproperty("Form", ctx_r1)("FormContext", ctx_r1.formContext)("BadgeCount", ctx_r1.GetSectionRowCount("mJMLTrainingRuns"))("DefaultExpanded", false);
120
+ i0.ɵɵadvance();
121
+ i0.ɵɵconditional(ctx_r1.record.IsSaved ? 29 : -1);
122
+ i0.ɵɵadvance();
123
+ i0.ɵɵproperty("Form", ctx_r1)("FormContext", ctx_r1.formContext)("BadgeCount", ctx_r1.GetSectionRowCount("mJMLModelScoringBindings"))("DefaultExpanded", false);
124
+ i0.ɵɵadvance();
125
+ i0.ɵɵconditional(ctx_r1.record.IsSaved ? 31 : -1);
126
+ i0.ɵɵadvance();
127
+ i0.ɵɵproperty("Entity", i0.ɵɵinterpolate(ctx_r1.record.EntityInfo.Name))("Record", ctx_r1.record)("FormComponent", ctx_r1)("FormContext", ctx_r1.formContext);
128
+ } }
129
+ /**
130
+ * Custom form override for `MJ: ML Models` (priority 100).
131
+ * Presents the ML Model in a left-nav experience with:
132
+ * - Lead panel: "Overview & Lifecycle" (<ps-model-detail>)
133
+ * - Details card: Model Identity & Status, Schema & Configuration, Training & Performance
134
+ * - Related grids: ML Training Runs, ML Model Scoring Bindings
135
+ * - More folder: System Metadata
136
+ */
137
+ let MLModelFormComponentExtended = class MLModelFormComponentExtended extends MJMLModelFormComponent {
138
+ async ngOnInit() {
139
+ await super.ngOnInit();
140
+ this.initSections([
141
+ { sectionKey: 'modelOverview', sectionName: 'Overview & Lifecycle', isExpanded: true },
142
+ { sectionKey: 'modelIdentityStatus', sectionName: 'Model Identity & Status', isExpanded: true },
143
+ { sectionKey: 'schemaConfiguration', sectionName: 'Schema & Configuration', isExpanded: true },
144
+ { sectionKey: 'trainingPerformance', sectionName: 'Training & Performance', isExpanded: true },
145
+ { sectionKey: 'systemMetadata', sectionName: 'System Metadata', isExpanded: false },
146
+ { sectionKey: 'mJMLTrainingRuns', sectionName: 'ML Training Runs', isExpanded: false },
147
+ { sectionKey: 'mJMLModelScoringBindings', sectionName: 'ML Model Scoring Bindings', isExpanded: false }
148
+ ]);
149
+ }
150
+ static { this.ɵfac = /*@__PURE__*/ (() => { let ɵMLModelFormComponentExtended_BaseFactory; return function MLModelFormComponentExtended_Factory(__ngFactoryType__) { return (ɵMLModelFormComponentExtended_BaseFactory || (ɵMLModelFormComponentExtended_BaseFactory = i0.ɵɵgetInheritedFactory(MLModelFormComponentExtended)))(__ngFactoryType__ || MLModelFormComponentExtended); }; })(); }
151
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MLModelFormComponentExtended, selectors: [["mj-ml-model-form-extended"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [[3, "Record", "FormComponent"], [3, "Navigate", "DeleteRequested", "FavoriteToggled", "HistoryRequested", "ListManagementRequested", "Record", "FormComponent"], ["Slot", "before-fields", 3, "Entity", "Record", "FormComponent", "FormContext"], ["SectionKey", "modelOverview", "SectionName", "Overview & Lifecycle", "Icon", "fa-solid fa-gauge-high", "Variant", "related-entity", 3, "Form", "FormContext", "DefaultExpanded"], [1, "ml-model-form-content"], [3, "model", "provider", "currentUser"], ["SectionKey", "modelIdentityStatus", "SectionName", "Model Identity & Status", "Icon", "fa fa-tag", 3, "Form", "FormContext"], ["FieldName", "PipelineID", "Type", "textbox", "LinkType", "Record", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "Version", "Type", "number", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "AlgorithmID", "Type", "textbox", "LinkType", "Record", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "ArtifactFileID", "Type", "textbox", "LinkType", "Record", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "Lineage", "Type", "code", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "Status", "Type", "select", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["SectionKey", "schemaConfiguration", "SectionName", "Schema & Configuration", "Icon", "fa fa-sliders-h", 3, "Form", "FormContext"], ["FieldName", "FittedPreprocessing", "Type", "code", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "FeatureSchema", "Type", "code", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "TargetVariable", "Type", "textbox", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "ProblemType", "Type", "select", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["SectionKey", "trainingPerformance", "SectionName", "Training & Performance", "Icon", "fa fa-chart-line", 3, "Form", "FormContext"], ["FieldName", "Metrics", "Type", "code", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "HoldoutMetrics", "Type", "code", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "FeatureImportance", "Type", "code", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "TrainedAt", "Type", "datepicker", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "TrainingDurationSec", "Type", "number", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "TrainingRowCount", "Type", "number", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["SectionKey", "systemMetadata", "SectionName", "System Metadata", "Icon", "fa fa-cog", 3, "Form", "FormContext"], ["FieldName", "__mj_CreatedAt", "Type", "textbox", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["FieldName", "__mj_UpdatedAt", "Type", "textbox", 3, "Record", "ShowLabel", "EditMode", "FormContext"], ["Slot", "after-fields", 3, "Entity", "Record", "FormComponent", "FormContext"], ["SectionKey", "mJMLTrainingRuns", "SectionName", "ML Training Runs", "Icon", "fa-solid fa-flask", "Variant", "related-entity", 3, "Form", "FormContext", "BadgeCount", "DefaultExpanded"], ["SectionKey", "mJMLModelScoringBindings", "SectionName", "ML Model Scoring Bindings", "Icon", "fa-solid fa-satellite-dish", "Variant", "related-entity", 3, "Form", "FormContext", "BadgeCount", "DefaultExpanded"], ["Slot", "after-related", 3, "Entity", "Record", "FormComponent", "FormContext"], [3, "Navigate", "AfterDataLoad", "Params", "NewRecordValues", "AllowLoad", "ShowToolbar"]], template: function MLModelFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
152
+ i0.ɵɵconditionalCreate(0, MLModelFormComponentExtended_Conditional_0_Template, 33, 113, "mj-record-form-container", 0);
153
+ } if (rf & 2) {
154
+ i0.ɵɵconditional(ctx.record ? 0 : -1);
155
+ } }, dependencies: [i1.PSModelDetailComponent, i2.MjFormFieldComponent, i2.MjCollapsiblePanelComponent, i2.MjRecordFormContainerComponent, i2.ExplorerEntityDataGridComponent, i2.FormPanelSlotComponent], styles: [".ml-model-form-content[_ngcontent-%COMP%] {\n padding: 20px 24px;\n max-width: 1200px;\n margin: 0 auto;\n width: 100%;\n box-sizing: border-box;\n}"] }); }
156
+ };
157
+ MLModelFormComponentExtended = __decorate([
158
+ RegisterClass(BaseFormComponent, 'MJ: ML Models', 100)
159
+ ], MLModelFormComponentExtended);
160
+ export { MLModelFormComponentExtended };
161
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MLModelFormComponentExtended, [{
162
+ type: Component,
163
+ args: [{ standalone: false, selector: 'mj-ml-model-form-extended', template: "@if (record) {\n<mj-record-form-container [Record]=\"record\" [FormComponent]=\"this\"\n (Navigate)=\"OnFormNavigate($event)\"\n (DeleteRequested)=\"OnDeleteRequested()\"\n (FavoriteToggled)=\"OnFavoriteToggled()\"\n (HistoryRequested)=\"OnHistoryRequested()\"\n (ListManagementRequested)=\"OnListManagementRequested()\">\n\n <mj-form-panel-slot Entity=\"{{record.EntityInfo.Name}}\" Slot=\"before-fields\" [Record]=\"record\" [FormComponent]=\"this\" [FormContext]=\"formContext\"></mj-form-panel-slot>\n\n <!-- ========================================\n OVERVIEW PANEL (Lead Panel)\n ======================================== -->\n <mj-collapsible-panel\n SectionKey=\"modelOverview\"\n SectionName=\"Overview & Lifecycle\"\n Icon=\"fa-solid fa-gauge-high\"\n Variant=\"related-entity\"\n [Form]=\"this\"\n [FormContext]=\"formContext\"\n [DefaultExpanded]=\"true\">\n <div class=\"ml-model-form-content\">\n <ps-model-detail\n [model]=\"record\"\n [provider]=\"ProviderToUse\"\n [currentUser]=\"ProviderToUse.CurrentUser ?? null\">\n </ps-model-detail>\n </div>\n </mj-collapsible-panel>\n\n <!-- ========================================\n FIELD PANELS (Fold into Details)\n ======================================== -->\n <!-- Model Identity & Status Section -->\n <mj-collapsible-panel\n SectionKey=\"modelIdentityStatus\"\n SectionName=\"Model Identity & Status\"\n Icon=\"fa fa-tag\"\n [Form]=\"this\"\n [FormContext]=\"formContext\">\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"PipelineID\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n LinkType=\"Record\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"Version\"\n Type=\"number\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"AlgorithmID\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n LinkType=\"Record\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ArtifactFileID\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n LinkType=\"Record\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"Lineage\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"Status\"\n Type=\"select\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n </mj-collapsible-panel>\n\n <!-- Schema & Configuration Section -->\n <mj-collapsible-panel\n SectionKey=\"schemaConfiguration\"\n SectionName=\"Schema & Configuration\"\n Icon=\"fa fa-sliders-h\"\n [Form]=\"this\"\n [FormContext]=\"formContext\">\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"FittedPreprocessing\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"FeatureSchema\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"TargetVariable\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ProblemType\"\n Type=\"select\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n </mj-collapsible-panel>\n\n <!-- Training & Performance Section -->\n <mj-collapsible-panel\n SectionKey=\"trainingPerformance\"\n SectionName=\"Training & Performance\"\n Icon=\"fa fa-chart-line\"\n [Form]=\"this\"\n [FormContext]=\"formContext\">\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"Metrics\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"HoldoutMetrics\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"FeatureImportance\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"TrainedAt\"\n Type=\"datepicker\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"TrainingDurationSec\"\n Type=\"number\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"TrainingRowCount\"\n Type=\"number\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n </mj-collapsible-panel>\n\n <!-- System Metadata Section -->\n <mj-collapsible-panel\n SectionKey=\"systemMetadata\"\n SectionName=\"System Metadata\"\n Icon=\"fa fa-cog\"\n [Form]=\"this\"\n [FormContext]=\"formContext\">\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"__mj_CreatedAt\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"__mj_UpdatedAt\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n </mj-collapsible-panel>\n\n <mj-form-panel-slot Entity=\"{{record.EntityInfo.Name}}\" Slot=\"after-fields\" [Record]=\"record\" [FormComponent]=\"this\" [FormContext]=\"formContext\"></mj-form-panel-slot>\n\n <!-- ========================================\n RELATED ENTITY PANELS\n ======================================== -->\n\n <!-- ML Training Runs Section -->\n <mj-collapsible-panel\n SectionKey=\"mJMLTrainingRuns\"\n SectionName=\"ML Training Runs\"\n Icon=\"fa-solid fa-flask\"\n Variant=\"related-entity\"\n [Form]=\"this\"\n [FormContext]=\"formContext\"\n [BadgeCount]=\"GetSectionRowCount('mJMLTrainingRuns')\"\n [DefaultExpanded]=\"false\">\n @if (record.IsSaved) {\n <div>\n <mj-explorer-entity-data-grid\n [Params]=\"BuildRelationshipViewParamsByEntityName('MJ: ML Training Runs','ResultingModelID')\"\n [NewRecordValues]=\"NewRecordValues('MJ: ML Training Runs','ResultingModelID')\"\n [AllowLoad]=\"IsSectionExpanded('mJMLTrainingRuns')\"\n [ShowToolbar]=\"true\"\n (Navigate)=\"OnFormNavigate($event)\"\n (AfterDataLoad)=\"SetSectionRowCount('mJMLTrainingRuns', $event.totalRowCount)\"\n >\n </mj-explorer-entity-data-grid>\n </div>\n }\n </mj-collapsible-panel>\n\n <!-- ML Model Scoring Bindings Section -->\n <mj-collapsible-panel\n SectionKey=\"mJMLModelScoringBindings\"\n SectionName=\"ML Model Scoring Bindings\"\n Icon=\"fa-solid fa-satellite-dish\"\n Variant=\"related-entity\"\n [Form]=\"this\"\n [FormContext]=\"formContext\"\n [BadgeCount]=\"GetSectionRowCount('mJMLModelScoringBindings')\"\n [DefaultExpanded]=\"false\">\n @if (record.IsSaved) {\n <div>\n <mj-explorer-entity-data-grid\n [Params]=\"BuildRelationshipViewParamsByEntityName('MJ: ML Model Scoring Bindings','MLModelID')\"\n [NewRecordValues]=\"NewRecordValues('MJ: ML Model Scoring Bindings','MLModelID')\"\n [AllowLoad]=\"IsSectionExpanded('mJMLModelScoringBindings')\"\n [ShowToolbar]=\"true\"\n (Navigate)=\"OnFormNavigate($event)\"\n (AfterDataLoad)=\"SetSectionRowCount('mJMLModelScoringBindings', $event.totalRowCount)\"\n >\n </mj-explorer-entity-data-grid>\n </div>\n }\n </mj-collapsible-panel>\n\n <mj-form-panel-slot Entity=\"{{record.EntityInfo.Name}}\" Slot=\"after-related\" [Record]=\"record\" [FormComponent]=\"this\" [FormContext]=\"formContext\"></mj-form-panel-slot>\n\n</mj-record-form-container>\n}\n", styles: [".ml-model-form-content {\n padding: 20px 24px;\n max-width: 1200px;\n margin: 0 auto;\n width: 100%;\n box-sizing: border-box;\n}\n"] }]
164
+ }], null, null); })();
165
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MLModelFormComponentExtended, { className: "MLModelFormComponentExtended", filePath: "src/lib/custom/MLModels/ml-model-form.component.ts", lineNumber: 21 }); })();
166
+ /**
167
+ * Policy ensuring that the Overview & Lifecycle panel sits as the lead group
168
+ * before the Details group on the left-nav rail.
169
+ */
170
+ let MLModelFormPolicy = class MLModelFormPolicy extends BaseFormPolicy {
171
+ DecorateChrome(spec, _ctx) {
172
+ const overview = spec.Groups.find(g => g.Key === 'modelOverview');
173
+ if (overview) {
174
+ overview.IsLead = true;
175
+ const remaining = spec.Groups.filter(g => g.Key !== 'modelOverview');
176
+ return {
177
+ ...spec,
178
+ Groups: [overview, ...remaining],
179
+ };
180
+ }
181
+ return spec;
182
+ }
183
+ };
184
+ MLModelFormPolicy = __decorate([
185
+ RegisterClassEx(BaseFormPolicy, { key: 'MJ: ML Models', metadata: { entity: 'MJ: ML Models' } })
186
+ ], MLModelFormPolicy);
187
+ export { MLModelFormPolicy };
188
+ /** Tree-shaking guard so the override and policy register with the ClassFactory. */
189
+ export function LoadMLModelFormComponentExtended() {
190
+ void MLModelFormComponentExtended;
191
+ void MLModelFormPolicy;
192
+ }
193
+ //# sourceMappingURL=ml-model-form.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ml-model-form.component.js","sourceRoot":"","sources":["../../../../src/lib/custom/MLModels/ml-model-form.component.ts","../../../../src/lib/custom/MLModels/ml-model-form.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit } from '@angular/core';\nimport { RegisterClass, RegisterClassEx } from '@memberjunction/global';\nimport { BaseFormComponent, BaseFormPolicy, FormChromeContext, FormChromeSpec } from '@memberjunction/ng-base-forms';\nimport { MJMLModelFormComponent } from '../../generated/Entities/MJMLModel/mjmlmodel.form.component';\n\n/**\n * Custom form override for `MJ: ML Models` (priority 100).\n * Presents the ML Model in a left-nav experience with:\n * - Lead panel: \"Overview & Lifecycle\" (<ps-model-detail>)\n * - Details card: Model Identity & Status, Schema & Configuration, Training & Performance\n * - Related grids: ML Training Runs, ML Model Scoring Bindings\n * - More folder: System Metadata\n */\n@RegisterClass(BaseFormComponent, 'MJ: ML Models', 100)\n@Component({\n standalone: false,\n selector: 'mj-ml-model-form-extended',\n templateUrl: './ml-model-form.component.html',\n styleUrls: ['./ml-model-form.component.css'],\n})\nexport class MLModelFormComponentExtended extends MJMLModelFormComponent implements OnInit {\n override async ngOnInit() {\n await super.ngOnInit();\n this.initSections([\n { sectionKey: 'modelOverview', sectionName: 'Overview & Lifecycle', isExpanded: true },\n { sectionKey: 'modelIdentityStatus', sectionName: 'Model Identity & Status', isExpanded: true },\n { sectionKey: 'schemaConfiguration', sectionName: 'Schema & Configuration', isExpanded: true },\n { sectionKey: 'trainingPerformance', sectionName: 'Training & Performance', isExpanded: true },\n { sectionKey: 'systemMetadata', sectionName: 'System Metadata', isExpanded: false },\n { sectionKey: 'mJMLTrainingRuns', sectionName: 'ML Training Runs', isExpanded: false },\n { sectionKey: 'mJMLModelScoringBindings', sectionName: 'ML Model Scoring Bindings', isExpanded: false }\n ]);\n }\n}\n\n/**\n * Policy ensuring that the Overview & Lifecycle panel sits as the lead group\n * before the Details group on the left-nav rail.\n */\n@RegisterClassEx(BaseFormPolicy, { key: 'MJ: ML Models', metadata: { entity: 'MJ: ML Models' } })\nexport class MLModelFormPolicy extends BaseFormPolicy {\n public override DecorateChrome(spec: FormChromeSpec, _ctx: FormChromeContext): FormChromeSpec {\n const overview = spec.Groups.find(g => g.Key === 'modelOverview');\n if (overview) {\n overview.IsLead = true;\n const remaining = spec.Groups.filter(g => g.Key !== 'modelOverview');\n return {\n ...spec,\n Groups: [overview, ...remaining],\n };\n }\n return spec;\n }\n}\n\n/** Tree-shaking guard so the override and policy register with the ClassFactory. */\nexport function LoadMLModelFormComponentExtended(): void {\n void MLModelFormComponentExtended;\n void MLModelFormPolicy;\n}\n","@if (record) {\n<mj-record-form-container [Record]=\"record\" [FormComponent]=\"this\"\n (Navigate)=\"OnFormNavigate($event)\"\n (DeleteRequested)=\"OnDeleteRequested()\"\n (FavoriteToggled)=\"OnFavoriteToggled()\"\n (HistoryRequested)=\"OnHistoryRequested()\"\n (ListManagementRequested)=\"OnListManagementRequested()\">\n\n <mj-form-panel-slot Entity=\"{{record.EntityInfo.Name}}\" Slot=\"before-fields\" [Record]=\"record\" [FormComponent]=\"this\" [FormContext]=\"formContext\"></mj-form-panel-slot>\n\n <!-- ========================================\n OVERVIEW PANEL (Lead Panel)\n ======================================== -->\n <mj-collapsible-panel\n SectionKey=\"modelOverview\"\n SectionName=\"Overview & Lifecycle\"\n Icon=\"fa-solid fa-gauge-high\"\n Variant=\"related-entity\"\n [Form]=\"this\"\n [FormContext]=\"formContext\"\n [DefaultExpanded]=\"true\">\n <div class=\"ml-model-form-content\">\n <ps-model-detail\n [model]=\"record\"\n [provider]=\"ProviderToUse\"\n [currentUser]=\"ProviderToUse.CurrentUser ?? null\">\n </ps-model-detail>\n </div>\n </mj-collapsible-panel>\n\n <!-- ========================================\n FIELD PANELS (Fold into Details)\n ======================================== -->\n <!-- Model Identity & Status Section -->\n <mj-collapsible-panel\n SectionKey=\"modelIdentityStatus\"\n SectionName=\"Model Identity & Status\"\n Icon=\"fa fa-tag\"\n [Form]=\"this\"\n [FormContext]=\"formContext\">\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"PipelineID\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n LinkType=\"Record\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"Version\"\n Type=\"number\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"AlgorithmID\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n LinkType=\"Record\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ArtifactFileID\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n LinkType=\"Record\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"Lineage\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"Status\"\n Type=\"select\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n </mj-collapsible-panel>\n\n <!-- Schema & Configuration Section -->\n <mj-collapsible-panel\n SectionKey=\"schemaConfiguration\"\n SectionName=\"Schema & Configuration\"\n Icon=\"fa fa-sliders-h\"\n [Form]=\"this\"\n [FormContext]=\"formContext\">\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"FittedPreprocessing\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"FeatureSchema\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"TargetVariable\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ProblemType\"\n Type=\"select\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n </mj-collapsible-panel>\n\n <!-- Training & Performance Section -->\n <mj-collapsible-panel\n SectionKey=\"trainingPerformance\"\n SectionName=\"Training & Performance\"\n Icon=\"fa fa-chart-line\"\n [Form]=\"this\"\n [FormContext]=\"formContext\">\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"Metrics\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"HoldoutMetrics\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"FeatureImportance\"\n Type=\"code\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"TrainedAt\"\n Type=\"datepicker\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"TrainingDurationSec\"\n Type=\"number\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"TrainingRowCount\"\n Type=\"number\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n </mj-collapsible-panel>\n\n <!-- System Metadata Section -->\n <mj-collapsible-panel\n SectionKey=\"systemMetadata\"\n SectionName=\"System Metadata\"\n Icon=\"fa fa-cog\"\n [Form]=\"this\"\n [FormContext]=\"formContext\">\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"__mj_CreatedAt\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n <mj-form-field \n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"__mj_UpdatedAt\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\"\n [FormContext]=\"formContext\"\n ></mj-form-field>\n </mj-collapsible-panel>\n\n <mj-form-panel-slot Entity=\"{{record.EntityInfo.Name}}\" Slot=\"after-fields\" [Record]=\"record\" [FormComponent]=\"this\" [FormContext]=\"formContext\"></mj-form-panel-slot>\n\n <!-- ========================================\n RELATED ENTITY PANELS\n ======================================== -->\n\n <!-- ML Training Runs Section -->\n <mj-collapsible-panel\n SectionKey=\"mJMLTrainingRuns\"\n SectionName=\"ML Training Runs\"\n Icon=\"fa-solid fa-flask\"\n Variant=\"related-entity\"\n [Form]=\"this\"\n [FormContext]=\"formContext\"\n [BadgeCount]=\"GetSectionRowCount('mJMLTrainingRuns')\"\n [DefaultExpanded]=\"false\">\n @if (record.IsSaved) {\n <div>\n <mj-explorer-entity-data-grid\n [Params]=\"BuildRelationshipViewParamsByEntityName('MJ: ML Training Runs','ResultingModelID')\"\n [NewRecordValues]=\"NewRecordValues('MJ: ML Training Runs','ResultingModelID')\"\n [AllowLoad]=\"IsSectionExpanded('mJMLTrainingRuns')\"\n [ShowToolbar]=\"true\"\n (Navigate)=\"OnFormNavigate($event)\"\n (AfterDataLoad)=\"SetSectionRowCount('mJMLTrainingRuns', $event.totalRowCount)\"\n >\n </mj-explorer-entity-data-grid>\n </div>\n }\n </mj-collapsible-panel>\n\n <!-- ML Model Scoring Bindings Section -->\n <mj-collapsible-panel\n SectionKey=\"mJMLModelScoringBindings\"\n SectionName=\"ML Model Scoring Bindings\"\n Icon=\"fa-solid fa-satellite-dish\"\n Variant=\"related-entity\"\n [Form]=\"this\"\n [FormContext]=\"formContext\"\n [BadgeCount]=\"GetSectionRowCount('mJMLModelScoringBindings')\"\n [DefaultExpanded]=\"false\">\n @if (record.IsSaved) {\n <div>\n <mj-explorer-entity-data-grid\n [Params]=\"BuildRelationshipViewParamsByEntityName('MJ: ML Model Scoring Bindings','MLModelID')\"\n [NewRecordValues]=\"NewRecordValues('MJ: ML Model Scoring Bindings','MLModelID')\"\n [AllowLoad]=\"IsSectionExpanded('mJMLModelScoringBindings')\"\n [ShowToolbar]=\"true\"\n (Navigate)=\"OnFormNavigate($event)\"\n (AfterDataLoad)=\"SetSectionRowCount('mJMLModelScoringBindings', $event.totalRowCount)\"\n >\n </mj-explorer-entity-data-grid>\n </div>\n }\n </mj-collapsible-panel>\n\n <mj-form-panel-slot Entity=\"{{record.EntityInfo.Name}}\" Slot=\"after-related\" [Record]=\"record\" [FormComponent]=\"this\" [FormContext]=\"formContext\"></mj-form-panel-slot>\n\n</mj-record-form-container>\n}\n"]}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Pure view-model functions and types for ML Model detail and metrics rendering.
3
+ * Framework-free, deterministic calculations over plain model entity data.
4
+ */
5
+ export interface PSFeatureBar {
6
+ name: string;
7
+ value: string;
8
+ pct: number;
9
+ warning: boolean;
10
+ }
11
+ export interface PSMetricDisplay {
12
+ key: string;
13
+ label: string;
14
+ value: string;
15
+ raw: number;
16
+ }
17
+ export type PSMetricKey = 'AUC' | 'Accuracy' | 'Precision' | 'Recall' | 'F1' | 'LogLoss' | 'R2' | 'RMSE' | 'MAE';
18
+ export type PSMetricMap = Partial<Record<PSMetricKey, number>>;
19
+ export declare const PS_KNOWN_METRIC_KEYS: readonly PSMetricKey[];
20
+ export declare const METRIC_LABELS: Record<PSMetricKey, string>;
21
+ export declare const PS_FEATURE_DOMINANCE_THRESHOLD = 0.6;
22
+ export declare function humanizeFeatureName(name: string): string;
23
+ export declare function parseMetrics(json: string | null | undefined): PSMetricMap;
24
+ export declare function canonicalMetricKey(rawKey: string): PSMetricKey | null;
25
+ export declare function formatMetricValue(key: PSMetricKey | string, val: number): string;
26
+ export declare function primaryModelScore(model: {
27
+ Metrics?: string | null;
28
+ HoldoutMetrics?: string | null;
29
+ ProblemType?: string | null;
30
+ }): {
31
+ key: PSMetricKey;
32
+ label: string;
33
+ value: number;
34
+ } | null;
35
+ export declare function metricsToDisplay(metrics: PSMetricMap, options?: {
36
+ excludeAuc?: boolean;
37
+ }): PSMetricDisplay[];
38
+ export declare function parseFeatureImportance(raw: string | null | undefined, topN?: number): PSFeatureBar[];
39
+ export declare function maxFeatureImportance(raw: string | null | undefined): number | null;
40
+ export declare function overfitGap(model: {
41
+ Metrics?: string | null;
42
+ HoldoutMetrics?: string | null;
43
+ }): number | null;
44
+ //# sourceMappingURL=ml-model-view-models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ml-model-view-models.d.ts","sourceRoot":"","sources":["../../../../src/lib/custom/MLModels/ml-model-view-models.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,UAAU,GACV,WAAW,GACX,QAAQ,GACR,IAAI,GACJ,SAAS,GACT,IAAI,GACJ,MAAM,GACN,KAAK,CAAC;AAEV,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;AAE/D,eAAO,MAAM,oBAAoB,EAAE,SAAS,WAAW,EAU7C,CAAC;AAEX,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAUrD,CAAC;AAyBF,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAElD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQxD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,WAAW,CAiBzE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAIrE;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAiBhF;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC9F;IAAE,GAAG,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAqB3D;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,eAAe,EAAE,CAehH;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,GAAE,MAAU,GAAG,YAAY,EAAE,CAyCvG;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAKlF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAU5G"}
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Pure view-model functions and types for ML Model detail and metrics rendering.
3
+ * Framework-free, deterministic calculations over plain model entity data.
4
+ */
5
+ export const PS_KNOWN_METRIC_KEYS = [
6
+ 'AUC',
7
+ 'Accuracy',
8
+ 'Precision',
9
+ 'Recall',
10
+ 'F1',
11
+ 'LogLoss',
12
+ 'R2',
13
+ 'RMSE',
14
+ 'MAE',
15
+ ];
16
+ export const METRIC_LABELS = {
17
+ AUC: 'AUC (ROC)',
18
+ Accuracy: 'Accuracy',
19
+ Precision: 'Precision',
20
+ Recall: 'Recall',
21
+ F1: 'F1 Score',
22
+ LogLoss: 'Log Loss',
23
+ R2: 'R² (Fit)',
24
+ RMSE: 'RMSE',
25
+ MAE: 'MAE',
26
+ };
27
+ const METRIC_ALIASES = {
28
+ auc: 'AUC',
29
+ 'roc-auc': 'AUC',
30
+ roc_auc: 'AUC',
31
+ acc: 'Accuracy',
32
+ accuracy: 'Accuracy',
33
+ prec: 'Precision',
34
+ precision: 'Precision',
35
+ rec: 'Recall',
36
+ recall: 'Recall',
37
+ f1: 'F1',
38
+ 'f1-score': 'F1',
39
+ f1_score: 'F1',
40
+ logloss: 'LogLoss',
41
+ 'log-loss': 'LogLoss',
42
+ log_loss: 'LogLoss',
43
+ r2: 'R2',
44
+ 'r-squared': 'R2',
45
+ r_squared: 'R2',
46
+ rmse: 'RMSE',
47
+ mae: 'MAE',
48
+ };
49
+ export const PS_FEATURE_DOMINANCE_THRESHOLD = 0.6;
50
+ export function humanizeFeatureName(name) {
51
+ if (!name)
52
+ return '';
53
+ return name
54
+ .replace(/^Is([A-Z])/, '$1')
55
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
56
+ .replace(/_/g, ' ')
57
+ .trim()
58
+ .replace(/\b[a-z]/g, (c) => c.toUpperCase());
59
+ }
60
+ export function parseMetrics(json) {
61
+ if (!json)
62
+ return {};
63
+ let parsed;
64
+ try {
65
+ parsed = JSON.parse(json);
66
+ }
67
+ catch {
68
+ return {};
69
+ }
70
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
71
+ return {};
72
+ const out = {};
73
+ for (const [rawKey, rawVal] of Object.entries(parsed)) {
74
+ const value = typeof rawVal === 'number' && Number.isFinite(rawVal) ? rawVal : null;
75
+ if (value == null)
76
+ continue;
77
+ const canonical = canonicalMetricKey(rawKey);
78
+ if (canonical && out[canonical] == null)
79
+ out[canonical] = value;
80
+ }
81
+ return out;
82
+ }
83
+ export function canonicalMetricKey(rawKey) {
84
+ const exact = PS_KNOWN_METRIC_KEYS.find((k) => k === rawKey);
85
+ if (exact)
86
+ return exact;
87
+ return METRIC_ALIASES[rawKey.trim().toLowerCase()] ?? null;
88
+ }
89
+ export function formatMetricValue(key, val) {
90
+ if (!Number.isFinite(val))
91
+ return '—';
92
+ switch (key) {
93
+ case 'AUC':
94
+ case 'Accuracy':
95
+ case 'Precision':
96
+ case 'Recall':
97
+ case 'F1':
98
+ case 'R2':
99
+ return val.toFixed(3);
100
+ case 'LogLoss':
101
+ case 'RMSE':
102
+ case 'MAE':
103
+ return val < 10 ? val.toFixed(3) : val.toLocaleString(undefined, { maximumFractionDigits: 2 });
104
+ default:
105
+ return val.toFixed(3);
106
+ }
107
+ }
108
+ export function primaryModelScore(model) {
109
+ const isReg = (model.ProblemType ?? '').toLowerCase() === 'regression';
110
+ const holdout = parseMetrics(model.HoldoutMetrics);
111
+ const train = parseMetrics(model.Metrics);
112
+ if (isReg) {
113
+ for (const k of ['R2', 'RMSE', 'MAE']) {
114
+ if (holdout[k] != null)
115
+ return { key: k, label: METRIC_LABELS[k], value: holdout[k] };
116
+ }
117
+ for (const k of ['R2', 'RMSE', 'MAE']) {
118
+ if (train[k] != null)
119
+ return { key: k, label: METRIC_LABELS[k], value: train[k] };
120
+ }
121
+ }
122
+ for (const k of ['AUC', 'Accuracy', 'F1', 'R2', 'RMSE']) {
123
+ if (holdout[k] != null)
124
+ return { key: k, label: METRIC_LABELS[k], value: holdout[k] };
125
+ }
126
+ for (const k of ['AUC', 'Accuracy', 'F1', 'R2', 'RMSE']) {
127
+ if (train[k] != null)
128
+ return { key: k, label: METRIC_LABELS[k], value: train[k] };
129
+ }
130
+ return null;
131
+ }
132
+ export function metricsToDisplay(metrics, options = {}) {
133
+ const out = [];
134
+ for (const k of PS_KNOWN_METRIC_KEYS) {
135
+ if (options.excludeAuc && k === 'AUC')
136
+ continue;
137
+ const v = metrics[k];
138
+ if (v != null) {
139
+ out.push({
140
+ key: k,
141
+ label: METRIC_LABELS[k] ?? k,
142
+ value: formatMetricValue(k, v),
143
+ raw: v,
144
+ });
145
+ }
146
+ }
147
+ return out;
148
+ }
149
+ export function parseFeatureImportance(raw, topN = 6) {
150
+ if (!raw)
151
+ return [];
152
+ let parsed;
153
+ try {
154
+ parsed = JSON.parse(raw);
155
+ }
156
+ catch {
157
+ return [];
158
+ }
159
+ const entries = [];
160
+ if (Array.isArray(parsed)) {
161
+ for (const item of parsed) {
162
+ const name = typeof item?.feature === 'string' ? item.feature : typeof item?.name === 'string' ? item.name : '';
163
+ const rawVal = typeof item?.importance === 'number' ? item.importance : typeof item?.weight === 'number' ? item.weight : typeof item?.value === 'number' ? item.value : NaN;
164
+ const val = Number(rawVal);
165
+ if (name && Number.isFinite(val)) {
166
+ entries.push({ name, val: Math.abs(val) });
167
+ }
168
+ }
169
+ }
170
+ else if (parsed && typeof parsed === 'object') {
171
+ for (const [k, v] of Object.entries(parsed)) {
172
+ const val = typeof v === 'number' && Number.isFinite(v) ? Math.abs(v) : NaN;
173
+ if (k && Number.isFinite(val)) {
174
+ entries.push({ name: k, val });
175
+ }
176
+ }
177
+ }
178
+ if (entries.length === 0)
179
+ return [];
180
+ entries.sort((a, b) => b.val - a.val);
181
+ const sliced = entries.slice(0, topN);
182
+ const max = sliced[0]?.val ?? 1;
183
+ return sliced.map((e) => ({
184
+ name: e.name,
185
+ value: e.val < 1 ? e.val.toFixed(3) : e.val.toFixed(1),
186
+ pct: max > 0 ? Math.round((e.val / max) * 100) : 0,
187
+ warning: e.val >= PS_FEATURE_DOMINANCE_THRESHOLD,
188
+ }));
189
+ }
190
+ export function maxFeatureImportance(raw) {
191
+ const bars = parseFeatureImportance(raw, 1);
192
+ if (bars.length === 0)
193
+ return null;
194
+ const num = parseFloat(bars[0].value);
195
+ return Number.isFinite(num) ? num : null;
196
+ }
197
+ export function overfitGap(model) {
198
+ const train = parseMetrics(model.Metrics);
199
+ const holdout = parseMetrics(model.HoldoutMetrics);
200
+ if (train.AUC != null && holdout.AUC != null) {
201
+ return train.AUC - holdout.AUC;
202
+ }
203
+ if (train.R2 != null && holdout.R2 != null) {
204
+ return train.R2 - holdout.R2;
205
+ }
206
+ return null;
207
+ }
208
+ //# sourceMappingURL=ml-model-view-models.js.map