@memberjunction/ng-dashboards 5.26.0 → 5.27.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/AI/components/analytics/agent-runs/agent-run-analysis.component.d.ts +96 -0
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js +710 -0
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js.map +1 -0
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts +52 -0
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/ai-analytics-resource.component.js +356 -0
- package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -0
- package/dist/AI/components/analytics/analytics-filter-bar.component.d.ts +52 -0
- package/dist/AI/components/analytics/analytics-filter-bar.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/analytics-filter-bar.component.js +306 -0
- package/dist/AI/components/analytics/analytics-filter-bar.component.js.map +1 -0
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +81 -0
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +744 -0
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -0
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.d.ts +61 -0
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.js +490 -0
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.js.map +1 -0
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts +77 -0
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +673 -0
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -0
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +65 -0
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/model-performance/model-performance.component.js +537 -0
- package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -0
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +131 -0
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +1030 -0
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -0
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +78 -0
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -0
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +569 -0
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -0
- package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +4 -14
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/overview/ai-overview-hub.component.d.ts +58 -0
- package/dist/AI/components/overview/ai-overview-hub.component.d.ts.map +1 -0
- package/dist/AI/components/overview/ai-overview-hub.component.js +315 -0
- package/dist/AI/components/overview/ai-overview-hub.component.js.map +1 -0
- package/dist/AI/components/prompts/prompt-management.component.js +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/index.d.ts +11 -0
- package/dist/AI/index.d.ts.map +1 -1
- package/dist/AI/index.js +13 -0
- package/dist/AI/index.js.map +1 -1
- package/dist/AI/interfaces/analytics-preferences.interface.d.ts +50 -0
- package/dist/AI/interfaces/analytics-preferences.interface.d.ts.map +1 -0
- package/dist/AI/interfaces/analytics-preferences.interface.js +9 -0
- package/dist/AI/interfaces/analytics-preferences.interface.js.map +1 -0
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.js +2 -2
- package/dist/MCP/index.d.ts +1 -0
- package/dist/MCP/index.d.ts.map +1 -1
- package/dist/MCP/index.js +2 -0
- package/dist/MCP/index.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.d.ts +1 -0
- package/dist/MCP/mcp-dashboard.component.d.ts.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +5 -4
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/MCP/mcp-resource.component.d.ts +6 -5
- package/dist/MCP/mcp-resource.component.d.ts.map +1 -1
- package/dist/MCP/mcp-resource.component.js +7 -8
- package/dist/MCP/mcp-resource.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +27 -17
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +66 -3
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +1 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +48 -48
- package/dist/__tests__/analytics-resource.test.d.ts +0 -2
- package/dist/__tests__/analytics-resource.test.d.ts.map +0 -1
- package/dist/__tests__/analytics-resource.test.js +0 -181
- package/dist/__tests__/analytics-resource.test.js.map +0 -1
- package/dist/__tests__/dashboards.test.d.ts +0 -2
- package/dist/__tests__/dashboards.test.d.ts.map +0 -1
- package/dist/__tests__/dashboards.test.js +0 -40
- package/dist/__tests__/dashboards.test.js.map +0 -1
- package/dist/__tests__/integration-data-service.test.d.ts +0 -2
- package/dist/__tests__/integration-data-service.test.d.ts.map +0 -1
- package/dist/__tests__/integration-data-service.test.js +0 -132
- package/dist/__tests__/integration-data-service.test.js.map +0 -1
- package/dist/__tests__/mapping-validation.test.d.ts +0 -2
- package/dist/__tests__/mapping-validation.test.d.ts.map +0 -1
- package/dist/__tests__/mapping-validation.test.js +0 -170
- package/dist/__tests__/mapping-validation.test.js.map +0 -1
- package/dist/__tests__/scheduling.test.d.ts +0 -2
- package/dist/__tests__/scheduling.test.d.ts.map +0 -1
- package/dist/__tests__/scheduling.test.js +0 -205
- package/dist/__tests__/scheduling.test.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-run-analysis.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/agent-runs/agent-run-analysis.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Agent Run Analysis -- Cost Attribution Focus.\n *\n * Displays agent run stats, cost attribution horizontal stacked bars per agent,\n * and a sortable recent agent runs table. All data loaded via RunView from\n * \"MJ: AI Agent Runs\" and \"MJ: AI Prompt Runs\" entities.\n */\n\nimport {\n Component, Input, Output, EventEmitter,\n OnInit, OnDestroy, ChangeDetectorRef, inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { RunView } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { GlobalFilterState } from '../../../interfaces/analytics-preferences.interface';\n\n// ── Interfaces ──\n\ninterface AgentRunFilters {\n Agents: string[];\n Statuses: string[];\n}\n\ninterface AgentRunRecord {\n ID: string;\n StartedAt: string;\n CompletedAt: string | null;\n Status: string;\n Success: boolean | null;\n TotalCost: number | null;\n TotalTokensUsed: number | null;\n AgentID: string;\n Agent: string | null;\n ErrorMessage: string | null;\n}\n\ninterface PromptRunRecord {\n ID: string;\n AgentRunID: string | null;\n Cost: number | null;\n TotalCost: number | null;\n Model: string | null;\n Vendor: string | null;\n}\n\ninterface AgentRunStats {\n TotalRuns: number;\n TotalCost: number;\n PromptRuns: number;\n AvgCostPerRun: number;\n SuccessRate: number;\n AvgDurationSeconds: number;\n}\n\ninterface CostAttributionRow {\n AgentName: string;\n AgentID: string;\n TotalCost: number;\n Segments: CostSegment[];\n}\n\ninterface CostSegment {\n Label: string;\n Value: number;\n Percent: number;\n Color: string;\n}\n\ninterface RecentRunRow {\n ID: string;\n Agent: string;\n Status: string;\n StatusClass: string;\n StepCount: number;\n Duration: string;\n Cost: string;\n Time: string;\n}\n\ntype SortField = 'Agent' | 'Status' | 'StepCount' | 'Duration' | 'Cost' | 'Time';\ntype SortDirection = 'asc' | 'desc';\n\nconst AGENT_RUN_FIELDS = [\n 'ID', 'StartedAt', 'CompletedAt', 'Status', 'Success',\n 'TotalCost', 'TotalTokensUsed', 'AgentID', 'Agent', 'ErrorMessage'\n];\n\nconst PROMPT_RUN_FIELDS = [\n 'ID', 'AgentRunID', 'Cost', 'TotalCost', 'Model', 'Vendor'\n];\n\nconst COST_COLORS = [\n 'var(--mj-brand-primary)',\n 'var(--mj-brand-accent, var(--mj-brand-primary-hover))',\n 'var(--mj-status-info)',\n 'var(--mj-text-disabled)'\n];\n\n@Component({\n standalone: false,\n selector: 'app-analytics-agent-runs',\n template: `\n <!-- Filter Bar -->\n <app-analytics-filter-bar\n [TimeRange]=\"TimeRange\"\n [Filters]=\"globalFilters\"\n [ShowModelFilter]=\"false\"\n [ShowPromptFilter]=\"false\"\n [ShowAgentFilter]=\"true\"\n [ShowStatusFilter]=\"true\"\n [ShowCompareToggle]=\"false\"\n [ShowExportButton]=\"false\"\n (TimeRangeChange)=\"OnTimeRangeChange($event)\"\n (FiltersChange)=\"OnFiltersChange($event)\"\n ></app-analytics-filter-bar>\n\n @if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading agent runs...\"></mj-loading>\n </div>\n } @else {\n <!-- Stats Bar -->\n <div class=\"stats-grid\">\n <div class=\"stat-card accent-brand\">\n <div class=\"stat-label\">Total Runs</div>\n <div class=\"stat-value\">{{ Stats.TotalRuns | number }}</div>\n </div>\n <div class=\"stat-card accent-brand\">\n <div class=\"stat-label\">Total Cost</div>\n <div class=\"stat-value\">{{ FormatCurrency(Stats.TotalCost) }}</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-label\">Prompt Runs</div>\n <div class=\"stat-value\">{{ Stats.PromptRuns | number }}</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-label\">Avg Cost/Run</div>\n <div class=\"stat-value\">{{ FormatCurrency(Stats.AvgCostPerRun, 4) }}</div>\n </div>\n <div class=\"stat-card accent-success\">\n <div class=\"stat-label\">Success Rate</div>\n <div class=\"stat-value\">{{ Stats.SuccessRate | number:'1.1-1' }}%</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-label\">Avg Duration</div>\n <div class=\"stat-value\">{{ Stats.AvgDurationSeconds | number:'1.1-1' }}s</div>\n </div>\n </div>\n\n <!-- Cost Attribution Panel -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-chart-bar panel-header__icon\"></i>\n Cost Attribution by Agent\n </div>\n </div>\n <div class=\"panel-body\">\n @if (CostAttributionRows.length === 0) {\n <div class=\"panel-empty\">No agent cost data for selected period</div>\n }\n @for (row of CostAttributionRows; track row.AgentID) {\n <div class=\"attribution-row\">\n <div class=\"attribution-name\" [title]=\"row.AgentName\">{{ row.AgentName }}</div>\n <div class=\"attribution-bar-container\">\n @for (seg of row.Segments; track seg.Label) {\n <div\n class=\"attribution-segment\"\n [style.width.%]=\"seg.Percent\"\n [style.background]=\"seg.Color\"\n [title]=\"seg.Label + ': ' + FormatCurrency(seg.Value, 4)\"\n ></div>\n }\n </div>\n <div class=\"attribution-total\">{{ FormatCurrency(row.TotalCost) }}</div>\n </div>\n }\n @if (CostAttributionRows.length > 0) {\n <div class=\"legend-row\">\n @for (item of LegendItems; track item.Label) {\n <div class=\"legend-item\">\n <span class=\"legend-swatch\" [style.background]=\"item.Color\"></span>\n {{ item.Label }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Recent Agent Runs Table -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-list panel-header__icon\"></i>\n Recent Agent Runs\n </div>\n <span class=\"panel-header__subtitle\">{{ RecentRuns.length }} runs</span>\n </div>\n <div class=\"table-wrapper\">\n <table class=\"data-table\">\n <thead>\n <tr>\n @for (col of TableColumns; track col.field) {\n <th\n class=\"sortable-header\"\n [class.sorted]=\"SortField === col.field\"\n (click)=\"OnSort(col.field)\">\n {{ col.label }}\n @if (SortField === col.field) {\n <i [class]=\"SortDir === 'asc' ? 'fa-solid fa-caret-up' : 'fa-solid fa-caret-down'\"></i>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (RecentRuns.length === 0) {\n <tr><td [attr.colspan]=\"TableColumns.length\" class=\"empty-row\">No runs found</td></tr>\n }\n @for (run of RecentRuns; track run.ID) {\n <tr>\n <td class=\"cell-agent\">{{ run.Agent }}</td>\n <td><span class=\"status-pill\" [class]=\"run.StatusClass\">{{ run.Status }}</span></td>\n <td class=\"cell-numeric\">{{ run.StepCount }}</td>\n <td class=\"cell-numeric\">{{ run.Duration }}</td>\n <td class=\"cell-numeric\">{{ run.Cost }}</td>\n <td class=\"cell-time\">{{ run.Time }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n }\n `,\n styles: [`\n :host { display: block; }\n\n .loading-container {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n }\n\n /* ── Stats Grid ── */\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: 12px;\n margin: 16px 0;\n }\n\n .stat-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n padding: 14px 16px;\n text-align: center;\n border-top: 3px solid var(--mj-border-subtle);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n }\n\n .stat-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n }\n\n .stat-card.accent-brand { border-top-color: var(--mj-brand-primary); }\n .stat-card.accent-success { border-top-color: var(--mj-status-success); }\n .stat-card.accent-warning { border-top-color: var(--mj-status-warning); }\n\n .stat-label {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n }\n\n .stat-value {\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n letter-spacing: -0.02em;\n }\n\n /* ── Panel ── */\n .panel {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n margin-bottom: 16px;\n overflow: hidden;\n }\n\n .panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .panel-header__title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .panel-header__icon {\n font-size: 13px;\n color: var(--mj-brand-primary);\n }\n\n .panel-header__subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n\n .panel-body {\n padding: 16px 18px;\n }\n\n .panel-empty {\n text-align: center;\n padding: 24px;\n color: var(--mj-text-disabled);\n font-size: 13px;\n }\n\n /* ── Cost Attribution ── */\n .attribution-row {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .attribution-row:last-of-type {\n border-bottom: none;\n }\n\n .attribution-name {\n width: 140px;\n min-width: 140px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .attribution-bar-container {\n flex: 1;\n display: flex;\n height: 24px;\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n }\n\n .attribution-segment {\n height: 100%;\n min-width: 2px;\n transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .attribution-total {\n width: 80px;\n min-width: 80px;\n text-align: right;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n }\n\n .legend-row {\n display: flex;\n gap: 16px;\n padding: 12px 0 4px;\n flex-wrap: wrap;\n }\n\n .legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: var(--mj-text-muted);\n }\n\n .legend-swatch {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n flex-shrink: 0;\n }\n\n /* ── Table ── */\n .table-wrapper {\n overflow-x: auto;\n }\n\n .data-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n }\n\n .data-table th,\n .data-table td {\n padding: 10px 14px;\n text-align: left;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .data-table th {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n background: var(--mj-bg-surface-card);\n position: sticky;\n top: 0;\n }\n\n .sortable-header {\n cursor: pointer;\n user-select: none;\n white-space: nowrap;\n transition: color 0.15s;\n }\n\n .sortable-header:hover {\n color: var(--mj-brand-primary);\n }\n\n .sortable-header.sorted {\n color: var(--mj-brand-primary);\n }\n\n .sortable-header i {\n margin-left: 4px;\n font-size: 10px;\n }\n\n .data-table tbody tr {\n transition: background 0.15s;\n }\n\n .data-table tbody tr:hover {\n background: var(--mj-bg-surface-hover);\n }\n\n .cell-agent {\n font-weight: 500;\n color: var(--mj-text-primary);\n max-width: 200px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .cell-numeric {\n text-align: right;\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-secondary);\n }\n\n .cell-time {\n white-space: nowrap;\n color: var(--mj-text-muted);\n font-size: 12px;\n }\n\n .empty-row {\n text-align: center;\n color: var(--mj-text-disabled);\n padding: 24px;\n }\n\n /* ── Status Pills ── */\n .status-pill {\n display: inline-block;\n padding: 3px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.3px;\n }\n\n .status-completed {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n }\n\n .status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n .status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n }\n\n .status-cancelled {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n }\n\n .status-paused, .status-awaitingfeedback {\n background: color-mix(in srgb, var(--mj-text-disabled) 12%, var(--mj-bg-surface));\n color: var(--mj-text-muted);\n }\n\n /* ── Responsive ── */\n @media (max-width: 1200px) {\n .stats-grid {\n grid-template-columns: repeat(3, 1fr);\n }\n }\n\n @media (max-width: 768px) {\n .stats-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .attribution-name {\n width: 100px;\n min-width: 100px;\n }\n\n .attribution-total {\n width: 60px;\n min-width: 60px;\n }\n\n .stat-value {\n font-size: 18px;\n }\n }\n `]\n})\nexport class AnalyticsAgentRunsComponent implements OnInit, OnDestroy {\n @Input() TimeRange = '7d';\n @Input() Filters: AgentRunFilters = { Agents: [], Statuses: [] };\n\n @Output() TimeRangeChange = new EventEmitter<string>();\n @Output() FiltersChange = new EventEmitter<AgentRunFilters>();\n\n private cdr = inject(ChangeDetectorRef);\n private destroy$ = new Subject<void>();\n\n public IsLoading = false;\n\n public Stats: AgentRunStats = {\n TotalRuns: 0,\n TotalCost: 0,\n PromptRuns: 0,\n AvgCostPerRun: 0,\n SuccessRate: 0,\n AvgDurationSeconds: 0\n };\n\n public CostAttributionRows: CostAttributionRow[] = [];\n public LegendItems: { Label: string; Color: string }[] = [];\n public RecentRuns: RecentRunRow[] = [];\n public SortField: SortField = 'Time';\n public SortDir: SortDirection = 'desc';\n\n public TableColumns: { field: SortField; label: string }[] = [\n { field: 'Agent', label: 'Agent' },\n { field: 'Status', label: 'Status' },\n { field: 'StepCount', label: 'Steps' },\n { field: 'Duration', label: 'Duration' },\n { field: 'Cost', label: 'Cost' },\n { field: 'Time', label: 'Time' }\n ];\n\n /** Bridge the local filter shape to the global shape the filter bar expects */\n public get globalFilters(): GlobalFilterState {\n return {\n Models: [],\n Agents: this.Filters.Agents,\n Prompts: [],\n Statuses: this.Filters.Statuses\n };\n }\n\n private agentRuns: AgentRunRecord[] = [];\n private promptRuns: PromptRunRecord[] = [];\n\n ngOnInit(): void {\n this.LoadData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ── Public Event Handlers ──\n\n public OnTimeRangeChange(range: string): void {\n this.TimeRange = range;\n this.TimeRangeChange.emit(range);\n this.LoadData();\n }\n\n public OnFiltersChange(filters: GlobalFilterState): void {\n this.Filters = { Agents: filters.Agents, Statuses: filters.Statuses };\n this.FiltersChange.emit(this.Filters);\n this.LoadData();\n }\n\n public OnSort(field: SortField): void {\n if (this.SortField === field) {\n this.SortDir = this.SortDir === 'asc' ? 'desc' : 'asc';\n } else {\n this.SortField = field;\n this.SortDir = field === 'Time' ? 'desc' : 'asc';\n }\n this.sortRecentRuns();\n this.cdr.detectChanges();\n }\n\n public FormatCurrency(value: number, decimals = 2): string {\n if (value === 0) return '$0.00';\n if (value < 0.01 && decimals < 4) decimals = 4;\n return '$' + value.toFixed(decimals);\n }\n\n // ── Data Loading ──\n\n private async LoadData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.detectChanges();\n\n try {\n const rv = new RunView();\n const dateFilter = this.buildDateFilter('StartedAt');\n const agentFilter = this.buildAgentFilter();\n const statusFilter = this.buildStatusFilter();\n const extraFilter = [dateFilter, agentFilter, statusFilter].filter(Boolean).join(' AND ');\n\n const promptDateFilter = this.buildDateFilter('RunAt');\n\n const [agentResult, promptResult] = await rv.RunViews([\n {\n EntityName: 'MJ: AI Agent Runs',\n ExtraFilter: extraFilter,\n Fields: AGENT_RUN_FIELDS,\n OrderBy: 'StartedAt DESC',\n ResultType: 'simple'\n },\n {\n EntityName: 'MJ: AI Prompt Runs',\n ExtraFilter: promptDateFilter,\n Fields: PROMPT_RUN_FIELDS,\n OrderBy: 'RunAt DESC',\n ResultType: 'simple'\n }\n ]);\n\n this.agentRuns = (agentResult?.Results ?? []) as AgentRunRecord[];\n this.promptRuns = (promptResult?.Results ?? []) as PromptRunRecord[];\n\n this.computeStats();\n this.computeCostAttribution();\n this.buildRecentRuns();\n this.sortRecentRuns();\n } catch (e) {\n console.error('Agent Run Analysis load error:', e);\n } finally {\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n // ── Computations ──\n\n private computeStats(): void {\n const runs = this.agentRuns;\n const total = runs.length;\n const totalCost = runs.reduce((s, r) => s + (r.TotalCost ?? 0), 0);\n const completed = runs.filter(r => r.Status === 'Completed');\n const successCount = runs.filter(r => r.Success === true).length;\n\n const durations = completed\n .filter(r => r.CompletedAt)\n .map(r => {\n const start = new Date(r.StartedAt).getTime();\n const end = new Date(r.CompletedAt!).getTime();\n return (end - start) / 1000;\n })\n .filter(d => d > 0);\n\n const avgDuration = durations.length > 0\n ? durations.reduce((s, d) => s + d, 0) / durations.length\n : 0;\n\n const linkedPromptRuns = this.promptRuns.filter(\n p => p.AgentRunID != null && this.agentRunIdSet.has(p.AgentRunID)\n );\n\n this.Stats = {\n TotalRuns: total,\n TotalCost: totalCost,\n PromptRuns: linkedPromptRuns.length,\n AvgCostPerRun: total > 0 ? totalCost / total : 0,\n SuccessRate: total > 0 ? (successCount / total) * 100 : 0,\n AvgDurationSeconds: avgDuration\n };\n }\n\n private get agentRunIdSet(): Set<string> {\n return new Set(this.agentRuns.map(r => r.ID));\n }\n\n private computeCostAttribution(): void {\n const agentCostMap = new Map<string, { name: string; vendorCosts: Map<string, number>; totalCost: number }>();\n\n // Group prompt runs by agent run, then by vendor\n for (const pr of this.promptRuns) {\n if (!pr.AgentRunID) continue;\n const agentRun = this.agentRuns.find(ar => UUIDsEqual(ar.ID, pr.AgentRunID));\n if (!agentRun) continue;\n\n const agentKey = agentRun.AgentID;\n if (!agentCostMap.has(agentKey)) {\n agentCostMap.set(agentKey, {\n name: agentRun.Agent ?? 'Unknown',\n vendorCosts: new Map<string, number>(),\n totalCost: 0\n });\n }\n\n const entry = agentCostMap.get(agentKey)!;\n const vendor = pr.Vendor ?? 'Other';\n const cost = pr.Cost ?? pr.TotalCost ?? 0;\n entry.vendorCosts.set(vendor, (entry.vendorCosts.get(vendor) ?? 0) + cost);\n entry.totalCost += cost;\n }\n\n // Collect all vendors for consistent coloring\n const allVendors = new Set<string>();\n for (const entry of agentCostMap.values()) {\n for (const v of entry.vendorCosts.keys()) {\n allVendors.add(v);\n }\n }\n const vendorList = Array.from(allVendors);\n\n // Build legend\n this.LegendItems = vendorList.map((v, i) => ({\n Label: v,\n Color: COST_COLORS[i % COST_COLORS.length]\n }));\n\n // Sort by total cost descending\n const sorted = Array.from(agentCostMap.entries())\n .sort((a, b) => b[1].totalCost - a[1].totalCost);\n\n this.CostAttributionRows = sorted.map(([agentId, entry]) => {\n const segments: CostSegment[] = vendorList.map((vendor, i) => {\n const val = entry.vendorCosts.get(vendor) ?? 0;\n return {\n Label: vendor,\n Value: val,\n Percent: entry.totalCost > 0 ? (val / entry.totalCost) * 100 : 0,\n Color: COST_COLORS[i % COST_COLORS.length]\n };\n }).filter(s => s.Value > 0);\n\n return {\n AgentName: entry.name,\n AgentID: agentId,\n TotalCost: entry.totalCost,\n Segments: segments\n };\n });\n }\n\n private buildRecentRuns(): void {\n // Count prompt runs per agent run\n const promptCountMap = new Map<string, number>();\n for (const pr of this.promptRuns) {\n if (pr.AgentRunID) {\n promptCountMap.set(pr.AgentRunID, (promptCountMap.get(pr.AgentRunID) ?? 0) + 1);\n }\n }\n\n this.RecentRuns = this.agentRuns.slice(0, 100).map(r => ({\n ID: r.ID,\n Agent: r.Agent ?? 'Unknown',\n Status: r.Status,\n StatusClass: this.getStatusClass(r.Status),\n StepCount: promptCountMap.get(r.ID) ?? 0,\n Duration: this.formatDuration(r.StartedAt, r.CompletedAt),\n Cost: this.FormatCurrency(r.TotalCost ?? 0),\n Time: this.formatRelativeTime(r.StartedAt)\n }));\n }\n\n private sortRecentRuns(): void {\n const dir = this.SortDir === 'asc' ? 1 : -1;\n this.RecentRuns.sort((a, b) => {\n switch (this.SortField) {\n case 'Agent': return dir * a.Agent.localeCompare(b.Agent);\n case 'Status': return dir * a.Status.localeCompare(b.Status);\n case 'StepCount': return dir * (a.StepCount - b.StepCount);\n case 'Duration': return dir * a.Duration.localeCompare(b.Duration);\n case 'Cost': return dir * a.Cost.localeCompare(b.Cost);\n case 'Time': return dir * a.Time.localeCompare(b.Time);\n default: return 0;\n }\n });\n }\n\n // ── Helpers ──\n\n private buildDateFilter(field: string): string {\n const now = new Date();\n const ms = this.timeRangeToMs(this.TimeRange);\n const start = new Date(now.getTime() - ms);\n return `${field} >= '${start.toISOString()}'`;\n }\n\n private buildAgentFilter(): string {\n if (this.Filters.Agents.length === 0) return '';\n const ids = this.Filters.Agents.map(id => `'${id}'`).join(',');\n return `AgentID IN (${ids})`;\n }\n\n private buildStatusFilter(): string {\n if (this.Filters.Statuses.length === 0) return '';\n const values = this.Filters.Statuses.map(s => `'${s}'`).join(',');\n return `Status IN (${values})`;\n }\n\n private timeRangeToMs(range: string): number {\n const map: Record<string, number> = {\n '1h': 3600000,\n '6h': 21600000,\n '24h': 86400000,\n '7d': 604800000,\n '30d': 2592000000\n };\n return map[range] ?? 604800000;\n }\n\n private getStatusClass(status: string): string {\n return 'status-pill status-' + status.toLowerCase().replace(/\\s+/g, '');\n }\n\n private formatDuration(startStr: string, endStr: string | null): string {\n if (!endStr) return '--';\n const ms = new Date(endStr).getTime() - new Date(startStr).getTime();\n if (ms < 1000) return ms + 'ms';\n if (ms < 60000) return (ms / 1000).toFixed(1) + 's';\n return (ms / 60000).toFixed(1) + 'm';\n }\n\n private formatRelativeTime(dateStr: string): string {\n const now = Date.now();\n const then = new Date(dateStr).getTime();\n const diffMs = now - then;\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 1) return 'just now';\n if (diffMin < 60) return diffMin + 'm ago';\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24) return diffHr + 'h ago';\n const diffDay = Math.floor(diffHr / 24);\n return diffDay + 'd ago';\n }\n}\n\nexport function LoadAnalyticsAgentRuns() { /* tree-shaking prevention */ }\n"]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview AI Analytics Shell — Resource Component
|
|
3
|
+
*
|
|
4
|
+
* Main resource component for the AI Analytics dashboard. Provides a left
|
|
5
|
+
* navigation panel and content area that switches between analytics sections:
|
|
6
|
+
* Executive Summary, Prompt Runs, Agent Runs, Model Performance, Cost & Budget,
|
|
7
|
+
* Error Analysis, and Usage Patterns.
|
|
8
|
+
*
|
|
9
|
+
* Persists the active section and filter state via UserInfoEngine settings
|
|
10
|
+
* with debounced writes.
|
|
11
|
+
*/
|
|
12
|
+
import { OnInit, OnDestroy } from '@angular/core';
|
|
13
|
+
import { Subject } from 'rxjs';
|
|
14
|
+
import { ResourceData } from '@memberjunction/core-entities';
|
|
15
|
+
import { BaseResourceComponent } from '@memberjunction/ng-shared';
|
|
16
|
+
import { GlobalFilterState } from '../../interfaces/analytics-preferences.interface';
|
|
17
|
+
import * as i0 from "@angular/core";
|
|
18
|
+
interface NavItem {
|
|
19
|
+
Label?: string;
|
|
20
|
+
Icon?: string;
|
|
21
|
+
Key: string;
|
|
22
|
+
}
|
|
23
|
+
export declare class AIAnalyticsResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {
|
|
24
|
+
private readonly USER_SETTINGS_KEY;
|
|
25
|
+
private settingsPersistSubject;
|
|
26
|
+
protected destroy$: Subject<void>;
|
|
27
|
+
private settingsLoaded;
|
|
28
|
+
private cdr;
|
|
29
|
+
ActiveSection: string;
|
|
30
|
+
CurrentTimeRange: string;
|
|
31
|
+
CurrentFilters: GlobalFilterState;
|
|
32
|
+
readonly NavItems: NavItem[];
|
|
33
|
+
ngOnInit(): Promise<void>;
|
|
34
|
+
ngOnDestroy(): void;
|
|
35
|
+
GetResourceDisplayName(data: ResourceData): Promise<string>;
|
|
36
|
+
GetResourceIconClass(data: ResourceData): Promise<string>;
|
|
37
|
+
/** Navigate to a different analytics section */
|
|
38
|
+
OnSectionChange(key: string): void;
|
|
39
|
+
/** Handle time range changes from the filter bar */
|
|
40
|
+
OnTimeRangeChange(range: string): void;
|
|
41
|
+
/** Handle filter changes from the filter bar */
|
|
42
|
+
OnFiltersChange(filters: GlobalFilterState): void;
|
|
43
|
+
private setupSettingsDebounce;
|
|
44
|
+
private loadUserSettings;
|
|
45
|
+
private saveUserSettings;
|
|
46
|
+
private persistUserSettings;
|
|
47
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AIAnalyticsResourceComponent, never>;
|
|
48
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<AIAnalyticsResourceComponent, "app-ai-analytics-resource", never, {}, {}, never, never, false, never>;
|
|
49
|
+
}
|
|
50
|
+
export declare function LoadAIAnalyticsResource(): void;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=ai-analytics-resource.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-analytics-resource.component.d.ts","sourceRoot":"","sources":["../../../../src/AI/components/analytics/ai-analytics-resource.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAgC,MAAM,EAAE,SAAS,EAAU,MAAM,eAAe,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,OAAO,EAAE,YAAY,EAAkB,MAAM,+BAA+B,CAAC;AAE7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAA0B,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;;AAE7G,UAAU,OAAO;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACf;AAED,qBA4Pa,4BAA6B,SAAQ,qBAAsB,YAAW,MAAM,EAAE,SAAS;IAChG,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkC;IACpE,OAAO,CAAC,sBAAsB,CAAuB;IACrD,UAAmB,QAAQ,gBAAuB;IAClD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,GAAG,CAA6B;IAEjC,aAAa,SAAuB;IACpC,gBAAgB,SAAS;IACzB,cAAc,EAAE,iBAAiB,CAKtC;IAEF,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAS1B;IAEI,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/B,WAAW,IAAI,IAAI;IAMb,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAI3D,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/D,gDAAgD;IACzC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IASzC,oDAAoD;IAC7C,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7C,gDAAgD;IACzC,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAOxD,OAAO,CAAC,qBAAqB;YAOf,gBAAgB;IAqB9B,OAAO,CAAC,gBAAgB;YAMV,mBAAmB;yCA1GxB,4BAA4B;2CAA5B,4BAA4B;CAmJxC;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* @fileoverview AI Analytics Shell — Resource Component
|
|
9
|
+
*
|
|
10
|
+
* Main resource component for the AI Analytics dashboard. Provides a left
|
|
11
|
+
* navigation panel and content area that switches between analytics sections:
|
|
12
|
+
* Executive Summary, Prompt Runs, Agent Runs, Model Performance, Cost & Budget,
|
|
13
|
+
* Error Analysis, and Usage Patterns.
|
|
14
|
+
*
|
|
15
|
+
* Persists the active section and filter state via UserInfoEngine settings
|
|
16
|
+
* with debounced writes.
|
|
17
|
+
*/
|
|
18
|
+
import { Component, ChangeDetectorRef, inject } from '@angular/core';
|
|
19
|
+
import { Subject } from 'rxjs';
|
|
20
|
+
import { debounceTime, takeUntil } from 'rxjs/operators';
|
|
21
|
+
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
22
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
23
|
+
import { BaseResourceComponent } from '@memberjunction/ng-shared';
|
|
24
|
+
import * as i0 from "@angular/core";
|
|
25
|
+
import * as i1 from "./executive-summary/executive-summary.component";
|
|
26
|
+
import * as i2 from "./prompt-runs/prompt-run-analysis.component";
|
|
27
|
+
import * as i3 from "./agent-runs/agent-run-analysis.component";
|
|
28
|
+
import * as i4 from "./model-performance/model-performance.component";
|
|
29
|
+
import * as i5 from "./cost-budget/cost-budget.component";
|
|
30
|
+
import * as i6 from "./error-analysis/error-analysis.component";
|
|
31
|
+
import * as i7 from "./usage-patterns/usage-patterns.component";
|
|
32
|
+
const _forTrack0 = ($index, $item) => $item.Key;
|
|
33
|
+
function AIAnalyticsResourceComponent_For_7_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
34
|
+
i0.ɵɵelement(0, "div", 7);
|
|
35
|
+
} }
|
|
36
|
+
function AIAnalyticsResourceComponent_For_7_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
37
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
38
|
+
i0.ɵɵelementStart(0, "button", 9);
|
|
39
|
+
i0.ɵɵlistener("click", function AIAnalyticsResourceComponent_For_7_Conditional_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const item_r2 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnSectionChange(item_r2.Key)); });
|
|
40
|
+
i0.ɵɵelement(1, "i");
|
|
41
|
+
i0.ɵɵelementStart(2, "span");
|
|
42
|
+
i0.ɵɵtext(3);
|
|
43
|
+
i0.ɵɵelementEnd()();
|
|
44
|
+
} if (rf & 2) {
|
|
45
|
+
const item_r2 = i0.ɵɵnextContext().$implicit;
|
|
46
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
47
|
+
i0.ɵɵclassProp("active", ctx_r2.ActiveSection === item_r2.Key);
|
|
48
|
+
i0.ɵɵadvance();
|
|
49
|
+
i0.ɵɵclassMap(item_r2.Icon);
|
|
50
|
+
i0.ɵɵadvance(2);
|
|
51
|
+
i0.ɵɵtextInterpolate(item_r2.Label);
|
|
52
|
+
} }
|
|
53
|
+
function AIAnalyticsResourceComponent_For_7_Template(rf, ctx) { if (rf & 1) {
|
|
54
|
+
i0.ɵɵconditionalCreate(0, AIAnalyticsResourceComponent_For_7_Conditional_0_Template, 1, 0, "div", 7)(1, AIAnalyticsResourceComponent_For_7_Conditional_1_Template, 4, 5, "button", 8);
|
|
55
|
+
} if (rf & 2) {
|
|
56
|
+
const item_r2 = ctx.$implicit;
|
|
57
|
+
i0.ɵɵconditional(item_r2.Key === "divider" ? 0 : 1);
|
|
58
|
+
} }
|
|
59
|
+
function AIAnalyticsResourceComponent_Case_9_Template(rf, ctx) { if (rf & 1) {
|
|
60
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
61
|
+
i0.ɵɵelementStart(0, "app-analytics-executive-summary", 10);
|
|
62
|
+
i0.ɵɵlistener("TimeRangeChange", function AIAnalyticsResourceComponent_Case_9_Template_app_analytics_executive_summary_TimeRangeChange_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnTimeRangeChange($event)); })("FiltersChange", function AIAnalyticsResourceComponent_Case_9_Template_app_analytics_executive_summary_FiltersChange_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnFiltersChange($event)); })("SectionNavigate", function AIAnalyticsResourceComponent_Case_9_Template_app_analytics_executive_summary_SectionNavigate_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnSectionChange($event)); });
|
|
63
|
+
i0.ɵɵelementEnd();
|
|
64
|
+
} if (rf & 2) {
|
|
65
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
66
|
+
i0.ɵɵproperty("TimeRange", ctx_r2.CurrentTimeRange)("Filters", ctx_r2.CurrentFilters);
|
|
67
|
+
} }
|
|
68
|
+
function AIAnalyticsResourceComponent_Case_10_Template(rf, ctx) { if (rf & 1) {
|
|
69
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
70
|
+
i0.ɵɵelementStart(0, "app-analytics-prompt-runs", 11);
|
|
71
|
+
i0.ɵɵlistener("TimeRangeChange", function AIAnalyticsResourceComponent_Case_10_Template_app_analytics_prompt_runs_TimeRangeChange_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnTimeRangeChange($event)); })("FiltersChange", function AIAnalyticsResourceComponent_Case_10_Template_app_analytics_prompt_runs_FiltersChange_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnFiltersChange($event)); });
|
|
72
|
+
i0.ɵɵelementEnd();
|
|
73
|
+
} if (rf & 2) {
|
|
74
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
75
|
+
i0.ɵɵproperty("TimeRange", ctx_r2.CurrentTimeRange)("Filters", ctx_r2.CurrentFilters);
|
|
76
|
+
} }
|
|
77
|
+
function AIAnalyticsResourceComponent_Case_11_Template(rf, ctx) { if (rf & 1) {
|
|
78
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
79
|
+
i0.ɵɵelementStart(0, "app-analytics-agent-runs", 12);
|
|
80
|
+
i0.ɵɵlistener("TimeRangeChange", function AIAnalyticsResourceComponent_Case_11_Template_app_analytics_agent_runs_TimeRangeChange_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnTimeRangeChange($event)); });
|
|
81
|
+
i0.ɵɵelementEnd();
|
|
82
|
+
} if (rf & 2) {
|
|
83
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
84
|
+
i0.ɵɵproperty("TimeRange", ctx_r2.CurrentTimeRange);
|
|
85
|
+
} }
|
|
86
|
+
function AIAnalyticsResourceComponent_Case_12_Template(rf, ctx) { if (rf & 1) {
|
|
87
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
88
|
+
i0.ɵɵelementStart(0, "app-analytics-model-performance", 12);
|
|
89
|
+
i0.ɵɵlistener("TimeRangeChange", function AIAnalyticsResourceComponent_Case_12_Template_app_analytics_model_performance_TimeRangeChange_0_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnTimeRangeChange($event)); });
|
|
90
|
+
i0.ɵɵelementEnd();
|
|
91
|
+
} if (rf & 2) {
|
|
92
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
93
|
+
i0.ɵɵproperty("TimeRange", ctx_r2.CurrentTimeRange);
|
|
94
|
+
} }
|
|
95
|
+
function AIAnalyticsResourceComponent_Case_13_Template(rf, ctx) { if (rf & 1) {
|
|
96
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
97
|
+
i0.ɵɵelementStart(0, "app-analytics-cost-budget", 11);
|
|
98
|
+
i0.ɵɵlistener("TimeRangeChange", function AIAnalyticsResourceComponent_Case_13_Template_app_analytics_cost_budget_TimeRangeChange_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnTimeRangeChange($event)); })("FiltersChange", function AIAnalyticsResourceComponent_Case_13_Template_app_analytics_cost_budget_FiltersChange_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnFiltersChange($event)); });
|
|
99
|
+
i0.ɵɵelementEnd();
|
|
100
|
+
} if (rf & 2) {
|
|
101
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
102
|
+
i0.ɵɵproperty("TimeRange", ctx_r2.CurrentTimeRange)("Filters", ctx_r2.CurrentFilters);
|
|
103
|
+
} }
|
|
104
|
+
function AIAnalyticsResourceComponent_Case_14_Template(rf, ctx) { if (rf & 1) {
|
|
105
|
+
i0.ɵɵelement(0, "app-analytics-error-analysis", 5);
|
|
106
|
+
} if (rf & 2) {
|
|
107
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
108
|
+
i0.ɵɵproperty("TimeRange", ctx_r2.CurrentTimeRange)("Filters", ctx_r2.CurrentFilters);
|
|
109
|
+
} }
|
|
110
|
+
function AIAnalyticsResourceComponent_Case_15_Template(rf, ctx) { if (rf & 1) {
|
|
111
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
112
|
+
i0.ɵɵelementStart(0, "app-analytics-usage-patterns", 12);
|
|
113
|
+
i0.ɵɵlistener("TimeRangeChange", function AIAnalyticsResourceComponent_Case_15_Template_app_analytics_usage_patterns_TimeRangeChange_0_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnTimeRangeChange($event)); });
|
|
114
|
+
i0.ɵɵelementEnd();
|
|
115
|
+
} if (rf & 2) {
|
|
116
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
117
|
+
i0.ɵɵproperty("TimeRange", ctx_r2.CurrentTimeRange);
|
|
118
|
+
} }
|
|
119
|
+
let AIAnalyticsResourceComponent = class AIAnalyticsResourceComponent extends BaseResourceComponent {
|
|
120
|
+
USER_SETTINGS_KEY = 'AI.Analytics.UserPreferences';
|
|
121
|
+
settingsPersistSubject = new Subject();
|
|
122
|
+
destroy$ = new Subject();
|
|
123
|
+
settingsLoaded = false;
|
|
124
|
+
cdr = inject(ChangeDetectorRef);
|
|
125
|
+
ActiveSection = 'executive-summary';
|
|
126
|
+
CurrentTimeRange = '24h';
|
|
127
|
+
CurrentFilters = {
|
|
128
|
+
Models: [],
|
|
129
|
+
Agents: [],
|
|
130
|
+
Prompts: [],
|
|
131
|
+
Statuses: []
|
|
132
|
+
};
|
|
133
|
+
NavItems = [
|
|
134
|
+
{ Label: 'Executive Summary', Icon: 'fa-solid fa-gauge-high', Key: 'executive-summary' },
|
|
135
|
+
{ Label: 'Prompt Runs', Icon: 'fa-solid fa-comment-dots', Key: 'prompt-runs' },
|
|
136
|
+
{ Label: 'Agent Runs', Icon: 'fa-solid fa-robot', Key: 'agent-runs' },
|
|
137
|
+
{ Label: 'Model Performance', Icon: 'fa-solid fa-microchip', Key: 'model-performance' },
|
|
138
|
+
{ Key: 'divider' },
|
|
139
|
+
{ Label: 'Cost & Budget', Icon: 'fa-solid fa-coins', Key: 'cost-budget' },
|
|
140
|
+
{ Label: 'Error Analysis', Icon: 'fa-solid fa-triangle-exclamation', Key: 'error-analysis' },
|
|
141
|
+
{ Label: 'Usage Patterns', Icon: 'fa-solid fa-clock', Key: 'usage-patterns' },
|
|
142
|
+
];
|
|
143
|
+
async ngOnInit() {
|
|
144
|
+
super.ngOnInit();
|
|
145
|
+
this.setupSettingsDebounce();
|
|
146
|
+
await this.loadUserSettings();
|
|
147
|
+
this.NotifyLoadComplete();
|
|
148
|
+
}
|
|
149
|
+
ngOnDestroy() {
|
|
150
|
+
super.ngOnDestroy();
|
|
151
|
+
this.destroy$.next();
|
|
152
|
+
this.destroy$.complete();
|
|
153
|
+
}
|
|
154
|
+
async GetResourceDisplayName(data) {
|
|
155
|
+
return 'AI Analytics';
|
|
156
|
+
}
|
|
157
|
+
async GetResourceIconClass(data) {
|
|
158
|
+
return 'fa-solid fa-chart-line';
|
|
159
|
+
}
|
|
160
|
+
/** Navigate to a different analytics section */
|
|
161
|
+
OnSectionChange(key) {
|
|
162
|
+
if (key === 'divider' || key === this.ActiveSection) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
this.ActiveSection = key;
|
|
166
|
+
this.saveUserSettings();
|
|
167
|
+
this.cdr.detectChanges();
|
|
168
|
+
}
|
|
169
|
+
/** Handle time range changes from the filter bar */
|
|
170
|
+
OnTimeRangeChange(range) {
|
|
171
|
+
this.CurrentTimeRange = range;
|
|
172
|
+
this.saveUserSettings();
|
|
173
|
+
}
|
|
174
|
+
/** Handle filter changes from the filter bar */
|
|
175
|
+
OnFiltersChange(filters) {
|
|
176
|
+
this.CurrentFilters = filters;
|
|
177
|
+
this.saveUserSettings();
|
|
178
|
+
}
|
|
179
|
+
// ── Private Helpers ──
|
|
180
|
+
setupSettingsDebounce() {
|
|
181
|
+
this.settingsPersistSubject.pipe(debounceTime(500), takeUntil(this.destroy$)).subscribe(() => this.persistUserSettings());
|
|
182
|
+
}
|
|
183
|
+
async loadUserSettings() {
|
|
184
|
+
try {
|
|
185
|
+
const raw = UserInfoEngine.Instance.GetSetting(this.USER_SETTINGS_KEY);
|
|
186
|
+
if (raw) {
|
|
187
|
+
const prefs = JSON.parse(raw);
|
|
188
|
+
if (prefs.ActiveSection) {
|
|
189
|
+
this.ActiveSection = prefs.ActiveSection;
|
|
190
|
+
}
|
|
191
|
+
if (prefs.ExecutiveSummary?.Filters) {
|
|
192
|
+
this.CurrentFilters = { ...this.CurrentFilters, ...prefs.ExecutiveSummary.Filters };
|
|
193
|
+
}
|
|
194
|
+
if (prefs.ExecutiveSummary?.TimeRange) {
|
|
195
|
+
this.CurrentTimeRange = prefs.ExecutiveSummary.TimeRange;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// Use defaults on parse failure
|
|
201
|
+
}
|
|
202
|
+
this.settingsLoaded = true;
|
|
203
|
+
}
|
|
204
|
+
saveUserSettings() {
|
|
205
|
+
if (this.settingsLoaded) {
|
|
206
|
+
this.settingsPersistSubject.next();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async persistUserSettings() {
|
|
210
|
+
try {
|
|
211
|
+
const prefs = {
|
|
212
|
+
ActiveSection: this.ActiveSection,
|
|
213
|
+
ExecutiveSummary: {
|
|
214
|
+
TimeRange: this.CurrentTimeRange,
|
|
215
|
+
ComparisonEnabled: false,
|
|
216
|
+
Filters: this.CurrentFilters
|
|
217
|
+
},
|
|
218
|
+
PromptRuns: {
|
|
219
|
+
TimeRange: this.CurrentTimeRange,
|
|
220
|
+
Filters: this.CurrentFilters,
|
|
221
|
+
ChartMetric: 'count',
|
|
222
|
+
SortField: 'StartedAt',
|
|
223
|
+
SortDirection: 'desc'
|
|
224
|
+
},
|
|
225
|
+
AgentRuns: {
|
|
226
|
+
TimeRange: this.CurrentTimeRange,
|
|
227
|
+
Filters: {
|
|
228
|
+
Agents: this.CurrentFilters.Agents,
|
|
229
|
+
Statuses: this.CurrentFilters.Statuses
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
ModelPerformance: {
|
|
233
|
+
TimeRange: this.CurrentTimeRange,
|
|
234
|
+
SortBy: 'latency',
|
|
235
|
+
VendorFilter: []
|
|
236
|
+
},
|
|
237
|
+
CostBudget: {
|
|
238
|
+
TimeRange: this.CurrentTimeRange,
|
|
239
|
+
Filters: this.CurrentFilters
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
await UserInfoEngine.Instance.SetSetting(this.USER_SETTINGS_KEY, JSON.stringify(prefs));
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
// Silent failure for settings persistence
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
static ɵfac = /*@__PURE__*/ (() => { let ɵAIAnalyticsResourceComponent_BaseFactory; return function AIAnalyticsResourceComponent_Factory(__ngFactoryType__) { return (ɵAIAnalyticsResourceComponent_BaseFactory || (ɵAIAnalyticsResourceComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AIAnalyticsResourceComponent)))(__ngFactoryType__ || AIAnalyticsResourceComponent); }; })();
|
|
249
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AIAnalyticsResourceComponent, selectors: [["app-ai-analytics-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 16, vars: 1, consts: [[1, "analytics-shell"], [1, "analytics-nav"], [1, "nav-header"], [1, "fa-solid", "fa-chart-line"], [1, "analytics-content"], [3, "TimeRange", "Filters"], [3, "TimeRange"], [1, "nav-divider"], [1, "nav-item", 3, "active"], [1, "nav-item", 3, "click"], [3, "TimeRangeChange", "FiltersChange", "SectionNavigate", "TimeRange", "Filters"], [3, "TimeRangeChange", "FiltersChange", "TimeRange", "Filters"], [3, "TimeRangeChange", "TimeRange"]], template: function AIAnalyticsResourceComponent_Template(rf, ctx) { if (rf & 1) {
|
|
250
|
+
i0.ɵɵelementStart(0, "div", 0)(1, "nav", 1)(2, "div", 2);
|
|
251
|
+
i0.ɵɵelement(3, "i", 3);
|
|
252
|
+
i0.ɵɵelementStart(4, "span");
|
|
253
|
+
i0.ɵɵtext(5, "AI Analytics");
|
|
254
|
+
i0.ɵɵelementEnd()();
|
|
255
|
+
i0.ɵɵrepeaterCreate(6, AIAnalyticsResourceComponent_For_7_Template, 2, 1, null, null, _forTrack0);
|
|
256
|
+
i0.ɵɵelementEnd();
|
|
257
|
+
i0.ɵɵelementStart(8, "div", 4);
|
|
258
|
+
i0.ɵɵconditionalCreate(9, AIAnalyticsResourceComponent_Case_9_Template, 1, 2, "app-analytics-executive-summary", 5)(10, AIAnalyticsResourceComponent_Case_10_Template, 1, 2, "app-analytics-prompt-runs", 5)(11, AIAnalyticsResourceComponent_Case_11_Template, 1, 1, "app-analytics-agent-runs", 6)(12, AIAnalyticsResourceComponent_Case_12_Template, 1, 1, "app-analytics-model-performance", 6)(13, AIAnalyticsResourceComponent_Case_13_Template, 1, 2, "app-analytics-cost-budget", 5)(14, AIAnalyticsResourceComponent_Case_14_Template, 1, 2, "app-analytics-error-analysis", 5)(15, AIAnalyticsResourceComponent_Case_15_Template, 1, 1, "app-analytics-usage-patterns", 6);
|
|
259
|
+
i0.ɵɵelementEnd()();
|
|
260
|
+
} if (rf & 2) {
|
|
261
|
+
let tmp_1_0;
|
|
262
|
+
i0.ɵɵadvance(6);
|
|
263
|
+
i0.ɵɵrepeater(ctx.NavItems);
|
|
264
|
+
i0.ɵɵadvance(3);
|
|
265
|
+
i0.ɵɵconditional((tmp_1_0 = ctx.ActiveSection) === "executive-summary" ? 9 : tmp_1_0 === "prompt-runs" ? 10 : tmp_1_0 === "agent-runs" ? 11 : tmp_1_0 === "model-performance" ? 12 : tmp_1_0 === "cost-budget" ? 13 : tmp_1_0 === "error-analysis" ? 14 : tmp_1_0 === "usage-patterns" ? 15 : -1);
|
|
266
|
+
} }, dependencies: [i1.AnalyticsExecutiveSummaryComponent, i2.AnalyticsPromptRunsComponent, i3.AnalyticsAgentRunsComponent, i4.AnalyticsModelPerformanceComponent, i5.AnalyticsCostBudgetComponent, i6.AnalyticsErrorAnalysisComponent, i7.AnalyticsUsagePatternsComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n }\n\n .analytics-shell[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n background: var(--mj-bg-page);\n }\n\n \n\n\n .analytics-nav[_ngcontent-%COMP%] {\n width: 220px;\n min-width: 220px;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n padding: 12px 0;\n overflow-y: auto;\n }\n\n .nav-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 18px 16px;\n font-size: 15px;\n font-weight: 700;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-subtle);\n margin-bottom: 8px;\n }\n\n .nav-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 16px;\n }\n\n .nav-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 18px;\n border: none;\n border-left: 3px solid transparent;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s, color 0.15s, border-color 0.15s;\n text-align: left;\n width: 100%;\n }\n\n .nav-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n\n .nav-item.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-left-color: var(--mj-brand-primary);\n font-weight: 600;\n }\n\n .nav-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 18px;\n text-align: center;\n font-size: 14px;\n }\n\n .nav-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: var(--mj-border-subtle);\n margin: 8px 18px;\n }\n\n \n\n\n .analytics-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 24px;\n }\n\n \n\n\n .section-placeholder[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 80px 24px;\n color: var(--mj-text-muted);\n }\n\n .placeholder-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-brand-primary);\n opacity: 0.4;\n }\n\n .section-placeholder[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 8px;\n }\n\n .section-placeholder[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin: 0;\n max-width: 420px;\n }\n\n \n\n\n @media (max-width: 768px) {\n .analytics-shell[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .analytics-nav[_ngcontent-%COMP%] {\n width: 100%;\n min-width: unset;\n flex-direction: row;\n overflow-x: auto;\n overflow-y: hidden;\n border-right: none;\n border-bottom: 1px solid var(--mj-border-default);\n padding: 0 8px;\n gap: 2px;\n }\n\n .nav-header[_ngcontent-%COMP%] {\n display: none;\n }\n\n .nav-divider[_ngcontent-%COMP%] {\n width: 1px;\n height: 28px;\n margin: auto 4px;\n }\n\n .nav-item[_ngcontent-%COMP%] {\n white-space: nowrap;\n border-left: none;\n border-bottom: 3px solid transparent;\n padding: 10px 14px;\n }\n\n .nav-item.active[_ngcontent-%COMP%] {\n border-left-color: transparent;\n border-bottom-color: var(--mj-brand-primary);\n }\n\n .analytics-content[_ngcontent-%COMP%] {\n padding: 16px;\n }\n }"] });
|
|
267
|
+
};
|
|
268
|
+
AIAnalyticsResourceComponent = __decorate([
|
|
269
|
+
RegisterClass(BaseResourceComponent, 'AIAnalyticsResource')
|
|
270
|
+
], AIAnalyticsResourceComponent);
|
|
271
|
+
export { AIAnalyticsResourceComponent };
|
|
272
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AIAnalyticsResourceComponent, [{
|
|
273
|
+
type: Component,
|
|
274
|
+
args: [{ standalone: false, selector: 'app-ai-analytics-resource', template: `
|
|
275
|
+
<div class="analytics-shell">
|
|
276
|
+
<nav class="analytics-nav">
|
|
277
|
+
<div class="nav-header">
|
|
278
|
+
<i class="fa-solid fa-chart-line"></i>
|
|
279
|
+
<span>AI Analytics</span>
|
|
280
|
+
</div>
|
|
281
|
+
@for (item of NavItems; track item.Key) {
|
|
282
|
+
@if (item.Key === 'divider') {
|
|
283
|
+
<div class="nav-divider"></div>
|
|
284
|
+
} @else {
|
|
285
|
+
<button
|
|
286
|
+
class="nav-item"
|
|
287
|
+
[class.active]="ActiveSection === item.Key"
|
|
288
|
+
(click)="OnSectionChange(item.Key)">
|
|
289
|
+
<i [class]="item.Icon"></i>
|
|
290
|
+
<span>{{ item.Label }}</span>
|
|
291
|
+
</button>
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
</nav>
|
|
295
|
+
|
|
296
|
+
<div class="analytics-content">
|
|
297
|
+
@switch (ActiveSection) {
|
|
298
|
+
@case ('executive-summary') {
|
|
299
|
+
<app-analytics-executive-summary
|
|
300
|
+
[TimeRange]="CurrentTimeRange"
|
|
301
|
+
[Filters]="CurrentFilters"
|
|
302
|
+
(TimeRangeChange)="OnTimeRangeChange($event)"
|
|
303
|
+
(FiltersChange)="OnFiltersChange($event)"
|
|
304
|
+
(SectionNavigate)="OnSectionChange($event)"
|
|
305
|
+
></app-analytics-executive-summary>
|
|
306
|
+
}
|
|
307
|
+
@case ('prompt-runs') {
|
|
308
|
+
<app-analytics-prompt-runs
|
|
309
|
+
[TimeRange]="CurrentTimeRange"
|
|
310
|
+
[Filters]="CurrentFilters"
|
|
311
|
+
(TimeRangeChange)="OnTimeRangeChange($event)"
|
|
312
|
+
(FiltersChange)="OnFiltersChange($event)"
|
|
313
|
+
></app-analytics-prompt-runs>
|
|
314
|
+
}
|
|
315
|
+
@case ('agent-runs') {
|
|
316
|
+
<app-analytics-agent-runs
|
|
317
|
+
[TimeRange]="CurrentTimeRange"
|
|
318
|
+
(TimeRangeChange)="OnTimeRangeChange($event)"
|
|
319
|
+
></app-analytics-agent-runs>
|
|
320
|
+
}
|
|
321
|
+
@case ('model-performance') {
|
|
322
|
+
<app-analytics-model-performance
|
|
323
|
+
[TimeRange]="CurrentTimeRange"
|
|
324
|
+
(TimeRangeChange)="OnTimeRangeChange($event)"
|
|
325
|
+
></app-analytics-model-performance>
|
|
326
|
+
}
|
|
327
|
+
@case ('cost-budget') {
|
|
328
|
+
<app-analytics-cost-budget
|
|
329
|
+
[TimeRange]="CurrentTimeRange"
|
|
330
|
+
[Filters]="CurrentFilters"
|
|
331
|
+
(TimeRangeChange)="OnTimeRangeChange($event)"
|
|
332
|
+
(FiltersChange)="OnFiltersChange($event)"
|
|
333
|
+
></app-analytics-cost-budget>
|
|
334
|
+
}
|
|
335
|
+
@case ('error-analysis') {
|
|
336
|
+
<app-analytics-error-analysis
|
|
337
|
+
[TimeRange]="CurrentTimeRange"
|
|
338
|
+
[Filters]="CurrentFilters"
|
|
339
|
+
></app-analytics-error-analysis>
|
|
340
|
+
}
|
|
341
|
+
@case ('usage-patterns') {
|
|
342
|
+
<app-analytics-usage-patterns
|
|
343
|
+
[TimeRange]="CurrentTimeRange"
|
|
344
|
+
(TimeRangeChange)="OnTimeRangeChange($event)"
|
|
345
|
+
></app-analytics-usage-patterns>
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
</div>
|
|
349
|
+
</div>
|
|
350
|
+
`, styles: ["\n :host {\n display: block;\n height: 100%;\n }\n\n .analytics-shell {\n display: flex;\n height: 100%;\n background: var(--mj-bg-page);\n }\n\n /* \u2500\u2500 Left Navigation \u2500\u2500 */\n\n .analytics-nav {\n width: 220px;\n min-width: 220px;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n padding: 12px 0;\n overflow-y: auto;\n }\n\n .nav-header {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 18px 16px;\n font-size: 15px;\n font-weight: 700;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-subtle);\n margin-bottom: 8px;\n }\n\n .nav-header i {\n color: var(--mj-brand-primary);\n font-size: 16px;\n }\n\n .nav-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 18px;\n border: none;\n border-left: 3px solid transparent;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s, color 0.15s, border-color 0.15s;\n text-align: left;\n width: 100%;\n }\n\n .nav-item:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n\n .nav-item.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-left-color: var(--mj-brand-primary);\n font-weight: 600;\n }\n\n .nav-item i {\n width: 18px;\n text-align: center;\n font-size: 14px;\n }\n\n .nav-divider {\n height: 1px;\n background: var(--mj-border-subtle);\n margin: 8px 18px;\n }\n\n /* \u2500\u2500 Content Area \u2500\u2500 */\n\n .analytics-content {\n flex: 1;\n overflow-y: auto;\n padding: 24px;\n }\n\n /* \u2500\u2500 Section Placeholders \u2500\u2500 */\n\n .section-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 80px 24px;\n color: var(--mj-text-muted);\n }\n\n .placeholder-icon {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-brand-primary);\n opacity: 0.4;\n }\n\n .section-placeholder h2 {\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 8px;\n }\n\n .section-placeholder p {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin: 0;\n max-width: 420px;\n }\n\n /* \u2500\u2500 Responsive: collapse nav to horizontal strip \u2500\u2500 */\n\n @media (max-width: 768px) {\n .analytics-shell {\n flex-direction: column;\n }\n\n .analytics-nav {\n width: 100%;\n min-width: unset;\n flex-direction: row;\n overflow-x: auto;\n overflow-y: hidden;\n border-right: none;\n border-bottom: 1px solid var(--mj-border-default);\n padding: 0 8px;\n gap: 2px;\n }\n\n .nav-header {\n display: none;\n }\n\n .nav-divider {\n width: 1px;\n height: 28px;\n margin: auto 4px;\n }\n\n .nav-item {\n white-space: nowrap;\n border-left: none;\n border-bottom: 3px solid transparent;\n padding: 10px 14px;\n }\n\n .nav-item.active {\n border-left-color: transparent;\n border-bottom-color: var(--mj-brand-primary);\n }\n\n .analytics-content {\n padding: 16px;\n }\n }\n "] }]
|
|
351
|
+
}], null, null); })();
|
|
352
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AIAnalyticsResourceComponent, { className: "AIAnalyticsResourceComponent", filePath: "src/AI/components/analytics/ai-analytics-resource.component.ts", lineNumber: 279 }); })();
|
|
353
|
+
export function LoadAIAnalyticsResource() {
|
|
354
|
+
// Prevents tree-shaking of the @RegisterClass decorator
|
|
355
|
+
}
|
|
356
|
+
//# sourceMappingURL=ai-analytics-resource.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-analytics-resource.component.js","sourceRoot":"","sources":["../../../../src/AI/components/analytics/ai-analytics-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview AI Analytics Shell — Resource Component\n *\n * Main resource component for the AI Analytics dashboard. Provides a left\n * navigation panel and content area that switches between analytics sections:\n * Executive Summary, Prompt Runs, Agent Runs, Model Performance, Cost & Budget,\n * Error Analysis, and Usage Patterns.\n *\n * Persists the active section and filter state via UserInfoEngine settings\n * with debounced writes.\n */\n\nimport { Component, ChangeDetectorRef, OnInit, OnDestroy, inject } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\nimport { ResourceData, UserInfoEngine } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { AIAnalyticsPreferences, GlobalFilterState } from '../../interfaces/analytics-preferences.interface';\n\ninterface NavItem {\n Label?: string;\n Icon?: string;\n Key: string;\n}\n\n@RegisterClass(BaseResourceComponent, 'AIAnalyticsResource')\n@Component({\n standalone: false,\n selector: 'app-ai-analytics-resource',\n template: `\n <div class=\"analytics-shell\">\n <nav class=\"analytics-nav\">\n <div class=\"nav-header\">\n <i class=\"fa-solid fa-chart-line\"></i>\n <span>AI Analytics</span>\n </div>\n @for (item of NavItems; track item.Key) {\n @if (item.Key === 'divider') {\n <div class=\"nav-divider\"></div>\n } @else {\n <button\n class=\"nav-item\"\n [class.active]=\"ActiveSection === item.Key\"\n (click)=\"OnSectionChange(item.Key)\">\n <i [class]=\"item.Icon\"></i>\n <span>{{ item.Label }}</span>\n </button>\n }\n }\n </nav>\n\n <div class=\"analytics-content\">\n @switch (ActiveSection) {\n @case ('executive-summary') {\n <app-analytics-executive-summary\n [TimeRange]=\"CurrentTimeRange\"\n [Filters]=\"CurrentFilters\"\n (TimeRangeChange)=\"OnTimeRangeChange($event)\"\n (FiltersChange)=\"OnFiltersChange($event)\"\n (SectionNavigate)=\"OnSectionChange($event)\"\n ></app-analytics-executive-summary>\n }\n @case ('prompt-runs') {\n <app-analytics-prompt-runs\n [TimeRange]=\"CurrentTimeRange\"\n [Filters]=\"CurrentFilters\"\n (TimeRangeChange)=\"OnTimeRangeChange($event)\"\n (FiltersChange)=\"OnFiltersChange($event)\"\n ></app-analytics-prompt-runs>\n }\n @case ('agent-runs') {\n <app-analytics-agent-runs\n [TimeRange]=\"CurrentTimeRange\"\n (TimeRangeChange)=\"OnTimeRangeChange($event)\"\n ></app-analytics-agent-runs>\n }\n @case ('model-performance') {\n <app-analytics-model-performance\n [TimeRange]=\"CurrentTimeRange\"\n (TimeRangeChange)=\"OnTimeRangeChange($event)\"\n ></app-analytics-model-performance>\n }\n @case ('cost-budget') {\n <app-analytics-cost-budget\n [TimeRange]=\"CurrentTimeRange\"\n [Filters]=\"CurrentFilters\"\n (TimeRangeChange)=\"OnTimeRangeChange($event)\"\n (FiltersChange)=\"OnFiltersChange($event)\"\n ></app-analytics-cost-budget>\n }\n @case ('error-analysis') {\n <app-analytics-error-analysis\n [TimeRange]=\"CurrentTimeRange\"\n [Filters]=\"CurrentFilters\"\n ></app-analytics-error-analysis>\n }\n @case ('usage-patterns') {\n <app-analytics-usage-patterns\n [TimeRange]=\"CurrentTimeRange\"\n (TimeRangeChange)=\"OnTimeRangeChange($event)\"\n ></app-analytics-usage-patterns>\n }\n }\n </div>\n </div>\n `,\n styles: [`\n :host {\n display: block;\n height: 100%;\n }\n\n .analytics-shell {\n display: flex;\n height: 100%;\n background: var(--mj-bg-page);\n }\n\n /* ── Left Navigation ── */\n\n .analytics-nav {\n width: 220px;\n min-width: 220px;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n padding: 12px 0;\n overflow-y: auto;\n }\n\n .nav-header {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 18px 16px;\n font-size: 15px;\n font-weight: 700;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-subtle);\n margin-bottom: 8px;\n }\n\n .nav-header i {\n color: var(--mj-brand-primary);\n font-size: 16px;\n }\n\n .nav-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 18px;\n border: none;\n border-left: 3px solid transparent;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s, color 0.15s, border-color 0.15s;\n text-align: left;\n width: 100%;\n }\n\n .nav-item:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n\n .nav-item.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-left-color: var(--mj-brand-primary);\n font-weight: 600;\n }\n\n .nav-item i {\n width: 18px;\n text-align: center;\n font-size: 14px;\n }\n\n .nav-divider {\n height: 1px;\n background: var(--mj-border-subtle);\n margin: 8px 18px;\n }\n\n /* ── Content Area ── */\n\n .analytics-content {\n flex: 1;\n overflow-y: auto;\n padding: 24px;\n }\n\n /* ── Section Placeholders ── */\n\n .section-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 80px 24px;\n color: var(--mj-text-muted);\n }\n\n .placeholder-icon {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-brand-primary);\n opacity: 0.4;\n }\n\n .section-placeholder h2 {\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 8px;\n }\n\n .section-placeholder p {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin: 0;\n max-width: 420px;\n }\n\n /* ── Responsive: collapse nav to horizontal strip ── */\n\n @media (max-width: 768px) {\n .analytics-shell {\n flex-direction: column;\n }\n\n .analytics-nav {\n width: 100%;\n min-width: unset;\n flex-direction: row;\n overflow-x: auto;\n overflow-y: hidden;\n border-right: none;\n border-bottom: 1px solid var(--mj-border-default);\n padding: 0 8px;\n gap: 2px;\n }\n\n .nav-header {\n display: none;\n }\n\n .nav-divider {\n width: 1px;\n height: 28px;\n margin: auto 4px;\n }\n\n .nav-item {\n white-space: nowrap;\n border-left: none;\n border-bottom: 3px solid transparent;\n padding: 10px 14px;\n }\n\n .nav-item.active {\n border-left-color: transparent;\n border-bottom-color: var(--mj-brand-primary);\n }\n\n .analytics-content {\n padding: 16px;\n }\n }\n `]\n})\nexport class AIAnalyticsResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n private readonly USER_SETTINGS_KEY = 'AI.Analytics.UserPreferences';\n private settingsPersistSubject = new Subject<void>();\n protected override destroy$ = new Subject<void>();\n private settingsLoaded = false;\n private cdr = inject(ChangeDetectorRef);\n\n public ActiveSection = 'executive-summary';\n public CurrentTimeRange = '24h';\n public CurrentFilters: GlobalFilterState = {\n Models: [],\n Agents: [],\n Prompts: [],\n Statuses: []\n };\n\n readonly NavItems: NavItem[] = [\n { Label: 'Executive Summary', Icon: 'fa-solid fa-gauge-high', Key: 'executive-summary' },\n { Label: 'Prompt Runs', Icon: 'fa-solid fa-comment-dots', Key: 'prompt-runs' },\n { Label: 'Agent Runs', Icon: 'fa-solid fa-robot', Key: 'agent-runs' },\n { Label: 'Model Performance', Icon: 'fa-solid fa-microchip', Key: 'model-performance' },\n { Key: 'divider' },\n { Label: 'Cost & Budget', Icon: 'fa-solid fa-coins', Key: 'cost-budget' },\n { Label: 'Error Analysis', Icon: 'fa-solid fa-triangle-exclamation', Key: 'error-analysis' },\n { Label: 'Usage Patterns', Icon: 'fa-solid fa-clock', Key: 'usage-patterns' },\n ];\n\n async ngOnInit(): Promise<void> {\n super.ngOnInit();\n this.setupSettingsDebounce();\n await this.loadUserSettings();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void {\n super.ngOnDestroy();\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'AI Analytics';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-chart-line';\n }\n\n /** Navigate to a different analytics section */\n public OnSectionChange(key: string): void {\n if (key === 'divider' || key === this.ActiveSection) {\n return;\n }\n this.ActiveSection = key;\n this.saveUserSettings();\n this.cdr.detectChanges();\n }\n\n /** Handle time range changes from the filter bar */\n public OnTimeRangeChange(range: string): void {\n this.CurrentTimeRange = range;\n this.saveUserSettings();\n }\n\n /** Handle filter changes from the filter bar */\n public OnFiltersChange(filters: GlobalFilterState): void {\n this.CurrentFilters = filters;\n this.saveUserSettings();\n }\n\n // ── Private Helpers ──\n\n private setupSettingsDebounce(): void {\n this.settingsPersistSubject.pipe(\n debounceTime(500),\n takeUntil(this.destroy$)\n ).subscribe(() => this.persistUserSettings());\n }\n\n private async loadUserSettings(): Promise<void> {\n try {\n const raw = UserInfoEngine.Instance.GetSetting(this.USER_SETTINGS_KEY);\n if (raw) {\n const prefs: AIAnalyticsPreferences = JSON.parse(raw);\n if (prefs.ActiveSection) {\n this.ActiveSection = prefs.ActiveSection;\n }\n if (prefs.ExecutiveSummary?.Filters) {\n this.CurrentFilters = { ...this.CurrentFilters, ...prefs.ExecutiveSummary.Filters };\n }\n if (prefs.ExecutiveSummary?.TimeRange) {\n this.CurrentTimeRange = prefs.ExecutiveSummary.TimeRange;\n }\n }\n } catch {\n // Use defaults on parse failure\n }\n this.settingsLoaded = true;\n }\n\n private saveUserSettings(): void {\n if (this.settingsLoaded) {\n this.settingsPersistSubject.next();\n }\n }\n\n private async persistUserSettings(): Promise<void> {\n try {\n const prefs: AIAnalyticsPreferences = {\n ActiveSection: this.ActiveSection,\n ExecutiveSummary: {\n TimeRange: this.CurrentTimeRange,\n ComparisonEnabled: false,\n Filters: this.CurrentFilters\n },\n PromptRuns: {\n TimeRange: this.CurrentTimeRange,\n Filters: this.CurrentFilters,\n ChartMetric: 'count',\n SortField: 'StartedAt',\n SortDirection: 'desc'\n },\n AgentRuns: {\n TimeRange: this.CurrentTimeRange,\n Filters: {\n Agents: this.CurrentFilters.Agents,\n Statuses: this.CurrentFilters.Statuses\n }\n },\n ModelPerformance: {\n TimeRange: this.CurrentTimeRange,\n SortBy: 'latency',\n VendorFilter: []\n },\n CostBudget: {\n TimeRange: this.CurrentTimeRange,\n Filters: this.CurrentFilters\n }\n };\n await UserInfoEngine.Instance.SetSetting(\n this.USER_SETTINGS_KEY,\n JSON.stringify(prefs)\n );\n } catch {\n // Silent failure for settings persistence\n }\n }\n}\n\nexport function LoadAIAnalyticsResource(): void {\n // Prevents tree-shaking of the @RegisterClass decorator\n}\n"]}
|