@memberjunction/ng-dashboards 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.
Files changed (99) hide show
  1. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +6 -1
  2. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  3. package/dist/AI/components/vectors/vector-management-resource.component.js +99 -45
  4. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  5. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +4 -0
  6. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts.map +1 -1
  7. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +16 -6
  8. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js.map +1 -1
  9. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +4 -0
  10. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  11. package/dist/DataExplorer/data-explorer-dashboard.component.js +14 -4
  12. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  13. package/dist/DataExplorer/services/explorer-state.service.js +2 -2
  14. package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
  15. package/dist/DevTools/graphql-console.component.d.ts.map +1 -1
  16. package/dist/DevTools/graphql-console.component.js +2 -0
  17. package/dist/DevTools/graphql-console.component.js.map +1 -1
  18. package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
  19. package/dist/Integration/components/connections/connections.component.js +2 -0
  20. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  21. package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.d.ts +4 -12
  22. package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.d.ts.map +1 -1
  23. package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.js +39 -78
  24. package/dist/KnowledgeHub/components/feature-pipelines/feature-pipelines-resource.component.js.map +1 -1
  25. package/dist/Lists/components/lists-browse-resource.component.d.ts +3 -0
  26. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  27. package/dist/Lists/components/lists-browse-resource.component.js +7 -6
  28. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  29. package/dist/Lists/components/lists-my-lists-resource.component.d.ts +3 -0
  30. package/dist/Lists/components/lists-my-lists-resource.component.d.ts.map +1 -1
  31. package/dist/Lists/components/lists-my-lists-resource.component.js +7 -6
  32. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  33. package/dist/PredictiveStudio/at-risk.view-models.d.ts +41 -3
  34. package/dist/PredictiveStudio/at-risk.view-models.d.ts.map +1 -1
  35. package/dist/PredictiveStudio/at-risk.view-models.js +99 -6
  36. package/dist/PredictiveStudio/at-risk.view-models.js.map +1 -1
  37. package/dist/PredictiveStudio/components/ps-catalog.component.d.ts +4 -1
  38. package/dist/PredictiveStudio/components/ps-catalog.component.d.ts.map +1 -1
  39. package/dist/PredictiveStudio/components/ps-catalog.component.js +61 -37
  40. package/dist/PredictiveStudio/components/ps-catalog.component.js.map +1 -1
  41. package/dist/PredictiveStudio/components/ps-experiments.component.d.ts +12 -0
  42. package/dist/PredictiveStudio/components/ps-experiments.component.d.ts.map +1 -1
  43. package/dist/PredictiveStudio/components/ps-experiments.component.js +426 -184
  44. package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
  45. package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.d.ts +84 -0
  46. package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.d.ts.map +1 -0
  47. package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js +1397 -0
  48. package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js.map +1 -0
  49. package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts +66 -34
  50. package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts.map +1 -1
  51. package/dist/PredictiveStudio/components/ps-pipelines.component.js +2456 -743
  52. package/dist/PredictiveStudio/components/ps-pipelines.component.js.map +1 -1
  53. package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts +194 -0
  54. package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts.map +1 -0
  55. package/dist/PredictiveStudio/components/ps-predictions-grid.component.js +1902 -0
  56. package/dist/PredictiveStudio/components/ps-predictions-grid.component.js.map +1 -0
  57. package/dist/PredictiveStudio/components/ps-production.component.d.ts +17 -1
  58. package/dist/PredictiveStudio/components/ps-production.component.d.ts.map +1 -1
  59. package/dist/PredictiveStudio/components/ps-production.component.js +653 -372
  60. package/dist/PredictiveStudio/components/ps-production.component.js.map +1 -1
  61. package/dist/PredictiveStudio/components/ps-registry.component.d.ts +21 -61
  62. package/dist/PredictiveStudio/components/ps-registry.component.d.ts.map +1 -1
  63. package/dist/PredictiveStudio/components/ps-registry.component.js +214 -681
  64. package/dist/PredictiveStudio/components/ps-registry.component.js.map +1 -1
  65. package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.d.ts +49 -0
  66. package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.d.ts.map +1 -0
  67. package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.js +658 -0
  68. package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.js.map +1 -0
  69. package/dist/PredictiveStudio/predictive-studio-score-history.service.d.ts +42 -0
  70. package/dist/PredictiveStudio/predictive-studio-score-history.service.d.ts.map +1 -0
  71. package/dist/PredictiveStudio/predictive-studio-score-history.service.js +90 -0
  72. package/dist/PredictiveStudio/predictive-studio-score-history.service.js.map +1 -0
  73. package/dist/PredictiveStudio/predictive-studio.view-models.d.ts +14 -2
  74. package/dist/PredictiveStudio/predictive-studio.view-models.d.ts.map +1 -1
  75. package/dist/PredictiveStudio/predictive-studio.view-models.js +41 -5
  76. package/dist/PredictiveStudio/predictive-studio.view-models.js.map +1 -1
  77. package/dist/PredictiveStudio/resources/ps-models-resource.component.d.ts +9 -1
  78. package/dist/PredictiveStudio/resources/ps-models-resource.component.d.ts.map +1 -1
  79. package/dist/PredictiveStudio/resources/ps-models-resource.component.js +178 -65
  80. package/dist/PredictiveStudio/resources/ps-models-resource.component.js.map +1 -1
  81. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts +9 -1
  82. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
  83. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +307 -369
  84. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
  85. package/dist/PredictiveStudio/resources/ps-resource-base.js +1 -1
  86. package/dist/PredictiveStudio/resources/ps-resource-base.js.map +1 -1
  87. package/dist/PredictiveStudio/resources/ps-studio-resource.component.d.ts +17 -1
  88. package/dist/PredictiveStudio/resources/ps-studio-resource.component.d.ts.map +1 -1
  89. package/dist/PredictiveStudio/resources/ps-studio-resource.component.js +309 -138
  90. package/dist/PredictiveStudio/resources/ps-studio-resource.component.js.map +1 -1
  91. package/dist/VersionHistory/components/graph-resource.component.d.ts +1 -0
  92. package/dist/VersionHistory/components/graph-resource.component.d.ts.map +1 -1
  93. package/dist/VersionHistory/components/graph-resource.component.js +6 -5
  94. package/dist/VersionHistory/components/graph-resource.component.js.map +1 -1
  95. package/dist/predictive-studio-dashboards.module.d.ts +10 -8
  96. package/dist/predictive-studio-dashboards.module.d.ts.map +1 -1
  97. package/dist/predictive-studio-dashboards.module.js +13 -3
  98. package/dist/predictive-studio-dashboards.module.js.map +1 -1
  99. package/package.json +64 -63
@@ -5,7 +5,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject } from '@angular/core';
8
- import { RegisterClass } from '@memberjunction/global';
8
+ import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
9
+ import { UserInfoEngine } from '@memberjunction/core-entities';
9
10
  import { BaseResourceComponent } from '@memberjunction/ng-shared';
10
11
  import { PSResourceBase } from './ps-resource-base';
11
12
  import { MODELS_SECTIONS, sectionGroups, sectionsInGroup, sectionLabel, hasSection } from '../predictive-studio.nav';
@@ -14,8 +15,9 @@ import { validateStringParam } from '../../shared/agent-tool-validation';
14
15
  import * as i0 from "@angular/core";
15
16
  import * as i1 from "@memberjunction/ng-ui-components";
16
17
  import * as i2 from "@memberjunction/ng-shared-generic";
17
- import * as i3 from "../components/ps-registry.component";
18
- import * as i4 from "../components/ps-production.component";
18
+ import * as i3 from "angular-split";
19
+ import * as i4 from "../components/ps-registry.component";
20
+ import * as i5 from "../components/ps-production.component";
19
21
  const _forTrack0 = ($index, $item) => $item.key;
20
22
  function PSModelsResourceComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
21
23
  i0.ɵɵelement(0, "mj-loading", 2);
@@ -42,72 +44,110 @@ function PSModelsResourceComponent_Conditional_3_Template(rf, ctx) { if (rf & 1)
42
44
  i0.ɵɵadvance(2);
43
45
  i0.ɵɵtextInterpolate(ctx_r1.loadError);
44
46
  } }
45
- function PSModelsResourceComponent_Conditional_4_For_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
46
- i0.ɵɵelementStart(0, "div", 14);
47
+ function PSModelsResourceComponent_Conditional_4_Conditional_1_Template(rf, ctx) { if (rf & 1) {
48
+ const _r4 = i0.ɵɵgetCurrentView();
49
+ i0.ɵɵelementStart(0, "div", 11)(1, "button", 18);
50
+ i0.ɵɵlistener("click", function PSModelsResourceComponent_Conditional_4_Conditional_1_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleNav()); });
51
+ i0.ɵɵelement(2, "i", 19);
52
+ i0.ɵɵelementEnd();
53
+ i0.ɵɵelementStart(3, "div", 20);
54
+ i0.ɵɵelement(4, "i", 21);
55
+ i0.ɵɵtext(5, " Models");
56
+ i0.ɵɵelementEnd()();
57
+ } }
58
+ function PSModelsResourceComponent_Conditional_4_Conditional_3_For_8_Conditional_0_Template(rf, ctx) { if (rf & 1) {
59
+ i0.ɵɵelementStart(0, "div", 27);
47
60
  i0.ɵɵtext(1);
48
61
  i0.ɵɵelementEnd();
49
62
  } if (rf & 2) {
50
- const group_r3 = i0.ɵɵnextContext().$implicit;
63
+ const group_r6 = i0.ɵɵnextContext().$implicit;
51
64
  i0.ɵɵadvance();
52
- i0.ɵɵtextInterpolate(group_r3);
65
+ i0.ɵɵtextInterpolate(group_r6);
53
66
  } }
54
- function PSModelsResourceComponent_Conditional_4_For_3_For_2_Template(rf, ctx) { if (rf & 1) {
55
- const _r4 = i0.ɵɵgetCurrentView();
56
- i0.ɵɵelementStart(0, "button", 16);
57
- i0.ɵɵlistener("click", function PSModelsResourceComponent_Conditional_4_For_3_For_2_Template_button_click_0_listener() { const item_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectSection(item_r5.key)); });
67
+ function PSModelsResourceComponent_Conditional_4_Conditional_3_For_8_For_2_Template(rf, ctx) { if (rf & 1) {
68
+ const _r7 = i0.ɵɵgetCurrentView();
69
+ i0.ɵɵelementStart(0, "button", 29);
70
+ i0.ɵɵlistener("click", function PSModelsResourceComponent_Conditional_4_Conditional_3_For_8_For_2_Template_button_click_0_listener() { const item_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.selectSection(item_r8.key)); });
58
71
  i0.ɵɵelement(1, "i");
59
72
  i0.ɵɵelementStart(2, "span");
60
73
  i0.ɵɵtext(3);
61
74
  i0.ɵɵelementEnd()();
62
75
  } if (rf & 2) {
63
- const item_r5 = ctx.$implicit;
64
- const ctx_r1 = i0.ɵɵnextContext(3);
65
- i0.ɵɵclassProp("active", ctx_r1.activeSection === item_r5.key);
66
- i0.ɵɵattribute("data-testid", "ps-nav-" + item_r5.key);
76
+ const item_r8 = ctx.$implicit;
77
+ const ctx_r1 = i0.ɵɵnextContext(4);
78
+ i0.ɵɵclassProp("active", ctx_r1.activeSection === item_r8.key);
79
+ i0.ɵɵattribute("data-testid", "ps-nav-" + item_r8.key);
67
80
  i0.ɵɵadvance();
68
- i0.ɵɵclassMap(item_r5.icon);
81
+ i0.ɵɵclassMap(item_r8.icon);
69
82
  i0.ɵɵadvance(2);
70
- i0.ɵɵtextInterpolate(item_r5.label);
83
+ i0.ɵɵtextInterpolate(item_r8.label);
71
84
  } }
72
- function PSModelsResourceComponent_Conditional_4_For_3_Template(rf, ctx) { if (rf & 1) {
73
- i0.ɵɵconditionalCreate(0, PSModelsResourceComponent_Conditional_4_For_3_Conditional_0_Template, 2, 1, "div", 14);
74
- i0.ɵɵrepeaterCreate(1, PSModelsResourceComponent_Conditional_4_For_3_For_2_Template, 4, 6, "button", 15, _forTrack0);
85
+ function PSModelsResourceComponent_Conditional_4_Conditional_3_For_8_Template(rf, ctx) { if (rf & 1) {
86
+ i0.ɵɵconditionalCreate(0, PSModelsResourceComponent_Conditional_4_Conditional_3_For_8_Conditional_0_Template, 2, 1, "div", 27);
87
+ i0.ɵɵrepeaterCreate(1, PSModelsResourceComponent_Conditional_4_Conditional_3_For_8_For_2_Template, 4, 6, "button", 28, _forTrack0);
75
88
  } if (rf & 2) {
76
- const group_r3 = ctx.$implicit;
77
- const ctx_r1 = i0.ɵɵnextContext(2);
78
- i0.ɵɵconditional(group_r3 ? 0 : -1);
89
+ const group_r6 = ctx.$implicit;
90
+ const ctx_r1 = i0.ɵɵnextContext(3);
91
+ i0.ɵɵconditional(group_r6 ? 0 : -1);
79
92
  i0.ɵɵadvance();
80
- i0.ɵɵrepeater(ctx_r1.itemsForGroup(group_r3));
93
+ i0.ɵɵrepeater(ctx_r1.itemsForGroup(group_r6));
81
94
  } }
82
- function PSModelsResourceComponent_Conditional_4_Case_5_Template(rf, ctx) { if (rf & 1) {
83
- i0.ɵɵelement(0, "ps-registry", 12);
95
+ function PSModelsResourceComponent_Conditional_4_Conditional_3_Template(rf, ctx) { if (rf & 1) {
96
+ const _r5 = i0.ɵɵgetCurrentView();
97
+ i0.ɵɵelementStart(0, "as-split-area", 13)(1, "aside", 22)(2, "div", 23)(3, "span", 24);
98
+ i0.ɵɵtext(4, "Lifecycle");
99
+ i0.ɵɵelementEnd();
100
+ i0.ɵɵelementStart(5, "button", 25);
101
+ i0.ɵɵlistener("click", function PSModelsResourceComponent_Conditional_4_Conditional_3_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleNav()); });
102
+ i0.ɵɵelement(6, "i", 26);
103
+ i0.ɵɵelementEnd()();
104
+ i0.ɵɵrepeaterCreate(7, PSModelsResourceComponent_Conditional_4_Conditional_3_For_8_Template, 3, 1, null, null, i0.ɵɵrepeaterTrackByIdentity);
105
+ i0.ɵɵelementEnd()();
84
106
  } if (rf & 2) {
85
107
  const ctx_r1 = i0.ɵɵnextContext(2);
86
- i0.ɵɵproperty("engine", ctx_r1.engine)("provider", ctx_r1.ProviderToUse)("currentUser", ctx_r1.ProviderToUse.CurrentUser);
108
+ i0.ɵɵproperty("size", ctx_r1.navSizePct)("minSize", 10)("maxSize", 30);
109
+ i0.ɵɵadvance(7);
110
+ i0.ɵɵrepeater(ctx_r1.groups);
87
111
  } }
88
112
  function PSModelsResourceComponent_Conditional_4_Case_6_Template(rf, ctx) { if (rf & 1) {
89
- i0.ɵɵelement(0, "ps-production", 13);
113
+ i0.ɵɵelement(0, "ps-registry", 16);
114
+ } if (rf & 2) {
115
+ const ctx_r1 = i0.ɵɵnextContext(2);
116
+ i0.ɵɵproperty("engine", ctx_r1.engine)("provider", ctx_r1.ProviderToUse)("currentUser", ctx_r1.ProviderToUse.CurrentUser)("initialModelId", ctx_r1.initialModelId);
117
+ } }
118
+ function PSModelsResourceComponent_Conditional_4_Case_7_Template(rf, ctx) { if (rf & 1) {
119
+ i0.ɵɵelement(0, "ps-production", 17);
90
120
  } if (rf & 2) {
91
121
  const ctx_r1 = i0.ɵɵnextContext(2);
92
122
  i0.ɵɵproperty("engine", ctx_r1.engine);
93
123
  } }
94
124
  function PSModelsResourceComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
95
- i0.ɵɵelementStart(0, "div", 4)(1, "aside", 10);
96
- i0.ɵɵrepeaterCreate(2, PSModelsResourceComponent_Conditional_4_For_3_Template, 3, 1, null, null, i0.ɵɵrepeaterTrackByIdentity);
97
- i0.ɵɵelementEnd();
98
- i0.ɵɵelementStart(4, "section", 11);
99
- i0.ɵɵconditionalCreate(5, PSModelsResourceComponent_Conditional_4_Case_5_Template, 1, 3, "ps-registry", 12)(6, PSModelsResourceComponent_Conditional_4_Case_6_Template, 1, 1, "ps-production", 13);
100
- i0.ɵɵelementEnd()();
125
+ const _r3 = i0.ɵɵgetCurrentView();
126
+ i0.ɵɵelementStart(0, "div", 10);
127
+ i0.ɵɵconditionalCreate(1, PSModelsResourceComponent_Conditional_4_Conditional_1_Template, 6, 0, "div", 11);
128
+ i0.ɵɵelementStart(2, "as-split", 12);
129
+ i0.ɵɵlistener("dragEnd", function PSModelsResourceComponent_Conditional_4_Template_as_split_dragEnd_2_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSplitDragEnd($event.sizes)); });
130
+ i0.ɵɵconditionalCreate(3, PSModelsResourceComponent_Conditional_4_Conditional_3_Template, 9, 3, "as-split-area", 13);
131
+ i0.ɵɵelementStart(4, "as-split-area", 14)(5, "section", 15);
132
+ i0.ɵɵconditionalCreate(6, PSModelsResourceComponent_Conditional_4_Case_6_Template, 1, 4, "ps-registry", 16)(7, PSModelsResourceComponent_Conditional_4_Case_7_Template, 1, 1, "ps-production", 17);
133
+ i0.ɵɵelementEnd()()()();
101
134
  } if (rf & 2) {
102
- let tmp_4_0;
135
+ let tmp_9_0;
103
136
  const ctx_r1 = i0.ɵɵnextContext();
104
- i0.ɵɵadvance(2);
105
- i0.ɵɵrepeater(ctx_r1.groups);
106
- i0.ɵɵadvance(2);
107
- i0.ɵɵclassProp("fill", ctx_r1.activeSection === "registry");
137
+ i0.ɵɵclassProp("nav-collapsed", ctx_r1.isNavCollapsed);
138
+ i0.ɵɵadvance();
139
+ i0.ɵɵconditional(ctx_r1.isNavCollapsed ? 1 : -1);
140
+ i0.ɵɵadvance();
141
+ i0.ɵɵproperty("gutterSize", ctx_r1.isNavCollapsed ? 0 : 6);
142
+ i0.ɵɵadvance();
143
+ i0.ɵɵconditional(!ctx_r1.isNavCollapsed ? 3 : -1);
144
+ i0.ɵɵadvance();
145
+ i0.ɵɵproperty("size", ctx_r1.isNavCollapsed ? 100 : ctx_r1.contentSizePct)("minSize", 50);
146
+ i0.ɵɵadvance();
147
+ i0.ɵɵclassProp("fill", ctx_r1.activeSection === "registry" || ctx_r1.activeSection === "production");
108
148
  i0.ɵɵattribute("data-testid", "ps-panel-" + ctx_r1.activeSection);
109
149
  i0.ɵɵadvance();
110
- i0.ɵɵconditional((tmp_4_0 = ctx_r1.activeSection) === "registry" ? 5 : tmp_4_0 === "production" ? 6 : -1);
150
+ i0.ɵɵconditional((tmp_9_0 = ctx_r1.activeSection) === "registry" ? 6 : tmp_9_0 === "production" ? 7 : -1);
111
151
  } }
112
152
  /**
113
153
  * **Models** — the trained-model lifecycle door (one of Predictive Studio's three consolidated nav
@@ -124,18 +164,68 @@ let PSModelsResourceComponent = class PSModelsResourceComponent extends PSResour
124
164
  cdrLocal = inject(ChangeDetectorRef);
125
165
  activeSection = 'registry';
126
166
  sections = MODELS_SECTIONS;
167
+ initialModelId;
168
+ isNavCollapsed = false;
169
+ navSizePct = 14;
170
+ contentSizePct = 86;
127
171
  ngOnInit() {
128
172
  super.ngOnInit();
129
- const initial = this.GetQueryParams()['section'];
173
+ const qp = this.GetQueryParams();
174
+ const initial = qp['section'];
130
175
  if (initial && hasSection(this.sections, initial))
131
176
  this.activeSection = initial;
177
+ if (qp['modelId'])
178
+ this.initialModelId = qp['modelId'];
179
+ this.loadLayoutPrefs();
132
180
  }
133
- OnQueryParamsChanged(params, _source) {
181
+ toggleNav() {
182
+ this.isNavCollapsed = !this.isNavCollapsed;
183
+ this.saveLayoutPrefs();
184
+ this.cdrLocal.detectChanges();
185
+ }
186
+ onSplitDragEnd(sizes) {
187
+ if (Array.isArray(sizes) && sizes.length === 2 && typeof sizes[0] === 'number' && typeof sizes[1] === 'number') {
188
+ this.navSizePct = Math.round(sizes[0]);
189
+ this.contentSizePct = Math.round(sizes[1]);
190
+ this.saveLayoutPrefs();
191
+ }
192
+ }
193
+ loadLayoutPrefs() {
194
+ const raw = UserInfoEngine.Instance.GetSetting('mj.predictiveStudio.models.layout');
195
+ if (raw) {
196
+ try {
197
+ const parsed = JSON.parse(raw);
198
+ if (typeof parsed.navSizePct === 'number' && parsed.navSizePct >= 10 && parsed.navSizePct <= 35) {
199
+ this.navSizePct = parsed.navSizePct;
200
+ this.contentSizePct = 100 - parsed.navSizePct;
201
+ }
202
+ if (typeof parsed.isNavCollapsed === 'boolean') {
203
+ this.isNavCollapsed = parsed.isNavCollapsed;
204
+ }
205
+ }
206
+ catch { }
207
+ }
208
+ }
209
+ saveLayoutPrefs() {
210
+ const prefs = {
211
+ navSizePct: this.navSizePct,
212
+ contentSizePct: this.contentSizePct,
213
+ isNavCollapsed: this.isNavCollapsed,
214
+ };
215
+ UserInfoEngine.Instance.SetSettingDebounced('mj.predictiveStudio.models.layout', JSON.stringify(prefs));
216
+ }
217
+ async OnQueryParamsChanged(params, _source) {
134
218
  const next = params['section'];
135
219
  if (next && next !== this.activeSection && hasSection(this.sections, next)) {
136
220
  this.activeSection = next;
137
- this.cdrLocal.detectChanges();
138
221
  }
222
+ if (params['modelId']) {
223
+ this.initialModelId = params['modelId'];
224
+ if (this.engine && !this.engine.Models.some((m) => UUIDsEqual(m.ID, params['modelId']))) {
225
+ await this.engine.Config(true, this.ProviderToUse.CurrentUser ?? undefined, this.ProviderToUse);
226
+ }
227
+ }
228
+ this.cdrLocal.detectChanges();
139
229
  }
140
230
  /** Deep agent context for the Models door: active section + trained-model lifecycle counts. */
141
231
  extraAgentContext() {
@@ -195,10 +285,10 @@ let PSModelsResourceComponent = class PSModelsResourceComponent extends PSResour
195
285
  this.cdrLocal.detectChanges();
196
286
  }
197
287
  static ɵfac = /*@__PURE__*/ (() => { let ɵPSModelsResourceComponent_BaseFactory; return function PSModelsResourceComponent_Factory(__ngFactoryType__) { return (ɵPSModelsResourceComponent_BaseFactory || (ɵPSModelsResourceComponent_BaseFactory = i0.ɵɵgetInheritedFactory(PSModelsResourceComponent)))(__ngFactoryType__ || PSModelsResourceComponent); }; })();
198
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PSModelsResourceComponent, selectors: [["mj-ps-models-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 5, consts: [[3, "Title", "Subtitle"], [3, "Flex", "Padding"], ["text", "Loading Models\u2026", "size", "medium"], ["data-testid", "ps-load-error", "role", "alert", 1, "ps-load-error"], ["data-testid", "ps-models-shell", 1, "ps-models-host"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "ps-load-error-text"], [1, "ps-load-error-detail"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-rotate-right"], [1, "ps-leftnav"], [1, "ps-content"], [3, "engine", "provider", "currentUser"], [3, "engine"], [1, "ps-nav-group"], [1, "ps-nav-item", 3, "active"], [1, "ps-nav-item", 3, "click"]], template: function PSModelsResourceComponent_Template(rf, ctx) { if (rf & 1) {
288
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PSModelsResourceComponent, selectors: [["mj-ps-models-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 5, consts: [[3, "Title", "Subtitle"], [3, "Flex", "Padding"], ["text", "Loading Models\u2026", "size", "medium"], ["data-testid", "ps-load-error", "role", "alert", 1, "ps-load-error"], ["data-testid", "ps-models-shell", 1, "ps-models-host", 3, "nav-collapsed"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "ps-load-error-text"], [1, "ps-load-error-detail"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-rotate-right"], ["data-testid", "ps-models-shell", 1, "ps-models-host"], ["role", "region", "aria-label", "Models navigation (collapsed)", 1, "ps-nav-collapsed-strip"], ["direction", "horizontal", "unit", "percent", 1, "models-splitter", 3, "dragEnd", "gutterSize"], [3, "size", "minSize", "maxSize"], [3, "size", "minSize"], [1, "ps-content"], [3, "engine", "provider", "currentUser", "initialModelId"], [3, "engine"], ["type", "button", "aria-label", "Expand models navigation", "title", "Expand navigation", 1, "ps-nav-rail-collapse", 3, "click"], [1, "fa-solid", "fa-chevron-right"], [1, "ps-nav-collapsed-strip-label"], [1, "fa-solid", "fa-cubes"], [1, "ps-leftnav"], [1, "ps-leftnav-header"], [1, "ps-leftnav-title"], ["type", "button", "title", "Collapse navigation", "aria-label", "Collapse navigation", 1, "ps-leftnav-collapse-btn", 3, "click"], [1, "fa-solid", "fa-chevron-left"], [1, "ps-nav-group"], [1, "ps-nav-item", 3, "active"], [1, "ps-nav-item", 3, "click"]], template: function PSModelsResourceComponent_Template(rf, ctx) { if (rf & 1) {
199
289
  i0.ɵɵelement(0, "mj-page-header-interior", 0);
200
290
  i0.ɵɵelementStart(1, "mj-page-body-interior", 1);
201
- i0.ɵɵconditionalCreate(2, PSModelsResourceComponent_Conditional_2_Template, 1, 0, "mj-loading", 2)(3, PSModelsResourceComponent_Conditional_3_Template, 10, 2, "div", 3)(4, PSModelsResourceComponent_Conditional_4_Template, 7, 4, "div", 4);
291
+ i0.ɵɵconditionalCreate(2, PSModelsResourceComponent_Conditional_2_Template, 1, 0, "mj-loading", 2)(3, PSModelsResourceComponent_Conditional_3_Template, 10, 2, "div", 3)(4, PSModelsResourceComponent_Conditional_4_Template, 8, 11, "div", 4);
202
292
  i0.ɵɵelementEnd();
203
293
  } if (rf & 2) {
204
294
  i0.ɵɵproperty("Title", ctx.activeLabel)("Subtitle", ctx.activeSubtitle);
@@ -206,7 +296,7 @@ let PSModelsResourceComponent = class PSModelsResourceComponent extends PSResour
206
296
  i0.ɵɵproperty("Flex", true)("Padding", false);
207
297
  i0.ɵɵadvance();
208
298
  i0.ɵɵconditional(ctx.isLoading ? 2 : ctx.loadError ? 3 : 4);
209
- } }, dependencies: [i1.MJButtonDirective, i1.MJPageHeaderInteriorComponent, i1.MJPageBodyInteriorComponent, i2.LoadingComponent, i3.PSRegistryComponent, i4.PSProductionComponent], styles: ["[_nghost-%COMP%] { display: flex; flex-direction: column; width: 100%; height: 100%; min-height: 0; }\n .ps-models-host[_ngcontent-%COMP%] { display: flex; flex: 1; min-height: 0; overflow: hidden; }\n .ps-leftnav[_ngcontent-%COMP%] { width: 210px; flex: none; border-right: 1px solid var(--mj-border-default); background: var(--mj-bg-surface-card); overflow-y: auto; padding: 10px 8px; display: flex; flex-direction: column; gap: 2px; }\n .ps-nav-group[_ngcontent-%COMP%] { font-size: var(--mj-text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--mj-text-muted); padding: 12px 10px 4px; }\n .ps-nav-item[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 8px 10px; border: none; background: transparent; border-radius: var(--mj-radius-md); cursor: pointer; color: var(--mj-text-secondary); font-size: var(--mj-text-sm); font-weight: 500; transition: background .12s, color .12s; }\n .ps-nav-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { width: 18px; text-align: center; color: var(--mj-text-muted); }\n .ps-nav-item[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n .ps-nav-item.active[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); color: var(--mj-brand-primary); font-weight: 600; }\n .ps-nav-item.active[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n .ps-content[_ngcontent-%COMP%] { flex: 1; min-width: 0; overflow-y: auto; padding: 8px 14px 24px; }\n \n\n .ps-content.fill[_ngcontent-%COMP%] { overflow: hidden; display: flex; flex-direction: column; padding-bottom: 14px; }\n .ps-content.fill[_ngcontent-%COMP%] > *[_ngcontent-%COMP%] { flex: 1; min-height: 0; display: flex; flex-direction: column; }\n .ps-load-error[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 14px; max-width: 620px; margin: 32px auto; padding: 18px 20px; border: 1px solid var(--mj-status-error-border); background: var(--mj-status-error-bg); border-radius: var(--mj-radius-lg); }\n .ps-load-error[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] { font-size: 24px; color: var(--mj-status-error); }\n .ps-load-error-text[_ngcontent-%COMP%] { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }\n .ps-load-error-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] { color: var(--mj-text-primary); }\n .ps-load-error-detail[_ngcontent-%COMP%] { color: var(--mj-text-secondary); font-size: var(--mj-text-sm); word-break: break-word; }"], changeDetection: 0 });
299
+ } }, dependencies: [i1.MJButtonDirective, i1.MJPageHeaderInteriorComponent, i1.MJPageBodyInteriorComponent, i2.LoadingComponent, i3.SplitComponent, i3.SplitAreaComponent, i4.PSRegistryComponent, i5.PSProductionComponent], styles: ["[_nghost-%COMP%] { display: flex; flex-direction: column; width: 100%; height: 100%; min-height: 0; }\n .ps-models-host[_ngcontent-%COMP%] { display: flex; flex: 1; min-height: 0; overflow: hidden; width: 100%; height: 100%; }\n .models-splitter[_ngcontent-%COMP%] { flex: 1; width: 100%; height: 100%; min-height: 0; min-width: 0; background: transparent; }\n .models-splitter[_ngcontent-%COMP%] .as-split-gutter[_ngcontent-%COMP%] { background: transparent; transition: background-color 0.15s ease; position: relative; }\n .models-splitter[_ngcontent-%COMP%] .as-split-gutter[_ngcontent-%COMP%]:hover { background-color: var(--mj-brand-primary, #6366f1); }\n .models-splitter[_ngcontent-%COMP%] .as-split-gutter[_ngcontent-%COMP%]::after { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 2px; height: 24px; border-radius: 1px; background: var(--mj-border-strong, #cbd5e1); }\n .models-splitter[_ngcontent-%COMP%] .as-split-gutter[_ngcontent-%COMP%]:hover::after { background: #ffffff; }\n\n .ps-nav-collapsed-strip[_ngcontent-%COMP%] { width: 44px; min-width: 44px; max-width: 44px; flex: none; background: var(--mj-bg-surface); border-right: 1px solid var(--mj-border-default); display: flex; flex-direction: column; align-items: center; padding: 10px 0; gap: 14px; z-index: 2; }\n .ps-nav-rail-collapse[_ngcontent-%COMP%] { background: var(--mj-bg-surface-subtle); border: 1px solid var(--mj-border-default); border-radius: 6px; color: var(--mj-text-secondary); cursor: pointer; display: grid; place-items: center; width: 28px; height: 28px; padding: 0; font-size: 11px; transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease; }\n .ps-nav-rail-collapse[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); border-color: var(--mj-border-strong); }\n .ps-nav-collapsed-strip-label[_ngcontent-%COMP%] { writing-mode: vertical-rl; transform: rotate(180deg); font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--mj-text-muted); display: flex; align-items: center; gap: 8px; text-transform: uppercase; }\n\n .ps-leftnav[_ngcontent-%COMP%] { width: 100%; height: 100%; border-right: 1px solid var(--mj-border-default); background: var(--mj-bg-surface-card); overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; box-sizing: border-box; }\n .ps-leftnav-header[_ngcontent-%COMP%] { display: flex; align-items: center; justify-content: space-between; padding: 4px 6px 8px; border-bottom: 1px solid var(--mj-border-subtle); margin-bottom: 4px; }\n .ps-leftnav-title[_ngcontent-%COMP%] { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--mj-text-muted); }\n .ps-leftnav-collapse-btn[_ngcontent-%COMP%] { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 6px; border: 1px solid var(--mj-border-default); background: var(--mj-bg-surface); color: var(--mj-text-muted); cursor: pointer; transition: all 0.15s ease; padding: 0; }\n .ps-leftnav-collapse-btn[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); border-color: var(--mj-border-strong); }\n\n .ps-nav-group[_ngcontent-%COMP%] { font-size: var(--mj-text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--mj-text-muted); padding: 10px 8px 4px; }\n .ps-nav-item[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 8px 10px; border: none; background: transparent; border-radius: var(--mj-radius-md); cursor: pointer; color: var(--mj-text-secondary); font-size: var(--mj-text-sm); font-weight: 500; transition: background .12s, color .12s; }\n .ps-nav-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { width: 18px; text-align: center; color: var(--mj-text-muted); }\n .ps-nav-item[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n .ps-nav-item.active[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); color: var(--mj-brand-primary); font-weight: 600; }\n .ps-nav-item.active[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n .ps-content[_ngcontent-%COMP%] { width: 100%; height: 100%; flex: 1; min-width: 0; overflow-y: auto; padding: 8px 14px 24px; }\n \n\n .ps-content.fill[_ngcontent-%COMP%] { overflow: hidden; display: flex; flex-direction: column; padding-bottom: 14px; }\n .ps-content.fill[_ngcontent-%COMP%] > *[_ngcontent-%COMP%] { flex: 1; min-height: 0; display: flex; flex-direction: column; }\n .ps-load-error[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 14px; max-width: 620px; margin: 32px auto; padding: 18px 20px; border: 1px solid var(--mj-status-error-border); background: var(--mj-status-error-bg); border-radius: var(--mj-radius-lg); }\n .ps-load-error[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] { font-size: 24px; color: var(--mj-status-error); }\n .ps-load-error-text[_ngcontent-%COMP%] { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }\n .ps-load-error-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] { color: var(--mj-text-primary); }\n .ps-load-error-detail[_ngcontent-%COMP%] { color: var(--mj-text-secondary); font-size: var(--mj-text-sm); word-break: break-word; }"], changeDetection: 0 });
210
300
  };
211
301
  PSModelsResourceComponent = __decorate([
212
302
  RegisterClass(BaseResourceComponent, 'PredictiveStudioModelsResource')
@@ -230,31 +320,54 @@ export { PSModelsResourceComponent };
230
320
  <button mjButton variant="secondary" size="sm" (click)="retryLoad()"><i class="fa-solid fa-rotate-right"></i> Try again</button>
231
321
  </div>
232
322
  } @else {
233
- <div class="ps-models-host" data-testid="ps-models-shell">
234
- <aside class="ps-leftnav">
235
- @for (group of groups; track group) {
236
- @if (group) { <div class="ps-nav-group">{{ group }}</div> }
237
- @for (item of itemsForGroup(group); track item.key) {
238
- <button class="ps-nav-item" [class.active]="activeSection === item.key"
239
- [attr.data-testid]="'ps-nav-' + item.key" (click)="selectSection(item.key)">
240
- <i [class]="item.icon"></i> <span>{{ item.label }}</span>
241
- </button>
242
- }
243
- }
244
- </aside>
323
+ <div class="ps-models-host" [class.nav-collapsed]="isNavCollapsed" data-testid="ps-models-shell">
324
+ @if (isNavCollapsed) {
325
+ <div class="ps-nav-collapsed-strip" role="region" aria-label="Models navigation (collapsed)">
326
+ <button class="ps-nav-rail-collapse" type="button" (click)="toggleNav()" aria-label="Expand models navigation" title="Expand navigation">
327
+ <i class="fa-solid fa-chevron-right"></i>
328
+ </button>
329
+ <div class="ps-nav-collapsed-strip-label"><i class="fa-solid fa-cubes"></i> Models</div>
330
+ </div>
331
+ }
245
332
 
246
- <section class="ps-content" [class.fill]="activeSection === 'registry'" [attr.data-testid]="'ps-panel-' + activeSection">
247
- @switch (activeSection) {
248
- @case ('registry') { <ps-registry [engine]="engine" [provider]="ProviderToUse" [currentUser]="ProviderToUse.CurrentUser"></ps-registry> }
249
- @case ('production') { <ps-production [engine]="engine"></ps-production> }
333
+ <as-split direction="horizontal" class="models-splitter" unit="percent" [gutterSize]="isNavCollapsed ? 0 : 6" (dragEnd)="onSplitDragEnd($event.sizes)">
334
+ @if (!isNavCollapsed) {
335
+ <as-split-area [size]="navSizePct" [minSize]="10" [maxSize]="30">
336
+ <aside class="ps-leftnav">
337
+ <div class="ps-leftnav-header">
338
+ <span class="ps-leftnav-title">Lifecycle</span>
339
+ <button class="ps-leftnav-collapse-btn" type="button" (click)="toggleNav()" title="Collapse navigation" aria-label="Collapse navigation">
340
+ <i class="fa-solid fa-chevron-left"></i>
341
+ </button>
342
+ </div>
343
+ @for (group of groups; track group) {
344
+ @if (group) { <div class="ps-nav-group">{{ group }}</div> }
345
+ @for (item of itemsForGroup(group); track item.key) {
346
+ <button class="ps-nav-item" [class.active]="activeSection === item.key"
347
+ [attr.data-testid]="'ps-nav-' + item.key" (click)="selectSection(item.key)">
348
+ <i [class]="item.icon"></i> <span>{{ item.label }}</span>
349
+ </button>
350
+ }
351
+ }
352
+ </aside>
353
+ </as-split-area>
250
354
  }
251
- </section>
355
+
356
+ <as-split-area [size]="isNavCollapsed ? 100 : contentSizePct" [minSize]="50">
357
+ <section class="ps-content" [class.fill]="activeSection === 'registry' || activeSection === 'production'" [attr.data-testid]="'ps-panel-' + activeSection">
358
+ @switch (activeSection) {
359
+ @case ('registry') { <ps-registry [engine]="engine" [provider]="ProviderToUse" [currentUser]="ProviderToUse.CurrentUser" [initialModelId]="initialModelId"></ps-registry> }
360
+ @case ('production') { <ps-production [engine]="engine"></ps-production> }
361
+ }
362
+ </section>
363
+ </as-split-area>
364
+ </as-split>
252
365
  </div>
253
366
  }
254
367
  </mj-page-body-interior>
255
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["\n :host { display: flex; flex-direction: column; width: 100%; height: 100%; min-height: 0; }\n .ps-models-host { display: flex; flex: 1; min-height: 0; overflow: hidden; }\n .ps-leftnav { width: 210px; flex: none; border-right: 1px solid var(--mj-border-default); background: var(--mj-bg-surface-card); overflow-y: auto; padding: 10px 8px; display: flex; flex-direction: column; gap: 2px; }\n .ps-nav-group { font-size: var(--mj-text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--mj-text-muted); padding: 12px 10px 4px; }\n .ps-nav-item { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 8px 10px; border: none; background: transparent; border-radius: var(--mj-radius-md); cursor: pointer; color: var(--mj-text-secondary); font-size: var(--mj-text-sm); font-weight: 500; transition: background .12s, color .12s; }\n .ps-nav-item i { width: 18px; text-align: center; color: var(--mj-text-muted); }\n .ps-nav-item:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n .ps-nav-item.active { background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); color: var(--mj-brand-primary); font-weight: 600; }\n .ps-nav-item.active i { color: var(--mj-brand-primary); }\n .ps-content { flex: 1; min-width: 0; overflow-y: auto; padding: 8px 14px 24px; }\n /* Fill mode (registry): the section stops page-scrolling so the panel's inner\n columns (model list / detail) can each own their scrollbar. */\n .ps-content.fill { overflow: hidden; display: flex; flex-direction: column; padding-bottom: 14px; }\n .ps-content.fill > * { flex: 1; min-height: 0; display: flex; flex-direction: column; }\n .ps-load-error { display: flex; align-items: center; gap: 14px; max-width: 620px; margin: 32px auto; padding: 18px 20px; border: 1px solid var(--mj-status-error-border); background: var(--mj-status-error-bg); border-radius: var(--mj-radius-lg); }\n .ps-load-error > i { font-size: 24px; color: var(--mj-status-error); }\n .ps-load-error-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }\n .ps-load-error-text strong { color: var(--mj-text-primary); }\n .ps-load-error-detail { color: var(--mj-text-secondary); font-size: var(--mj-text-sm); word-break: break-word; }\n "] }]
368
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["\n :host { display: flex; flex-direction: column; width: 100%; height: 100%; min-height: 0; }\n .ps-models-host { display: flex; flex: 1; min-height: 0; overflow: hidden; width: 100%; height: 100%; }\n .models-splitter { flex: 1; width: 100%; height: 100%; min-height: 0; min-width: 0; background: transparent; }\n .models-splitter .as-split-gutter { background: transparent; transition: background-color 0.15s ease; position: relative; }\n .models-splitter .as-split-gutter:hover { background-color: var(--mj-brand-primary, #6366f1); }\n .models-splitter .as-split-gutter::after { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 2px; height: 24px; border-radius: 1px; background: var(--mj-border-strong, #cbd5e1); }\n .models-splitter .as-split-gutter:hover::after { background: #ffffff; }\n\n .ps-nav-collapsed-strip { width: 44px; min-width: 44px; max-width: 44px; flex: none; background: var(--mj-bg-surface); border-right: 1px solid var(--mj-border-default); display: flex; flex-direction: column; align-items: center; padding: 10px 0; gap: 14px; z-index: 2; }\n .ps-nav-rail-collapse { background: var(--mj-bg-surface-subtle); border: 1px solid var(--mj-border-default); border-radius: 6px; color: var(--mj-text-secondary); cursor: pointer; display: grid; place-items: center; width: 28px; height: 28px; padding: 0; font-size: 11px; transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease; }\n .ps-nav-rail-collapse:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); border-color: var(--mj-border-strong); }\n .ps-nav-collapsed-strip-label { writing-mode: vertical-rl; transform: rotate(180deg); font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--mj-text-muted); display: flex; align-items: center; gap: 8px; text-transform: uppercase; }\n\n .ps-leftnav { width: 100%; height: 100%; border-right: 1px solid var(--mj-border-default); background: var(--mj-bg-surface-card); overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; box-sizing: border-box; }\n .ps-leftnav-header { display: flex; align-items: center; justify-content: space-between; padding: 4px 6px 8px; border-bottom: 1px solid var(--mj-border-subtle); margin-bottom: 4px; }\n .ps-leftnav-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--mj-text-muted); }\n .ps-leftnav-collapse-btn { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 6px; border: 1px solid var(--mj-border-default); background: var(--mj-bg-surface); color: var(--mj-text-muted); cursor: pointer; transition: all 0.15s ease; padding: 0; }\n .ps-leftnav-collapse-btn:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); border-color: var(--mj-border-strong); }\n\n .ps-nav-group { font-size: var(--mj-text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--mj-text-muted); padding: 10px 8px 4px; }\n .ps-nav-item { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 8px 10px; border: none; background: transparent; border-radius: var(--mj-radius-md); cursor: pointer; color: var(--mj-text-secondary); font-size: var(--mj-text-sm); font-weight: 500; transition: background .12s, color .12s; }\n .ps-nav-item i { width: 18px; text-align: center; color: var(--mj-text-muted); }\n .ps-nav-item:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n .ps-nav-item.active { background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); color: var(--mj-brand-primary); font-weight: 600; }\n .ps-nav-item.active i { color: var(--mj-brand-primary); }\n .ps-content { width: 100%; height: 100%; flex: 1; min-width: 0; overflow-y: auto; padding: 8px 14px 24px; }\n /* Fill mode (registry): the section stops page-scrolling so the panel's inner\n columns (model list / detail) can each own their scrollbar. */\n .ps-content.fill { overflow: hidden; display: flex; flex-direction: column; padding-bottom: 14px; }\n .ps-content.fill > * { flex: 1; min-height: 0; display: flex; flex-direction: column; }\n .ps-load-error { display: flex; align-items: center; gap: 14px; max-width: 620px; margin: 32px auto; padding: 18px 20px; border: 1px solid var(--mj-status-error-border); background: var(--mj-status-error-bg); border-radius: var(--mj-radius-lg); }\n .ps-load-error > i { font-size: 24px; color: var(--mj-status-error); }\n .ps-load-error-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }\n .ps-load-error-text strong { color: var(--mj-text-primary); }\n .ps-load-error-detail { color: var(--mj-text-secondary); font-size: var(--mj-text-sm); word-break: break-word; }\n "] }]
256
369
  }], null, null); })();
257
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PSModelsResourceComponent, { className: "PSModelsResourceComponent", filePath: "src/PredictiveStudio/resources/ps-models-resource.component.ts", lineNumber: 86 }); })();
370
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PSModelsResourceComponent, { className: "PSModelsResourceComponent", filePath: "src/PredictiveStudio/resources/ps-models-resource.component.ts", lineNumber: 126 }); })();
258
371
  /** Tree-shaking prevention — called from the subpath module so the @RegisterClass survives bundling. */
259
372
  export function LoadPSModelsResource() {
260
373
  // intentionally empty
@@ -1 +1 @@
1
- {"version":3,"file":"ps-models-resource.component.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/resources/ps-models-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { PSResourceBase } from './ps-resource-base';\nimport { PSPanelKey } from '../predictive-studio.types';\nimport { MODELS_SECTIONS, PSSection, sectionGroups, sectionsInGroup, sectionLabel, hasSection } from '../predictive-studio.nav';\nimport { buildModelsAgentContext, resolvePSRecord, buildPSNotFoundError } from '../predictive-studio-agent-context';\nimport { validateStringParam } from '../../shared/agent-tool-validation';\n\n/**\n * **Models** — the trained-model lifecycle door (one of Predictive Studio's three consolidated nav\n * items, alongside `Predictions` and `Studio`). Hosts the registry + production section panels\n * (`ps-registry`, `ps-production`) behind an internal left-nav. The active section round-trips through\n * the `section` query param, so the `Overview` panel's cross-door \"view in production\" links (and any\n * deep link) can land directly on the right section. No docked copilot here — these are read/manage\n * surfaces; model creation + the Model Dev Agent live in the `Studio` and `Predictions` doors.\n */\n@RegisterClass(BaseResourceComponent, 'PredictiveStudioModelsResource')\n@Component({\n standalone: false,\n selector: 'mj-ps-models-resource',\n template: `\n <mj-page-header-interior [Title]=\"activeLabel\" [Subtitle]=\"activeSubtitle\">\n </mj-page-header-interior>\n <mj-page-body-interior [Flex]=\"true\" [Padding]=\"false\">\n @if (isLoading) {\n <mj-loading text=\"Loading Models…\" size=\"medium\"></mj-loading>\n } @else if (loadError) {\n <div class=\"ps-load-error\" data-testid=\"ps-load-error\" role=\"alert\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <div class=\"ps-load-error-text\">\n <strong>Couldn't load {{ sectionTitle }}</strong>\n <span class=\"ps-load-error-detail\">{{ loadError }}</span>\n </div>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"retryLoad()\"><i class=\"fa-solid fa-rotate-right\"></i> Try again</button>\n </div>\n } @else {\n <div class=\"ps-models-host\" data-testid=\"ps-models-shell\">\n <aside class=\"ps-leftnav\">\n @for (group of groups; track group) {\n @if (group) { <div class=\"ps-nav-group\">{{ group }}</div> }\n @for (item of itemsForGroup(group); track item.key) {\n <button class=\"ps-nav-item\" [class.active]=\"activeSection === item.key\"\n [attr.data-testid]=\"'ps-nav-' + item.key\" (click)=\"selectSection(item.key)\">\n <i [class]=\"item.icon\"></i> <span>{{ item.label }}</span>\n </button>\n }\n }\n </aside>\n\n <section class=\"ps-content\" [class.fill]=\"activeSection === 'registry'\" [attr.data-testid]=\"'ps-panel-' + activeSection\">\n @switch (activeSection) {\n @case ('registry') { <ps-registry [engine]=\"engine\" [provider]=\"ProviderToUse\" [currentUser]=\"ProviderToUse.CurrentUser\"></ps-registry> }\n @case ('production') { <ps-production [engine]=\"engine\"></ps-production> }\n }\n </section>\n </div>\n }\n </mj-page-body-interior>\n `,\n styles: [\n `\n :host { display: flex; flex-direction: column; width: 100%; height: 100%; min-height: 0; }\n .ps-models-host { display: flex; flex: 1; min-height: 0; overflow: hidden; }\n .ps-leftnav { width: 210px; flex: none; border-right: 1px solid var(--mj-border-default); background: var(--mj-bg-surface-card); overflow-y: auto; padding: 10px 8px; display: flex; flex-direction: column; gap: 2px; }\n .ps-nav-group { font-size: var(--mj-text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--mj-text-muted); padding: 12px 10px 4px; }\n .ps-nav-item { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 8px 10px; border: none; background: transparent; border-radius: var(--mj-radius-md); cursor: pointer; color: var(--mj-text-secondary); font-size: var(--mj-text-sm); font-weight: 500; transition: background .12s, color .12s; }\n .ps-nav-item i { width: 18px; text-align: center; color: var(--mj-text-muted); }\n .ps-nav-item:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n .ps-nav-item.active { background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); color: var(--mj-brand-primary); font-weight: 600; }\n .ps-nav-item.active i { color: var(--mj-brand-primary); }\n .ps-content { flex: 1; min-width: 0; overflow-y: auto; padding: 8px 14px 24px; }\n /* Fill mode (registry): the section stops page-scrolling so the panel's inner\n columns (model list / detail) can each own their scrollbar. */\n .ps-content.fill { overflow: hidden; display: flex; flex-direction: column; padding-bottom: 14px; }\n .ps-content.fill > * { flex: 1; min-height: 0; display: flex; flex-direction: column; }\n .ps-load-error { display: flex; align-items: center; gap: 14px; max-width: 620px; margin: 32px auto; padding: 18px 20px; border: 1px solid var(--mj-status-error-border); background: var(--mj-status-error-bg); border-radius: var(--mj-radius-lg); }\n .ps-load-error > i { font-size: 24px; color: var(--mj-status-error); }\n .ps-load-error-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }\n .ps-load-error-text strong { color: var(--mj-text-primary); }\n .ps-load-error-detail { color: var(--mj-text-secondary); font-size: var(--mj-text-sm); word-break: break-word; }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class PSModelsResourceComponent extends PSResourceBase {\n protected readonly SectionKey = 'models';\n protected readonly SectionLabel = 'Models';\n protected readonly SectionIcon = 'fa-solid fa-cubes';\n\n private readonly cdrLocal = inject(ChangeDetectorRef);\n\n public activeSection: PSPanelKey = 'registry';\n public readonly sections: readonly PSSection[] = MODELS_SECTIONS;\n\n override ngOnInit(): void {\n super.ngOnInit();\n const initial = this.GetQueryParams()['section'] as PSPanelKey | undefined;\n if (initial && hasSection(this.sections, initial)) this.activeSection = initial;\n }\n\n protected override OnQueryParamsChanged(params: Record<string, string>, _source: 'popstate' | 'deeplink'): void {\n const next = params['section'] as PSPanelKey | undefined;\n if (next && next !== this.activeSection && hasSection(this.sections, next)) {\n this.activeSection = next;\n this.cdrLocal.detectChanges();\n }\n }\n\n /** Deep agent context for the Models door: active section + trained-model lifecycle counts. */\n protected override extraAgentContext(): Record<string, unknown> {\n const models = this.engine.Models;\n return buildModelsAgentContext({\n ActiveSection: this.activeSection,\n ActiveSectionLabel: this.activeLabel,\n SectionLabels: this.sections.map((s) => s.label),\n TotalModelCount: models.length,\n PublishedModelCount: this.engine.PublishedModels.length,\n DraftModelCount: models.filter((m) => m.Status === 'Draft').length,\n ProductionModelCount: models.filter((m) => this.engine.RecordProcessIDsForModel(m.ID).length > 0).length,\n });\n }\n\n /**\n * 🔒 Read/navigate-only agent tool for the Models door: switch the active section (Model Registry ↔\n * Models in Production). NO promote/retire/delete/score tool is exposed — model lifecycle changes stay\n * behind the user's own clicks.\n */\n protected override registerAgentTools(): void {\n this.navigationService.SetAgentClientTools(this, [\n {\n Name: 'SwitchModelsSection',\n Description: 'Switch the Models door to a section. Pass the section key or label (see SectionLabels): Model Registry or Models in Production.',\n ParameterSchema: { type: 'object', properties: { section: { type: 'string', description: 'The section key or label to switch to' } } },\n Handler: async (params: Record<string, unknown>) => {\n const check = validateStringParam(params['section'], 'section');\n if (!check.ok) return check.result;\n const candidates = this.sections.map((s) => ({ ID: s.key, Name: s.label }));\n const match = resolvePSRecord(check.value, candidates);\n if (!match) return { Success: false, ErrorMessage: buildPSNotFoundError(check.value, candidates, 'section') };\n this.selectSection(match.ID as PSPanelKey);\n return { Success: true, Data: { activeSection: match.Name } };\n },\n },\n ]);\n }\n\n public get groups(): string[] { return sectionGroups(this.sections); }\n public itemsForGroup(group: string): PSSection[] { return sectionsInGroup(this.sections, group); }\n public get activeLabel(): string { return sectionLabel(this.sections, this.activeSection); }\n\n /** Section-specific subtitle for the interior header. */\n public get activeSubtitle(): string {\n const map: Record<string, string> = {\n registry: 'Versioned trained models, their metrics, and lineage.',\n production: \"What's scoring live, and its recent runs.\",\n };\n return map[this.activeSection] ?? '';\n }\n\n public selectSection(key: PSPanelKey): void {\n if (this.activeSection === key) return;\n this.activeSection = key;\n this.UpdateQueryParams({ section: key });\n this.publishAgentContext();\n this.cdrLocal.detectChanges();\n }\n}\n\n/** Tree-shaking prevention — called from the subpath module so the @RegisterClass survives bundling. */\nexport function LoadPSModelsResource(): void {\n // intentionally empty\n}\n"]}
1
+ {"version":3,"file":"ps-models-resource.component.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/resources/ps-models-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject } from '@angular/core';\nimport { RegisterClass, UUIDsEqual } from '@memberjunction/global';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { PSResourceBase } from './ps-resource-base';\nimport { PSPanelKey } from '../predictive-studio.types';\nimport { MODELS_SECTIONS, PSSection, sectionGroups, sectionsInGroup, sectionLabel, hasSection } from '../predictive-studio.nav';\nimport { buildModelsAgentContext, resolvePSRecord, buildPSNotFoundError } from '../predictive-studio-agent-context';\nimport { validateStringParam } from '../../shared/agent-tool-validation';\n\n/**\n * **Models** — the trained-model lifecycle door (one of Predictive Studio's three consolidated nav\n * items, alongside `Predictions` and `Studio`). Hosts the registry + production section panels\n * (`ps-registry`, `ps-production`) behind an internal left-nav. The active section round-trips through\n * the `section` query param, so the `Overview` panel's cross-door \"view in production\" links (and any\n * deep link) can land directly on the right section. No docked copilot here — these are read/manage\n * surfaces; model creation + the Model Dev Agent live in the `Studio` and `Predictions` doors.\n */\n@RegisterClass(BaseResourceComponent, 'PredictiveStudioModelsResource')\n@Component({\n standalone: false,\n selector: 'mj-ps-models-resource',\n template: `\n <mj-page-header-interior [Title]=\"activeLabel\" [Subtitle]=\"activeSubtitle\">\n </mj-page-header-interior>\n <mj-page-body-interior [Flex]=\"true\" [Padding]=\"false\">\n @if (isLoading) {\n <mj-loading text=\"Loading Models…\" size=\"medium\"></mj-loading>\n } @else if (loadError) {\n <div class=\"ps-load-error\" data-testid=\"ps-load-error\" role=\"alert\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <div class=\"ps-load-error-text\">\n <strong>Couldn't load {{ sectionTitle }}</strong>\n <span class=\"ps-load-error-detail\">{{ loadError }}</span>\n </div>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"retryLoad()\"><i class=\"fa-solid fa-rotate-right\"></i> Try again</button>\n </div>\n } @else {\n <div class=\"ps-models-host\" [class.nav-collapsed]=\"isNavCollapsed\" data-testid=\"ps-models-shell\">\n @if (isNavCollapsed) {\n <div class=\"ps-nav-collapsed-strip\" role=\"region\" aria-label=\"Models navigation (collapsed)\">\n <button class=\"ps-nav-rail-collapse\" type=\"button\" (click)=\"toggleNav()\" aria-label=\"Expand models navigation\" title=\"Expand navigation\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n <div class=\"ps-nav-collapsed-strip-label\"><i class=\"fa-solid fa-cubes\"></i> Models</div>\n </div>\n }\n\n <as-split direction=\"horizontal\" class=\"models-splitter\" unit=\"percent\" [gutterSize]=\"isNavCollapsed ? 0 : 6\" (dragEnd)=\"onSplitDragEnd($event.sizes)\">\n @if (!isNavCollapsed) {\n <as-split-area [size]=\"navSizePct\" [minSize]=\"10\" [maxSize]=\"30\">\n <aside class=\"ps-leftnav\">\n <div class=\"ps-leftnav-header\">\n <span class=\"ps-leftnav-title\">Lifecycle</span>\n <button class=\"ps-leftnav-collapse-btn\" type=\"button\" (click)=\"toggleNav()\" title=\"Collapse navigation\" aria-label=\"Collapse navigation\">\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n </div>\n @for (group of groups; track group) {\n @if (group) { <div class=\"ps-nav-group\">{{ group }}</div> }\n @for (item of itemsForGroup(group); track item.key) {\n <button class=\"ps-nav-item\" [class.active]=\"activeSection === item.key\"\n [attr.data-testid]=\"'ps-nav-' + item.key\" (click)=\"selectSection(item.key)\">\n <i [class]=\"item.icon\"></i> <span>{{ item.label }}</span>\n </button>\n }\n }\n </aside>\n </as-split-area>\n }\n\n <as-split-area [size]=\"isNavCollapsed ? 100 : contentSizePct\" [minSize]=\"50\">\n <section class=\"ps-content\" [class.fill]=\"activeSection === 'registry' || activeSection === 'production'\" [attr.data-testid]=\"'ps-panel-' + activeSection\">\n @switch (activeSection) {\n @case ('registry') { <ps-registry [engine]=\"engine\" [provider]=\"ProviderToUse\" [currentUser]=\"ProviderToUse.CurrentUser\" [initialModelId]=\"initialModelId\"></ps-registry> }\n @case ('production') { <ps-production [engine]=\"engine\"></ps-production> }\n }\n </section>\n </as-split-area>\n </as-split>\n </div>\n }\n </mj-page-body-interior>\n `,\n styles: [\n `\n :host { display: flex; flex-direction: column; width: 100%; height: 100%; min-height: 0; }\n .ps-models-host { display: flex; flex: 1; min-height: 0; overflow: hidden; width: 100%; height: 100%; }\n .models-splitter { flex: 1; width: 100%; height: 100%; min-height: 0; min-width: 0; background: transparent; }\n .models-splitter .as-split-gutter { background: transparent; transition: background-color 0.15s ease; position: relative; }\n .models-splitter .as-split-gutter:hover { background-color: var(--mj-brand-primary, #6366f1); }\n .models-splitter .as-split-gutter::after { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 2px; height: 24px; border-radius: 1px; background: var(--mj-border-strong, #cbd5e1); }\n .models-splitter .as-split-gutter:hover::after { background: #ffffff; }\n\n .ps-nav-collapsed-strip { width: 44px; min-width: 44px; max-width: 44px; flex: none; background: var(--mj-bg-surface); border-right: 1px solid var(--mj-border-default); display: flex; flex-direction: column; align-items: center; padding: 10px 0; gap: 14px; z-index: 2; }\n .ps-nav-rail-collapse { background: var(--mj-bg-surface-subtle); border: 1px solid var(--mj-border-default); border-radius: 6px; color: var(--mj-text-secondary); cursor: pointer; display: grid; place-items: center; width: 28px; height: 28px; padding: 0; font-size: 11px; transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease; }\n .ps-nav-rail-collapse:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); border-color: var(--mj-border-strong); }\n .ps-nav-collapsed-strip-label { writing-mode: vertical-rl; transform: rotate(180deg); font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--mj-text-muted); display: flex; align-items: center; gap: 8px; text-transform: uppercase; }\n\n .ps-leftnav { width: 100%; height: 100%; border-right: 1px solid var(--mj-border-default); background: var(--mj-bg-surface-card); overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; box-sizing: border-box; }\n .ps-leftnav-header { display: flex; align-items: center; justify-content: space-between; padding: 4px 6px 8px; border-bottom: 1px solid var(--mj-border-subtle); margin-bottom: 4px; }\n .ps-leftnav-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--mj-text-muted); }\n .ps-leftnav-collapse-btn { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 6px; border: 1px solid var(--mj-border-default); background: var(--mj-bg-surface); color: var(--mj-text-muted); cursor: pointer; transition: all 0.15s ease; padding: 0; }\n .ps-leftnav-collapse-btn:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); border-color: var(--mj-border-strong); }\n\n .ps-nav-group { font-size: var(--mj-text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--mj-text-muted); padding: 10px 8px 4px; }\n .ps-nav-item { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 8px 10px; border: none; background: transparent; border-radius: var(--mj-radius-md); cursor: pointer; color: var(--mj-text-secondary); font-size: var(--mj-text-sm); font-weight: 500; transition: background .12s, color .12s; }\n .ps-nav-item i { width: 18px; text-align: center; color: var(--mj-text-muted); }\n .ps-nav-item:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n .ps-nav-item.active { background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); color: var(--mj-brand-primary); font-weight: 600; }\n .ps-nav-item.active i { color: var(--mj-brand-primary); }\n .ps-content { width: 100%; height: 100%; flex: 1; min-width: 0; overflow-y: auto; padding: 8px 14px 24px; }\n /* Fill mode (registry): the section stops page-scrolling so the panel's inner\n columns (model list / detail) can each own their scrollbar. */\n .ps-content.fill { overflow: hidden; display: flex; flex-direction: column; padding-bottom: 14px; }\n .ps-content.fill > * { flex: 1; min-height: 0; display: flex; flex-direction: column; }\n .ps-load-error { display: flex; align-items: center; gap: 14px; max-width: 620px; margin: 32px auto; padding: 18px 20px; border: 1px solid var(--mj-status-error-border); background: var(--mj-status-error-bg); border-radius: var(--mj-radius-lg); }\n .ps-load-error > i { font-size: 24px; color: var(--mj-status-error); }\n .ps-load-error-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }\n .ps-load-error-text strong { color: var(--mj-text-primary); }\n .ps-load-error-detail { color: var(--mj-text-secondary); font-size: var(--mj-text-sm); word-break: break-word; }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class PSModelsResourceComponent extends PSResourceBase {\n protected readonly SectionKey = 'models';\n protected readonly SectionLabel = 'Models';\n protected readonly SectionIcon = 'fa-solid fa-cubes';\n\n private readonly cdrLocal = inject(ChangeDetectorRef);\n\n public activeSection: PSPanelKey = 'registry';\n public readonly sections: readonly PSSection[] = MODELS_SECTIONS;\n public initialModelId?: string;\n public isNavCollapsed = false;\n public navSizePct = 14;\n public contentSizePct = 86;\n\n override ngOnInit(): void {\n super.ngOnInit();\n const qp = this.GetQueryParams();\n const initial = qp['section'] as PSPanelKey | undefined;\n if (initial && hasSection(this.sections, initial)) this.activeSection = initial;\n if (qp['modelId']) this.initialModelId = qp['modelId'];\n this.loadLayoutPrefs();\n }\n\n public toggleNav(): void {\n this.isNavCollapsed = !this.isNavCollapsed;\n this.saveLayoutPrefs();\n this.cdrLocal.detectChanges();\n }\n\n public onSplitDragEnd(sizes: readonly (number | '*')[]): void {\n if (Array.isArray(sizes) && sizes.length === 2 && typeof sizes[0] === 'number' && typeof sizes[1] === 'number') {\n this.navSizePct = Math.round(sizes[0]);\n this.contentSizePct = Math.round(sizes[1]);\n this.saveLayoutPrefs();\n }\n }\n\n private loadLayoutPrefs(): void {\n const raw = UserInfoEngine.Instance.GetSetting('mj.predictiveStudio.models.layout');\n if (raw) {\n try {\n const parsed = JSON.parse(raw);\n if (typeof parsed.navSizePct === 'number' && parsed.navSizePct >= 10 && parsed.navSizePct <= 35) {\n this.navSizePct = parsed.navSizePct;\n this.contentSizePct = 100 - parsed.navSizePct;\n }\n if (typeof parsed.isNavCollapsed === 'boolean') {\n this.isNavCollapsed = parsed.isNavCollapsed;\n }\n } catch {}\n }\n }\n\n private saveLayoutPrefs(): void {\n const prefs = {\n navSizePct: this.navSizePct,\n contentSizePct: this.contentSizePct,\n isNavCollapsed: this.isNavCollapsed,\n };\n UserInfoEngine.Instance.SetSettingDebounced('mj.predictiveStudio.models.layout', JSON.stringify(prefs));\n }\n\n protected override async OnQueryParamsChanged(params: Record<string, string>, _source: 'popstate' | 'deeplink'): Promise<void> {\n const next = params['section'] as PSPanelKey | undefined;\n if (next && next !== this.activeSection && hasSection(this.sections, next)) {\n this.activeSection = next;\n }\n if (params['modelId']) {\n this.initialModelId = params['modelId'];\n if (this.engine && !this.engine.Models.some((m) => UUIDsEqual(m.ID, params['modelId']))) {\n await this.engine.Config(true, this.ProviderToUse.CurrentUser ?? undefined, this.ProviderToUse);\n }\n }\n this.cdrLocal.detectChanges();\n }\n\n /** Deep agent context for the Models door: active section + trained-model lifecycle counts. */\n protected override extraAgentContext(): Record<string, unknown> {\n const models = this.engine.Models;\n return buildModelsAgentContext({\n ActiveSection: this.activeSection,\n ActiveSectionLabel: this.activeLabel,\n SectionLabels: this.sections.map((s) => s.label),\n TotalModelCount: models.length,\n PublishedModelCount: this.engine.PublishedModels.length,\n DraftModelCount: models.filter((m) => m.Status === 'Draft').length,\n ProductionModelCount: models.filter((m) => this.engine.RecordProcessIDsForModel(m.ID).length > 0).length,\n });\n }\n\n /**\n * 🔒 Read/navigate-only agent tool for the Models door: switch the active section (Model Registry ↔\n * Models in Production). NO promote/retire/delete/score tool is exposed — model lifecycle changes stay\n * behind the user's own clicks.\n */\n protected override registerAgentTools(): void {\n this.navigationService.SetAgentClientTools(this, [\n {\n Name: 'SwitchModelsSection',\n Description: 'Switch the Models door to a section. Pass the section key or label (see SectionLabels): Model Registry or Models in Production.',\n ParameterSchema: { type: 'object', properties: { section: { type: 'string', description: 'The section key or label to switch to' } } },\n Handler: async (params: Record<string, unknown>) => {\n const check = validateStringParam(params['section'], 'section');\n if (!check.ok) return check.result;\n const candidates = this.sections.map((s) => ({ ID: s.key, Name: s.label }));\n const match = resolvePSRecord(check.value, candidates);\n if (!match) return { Success: false, ErrorMessage: buildPSNotFoundError(check.value, candidates, 'section') };\n this.selectSection(match.ID as PSPanelKey);\n return { Success: true, Data: { activeSection: match.Name } };\n },\n },\n ]);\n }\n\n public get groups(): string[] { return sectionGroups(this.sections); }\n public itemsForGroup(group: string): PSSection[] { return sectionsInGroup(this.sections, group); }\n public get activeLabel(): string { return sectionLabel(this.sections, this.activeSection); }\n\n /** Section-specific subtitle for the interior header. */\n public get activeSubtitle(): string {\n const map: Record<string, string> = {\n registry: 'Versioned trained models, their metrics, and lineage.',\n production: \"What's scoring live, and its recent runs.\",\n };\n return map[this.activeSection] ?? '';\n }\n\n public selectSection(key: PSPanelKey): void {\n if (this.activeSection === key) return;\n this.activeSection = key;\n this.UpdateQueryParams({ section: key });\n this.publishAgentContext();\n this.cdrLocal.detectChanges();\n }\n}\n\n/** Tree-shaking prevention — called from the subpath module so the @RegisterClass survives bundling. */\nexport function LoadPSModelsResource(): void {\n // intentionally empty\n}\n"]}
@@ -33,6 +33,12 @@ export declare class PSPredictionsResourceComponent extends PSResourceBase {
33
33
  chatConversation: MJConversationEntity | null;
34
34
  chatConversationId: string | null;
35
35
  chatIsNewConversation: boolean;
36
+ mainSizePct: number;
37
+ copilotSizePct: number;
38
+ ngOnInit(): void;
39
+ onCopilotSplitDragEnd(sizes: readonly (number | '*')[]): void;
40
+ private loadLayoutPrefs;
41
+ private saveLayoutPrefs;
36
42
  /** The ranked at-risk rows for the open prediction's latest run (empty until loaded / when no run yet). */
37
43
  atRiskRows: AtRiskRow[];
38
44
  /** Plain-language "what's driving this" drivers for the open prediction (global feature importance). */
@@ -44,6 +50,7 @@ export declare class PSPredictionsResourceComponent extends PSResourceBase {
44
50
  /** "Send to a list" in-flight guard + last-result message (P1 #4). */
45
51
  creatingList: boolean;
46
52
  listResult: string | null;
53
+ latestRunId: string | null;
47
54
  /** Capability cards for the first-run intro (what PS can do), shown when the catalog is empty. */
48
55
  readonly capabilityCards: readonly PSCapabilityCard[];
49
56
  /** The business catalog cards, most-trustworthy first, derived from the engine's published models. */
@@ -70,7 +77,8 @@ export declare class PSPredictionsResourceComponent extends PSResourceBase {
70
77
  * model's target entity, so the list reads like a call sheet instead of a column of UUIDs. Resolves the
71
78
  * top-risk rows (capped) to keep the lookup light; unresolved rows fall back to their id in the template.
72
79
  */
73
- /** Resolve a model's scored target entity (id + name) via its pipeline — the model row itself only carries PipelineID. */
80
+ get selectedTargetEntityName(): string | null;
81
+ get selectedProblemType(): string | null;
74
82
  private targetEntityForModel;
75
83
  private resolveAtRiskLabels;
76
84
  backToCatalog(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"ps-predictions-resource.component.d.ts","sourceRoot":"","sources":["../../../src/PredictiveStudio/resources/ps-predictions-resource.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ps-predictions-resource.component.d.ts","sourceRoot":"","sources":["../../../src/PredictiveStudio/resources/ps-predictions-resource.component.ts"],"names":[],"mappings":"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"}