@memberjunction/ng-dashboards 5.45.1 → 5.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PredictiveStudio/at-risk.view-models.d.ts +33 -0
- package/dist/PredictiveStudio/at-risk.view-models.d.ts.map +1 -1
- package/dist/PredictiveStudio/at-risk.view-models.js +69 -2
- package/dist/PredictiveStudio/at-risk.view-models.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-catalog.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-catalog.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-compare.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-compare.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-experiments.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-home.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-home.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-operate-dialog.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-operate-dialog.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.js +306 -297
- package/dist/PredictiveStudio/components/ps-pipelines.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-production.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-production.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-registry.component.d.ts +1 -1
- package/dist/PredictiveStudio/components/ps-registry.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-registry.component.js +15 -9
- package/dist/PredictiveStudio/components/ps-registry.component.js.map +1 -1
- package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts +115 -0
- package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts.map +1 -0
- package/dist/PredictiveStudio/predictive-studio-agent-context.js +119 -0
- package/dist/PredictiveStudio/predictive-studio-agent-context.js.map +1 -0
- package/dist/PredictiveStudio/predictive-studio-copilot.view-models.d.ts +36 -0
- package/dist/PredictiveStudio/predictive-studio-copilot.view-models.d.ts.map +1 -0
- package/dist/PredictiveStudio/predictive-studio-copilot.view-models.js +52 -0
- package/dist/PredictiveStudio/predictive-studio-copilot.view-models.js.map +1 -0
- package/dist/PredictiveStudio/resources/ps-models-resource.component.d.ts +9 -1
- package/dist/PredictiveStudio/resources/ps-models-resource.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-models-resource.component.js +133 -56
- package/dist/PredictiveStudio/resources/ps-models-resource.component.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts +50 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +591 -165
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-resource-base.d.ts +17 -0
- package/dist/PredictiveStudio/resources/ps-resource-base.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-resource-base.js +27 -1
- package/dist/PredictiveStudio/resources/ps-resource-base.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.d.ts +11 -1
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.js +199 -99
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.js.map +1 -1
- package/package.json +59 -59
|
@@ -664,7 +664,7 @@ export class PSProductionComponent extends BaseAngularComponent {
|
|
|
664
664
|
} if (rf & 2) {
|
|
665
665
|
i0.ɵɵadvance();
|
|
666
666
|
i0.ɵɵconditional(ctx.models.length === 0 ? 1 : 2);
|
|
667
|
-
} }, dependencies: [CommonModule, SharedGenericModule, i1.LoadingComponent, MJButtonDirective, PSOperateDialogComponent, i2.DatePipe], styles: ["/* ============================================================================\n Predictive Studio \u2014 shared panel styles (design-token compliant)\n Maps the mockup design system onto MemberJunction semantic --mj-* tokens.\n Loaded by every PS panel component (styleUrls) under ViewEncapsulation.None,\n so the class names are global within the PS dashboard subtree.\n No hardcoded colors except the intentional categorical node/algorithm palette\n (declared once as --ps-* custom props below) which must stay distinct across\n light/dark to remain readable as diagram accents.\n ============================================================================ */\n\n/* Categorical accents for DAG node types + algorithm chips. These are\n data-visualization colors that must remain distinct regardless of theme\n (allowed exception #3 in the design-token rules). */\n.ps-panel {\n --ps-node-source: #6b7280;\n --ps-node-feature: #2050c8;\n --ps-node-embedding: #7b3ff0;\n --ps-node-target: #1f9d57;\n --ps-node-algorithm: #d98213;\n /* budget-gauge categorical accents (reuse the node palette so light/dark stay distinct) */\n --ps-gauge-cost: var(--ps-node-algorithm);\n --ps-gauge-iterations: var(--ps-node-feature);\n}\n\n.ps-panel {\n display: block;\n height: 100%;\n}\n\n/* ---- generic layout helpers ---- */\n.ps-row { display: flex; gap: 16px; }\n.ps-col { display: flex; flex-direction: column; gap: 16px; }\n.ps-wrap { flex-wrap: wrap; }\n.ps-spacer { flex: 1; }\n.ps-muted { color: var(--mj-text-muted); }\n.ps-small { font-size: 12.5px; }\n.ps-mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-section-title {\n font-size: 12px; text-transform: uppercase; letter-spacing: .06em;\n color: var(--mj-text-muted); margin: 4px 0 2px; font-weight: 700;\n}\n\n/* ---- cards ---- */\n.ps-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n}\n.ps-card-head {\n display: flex; align-items: center; gap: 10px;\n padding: 14px 16px; border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-card-head h3 { font-size: 14.5px; margin: 0; font-weight: 650; color: var(--mj-text-primary); }\n.ps-card-body { padding: 16px; }\n\n/* ---- KPI tiles ---- */\n.ps-kpi {\n background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default);\n border-radius: 10px; padding: 16px 18px; box-shadow: var(--mj-shadow-sm);\n}\n.ps-kpi .label { font-size: 12px; color: var(--mj-text-muted); font-weight: 600; }\n.ps-kpi .val { font-size: 26px; font-weight: 720; letter-spacing: -.02em; margin-top: 2px; color: var(--mj-text-primary); }\n\n/* ---- badges ---- */\n.ps-badge {\n display: inline-flex; align-items: center; gap: 5px;\n padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 650; line-height: 1.7;\n}\n.ps-badge.gray { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.ps-badge.blue { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); }\n.ps-badge.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-badge.amber { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-badge.red { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }\n\n/* recommendation-level chips (the ranking matrix payoff) */\n.ps-lvl {\n display: inline-flex; align-items: center; justify-content: center;\n min-width: 92px; padding: 4px 10px; border-radius: 7px;\n font-weight: 650; font-size: 11.5px; color: var(--mj-text-inverse);\n}\n.ps-lvl-Primary { background: var(--mj-status-success); }\n.ps-lvl-Strong { background: var(--mj-status-info); }\n.ps-lvl-Viable { background: var(--mj-status-warning); }\n.ps-lvl-Weak { background: var(--mj-text-disabled); }\n.ps-lvl-NotRecommended { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n/* ---- tags ---- */\n.ps-tag {\n display: inline-block; padding: 2px 8px; border-radius: 6px;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n font-size: 11.5px; font-weight: 600;\n}\n.ps-tag.muted { opacity: .6; }\n.ps-divider { height: 1px; background: var(--mj-border-subtle); margin: 8px 0; }\n\n/* ---- tables ---- */\n.ps-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.ps-table th {\n text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; padding: 9px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n.ps-table td { padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-primary); }\n.ps-table tr:hover td { background: var(--mj-bg-surface-hover); }\n.ps-table .num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.ps-rank {\n width: 22px; height: 22px; border-radius: 6px; background: var(--mj-bg-surface-sunken);\n display: inline-grid; place-items: center; font-weight: 700; font-size: 11.5px; color: var(--mj-text-secondary);\n}\n.ps-rank.gold { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n\n/* ---- progress bars ---- */\n.ps-bar { height: 8px; border-radius: 999px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-bar > span { display: block; height: 100%; border-radius: 999px; background: var(--mj-brand-primary); }\n.ps-bar.warn > span { background: var(--mj-status-warning); }\n.ps-bar.run > span { background: var(--mj-brand-primary); }\n\n.ps-fbar { display: grid; grid-template-columns: 150px 1fr 48px; align-items: center; gap: 10px; padding: 5px 0; }\n.ps-fbar .track { height: 14px; border-radius: 5px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-secondary); }\n\n/* gauge */\n.ps-gauge {\n position: relative; width: 64px; height: 64px; border-radius: 50%; flex: 0 0 auto;\n background: conic-gradient(var(--ps-gauge-color, var(--mj-brand-primary)) calc(var(--ps-p, 40) * 1%), var(--mj-bg-surface-sunken) 0);\n display: grid; place-items: center;\n}\n.ps-gauge::after { content: ''; position: absolute; inset: 9px; background: var(--mj-bg-surface); border-radius: 50%; }\n.ps-gauge .g-val { position: relative; font-weight: 720; font-size: 14px; color: var(--mj-text-primary); }\n\n/* warning / info callouts */\n.ps-callout { display: flex; gap: 11px; padding: 12px 14px; border-radius: 10px; border: 1px solid; }\n.ps-callout.warn { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); color: var(--mj-status-warning-text); }\n.ps-callout.info { background: var(--mj-status-info-bg); border-color: var(--mj-status-info-border); color: var(--mj-status-info-text); }\n.ps-callout.success { background: var(--mj-status-success-bg); border-color: var(--mj-status-success-border); color: var(--mj-status-success-text); }\n.ps-callout i { font-size: 16px; margin-top: 1px; }\n\n/* lifecycle stepper */\n.ps-stepper { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }\n.ps-step { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--mj-text-muted); }\n.ps-step .pip {\n width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--mj-border-strong);\n display: grid; place-items: center; font-size: 11px;\n}\n.ps-step.done { color: var(--mj-status-success-text); }\n.ps-step.done .pip { background: var(--mj-status-success); border-color: var(--mj-status-success); color: var(--mj-text-inverse); }\n.ps-step.curr { color: var(--mj-brand-primary); }\n.ps-step.curr .pip { border-color: var(--mj-brand-primary); color: var(--mj-brand-primary); }\n.ps-step .ln { width: 26px; height: 2px; background: var(--mj-border-strong); }\n\n/* ---- DAG flow canvas ---- */\n.ps-flow {\n position: relative;\n background:\n linear-gradient(var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n linear-gradient(90deg, var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default); border-radius: 10px;\n min-height: 620px; overflow: hidden;\n}\n.ps-node {\n position: absolute; width: 190px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong); border-left-width: 3px; border-radius: 10px;\n box-shadow: var(--mj-shadow-sm); cursor: pointer;\n}\n.ps-node .nh {\n display: flex; align-items: center; gap: 8px; padding: 9px 11px;\n border-bottom: 1px solid var(--mj-border-subtle); font-weight: 650; font-size: 12.5px; color: var(--mj-text-primary);\n}\n.ps-node .nh i.tile {\n width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-node .nh .ps-tag { margin-left: auto; }\n.ps-node .nb { padding: 9px 11px; font-size: 12px; color: var(--mj-text-secondary); }\n.ps-node .nb-row { display: flex; justify-content: space-between; gap: 8px; padding: 2px 0; }\n.ps-node .nb-row .k { color: var(--mj-text-muted); }\n.ps-node.src { border-left-color: var(--ps-node-source); }\n.ps-node.src .nh i.tile { background: var(--ps-node-source); }\n.ps-node.feat { border-left-color: var(--ps-node-feature); }\n.ps-node.feat .nh i.tile { background: var(--ps-node-feature); }\n.ps-node.emb { border-left-color: var(--ps-node-embedding); }\n.ps-node.emb .nh i.tile { background: var(--ps-node-embedding); }\n.ps-node.target { border-left-color: var(--ps-node-target); }\n.ps-node.target .nh i.tile { background: var(--ps-node-target); }\n.ps-node.algo { border-left-color: var(--ps-node-algorithm); }\n.ps-node.algo .nh i.tile { background: var(--ps-node-algorithm); }\n.ps-node.output { border-left-color: var(--mj-status-success); }\n.ps-node.output .nh i.tile { background: var(--mj-status-success); }\n.ps-node.selected {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n.ps-node .port {\n position: absolute; width: 11px; height: 11px; border-radius: 50%;\n background: var(--mj-bg-surface); border: 2px solid var(--mj-brand-primary);\n top: 50%; transform: translateY(-50%);\n}\n.ps-node .port.in { left: -6px; }\n.ps-node .port.out { right: -6px; }\nsvg.ps-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }\nsvg.ps-edges path { stroke: color-mix(in srgb, var(--mj-brand-primary) 45%, transparent); stroke-width: 2; fill: none; }\n\n/* palette chips */\n.ps-pchip {\n display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border-radius: 8px;\n border: 1px dashed var(--mj-border-strong); background: var(--mj-bg-surface);\n font-size: 12.5px; font-weight: 600; color: var(--mj-text-secondary); cursor: grab;\n}\n.ps-pchip i { font-size: 12px; color: var(--mj-text-inverse); width: 20px; height: 20px; border-radius: 5px; display: grid; place-items: center; }\n.ps-pchip.s i { background: var(--ps-node-source); }\n.ps-pchip.f i { background: var(--ps-node-feature); }\n.ps-pchip.e i { background: var(--ps-node-embedding); }\n.ps-pchip.t i { background: var(--ps-node-target); }\n.ps-pchip.a i { background: var(--ps-node-algorithm); }\n\n/* segmented control */\n.ps-seg { display: inline-flex; border: 1px solid var(--mj-border-default); border-radius: 8px; overflow: hidden; }\n.ps-seg button {\n border: none; background: var(--mj-bg-surface); color: var(--mj-text-secondary);\n padding: 6px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;\n border-right: 1px solid var(--mj-border-default);\n}\n.ps-seg button:last-child { border-right: none; }\n.ps-seg button.on { background: var(--mj-brand-primary); color: var(--mj-text-inverse); }\n\n/* field control */\n.ps-field { margin-bottom: 14px; }\n.ps-field > label {\n display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; margin-bottom: 6px;\n}\n.ps-input {\n width: 100%; padding: 8px 10px; border: 1px solid var(--mj-border-default);\n border-radius: 6px; font-size: 13px; background: var(--mj-bg-surface); color: var(--mj-text-primary);\n box-sizing: border-box;\n}\n.ps-input:focus { outline: none; border-color: var(--mj-brand-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); }\n\n/* loading container */\n.ps-loading { display: flex; align-items: center; justify-content: center; padding: 60px 0; }\n\n/* ---- empty / prompt states ---- */\n.ps-empty {\n display: flex; flex-direction: column; align-items: center; justify-content: center;\n text-align: center; gap: 10px; padding: 56px 24px; color: var(--mj-text-muted);\n}\n.ps-empty .ps-empty-ico {\n width: 60px; height: 60px; border-radius: 16px; display: grid; place-items: center;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-disabled); font-size: 24px;\n}\n.ps-empty h3 { margin: 4px 0 0; font-size: 16px; font-weight: 650; color: var(--mj-text-secondary); }\n.ps-empty p { margin: 0; max-width: 420px; font-size: 13px; line-height: 1.5; }\n\n/* ---- confirm modal ---- */\n.ps-modal-backdrop {\n position: fixed; inset: 0; z-index: 1000;\n background: var(--mj-bg-overlay);\n display: flex; align-items: center; justify-content: center; padding: 24px;\n}\n.ps-modal {\n width: 100%; max-width: 480px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default); border-radius: 14px;\n box-shadow: var(--mj-shadow-lg, var(--mj-shadow-sm)); overflow: hidden;\n}\n.ps-modal-head {\n display: flex; align-items: center; gap: 12px; padding: 18px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-modal-head .ico {\n width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center;\n font-size: 16px; flex: 0 0 auto;\n background: var(--mj-status-info-bg); color: var(--mj-status-info-text);\n}\n.ps-modal-head.warn .ico { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-modal-head.danger .ico { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-modal-head h3 { margin: 0; font-size: 15.5px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-modal-body { padding: 18px 20px; font-size: 13.5px; line-height: 1.55; color: var(--mj-text-secondary); }\n.ps-modal-body .ps-field { margin-top: 14px; margin-bottom: 0; }\n.ps-modal-foot {\n display: flex; align-items: center; gap: 10px; padding: 14px 20px;\n border-top: 1px solid var(--mj-border-subtle); background: var(--mj-bg-surface-card);\n}\n.ps-modal-foot .ps-spacer { flex: 1; }\n", "/* Models in Production \u2014 model-centric control tower (master/detail). All colors via --mj-* tokens. */\n\n.ps-production {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 4px;\n}\n\n.prod-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 14px;\n}\n\n.prod-layout {\n display: grid;\n grid-template-columns: minmax(280px, 340px) minmax(0, 1fr);\n gap: 16px;\n align-items: start;\n}\n@media (max-width: 900px) {\n .prod-layout { grid-template-columns: 1fr; }\n}\n\n/* master list */\n.prod-layout .mlist .mrow {\n display: flex;\n align-items: center;\n gap: 11px;\n padding: 10px 10px;\n border-radius: 9px;\n cursor: pointer;\n}\n.prod-layout .mlist .mrow:hover { background: var(--mj-bg-surface-hover); }\n.prod-layout .mlist .mrow.sel { background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface)); }\n.prod-layout .mlist .mrow .ico {\n width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 13px; flex: 0 0 auto;\n}\n.prod-layout .mlist .mrow .nm { font-weight: 640; font-size: 14px; color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.prod-layout .mlist .mrow .ln2 { margin-top: 2px; }\n.prod-layout .mlist .mrow .meta { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; flex: 0 0 auto; }\n\n/* deploy-state icon colors (master + detail) */\n.st-bound { background: var(--mj-status-success); }\n.st-scheduled { background: var(--mj-status-info); }\n.st-idle { background: var(--mj-text-disabled); }\n\n/* detail */\n.prod-layout .detail { display: flex; flex-direction: column; gap: 14px; }\n.prod-layout .detail .dh { display: flex; align-items: center; gap: 13px; }\n.prod-layout .detail .dh h2 { margin: 0; font-size: 17px; font-weight: 680; color: var(--mj-text-primary); }\n.prod-layout .detail .dh .sub { margin-top: 3px; }\n.prod-layout .detail .big-ico {\n width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 16px; flex: 0 0 auto;\n}\n\n/* binding rows */\n.bind-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.bind-row:last-child { border-bottom: none; }\n\n/* run history table */\n.runs-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.runs-table th {\n text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; padding: 6px 8px; border-bottom: 1px solid var(--mj-border-default);\n}\n.runs-table td { padding: 7px 8px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-secondary); }\n.runs-table tr:last-child td { border-bottom: none; }\n.runs-table tr.run-row { cursor: pointer; }\n.runs-table tr.run-row:hover td { background: var(--mj-bg-surface-hover); }\n.runs-table .run-right { text-align: right; white-space: nowrap; }\n.runs-table .run-right i { margin-left: 8px; opacity: .5; }\n\n.run-back {\n display: inline-flex; align-items: center; gap: 6px; cursor: pointer;\n background: none; border: none; color: var(--mj-text-link); font-size: 13px; padding: 0 0 10px;\n}\n\n/* empty state CTA spacing (shared .ps-empty) */\n.ps-production .ps-empty p { max-width: 520px; }\n"], encapsulation: 2 });
|
|
667
|
+
} }, dependencies: [CommonModule, SharedGenericModule, i1.LoadingComponent, MJButtonDirective, PSOperateDialogComponent, i2.DatePipe], styles: ["/* ============================================================================\n Predictive Studio \u2014 shared panel styles (design-token compliant)\n Maps the mockup design system onto MemberJunction semantic --mj-* tokens.\n Loaded by every PS panel component (styleUrls) under ViewEncapsulation.None,\n so the class names are global within the PS dashboard subtree.\n No hardcoded colors except the intentional categorical node/algorithm palette\n (declared once as --ps-* custom props below) which must stay distinct across\n light/dark to remain readable as diagram accents.\n ============================================================================ */\n\n/* Categorical accents for DAG node types + algorithm chips. These are\n data-visualization colors that must remain distinct regardless of theme\n (allowed exception #3 in the design-token rules). */\n.ps-panel {\n --ps-node-source: #6b7280;\n --ps-node-feature: #2050c8;\n --ps-node-embedding: #7b3ff0;\n --ps-node-target: #1f9d57;\n --ps-node-algorithm: #d98213;\n /* budget-gauge categorical accents (reuse the node palette so light/dark stay distinct) */\n --ps-gauge-cost: var(--ps-node-algorithm);\n --ps-gauge-iterations: var(--ps-node-feature);\n}\n\n.ps-panel {\n display: block;\n height: 100%;\n}\n\n/* ---- generic layout helpers ---- */\n.ps-row { display: flex; gap: 16px; }\n.ps-col { display: flex; flex-direction: column; gap: 16px; }\n.ps-wrap { flex-wrap: wrap; }\n.ps-spacer { flex: 1; }\n.ps-muted { color: var(--mj-text-muted); }\n.ps-small { font-size: 12.5px; }\n.ps-mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-section-title {\n font-size: 12px; text-transform: uppercase; letter-spacing: .06em;\n color: var(--mj-text-muted); margin: 4px 0 2px; font-weight: 700;\n}\n\n/* ---- cards ---- */\n.ps-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n.ps-card-head {\n display: flex; align-items: center; gap: 10px;\n padding: 14px 16px; border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-card-head h3 { font-size: 14.5px; margin: 0; font-weight: 650; color: var(--mj-text-primary); }\n.ps-card-body { padding: 16px; }\n\n/* ---- KPI tiles ---- */\n.ps-kpi {\n background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default);\n border-radius: 8px; padding: 16px 18px;\n}\n.ps-kpi .label { font-size: 12px; color: var(--mj-text-muted); font-weight: 600; }\n.ps-kpi .val { font-size: 26px; font-weight: 720; letter-spacing: -.02em; margin-top: 2px; color: var(--mj-text-primary); }\n\n/* ---- badges ---- */\n.ps-badge {\n display: inline-flex; align-items: center; gap: 5px;\n padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 650; line-height: 1.7;\n}\n.ps-badge.gray { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.ps-badge.blue { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); }\n.ps-badge.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-badge.amber { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-badge.red { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }\n\n/* recommendation-level chips (the ranking matrix payoff) */\n.ps-lvl {\n display: inline-flex; align-items: center; justify-content: center;\n min-width: 92px; padding: 4px 10px; border-radius: 7px;\n font-weight: 650; font-size: 11.5px; color: var(--mj-text-inverse);\n}\n.ps-lvl-Primary { background: var(--mj-status-success); }\n.ps-lvl-Strong { background: var(--mj-status-info); }\n.ps-lvl-Viable { background: var(--mj-status-warning); }\n.ps-lvl-Weak { background: var(--mj-text-disabled); }\n.ps-lvl-NotRecommended { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n/* ---- tags ---- */\n.ps-tag {\n display: inline-block; padding: 2px 8px; border-radius: 6px;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n font-size: 11.5px; font-weight: 600;\n}\n.ps-tag.muted { opacity: .6; }\n.ps-divider { height: 1px; background: var(--mj-border-subtle); margin: 8px 0; }\n\n/* ---- tables ---- */\n.ps-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.ps-table th {\n text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; padding: 9px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n.ps-table td { padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-primary); }\n.ps-table tr:hover td { background: var(--mj-bg-surface-hover); }\n.ps-table .num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.ps-rank {\n width: 22px; height: 22px; border-radius: 6px; background: var(--mj-bg-surface-sunken);\n display: inline-grid; place-items: center; font-weight: 700; font-size: 11.5px; color: var(--mj-text-secondary);\n}\n.ps-rank.gold { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n\n/* ---- progress bars ---- */\n.ps-bar { height: 8px; border-radius: 999px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-bar > span { display: block; height: 100%; border-radius: 999px; background: var(--mj-brand-primary); }\n.ps-bar.warn > span { background: var(--mj-status-warning); }\n.ps-bar.run > span { background: var(--mj-brand-primary); }\n\n.ps-fbar { display: grid; grid-template-columns: minmax(150px, 1.3fr) 2fr 56px; align-items: center; gap: 14px; padding: 8px 0; }\n.ps-fbar + .ps-fbar { border-top: 1px solid var(--mj-border-subtle); }\n.ps-fbar .track { height: 10px; border-radius: var(--mj-radius-full); background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; border-radius: var(--mj-radius-full); background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ps-fbar > .ps-mono { text-align: right; color: var(--mj-text-secondary); font-variant-numeric: tabular-nums; }\n\n/* gauge */\n.ps-gauge {\n position: relative; width: 64px; height: 64px; border-radius: 50%; flex: 0 0 auto;\n background: conic-gradient(var(--ps-gauge-color, var(--mj-brand-primary)) calc(var(--ps-p, 40) * 1%), var(--mj-bg-surface-sunken) 0);\n display: grid; place-items: center;\n}\n.ps-gauge::after { content: ''; position: absolute; inset: 9px; background: var(--mj-bg-surface); border-radius: 50%; }\n.ps-gauge .g-val { position: relative; font-weight: 720; font-size: 14px; color: var(--mj-text-primary); }\n\n/* warning / info callouts */\n.ps-callout { display: flex; gap: 11px; padding: 12px 14px; border-radius: 10px; border: 1px solid; }\n.ps-callout.warn { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); color: var(--mj-status-warning-text); }\n.ps-callout.info { background: var(--mj-status-info-bg); border-color: var(--mj-status-info-border); color: var(--mj-status-info-text); }\n.ps-callout.success { background: var(--mj-status-success-bg); border-color: var(--mj-status-success-border); color: var(--mj-status-success-text); }\n.ps-callout i { font-size: 16px; margin-top: 1px; }\n\n/* lifecycle stepper */\n.ps-stepper { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }\n.ps-step { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--mj-text-muted); }\n.ps-step .pip {\n width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--mj-border-strong);\n display: grid; place-items: center; font-size: 11px;\n}\n.ps-step.done { color: var(--mj-status-success-text); }\n.ps-step.done .pip { background: var(--mj-status-success); border-color: var(--mj-status-success); color: var(--mj-text-inverse); }\n.ps-step.curr { color: var(--mj-brand-primary); }\n.ps-step.curr .pip { border-color: var(--mj-brand-primary); color: var(--mj-brand-primary); }\n.ps-step .ln { width: 26px; height: 2px; background: var(--mj-border-strong); }\n\n/* ---- DAG flow canvas ---- */\n.ps-flow {\n position: relative;\n background:\n linear-gradient(var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n linear-gradient(90deg, var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default); border-radius: 10px;\n min-height: 620px; overflow: hidden;\n}\n.ps-node {\n position: absolute; width: 190px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong); border-left-width: 3px; border-radius: 8px;\n cursor: pointer;\n}\n.ps-node .nh {\n display: flex; align-items: center; gap: 8px; padding: 9px 11px;\n border-bottom: 1px solid var(--mj-border-subtle); font-weight: 650; font-size: 12.5px; color: var(--mj-text-primary);\n}\n.ps-node .nh i.tile {\n width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-node .nh .ps-tag { margin-left: auto; }\n.ps-node .nb { padding: 9px 11px; font-size: 12px; color: var(--mj-text-secondary); }\n.ps-node .nb-row { display: flex; justify-content: space-between; gap: 8px; padding: 2px 0; }\n.ps-node .nb-row .k { color: var(--mj-text-muted); }\n.ps-node.src { border-left-color: var(--ps-node-source); }\n.ps-node.src .nh i.tile { background: var(--ps-node-source); }\n.ps-node.feat { border-left-color: var(--ps-node-feature); }\n.ps-node.feat .nh i.tile { background: var(--ps-node-feature); }\n.ps-node.emb { border-left-color: var(--ps-node-embedding); }\n.ps-node.emb .nh i.tile { background: var(--ps-node-embedding); }\n.ps-node.target { border-left-color: var(--ps-node-target); }\n.ps-node.target .nh i.tile { background: var(--ps-node-target); }\n.ps-node.algo { border-left-color: var(--ps-node-algorithm); }\n.ps-node.algo .nh i.tile { background: var(--ps-node-algorithm); }\n.ps-node.output { border-left-color: var(--mj-status-success); }\n.ps-node.output .nh i.tile { background: var(--mj-status-success); }\n.ps-node.selected {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n.ps-node .port {\n position: absolute; width: 11px; height: 11px; border-radius: 50%;\n background: var(--mj-bg-surface); border: 2px solid var(--mj-brand-primary);\n top: 50%; transform: translateY(-50%);\n}\n.ps-node .port.in { left: -6px; }\n.ps-node .port.out { right: -6px; }\nsvg.ps-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }\nsvg.ps-edges path { stroke: color-mix(in srgb, var(--mj-brand-primary) 45%, transparent); stroke-width: 2; fill: none; }\n\n/* palette chips */\n.ps-pchip {\n display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border-radius: 8px;\n border: 1px dashed var(--mj-border-strong); background: var(--mj-bg-surface);\n font-size: 12.5px; font-weight: 600; color: var(--mj-text-secondary); cursor: grab;\n}\n.ps-pchip i { font-size: 12px; color: var(--mj-text-inverse); width: 20px; height: 20px; border-radius: 5px; display: grid; place-items: center; }\n.ps-pchip.s i { background: var(--ps-node-source); }\n.ps-pchip.f i { background: var(--ps-node-feature); }\n.ps-pchip.e i { background: var(--ps-node-embedding); }\n.ps-pchip.t i { background: var(--ps-node-target); }\n.ps-pchip.a i { background: var(--ps-node-algorithm); }\n\n/* segmented control */\n.ps-seg { display: inline-flex; border: 1px solid var(--mj-border-default); border-radius: 8px; overflow: hidden; }\n.ps-seg button {\n border: none; background: var(--mj-bg-surface); color: var(--mj-text-secondary);\n padding: 6px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;\n border-right: 1px solid var(--mj-border-default);\n}\n.ps-seg button:last-child { border-right: none; }\n.ps-seg button.on { background: var(--mj-brand-primary); color: var(--mj-text-inverse); }\n\n/* field control */\n.ps-field { margin-bottom: 14px; }\n.ps-field > label {\n display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; margin-bottom: 6px;\n}\n.ps-input {\n width: 100%; padding: 8px 10px; border: 1px solid var(--mj-border-default);\n border-radius: 6px; font-size: 13px; background: var(--mj-bg-surface); color: var(--mj-text-primary);\n box-sizing: border-box;\n}\n.ps-input:focus { outline: none; border-color: var(--mj-brand-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); }\n\n/* loading container */\n.ps-loading { display: flex; align-items: center; justify-content: center; padding: 60px 0; }\n\n/* ---- empty / prompt states ---- */\n.ps-empty {\n display: flex; flex-direction: column; align-items: center; justify-content: center;\n text-align: center; gap: 10px; padding: 56px 24px; color: var(--mj-text-muted);\n}\n.ps-empty .ps-empty-ico {\n width: 60px; height: 60px; border-radius: 16px; display: grid; place-items: center;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-disabled); font-size: 24px;\n}\n.ps-empty h3 { margin: 4px 0 0; font-size: 16px; font-weight: 650; color: var(--mj-text-secondary); }\n.ps-empty p { margin: 0; max-width: 420px; font-size: 13px; line-height: 1.5; }\n\n/* ---- confirm modal ---- */\n.ps-modal-backdrop {\n position: fixed; inset: 0; z-index: 1000;\n background: var(--mj-bg-overlay);\n display: flex; align-items: center; justify-content: center; padding: 24px;\n}\n.ps-modal {\n width: 100%; max-width: 480px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default); border-radius: 14px;\n box-shadow: var(--mj-shadow-lg, var(--mj-shadow-sm)); overflow: hidden;\n}\n.ps-modal-head {\n display: flex; align-items: center; gap: 12px; padding: 18px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-modal-head .ico {\n width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center;\n font-size: 16px; flex: 0 0 auto;\n background: var(--mj-status-info-bg); color: var(--mj-status-info-text);\n}\n.ps-modal-head.warn .ico { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-modal-head.danger .ico { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-modal-head h3 { margin: 0; font-size: 15.5px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-modal-body { padding: 18px 20px; font-size: 13.5px; line-height: 1.55; color: var(--mj-text-secondary); }\n.ps-modal-body .ps-field { margin-top: 14px; margin-bottom: 0; }\n.ps-modal-foot {\n display: flex; align-items: center; gap: 10px; padding: 14px 20px;\n border-top: 1px solid var(--mj-border-subtle); background: var(--mj-bg-surface-card);\n}\n.ps-modal-foot .ps-spacer { flex: 1; }\n", "/* Models in Production \u2014 model-centric control tower (master/detail). All colors via --mj-* tokens. */\n\n.ps-production {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 4px;\n}\n\n.prod-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 14px;\n}\n\n.prod-layout {\n display: grid;\n grid-template-columns: minmax(280px, 340px) minmax(0, 1fr);\n gap: 16px;\n align-items: start;\n}\n@media (max-width: 900px) {\n .prod-layout { grid-template-columns: 1fr; }\n}\n\n/* master list */\n.prod-layout .mlist .mrow {\n display: flex;\n align-items: center;\n gap: 11px;\n padding: 10px 10px;\n border-radius: 9px;\n cursor: pointer;\n}\n.prod-layout .mlist .mrow:hover { background: var(--mj-bg-surface-hover); }\n.prod-layout .mlist .mrow.sel { background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface)); }\n.prod-layout .mlist .mrow .ico {\n width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 13px; flex: 0 0 auto;\n}\n.prod-layout .mlist .mrow .nm { font-weight: 640; font-size: 14px; color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.prod-layout .mlist .mrow .ln2 { margin-top: 2px; }\n.prod-layout .mlist .mrow .meta { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; flex: 0 0 auto; }\n\n/* deploy-state icon colors (master + detail) */\n.st-bound { background: var(--mj-status-success); }\n.st-scheduled { background: var(--mj-status-info); }\n.st-idle { background: var(--mj-text-disabled); }\n\n/* detail */\n.prod-layout .detail { display: flex; flex-direction: column; gap: 14px; }\n.prod-layout .detail .dh { display: flex; align-items: center; gap: 13px; }\n.prod-layout .detail .dh h2 { margin: 0; font-size: 17px; font-weight: 680; color: var(--mj-text-primary); }\n.prod-layout .detail .dh .sub { margin-top: 3px; }\n.prod-layout .detail .big-ico {\n width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 16px; flex: 0 0 auto;\n}\n\n/* binding rows */\n.bind-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.bind-row:last-child { border-bottom: none; }\n\n/* run history table */\n.runs-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.runs-table th {\n text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; padding: 6px 8px; border-bottom: 1px solid var(--mj-border-default);\n}\n.runs-table td { padding: 7px 8px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-secondary); }\n.runs-table tr:last-child td { border-bottom: none; }\n.runs-table tr.run-row { cursor: pointer; }\n.runs-table tr.run-row:hover td { background: var(--mj-bg-surface-hover); }\n.runs-table .run-right { text-align: right; white-space: nowrap; }\n.runs-table .run-right i { margin-left: 8px; opacity: .5; }\n\n.run-back {\n display: inline-flex; align-items: center; gap: 6px; cursor: pointer;\n background: none; border: none; color: var(--mj-text-link); font-size: 13px; padding: 0 0 10px;\n}\n\n/* empty state CTA spacing (shared .ps-empty) */\n.ps-production .ps-empty p { max-width: 520px; }\n"], encapsulation: 2 });
|
|
668
668
|
}
|
|
669
669
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PSProductionComponent, [{
|
|
670
670
|
type: Component,
|
|
@@ -824,7 +824,7 @@ export class PSProductionComponent extends BaseAngularComponent {
|
|
|
824
824
|
</ps-operate-dialog>
|
|
825
825
|
}
|
|
826
826
|
</div>
|
|
827
|
-
`, styles: ["/* ============================================================================\n Predictive Studio \u2014 shared panel styles (design-token compliant)\n Maps the mockup design system onto MemberJunction semantic --mj-* tokens.\n Loaded by every PS panel component (styleUrls) under ViewEncapsulation.None,\n so the class names are global within the PS dashboard subtree.\n No hardcoded colors except the intentional categorical node/algorithm palette\n (declared once as --ps-* custom props below) which must stay distinct across\n light/dark to remain readable as diagram accents.\n ============================================================================ */\n\n/* Categorical accents for DAG node types + algorithm chips. These are\n data-visualization colors that must remain distinct regardless of theme\n (allowed exception #3 in the design-token rules). */\n.ps-panel {\n --ps-node-source: #6b7280;\n --ps-node-feature: #2050c8;\n --ps-node-embedding: #7b3ff0;\n --ps-node-target: #1f9d57;\n --ps-node-algorithm: #d98213;\n /* budget-gauge categorical accents (reuse the node palette so light/dark stay distinct) */\n --ps-gauge-cost: var(--ps-node-algorithm);\n --ps-gauge-iterations: var(--ps-node-feature);\n}\n\n.ps-panel {\n display: block;\n height: 100%;\n}\n\n/* ---- generic layout helpers ---- */\n.ps-row { display: flex; gap: 16px; }\n.ps-col { display: flex; flex-direction: column; gap: 16px; }\n.ps-wrap { flex-wrap: wrap; }\n.ps-spacer { flex: 1; }\n.ps-muted { color: var(--mj-text-muted); }\n.ps-small { font-size: 12.5px; }\n.ps-mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-section-title {\n font-size: 12px; text-transform: uppercase; letter-spacing: .06em;\n color: var(--mj-text-muted); margin: 4px 0 2px; font-weight: 700;\n}\n\n/* ---- cards ---- */\n.ps-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n}\n.ps-card-head {\n display: flex; align-items: center; gap: 10px;\n padding: 14px 16px; border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-card-head h3 { font-size: 14.5px; margin: 0; font-weight: 650; color: var(--mj-text-primary); }\n.ps-card-body { padding: 16px; }\n\n/* ---- KPI tiles ---- */\n.ps-kpi {\n background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default);\n border-radius: 10px; padding: 16px 18px; box-shadow: var(--mj-shadow-sm);\n}\n.ps-kpi .label { font-size: 12px; color: var(--mj-text-muted); font-weight: 600; }\n.ps-kpi .val { font-size: 26px; font-weight: 720; letter-spacing: -.02em; margin-top: 2px; color: var(--mj-text-primary); }\n\n/* ---- badges ---- */\n.ps-badge {\n display: inline-flex; align-items: center; gap: 5px;\n padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 650; line-height: 1.7;\n}\n.ps-badge.gray { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.ps-badge.blue { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); }\n.ps-badge.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-badge.amber { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-badge.red { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }\n\n/* recommendation-level chips (the ranking matrix payoff) */\n.ps-lvl {\n display: inline-flex; align-items: center; justify-content: center;\n min-width: 92px; padding: 4px 10px; border-radius: 7px;\n font-weight: 650; font-size: 11.5px; color: var(--mj-text-inverse);\n}\n.ps-lvl-Primary { background: var(--mj-status-success); }\n.ps-lvl-Strong { background: var(--mj-status-info); }\n.ps-lvl-Viable { background: var(--mj-status-warning); }\n.ps-lvl-Weak { background: var(--mj-text-disabled); }\n.ps-lvl-NotRecommended { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n/* ---- tags ---- */\n.ps-tag {\n display: inline-block; padding: 2px 8px; border-radius: 6px;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n font-size: 11.5px; font-weight: 600;\n}\n.ps-tag.muted { opacity: .6; }\n.ps-divider { height: 1px; background: var(--mj-border-subtle); margin: 8px 0; }\n\n/* ---- tables ---- */\n.ps-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.ps-table th {\n text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; padding: 9px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n.ps-table td { padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-primary); }\n.ps-table tr:hover td { background: var(--mj-bg-surface-hover); }\n.ps-table .num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.ps-rank {\n width: 22px; height: 22px; border-radius: 6px; background: var(--mj-bg-surface-sunken);\n display: inline-grid; place-items: center; font-weight: 700; font-size: 11.5px; color: var(--mj-text-secondary);\n}\n.ps-rank.gold { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n\n/* ---- progress bars ---- */\n.ps-bar { height: 8px; border-radius: 999px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-bar > span { display: block; height: 100%; border-radius: 999px; background: var(--mj-brand-primary); }\n.ps-bar.warn > span { background: var(--mj-status-warning); }\n.ps-bar.run > span { background: var(--mj-brand-primary); }\n\n.ps-fbar { display: grid; grid-template-columns: 150px 1fr 48px; align-items: center; gap: 10px; padding: 5px 0; }\n.ps-fbar .track { height: 14px; border-radius: 5px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-secondary); }\n\n/* gauge */\n.ps-gauge {\n position: relative; width: 64px; height: 64px; border-radius: 50%; flex: 0 0 auto;\n background: conic-gradient(var(--ps-gauge-color, var(--mj-brand-primary)) calc(var(--ps-p, 40) * 1%), var(--mj-bg-surface-sunken) 0);\n display: grid; place-items: center;\n}\n.ps-gauge::after { content: ''; position: absolute; inset: 9px; background: var(--mj-bg-surface); border-radius: 50%; }\n.ps-gauge .g-val { position: relative; font-weight: 720; font-size: 14px; color: var(--mj-text-primary); }\n\n/* warning / info callouts */\n.ps-callout { display: flex; gap: 11px; padding: 12px 14px; border-radius: 10px; border: 1px solid; }\n.ps-callout.warn { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); color: var(--mj-status-warning-text); }\n.ps-callout.info { background: var(--mj-status-info-bg); border-color: var(--mj-status-info-border); color: var(--mj-status-info-text); }\n.ps-callout.success { background: var(--mj-status-success-bg); border-color: var(--mj-status-success-border); color: var(--mj-status-success-text); }\n.ps-callout i { font-size: 16px; margin-top: 1px; }\n\n/* lifecycle stepper */\n.ps-stepper { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }\n.ps-step { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--mj-text-muted); }\n.ps-step .pip {\n width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--mj-border-strong);\n display: grid; place-items: center; font-size: 11px;\n}\n.ps-step.done { color: var(--mj-status-success-text); }\n.ps-step.done .pip { background: var(--mj-status-success); border-color: var(--mj-status-success); color: var(--mj-text-inverse); }\n.ps-step.curr { color: var(--mj-brand-primary); }\n.ps-step.curr .pip { border-color: var(--mj-brand-primary); color: var(--mj-brand-primary); }\n.ps-step .ln { width: 26px; height: 2px; background: var(--mj-border-strong); }\n\n/* ---- DAG flow canvas ---- */\n.ps-flow {\n position: relative;\n background:\n linear-gradient(var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n linear-gradient(90deg, var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default); border-radius: 10px;\n min-height: 620px; overflow: hidden;\n}\n.ps-node {\n position: absolute; width: 190px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong); border-left-width: 3px; border-radius: 10px;\n box-shadow: var(--mj-shadow-sm); cursor: pointer;\n}\n.ps-node .nh {\n display: flex; align-items: center; gap: 8px; padding: 9px 11px;\n border-bottom: 1px solid var(--mj-border-subtle); font-weight: 650; font-size: 12.5px; color: var(--mj-text-primary);\n}\n.ps-node .nh i.tile {\n width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-node .nh .ps-tag { margin-left: auto; }\n.ps-node .nb { padding: 9px 11px; font-size: 12px; color: var(--mj-text-secondary); }\n.ps-node .nb-row { display: flex; justify-content: space-between; gap: 8px; padding: 2px 0; }\n.ps-node .nb-row .k { color: var(--mj-text-muted); }\n.ps-node.src { border-left-color: var(--ps-node-source); }\n.ps-node.src .nh i.tile { background: var(--ps-node-source); }\n.ps-node.feat { border-left-color: var(--ps-node-feature); }\n.ps-node.feat .nh i.tile { background: var(--ps-node-feature); }\n.ps-node.emb { border-left-color: var(--ps-node-embedding); }\n.ps-node.emb .nh i.tile { background: var(--ps-node-embedding); }\n.ps-node.target { border-left-color: var(--ps-node-target); }\n.ps-node.target .nh i.tile { background: var(--ps-node-target); }\n.ps-node.algo { border-left-color: var(--ps-node-algorithm); }\n.ps-node.algo .nh i.tile { background: var(--ps-node-algorithm); }\n.ps-node.output { border-left-color: var(--mj-status-success); }\n.ps-node.output .nh i.tile { background: var(--mj-status-success); }\n.ps-node.selected {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n.ps-node .port {\n position: absolute; width: 11px; height: 11px; border-radius: 50%;\n background: var(--mj-bg-surface); border: 2px solid var(--mj-brand-primary);\n top: 50%; transform: translateY(-50%);\n}\n.ps-node .port.in { left: -6px; }\n.ps-node .port.out { right: -6px; }\nsvg.ps-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }\nsvg.ps-edges path { stroke: color-mix(in srgb, var(--mj-brand-primary) 45%, transparent); stroke-width: 2; fill: none; }\n\n/* palette chips */\n.ps-pchip {\n display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border-radius: 8px;\n border: 1px dashed var(--mj-border-strong); background: var(--mj-bg-surface);\n font-size: 12.5px; font-weight: 600; color: var(--mj-text-secondary); cursor: grab;\n}\n.ps-pchip i { font-size: 12px; color: var(--mj-text-inverse); width: 20px; height: 20px; border-radius: 5px; display: grid; place-items: center; }\n.ps-pchip.s i { background: var(--ps-node-source); }\n.ps-pchip.f i { background: var(--ps-node-feature); }\n.ps-pchip.e i { background: var(--ps-node-embedding); }\n.ps-pchip.t i { background: var(--ps-node-target); }\n.ps-pchip.a i { background: var(--ps-node-algorithm); }\n\n/* segmented control */\n.ps-seg { display: inline-flex; border: 1px solid var(--mj-border-default); border-radius: 8px; overflow: hidden; }\n.ps-seg button {\n border: none; background: var(--mj-bg-surface); color: var(--mj-text-secondary);\n padding: 6px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;\n border-right: 1px solid var(--mj-border-default);\n}\n.ps-seg button:last-child { border-right: none; }\n.ps-seg button.on { background: var(--mj-brand-primary); color: var(--mj-text-inverse); }\n\n/* field control */\n.ps-field { margin-bottom: 14px; }\n.ps-field > label {\n display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; margin-bottom: 6px;\n}\n.ps-input {\n width: 100%; padding: 8px 10px; border: 1px solid var(--mj-border-default);\n border-radius: 6px; font-size: 13px; background: var(--mj-bg-surface); color: var(--mj-text-primary);\n box-sizing: border-box;\n}\n.ps-input:focus { outline: none; border-color: var(--mj-brand-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); }\n\n/* loading container */\n.ps-loading { display: flex; align-items: center; justify-content: center; padding: 60px 0; }\n\n/* ---- empty / prompt states ---- */\n.ps-empty {\n display: flex; flex-direction: column; align-items: center; justify-content: center;\n text-align: center; gap: 10px; padding: 56px 24px; color: var(--mj-text-muted);\n}\n.ps-empty .ps-empty-ico {\n width: 60px; height: 60px; border-radius: 16px; display: grid; place-items: center;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-disabled); font-size: 24px;\n}\n.ps-empty h3 { margin: 4px 0 0; font-size: 16px; font-weight: 650; color: var(--mj-text-secondary); }\n.ps-empty p { margin: 0; max-width: 420px; font-size: 13px; line-height: 1.5; }\n\n/* ---- confirm modal ---- */\n.ps-modal-backdrop {\n position: fixed; inset: 0; z-index: 1000;\n background: var(--mj-bg-overlay);\n display: flex; align-items: center; justify-content: center; padding: 24px;\n}\n.ps-modal {\n width: 100%; max-width: 480px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default); border-radius: 14px;\n box-shadow: var(--mj-shadow-lg, var(--mj-shadow-sm)); overflow: hidden;\n}\n.ps-modal-head {\n display: flex; align-items: center; gap: 12px; padding: 18px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-modal-head .ico {\n width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center;\n font-size: 16px; flex: 0 0 auto;\n background: var(--mj-status-info-bg); color: var(--mj-status-info-text);\n}\n.ps-modal-head.warn .ico { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-modal-head.danger .ico { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-modal-head h3 { margin: 0; font-size: 15.5px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-modal-body { padding: 18px 20px; font-size: 13.5px; line-height: 1.55; color: var(--mj-text-secondary); }\n.ps-modal-body .ps-field { margin-top: 14px; margin-bottom: 0; }\n.ps-modal-foot {\n display: flex; align-items: center; gap: 10px; padding: 14px 20px;\n border-top: 1px solid var(--mj-border-subtle); background: var(--mj-bg-surface-card);\n}\n.ps-modal-foot .ps-spacer { flex: 1; }\n", "/* Models in Production \u2014 model-centric control tower (master/detail). All colors via --mj-* tokens. */\n\n.ps-production {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 4px;\n}\n\n.prod-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 14px;\n}\n\n.prod-layout {\n display: grid;\n grid-template-columns: minmax(280px, 340px) minmax(0, 1fr);\n gap: 16px;\n align-items: start;\n}\n@media (max-width: 900px) {\n .prod-layout { grid-template-columns: 1fr; }\n}\n\n/* master list */\n.prod-layout .mlist .mrow {\n display: flex;\n align-items: center;\n gap: 11px;\n padding: 10px 10px;\n border-radius: 9px;\n cursor: pointer;\n}\n.prod-layout .mlist .mrow:hover { background: var(--mj-bg-surface-hover); }\n.prod-layout .mlist .mrow.sel { background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface)); }\n.prod-layout .mlist .mrow .ico {\n width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 13px; flex: 0 0 auto;\n}\n.prod-layout .mlist .mrow .nm { font-weight: 640; font-size: 14px; color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.prod-layout .mlist .mrow .ln2 { margin-top: 2px; }\n.prod-layout .mlist .mrow .meta { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; flex: 0 0 auto; }\n\n/* deploy-state icon colors (master + detail) */\n.st-bound { background: var(--mj-status-success); }\n.st-scheduled { background: var(--mj-status-info); }\n.st-idle { background: var(--mj-text-disabled); }\n\n/* detail */\n.prod-layout .detail { display: flex; flex-direction: column; gap: 14px; }\n.prod-layout .detail .dh { display: flex; align-items: center; gap: 13px; }\n.prod-layout .detail .dh h2 { margin: 0; font-size: 17px; font-weight: 680; color: var(--mj-text-primary); }\n.prod-layout .detail .dh .sub { margin-top: 3px; }\n.prod-layout .detail .big-ico {\n width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 16px; flex: 0 0 auto;\n}\n\n/* binding rows */\n.bind-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.bind-row:last-child { border-bottom: none; }\n\n/* run history table */\n.runs-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.runs-table th {\n text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; padding: 6px 8px; border-bottom: 1px solid var(--mj-border-default);\n}\n.runs-table td { padding: 7px 8px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-secondary); }\n.runs-table tr:last-child td { border-bottom: none; }\n.runs-table tr.run-row { cursor: pointer; }\n.runs-table tr.run-row:hover td { background: var(--mj-bg-surface-hover); }\n.runs-table .run-right { text-align: right; white-space: nowrap; }\n.runs-table .run-right i { margin-left: 8px; opacity: .5; }\n\n.run-back {\n display: inline-flex; align-items: center; gap: 6px; cursor: pointer;\n background: none; border: none; color: var(--mj-text-link); font-size: 13px; padding: 0 0 10px;\n}\n\n/* empty state CTA spacing (shared .ps-empty) */\n.ps-production .ps-empty p { max-width: 520px; }\n"] }]
|
|
827
|
+
`, styles: ["/* ============================================================================\n Predictive Studio \u2014 shared panel styles (design-token compliant)\n Maps the mockup design system onto MemberJunction semantic --mj-* tokens.\n Loaded by every PS panel component (styleUrls) under ViewEncapsulation.None,\n so the class names are global within the PS dashboard subtree.\n No hardcoded colors except the intentional categorical node/algorithm palette\n (declared once as --ps-* custom props below) which must stay distinct across\n light/dark to remain readable as diagram accents.\n ============================================================================ */\n\n/* Categorical accents for DAG node types + algorithm chips. These are\n data-visualization colors that must remain distinct regardless of theme\n (allowed exception #3 in the design-token rules). */\n.ps-panel {\n --ps-node-source: #6b7280;\n --ps-node-feature: #2050c8;\n --ps-node-embedding: #7b3ff0;\n --ps-node-target: #1f9d57;\n --ps-node-algorithm: #d98213;\n /* budget-gauge categorical accents (reuse the node palette so light/dark stay distinct) */\n --ps-gauge-cost: var(--ps-node-algorithm);\n --ps-gauge-iterations: var(--ps-node-feature);\n}\n\n.ps-panel {\n display: block;\n height: 100%;\n}\n\n/* ---- generic layout helpers ---- */\n.ps-row { display: flex; gap: 16px; }\n.ps-col { display: flex; flex-direction: column; gap: 16px; }\n.ps-wrap { flex-wrap: wrap; }\n.ps-spacer { flex: 1; }\n.ps-muted { color: var(--mj-text-muted); }\n.ps-small { font-size: 12.5px; }\n.ps-mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-section-title {\n font-size: 12px; text-transform: uppercase; letter-spacing: .06em;\n color: var(--mj-text-muted); margin: 4px 0 2px; font-weight: 700;\n}\n\n/* ---- cards ---- */\n.ps-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n.ps-card-head {\n display: flex; align-items: center; gap: 10px;\n padding: 14px 16px; border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-card-head h3 { font-size: 14.5px; margin: 0; font-weight: 650; color: var(--mj-text-primary); }\n.ps-card-body { padding: 16px; }\n\n/* ---- KPI tiles ---- */\n.ps-kpi {\n background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default);\n border-radius: 8px; padding: 16px 18px;\n}\n.ps-kpi .label { font-size: 12px; color: var(--mj-text-muted); font-weight: 600; }\n.ps-kpi .val { font-size: 26px; font-weight: 720; letter-spacing: -.02em; margin-top: 2px; color: var(--mj-text-primary); }\n\n/* ---- badges ---- */\n.ps-badge {\n display: inline-flex; align-items: center; gap: 5px;\n padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 650; line-height: 1.7;\n}\n.ps-badge.gray { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.ps-badge.blue { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); }\n.ps-badge.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-badge.amber { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-badge.red { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }\n\n/* recommendation-level chips (the ranking matrix payoff) */\n.ps-lvl {\n display: inline-flex; align-items: center; justify-content: center;\n min-width: 92px; padding: 4px 10px; border-radius: 7px;\n font-weight: 650; font-size: 11.5px; color: var(--mj-text-inverse);\n}\n.ps-lvl-Primary { background: var(--mj-status-success); }\n.ps-lvl-Strong { background: var(--mj-status-info); }\n.ps-lvl-Viable { background: var(--mj-status-warning); }\n.ps-lvl-Weak { background: var(--mj-text-disabled); }\n.ps-lvl-NotRecommended { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n/* ---- tags ---- */\n.ps-tag {\n display: inline-block; padding: 2px 8px; border-radius: 6px;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n font-size: 11.5px; font-weight: 600;\n}\n.ps-tag.muted { opacity: .6; }\n.ps-divider { height: 1px; background: var(--mj-border-subtle); margin: 8px 0; }\n\n/* ---- tables ---- */\n.ps-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.ps-table th {\n text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; padding: 9px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n.ps-table td { padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-primary); }\n.ps-table tr:hover td { background: var(--mj-bg-surface-hover); }\n.ps-table .num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.ps-rank {\n width: 22px; height: 22px; border-radius: 6px; background: var(--mj-bg-surface-sunken);\n display: inline-grid; place-items: center; font-weight: 700; font-size: 11.5px; color: var(--mj-text-secondary);\n}\n.ps-rank.gold { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n\n/* ---- progress bars ---- */\n.ps-bar { height: 8px; border-radius: 999px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-bar > span { display: block; height: 100%; border-radius: 999px; background: var(--mj-brand-primary); }\n.ps-bar.warn > span { background: var(--mj-status-warning); }\n.ps-bar.run > span { background: var(--mj-brand-primary); }\n\n.ps-fbar { display: grid; grid-template-columns: minmax(150px, 1.3fr) 2fr 56px; align-items: center; gap: 14px; padding: 8px 0; }\n.ps-fbar + .ps-fbar { border-top: 1px solid var(--mj-border-subtle); }\n.ps-fbar .track { height: 10px; border-radius: var(--mj-radius-full); background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; border-radius: var(--mj-radius-full); background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ps-fbar > .ps-mono { text-align: right; color: var(--mj-text-secondary); font-variant-numeric: tabular-nums; }\n\n/* gauge */\n.ps-gauge {\n position: relative; width: 64px; height: 64px; border-radius: 50%; flex: 0 0 auto;\n background: conic-gradient(var(--ps-gauge-color, var(--mj-brand-primary)) calc(var(--ps-p, 40) * 1%), var(--mj-bg-surface-sunken) 0);\n display: grid; place-items: center;\n}\n.ps-gauge::after { content: ''; position: absolute; inset: 9px; background: var(--mj-bg-surface); border-radius: 50%; }\n.ps-gauge .g-val { position: relative; font-weight: 720; font-size: 14px; color: var(--mj-text-primary); }\n\n/* warning / info callouts */\n.ps-callout { display: flex; gap: 11px; padding: 12px 14px; border-radius: 10px; border: 1px solid; }\n.ps-callout.warn { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); color: var(--mj-status-warning-text); }\n.ps-callout.info { background: var(--mj-status-info-bg); border-color: var(--mj-status-info-border); color: var(--mj-status-info-text); }\n.ps-callout.success { background: var(--mj-status-success-bg); border-color: var(--mj-status-success-border); color: var(--mj-status-success-text); }\n.ps-callout i { font-size: 16px; margin-top: 1px; }\n\n/* lifecycle stepper */\n.ps-stepper { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }\n.ps-step { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--mj-text-muted); }\n.ps-step .pip {\n width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--mj-border-strong);\n display: grid; place-items: center; font-size: 11px;\n}\n.ps-step.done { color: var(--mj-status-success-text); }\n.ps-step.done .pip { background: var(--mj-status-success); border-color: var(--mj-status-success); color: var(--mj-text-inverse); }\n.ps-step.curr { color: var(--mj-brand-primary); }\n.ps-step.curr .pip { border-color: var(--mj-brand-primary); color: var(--mj-brand-primary); }\n.ps-step .ln { width: 26px; height: 2px; background: var(--mj-border-strong); }\n\n/* ---- DAG flow canvas ---- */\n.ps-flow {\n position: relative;\n background:\n linear-gradient(var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n linear-gradient(90deg, var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default); border-radius: 10px;\n min-height: 620px; overflow: hidden;\n}\n.ps-node {\n position: absolute; width: 190px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong); border-left-width: 3px; border-radius: 8px;\n cursor: pointer;\n}\n.ps-node .nh {\n display: flex; align-items: center; gap: 8px; padding: 9px 11px;\n border-bottom: 1px solid var(--mj-border-subtle); font-weight: 650; font-size: 12.5px; color: var(--mj-text-primary);\n}\n.ps-node .nh i.tile {\n width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-node .nh .ps-tag { margin-left: auto; }\n.ps-node .nb { padding: 9px 11px; font-size: 12px; color: var(--mj-text-secondary); }\n.ps-node .nb-row { display: flex; justify-content: space-between; gap: 8px; padding: 2px 0; }\n.ps-node .nb-row .k { color: var(--mj-text-muted); }\n.ps-node.src { border-left-color: var(--ps-node-source); }\n.ps-node.src .nh i.tile { background: var(--ps-node-source); }\n.ps-node.feat { border-left-color: var(--ps-node-feature); }\n.ps-node.feat .nh i.tile { background: var(--ps-node-feature); }\n.ps-node.emb { border-left-color: var(--ps-node-embedding); }\n.ps-node.emb .nh i.tile { background: var(--ps-node-embedding); }\n.ps-node.target { border-left-color: var(--ps-node-target); }\n.ps-node.target .nh i.tile { background: var(--ps-node-target); }\n.ps-node.algo { border-left-color: var(--ps-node-algorithm); }\n.ps-node.algo .nh i.tile { background: var(--ps-node-algorithm); }\n.ps-node.output { border-left-color: var(--mj-status-success); }\n.ps-node.output .nh i.tile { background: var(--mj-status-success); }\n.ps-node.selected {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n.ps-node .port {\n position: absolute; width: 11px; height: 11px; border-radius: 50%;\n background: var(--mj-bg-surface); border: 2px solid var(--mj-brand-primary);\n top: 50%; transform: translateY(-50%);\n}\n.ps-node .port.in { left: -6px; }\n.ps-node .port.out { right: -6px; }\nsvg.ps-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }\nsvg.ps-edges path { stroke: color-mix(in srgb, var(--mj-brand-primary) 45%, transparent); stroke-width: 2; fill: none; }\n\n/* palette chips */\n.ps-pchip {\n display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border-radius: 8px;\n border: 1px dashed var(--mj-border-strong); background: var(--mj-bg-surface);\n font-size: 12.5px; font-weight: 600; color: var(--mj-text-secondary); cursor: grab;\n}\n.ps-pchip i { font-size: 12px; color: var(--mj-text-inverse); width: 20px; height: 20px; border-radius: 5px; display: grid; place-items: center; }\n.ps-pchip.s i { background: var(--ps-node-source); }\n.ps-pchip.f i { background: var(--ps-node-feature); }\n.ps-pchip.e i { background: var(--ps-node-embedding); }\n.ps-pchip.t i { background: var(--ps-node-target); }\n.ps-pchip.a i { background: var(--ps-node-algorithm); }\n\n/* segmented control */\n.ps-seg { display: inline-flex; border: 1px solid var(--mj-border-default); border-radius: 8px; overflow: hidden; }\n.ps-seg button {\n border: none; background: var(--mj-bg-surface); color: var(--mj-text-secondary);\n padding: 6px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;\n border-right: 1px solid var(--mj-border-default);\n}\n.ps-seg button:last-child { border-right: none; }\n.ps-seg button.on { background: var(--mj-brand-primary); color: var(--mj-text-inverse); }\n\n/* field control */\n.ps-field { margin-bottom: 14px; }\n.ps-field > label {\n display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; margin-bottom: 6px;\n}\n.ps-input {\n width: 100%; padding: 8px 10px; border: 1px solid var(--mj-border-default);\n border-radius: 6px; font-size: 13px; background: var(--mj-bg-surface); color: var(--mj-text-primary);\n box-sizing: border-box;\n}\n.ps-input:focus { outline: none; border-color: var(--mj-brand-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); }\n\n/* loading container */\n.ps-loading { display: flex; align-items: center; justify-content: center; padding: 60px 0; }\n\n/* ---- empty / prompt states ---- */\n.ps-empty {\n display: flex; flex-direction: column; align-items: center; justify-content: center;\n text-align: center; gap: 10px; padding: 56px 24px; color: var(--mj-text-muted);\n}\n.ps-empty .ps-empty-ico {\n width: 60px; height: 60px; border-radius: 16px; display: grid; place-items: center;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-disabled); font-size: 24px;\n}\n.ps-empty h3 { margin: 4px 0 0; font-size: 16px; font-weight: 650; color: var(--mj-text-secondary); }\n.ps-empty p { margin: 0; max-width: 420px; font-size: 13px; line-height: 1.5; }\n\n/* ---- confirm modal ---- */\n.ps-modal-backdrop {\n position: fixed; inset: 0; z-index: 1000;\n background: var(--mj-bg-overlay);\n display: flex; align-items: center; justify-content: center; padding: 24px;\n}\n.ps-modal {\n width: 100%; max-width: 480px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default); border-radius: 14px;\n box-shadow: var(--mj-shadow-lg, var(--mj-shadow-sm)); overflow: hidden;\n}\n.ps-modal-head {\n display: flex; align-items: center; gap: 12px; padding: 18px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-modal-head .ico {\n width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center;\n font-size: 16px; flex: 0 0 auto;\n background: var(--mj-status-info-bg); color: var(--mj-status-info-text);\n}\n.ps-modal-head.warn .ico { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-modal-head.danger .ico { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-modal-head h3 { margin: 0; font-size: 15.5px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-modal-body { padding: 18px 20px; font-size: 13.5px; line-height: 1.55; color: var(--mj-text-secondary); }\n.ps-modal-body .ps-field { margin-top: 14px; margin-bottom: 0; }\n.ps-modal-foot {\n display: flex; align-items: center; gap: 10px; padding: 14px 20px;\n border-top: 1px solid var(--mj-border-subtle); background: var(--mj-bg-surface-card);\n}\n.ps-modal-foot .ps-spacer { flex: 1; }\n", "/* Models in Production \u2014 model-centric control tower (master/detail). All colors via --mj-* tokens. */\n\n.ps-production {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 4px;\n}\n\n.prod-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 14px;\n}\n\n.prod-layout {\n display: grid;\n grid-template-columns: minmax(280px, 340px) minmax(0, 1fr);\n gap: 16px;\n align-items: start;\n}\n@media (max-width: 900px) {\n .prod-layout { grid-template-columns: 1fr; }\n}\n\n/* master list */\n.prod-layout .mlist .mrow {\n display: flex;\n align-items: center;\n gap: 11px;\n padding: 10px 10px;\n border-radius: 9px;\n cursor: pointer;\n}\n.prod-layout .mlist .mrow:hover { background: var(--mj-bg-surface-hover); }\n.prod-layout .mlist .mrow.sel { background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface)); }\n.prod-layout .mlist .mrow .ico {\n width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 13px; flex: 0 0 auto;\n}\n.prod-layout .mlist .mrow .nm { font-weight: 640; font-size: 14px; color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.prod-layout .mlist .mrow .ln2 { margin-top: 2px; }\n.prod-layout .mlist .mrow .meta { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; flex: 0 0 auto; }\n\n/* deploy-state icon colors (master + detail) */\n.st-bound { background: var(--mj-status-success); }\n.st-scheduled { background: var(--mj-status-info); }\n.st-idle { background: var(--mj-text-disabled); }\n\n/* detail */\n.prod-layout .detail { display: flex; flex-direction: column; gap: 14px; }\n.prod-layout .detail .dh { display: flex; align-items: center; gap: 13px; }\n.prod-layout .detail .dh h2 { margin: 0; font-size: 17px; font-weight: 680; color: var(--mj-text-primary); }\n.prod-layout .detail .dh .sub { margin-top: 3px; }\n.prod-layout .detail .big-ico {\n width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 16px; flex: 0 0 auto;\n}\n\n/* binding rows */\n.bind-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.bind-row:last-child { border-bottom: none; }\n\n/* run history table */\n.runs-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.runs-table th {\n text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; padding: 6px 8px; border-bottom: 1px solid var(--mj-border-default);\n}\n.runs-table td { padding: 7px 8px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-secondary); }\n.runs-table tr:last-child td { border-bottom: none; }\n.runs-table tr.run-row { cursor: pointer; }\n.runs-table tr.run-row:hover td { background: var(--mj-bg-surface-hover); }\n.runs-table .run-right { text-align: right; white-space: nowrap; }\n.runs-table .run-right i { margin-left: 8px; opacity: .5; }\n\n.run-back {\n display: inline-flex; align-items: center; gap: 6px; cursor: pointer;\n background: none; border: none; color: var(--mj-text-link); font-size: 13px; padding: 0 0 10px;\n}\n\n/* empty state CTA spacing (shared .ps-empty) */\n.ps-production .ps-empty p { max-width: 520px; }\n"] }]
|
|
828
828
|
}], null, { engine: [{
|
|
829
829
|
type: Input
|
|
830
830
|
}] }); })();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ps-production.component.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/components/ps-production.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport { SharedGenericModule } from '@memberjunction/ng-shared-generic';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { RunView } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { MJMLModelEntity, MJMLModelScoringBindingEntity, MJProcessRunDetailEntity } from '@memberjunction/core-entities';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { PredictiveStudioEngine } from '../engine/predictive-studio.engine';\nimport { PSProcessRunRow, primaryAuc } from '../predictive-studio.view-models';\nimport { humanizeCron, StatusVariant } from '../production-distribution';\nimport { PSOperateDialogComponent } from './ps-operate-dialog.component';\n\n/** A model's deployment state, derived purely from cached bindings + Record Processes. */\ntype DeployState = 'bound' | 'scheduled' | 'idle';\n\n/** One scoring binding shown in a model's deployment detail. */\ninterface BindingVM {\n id: string;\n targetEntity: string;\n targetColumn: string;\n mode: string;\n schedulePhrase: string | null;\n}\n\n/** One published model in the production control tower (DB-light — all fields from engine caches). */\ninterface ProductionModelVM {\n modelId: string;\n label: string;\n algorithm: string;\n problemType: string;\n version: number;\n holdoutMetric: string;\n deployState: DeployState;\n bindingCount: number;\n processCount: number;\n scheduledCount: number;\n /** Most recent scored-at across the model's bindings (cached lineage — no DB hit). */\n lastScoredAt: Date | null;\n lastRowCount: number | null;\n}\n\n/** One per-record prediction in a run's drill-in (parsed from `MJ: Process Run Details` `ResultPayload`). */\ninterface RunDetailVM {\n recordId: string;\n status: string;\n /** Formatted numeric prediction, or '—'. */\n score: string;\n /** Predicted class label (classification), or null. */\n class: string | null;\n /** ISO timestamp the prediction was produced (`$.scoredAt`), or the detail's completion time. */\n scoredAt: string | null;\n}\n\n/**\n * Models in Production — the **model-centric** control tower. Every approved (Published) model appears\n * here whether it's idle, scheduled, or bound — a scoring binding is a *deployment marker*, not a\n * prerequisite to appear or to run. Reactive + DB-light: the published-model list and each model's\n * deployment state come straight from the `PredictiveStudioEngine` caches (a `BaseEngine` subclass) via\n * `ObserveProperty`, so it re-renders on any model/binding change with no polling; a model's **past runs**\n * are loaded on demand when selected (`MJ: Process Runs` grow unbounded — never bulk-cached).\n *\n * Entity-agnostic: model labels derive from the producing pipeline; binding targets come from the binding\n * rows. **Operate** (the rocket button) opens the {@link PSOperateDialogComponent} to run/schedule/bind the\n * model; clicking a run drills into its per-record predictions (`MJ: Process Run Details`).\n */\n@Component({\n standalone: true,\n selector: 'ps-production',\n imports: [CommonModule, SharedGenericModule, MJButtonDirective, PSOperateDialogComponent],\n encapsulation: ViewEncapsulation.None,\n styleUrls: ['../predictive-studio.shared.scss', './ps-production.component.scss'],\n template: `\n <div class=\"ps-panel ps-production\" data-testid=\"ps-production-panel\">\n @if (models.length === 0) {\n <div class=\"ps-empty\" data-testid=\"ps-production-empty\">\n <span class=\"ps-empty-ico\"><i class=\"fa-solid fa-satellite-dish\"></i></span>\n <h3>No models in production yet</h3>\n <p>\n When you publish a trained model in the Model Registry it shows up here — ready to schedule,\n bind to a column, and run. Train a pipeline and promote the model to Published to get started.\n </p>\n </div>\n } @else {\n <!-- KPI strip -->\n <div class=\"prod-kpis\" data-testid=\"ps-production-kpis\">\n <div class=\"ps-kpi\"><div class=\"label\">Published</div><div class=\"val\">{{ models.length }}</div></div>\n <div class=\"ps-kpi\"><div class=\"label\">Scheduled</div><div class=\"val\">{{ scheduledModelCount }}</div></div>\n <div class=\"ps-kpi\"><div class=\"label\">Bound (write-back)</div><div class=\"val\">{{ boundModelCount }}</div></div>\n <div class=\"ps-kpi\"><div class=\"label\">Idle</div><div class=\"val\">{{ idleModelCount }}</div></div>\n </div>\n\n <div class=\"prod-layout\">\n <!-- master list -->\n <div class=\"ps-card mlist\" data-testid=\"ps-production-list\">\n <div class=\"ps-card-head\"><h3>Published models</h3><span class=\"ps-badge gray\">{{ models.length }}</span></div>\n <div class=\"ps-card-body\" style=\"padding:8px\">\n @for (m of models; track m.modelId) {\n <div class=\"mrow\" data-testid=\"ps-production-row\" [class.sel]=\"m.modelId === selectedModelId\" (click)=\"select(m.modelId)\">\n <div class=\"ico\" [class]=\"'st-' + m.deployState\"><i [class]=\"deployIcon(m.deployState)\"></i></div>\n <div style=\"flex:1;min-width:0\">\n <div class=\"nm\">{{ m.label }}</div>\n <div class=\"ln2 ps-muted ps-small\">v{{ m.version }} · {{ m.algorithm }}</div>\n </div>\n <div class=\"meta\">\n <span class=\"ps-badge\" [class]=\"deployBadge(m.deployState)\">{{ deployLabel(m.deployState) }}</span>\n <div class=\"ps-mono ps-small ps-muted\">{{ m.holdoutMetric }}</div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- detail -->\n <div class=\"ps-col detail\" data-testid=\"ps-production-detail\">\n <div class=\"ps-card\">\n <div class=\"ps-card-body dh\">\n <div class=\"big-ico\" [class]=\"'st-' + selected.deployState\"><i [class]=\"deployIcon(selected.deployState)\"></i></div>\n <div style=\"flex:1\">\n <h2 data-testid=\"ps-production-detail-name\">{{ selected.label }} <span class=\"ps-tag ps-mono\">v{{ selected.version }}</span></h2>\n <div class=\"ps-muted ps-small sub\">{{ selected.algorithm }} · {{ selected.problemType }} · holdout {{ selected.holdoutMetric }}</div>\n </div>\n <span class=\"ps-badge\" [class]=\"deployBadge(selected.deployState)\">{{ deployLabel(selected.deployState) }}</span>\n <button mjButton variant=\"primary\" size=\"sm\" data-testid=\"ps-production-operate\" (click)=\"operateOpen = true\">\n <i class=\"fa-solid fa-rocket\"></i> Operate\n </button>\n </div>\n </div>\n\n <!-- deployment status -->\n <div class=\"ps-card\">\n <div class=\"ps-card-head\"><h3>Deployment</h3>\n <span class=\"ps-muted ps-small\">{{ selected.processCount }} process{{ selected.processCount === 1 ? '' : 'es' }} · {{ selected.bindingCount }} binding{{ selected.bindingCount === 1 ? '' : 's' }}</span>\n </div>\n <div class=\"ps-card-body\">\n @if (selected.deployState === 'idle') {\n <div class=\"ps-callout info\">\n <i class=\"fa-solid fa-circle-info\"></i>\n <div class=\"ps-small\">This model is published but <strong>not operating</strong> yet — nothing scores with it. Click <strong>Operate</strong> above to run it now, schedule it to run regularly, or write predictions back to a column.</div>\n </div>\n } @else {\n @if (selectedBindings.length > 0) {\n <div class=\"ps-section-title\">Scoring bindings</div>\n @for (b of selectedBindings; track b.id) {\n <div class=\"bind-row\">\n <i class=\"fa-solid fa-arrow-right-to-bracket ps-muted\"></i>\n <div style=\"flex:1\">\n <div class=\"ps-small\"><strong>{{ b.targetEntity }}</strong>.{{ b.targetColumn }}</div>\n <div class=\"ps-muted ps-small\">{{ b.mode }}{{ b.schedulePhrase ? ' · ' + b.schedulePhrase : '' }}</div>\n </div>\n <span class=\"ps-badge\" [class]=\"modeBadge(b.mode)\">{{ b.mode }}</span>\n </div>\n }\n } @else {\n <div class=\"ps-small ps-muted\">Scheduled to run, writing generic output to the process run history (no write-back column).</div>\n }\n @if (selected.lastScoredAt) {\n <div class=\"ps-divider\"></div>\n <div class=\"ps-row\" style=\"justify-content:space-between\"><span class=\"ps-muted ps-small\">Last scored</span><span class=\"ps-small\">{{ selected.lastScoredAt | date:'medium' }}{{ selected.lastRowCount != null ? ' · ' + selected.lastRowCount + ' rows' : '' }}</span></div>\n }\n }\n </div>\n </div>\n\n <!-- past runs (on demand) -->\n <div class=\"ps-card\">\n <div class=\"ps-card-head\"><h3>Run history</h3><span class=\"ps-muted ps-small\">last 90 days · newest first</span></div>\n <div class=\"ps-card-body\">\n @if (selectedRunId) {\n <!-- run drill-in: per-record predictions from Process Run Details -->\n <button class=\"run-back\" data-testid=\"ps-production-run-back\" (click)=\"closeRun()\">\n <i class=\"fa-solid fa-arrow-left\"></i> All runs\n </button>\n @if (loadingDetails) {\n <mj-loading text=\"Loading predictions...\" size=\"small\"></mj-loading>\n } @else if (runDetails.length === 0) {\n <div class=\"ps-small ps-muted\">No per-record predictions recorded for this run.</div>\n } @else {\n <table class=\"runs-table\" data-testid=\"ps-production-run-detail\">\n <thead><tr><th>Record</th><th>Status</th><th>Prediction</th><th>Scored</th></tr></thead>\n <tbody>\n @for (d of runDetails; track d.recordId) {\n <tr>\n <td class=\"ps-mono ps-small\">{{ d.recordId }}</td>\n <td><span class=\"ps-badge\" [class]=\"runBadge(d.status)\">{{ d.status }}</span></td>\n <td class=\"ps-mono\">{{ d.score }}@if (d.class) { <span class=\"ps-muted\"> · {{ d.class }}</span> }</td>\n <td class=\"ps-small ps-muted\">{{ d.scoredAt ? (d.scoredAt | date:'short') : '—' }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n } @else if (loadingRuns) {\n <mj-loading text=\"Loading runs...\" size=\"small\"></mj-loading>\n } @else if (runs.length === 0) {\n <div class=\"ps-small ps-muted\">No runs recorded yet. Each time this model runs as a Record Process, its predictions are saved to the process run history — even without a scoring binding.</div>\n } @else {\n <table class=\"runs-table\">\n <thead><tr><th>When</th><th>Status</th><th>Scored</th><th>Process</th><th></th></tr></thead>\n <tbody>\n @for (r of runs; track r.ID) {\n <tr data-testid=\"ps-production-run\" class=\"run-row\" (click)=\"openRun(r.ID)\">\n <td>{{ (r.StartTime || r.CreatedAt) | date:'short' }}</td>\n <td><span class=\"ps-badge\" [class]=\"runBadge(r.Status)\">{{ r.Status }}</span></td>\n <td class=\"ps-mono\">{{ r.SuccessCount }}<span class=\"ps-muted\">/{{ r.TotalItemCount ?? 0 }}</span></td>\n <td class=\"ps-small ps-muted\">{{ r.ProcessName || '—' }}</td>\n <td class=\"run-right\">@if (r.DryRun) { <span class=\"ps-tag amber\">dry run</span> }<i class=\"fa-solid fa-chevron-right ps-muted\"></i></td>\n </tr>\n }\n </tbody>\n </table>\n }\n </div>\n </div>\n </div>\n </div>\n\n <ps-operate-dialog\n [Visible]=\"operateOpen\"\n [modelId]=\"selected.modelId\"\n [modelLabel]=\"selected.label\"\n [engine]=\"engine\"\n [provider]=\"ProviderToUse\"\n [currentUser]=\"ProviderToUse.CurrentUser\"\n (Close)=\"onOperateClose($event)\">\n </ps-operate-dialog>\n }\n </div>\n `,\n})\nexport class PSProductionComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n @Input() engine!: PredictiveStudioEngine;\n\n private cdr = inject(ChangeDetectorRef);\n private modelsSub?: Subscription;\n\n public models: ProductionModelVM[] = [];\n public selectedModelId = '';\n public selectedBindings: BindingVM[] = [];\n public runs: PSProcessRunRow[] = [];\n public loadingRuns = false;\n /** Whether the \"Operate this model\" dialog is open for the selected model. */\n public operateOpen = false;\n /** The run whose per-record predictions are drilled into (null = the run list). */\n public selectedRunId: string | null = null;\n public runDetails: RunDetailVM[] = [];\n public loadingDetails = false;\n\n ngOnInit(): void {\n // Reactive: rebuild the published-model list on any MJ: ML Models change (save/delete/remote-invalidate).\n this.modelsSub = this.engine\n .ObserveProperty<MJMLModelEntity>('_Models')\n .subscribe(() => {\n this.rebuildModels();\n this.cdr.detectChanges();\n });\n }\n\n ngOnDestroy(): void {\n this.modelsSub?.unsubscribe();\n }\n\n // ---- KPIs ----\n\n public get scheduledModelCount(): number {\n return this.models.filter((m) => m.deployState === 'scheduled' || m.scheduledCount > 0).length;\n }\n public get boundModelCount(): number {\n return this.models.filter((m) => m.bindingCount > 0).length;\n }\n public get idleModelCount(): number {\n return this.models.filter((m) => m.deployState === 'idle').length;\n }\n\n // ---- reactive list build (DB-light, from caches) ----\n\n private rebuildModels(): void {\n this.models = (this.engine?.PublishedModels ?? []).map((m) => this.toVM(m));\n if (!this.models.some((m) => UUIDsEqual(m.modelId, this.selectedModelId))) {\n const first = this.models[0]?.modelId ?? '';\n if (first) {\n this.select(first);\n } else {\n this.selectedModelId = '';\n this.selectedBindings = [];\n this.runs = [];\n }\n } else {\n this.selectedBindings = this.bindingsForModel(this.selectedModelId);\n }\n }\n\n private toVM(m: MJMLModelEntity): ProductionModelVM {\n const bindings = this.engine.ScoringBindings.filter((b) => UUIDsEqual(b.MLModelID, m.ID));\n const processes = this.engine.RecordProcessesForModel(m.ID);\n const scheduledCount = processes.filter((p) => !!p.ScheduleEnabled).length\n + bindings.filter((b) => b.Mode === 'Scheduled').length;\n const lastScoredAt = bindings.reduce<Date | null>(\n (acc, b) => (b.LastScoredAt && (!acc || b.LastScoredAt.getTime() > acc.getTime()) ? b.LastScoredAt : acc),\n null,\n );\n const lastRowCount = bindings.find((b) => b.LastRowCount != null)?.LastRowCount ?? null;\n const auc = primaryAuc(m);\n return {\n modelId: m.ID,\n label: this.engine.ModelDisplayName(m),\n algorithm: this.engine.AlgorithmName(m.AlgorithmID),\n problemType: m.ProblemType ?? '—',\n version: m.Version,\n holdoutMetric: auc != null ? auc.toFixed(3) : '—',\n deployState: bindings.length > 0 ? 'bound' : scheduledCount > 0 ? 'scheduled' : 'idle',\n bindingCount: bindings.length,\n processCount: processes.length,\n scheduledCount,\n lastScoredAt,\n lastRowCount,\n };\n }\n\n private bindingsForModel(modelId: string): BindingVM[] {\n return this.engine.ScoringBindings\n .filter((b) => UUIDsEqual(b.MLModelID, modelId))\n .map((b) => this.toBindingVM(b));\n }\n\n private toBindingVM(b: MJMLModelScoringBindingEntity): BindingVM {\n const process = this.engine.RecordProcessByID(b.RecordProcessID);\n return {\n id: b.ID,\n targetEntity: this.resolveEntityName(b),\n targetColumn: b.TargetColumn ?? '(generic output)',\n mode: b.Mode,\n schedulePhrase: b.Mode === 'Scheduled' ? humanizeCron(process?.CronExpression ?? null) : null,\n };\n }\n\n private resolveEntityName(b: MJMLModelScoringBindingEntity): string {\n if (b.TargetEntity) return b.TargetEntity;\n if (b.TargetEntityID) {\n const entity = this.ProviderToUse.Entities.find((e) => UUIDsEqual(e.ID, b.TargetEntityID));\n if (entity) return entity.Name;\n }\n return '—';\n }\n\n // ---- selection + on-demand run history ----\n\n public get selected(): ProductionModelVM {\n return (\n this.models.find((m) => UUIDsEqual(m.modelId, this.selectedModelId)) ??\n this.models[0] ?? {\n modelId: '', label: '—', algorithm: '—', problemType: '—', version: 0, holdoutMetric: '—',\n deployState: 'idle', bindingCount: 0, processCount: 0, scheduledCount: 0, lastScoredAt: null, lastRowCount: null,\n }\n );\n }\n\n /**\n * Close the Operate dialog. On a successful change the dialog already refreshed the engine\n * (Config(true)) — the reactive `_Models` subscription re-renders the deploy state — but the\n * on-demand run history + bindings of the SELECTED model are not part of that stream, so reload them\n * here so a just-created run / binding shows immediately.\n */\n public onOperateClose(result: { changed: boolean }): void {\n this.operateOpen = false;\n if (result.changed && this.selectedModelId) {\n this.selectedBindings = this.bindingsForModel(this.selectedModelId);\n void this.loadRuns(this.selectedModelId);\n }\n }\n\n public select(id: string): void {\n this.selectedModelId = id;\n this.selectedBindings = this.bindingsForModel(id);\n this.closeRun();\n void this.loadRuns(id);\n }\n\n // ---- run drill-in: per-record predictions (on demand) ----\n\n /** Drill into a run's per-record predictions (`MJ: Process Run Details` `ResultPayload`). */\n public openRun(runId: string): void {\n this.selectedRunId = runId;\n void this.loadRunDetails(runId);\n }\n\n public closeRun(): void {\n this.selectedRunId = null;\n this.runDetails = [];\n }\n\n private async loadRunDetails(runId: string): Promise<void> {\n this.loadingDetails = true;\n this.runDetails = [];\n this.cdr.detectChanges();\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const r = await rv.RunView<MJProcessRunDetailEntity>(\n {\n EntityName: 'MJ: Process Run Details',\n ExtraFilter: `ProcessRunID='${runId}'`,\n OrderBy: '__mj_CreatedAt ASC',\n MaxRows: 200,\n ResultType: 'entity_object',\n },\n this.ProviderToUse.CurrentUser,\n );\n this.runDetails = r.Success ? (r.Results ?? []).map((d) => this.toDetailVM(d)) : [];\n } finally {\n this.loadingDetails = false;\n this.cdr.detectChanges();\n }\n }\n\n /** Project a Process Run Detail into a per-record prediction row, parsing the ML `ResultPayload`. */\n private toDetailVM(d: MJProcessRunDetailEntity): RunDetailVM {\n let score = '—';\n let cls: string | null = null;\n let scoredAt: string | null = d.CompletedAt ? d.CompletedAt.toISOString() : null;\n if (d.ResultPayload) {\n try {\n const p = JSON.parse(d.ResultPayload) as { score?: number; class?: string; scoredAt?: string };\n if (typeof p.score === 'number') {\n score = p.score.toFixed(4);\n }\n cls = p.class ?? null;\n scoredAt = p.scoredAt ?? scoredAt;\n } catch {\n /* leave defaults — a non-ML payload (or malformed) just shows '—' */\n }\n }\n return { recordId: d.RecordID ?? '—', status: d.Status, score, class: cls, scoredAt };\n }\n\n /** On-demand run history for the selected model (DB-light — only the selected model, capped). */\n private async loadRuns(modelId: string): Promise<void> {\n this.loadingRuns = true;\n this.runs = [];\n this.cdr.detectChanges();\n try {\n this.runs = await this.engine.LoadRecentRunsForModel(\n modelId,\n this.ProviderToUse,\n this.ProviderToUse.CurrentUser,\n { sinceDays: 90, maxRows: 50 },\n );\n } finally {\n this.loadingRuns = false;\n this.cdr.detectChanges();\n }\n }\n\n // ---- display helpers ----\n\n public deployIcon(state: DeployState): string {\n switch (state) {\n case 'bound': return 'fa-solid fa-arrow-right-to-bracket';\n case 'scheduled': return 'fa-solid fa-clock';\n case 'idle': return 'fa-solid fa-circle-pause';\n }\n }\n public deployLabel(state: DeployState): string {\n switch (state) {\n case 'bound': return 'Bound';\n case 'scheduled': return 'Scheduled';\n case 'idle': return 'Idle';\n }\n }\n public deployBadge(state: DeployState): StatusVariant {\n switch (state) {\n case 'bound': return 'green';\n case 'scheduled': return 'blue';\n case 'idle': return 'gray';\n }\n }\n public modeBadge(mode: string): StatusVariant {\n return mode === 'Scheduled' ? 'blue' : mode === 'Materialized' ? 'green' : 'gray';\n }\n public runBadge(status: string): StatusVariant {\n const s = (status || '').toLowerCase();\n if (s.includes('complete') || s.includes('success')) return 'green';\n if (s.includes('fail') || s.includes('error')) return 'red';\n if (s.includes('run') || s.includes('progress')) return 'blue';\n return 'gray';\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ps-production.component.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/components/ps-production.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport { SharedGenericModule } from '@memberjunction/ng-shared-generic';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { RunView } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { MJMLModelEntity, MJMLModelScoringBindingEntity, MJProcessRunDetailEntity } from '@memberjunction/core-entities';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { PredictiveStudioEngine } from '../engine/predictive-studio.engine';\nimport { PSProcessRunRow, primaryAuc } from '../predictive-studio.view-models';\nimport { humanizeCron, StatusVariant } from '../production-distribution';\nimport { PSOperateDialogComponent } from './ps-operate-dialog.component';\n\n/** A model's deployment state, derived purely from cached bindings + Record Processes. */\ntype DeployState = 'bound' | 'scheduled' | 'idle';\n\n/** One scoring binding shown in a model's deployment detail. */\ninterface BindingVM {\n id: string;\n targetEntity: string;\n targetColumn: string;\n mode: string;\n schedulePhrase: string | null;\n}\n\n/** One published model in the production control tower (DB-light — all fields from engine caches). */\ninterface ProductionModelVM {\n modelId: string;\n label: string;\n algorithm: string;\n problemType: string;\n version: number;\n holdoutMetric: string;\n deployState: DeployState;\n bindingCount: number;\n processCount: number;\n scheduledCount: number;\n /** Most recent scored-at across the model's bindings (cached lineage — no DB hit). */\n lastScoredAt: Date | null;\n lastRowCount: number | null;\n}\n\n/** One per-record prediction in a run's drill-in (parsed from `MJ: Process Run Details` `ResultPayload`). */\ninterface RunDetailVM {\n recordId: string;\n status: string;\n /** Formatted numeric prediction, or '—'. */\n score: string;\n /** Predicted class label (classification), or null. */\n class: string | null;\n /** ISO timestamp the prediction was produced (`$.scoredAt`), or the detail's completion time. */\n scoredAt: string | null;\n}\n\n/**\n * Models in Production — the **model-centric** control tower. Every approved (Published) model appears\n * here whether it's idle, scheduled, or bound — a scoring binding is a *deployment marker*, not a\n * prerequisite to appear or to run. Reactive + DB-light: the published-model list and each model's\n * deployment state come straight from the `PredictiveStudioEngine` caches (a `BaseEngine` subclass) via\n * `ObserveProperty`, so it re-renders on any model/binding change with no polling; a model's **past runs**\n * are loaded on demand when selected (`MJ: Process Runs` grow unbounded — never bulk-cached).\n *\n * Entity-agnostic: model labels derive from the producing pipeline; binding targets come from the binding\n * rows. **Operate** (the rocket button) opens the {@link PSOperateDialogComponent} to run/schedule/bind the\n * model; clicking a run drills into its per-record predictions (`MJ: Process Run Details`).\n */\n@Component({\n standalone: true,\n selector: 'ps-production',\n imports: [CommonModule, SharedGenericModule, MJButtonDirective, PSOperateDialogComponent],\n encapsulation: ViewEncapsulation.None,\n styleUrls: ['../predictive-studio.shared.css', './ps-production.component.css'],\n template: `\n <div class=\"ps-panel ps-production\" data-testid=\"ps-production-panel\">\n @if (models.length === 0) {\n <div class=\"ps-empty\" data-testid=\"ps-production-empty\">\n <span class=\"ps-empty-ico\"><i class=\"fa-solid fa-satellite-dish\"></i></span>\n <h3>No models in production yet</h3>\n <p>\n When you publish a trained model in the Model Registry it shows up here — ready to schedule,\n bind to a column, and run. Train a pipeline and promote the model to Published to get started.\n </p>\n </div>\n } @else {\n <!-- KPI strip -->\n <div class=\"prod-kpis\" data-testid=\"ps-production-kpis\">\n <div class=\"ps-kpi\"><div class=\"label\">Published</div><div class=\"val\">{{ models.length }}</div></div>\n <div class=\"ps-kpi\"><div class=\"label\">Scheduled</div><div class=\"val\">{{ scheduledModelCount }}</div></div>\n <div class=\"ps-kpi\"><div class=\"label\">Bound (write-back)</div><div class=\"val\">{{ boundModelCount }}</div></div>\n <div class=\"ps-kpi\"><div class=\"label\">Idle</div><div class=\"val\">{{ idleModelCount }}</div></div>\n </div>\n\n <div class=\"prod-layout\">\n <!-- master list -->\n <div class=\"ps-card mlist\" data-testid=\"ps-production-list\">\n <div class=\"ps-card-head\"><h3>Published models</h3><span class=\"ps-badge gray\">{{ models.length }}</span></div>\n <div class=\"ps-card-body\" style=\"padding:8px\">\n @for (m of models; track m.modelId) {\n <div class=\"mrow\" data-testid=\"ps-production-row\" [class.sel]=\"m.modelId === selectedModelId\" (click)=\"select(m.modelId)\">\n <div class=\"ico\" [class]=\"'st-' + m.deployState\"><i [class]=\"deployIcon(m.deployState)\"></i></div>\n <div style=\"flex:1;min-width:0\">\n <div class=\"nm\">{{ m.label }}</div>\n <div class=\"ln2 ps-muted ps-small\">v{{ m.version }} · {{ m.algorithm }}</div>\n </div>\n <div class=\"meta\">\n <span class=\"ps-badge\" [class]=\"deployBadge(m.deployState)\">{{ deployLabel(m.deployState) }}</span>\n <div class=\"ps-mono ps-small ps-muted\">{{ m.holdoutMetric }}</div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- detail -->\n <div class=\"ps-col detail\" data-testid=\"ps-production-detail\">\n <div class=\"ps-card\">\n <div class=\"ps-card-body dh\">\n <div class=\"big-ico\" [class]=\"'st-' + selected.deployState\"><i [class]=\"deployIcon(selected.deployState)\"></i></div>\n <div style=\"flex:1\">\n <h2 data-testid=\"ps-production-detail-name\">{{ selected.label }} <span class=\"ps-tag ps-mono\">v{{ selected.version }}</span></h2>\n <div class=\"ps-muted ps-small sub\">{{ selected.algorithm }} · {{ selected.problemType }} · holdout {{ selected.holdoutMetric }}</div>\n </div>\n <span class=\"ps-badge\" [class]=\"deployBadge(selected.deployState)\">{{ deployLabel(selected.deployState) }}</span>\n <button mjButton variant=\"primary\" size=\"sm\" data-testid=\"ps-production-operate\" (click)=\"operateOpen = true\">\n <i class=\"fa-solid fa-rocket\"></i> Operate\n </button>\n </div>\n </div>\n\n <!-- deployment status -->\n <div class=\"ps-card\">\n <div class=\"ps-card-head\"><h3>Deployment</h3>\n <span class=\"ps-muted ps-small\">{{ selected.processCount }} process{{ selected.processCount === 1 ? '' : 'es' }} · {{ selected.bindingCount }} binding{{ selected.bindingCount === 1 ? '' : 's' }}</span>\n </div>\n <div class=\"ps-card-body\">\n @if (selected.deployState === 'idle') {\n <div class=\"ps-callout info\">\n <i class=\"fa-solid fa-circle-info\"></i>\n <div class=\"ps-small\">This model is published but <strong>not operating</strong> yet — nothing scores with it. Click <strong>Operate</strong> above to run it now, schedule it to run regularly, or write predictions back to a column.</div>\n </div>\n } @else {\n @if (selectedBindings.length > 0) {\n <div class=\"ps-section-title\">Scoring bindings</div>\n @for (b of selectedBindings; track b.id) {\n <div class=\"bind-row\">\n <i class=\"fa-solid fa-arrow-right-to-bracket ps-muted\"></i>\n <div style=\"flex:1\">\n <div class=\"ps-small\"><strong>{{ b.targetEntity }}</strong>.{{ b.targetColumn }}</div>\n <div class=\"ps-muted ps-small\">{{ b.mode }}{{ b.schedulePhrase ? ' · ' + b.schedulePhrase : '' }}</div>\n </div>\n <span class=\"ps-badge\" [class]=\"modeBadge(b.mode)\">{{ b.mode }}</span>\n </div>\n }\n } @else {\n <div class=\"ps-small ps-muted\">Scheduled to run, writing generic output to the process run history (no write-back column).</div>\n }\n @if (selected.lastScoredAt) {\n <div class=\"ps-divider\"></div>\n <div class=\"ps-row\" style=\"justify-content:space-between\"><span class=\"ps-muted ps-small\">Last scored</span><span class=\"ps-small\">{{ selected.lastScoredAt | date:'medium' }}{{ selected.lastRowCount != null ? ' · ' + selected.lastRowCount + ' rows' : '' }}</span></div>\n }\n }\n </div>\n </div>\n\n <!-- past runs (on demand) -->\n <div class=\"ps-card\">\n <div class=\"ps-card-head\"><h3>Run history</h3><span class=\"ps-muted ps-small\">last 90 days · newest first</span></div>\n <div class=\"ps-card-body\">\n @if (selectedRunId) {\n <!-- run drill-in: per-record predictions from Process Run Details -->\n <button class=\"run-back\" data-testid=\"ps-production-run-back\" (click)=\"closeRun()\">\n <i class=\"fa-solid fa-arrow-left\"></i> All runs\n </button>\n @if (loadingDetails) {\n <mj-loading text=\"Loading predictions...\" size=\"small\"></mj-loading>\n } @else if (runDetails.length === 0) {\n <div class=\"ps-small ps-muted\">No per-record predictions recorded for this run.</div>\n } @else {\n <table class=\"runs-table\" data-testid=\"ps-production-run-detail\">\n <thead><tr><th>Record</th><th>Status</th><th>Prediction</th><th>Scored</th></tr></thead>\n <tbody>\n @for (d of runDetails; track d.recordId) {\n <tr>\n <td class=\"ps-mono ps-small\">{{ d.recordId }}</td>\n <td><span class=\"ps-badge\" [class]=\"runBadge(d.status)\">{{ d.status }}</span></td>\n <td class=\"ps-mono\">{{ d.score }}@if (d.class) { <span class=\"ps-muted\"> · {{ d.class }}</span> }</td>\n <td class=\"ps-small ps-muted\">{{ d.scoredAt ? (d.scoredAt | date:'short') : '—' }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n } @else if (loadingRuns) {\n <mj-loading text=\"Loading runs...\" size=\"small\"></mj-loading>\n } @else if (runs.length === 0) {\n <div class=\"ps-small ps-muted\">No runs recorded yet. Each time this model runs as a Record Process, its predictions are saved to the process run history — even without a scoring binding.</div>\n } @else {\n <table class=\"runs-table\">\n <thead><tr><th>When</th><th>Status</th><th>Scored</th><th>Process</th><th></th></tr></thead>\n <tbody>\n @for (r of runs; track r.ID) {\n <tr data-testid=\"ps-production-run\" class=\"run-row\" (click)=\"openRun(r.ID)\">\n <td>{{ (r.StartTime || r.CreatedAt) | date:'short' }}</td>\n <td><span class=\"ps-badge\" [class]=\"runBadge(r.Status)\">{{ r.Status }}</span></td>\n <td class=\"ps-mono\">{{ r.SuccessCount }}<span class=\"ps-muted\">/{{ r.TotalItemCount ?? 0 }}</span></td>\n <td class=\"ps-small ps-muted\">{{ r.ProcessName || '—' }}</td>\n <td class=\"run-right\">@if (r.DryRun) { <span class=\"ps-tag amber\">dry run</span> }<i class=\"fa-solid fa-chevron-right ps-muted\"></i></td>\n </tr>\n }\n </tbody>\n </table>\n }\n </div>\n </div>\n </div>\n </div>\n\n <ps-operate-dialog\n [Visible]=\"operateOpen\"\n [modelId]=\"selected.modelId\"\n [modelLabel]=\"selected.label\"\n [engine]=\"engine\"\n [provider]=\"ProviderToUse\"\n [currentUser]=\"ProviderToUse.CurrentUser\"\n (Close)=\"onOperateClose($event)\">\n </ps-operate-dialog>\n }\n </div>\n `,\n})\nexport class PSProductionComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n @Input() engine!: PredictiveStudioEngine;\n\n private cdr = inject(ChangeDetectorRef);\n private modelsSub?: Subscription;\n\n public models: ProductionModelVM[] = [];\n public selectedModelId = '';\n public selectedBindings: BindingVM[] = [];\n public runs: PSProcessRunRow[] = [];\n public loadingRuns = false;\n /** Whether the \"Operate this model\" dialog is open for the selected model. */\n public operateOpen = false;\n /** The run whose per-record predictions are drilled into (null = the run list). */\n public selectedRunId: string | null = null;\n public runDetails: RunDetailVM[] = [];\n public loadingDetails = false;\n\n ngOnInit(): void {\n // Reactive: rebuild the published-model list on any MJ: ML Models change (save/delete/remote-invalidate).\n this.modelsSub = this.engine\n .ObserveProperty<MJMLModelEntity>('_Models')\n .subscribe(() => {\n this.rebuildModels();\n this.cdr.detectChanges();\n });\n }\n\n ngOnDestroy(): void {\n this.modelsSub?.unsubscribe();\n }\n\n // ---- KPIs ----\n\n public get scheduledModelCount(): number {\n return this.models.filter((m) => m.deployState === 'scheduled' || m.scheduledCount > 0).length;\n }\n public get boundModelCount(): number {\n return this.models.filter((m) => m.bindingCount > 0).length;\n }\n public get idleModelCount(): number {\n return this.models.filter((m) => m.deployState === 'idle').length;\n }\n\n // ---- reactive list build (DB-light, from caches) ----\n\n private rebuildModels(): void {\n this.models = (this.engine?.PublishedModels ?? []).map((m) => this.toVM(m));\n if (!this.models.some((m) => UUIDsEqual(m.modelId, this.selectedModelId))) {\n const first = this.models[0]?.modelId ?? '';\n if (first) {\n this.select(first);\n } else {\n this.selectedModelId = '';\n this.selectedBindings = [];\n this.runs = [];\n }\n } else {\n this.selectedBindings = this.bindingsForModel(this.selectedModelId);\n }\n }\n\n private toVM(m: MJMLModelEntity): ProductionModelVM {\n const bindings = this.engine.ScoringBindings.filter((b) => UUIDsEqual(b.MLModelID, m.ID));\n const processes = this.engine.RecordProcessesForModel(m.ID);\n const scheduledCount = processes.filter((p) => !!p.ScheduleEnabled).length\n + bindings.filter((b) => b.Mode === 'Scheduled').length;\n const lastScoredAt = bindings.reduce<Date | null>(\n (acc, b) => (b.LastScoredAt && (!acc || b.LastScoredAt.getTime() > acc.getTime()) ? b.LastScoredAt : acc),\n null,\n );\n const lastRowCount = bindings.find((b) => b.LastRowCount != null)?.LastRowCount ?? null;\n const auc = primaryAuc(m);\n return {\n modelId: m.ID,\n label: this.engine.ModelDisplayName(m),\n algorithm: this.engine.AlgorithmName(m.AlgorithmID),\n problemType: m.ProblemType ?? '—',\n version: m.Version,\n holdoutMetric: auc != null ? auc.toFixed(3) : '—',\n deployState: bindings.length > 0 ? 'bound' : scheduledCount > 0 ? 'scheduled' : 'idle',\n bindingCount: bindings.length,\n processCount: processes.length,\n scheduledCount,\n lastScoredAt,\n lastRowCount,\n };\n }\n\n private bindingsForModel(modelId: string): BindingVM[] {\n return this.engine.ScoringBindings\n .filter((b) => UUIDsEqual(b.MLModelID, modelId))\n .map((b) => this.toBindingVM(b));\n }\n\n private toBindingVM(b: MJMLModelScoringBindingEntity): BindingVM {\n const process = this.engine.RecordProcessByID(b.RecordProcessID);\n return {\n id: b.ID,\n targetEntity: this.resolveEntityName(b),\n targetColumn: b.TargetColumn ?? '(generic output)',\n mode: b.Mode,\n schedulePhrase: b.Mode === 'Scheduled' ? humanizeCron(process?.CronExpression ?? null) : null,\n };\n }\n\n private resolveEntityName(b: MJMLModelScoringBindingEntity): string {\n if (b.TargetEntity) return b.TargetEntity;\n if (b.TargetEntityID) {\n const entity = this.ProviderToUse.Entities.find((e) => UUIDsEqual(e.ID, b.TargetEntityID));\n if (entity) return entity.Name;\n }\n return '—';\n }\n\n // ---- selection + on-demand run history ----\n\n public get selected(): ProductionModelVM {\n return (\n this.models.find((m) => UUIDsEqual(m.modelId, this.selectedModelId)) ??\n this.models[0] ?? {\n modelId: '', label: '—', algorithm: '—', problemType: '—', version: 0, holdoutMetric: '—',\n deployState: 'idle', bindingCount: 0, processCount: 0, scheduledCount: 0, lastScoredAt: null, lastRowCount: null,\n }\n );\n }\n\n /**\n * Close the Operate dialog. On a successful change the dialog already refreshed the engine\n * (Config(true)) — the reactive `_Models` subscription re-renders the deploy state — but the\n * on-demand run history + bindings of the SELECTED model are not part of that stream, so reload them\n * here so a just-created run / binding shows immediately.\n */\n public onOperateClose(result: { changed: boolean }): void {\n this.operateOpen = false;\n if (result.changed && this.selectedModelId) {\n this.selectedBindings = this.bindingsForModel(this.selectedModelId);\n void this.loadRuns(this.selectedModelId);\n }\n }\n\n public select(id: string): void {\n this.selectedModelId = id;\n this.selectedBindings = this.bindingsForModel(id);\n this.closeRun();\n void this.loadRuns(id);\n }\n\n // ---- run drill-in: per-record predictions (on demand) ----\n\n /** Drill into a run's per-record predictions (`MJ: Process Run Details` `ResultPayload`). */\n public openRun(runId: string): void {\n this.selectedRunId = runId;\n void this.loadRunDetails(runId);\n }\n\n public closeRun(): void {\n this.selectedRunId = null;\n this.runDetails = [];\n }\n\n private async loadRunDetails(runId: string): Promise<void> {\n this.loadingDetails = true;\n this.runDetails = [];\n this.cdr.detectChanges();\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const r = await rv.RunView<MJProcessRunDetailEntity>(\n {\n EntityName: 'MJ: Process Run Details',\n ExtraFilter: `ProcessRunID='${runId}'`,\n OrderBy: '__mj_CreatedAt ASC',\n MaxRows: 200,\n ResultType: 'entity_object',\n },\n this.ProviderToUse.CurrentUser,\n );\n this.runDetails = r.Success ? (r.Results ?? []).map((d) => this.toDetailVM(d)) : [];\n } finally {\n this.loadingDetails = false;\n this.cdr.detectChanges();\n }\n }\n\n /** Project a Process Run Detail into a per-record prediction row, parsing the ML `ResultPayload`. */\n private toDetailVM(d: MJProcessRunDetailEntity): RunDetailVM {\n let score = '—';\n let cls: string | null = null;\n let scoredAt: string | null = d.CompletedAt ? d.CompletedAt.toISOString() : null;\n if (d.ResultPayload) {\n try {\n const p = JSON.parse(d.ResultPayload) as { score?: number; class?: string; scoredAt?: string };\n if (typeof p.score === 'number') {\n score = p.score.toFixed(4);\n }\n cls = p.class ?? null;\n scoredAt = p.scoredAt ?? scoredAt;\n } catch {\n /* leave defaults — a non-ML payload (or malformed) just shows '—' */\n }\n }\n return { recordId: d.RecordID ?? '—', status: d.Status, score, class: cls, scoredAt };\n }\n\n /** On-demand run history for the selected model (DB-light — only the selected model, capped). */\n private async loadRuns(modelId: string): Promise<void> {\n this.loadingRuns = true;\n this.runs = [];\n this.cdr.detectChanges();\n try {\n this.runs = await this.engine.LoadRecentRunsForModel(\n modelId,\n this.ProviderToUse,\n this.ProviderToUse.CurrentUser,\n { sinceDays: 90, maxRows: 50 },\n );\n } finally {\n this.loadingRuns = false;\n this.cdr.detectChanges();\n }\n }\n\n // ---- display helpers ----\n\n public deployIcon(state: DeployState): string {\n switch (state) {\n case 'bound': return 'fa-solid fa-arrow-right-to-bracket';\n case 'scheduled': return 'fa-solid fa-clock';\n case 'idle': return 'fa-solid fa-circle-pause';\n }\n }\n public deployLabel(state: DeployState): string {\n switch (state) {\n case 'bound': return 'Bound';\n case 'scheduled': return 'Scheduled';\n case 'idle': return 'Idle';\n }\n }\n public deployBadge(state: DeployState): StatusVariant {\n switch (state) {\n case 'bound': return 'green';\n case 'scheduled': return 'blue';\n case 'idle': return 'gray';\n }\n }\n public modeBadge(mode: string): StatusVariant {\n return mode === 'Scheduled' ? 'blue' : mode === 'Materialized' ? 'green' : 'gray';\n }\n public runBadge(status: string): StatusVariant {\n const s = (status || '').toLowerCase();\n if (s.includes('complete') || s.includes('success')) return 'green';\n if (s.includes('fail') || s.includes('error')) return 'red';\n if (s.includes('run') || s.includes('progress')) return 'blue';\n return 'gray';\n }\n}\n"]}
|
|
@@ -56,7 +56,7 @@ export declare class PSRegistryComponent implements OnInit {
|
|
|
56
56
|
select(id: string): void;
|
|
57
57
|
get selected(): ModelRowVM;
|
|
58
58
|
private get selectedEntity();
|
|
59
|
-
/** Top-6 feature importance bars parsed live from the selected model's `FeatureImportance` JSON. */
|
|
59
|
+
/** Top-6 feature importance bars parsed live from the selected model's `FeatureImportance` JSON, with humanized display names. */
|
|
60
60
|
get importance(): PSFeatureBar[];
|
|
61
61
|
get importanceCaption(): string;
|
|
62
62
|
get topFeatureName(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ps-registry.component.d.ts","sourceRoot":"","sources":["../../../src/PredictiveStudio/components/ps-registry.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,MAAM,EAA6B,MAAM,eAAe,CAAC;AAKvG,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAGL,iCAAiC,EAClC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAsB,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC/F,OAAO,EAEL,eAAe,EAOhB,MAAM,kCAAkC,CAAC;;
|
|
1
|
+
{"version":3,"file":"ps-registry.component.d.ts","sourceRoot":"","sources":["../../../src/PredictiveStudio/components/ps-registry.component.ts"],"names":[],"mappings":"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"}
|