@memberjunction/ng-explorer-core 5.43.0 → 5.44.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/generated/lazy-feature-config.d.ts +1 -1
- package/dist/generated/lazy-feature-config.d.ts.map +1 -1
- package/dist/generated/lazy-feature-config.js +11 -3
- package/dist/generated/lazy-feature-config.js.map +1 -1
- package/dist/lib/about/about-dialog.component.d.ts +0 -1
- package/dist/lib/about/about-dialog.component.d.ts.map +1 -1
- package/dist/lib/about/about-dialog.component.js +217 -218
- package/dist/lib/about/about-dialog.component.js.map +1 -1
- package/dist/lib/command-palette/command-palette.component.js +8 -14
- package/dist/lib/command-palette/command-palette.component.js.map +1 -1
- package/dist/lib/conversation-feedback/conversation-feedback.js +66 -73
- package/dist/lib/conversation-feedback/conversation-feedback.js.map +1 -1
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +35 -45
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +2 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +14 -8
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +9 -8
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.js +35 -43
- package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts +10 -2
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js +19 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts +1 -0
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +3 -2
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/shell.module.d.ts +1 -1
- package/dist/lib/shell/shell.module.d.ts.map +1 -1
- package/dist/lib/shell/shell.module.js +4 -1
- package/dist/lib/shell/shell.module.js.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +5 -7
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js +17 -27
- package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts +6 -2
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.js +48 -57
- package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
- package/dist/lib/single-search-result/single-search-result.component.js +17 -22
- package/dist/lib/single-search-result/single-search-result.component.js.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.js +60 -75
- package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +12 -5
- package/dist/module.js.map +1 -1
- package/package.json +47 -47
- package/dist/lib/__tests__/explorer-core.test.d.ts +0 -2
- package/dist/lib/__tests__/explorer-core.test.d.ts.map +0 -1
- package/dist/lib/__tests__/explorer-core.test.js +0 -229
- package/dist/lib/__tests__/explorer-core.test.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-feedback.js","sourceRoot":"","sources":["../../../src/lib/conversation-feedback/conversation-feedback.ts","../../../src/lib/conversation-feedback/conversation-feedback.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, ChangeDetectorRef, HostListener, inject } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RunQuery } from '@memberjunction/core';\nimport { ApplicationManager } from '@memberjunction/ng-base-application';\n\nexport interface FeedbackRow {\n ratingID: string;\n rating: number;\n comments: string | null;\n createdAt: string;\n raterName: string | null;\n raterEmail: string | null;\n conversationDetailID: string;\n conversationID: string | null;\n conversationName: string | null;\n messageText: string | null;\n messageSnippet: string | null;\n messageRole: string | null;\n agentID: string | null;\n agentName: string | null;\n}\n\nexport type RatingBand = 'all' | 'high' | 'mid' | 'low';\nexport type DateRange = 'all' | '1d' | '7d' | '30d' | '90d';\n\n@Component({\n standalone: false,\n selector: 'mj-conversation-feedback',\n templateUrl: './conversation-feedback.html',\n styleUrls: ['./conversation-feedback.css']\n})\n@RegisterClass(BaseResourceComponent, 'ConversationFeedbackResource')\nexport class ConversationFeedbackResource extends BaseResourceComponent implements OnInit {\n isInitializing = true;\n loading = false;\n statsLoading = false;\n error: string | null = null;\n\n ratingBand: RatingBand = 'all';\n dateRange: DateRange = '7d';\n searchTerm = '';\n\n rows: FeedbackRow[] = [];\n totalRowCount = 0;\n\n pageSize: number = 10;\n currentPage: number = 1;\n readonly pageSizeOptions: number[] = [10, 25, 50, 100];\n\n stats = { total: 0, avgRating: 0, percentPositive: 0, percentNegative: 0 };\n\n selectedRow: FeedbackRow | null = null;\n\n private searchDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n private cdr = inject(ChangeDetectorRef);\n private appManager = inject(ApplicationManager);\n\n async GetResourceDisplayName(): Promise<string> {\n return 'Agent Feedback';\n }\n\n async GetResourceIconClass(): Promise<string> {\n return 'fa-solid fa-comment-dots';\n }\n\n override async ngOnInit(): Promise<void> {\n this.isInitializing = false;\n this.cdr.detectChanges();\n await this.applyFilters();\n this.NotifyLoadComplete();\n }\n\n /** Manual refresh from the page header — same path as a filter change. */\n async loadFeedback(): Promise<void> {\n await this.applyFilters();\n }\n\n setBand(band: RatingBand): void {\n if (this.ratingBand === band) return;\n this.ratingBand = band;\n this.currentPage = 1;\n void this.applyFilters();\n }\n\n setDateRange(range: DateRange): void {\n if (this.dateRange === range) return;\n this.dateRange = range;\n this.currentPage = 1;\n void this.applyFilters();\n }\n\n /**\n * Search input fires on every keystroke; debounce so we don't slam the\n * server while the user is typing. 250ms is enough to feel responsive\n * without firing on intermediate states.\n */\n onSearchChange(): void {\n if (this.searchDebounceTimer) clearTimeout(this.searchDebounceTimer);\n this.searchDebounceTimer = setTimeout(() => {\n this.currentPage = 1;\n void this.applyFilters();\n }, 250);\n }\n\n onPageChange(event: { PageNumber: number; PageSize: number; StartRow: number }): void {\n if (event.PageNumber === this.currentPage) return;\n this.currentPage = event.PageNumber;\n void this.loadRows();\n }\n\n onPageSizeChange(size: number): void {\n const next = Number(size);\n if (!next || next === this.pageSize) return;\n this.pageSize = next;\n this.currentPage = 1;\n void this.loadRows();\n }\n\n openDrawer(row: FeedbackRow): void {\n this.selectedRow = row;\n this.cdr.detectChanges();\n }\n\n closeDrawer(): void {\n this.selectedRow = null;\n this.cdr.detectChanges();\n }\n\n async openConversation(): Promise<void> {\n if (!this.selectedRow?.conversationID) return;\n const conversationID = this.selectedRow.conversationID;\n\n // The Chat app owns the Conversations nav item; the active app (Agent\n // Feedback) does not, so we must target Chat explicitly. Fall back to\n // scanning all apps for a nav item whose DriverClass is the chat resource.\n let appId: string | undefined = this.appManager.GetAppByName('Chat')?.ID;\n let navItemLabel = 'Conversations';\n\n if (!appId) {\n for (const app of this.appManager.GetAllApps()) {\n const navItems = await app.GetNavItems();\n const match = navItems.find(n => (n as any).DriverClass === 'ChatConversationsResource');\n if (match) {\n appId = app.ID;\n navItemLabel = match.Label;\n break;\n }\n }\n }\n\n if (!appId) {\n this.error = 'Could not find a Chat application to open this conversation in.';\n this.cdr.detectChanges();\n return;\n }\n\n this.closeDrawer();\n await this.navigationService.OpenNavItemByName(navItemLabel, { conversationId: conversationID }, appId);\n }\n\n @HostListener('document:keydown.escape')\n onEscape(): void {\n if (this.selectedRow) this.closeDrawer();\n }\n\n bandClassFor(rating: number): string {\n if (rating >= 8) return 'rating-high';\n if (rating >= 4) return 'rating-mid';\n return 'rating-low';\n }\n\n trackByRatingID = (_: number, row: FeedbackRow): string => row.ratingID;\n\n /** 1-based index of the first row on the current page (0 when empty). */\n get rangeStart(): number {\n if (this.totalRowCount === 0) return 0;\n return (this.currentPage - 1) * this.pageSize + 1;\n }\n\n /** 1-based index of the last row on the current page (clamped to total). */\n get rangeEnd(): number {\n return Math.min(this.currentPage * this.pageSize, this.totalRowCount);\n }\n\n /**\n * True when the filtered set fits on a single page — in this case\n * mj-pagination hides itself, so the footer renders a fallback summary\n * line. When false we let mj-pagination own the bar (it has its own\n * `1-N of M` summary on the left + nav controls on the right).\n */\n get isSinglePage(): boolean {\n if (this.totalRowCount <= 0) return false;\n return Math.ceil(this.totalRowCount / this.pageSize) <= 1;\n }\n\n /**\n * Run both the rows-query (paged) and the stats-query (aggregate) against\n * the current filter state. Called when filters change or on initial load.\n */\n private async applyFilters(): Promise<void> {\n await Promise.all([this.loadRows(), this.loadStats()]);\n }\n\n /**\n * Fetch the current page of rows from the server. The mj-pagination\n * footer reads `totalRowCount` to derive the page count.\n */\n private async loadRows(): Promise<void> {\n this.loading = true;\n this.error = null;\n this.cdr.detectChanges();\n\n try {\n const rq = new RunQuery();\n const result = await rq.RunQuery({\n QueryName: 'ListConversationDetailFeedback',\n CategoryPath: '/MJ/Conversations',\n Parameters: this.buildQueryParameters(),\n StartRow: (this.currentPage - 1) * this.pageSize,\n MaxRows: this.pageSize\n });\n\n if (!result.Success) {\n this.error = result.ErrorMessage || 'Failed to load feedback';\n this.rows = [];\n this.totalRowCount = 0;\n return;\n }\n\n this.rows = (result.Results ?? []).map((r: any) => this.mapRow(r));\n this.totalRowCount = result.TotalRowCount ?? this.rows.length;\n } catch (e: any) {\n this.error = e?.message || 'Failed to load feedback';\n this.rows = [];\n this.totalRowCount = 0;\n } finally {\n this.loading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Aggregate counts over the same filter universe as `loadRows()`. Runs in\n * parallel with the rows query so the stat cards and the table stay in\n * sync after every filter change.\n */\n private async loadStats(): Promise<void> {\n this.statsLoading = true;\n this.cdr.detectChanges();\n\n try {\n const rq = new RunQuery();\n const result = await rq.RunQuery({\n QueryName: 'ListConversationDetailFeedbackStats',\n CategoryPath: '/MJ/Conversations',\n Parameters: this.buildQueryParameters()\n });\n\n const row = (result.Results?.[0] as any) || {};\n const total = Number(row.Total ?? 0);\n const avg = Number(row.AvgRating ?? 0);\n const pos = Number(row.PositiveCount ?? 0);\n const neg = Number(row.NegativeCount ?? 0);\n\n this.stats = {\n total,\n avgRating: total ? Math.round(avg * 10) / 10 : 0,\n percentPositive: total ? Math.round((pos / total) * 100) : 0,\n percentNegative: total ? Math.round((neg / total) * 100) : 0\n };\n } catch (e) {\n // Stats are non-critical — the table is the primary surface. Log and\n // leave the previous stats values in place.\n console.warn('[Feedback] stats query failed', e);\n } finally {\n this.statsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Build the Nunjucks-bound parameter set passed to both queries. Server-side\n * filtering: emit only the keys that actually have a value so the SQL's\n * `{% if X %}` blocks stay inert when filters are at their default.\n */\n private buildQueryParameters(): Record<string, unknown> {\n const params: {\n MinRating?: number;\n MaxRating?: number;\n StartDate?: string;\n SearchText?: string;\n } = {};\n\n if (this.ratingBand === 'high') {\n params.MinRating = 8;\n } else if (this.ratingBand === 'mid') {\n params.MinRating = 4;\n params.MaxRating = 7;\n } else if (this.ratingBand === 'low') {\n params.MaxRating = 3;\n }\n\n const cutoffIso = this.dateRangeCutoffIso();\n if (cutoffIso) {\n params.StartDate = cutoffIso;\n }\n\n const term = this.searchTerm.trim();\n if (term) {\n params.SearchText = term;\n }\n\n return params;\n }\n\n private dateRangeCutoffIso(): string | null {\n if (this.dateRange === 'all') return null;\n const days = this.dateRange === '1d' ? 1\n : this.dateRange === '7d' ? 7\n : this.dateRange === '30d' ? 30\n : 90;\n const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n return cutoff.toISOString();\n }\n\n private mapRow(r: any): FeedbackRow {\n const message: string | null = r.MessageText ?? null;\n const snippet = message\n ? (message.length > 160 ? message.slice(0, 160) + '…' : message)\n : null;\n return {\n ratingID: r.RatingID,\n rating: r.Rating,\n comments: r.Comments ?? null,\n createdAt: r.RatedAt ?? '',\n raterName: r.RaterName ?? null,\n raterEmail: r.RaterEmail ?? null,\n conversationDetailID: r.ConversationDetailID,\n conversationID: r.ConversationID ?? null,\n conversationName: r.ConversationName ?? null,\n messageText: message,\n messageSnippet: snippet,\n messageRole: r.MessageRole ?? null,\n agentID: r.AgentID ?? null,\n agentName: r.AgentName ?? null\n };\n }\n}\n","<div class=\"feedback-container\">\n\n @if (isInitializing) {\n <div class=\"loading-overlay\"><div class=\"spinner\"></div> Loading...</div>\n }\n\n @if (!isInitializing) {\n\n <div class=\"sticky-header\">\n <div class=\"page-header\">\n <div class=\"page-title-area\">\n <div class=\"page-icon\"><i class=\"fa-solid fa-comment-dots\"></i></div>\n <div>\n <h1 class=\"page-title\">Agent Feedback</h1>\n <p class=\"page-subtitle\">User ratings and comments on AI messages</p>\n </div>\n </div>\n <div class=\"page-actions\">\n <button class=\"btn-action\" (click)=\"loadFeedback()\" [disabled]=\"loading\">\n <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"loading\"></i> Refresh\n </button>\n </div>\n </div>\n\n @if (error) {\n <div class=\"error-banner\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n {{ error }}\n <button (click)=\"error = null\" aria-label=\"Dismiss error\">×</button>\n </div>\n }\n\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-total\"><i class=\"fa-solid fa-comment-dots\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.total }}</div>\n <div class=\"stat-label\">Total Ratings</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-avg\"><i class=\"fa-solid fa-star\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.avgRating }}<span class=\"stat-unit\">/10</span></div>\n <div class=\"stat-label\">Avg Rating</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-positive\"><i class=\"fa-solid fa-thumbs-up\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value rating-high-text\">{{ stats.percentPositive }}%</div>\n <div class=\"stat-label\">Positive (8-10)</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-negative\"><i class=\"fa-solid fa-thumbs-down\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value rating-low-text\">{{ stats.percentNegative }}%</div>\n <div class=\"stat-label\">Negative (1-3)</div>\n </div>\n </div>\n </div>\n\n <div class=\"filter-bar\">\n <div class=\"filter-row\">\n <div class=\"filter-group\">\n <span class=\"filter-label\">Date Range</span>\n <div class=\"btn-group\">\n <button class=\"btn-filter\" [class.active]=\"dateRange === '1d'\" (click)=\"setDateRange('1d')\">1d</button>\n <button class=\"btn-filter\" [class.active]=\"dateRange === '7d'\" (click)=\"setDateRange('7d')\">7d</button>\n <button class=\"btn-filter\" [class.active]=\"dateRange === '30d'\" (click)=\"setDateRange('30d')\">30d</button>\n <button class=\"btn-filter\" [class.active]=\"dateRange === '90d'\" (click)=\"setDateRange('90d')\">90d</button>\n <button class=\"btn-filter\" [class.active]=\"dateRange === 'all'\" (click)=\"setDateRange('all')\">All</button>\n </div>\n </div>\n <div class=\"filter-group\">\n <span class=\"filter-label\">Rating Band</span>\n <div class=\"btn-group\">\n <button class=\"btn-filter\" [class.active]=\"ratingBand === 'all'\" (click)=\"setBand('all')\">All</button>\n <button class=\"btn-filter band-high\" [class.active]=\"ratingBand === 'high'\" (click)=\"setBand('high')\">High 8-10</button>\n <button class=\"btn-filter band-mid\" [class.active]=\"ratingBand === 'mid'\" (click)=\"setBand('mid')\">Mid 4-7</button>\n <button class=\"btn-filter band-low\" [class.active]=\"ratingBand === 'low'\" (click)=\"setBand('low')\">Low 1-3</button>\n </div>\n </div>\n <div class=\"filter-group filter-search\">\n <span class=\"filter-label\">Search</span>\n <input\n type=\"text\"\n class=\"input-search\"\n [(ngModel)]=\"searchTerm\"\n (input)=\"onSearchChange()\"\n placeholder=\"Search comments, message, agent, rater...\" />\n </div>\n </div>\n <div class=\"diagnostic-line\">\n {{ totalRowCount }} {{ totalRowCount === 1 ? 'rating' : 'ratings' }} match the current filters\n </div>\n </div>\n </div>\n\n <div class=\"scrollable-content\">\n @if (loading) {\n <div class=\"loading-overlay\"><div class=\"spinner\"></div> Loading feedback...</div>\n }\n\n @if (!loading) {\n @if (rows.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comment-slash\"></i>\n <p>No feedback matches the current filters.</p>\n </div>\n } @else {\n <div class=\"feedback-table-wrapper\">\n <table class=\"feedback-table\">\n <thead>\n <tr>\n <th class=\"col-rating\">Rating</th>\n <th class=\"col-comment\">Comments</th>\n <th class=\"col-agent\">Agent</th>\n <th class=\"col-message\">Message</th>\n <th class=\"col-rater\">Rater</th>\n <th class=\"col-when\">When</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rows; track trackByRatingID($index, row)) {\n <tr\n class=\"feedback-row\"\n [class.expanded]=\"selectedRow?.ratingID === row.ratingID\"\n (click)=\"openDrawer(row)\">\n <td class=\"col-rating\">\n <span class=\"rating-badge\" [ngClass]=\"bandClassFor(row.rating)\">\n {{ row.rating }}<small>/10</small>\n </span>\n </td>\n <td class=\"col-comment\">\n @if (row.comments) {\n <div class=\"comment-text clamped\">{{ row.comments }}</div>\n } @else {\n <span class=\"muted\">(no comment)</span>\n }\n </td>\n <td class=\"col-agent\">\n <span class=\"agent-name\">{{ row.agentName || '—' }}</span>\n </td>\n <td class=\"col-message\">\n @if (row.messageSnippet) {\n <span class=\"message-snippet\">{{ row.messageSnippet }}</span>\n } @else {\n <span class=\"muted\">—</span>\n }\n </td>\n <td class=\"col-rater\">\n <div class=\"rater-name\">{{ row.raterName || row.raterEmail || '—' }}</div>\n @if (row.raterEmail && row.raterName) {\n <div class=\"rater-email\">{{ row.raterEmail }}</div>\n }\n </td>\n <td class=\"col-when\">\n <span class=\"when\">{{ row.createdAt | date:'short' }}</span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <!--\n Bottom bar. When the filtered set spans multiple pages mj-pagination\n renders its own full-width `1-N of M | controls` row. When it fits\n on a single page mj-pagination self-hides, so the footer renders\n a single fallback summary line in its place.\n -->\n <!--\n Bottom bar: mj-pagination on the left (it has its own internal\n `1-N of M | nav controls` layout) + page-size selector hugging the\n right edge. The selector lives outside mj-pagination because the\n shared component doesn't expose a size-change output; the parent\n owns PageSize.\n -->\n <div class=\"pagination-bar\">\n @if (isSinglePage) {\n <span class=\"pagination-summary\">\n {{ rangeStart | number }}-{{ rangeEnd | number }} of {{ totalRowCount | number }}\n {{ totalRowCount === 1 ? 'rating' : 'ratings' }}\n </span>\n } @else {\n <mj-pagination\n class=\"feedback-pagination\"\n [TotalRowCount]=\"totalRowCount\"\n [PageNumber]=\"currentPage\"\n [PageSize]=\"pageSize\"\n [IsLoading]=\"loading\"\n (PageChange)=\"onPageChange($event)\">\n </mj-pagination>\n }\n\n <label class=\"page-size-control\">\n <span class=\"page-size-label\">Rows</span>\n <select\n class=\"page-size-select\"\n [ngModel]=\"pageSize\"\n (ngModelChange)=\"onPageSizeChange($event)\">\n @for (size of pageSizeOptions; track size) {\n <option [ngValue]=\"size\">{{ size }}</option>\n }\n </select>\n </label>\n </div>\n }\n }\n </div>\n }\n\n <!-- ===== Detail slide-out panel ===== -->\n @if (selectedRow) {\n <div class=\"slideout-backdrop\" (click)=\"closeDrawer()\"></div>\n }\n\n <aside class=\"slideout-panel\"\n [class.open]=\"!!selectedRow\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"slideout-title\">\n @if (selectedRow; as r) {\n <div class=\"slideout-header\">\n <div class=\"slideout-title\">\n <i class=\"fa-solid fa-comment-dots\"></i>\n <div class=\"slideout-title-text\">\n <h2 id=\"slideout-title\" class=\"slideout-title-line\">\n Feedback on {{ r.agentName || 'AI message' }}\n </h2>\n <div class=\"slideout-subtitle\">\n <span class=\"rating-badge\" [ngClass]=\"bandClassFor(r.rating)\">\n {{ r.rating }}<small>/10</small>\n </span>\n <span>\n Rated by <strong>{{ r.raterName || r.raterEmail || 'Unknown user' }}</strong>\n · {{ r.createdAt | date:'medium' }}\n </span>\n </div>\n </div>\n </div>\n <button class=\"slideout-close\" (click)=\"closeDrawer()\" title=\"Close (Esc)\" aria-label=\"Close\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <div class=\"slideout-content\">\n <div class=\"slideout-section\">\n <div class=\"section-label\">Reviewer Comment</div>\n @if (r.comments) {\n <div class=\"comment-body\">{{ r.comments }}</div>\n } @else {\n <div class=\"comment-body muted\">(no comment was provided)</div>\n }\n </div>\n\n <div class=\"slideout-section\">\n <div class=\"meta-grid\">\n <div class=\"meta-card\">\n <div class=\"meta-label\">Agent</div>\n <div class=\"meta-value\">{{ r.agentName || '—' }}</div>\n </div>\n <div class=\"meta-card\">\n <div class=\"meta-label\">Conversation</div>\n <div class=\"meta-value\">{{ r.conversationName || '—' }}</div>\n </div>\n <div class=\"meta-card\">\n <div class=\"meta-label\">Message Role</div>\n <div class=\"meta-value\">{{ r.messageRole || '—' }}</div>\n </div>\n </div>\n </div>\n\n <div class=\"slideout-section\">\n <div class=\"message-card\">\n <div class=\"message-card-header\">\n <i class=\"fa-solid fa-message\"></i> Rated Message\n </div>\n <div class=\"message-card-body\">\n @if (r.messageText) {\n {{ r.messageText }}\n } @else {\n <span class=\"muted\">(message text unavailable)</span>\n }\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"slideout-footer\">\n <button mjButton variant=\"flat\" size=\"lg\" (click)=\"closeDrawer()\">Close</button>\n <button mjButton variant=\"primary\" size=\"lg\"\n (click)=\"openConversation()\"\n [disabled]=\"!r.conversationID\"\n [title]=\"r.conversationID ? 'Open the source conversation' : 'No conversation linked'\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i>\n Open Conversation\n </button>\n </div>\n }\n </aside>\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"conversation-feedback.js","sourceRoot":"","sources":["../../../src/lib/conversation-feedback/conversation-feedback.ts","../../../src/lib/conversation-feedback/conversation-feedback.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, ChangeDetectorRef, HostListener, inject } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RunQuery } from '@memberjunction/core';\nimport { ApplicationManager } from '@memberjunction/ng-base-application';\n\nexport interface FeedbackRow {\n ratingID: string;\n rating: number;\n comments: string | null;\n createdAt: string;\n raterName: string | null;\n raterEmail: string | null;\n conversationDetailID: string;\n conversationID: string | null;\n conversationName: string | null;\n messageText: string | null;\n messageSnippet: string | null;\n messageRole: string | null;\n agentID: string | null;\n agentName: string | null;\n}\n\nexport type RatingBand = 'all' | 'high' | 'mid' | 'low';\nexport type DateRange = 'all' | '1d' | '7d' | '30d' | '90d';\n\n@Component({\n standalone: false,\n selector: 'mj-conversation-feedback',\n templateUrl: './conversation-feedback.html',\n styleUrls: ['./conversation-feedback.css']\n})\n@RegisterClass(BaseResourceComponent, 'ConversationFeedbackResource')\nexport class ConversationFeedbackResource extends BaseResourceComponent implements OnInit {\n isInitializing = true;\n loading = false;\n statsLoading = false;\n error: string | null = null;\n\n ratingBand: RatingBand = 'all';\n dateRange: DateRange = '7d';\n searchTerm = '';\n\n rows: FeedbackRow[] = [];\n totalRowCount = 0;\n\n pageSize: number = 10;\n currentPage: number = 1;\n readonly pageSizeOptions: number[] = [10, 25, 50, 100];\n\n stats = { total: 0, avgRating: 0, percentPositive: 0, percentNegative: 0 };\n\n selectedRow: FeedbackRow | null = null;\n\n private searchDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n private cdr = inject(ChangeDetectorRef);\n private appManager = inject(ApplicationManager);\n\n async GetResourceDisplayName(): Promise<string> {\n return 'Agent Feedback';\n }\n\n async GetResourceIconClass(): Promise<string> {\n return 'fa-solid fa-comment-dots';\n }\n\n override async ngOnInit(): Promise<void> {\n this.isInitializing = false;\n this.cdr.detectChanges();\n await this.applyFilters();\n this.NotifyLoadComplete();\n }\n\n /** Manual refresh from the page header — same path as a filter change. */\n async loadFeedback(): Promise<void> {\n await this.applyFilters();\n }\n\n setBand(band: RatingBand): void {\n if (this.ratingBand === band) return;\n this.ratingBand = band;\n this.currentPage = 1;\n void this.applyFilters();\n }\n\n setDateRange(range: DateRange): void {\n if (this.dateRange === range) return;\n this.dateRange = range;\n this.currentPage = 1;\n void this.applyFilters();\n }\n\n /**\n * Search input fires on every keystroke; debounce so we don't slam the\n * server while the user is typing. 250ms is enough to feel responsive\n * without firing on intermediate states.\n */\n onSearchChange(): void {\n if (this.searchDebounceTimer) clearTimeout(this.searchDebounceTimer);\n this.searchDebounceTimer = setTimeout(() => {\n this.currentPage = 1;\n void this.applyFilters();\n }, 250);\n }\n\n onPageChange(event: { PageNumber: number; PageSize: number; StartRow: number }): void {\n if (event.PageNumber === this.currentPage) return;\n this.currentPage = event.PageNumber;\n void this.loadRows();\n }\n\n onPageSizeChange(size: number): void {\n const next = Number(size);\n if (!next || next === this.pageSize) return;\n this.pageSize = next;\n this.currentPage = 1;\n void this.loadRows();\n }\n\n openDrawer(row: FeedbackRow): void {\n this.selectedRow = row;\n this.cdr.detectChanges();\n }\n\n closeDrawer(): void {\n this.selectedRow = null;\n this.cdr.detectChanges();\n }\n\n async openConversation(): Promise<void> {\n if (!this.selectedRow?.conversationID) return;\n const conversationID = this.selectedRow.conversationID;\n\n // The Chat app owns the Conversations nav item; the active app (Agent\n // Feedback) does not, so we must target Chat explicitly. Fall back to\n // scanning all apps for a nav item whose DriverClass is the chat resource.\n let appId: string | undefined = this.appManager.GetAppByName('Chat')?.ID;\n let navItemLabel = 'Conversations';\n\n if (!appId) {\n for (const app of this.appManager.GetAllApps()) {\n const navItems = await app.GetNavItems();\n const match = navItems.find(n => (n as any).DriverClass === 'ChatConversationsResource');\n if (match) {\n appId = app.ID;\n navItemLabel = match.Label;\n break;\n }\n }\n }\n\n if (!appId) {\n this.error = 'Could not find a Chat application to open this conversation in.';\n this.cdr.detectChanges();\n return;\n }\n\n this.closeDrawer();\n await this.navigationService.OpenNavItemByName(navItemLabel, { conversationId: conversationID }, appId);\n }\n\n @HostListener('document:keydown.escape')\n onEscape(): void {\n if (this.selectedRow) this.closeDrawer();\n }\n\n bandClassFor(rating: number): string {\n if (rating >= 8) return 'rating-high';\n if (rating >= 4) return 'rating-mid';\n return 'rating-low';\n }\n\n trackByRatingID = (_: number, row: FeedbackRow): string => row.ratingID;\n\n /** 1-based index of the first row on the current page (0 when empty). */\n get rangeStart(): number {\n if (this.totalRowCount === 0) return 0;\n return (this.currentPage - 1) * this.pageSize + 1;\n }\n\n /** 1-based index of the last row on the current page (clamped to total). */\n get rangeEnd(): number {\n return Math.min(this.currentPage * this.pageSize, this.totalRowCount);\n }\n\n /**\n * True when the filtered set fits on a single page — in this case\n * mj-pagination hides itself, so the footer renders a fallback summary\n * line. When false we let mj-pagination own the bar (it has its own\n * `1-N of M` summary on the left + nav controls on the right).\n */\n get isSinglePage(): boolean {\n if (this.totalRowCount <= 0) return false;\n return Math.ceil(this.totalRowCount / this.pageSize) <= 1;\n }\n\n /**\n * Run both the rows-query (paged) and the stats-query (aggregate) against\n * the current filter state. Called when filters change or on initial load.\n */\n private async applyFilters(): Promise<void> {\n await Promise.all([this.loadRows(), this.loadStats()]);\n }\n\n /**\n * Fetch the current page of rows from the server. The mj-pagination\n * footer reads `totalRowCount` to derive the page count.\n */\n private async loadRows(): Promise<void> {\n this.loading = true;\n this.error = null;\n this.cdr.detectChanges();\n\n try {\n const rq = new RunQuery();\n const result = await rq.RunQuery({\n QueryName: 'ListConversationDetailFeedback',\n CategoryPath: '/MJ/Conversations',\n Parameters: this.buildQueryParameters(),\n StartRow: (this.currentPage - 1) * this.pageSize,\n MaxRows: this.pageSize\n });\n\n if (!result.Success) {\n this.error = result.ErrorMessage || 'Failed to load feedback';\n this.rows = [];\n this.totalRowCount = 0;\n return;\n }\n\n this.rows = (result.Results ?? []).map((r: any) => this.mapRow(r));\n this.totalRowCount = result.TotalRowCount ?? this.rows.length;\n } catch (e: any) {\n this.error = e?.message || 'Failed to load feedback';\n this.rows = [];\n this.totalRowCount = 0;\n } finally {\n this.loading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Aggregate counts over the same filter universe as `loadRows()`. Runs in\n * parallel with the rows query so the stat cards and the table stay in\n * sync after every filter change.\n */\n private async loadStats(): Promise<void> {\n this.statsLoading = true;\n this.cdr.detectChanges();\n\n try {\n const rq = new RunQuery();\n const result = await rq.RunQuery({\n QueryName: 'ListConversationDetailFeedbackStats',\n CategoryPath: '/MJ/Conversations',\n Parameters: this.buildQueryParameters()\n });\n\n const row = (result.Results?.[0] as any) || {};\n const total = Number(row.Total ?? 0);\n const avg = Number(row.AvgRating ?? 0);\n const pos = Number(row.PositiveCount ?? 0);\n const neg = Number(row.NegativeCount ?? 0);\n\n this.stats = {\n total,\n avgRating: total ? Math.round(avg * 10) / 10 : 0,\n percentPositive: total ? Math.round((pos / total) * 100) : 0,\n percentNegative: total ? Math.round((neg / total) * 100) : 0\n };\n } catch (e) {\n // Stats are non-critical — the table is the primary surface. Log and\n // leave the previous stats values in place.\n console.warn('[Feedback] stats query failed', e);\n } finally {\n this.statsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Build the Nunjucks-bound parameter set passed to both queries. Server-side\n * filtering: emit only the keys that actually have a value so the SQL's\n * `{% if X %}` blocks stay inert when filters are at their default.\n */\n private buildQueryParameters(): Record<string, unknown> {\n const params: {\n MinRating?: number;\n MaxRating?: number;\n StartDate?: string;\n SearchText?: string;\n } = {};\n\n if (this.ratingBand === 'high') {\n params.MinRating = 8;\n } else if (this.ratingBand === 'mid') {\n params.MinRating = 4;\n params.MaxRating = 7;\n } else if (this.ratingBand === 'low') {\n params.MaxRating = 3;\n }\n\n const cutoffIso = this.dateRangeCutoffIso();\n if (cutoffIso) {\n params.StartDate = cutoffIso;\n }\n\n const term = this.searchTerm.trim();\n if (term) {\n params.SearchText = term;\n }\n\n return params;\n }\n\n private dateRangeCutoffIso(): string | null {\n if (this.dateRange === 'all') return null;\n const days = this.dateRange === '1d' ? 1\n : this.dateRange === '7d' ? 7\n : this.dateRange === '30d' ? 30\n : 90;\n const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n return cutoff.toISOString();\n }\n\n private mapRow(r: any): FeedbackRow {\n const message: string | null = r.MessageText ?? null;\n const snippet = message\n ? (message.length > 160 ? message.slice(0, 160) + '…' : message)\n : null;\n return {\n ratingID: r.RatingID,\n rating: r.Rating,\n comments: r.Comments ?? null,\n createdAt: r.RatedAt ?? '',\n raterName: r.RaterName ?? null,\n raterEmail: r.RaterEmail ?? null,\n conversationDetailID: r.ConversationDetailID,\n conversationID: r.ConversationID ?? null,\n conversationName: r.ConversationName ?? null,\n messageText: message,\n messageSnippet: snippet,\n messageRole: r.MessageRole ?? null,\n agentID: r.AgentID ?? null,\n agentName: r.AgentName ?? null\n };\n }\n}\n","<div class=\"feedback-container\">\n\n @if (isInitializing) {\n <div class=\"loading-overlay\"><div class=\"spinner\"></div> Loading...</div>\n }\n\n @if (!isInitializing) {\n\n <div class=\"sticky-header\">\n <div class=\"page-header\">\n <div class=\"page-title-area\">\n <div class=\"page-icon\"><i class=\"fa-solid fa-comment-dots\"></i></div>\n <div>\n <h1 class=\"page-title\">Agent Feedback</h1>\n <p class=\"page-subtitle\">User ratings and comments on AI messages</p>\n </div>\n </div>\n <div class=\"page-actions\">\n <button class=\"btn-action\" (click)=\"loadFeedback()\" [disabled]=\"loading\">\n <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"loading\"></i> Refresh\n </button>\n </div>\n </div>\n\n @if (error) {\n <mj-alert Variant=\"error\" class=\"feedback-error-spacing\" Dismissible (Dismissed)=\"error = null\">{{ error }}</mj-alert>\n }\n\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-total\"><i class=\"fa-solid fa-comment-dots\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.total }}</div>\n <div class=\"stat-label\">Total Ratings</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-avg\"><i class=\"fa-solid fa-star\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.avgRating }}<span class=\"stat-unit\">/10</span></div>\n <div class=\"stat-label\">Avg Rating</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-positive\"><i class=\"fa-solid fa-thumbs-up\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value rating-high-text\">{{ stats.percentPositive }}%</div>\n <div class=\"stat-label\">Positive (8-10)</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-negative\"><i class=\"fa-solid fa-thumbs-down\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value rating-low-text\">{{ stats.percentNegative }}%</div>\n <div class=\"stat-label\">Negative (1-3)</div>\n </div>\n </div>\n </div>\n\n <div class=\"filter-bar\">\n <div class=\"filter-row\">\n <div class=\"filter-group\">\n <span class=\"filter-label\">Date Range</span>\n <div class=\"btn-group\">\n <button class=\"btn-filter\" [class.active]=\"dateRange === '1d'\" (click)=\"setDateRange('1d')\">1d</button>\n <button class=\"btn-filter\" [class.active]=\"dateRange === '7d'\" (click)=\"setDateRange('7d')\">7d</button>\n <button class=\"btn-filter\" [class.active]=\"dateRange === '30d'\" (click)=\"setDateRange('30d')\">30d</button>\n <button class=\"btn-filter\" [class.active]=\"dateRange === '90d'\" (click)=\"setDateRange('90d')\">90d</button>\n <button class=\"btn-filter\" [class.active]=\"dateRange === 'all'\" (click)=\"setDateRange('all')\">All</button>\n </div>\n </div>\n <div class=\"filter-group\">\n <span class=\"filter-label\">Rating Band</span>\n <div class=\"btn-group\">\n <button class=\"btn-filter\" [class.active]=\"ratingBand === 'all'\" (click)=\"setBand('all')\">All</button>\n <button class=\"btn-filter band-high\" [class.active]=\"ratingBand === 'high'\" (click)=\"setBand('high')\">High 8-10</button>\n <button class=\"btn-filter band-mid\" [class.active]=\"ratingBand === 'mid'\" (click)=\"setBand('mid')\">Mid 4-7</button>\n <button class=\"btn-filter band-low\" [class.active]=\"ratingBand === 'low'\" (click)=\"setBand('low')\">Low 1-3</button>\n </div>\n </div>\n <div class=\"filter-group filter-search\">\n <span class=\"filter-label\">Search</span>\n <input\n type=\"text\"\n class=\"input-search\"\n [(ngModel)]=\"searchTerm\"\n (input)=\"onSearchChange()\"\n placeholder=\"Search comments, message, agent, rater...\" />\n </div>\n </div>\n <div class=\"diagnostic-line\">\n {{ totalRowCount }} {{ totalRowCount === 1 ? 'rating' : 'ratings' }} match the current filters\n </div>\n </div>\n </div>\n\n <div class=\"scrollable-content\">\n @if (loading) {\n <div class=\"loading-overlay\"><div class=\"spinner\"></div> Loading feedback...</div>\n }\n\n @if (!loading) {\n @if (rows.length === 0) {\n <mj-empty-state\n class=\"feedback-empty-state\"\n Variant=\"no-results\"\n Icon=\"fa-solid fa-comment-slash\"\n Title=\"No feedback matches the current filters.\" />\n } @else {\n <div class=\"feedback-table-wrapper\">\n <table class=\"feedback-table\">\n <thead>\n <tr>\n <th class=\"col-rating\">Rating</th>\n <th class=\"col-comment\">Comments</th>\n <th class=\"col-agent\">Agent</th>\n <th class=\"col-message\">Message</th>\n <th class=\"col-rater\">Rater</th>\n <th class=\"col-when\">When</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rows; track trackByRatingID($index, row)) {\n <tr\n class=\"feedback-row\"\n [class.expanded]=\"selectedRow?.ratingID === row.ratingID\"\n (click)=\"openDrawer(row)\">\n <td class=\"col-rating\">\n <span class=\"rating-badge\" [ngClass]=\"bandClassFor(row.rating)\">\n {{ row.rating }}<small>/10</small>\n </span>\n </td>\n <td class=\"col-comment\">\n @if (row.comments) {\n <div class=\"comment-text clamped\">{{ row.comments }}</div>\n } @else {\n <span class=\"muted\">(no comment)</span>\n }\n </td>\n <td class=\"col-agent\">\n <span class=\"agent-name\">{{ row.agentName || '—' }}</span>\n </td>\n <td class=\"col-message\">\n @if (row.messageSnippet) {\n <span class=\"message-snippet\">{{ row.messageSnippet }}</span>\n } @else {\n <span class=\"muted\">—</span>\n }\n </td>\n <td class=\"col-rater\">\n <div class=\"rater-name\">{{ row.raterName || row.raterEmail || '—' }}</div>\n @if (row.raterEmail && row.raterName) {\n <div class=\"rater-email\">{{ row.raterEmail }}</div>\n }\n </td>\n <td class=\"col-when\">\n <span class=\"when\">{{ row.createdAt | date:'short' }}</span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <!--\n Bottom bar. When the filtered set spans multiple pages mj-pagination\n renders its own full-width `1-N of M | controls` row. When it fits\n on a single page mj-pagination self-hides, so the footer renders\n a single fallback summary line in its place.\n -->\n <!--\n Bottom bar: mj-pagination on the left (it has its own internal\n `1-N of M | nav controls` layout) + page-size selector hugging the\n right edge. The selector lives outside mj-pagination because the\n shared component doesn't expose a size-change output; the parent\n owns PageSize.\n -->\n <div class=\"pagination-bar\">\n @if (isSinglePage) {\n <span class=\"pagination-summary\">\n {{ rangeStart | number }}-{{ rangeEnd | number }} of {{ totalRowCount | number }}\n {{ totalRowCount === 1 ? 'rating' : 'ratings' }}\n </span>\n } @else {\n <mj-pagination\n class=\"feedback-pagination\"\n [TotalRowCount]=\"totalRowCount\"\n [PageNumber]=\"currentPage\"\n [PageSize]=\"pageSize\"\n [IsLoading]=\"loading\"\n (PageChange)=\"onPageChange($event)\">\n </mj-pagination>\n }\n\n <label class=\"page-size-control\">\n <span class=\"page-size-label\">Rows</span>\n <select\n class=\"page-size-select\"\n [ngModel]=\"pageSize\"\n (ngModelChange)=\"onPageSizeChange($event)\">\n @for (size of pageSizeOptions; track size) {\n <option [ngValue]=\"size\">{{ size }}</option>\n }\n </select>\n </label>\n </div>\n }\n }\n </div>\n }\n\n <!-- ===== Detail slide-out panel ===== -->\n @if (selectedRow) {\n <div class=\"slideout-backdrop\" (click)=\"closeDrawer()\"></div>\n }\n\n <aside class=\"slideout-panel\"\n [class.open]=\"!!selectedRow\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"slideout-title\">\n @if (selectedRow; as r) {\n <div class=\"slideout-header\">\n <div class=\"slideout-title\">\n <i class=\"fa-solid fa-comment-dots\"></i>\n <div class=\"slideout-title-text\">\n <h2 id=\"slideout-title\" class=\"slideout-title-line\">\n Feedback on {{ r.agentName || 'AI message' }}\n </h2>\n <div class=\"slideout-subtitle\">\n <span class=\"rating-badge\" [ngClass]=\"bandClassFor(r.rating)\">\n {{ r.rating }}<small>/10</small>\n </span>\n <span>\n Rated by <strong>{{ r.raterName || r.raterEmail || 'Unknown user' }}</strong>\n · {{ r.createdAt | date:'medium' }}\n </span>\n </div>\n </div>\n </div>\n <button class=\"slideout-close\" (click)=\"closeDrawer()\" title=\"Close (Esc)\" aria-label=\"Close\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <div class=\"slideout-content\">\n <div class=\"slideout-section\">\n <div class=\"section-label\">Reviewer Comment</div>\n @if (r.comments) {\n <div class=\"comment-body\">{{ r.comments }}</div>\n } @else {\n <div class=\"comment-body muted\">(no comment was provided)</div>\n }\n </div>\n\n <div class=\"slideout-section\">\n <div class=\"meta-grid\">\n <div class=\"meta-card\">\n <div class=\"meta-label\">Agent</div>\n <div class=\"meta-value\">{{ r.agentName || '—' }}</div>\n </div>\n <div class=\"meta-card\">\n <div class=\"meta-label\">Conversation</div>\n <div class=\"meta-value\">{{ r.conversationName || '—' }}</div>\n </div>\n <div class=\"meta-card\">\n <div class=\"meta-label\">Message Role</div>\n <div class=\"meta-value\">{{ r.messageRole || '—' }}</div>\n </div>\n </div>\n </div>\n\n <div class=\"slideout-section\">\n <div class=\"message-card\">\n <div class=\"message-card-header\">\n <i class=\"fa-solid fa-message\"></i> Rated Message\n </div>\n <div class=\"message-card-body\">\n @if (r.messageText) {\n {{ r.messageText }}\n } @else {\n <span class=\"muted\">(message text unavailable)</span>\n }\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"slideout-footer\">\n <button mjButton variant=\"flat\" size=\"lg\" (click)=\"closeDrawer()\">Close</button>\n <button mjButton variant=\"primary\" size=\"lg\"\n (click)=\"openConversation()\"\n [disabled]=\"!r.conversationID\"\n [title]=\"r.conversationID ? 'Open the source conversation' : 'No conversation linked'\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i>\n Open Conversation\n </button>\n </div>\n }\n </aside>\n</div>\n"]}
|
|
@@ -49,23 +49,16 @@ function DashboardPreferencesDialogComponent_Conditional_11_Template(rf, ctx) {
|
|
|
49
49
|
i0.ɵɵelementEnd();
|
|
50
50
|
} }
|
|
51
51
|
function DashboardPreferencesDialogComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
52
|
-
i0.ɵɵ
|
|
53
|
-
i0.ɵɵelement(1, "i", 20);
|
|
54
|
-
i0.ɵɵtext(2);
|
|
55
|
-
i0.ɵɵelementEnd();
|
|
52
|
+
i0.ɵɵelement(0, "mj-empty-state", 10);
|
|
56
53
|
} if (rf & 2) {
|
|
57
54
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
58
|
-
i0.ɵɵ
|
|
59
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r0.error, " ");
|
|
55
|
+
i0.ɵɵproperty("Title", ctx_r0.error);
|
|
60
56
|
} }
|
|
61
57
|
function DashboardPreferencesDialogComponent_Conditional_13_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
62
|
-
i0.ɵɵ
|
|
63
|
-
i0.ɵɵelement(1, "i", 29);
|
|
64
|
-
i0.ɵɵtext(2, " All dashboards are configured ");
|
|
65
|
-
i0.ɵɵelementEnd();
|
|
58
|
+
i0.ɵɵelement(0, "mj-empty-state", 23);
|
|
66
59
|
} }
|
|
67
60
|
function DashboardPreferencesDialogComponent_Conditional_13_For_9_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
68
|
-
i0.ɵɵelementStart(0, "span",
|
|
61
|
+
i0.ɵɵelementStart(0, "span", 33);
|
|
69
62
|
i0.ɵɵtext(1);
|
|
70
63
|
i0.ɵɵelementEnd();
|
|
71
64
|
} if (rf & 2) {
|
|
@@ -75,16 +68,16 @@ function DashboardPreferencesDialogComponent_Conditional_13_For_9_Conditional_6_
|
|
|
75
68
|
} }
|
|
76
69
|
function DashboardPreferencesDialogComponent_Conditional_13_For_9_Template(rf, ctx) { if (rf & 1) {
|
|
77
70
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
78
|
-
i0.ɵɵelementStart(0, "div",
|
|
79
|
-
i0.ɵɵelement(2, "i",
|
|
80
|
-
i0.ɵɵelementStart(3, "div",
|
|
71
|
+
i0.ɵɵelementStart(0, "div", 24)(1, "div", 29);
|
|
72
|
+
i0.ɵɵelement(2, "i", 30);
|
|
73
|
+
i0.ɵɵelementStart(3, "div", 31)(4, "span", 32);
|
|
81
74
|
i0.ɵɵtext(5);
|
|
82
75
|
i0.ɵɵelementEnd();
|
|
83
|
-
i0.ɵɵconditionalCreate(6, DashboardPreferencesDialogComponent_Conditional_13_For_9_Conditional_6_Template, 2, 1, "span",
|
|
76
|
+
i0.ɵɵconditionalCreate(6, DashboardPreferencesDialogComponent_Conditional_13_For_9_Conditional_6_Template, 2, 1, "span", 33);
|
|
84
77
|
i0.ɵɵelementEnd();
|
|
85
|
-
i0.ɵɵelementStart(7, "button",
|
|
78
|
+
i0.ɵɵelementStart(7, "button", 34);
|
|
86
79
|
i0.ɵɵlistener("click", function DashboardPreferencesDialogComponent_Conditional_13_For_9_Template_button_click_7_listener() { const dashboard_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.addDashboard(dashboard_r5)); });
|
|
87
|
-
i0.ɵɵelement(8, "i",
|
|
80
|
+
i0.ɵɵelement(8, "i", 35);
|
|
88
81
|
i0.ɵɵelementEnd()()();
|
|
89
82
|
} if (rf & 2) {
|
|
90
83
|
const dashboard_r5 = ctx.$implicit;
|
|
@@ -95,13 +88,10 @@ function DashboardPreferencesDialogComponent_Conditional_13_For_9_Template(rf, c
|
|
|
95
88
|
i0.ɵɵconditional(dashboard_r5.Description ? 6 : -1);
|
|
96
89
|
} }
|
|
97
90
|
function DashboardPreferencesDialogComponent_Conditional_13_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
98
|
-
i0.ɵɵ
|
|
99
|
-
i0.ɵɵelement(1, "i", 29);
|
|
100
|
-
i0.ɵɵtext(2, " No dashboards configured ");
|
|
101
|
-
i0.ɵɵelementEnd();
|
|
91
|
+
i0.ɵɵelement(0, "mj-empty-state", 27);
|
|
102
92
|
} }
|
|
103
93
|
function DashboardPreferencesDialogComponent_Conditional_13_For_18_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
104
|
-
i0.ɵɵelementStart(0, "span",
|
|
94
|
+
i0.ɵɵelementStart(0, "span", 33);
|
|
105
95
|
i0.ɵɵtext(1);
|
|
106
96
|
i0.ɵɵelementEnd();
|
|
107
97
|
} if (rf & 2) {
|
|
@@ -111,26 +101,26 @@ function DashboardPreferencesDialogComponent_Conditional_13_For_18_Conditional_8
|
|
|
111
101
|
} }
|
|
112
102
|
function DashboardPreferencesDialogComponent_Conditional_13_For_18_Template(rf, ctx) { if (rf & 1) {
|
|
113
103
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
114
|
-
i0.ɵɵelementStart(0, "div", 28)(1, "div",
|
|
115
|
-
i0.ɵɵelement(2, "i",
|
|
116
|
-
i0.ɵɵelementStart(3, "span",
|
|
104
|
+
i0.ɵɵelementStart(0, "div", 28)(1, "div", 29);
|
|
105
|
+
i0.ɵɵelement(2, "i", 30);
|
|
106
|
+
i0.ɵɵelementStart(3, "span", 36);
|
|
117
107
|
i0.ɵɵtext(4);
|
|
118
108
|
i0.ɵɵelementEnd();
|
|
119
|
-
i0.ɵɵelementStart(5, "div",
|
|
109
|
+
i0.ɵɵelementStart(5, "div", 31)(6, "span", 32);
|
|
120
110
|
i0.ɵɵtext(7);
|
|
121
111
|
i0.ɵɵelementEnd();
|
|
122
|
-
i0.ɵɵconditionalCreate(8, DashboardPreferencesDialogComponent_Conditional_13_For_18_Conditional_8_Template, 2, 1, "span",
|
|
112
|
+
i0.ɵɵconditionalCreate(8, DashboardPreferencesDialogComponent_Conditional_13_For_18_Conditional_8_Template, 2, 1, "span", 33);
|
|
123
113
|
i0.ɵɵelementEnd();
|
|
124
|
-
i0.ɵɵelementStart(9, "button",
|
|
114
|
+
i0.ɵɵelementStart(9, "button", 37);
|
|
125
115
|
i0.ɵɵlistener("click", function DashboardPreferencesDialogComponent_Conditional_13_For_18_Template_button_click_9_listener() { const dashboard_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.removeDashboard(dashboard_r7)); });
|
|
126
116
|
i0.ɵɵelement(10, "i", 13);
|
|
127
117
|
i0.ɵɵelementEnd()()();
|
|
128
118
|
} if (rf & 2) {
|
|
129
119
|
const dashboard_r7 = ctx.$implicit;
|
|
130
|
-
const ɵ$
|
|
120
|
+
const ɵ$index_92_r8 = ctx.$index;
|
|
131
121
|
i0.ɵɵproperty("cdkDragData", dashboard_r7);
|
|
132
122
|
i0.ɵɵadvance(4);
|
|
133
|
-
i0.ɵɵtextInterpolate(ɵ$
|
|
123
|
+
i0.ɵɵtextInterpolate(ɵ$index_92_r8 + 1);
|
|
134
124
|
i0.ɵɵadvance(3);
|
|
135
125
|
i0.ɵɵtextInterpolate(dashboard_r7.Name);
|
|
136
126
|
i0.ɵɵadvance();
|
|
@@ -138,22 +128,22 @@ function DashboardPreferencesDialogComponent_Conditional_13_For_18_Template(rf,
|
|
|
138
128
|
} }
|
|
139
129
|
function DashboardPreferencesDialogComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
140
130
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
141
|
-
i0.ɵɵelementStart(0, "div", 11)(1, "div",
|
|
142
|
-
i0.ɵɵelement(3, "i",
|
|
131
|
+
i0.ɵɵelementStart(0, "div", 11)(1, "div", 20)(2, "h4");
|
|
132
|
+
i0.ɵɵelement(3, "i", 21);
|
|
143
133
|
i0.ɵɵtext(4, " Available Dashboards");
|
|
144
134
|
i0.ɵɵelementEnd();
|
|
145
|
-
i0.ɵɵelementStart(5, "div",
|
|
135
|
+
i0.ɵɵelementStart(5, "div", 22, 0);
|
|
146
136
|
i0.ɵɵlistener("cdkDropListDropped", function DashboardPreferencesDialogComponent_Conditional_13_Template_div_cdkDropListDropped_5_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onDrop($event)); });
|
|
147
|
-
i0.ɵɵconditionalCreate(7, DashboardPreferencesDialogComponent_Conditional_13_Conditional_7_Template,
|
|
148
|
-
i0.ɵɵrepeaterCreate(8, DashboardPreferencesDialogComponent_Conditional_13_For_9_Template, 9, 3, "div",
|
|
137
|
+
i0.ɵɵconditionalCreate(7, DashboardPreferencesDialogComponent_Conditional_13_Conditional_7_Template, 1, 0, "mj-empty-state", 23);
|
|
138
|
+
i0.ɵɵrepeaterCreate(8, DashboardPreferencesDialogComponent_Conditional_13_For_9_Template, 9, 3, "div", 24, _forTrack0);
|
|
149
139
|
i0.ɵɵelementEnd()();
|
|
150
|
-
i0.ɵɵelementStart(10, "div",
|
|
151
|
-
i0.ɵɵelement(12, "i",
|
|
140
|
+
i0.ɵɵelementStart(10, "div", 25)(11, "h4");
|
|
141
|
+
i0.ɵɵelement(12, "i", 26);
|
|
152
142
|
i0.ɵɵtext(13, " Configured Dashboards");
|
|
153
143
|
i0.ɵɵelementEnd();
|
|
154
|
-
i0.ɵɵelementStart(14, "div",
|
|
144
|
+
i0.ɵɵelementStart(14, "div", 22, 1);
|
|
155
145
|
i0.ɵɵlistener("cdkDropListDropped", function DashboardPreferencesDialogComponent_Conditional_13_Template_div_cdkDropListDropped_14_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onDrop($event)); });
|
|
156
|
-
i0.ɵɵconditionalCreate(16, DashboardPreferencesDialogComponent_Conditional_13_Conditional_16_Template,
|
|
146
|
+
i0.ɵɵconditionalCreate(16, DashboardPreferencesDialogComponent_Conditional_13_Conditional_16_Template, 1, 0, "mj-empty-state", 27);
|
|
157
147
|
i0.ɵɵrepeaterCreate(17, DashboardPreferencesDialogComponent_Conditional_13_For_18_Template, 11, 4, "div", 28, _forTrack0);
|
|
158
148
|
i0.ɵɵelementEnd()()();
|
|
159
149
|
} if (rf & 2) {
|
|
@@ -174,13 +164,13 @@ function DashboardPreferencesDialogComponent_Conditional_13_Template(rf, ctx) {
|
|
|
174
164
|
i0.ɵɵrepeater(ctx_r0.configuredDashboards);
|
|
175
165
|
} }
|
|
176
166
|
function DashboardPreferencesDialogComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
177
|
-
i0.ɵɵelement(0, "mj-loading",
|
|
167
|
+
i0.ɵɵelement(0, "mj-loading", 38);
|
|
178
168
|
i0.ɵɵtext(1, " Saving... ");
|
|
179
169
|
} if (rf & 2) {
|
|
180
170
|
i0.ɵɵproperty("showText", false);
|
|
181
171
|
} }
|
|
182
172
|
function DashboardPreferencesDialogComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
183
|
-
i0.ɵɵelement(0, "i",
|
|
173
|
+
i0.ɵɵelement(0, "i", 39);
|
|
184
174
|
i0.ɵɵtext(1, " Save Changes ");
|
|
185
175
|
} }
|
|
186
176
|
export class DashboardPreferencesDialogComponent extends BaseAngularComponent {
|
|
@@ -515,7 +505,7 @@ export class DashboardPreferencesDialogComponent extends BaseAngularComponent {
|
|
|
515
505
|
this.result.emit({ saved: false });
|
|
516
506
|
}
|
|
517
507
|
static ɵfac = /*@__PURE__*/ (() => { let ɵDashboardPreferencesDialogComponent_BaseFactory; return function DashboardPreferencesDialogComponent_Factory(__ngFactoryType__) { return (ɵDashboardPreferencesDialogComponent_BaseFactory || (ɵDashboardPreferencesDialogComponent_BaseFactory = i0.ɵɵgetInheritedFactory(DashboardPreferencesDialogComponent)))(__ngFactoryType__ || DashboardPreferencesDialogComponent); }; })();
|
|
518
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DashboardPreferencesDialogComponent, selectors: [["mj-dashboard-preferences-dialog"]], inputs: { applicationId: "applicationId", scope: "scope" }, outputs: { result: "result" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 21, vars: 11, consts: [["availableList", "cdkDropList"], ["configuredList", "cdkDropList"], ["Title", "Dashboard Preferences", 3, "Close", "Visible", "Width", "Height", "MinWidth"], [1, "dashboard-preferences-dialog"], [1, "dialog-header"], [1, "fa-solid", "fa-sliders"], [1, "scope-indicator"], [1, "preference-mode-selector"], [1, "dialog-content"], [1, "loading-overlay"], [
|
|
508
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DashboardPreferencesDialogComponent, selectors: [["mj-dashboard-preferences-dialog"]], inputs: { applicationId: "applicationId", scope: "scope" }, outputs: { result: "result" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 21, vars: 11, consts: [["availableList", "cdkDropList"], ["configuredList", "cdkDropList"], ["Title", "Dashboard Preferences", 3, "Close", "Visible", "Width", "Height", "MinWidth"], [1, "dashboard-preferences-dialog"], [1, "dialog-header"], [1, "fa-solid", "fa-sliders"], [1, "scope-indicator"], [1, "preference-mode-selector"], [1, "dialog-content"], [1, "loading-overlay"], ["Variant", "error", "Size", "compact", "Icon", "fa-solid fa-triangle-exclamation", 3, "Title"], [1, "preferences-panels"], ["type", "button", 1, "btn", "btn-secondary", 3, "click"], [1, "fa-solid", "fa-times"], ["type", "button", 1, "btn", "btn-primary", 3, "click", "disabled"], [1, "fa-solid", "fa-globe"], [1, "fa-solid", "fa-layer-group"], ["type", "radio", "name", "preferenceMode", "value", "personal", 3, "ngModelChange", "change", "ngModel"], ["type", "radio", "name", "preferenceMode", "value", "system", 3, "ngModelChange", "change", "ngModel"], ["text", "Loading preferences...", "size", "large"], [1, "panel", "available-panel"], [1, "fa-solid", "fa-list"], ["cdkDropList", "", 1, "dashboard-list", 3, "cdkDropListDropped", "cdkDropListData", "cdkDropListConnectedTo"], ["Variant", "success", "Size", "compact", "Icon", "fa-solid fa-circle-check", "Title", "All dashboards are configured"], ["cdkDrag", "", 1, "dashboard-item", "available-item", 3, "cdkDragData"], [1, "panel", "configured-panel"], [1, "fa-solid", "fa-list-ol"], ["Size", "compact", "Icon", "fa-solid fa-circle-info", "Title", "No dashboards configured"], ["cdkDrag", "", 1, "dashboard-item", "configured-item", 3, "cdkDragData"], [1, "dashboard-item-content"], [1, "fa-solid", "fa-grip-vertical", "drag-handle"], [1, "dashboard-info"], [1, "dashboard-name"], [1, "dashboard-description"], ["type", "button", "title", "Add to configured dashboards", 1, "add-button", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "order-number"], ["type", "button", "title", "Remove from configured dashboards", 1, "remove-button", 3, "click"], ["size", "small", 3, "showText"], [1, "fa-solid", "fa-check"]], template: function DashboardPreferencesDialogComponent_Template(rf, ctx) { if (rf & 1) {
|
|
519
509
|
i0.ɵɵelementStart(0, "mj-dialog", 2);
|
|
520
510
|
i0.ɵɵlistener("Close", function DashboardPreferencesDialogComponent_Template_mj_dialog_Close_0_listener() { return ctx.onCancel(); });
|
|
521
511
|
i0.ɵɵelementStart(1, "div", 3)(2, "div", 4)(3, "h3");
|
|
@@ -529,7 +519,7 @@ export class DashboardPreferencesDialogComponent extends BaseAngularComponent {
|
|
|
529
519
|
i0.ɵɵelementEnd();
|
|
530
520
|
i0.ɵɵelementStart(10, "div", 8);
|
|
531
521
|
i0.ɵɵconditionalCreate(11, DashboardPreferencesDialogComponent_Conditional_11_Template, 2, 0, "div", 9);
|
|
532
|
-
i0.ɵɵconditionalCreate(12, DashboardPreferencesDialogComponent_Conditional_12_Template,
|
|
522
|
+
i0.ɵɵconditionalCreate(12, DashboardPreferencesDialogComponent_Conditional_12_Template, 1, 1, "mj-empty-state", 10);
|
|
533
523
|
i0.ɵɵconditionalCreate(13, DashboardPreferencesDialogComponent_Conditional_13_Template, 19, 10, "div", 11);
|
|
534
524
|
i0.ɵɵelementEnd();
|
|
535
525
|
i0.ɵɵelementStart(14, "mj-dialog-actions")(15, "button", 12);
|
|
@@ -557,11 +547,11 @@ export class DashboardPreferencesDialogComponent extends BaseAngularComponent {
|
|
|
557
547
|
i0.ɵɵproperty("disabled", !ctx.hasChanges || ctx.saving);
|
|
558
548
|
i0.ɵɵadvance();
|
|
559
549
|
i0.ɵɵconditional(ctx.saving ? 19 : 20);
|
|
560
|
-
} }, dependencies: [i1.DefaultValueAccessor, i1.RadioControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.CdkDropList, i2.CdkDrag, i3.LoadingComponent, i4.MJDialogComponent, i4.MJDialogActionsComponent], styles: [".dashboard-preferences-dialog[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.dialog-header[_ngcontent-%COMP%] {\n padding: 20px 24px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.dialog-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.dialog-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 8px;\n color: var(--mj-text-secondary);\n}\n\n.scope-indicator[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.scope-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 6px;\n}\n\n.preference-mode-selector[_ngcontent-%COMP%] {\n margin-top: 12px;\n display: flex;\n gap: 20px;\n}\n\n.preference-mode-selector[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.preference-mode-selector[_ngcontent-%COMP%] input[type=\"radio\"][_ngcontent-%COMP%] {\n margin: 0;\n}\n\n.dialog-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n padding: 20px 24px;\n}\n\n.loading-container[_ngcontent-%COMP%]
|
|
550
|
+
} }, dependencies: [i1.DefaultValueAccessor, i1.RadioControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.CdkDropList, i2.CdkDrag, i3.LoadingComponent, i4.MJDialogComponent, i4.MJDialogActionsComponent, i4.MJEmptyStateComponent], styles: [".dashboard-preferences-dialog[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.dialog-header[_ngcontent-%COMP%] {\n padding: 20px 24px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.dialog-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.dialog-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 8px;\n color: var(--mj-text-secondary);\n}\n\n.scope-indicator[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.scope-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 6px;\n}\n\n.preference-mode-selector[_ngcontent-%COMP%] {\n margin-top: 12px;\n display: flex;\n gap: 20px;\n}\n\n.preference-mode-selector[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.preference-mode-selector[_ngcontent-%COMP%] input[type=\"radio\"][_ngcontent-%COMP%] {\n margin: 0;\n}\n\n.dialog-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n padding: 20px 24px;\n}\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n flex-direction: column;\n gap: 12px;\n}\n\n.preferences-panels[_ngcontent-%COMP%] {\n display: flex;\n gap: 20px;\n height: 100%;\n}\n\n.panel[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.panel[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.panel[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 8px;\n color: var(--mj-text-muted);\n}\n\n.dashboard-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n}\n\n.dashboard-item[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n cursor: move;\n}\n\n.dashboard-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 4px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.dashboard-item.cdk-drag-preview[_ngcontent-%COMP%] {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform: rotate(2deg);\n}\n\n.dashboard-item.cdk-drag-placeholder[_ngcontent-%COMP%] {\n opacity: 0.3;\n border-style: dashed;\n}\n\n.dashboard-item-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px;\n gap: 12px;\n}\n\n.drag-handle[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n cursor: move;\n font-size: 14px;\n}\n\n.order-number[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: var(--mj-brand-primary);\n color: white;\n border-radius: 50%;\n font-size: 12px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.dashboard-info[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.dashboard-name[_ngcontent-%COMP%] {\n font-weight: 500;\n color: var(--mj-text-primary);\n font-size: 14px;\n}\n\n.dashboard-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.3;\n}\n\n.add-button[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--mj-status-success);\n border-radius: 4px;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n opacity: 0.7;\n}\n\n.add-button[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n opacity: 1;\n}\n\n.remove-button[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--mj-status-error);\n border-radius: 4px;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n}\n\n.remove-button[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-status-error) 10%, transparent);\n}\n\n.cdk-drop-list-dragging[_ngcontent-%COMP%] .dashboard-item[_ngcontent-%COMP%]:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.dialog-footer[_ngcontent-%COMP%] {\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n background: var(--mj-bg-surface-card);\n}\n\n.btn[_ngcontent-%COMP%] {\n padding: 8px 16px;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n border: 1px solid transparent;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-color: var(--mj-text-muted);\n color: var(--mj-text-muted);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-text-muted);\n color: white;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n\n\n@media (max-width: 768px) {\n .dashboard-preferences-dialog[_ngcontent-%COMP%] {\n width: 95vw;\n max-height: 90vh;\n }\n\n .preferences-panels[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .panel[_ngcontent-%COMP%] {\n min-height: 200px;\n }\n\n .dashboard-list[_ngcontent-%COMP%] {\n min-height: 150px;\n }\n}"] });
|
|
561
551
|
}
|
|
562
552
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DashboardPreferencesDialogComponent, [{
|
|
563
553
|
type: Component,
|
|
564
|
-
args: [{ standalone: false, selector: 'mj-dashboard-preferences-dialog', template: "<mj-dialog [Visible]=\"true\" Title=\"Dashboard Preferences\"\n [Width]=\"800\"\n [Height]=\"600\"\n [MinWidth]=\"600\"\n (Close)=\"onCancel()\">\n<div class=\"dashboard-preferences-dialog\">\n <div class=\"dialog-header\">\n <h3><i class=\"fa-solid fa-sliders\"></i> Dashboard Preferences</h3>\n <p class=\"scope-indicator\">\n @if (scope === 'Global') {\n <i class=\"fa-solid fa-globe\"></i> Global Scope\n } @else {\n <i class=\"fa-solid fa-layer-group\"></i> Application: {{ applicationName }}\n }\n </p>\n @if (isSysAdmin && scope === 'Global') {\n <div class=\"preference-mode-selector\">\n <label>\n <input type=\"radio\"\n name=\"preferenceMode\"\n value=\"personal\"\n [(ngModel)]=\"preferenceMode\"\n (change)=\"onPreferenceModeChange()\">\n Personal Preferences\n </label>\n <label>\n <input type=\"radio\"\n name=\"preferenceMode\"\n value=\"system\"\n [(ngModel)]=\"preferenceMode\"\n (change)=\"onPreferenceModeChange()\">\n System Defaults\n </label>\n </div>\n }\n </div>\n\n <div class=\"dialog-content\">\n @if (loading) {\n <div class=\"loading-overlay\">\n <mj-loading text=\"Loading preferences...\" size=\"large\"></mj-loading>\n </div>\n }\n\n @if (error) {\n <div class=\"error-container\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n {{ error }}\n </div>\n }\n\n @if (!loading && !error) {\n <div class=\"preferences-panels\">\n <!-- Available Dashboards Panel -->\n <div class=\"panel available-panel\">\n <h4><i class=\"fa-solid fa-list\"></i> Available Dashboards</h4>\n <div class=\"dashboard-list\"\n cdkDropList\n #availableList=\"cdkDropList\"\n [cdkDropListData]=\"availableDashboards\"\n [cdkDropListConnectedTo]=\"[configuredList]\"\n (cdkDropListDropped)=\"onDrop($event)\">\n\n @if (availableDashboards.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-info-circle\"></i>\n All dashboards are configured\n </div>\n }\n\n @for (dashboard of availableDashboards; track dashboard.ID) {\n <div class=\"dashboard-item available-item\"\n cdkDrag\n [cdkDragData]=\"dashboard\">\n <div class=\"dashboard-item-content\">\n <i class=\"fa-solid fa-grip-vertical drag-handle\"></i>\n <div class=\"dashboard-info\">\n <span class=\"dashboard-name\">{{ dashboard.Name }}</span>\n @if (dashboard.Description) {\n <span class=\"dashboard-description\">{{ dashboard.Description }}</span>\n }\n </div>\n <button type=\"button\"\n class=\"add-button\"\n (click)=\"addDashboard(dashboard)\"\n title=\"Add to configured dashboards\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Configured Dashboards Panel -->\n <div class=\"panel configured-panel\">\n <h4><i class=\"fa-solid fa-list-ol\"></i> Configured Dashboards</h4>\n <div class=\"dashboard-list\"\n cdkDropList\n #configuredList=\"cdkDropList\"\n [cdkDropListData]=\"configuredDashboards\"\n [cdkDropListConnectedTo]=\"[availableList]\"\n (cdkDropListDropped)=\"onDrop($event)\">\n\n @if (configuredDashboards.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-info-circle\"></i>\n No dashboards configured\n </div>\n }\n\n @for (dashboard of configuredDashboards; track dashboard.ID; let i = $index) {\n <div class=\"dashboard-item configured-item\"\n cdkDrag\n [cdkDragData]=\"dashboard\">\n <div class=\"dashboard-item-content\">\n <i class=\"fa-solid fa-grip-vertical drag-handle\"></i>\n <span class=\"order-number\">{{ i + 1 }}</span>\n <div class=\"dashboard-info\">\n <span class=\"dashboard-name\">{{ dashboard.Name }}</span>\n @if (dashboard.Description) {\n <span class=\"dashboard-description\">{{ dashboard.Description }}</span>\n }\n </div>\n <button type=\"button\"\n class=\"remove-button\"\n (click)=\"removeDashboard(dashboard)\"\n title=\"Remove from configured dashboards\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n <mj-dialog-actions>\n <button type=\"button\"\n class=\"btn btn-secondary\"\n (click)=\"onCancel()\">\n <i class=\"fa-solid fa-times\"></i> Cancel\n </button>\n <button type=\"button\"\n class=\"btn btn-primary\"\n [disabled]=\"!hasChanges || saving\"\n (click)=\"onSave()\">\n @if (saving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n Saving...\n } @else {\n <i class=\"fa-solid fa-check\"></i> Save Changes\n }\n </button>\n </mj-dialog-actions>\n</div>\n</mj-dialog>\n", styles: [".dashboard-preferences-dialog {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.dialog-header {\n padding: 20px 24px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.dialog-header h3 {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.dialog-header h3 i {\n margin-right: 8px;\n color: var(--mj-text-secondary);\n}\n\n.scope-indicator {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.scope-indicator i {\n margin-right: 6px;\n}\n\n.preference-mode-selector {\n margin-top: 12px;\n display: flex;\n gap: 20px;\n}\n\n.preference-mode-selector label {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.preference-mode-selector input[type=\"radio\"] {\n margin: 0;\n}\n\n.dialog-content {\n flex: 1;\n overflow: hidden;\n padding: 20px 24px;\n}\n\n.loading-container, .error-container {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n flex-direction: column;\n gap: 12px;\n}\n\n.error-container {\n color: var(--mj-status-error);\n}\n\n.error-container i {\n font-size: 24px;\n margin-bottom: 8px;\n}\n\n.preferences-panels {\n display: flex;\n gap: 20px;\n height: 100%;\n}\n\n.panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.panel h4 {\n margin: 0;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.panel h4 i {\n margin-right: 8px;\n color: var(--mj-text-muted);\n}\n\n.dashboard-list {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n}\n\n.empty-state {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100px;\n color: var(--mj-text-muted);\n font-style: italic;\n flex-direction: column;\n gap: 8px;\n}\n\n.empty-state i {\n font-size: 24px;\n opacity: 0.5;\n}\n\n.dashboard-item {\n margin-bottom: 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n cursor: move;\n}\n\n.dashboard-item:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 4px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.dashboard-item.cdk-drag-preview {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform: rotate(2deg);\n}\n\n.dashboard-item.cdk-drag-placeholder {\n opacity: 0.3;\n border-style: dashed;\n}\n\n.dashboard-item-content {\n display: flex;\n align-items: center;\n padding: 12px;\n gap: 12px;\n}\n\n.drag-handle {\n color: var(--mj-text-disabled);\n cursor: move;\n font-size: 14px;\n}\n\n.order-number {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: var(--mj-brand-primary);\n color: white;\n border-radius: 50%;\n font-size: 12px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.dashboard-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.dashboard-name {\n font-weight: 500;\n color: var(--mj-text-primary);\n font-size: 14px;\n}\n\n.dashboard-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.3;\n}\n\n.add-button {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--mj-status-success);\n border-radius: 4px;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n opacity: 0.7;\n}\n\n.add-button:hover {\n background-color: color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n opacity: 1;\n}\n\n.remove-button {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--mj-status-error);\n border-radius: 4px;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n}\n\n.remove-button:hover {\n background-color: color-mix(in srgb, var(--mj-status-error) 10%, transparent);\n}\n\n.cdk-drop-list-dragging .dashboard-item:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.dialog-footer {\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n background: var(--mj-bg-surface-card);\n}\n\n.btn {\n padding: 8px 16px;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n border: 1px solid transparent;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-secondary {\n background: var(--mj-bg-surface);\n border-color: var(--mj-text-muted);\n color: var(--mj-text-muted);\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--mj-text-muted);\n color: white;\n}\n\n.btn-primary {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n}\n\n.btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n/* Responsive design */\n@media (max-width: 768px) {\n .dashboard-preferences-dialog {\n width: 95vw;\n max-height: 90vh;\n }\n\n .preferences-panels {\n flex-direction: column;\n gap: 16px;\n }\n\n .panel {\n min-height: 200px;\n }\n\n .dashboard-list {\n min-height: 150px;\n }\n}\n"] }]
|
|
554
|
+
args: [{ standalone: false, selector: 'mj-dashboard-preferences-dialog', template: "<mj-dialog [Visible]=\"true\" Title=\"Dashboard Preferences\"\n [Width]=\"800\"\n [Height]=\"600\"\n [MinWidth]=\"600\"\n (Close)=\"onCancel()\">\n<div class=\"dashboard-preferences-dialog\">\n <div class=\"dialog-header\">\n <h3><i class=\"fa-solid fa-sliders\"></i> Dashboard Preferences</h3>\n <p class=\"scope-indicator\">\n @if (scope === 'Global') {\n <i class=\"fa-solid fa-globe\"></i> Global Scope\n } @else {\n <i class=\"fa-solid fa-layer-group\"></i> Application: {{ applicationName }}\n }\n </p>\n @if (isSysAdmin && scope === 'Global') {\n <div class=\"preference-mode-selector\">\n <label>\n <input type=\"radio\"\n name=\"preferenceMode\"\n value=\"personal\"\n [(ngModel)]=\"preferenceMode\"\n (change)=\"onPreferenceModeChange()\">\n Personal Preferences\n </label>\n <label>\n <input type=\"radio\"\n name=\"preferenceMode\"\n value=\"system\"\n [(ngModel)]=\"preferenceMode\"\n (change)=\"onPreferenceModeChange()\">\n System Defaults\n </label>\n </div>\n }\n </div>\n\n <div class=\"dialog-content\">\n @if (loading) {\n <div class=\"loading-overlay\">\n <mj-loading text=\"Loading preferences...\" size=\"large\"></mj-loading>\n </div>\n }\n\n @if (error) {\n <mj-empty-state\n Variant=\"error\"\n Size=\"compact\"\n Icon=\"fa-solid fa-triangle-exclamation\"\n [Title]=\"error\" />\n }\n\n @if (!loading && !error) {\n <div class=\"preferences-panels\">\n <!-- Available Dashboards Panel -->\n <div class=\"panel available-panel\">\n <h4><i class=\"fa-solid fa-list\"></i> Available Dashboards</h4>\n <div class=\"dashboard-list\"\n cdkDropList\n #availableList=\"cdkDropList\"\n [cdkDropListData]=\"availableDashboards\"\n [cdkDropListConnectedTo]=\"[configuredList]\"\n (cdkDropListDropped)=\"onDrop($event)\">\n\n @if (availableDashboards.length === 0) {\n <mj-empty-state\n Variant=\"success\"\n Size=\"compact\"\n Icon=\"fa-solid fa-circle-check\"\n Title=\"All dashboards are configured\" />\n }\n\n @for (dashboard of availableDashboards; track dashboard.ID) {\n <div class=\"dashboard-item available-item\"\n cdkDrag\n [cdkDragData]=\"dashboard\">\n <div class=\"dashboard-item-content\">\n <i class=\"fa-solid fa-grip-vertical drag-handle\"></i>\n <div class=\"dashboard-info\">\n <span class=\"dashboard-name\">{{ dashboard.Name }}</span>\n @if (dashboard.Description) {\n <span class=\"dashboard-description\">{{ dashboard.Description }}</span>\n }\n </div>\n <button type=\"button\"\n class=\"add-button\"\n (click)=\"addDashboard(dashboard)\"\n title=\"Add to configured dashboards\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Configured Dashboards Panel -->\n <div class=\"panel configured-panel\">\n <h4><i class=\"fa-solid fa-list-ol\"></i> Configured Dashboards</h4>\n <div class=\"dashboard-list\"\n cdkDropList\n #configuredList=\"cdkDropList\"\n [cdkDropListData]=\"configuredDashboards\"\n [cdkDropListConnectedTo]=\"[availableList]\"\n (cdkDropListDropped)=\"onDrop($event)\">\n\n @if (configuredDashboards.length === 0) {\n <mj-empty-state\n Size=\"compact\"\n Icon=\"fa-solid fa-circle-info\"\n Title=\"No dashboards configured\" />\n }\n\n @for (dashboard of configuredDashboards; track dashboard.ID; let i = $index) {\n <div class=\"dashboard-item configured-item\"\n cdkDrag\n [cdkDragData]=\"dashboard\">\n <div class=\"dashboard-item-content\">\n <i class=\"fa-solid fa-grip-vertical drag-handle\"></i>\n <span class=\"order-number\">{{ i + 1 }}</span>\n <div class=\"dashboard-info\">\n <span class=\"dashboard-name\">{{ dashboard.Name }}</span>\n @if (dashboard.Description) {\n <span class=\"dashboard-description\">{{ dashboard.Description }}</span>\n }\n </div>\n <button type=\"button\"\n class=\"remove-button\"\n (click)=\"removeDashboard(dashboard)\"\n title=\"Remove from configured dashboards\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n <mj-dialog-actions>\n <button type=\"button\"\n class=\"btn btn-secondary\"\n (click)=\"onCancel()\">\n <i class=\"fa-solid fa-times\"></i> Cancel\n </button>\n <button type=\"button\"\n class=\"btn btn-primary\"\n [disabled]=\"!hasChanges || saving\"\n (click)=\"onSave()\">\n @if (saving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n Saving...\n } @else {\n <i class=\"fa-solid fa-check\"></i> Save Changes\n }\n </button>\n </mj-dialog-actions>\n</div>\n</mj-dialog>\n", styles: [".dashboard-preferences-dialog {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.dialog-header {\n padding: 20px 24px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.dialog-header h3 {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.dialog-header h3 i {\n margin-right: 8px;\n color: var(--mj-text-secondary);\n}\n\n.scope-indicator {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.scope-indicator i {\n margin-right: 6px;\n}\n\n.preference-mode-selector {\n margin-top: 12px;\n display: flex;\n gap: 20px;\n}\n\n.preference-mode-selector label {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.preference-mode-selector input[type=\"radio\"] {\n margin: 0;\n}\n\n.dialog-content {\n flex: 1;\n overflow: hidden;\n padding: 20px 24px;\n}\n\n.loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n flex-direction: column;\n gap: 12px;\n}\n\n.preferences-panels {\n display: flex;\n gap: 20px;\n height: 100%;\n}\n\n.panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.panel h4 {\n margin: 0;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.panel h4 i {\n margin-right: 8px;\n color: var(--mj-text-muted);\n}\n\n.dashboard-list {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n}\n\n.dashboard-item {\n margin-bottom: 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n transition: all 0.2s ease;\n cursor: move;\n}\n\n.dashboard-item:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 4px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.dashboard-item.cdk-drag-preview {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform: rotate(2deg);\n}\n\n.dashboard-item.cdk-drag-placeholder {\n opacity: 0.3;\n border-style: dashed;\n}\n\n.dashboard-item-content {\n display: flex;\n align-items: center;\n padding: 12px;\n gap: 12px;\n}\n\n.drag-handle {\n color: var(--mj-text-disabled);\n cursor: move;\n font-size: 14px;\n}\n\n.order-number {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: var(--mj-brand-primary);\n color: white;\n border-radius: 50%;\n font-size: 12px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.dashboard-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.dashboard-name {\n font-weight: 500;\n color: var(--mj-text-primary);\n font-size: 14px;\n}\n\n.dashboard-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.3;\n}\n\n.add-button {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--mj-status-success);\n border-radius: 4px;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n opacity: 0.7;\n}\n\n.add-button:hover {\n background-color: color-mix(in srgb, var(--mj-status-success) 10%, transparent);\n opacity: 1;\n}\n\n.remove-button {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--mj-status-error);\n border-radius: 4px;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n}\n\n.remove-button:hover {\n background-color: color-mix(in srgb, var(--mj-status-error) 10%, transparent);\n}\n\n.cdk-drop-list-dragging .dashboard-item:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.dialog-footer {\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n background: var(--mj-bg-surface-card);\n}\n\n.btn {\n padding: 8px 16px;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n border: 1px solid transparent;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-secondary {\n background: var(--mj-bg-surface);\n border-color: var(--mj-text-muted);\n color: var(--mj-text-muted);\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--mj-text-muted);\n color: white;\n}\n\n.btn-primary {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n}\n\n.btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n/* Responsive design */\n@media (max-width: 768px) {\n .dashboard-preferences-dialog {\n width: 95vw;\n max-height: 90vh;\n }\n\n .preferences-panels {\n flex-direction: column;\n gap: 16px;\n }\n\n .panel {\n min-height: 200px;\n }\n\n .dashboard-list {\n min-height: 150px;\n }\n}\n"] }]
|
|
565
555
|
}], null, { applicationId: [{
|
|
566
556
|
type: Input
|
|
567
557
|
}], scope: [{
|