@memberjunction/ng-tasks 5.11.0 → 5.13.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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @memberjunction/ng-tasks@5.11.0 build
2
+ > @memberjunction/ng-tasks@5.13.0 build
3
3
  > ngc
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @memberjunction/ng-tasks
2
2
 
3
+ ## 5.13.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [f72b538]
8
+ - Updated dependencies [d0d9eba]
9
+ - @memberjunction/core@5.13.0
10
+ - @memberjunction/ai-engine-base@5.13.0
11
+ - @memberjunction/ai-core-plus@5.13.0
12
+ - @memberjunction/core-entities@5.13.0
13
+
14
+ ## 5.12.0
15
+
16
+ ### Patch Changes
17
+
18
+ - a57b8d5: Migrate all hardcoded CSS colors to design tokens for dark mode and white-label support. Introduces `--mj-*` semantic CSS custom properties in `_tokens.scss` with full `[data-theme="dark"]` overrides. Migrates 1,544 of 1,659 hardcoded hex values (93%) across 72+ CSS files to semantic tokens. Adds logo token system (`--mj-logo-mark`, `--mj-logo-color`) for themeable branding. Fixes dark mode theming for CodeMirror, AG Grid v35, and Kendo popups. No API or behavioral changes — CSS only.
19
+ - e87d153: design tokens phase 1
20
+ - Updated dependencies [05f19ff]
21
+ - Updated dependencies [d92502e]
22
+ - Updated dependencies [1567293]
23
+ - Updated dependencies [1e5d181]
24
+ - @memberjunction/core@5.12.0
25
+ - @memberjunction/core-entities@5.12.0
26
+ - @memberjunction/ai-engine-base@5.12.0
27
+ - @memberjunction/ai-core-plus@5.12.0
28
+
3
29
  ## 5.11.0
4
30
 
5
31
  ### Patch Changes
@@ -410,7 +410,7 @@ export class GanttTaskViewerComponent {
410
410
  i0.ɵɵconditional(!ctx.tasks || ctx.tasks.length === 0 ? 1 : -1);
411
411
  i0.ɵɵadvance();
412
412
  i0.ɵɵconditional(ctx.tasks && ctx.tasks.length > 0 ? 2 : -1);
413
- } }, dependencies: [TaskDetailPanelComponent], styles: [".gantt-task-viewer[_ngcontent-%COMP%] {\n height: 100%;\n background: white;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .gantt-layout[_ngcontent-%COMP%] {\n display: flex;\n height: 600px;\n position: relative;\n }\n\n .gantt-container[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 400px;\n height: 100%;\n position: relative;\n }\n\n .gantt-resizer[_ngcontent-%COMP%] {\n width: 4px;\n background: #E5E7EB;\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .gantt-resizer[_ngcontent-%COMP%]:hover {\n background: #3B82F6;\n }\n\n .task-detail-panel[_ngcontent-%COMP%] {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n border-left: 1px solid #E5E7EB;\n flex-shrink: 0;\n }\n\n \n\n [_nghost-%COMP%] .gantt_container {\n font-family: inherit;\n font-size: 13px;\n }\n\n [_nghost-%COMP%] .gantt_grid_scale, \n [_nghost-%COMP%] .gantt_task_scale {\n background: #F9FAFB;\n border-bottom: 2px solid #E5E7EB;\n }\n\n [_nghost-%COMP%] .gantt_task .gantt_task_content {\n font-weight: 500;\n }\n\n .no-tasks[_ngcontent-%COMP%] {\n text-align: center;\n padding: 80px 20px;\n color: #9CA3AF;\n }\n\n .no-tasks[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 64px;\n opacity: 0.3;\n margin-bottom: 16px;\n }\n\n .no-tasks[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n }"] });
413
+ } }, dependencies: [TaskDetailPanelComponent], styles: [".gantt-task-viewer[_ngcontent-%COMP%] {\n height: 100%;\n background: var(--mj-bg-surface);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .gantt-layout[_ngcontent-%COMP%] {\n display: flex;\n height: 600px;\n position: relative;\n }\n\n .gantt-container[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 400px;\n height: 100%;\n position: relative;\n }\n\n .gantt-resizer[_ngcontent-%COMP%] {\n width: 4px;\n background: var(--mj-border-default);\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .gantt-resizer[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n }\n\n .task-detail-panel[_ngcontent-%COMP%] {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n border-left: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n }\n\n \n\n [_nghost-%COMP%] .gantt_container {\n font-family: inherit;\n font-size: 13px;\n }\n\n [_nghost-%COMP%] .gantt_grid_scale, \n [_nghost-%COMP%] .gantt_task_scale {\n background: var(--mj-bg-surface-sunken);\n border-bottom: 2px solid var(--mj-border-default);\n }\n\n [_nghost-%COMP%] .gantt_task .gantt_task_content {\n font-weight: 500;\n }\n\n .no-tasks[_ngcontent-%COMP%] {\n text-align: center;\n padding: 80px 20px;\n color: var(--mj-text-disabled);\n }\n\n .no-tasks[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 64px;\n opacity: 0.3;\n margin-bottom: 16px;\n }\n\n .no-tasks[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n }"] });
414
414
  }
415
415
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(GanttTaskViewerComponent, [{
416
416
  type: Component,
@@ -443,7 +443,7 @@ export class GanttTaskViewerComponent {
443
443
  </div>
444
444
  }
445
445
  </div>
446
- `, styles: ["\n .gantt-task-viewer {\n height: 100%;\n background: white;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .gantt-layout {\n display: flex;\n height: 600px;\n position: relative;\n }\n\n .gantt-container {\n flex: 1;\n min-width: 400px;\n height: 100%;\n position: relative;\n }\n\n .gantt-resizer {\n width: 4px;\n background: #E5E7EB;\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .gantt-resizer:hover {\n background: #3B82F6;\n }\n\n .task-detail-panel {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n border-left: 1px solid #E5E7EB;\n flex-shrink: 0;\n }\n\n /* Override DHTMLX Gantt default styles */\n :host ::ng-deep .gantt_container {\n font-family: inherit;\n font-size: 13px;\n }\n\n :host ::ng-deep .gantt_grid_scale,\n :host ::ng-deep .gantt_task_scale {\n background: #F9FAFB;\n border-bottom: 2px solid #E5E7EB;\n }\n\n :host ::ng-deep .gantt_task .gantt_task_content {\n font-weight: 500;\n }\n\n .no-tasks {\n text-align: center;\n padding: 80px 20px;\n color: #9CA3AF;\n }\n\n .no-tasks i {\n font-size: 64px;\n opacity: 0.3;\n margin-bottom: 16px;\n }\n\n .no-tasks p {\n margin: 0;\n font-size: 14px;\n }\n "] }]
446
+ `, styles: ["\n .gantt-task-viewer {\n height: 100%;\n background: var(--mj-bg-surface);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .gantt-layout {\n display: flex;\n height: 600px;\n position: relative;\n }\n\n .gantt-container {\n flex: 1;\n min-width: 400px;\n height: 100%;\n position: relative;\n }\n\n .gantt-resizer {\n width: 4px;\n background: var(--mj-border-default);\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .gantt-resizer:hover {\n background: var(--mj-brand-primary);\n }\n\n .task-detail-panel {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n border-left: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n }\n\n /* Override DHTMLX Gantt default styles */\n :host ::ng-deep .gantt_container {\n font-family: inherit;\n font-size: 13px;\n }\n\n :host ::ng-deep .gantt_grid_scale,\n :host ::ng-deep .gantt_task_scale {\n background: var(--mj-bg-surface-sunken);\n border-bottom: 2px solid var(--mj-border-default);\n }\n\n :host ::ng-deep .gantt_task .gantt_task_content {\n font-weight: 500;\n }\n\n .no-tasks {\n text-align: center;\n padding: 80px 20px;\n color: var(--mj-text-disabled);\n }\n\n .no-tasks i {\n font-size: 64px;\n opacity: 0.3;\n margin-bottom: 16px;\n }\n\n .no-tasks p {\n margin: 0;\n font-size: 14px;\n }\n "] }]
447
447
  }], null, { tasks: [{
448
448
  type: Input
449
449
  }], taskDependencies: [{
@@ -1 +1 @@
1
- {"version":3,"file":"gantt-task-viewer.component.js","sourceRoot":"","sources":["../../../src/lib/components/gantt-task-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnChanges, AfterViewInit, ElementRef, ViewChild, OnDestroy, HostListener } from '@angular/core';\n\nimport { MJTaskEntity, MJTaskDependencyEntity } from '@memberjunction/core-entities';\nimport { gantt } from 'dhtmlx-gantt';\nimport { TaskDetailPanelComponent } from './task-detail-panel.component';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Gantt chart view for tasks using DHTMLX Gantt\n */\n@Component({\n selector: 'mj-gantt-task-viewer',\n standalone: true,\n imports: [TaskDetailPanelComponent],\n template: `\n <div class=\"gantt-task-viewer\">\n @if (!tasks || tasks.length === 0) {\n <div class=\"no-tasks\">\n <i class=\"fas fa-chart-gantt\"></i>\n <p>No tasks to display in Gantt view</p>\n </div>\n }\n \n @if (tasks && tasks.length > 0) {\n <div class=\"gantt-layout\">\n <div #ganttContainer class=\"gantt-container\"></div>\n @if (selectedTask) {\n <div class=\"gantt-resizer\"\n (mousedown)=\"startResize($event)\"></div>\n }\n @if (selectedTask) {\n <div class=\"task-detail-panel\" [style.width.px]=\"detailPanelWidth\">\n <mj-task-detail-panel\n [task]=\"selectedTask\"\n [agentRunId]=\"getAgentRunId(selectedTask)\"\n (closePanel)=\"closeDetailPanel()\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-task-detail-panel>\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [`\n .gantt-task-viewer {\n height: 100%;\n background: white;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .gantt-layout {\n display: flex;\n height: 600px;\n position: relative;\n }\n\n .gantt-container {\n flex: 1;\n min-width: 400px;\n height: 100%;\n position: relative;\n }\n\n .gantt-resizer {\n width: 4px;\n background: #E5E7EB;\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .gantt-resizer:hover {\n background: #3B82F6;\n }\n\n .task-detail-panel {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n border-left: 1px solid #E5E7EB;\n flex-shrink: 0;\n }\n\n /* Override DHTMLX Gantt default styles */\n :host ::ng-deep .gantt_container {\n font-family: inherit;\n font-size: 13px;\n }\n\n :host ::ng-deep .gantt_grid_scale,\n :host ::ng-deep .gantt_task_scale {\n background: #F9FAFB;\n border-bottom: 2px solid #E5E7EB;\n }\n\n :host ::ng-deep .gantt_task .gantt_task_content {\n font-weight: 500;\n }\n\n .no-tasks {\n text-align: center;\n padding: 80px 20px;\n color: #9CA3AF;\n }\n\n .no-tasks i {\n font-size: 64px;\n opacity: 0.3;\n margin-bottom: 16px;\n }\n\n .no-tasks p {\n margin: 0;\n font-size: 14px;\n }\n `]\n})\nexport class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDestroy {\n @Input() tasks: MJTaskEntity[] = [];\n @Input() taskDependencies: MJTaskDependencyEntity[] = [];\n @Input() agentRunMap?: Map<string, string>; // Maps TaskID -> AgentRunID\n @Output() taskClicked = new EventEmitter<MJTaskEntity>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n\n @ViewChild('ganttContainer', { static: false }) ganttContainer!: ElementRef<HTMLDivElement>;\n\n public selectedTask: MJTaskEntity | null = null;\n public detailPanelWidth: number = 400;\n\n private ganttInitialized = false;\n private isResizing = false;\n private resizeStartX = 0;\n private resizeStartWidth = 0;\n\n ngAfterViewInit() {\n console.log('🔧 ngAfterViewInit called', {\n taskCount: this.tasks?.length || 0,\n hasContainer: !!this.ganttContainer\n });\n\n if (this.tasks && this.tasks.length > 0 && this.ganttContainer) {\n this.initGantt();\n }\n }\n\n ngOnChanges() {\n console.log('🔄 ngOnChanges called', {\n initialized: this.ganttInitialized,\n hasContainer: !!this.ganttContainer,\n taskCount: this.tasks?.length || 0\n });\n\n if (this.ganttInitialized && this.ganttContainer) {\n this.updateGanttData();\n } else if (!this.ganttInitialized && this.ganttContainer && this.tasks && this.tasks.length > 0) {\n // Initialize if we have container and tasks but haven't initialized yet\n console.log('🎨 Late initialization - gantt not initialized but container and tasks available');\n this.initGantt();\n }\n }\n\n ngOnDestroy() {\n if (this.ganttInitialized) {\n gantt.clearAll();\n this.ganttInitialized = false;\n }\n }\n\n private initGantt(): void {\n try {\n console.log('🎨 Initializing DHTMLX Gantt');\n\n // IMPORTANT: Clear any previous configuration\n gantt.clearAll();\n\n // Configure Gantt layout and appearance\n gantt.config.date_format = '%Y-%m-%d %H:%i';\n gantt.config.scale_unit = 'day';\n gantt.config.date_scale = '%d %M';\n gantt.config.subscales = [];\n gantt.config.show_progress = true;\n gantt.config.show_links = true;\n gantt.config.auto_types = true;\n gantt.config.readonly = true; // Read-only for now\n gantt.config.fit_tasks = true; // Auto-fit timeline to tasks\n\n // Disable auto-scheduling - we calculate dates ourselves based on dependencies\n gantt.config.auto_scheduling = false;\n\n // Grid configuration\n gantt.config.grid_width = 350;\n gantt.config.row_height = 36;\n gantt.config.scale_height = 0; // Hide date scale - dates are just for positioning\n\n // Layout configuration - ensure timeline is visible\n gantt.config.layout = {\n css: \"gantt_container\",\n rows: [\n {\n cols: [\n { view: \"grid\", group: \"grids\", scrollY: \"scrollVer\" },\n { resizer: true, width: 1 },\n { view: \"timeline\", scrollX: \"scrollHor\", scrollY: \"scrollVer\" },\n { view: \"scrollbar\", id: \"scrollVer\", group: \"vertical\" }\n ]\n },\n { view: \"scrollbar\", id: \"scrollHor\", group: \"horizontal\" }\n ]\n };\n\n // Column configuration - only show task names, hide dates\n gantt.config.columns = [\n { name: 'text', label: 'Task name', tree: true, width: '*' }\n ];\n\n // Initialize Gantt in the container\n gantt.init(this.ganttContainer.nativeElement);\n this.ganttInitialized = true;\n\n // Attach click event\n gantt.attachEvent('onTaskClick', (id: string) => {\n const originalTask = this.tasks.find(t => UUIDsEqual(t.ID, id));\n if (originalTask) {\n this.selectedTask = originalTask;\n this.taskClicked.emit(originalTask);\n }\n return true;\n });\n\n // Load data\n this.updateGanttData();\n\n // Force resize after data load to ensure proper rendering\n setTimeout(() => {\n gantt.setSizes();\n }, 0);\n\n // Expand and select after render completes\n setTimeout(() => {\n this.expandAllAndSelectRoot();\n }, 100);\n\n console.log('✅ DHTMLX Gantt initialized successfully');\n } catch (error) {\n console.error('❌ Error initializing Gantt:', error);\n }\n }\n\n private updateGanttData(): void {\n if (!this.ganttInitialized) return;\n\n try {\n console.log('📊 Updating Gantt data with', this.tasks.length, 'tasks');\n\n const ganttData = this.convertToGanttFormat(this.tasks);\n gantt.clearAll();\n gantt.parse(ganttData);\n\n // Log final parsed data for debugging\n console.log('📋 Gantt data after parse:', {\n tasks: gantt.getTaskByTime(),\n links: gantt.getLinks()\n });\n\n // Force resize after data update\n setTimeout(() => {\n gantt.setSizes();\n }, 0);\n\n // Expand and select after render completes\n setTimeout(() => {\n this.expandAllAndSelectRoot();\n }, 100);\n\n console.log('✅ Gantt data updated');\n } catch (error) {\n console.error('❌ Error updating Gantt data:', error);\n }\n }\n\n private convertToGanttFormat(tasks: MJTaskEntity[]): { data: any[], links: any[] } {\n const data: any[] = [];\n const links: any[] = [];\n\n console.log('🔍 Converting tasks:', tasks);\n console.log('🔗 Task dependencies:', this.taskDependencies);\n\n // Build a map of task ID to task for quick lookup\n const taskMap = new Map<string, MJTaskEntity>();\n tasks.forEach(t => taskMap.set(t.ID, t));\n\n // Build dependency map: taskId -> array of tasks it depends on\n const dependencyMap = new Map<string, string[]>();\n this.taskDependencies.forEach(dep => {\n if (!dependencyMap.has(dep.TaskID)) {\n dependencyMap.set(dep.TaskID, []);\n }\n dependencyMap.get(dep.TaskID)!.push(dep.DependsOnTaskID);\n });\n\n // Calculate start dates based on dependencies\n const taskStartDates = new Map<string, Date>();\n const baseDate = new Date();\n baseDate.setHours(0, 0, 0, 0);\n\n // Recursive function to calculate start date for a task\n const calculateStartDate = (taskId: string, visited = new Set<string>()): Date => {\n // Prevent circular dependencies\n if (visited.has(taskId)) {\n return new Date(baseDate);\n }\n visited.add(taskId);\n\n // If already calculated, return it\n if (taskStartDates.has(taskId)) {\n return taskStartDates.get(taskId)!;\n }\n\n const task = taskMap.get(taskId);\n if (!task) return new Date(baseDate);\n\n const dependencies = dependencyMap.get(taskId) || [];\n\n if (dependencies.length === 0) {\n // No dependencies - use base date or task's actual start date\n const startDate = task.StartedAt ? new Date(task.StartedAt) : new Date(baseDate);\n taskStartDates.set(taskId, startDate);\n return startDate;\n }\n\n // Has dependencies - start after the latest dependency ends\n let latestEnd = new Date(baseDate);\n for (const depId of dependencies) {\n const depTask = taskMap.get(depId);\n if (depTask) {\n const depStart = calculateStartDate(depId, new Set(visited));\n const depDuration = this.calculateDuration(depTask);\n const depEnd = new Date(depStart);\n depEnd.setDate(depEnd.getDate() + depDuration);\n\n if (depEnd > latestEnd) {\n latestEnd = depEnd;\n }\n }\n }\n\n taskStartDates.set(taskId, latestEnd);\n return latestEnd;\n };\n\n // Calculate start dates for all tasks\n tasks.forEach(task => calculateStartDate(task.ID));\n\n // Calculate min/max dates for timeline display range\n let minDate: Date | null = null;\n let maxDate: Date | null = null;\n\n tasks.forEach(task => {\n const startDate = taskStartDates.get(task.ID);\n if (startDate) {\n const duration = this.calculateDuration(task);\n const endDate = new Date(startDate);\n endDate.setDate(endDate.getDate() + duration);\n\n if (!minDate || startDate < minDate) {\n minDate = startDate;\n }\n if (!maxDate || endDate > maxDate) {\n maxDate = endDate;\n }\n }\n });\n\n // Add 1 day padding before and after\n if (minDate) {\n const paddedStart = new Date(minDate);\n paddedStart.setDate(paddedStart.getDate() - 1);\n gantt.config.start_date = paddedStart;\n }\n if (maxDate) {\n const paddedEnd = new Date(maxDate);\n paddedEnd.setDate(paddedEnd.getDate() + 1);\n gantt.config.end_date = paddedEnd;\n }\n\n // Now create Gantt tasks with calculated dates\n tasks.forEach((task) => {\n console.log('📝 Processing task:', {\n ID: task.ID,\n Name: task.Name,\n ParentID: task.ParentID\n });\n\n // Calculate progress (0-1 scale for DHTMLX)\n let progress = (task.PercentComplete || 0) / 100;\n if (task.Status === 'Complete') {\n progress = 1;\n }\n\n const duration = this.calculateDuration(task);\n const startDate = taskStartDates.get(task.ID) || new Date(baseDate);\n\n const ganttTask: any = {\n id: task.ID,\n text: task.Name || 'Untitled Task',\n start_date: this.formatDateForDHTMLX(startDate),\n duration: duration,\n progress: progress\n };\n\n // Add parent relationship for tree structure (not dependency)\n if (task.ParentID) {\n ganttTask.parent = task.ParentID;\n } else {\n // Root tasks need parent: 0\n ganttTask.parent = 0;\n }\n\n console.log('✅ Created Gantt task:', ganttTask);\n data.push(ganttTask);\n });\n\n // Create links from MJTaskDependencyEntity records\n this.taskDependencies.forEach((dep, index) => {\n links.push({\n id: dep.ID || `link_${index}`,\n source: dep.DependsOnTaskID, // The task being depended on\n target: dep.TaskID, // The task that depends on it\n type: '0' // finish-to-start (DHTMLX type 0)\n });\n console.log(`🔗 Created link: ${dep.DependsOnTaskID} -> ${dep.TaskID}`);\n });\n\n console.log('📊 Final DHTMLX format:', { data, links });\n return { data, links };\n }\n\n private calculateDuration(task: MJTaskEntity): number {\n if (task.StartedAt && task.DueAt) {\n const startDate = new Date(task.StartedAt);\n const endDate = new Date(task.DueAt);\n return Math.max(1, Math.ceil((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24)));\n }\n return 1; // Default to 1 day\n }\n\n private formatDateForDHTMLX(date: Date): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return `${year}-${month}-${day} 00:00`;\n }\n\n public getAgentRunId(task: MJTaskEntity): string | null {\n return this.agentRunMap?.get(task.ID) || null;\n }\n\n public closeDetailPanel(): void {\n this.selectedTask = null;\n }\n\n public onOpenEntityRecord(event: { entityName: string; recordId: string }): void {\n this.openEntityRecord.emit(event);\n }\n\n public startResize(event: MouseEvent): void {\n this.isResizing = true;\n this.resizeStartX = event.clientX;\n this.resizeStartWidth = this.detailPanelWidth;\n event.preventDefault();\n }\n\n @HostListener('document:mousemove', ['$event'])\n handleResize(event: MouseEvent): void {\n if (!this.isResizing) return;\n\n const delta = this.resizeStartX - event.clientX;\n const newWidth = this.resizeStartWidth + delta;\n\n // Constrain width between min and max\n this.detailPanelWidth = Math.max(300, Math.min(600, newWidth));\n }\n\n @HostListener('document:mouseup')\n stopResize(): void {\n if (this.isResizing) {\n this.isResizing = false;\n // Resize gantt chart after panel resize completes\n setTimeout(() => {\n if (this.ganttInitialized) {\n gantt.setSizes();\n }\n }, 0);\n }\n }\n\n private expandAllAndSelectRoot(): void {\n try {\n // Expand all tasks\n gantt.eachTask((task: any) => {\n gantt.open(task.id);\n });\n\n // Find and select the root task (task with parent = 0)\n let rootTask: any = null;\n gantt.eachTask((task: any) => {\n if (task.parent === 0 || task.parent === '0') {\n rootTask = task;\n return false; // Stop iteration\n }\n });\n\n if (rootTask) {\n gantt.selectTask(rootTask.id);\n // Trigger task click event to open detail panel\n const originalTask = this.tasks.find(t => UUIDsEqual(t.ID, rootTask.id));\n if (originalTask) {\n this.selectedTask = originalTask;\n this.taskClicked.emit(originalTask);\n }\n }\n\n console.log('✅ Expanded all tasks and selected root:', rootTask?.id);\n } catch (error) {\n console.error('❌ Error expanding/selecting tasks:', error);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"gantt-task-viewer.component.js","sourceRoot":"","sources":["../../../src/lib/components/gantt-task-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnChanges, AfterViewInit, ElementRef, ViewChild, OnDestroy, HostListener } from '@angular/core';\n\nimport { MJTaskEntity, MJTaskDependencyEntity } from '@memberjunction/core-entities';\nimport { gantt } from 'dhtmlx-gantt';\nimport { TaskDetailPanelComponent } from './task-detail-panel.component';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Gantt chart view for tasks using DHTMLX Gantt\n */\n@Component({\n selector: 'mj-gantt-task-viewer',\n standalone: true,\n imports: [TaskDetailPanelComponent],\n template: `\n <div class=\"gantt-task-viewer\">\n @if (!tasks || tasks.length === 0) {\n <div class=\"no-tasks\">\n <i class=\"fas fa-chart-gantt\"></i>\n <p>No tasks to display in Gantt view</p>\n </div>\n }\n \n @if (tasks && tasks.length > 0) {\n <div class=\"gantt-layout\">\n <div #ganttContainer class=\"gantt-container\"></div>\n @if (selectedTask) {\n <div class=\"gantt-resizer\"\n (mousedown)=\"startResize($event)\"></div>\n }\n @if (selectedTask) {\n <div class=\"task-detail-panel\" [style.width.px]=\"detailPanelWidth\">\n <mj-task-detail-panel\n [task]=\"selectedTask\"\n [agentRunId]=\"getAgentRunId(selectedTask)\"\n (closePanel)=\"closeDetailPanel()\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-task-detail-panel>\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [`\n .gantt-task-viewer {\n height: 100%;\n background: var(--mj-bg-surface);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .gantt-layout {\n display: flex;\n height: 600px;\n position: relative;\n }\n\n .gantt-container {\n flex: 1;\n min-width: 400px;\n height: 100%;\n position: relative;\n }\n\n .gantt-resizer {\n width: 4px;\n background: var(--mj-border-default);\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .gantt-resizer:hover {\n background: var(--mj-brand-primary);\n }\n\n .task-detail-panel {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n border-left: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n }\n\n /* Override DHTMLX Gantt default styles */\n :host ::ng-deep .gantt_container {\n font-family: inherit;\n font-size: 13px;\n }\n\n :host ::ng-deep .gantt_grid_scale,\n :host ::ng-deep .gantt_task_scale {\n background: var(--mj-bg-surface-sunken);\n border-bottom: 2px solid var(--mj-border-default);\n }\n\n :host ::ng-deep .gantt_task .gantt_task_content {\n font-weight: 500;\n }\n\n .no-tasks {\n text-align: center;\n padding: 80px 20px;\n color: var(--mj-text-disabled);\n }\n\n .no-tasks i {\n font-size: 64px;\n opacity: 0.3;\n margin-bottom: 16px;\n }\n\n .no-tasks p {\n margin: 0;\n font-size: 14px;\n }\n `]\n})\nexport class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDestroy {\n @Input() tasks: MJTaskEntity[] = [];\n @Input() taskDependencies: MJTaskDependencyEntity[] = [];\n @Input() agentRunMap?: Map<string, string>; // Maps TaskID -> AgentRunID\n @Output() taskClicked = new EventEmitter<MJTaskEntity>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n\n @ViewChild('ganttContainer', { static: false }) ganttContainer!: ElementRef<HTMLDivElement>;\n\n public selectedTask: MJTaskEntity | null = null;\n public detailPanelWidth: number = 400;\n\n private ganttInitialized = false;\n private isResizing = false;\n private resizeStartX = 0;\n private resizeStartWidth = 0;\n\n ngAfterViewInit() {\n console.log('🔧 ngAfterViewInit called', {\n taskCount: this.tasks?.length || 0,\n hasContainer: !!this.ganttContainer\n });\n\n if (this.tasks && this.tasks.length > 0 && this.ganttContainer) {\n this.initGantt();\n }\n }\n\n ngOnChanges() {\n console.log('🔄 ngOnChanges called', {\n initialized: this.ganttInitialized,\n hasContainer: !!this.ganttContainer,\n taskCount: this.tasks?.length || 0\n });\n\n if (this.ganttInitialized && this.ganttContainer) {\n this.updateGanttData();\n } else if (!this.ganttInitialized && this.ganttContainer && this.tasks && this.tasks.length > 0) {\n // Initialize if we have container and tasks but haven't initialized yet\n console.log('🎨 Late initialization - gantt not initialized but container and tasks available');\n this.initGantt();\n }\n }\n\n ngOnDestroy() {\n if (this.ganttInitialized) {\n gantt.clearAll();\n this.ganttInitialized = false;\n }\n }\n\n private initGantt(): void {\n try {\n console.log('🎨 Initializing DHTMLX Gantt');\n\n // IMPORTANT: Clear any previous configuration\n gantt.clearAll();\n\n // Configure Gantt layout and appearance\n gantt.config.date_format = '%Y-%m-%d %H:%i';\n gantt.config.scale_unit = 'day';\n gantt.config.date_scale = '%d %M';\n gantt.config.subscales = [];\n gantt.config.show_progress = true;\n gantt.config.show_links = true;\n gantt.config.auto_types = true;\n gantt.config.readonly = true; // Read-only for now\n gantt.config.fit_tasks = true; // Auto-fit timeline to tasks\n\n // Disable auto-scheduling - we calculate dates ourselves based on dependencies\n gantt.config.auto_scheduling = false;\n\n // Grid configuration\n gantt.config.grid_width = 350;\n gantt.config.row_height = 36;\n gantt.config.scale_height = 0; // Hide date scale - dates are just for positioning\n\n // Layout configuration - ensure timeline is visible\n gantt.config.layout = {\n css: \"gantt_container\",\n rows: [\n {\n cols: [\n { view: \"grid\", group: \"grids\", scrollY: \"scrollVer\" },\n { resizer: true, width: 1 },\n { view: \"timeline\", scrollX: \"scrollHor\", scrollY: \"scrollVer\" },\n { view: \"scrollbar\", id: \"scrollVer\", group: \"vertical\" }\n ]\n },\n { view: \"scrollbar\", id: \"scrollHor\", group: \"horizontal\" }\n ]\n };\n\n // Column configuration - only show task names, hide dates\n gantt.config.columns = [\n { name: 'text', label: 'Task name', tree: true, width: '*' }\n ];\n\n // Initialize Gantt in the container\n gantt.init(this.ganttContainer.nativeElement);\n this.ganttInitialized = true;\n\n // Attach click event\n gantt.attachEvent('onTaskClick', (id: string) => {\n const originalTask = this.tasks.find(t => UUIDsEqual(t.ID, id));\n if (originalTask) {\n this.selectedTask = originalTask;\n this.taskClicked.emit(originalTask);\n }\n return true;\n });\n\n // Load data\n this.updateGanttData();\n\n // Force resize after data load to ensure proper rendering\n setTimeout(() => {\n gantt.setSizes();\n }, 0);\n\n // Expand and select after render completes\n setTimeout(() => {\n this.expandAllAndSelectRoot();\n }, 100);\n\n console.log('✅ DHTMLX Gantt initialized successfully');\n } catch (error) {\n console.error('❌ Error initializing Gantt:', error);\n }\n }\n\n private updateGanttData(): void {\n if (!this.ganttInitialized) return;\n\n try {\n console.log('📊 Updating Gantt data with', this.tasks.length, 'tasks');\n\n const ganttData = this.convertToGanttFormat(this.tasks);\n gantt.clearAll();\n gantt.parse(ganttData);\n\n // Log final parsed data for debugging\n console.log('📋 Gantt data after parse:', {\n tasks: gantt.getTaskByTime(),\n links: gantt.getLinks()\n });\n\n // Force resize after data update\n setTimeout(() => {\n gantt.setSizes();\n }, 0);\n\n // Expand and select after render completes\n setTimeout(() => {\n this.expandAllAndSelectRoot();\n }, 100);\n\n console.log('✅ Gantt data updated');\n } catch (error) {\n console.error('❌ Error updating Gantt data:', error);\n }\n }\n\n private convertToGanttFormat(tasks: MJTaskEntity[]): { data: any[], links: any[] } {\n const data: any[] = [];\n const links: any[] = [];\n\n console.log('🔍 Converting tasks:', tasks);\n console.log('🔗 Task dependencies:', this.taskDependencies);\n\n // Build a map of task ID to task for quick lookup\n const taskMap = new Map<string, MJTaskEntity>();\n tasks.forEach(t => taskMap.set(t.ID, t));\n\n // Build dependency map: taskId -> array of tasks it depends on\n const dependencyMap = new Map<string, string[]>();\n this.taskDependencies.forEach(dep => {\n if (!dependencyMap.has(dep.TaskID)) {\n dependencyMap.set(dep.TaskID, []);\n }\n dependencyMap.get(dep.TaskID)!.push(dep.DependsOnTaskID);\n });\n\n // Calculate start dates based on dependencies\n const taskStartDates = new Map<string, Date>();\n const baseDate = new Date();\n baseDate.setHours(0, 0, 0, 0);\n\n // Recursive function to calculate start date for a task\n const calculateStartDate = (taskId: string, visited = new Set<string>()): Date => {\n // Prevent circular dependencies\n if (visited.has(taskId)) {\n return new Date(baseDate);\n }\n visited.add(taskId);\n\n // If already calculated, return it\n if (taskStartDates.has(taskId)) {\n return taskStartDates.get(taskId)!;\n }\n\n const task = taskMap.get(taskId);\n if (!task) return new Date(baseDate);\n\n const dependencies = dependencyMap.get(taskId) || [];\n\n if (dependencies.length === 0) {\n // No dependencies - use base date or task's actual start date\n const startDate = task.StartedAt ? new Date(task.StartedAt) : new Date(baseDate);\n taskStartDates.set(taskId, startDate);\n return startDate;\n }\n\n // Has dependencies - start after the latest dependency ends\n let latestEnd = new Date(baseDate);\n for (const depId of dependencies) {\n const depTask = taskMap.get(depId);\n if (depTask) {\n const depStart = calculateStartDate(depId, new Set(visited));\n const depDuration = this.calculateDuration(depTask);\n const depEnd = new Date(depStart);\n depEnd.setDate(depEnd.getDate() + depDuration);\n\n if (depEnd > latestEnd) {\n latestEnd = depEnd;\n }\n }\n }\n\n taskStartDates.set(taskId, latestEnd);\n return latestEnd;\n };\n\n // Calculate start dates for all tasks\n tasks.forEach(task => calculateStartDate(task.ID));\n\n // Calculate min/max dates for timeline display range\n let minDate: Date | null = null;\n let maxDate: Date | null = null;\n\n tasks.forEach(task => {\n const startDate = taskStartDates.get(task.ID);\n if (startDate) {\n const duration = this.calculateDuration(task);\n const endDate = new Date(startDate);\n endDate.setDate(endDate.getDate() + duration);\n\n if (!minDate || startDate < minDate) {\n minDate = startDate;\n }\n if (!maxDate || endDate > maxDate) {\n maxDate = endDate;\n }\n }\n });\n\n // Add 1 day padding before and after\n if (minDate) {\n const paddedStart = new Date(minDate);\n paddedStart.setDate(paddedStart.getDate() - 1);\n gantt.config.start_date = paddedStart;\n }\n if (maxDate) {\n const paddedEnd = new Date(maxDate);\n paddedEnd.setDate(paddedEnd.getDate() + 1);\n gantt.config.end_date = paddedEnd;\n }\n\n // Now create Gantt tasks with calculated dates\n tasks.forEach((task) => {\n console.log('📝 Processing task:', {\n ID: task.ID,\n Name: task.Name,\n ParentID: task.ParentID\n });\n\n // Calculate progress (0-1 scale for DHTMLX)\n let progress = (task.PercentComplete || 0) / 100;\n if (task.Status === 'Complete') {\n progress = 1;\n }\n\n const duration = this.calculateDuration(task);\n const startDate = taskStartDates.get(task.ID) || new Date(baseDate);\n\n const ganttTask: any = {\n id: task.ID,\n text: task.Name || 'Untitled Task',\n start_date: this.formatDateForDHTMLX(startDate),\n duration: duration,\n progress: progress\n };\n\n // Add parent relationship for tree structure (not dependency)\n if (task.ParentID) {\n ganttTask.parent = task.ParentID;\n } else {\n // Root tasks need parent: 0\n ganttTask.parent = 0;\n }\n\n console.log('✅ Created Gantt task:', ganttTask);\n data.push(ganttTask);\n });\n\n // Create links from MJTaskDependencyEntity records\n this.taskDependencies.forEach((dep, index) => {\n links.push({\n id: dep.ID || `link_${index}`,\n source: dep.DependsOnTaskID, // The task being depended on\n target: dep.TaskID, // The task that depends on it\n type: '0' // finish-to-start (DHTMLX type 0)\n });\n console.log(`🔗 Created link: ${dep.DependsOnTaskID} -> ${dep.TaskID}`);\n });\n\n console.log('📊 Final DHTMLX format:', { data, links });\n return { data, links };\n }\n\n private calculateDuration(task: MJTaskEntity): number {\n if (task.StartedAt && task.DueAt) {\n const startDate = new Date(task.StartedAt);\n const endDate = new Date(task.DueAt);\n return Math.max(1, Math.ceil((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24)));\n }\n return 1; // Default to 1 day\n }\n\n private formatDateForDHTMLX(date: Date): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return `${year}-${month}-${day} 00:00`;\n }\n\n public getAgentRunId(task: MJTaskEntity): string | null {\n return this.agentRunMap?.get(task.ID) || null;\n }\n\n public closeDetailPanel(): void {\n this.selectedTask = null;\n }\n\n public onOpenEntityRecord(event: { entityName: string; recordId: string }): void {\n this.openEntityRecord.emit(event);\n }\n\n public startResize(event: MouseEvent): void {\n this.isResizing = true;\n this.resizeStartX = event.clientX;\n this.resizeStartWidth = this.detailPanelWidth;\n event.preventDefault();\n }\n\n @HostListener('document:mousemove', ['$event'])\n handleResize(event: MouseEvent): void {\n if (!this.isResizing) return;\n\n const delta = this.resizeStartX - event.clientX;\n const newWidth = this.resizeStartWidth + delta;\n\n // Constrain width between min and max\n this.detailPanelWidth = Math.max(300, Math.min(600, newWidth));\n }\n\n @HostListener('document:mouseup')\n stopResize(): void {\n if (this.isResizing) {\n this.isResizing = false;\n // Resize gantt chart after panel resize completes\n setTimeout(() => {\n if (this.ganttInitialized) {\n gantt.setSizes();\n }\n }, 0);\n }\n }\n\n private expandAllAndSelectRoot(): void {\n try {\n // Expand all tasks\n gantt.eachTask((task: any) => {\n gantt.open(task.id);\n });\n\n // Find and select the root task (task with parent = 0)\n let rootTask: any = null;\n gantt.eachTask((task: any) => {\n if (task.parent === 0 || task.parent === '0') {\n rootTask = task;\n return false; // Stop iteration\n }\n });\n\n if (rootTask) {\n gantt.selectTask(rootTask.id);\n // Trigger task click event to open detail panel\n const originalTask = this.tasks.find(t => UUIDsEqual(t.ID, rootTask.id));\n if (originalTask) {\n this.selectedTask = originalTask;\n this.taskClicked.emit(originalTask);\n }\n }\n\n console.log('✅ Expanded all tasks and selected root:', rootTask?.id);\n } catch (error) {\n console.error('❌ Error expanding/selecting tasks:', error);\n }\n }\n}\n"]}
@@ -192,7 +192,7 @@ export class SimpleTaskViewerComponent {
192
192
  i0.ɵɵconditional(ctx.selectedTask ? 6 : -1);
193
193
  i0.ɵɵadvance();
194
194
  i0.ɵɵconditional(ctx.selectedTask ? 7 : -1);
195
- } }, dependencies: [CommonModule, i1.NgClass, TaskDetailPanelComponent], styles: [".simple-task-viewer[_ngcontent-%COMP%] {\n height: 100%;\n background: #FAFAFA;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .list-layout[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n position: relative;\n }\n\n .task-list[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 400px;\n padding: 16px;\n overflow-y: auto;\n }\n\n .task-list.with-detail[_ngcontent-%COMP%] {\n border-right: 1px solid #E5E7EB;\n }\n\n .list-resizer[_ngcontent-%COMP%] {\n width: 4px;\n background: #E5E7EB;\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .list-resizer[_ngcontent-%COMP%]:hover {\n background: #3B82F6;\n }\n\n .task-detail-panel[_ngcontent-%COMP%] {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n flex-shrink: 0;\n }\n\n .task-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 16px;\n background: white;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n margin-bottom: 8px;\n transition: all 0.2s;\n cursor: pointer;\n }\n\n .task-item[_ngcontent-%COMP%]:hover {\n border-color: #3B82F6;\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1);\n transform: translateY(-1px);\n }\n\n .task-item.selected[_ngcontent-%COMP%] {\n border-color: #3B82F6;\n background: #EFF6FF;\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n\n .task-item.completed[_ngcontent-%COMP%] {\n background: #F9FAFB;\n border-color: #D1D5DB;\n }\n\n .status-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #FEF3C7;\n color: #F59E0B;\n flex-shrink: 0;\n }\n\n .status-icon.complete[_ngcontent-%COMP%] {\n background: #D1FAE5;\n color: #10B981;\n }\n\n .task-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n\n .task-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 12px;\n margin-bottom: 6px;\n }\n\n .task-title-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n }\n\n .task-title[_ngcontent-%COMP%] {\n font-weight: 600;\n color: #111827;\n font-size: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .task-title.completed-text[_ngcontent-%COMP%] {\n color: #6B7280;\n text-decoration: line-through;\n text-decoration-thickness: 1.5px;\n }\n\n .completed-check[_ngcontent-%COMP%] {\n color: #10B981;\n font-size: 12px;\n }\n\n .task-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: #6B7280;\n white-space: nowrap;\n }\n\n .task-meta[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 4px;\n }\n\n .task-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #6B7280;\n margin-bottom: 8px;\n line-height: 1.5;\n }\n\n .task-progress-compact[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n }\n\n .progress-bar-compact[_ngcontent-%COMP%] {\n width: 80px;\n height: 4px;\n background: #E5E7EB;\n border-radius: 2px;\n overflow: hidden;\n }\n\n .progress-fill-compact[_ngcontent-%COMP%] {\n height: 100%;\n background: #3B82F6;\n transition: width 0.3s ease;\n }\n\n .progress-fill-compact.complete[_ngcontent-%COMP%] {\n background: #10B981;\n }\n\n .progress-text-compact[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 600;\n color: #6B7280;\n min-width: 30px;\n text-align: right;\n }\n\n .no-tasks[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px 20px;\n color: #9CA3AF;\n }\n\n .no-tasks[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n opacity: 0.3;\n margin-bottom: 12px;\n }\n\n .no-tasks[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n }"] });
195
+ } }, dependencies: [CommonModule, i1.NgClass, TaskDetailPanelComponent], styles: [".simple-task-viewer[_ngcontent-%COMP%] {\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .list-layout[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n position: relative;\n }\n\n .task-list[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 400px;\n padding: 16px;\n overflow-y: auto;\n }\n\n .task-list.with-detail[_ngcontent-%COMP%] {\n border-right: 1px solid var(--mj-border-default);\n }\n\n .list-resizer[_ngcontent-%COMP%] {\n width: 4px;\n background: var(--mj-border-default);\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .list-resizer[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n }\n\n .task-detail-panel[_ngcontent-%COMP%] {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n flex-shrink: 0;\n }\n\n .task-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 8px;\n transition: all 0.2s;\n cursor: pointer;\n }\n\n .task-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n transform: translateY(-1px);\n }\n\n .task-item.selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n box-shadow: var(--mj-shadow-sm);\n }\n\n .task-item.completed[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n }\n\n .status-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n flex-shrink: 0;\n }\n\n .status-icon.complete[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n }\n\n .task-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n\n .task-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 12px;\n margin-bottom: 6px;\n }\n\n .task-title-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n }\n\n .task-title[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-primary);\n font-size: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .task-title.completed-text[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n text-decoration: line-through;\n text-decoration-thickness: 1.5px;\n }\n\n .completed-check[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n font-size: 12px;\n }\n\n .task-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n .task-meta[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 4px;\n }\n\n .task-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n line-height: 1.5;\n }\n\n .task-progress-compact[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n }\n\n .progress-bar-compact[_ngcontent-%COMP%] {\n width: 80px;\n height: 4px;\n background: var(--mj-border-default);\n border-radius: 2px;\n overflow: hidden;\n }\n\n .progress-fill-compact[_ngcontent-%COMP%] {\n height: 100%;\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n }\n\n .progress-fill-compact.complete[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n }\n\n .progress-text-compact[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-muted);\n min-width: 30px;\n text-align: right;\n }\n\n .no-tasks[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-disabled);\n }\n\n .no-tasks[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n opacity: 0.3;\n margin-bottom: 12px;\n }\n\n .no-tasks[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n }"] });
196
196
  }
197
197
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SimpleTaskViewerComponent, [{
198
198
  type: Component,
@@ -276,7 +276,7 @@ export class SimpleTaskViewerComponent {
276
276
  }
277
277
  </div>
278
278
  </div>
279
- `, styles: ["\n .simple-task-viewer {\n height: 100%;\n background: #FAFAFA;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .list-layout {\n display: flex;\n height: 100%;\n position: relative;\n }\n\n .task-list {\n flex: 1;\n min-width: 400px;\n padding: 16px;\n overflow-y: auto;\n }\n\n .task-list.with-detail {\n border-right: 1px solid #E5E7EB;\n }\n\n .list-resizer {\n width: 4px;\n background: #E5E7EB;\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .list-resizer:hover {\n background: #3B82F6;\n }\n\n .task-detail-panel {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n flex-shrink: 0;\n }\n\n .task-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 16px;\n background: white;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n margin-bottom: 8px;\n transition: all 0.2s;\n cursor: pointer;\n }\n\n .task-item:hover {\n border-color: #3B82F6;\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1);\n transform: translateY(-1px);\n }\n\n .task-item.selected {\n border-color: #3B82F6;\n background: #EFF6FF;\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n\n .task-item.completed {\n background: #F9FAFB;\n border-color: #D1D5DB;\n }\n\n .status-icon {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #FEF3C7;\n color: #F59E0B;\n flex-shrink: 0;\n }\n\n .status-icon.complete {\n background: #D1FAE5;\n color: #10B981;\n }\n\n .task-content {\n flex: 1;\n min-width: 0;\n }\n\n .task-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 12px;\n margin-bottom: 6px;\n }\n\n .task-title-row {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n }\n\n .task-title {\n font-weight: 600;\n color: #111827;\n font-size: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .task-title.completed-text {\n color: #6B7280;\n text-decoration: line-through;\n text-decoration-thickness: 1.5px;\n }\n\n .completed-check {\n color: #10B981;\n font-size: 12px;\n }\n\n .task-meta {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: #6B7280;\n white-space: nowrap;\n }\n\n .task-meta i {\n margin-right: 4px;\n }\n\n .task-description {\n font-size: 13px;\n color: #6B7280;\n margin-bottom: 8px;\n line-height: 1.5;\n }\n\n .task-progress-compact {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n }\n\n .progress-bar-compact {\n width: 80px;\n height: 4px;\n background: #E5E7EB;\n border-radius: 2px;\n overflow: hidden;\n }\n\n .progress-fill-compact {\n height: 100%;\n background: #3B82F6;\n transition: width 0.3s ease;\n }\n\n .progress-fill-compact.complete {\n background: #10B981;\n }\n\n .progress-text-compact {\n font-size: 10px;\n font-weight: 600;\n color: #6B7280;\n min-width: 30px;\n text-align: right;\n }\n\n .no-tasks {\n text-align: center;\n padding: 60px 20px;\n color: #9CA3AF;\n }\n\n .no-tasks i {\n font-size: 48px;\n opacity: 0.3;\n margin-bottom: 12px;\n }\n\n .no-tasks p {\n margin: 0;\n font-size: 14px;\n }\n "] }]
279
+ `, styles: ["\n .simple-task-viewer {\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .list-layout {\n display: flex;\n height: 100%;\n position: relative;\n }\n\n .task-list {\n flex: 1;\n min-width: 400px;\n padding: 16px;\n overflow-y: auto;\n }\n\n .task-list.with-detail {\n border-right: 1px solid var(--mj-border-default);\n }\n\n .list-resizer {\n width: 4px;\n background: var(--mj-border-default);\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .list-resizer:hover {\n background: var(--mj-brand-primary);\n }\n\n .task-detail-panel {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n flex-shrink: 0;\n }\n\n .task-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 8px;\n transition: all 0.2s;\n cursor: pointer;\n }\n\n .task-item:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n transform: translateY(-1px);\n }\n\n .task-item.selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n box-shadow: var(--mj-shadow-sm);\n }\n\n .task-item.completed {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n }\n\n .status-icon {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n flex-shrink: 0;\n }\n\n .status-icon.complete {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n }\n\n .task-content {\n flex: 1;\n min-width: 0;\n }\n\n .task-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 12px;\n margin-bottom: 6px;\n }\n\n .task-title-row {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n }\n\n .task-title {\n font-weight: 600;\n color: var(--mj-text-primary);\n font-size: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .task-title.completed-text {\n color: var(--mj-text-muted);\n text-decoration: line-through;\n text-decoration-thickness: 1.5px;\n }\n\n .completed-check {\n color: var(--mj-status-success);\n font-size: 12px;\n }\n\n .task-meta {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n .task-meta i {\n margin-right: 4px;\n }\n\n .task-description {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n line-height: 1.5;\n }\n\n .task-progress-compact {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n }\n\n .progress-bar-compact {\n width: 80px;\n height: 4px;\n background: var(--mj-border-default);\n border-radius: 2px;\n overflow: hidden;\n }\n\n .progress-fill-compact {\n height: 100%;\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n }\n\n .progress-fill-compact.complete {\n background: var(--mj-status-success);\n }\n\n .progress-text-compact {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-muted);\n min-width: 30px;\n text-align: right;\n }\n\n .no-tasks {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-disabled);\n }\n\n .no-tasks i {\n font-size: 48px;\n opacity: 0.3;\n margin-bottom: 12px;\n }\n\n .no-tasks p {\n margin: 0;\n font-size: 14px;\n }\n "] }]
280
280
  }], null, { tasks: [{
281
281
  type: Input
282
282
  }], agentRunMap: [{
@@ -1 +1 @@
1
- {"version":3,"file":"simple-task-viewer.component.js","sourceRoot":"","sources":["../../../src/lib/components/simple-task-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnChanges, HostListener } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MJTaskEntity } from '@memberjunction/core-entities';\nimport { TaskDetailPanelComponent } from './task-detail-panel.component';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Simple list view for tasks\n */\n@Component({\n selector: 'mj-simple-task-viewer',\n standalone: true,\n imports: [CommonModule, TaskDetailPanelComponent],\n template: `\n <div class=\"simple-task-viewer\">\n <div class=\"list-layout\">\n <div class=\"task-list\" [class.with-detail]=\"selectedTask\">\n @for (task of tasks; track task) {\n <div\n class=\"task-item\"\n [class.completed]=\"task.Status === 'Complete'\"\n [class.selected]=\"IsTaskSelected(task)\"\n (click)=\"onTaskClick(task)\">\n <!-- Status Icon -->\n <div class=\"status-icon\" [class.complete]=\"task.Status === 'Complete'\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon(task.Status)\"></i>\n </div>\n <!-- Task Content -->\n <div class=\"task-content\">\n <div class=\"task-header\">\n <div class=\"task-title-row\">\n <span class=\"task-title\" [class.completed-text]=\"task.Status === 'Complete'\">\n {{ task.Name }}\n @if (task.Status === 'Complete') {\n <i class=\"fas fa-check completed-check\"></i>\n }\n </span>\n <!-- Compact progress indicator for all tasks -->\n @if (task.PercentComplete != null) {\n <div class=\"task-progress-compact\">\n <div class=\"progress-bar-compact\">\n <div class=\"progress-fill-compact\"\n [style.width.%]=\"task.PercentComplete\"\n [class.complete]=\"task.Status === 'Complete'\"></div>\n </div>\n <span class=\"progress-text-compact\">{{ task.PercentComplete }}%</span>\n </div>\n }\n </div>\n <span class=\"task-meta\">\n @if (task.DueAt) {\n <span class=\"due-date\">\n <i class=\"far fa-calendar\"></i>\n {{ formatDate(task.DueAt) }}\n </span>\n }\n @if (task.User) {\n <span class=\"assigned-to\">\n <i class=\"far fa-user\"></i>\n {{ task.User }}\n </span>\n }\n </span>\n </div>\n </div>\n </div>\n }\n \n @if (!tasks || tasks.length === 0) {\n <div class=\"no-tasks\">\n <i class=\"fas fa-tasks\"></i>\n <p>No tasks to display</p>\n </div>\n }\n </div>\n \n @if (selectedTask) {\n <div class=\"list-resizer\"\n (mousedown)=\"startResize($event)\"></div>\n }\n \n @if (selectedTask) {\n <div class=\"task-detail-panel\" [style.width.px]=\"detailPanelWidth\">\n <mj-task-detail-panel\n [task]=\"selectedTask\"\n [agentRunId]=\"getAgentRunId(selectedTask)\"\n (closePanel)=\"closeDetailPanel()\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-task-detail-panel>\n </div>\n }\n </div>\n </div>\n `,\n styles: [`\n .simple-task-viewer {\n height: 100%;\n background: #FAFAFA;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .list-layout {\n display: flex;\n height: 100%;\n position: relative;\n }\n\n .task-list {\n flex: 1;\n min-width: 400px;\n padding: 16px;\n overflow-y: auto;\n }\n\n .task-list.with-detail {\n border-right: 1px solid #E5E7EB;\n }\n\n .list-resizer {\n width: 4px;\n background: #E5E7EB;\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .list-resizer:hover {\n background: #3B82F6;\n }\n\n .task-detail-panel {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n flex-shrink: 0;\n }\n\n .task-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 16px;\n background: white;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n margin-bottom: 8px;\n transition: all 0.2s;\n cursor: pointer;\n }\n\n .task-item:hover {\n border-color: #3B82F6;\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1);\n transform: translateY(-1px);\n }\n\n .task-item.selected {\n border-color: #3B82F6;\n background: #EFF6FF;\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n\n .task-item.completed {\n background: #F9FAFB;\n border-color: #D1D5DB;\n }\n\n .status-icon {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #FEF3C7;\n color: #F59E0B;\n flex-shrink: 0;\n }\n\n .status-icon.complete {\n background: #D1FAE5;\n color: #10B981;\n }\n\n .task-content {\n flex: 1;\n min-width: 0;\n }\n\n .task-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 12px;\n margin-bottom: 6px;\n }\n\n .task-title-row {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n }\n\n .task-title {\n font-weight: 600;\n color: #111827;\n font-size: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .task-title.completed-text {\n color: #6B7280;\n text-decoration: line-through;\n text-decoration-thickness: 1.5px;\n }\n\n .completed-check {\n color: #10B981;\n font-size: 12px;\n }\n\n .task-meta {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: #6B7280;\n white-space: nowrap;\n }\n\n .task-meta i {\n margin-right: 4px;\n }\n\n .task-description {\n font-size: 13px;\n color: #6B7280;\n margin-bottom: 8px;\n line-height: 1.5;\n }\n\n .task-progress-compact {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n }\n\n .progress-bar-compact {\n width: 80px;\n height: 4px;\n background: #E5E7EB;\n border-radius: 2px;\n overflow: hidden;\n }\n\n .progress-fill-compact {\n height: 100%;\n background: #3B82F6;\n transition: width 0.3s ease;\n }\n\n .progress-fill-compact.complete {\n background: #10B981;\n }\n\n .progress-text-compact {\n font-size: 10px;\n font-weight: 600;\n color: #6B7280;\n min-width: 30px;\n text-align: right;\n }\n\n .no-tasks {\n text-align: center;\n padding: 60px 20px;\n color: #9CA3AF;\n }\n\n .no-tasks i {\n font-size: 48px;\n opacity: 0.3;\n margin-bottom: 12px;\n }\n\n .no-tasks p {\n margin: 0;\n font-size: 14px;\n }\n `]\n})\nexport class SimpleTaskViewerComponent implements OnChanges {\n @Input() tasks: MJTaskEntity[] = [];\n @Input() agentRunMap?: Map<string, string>; // Maps TaskID -> AgentRunID\n @Output() taskClicked = new EventEmitter<MJTaskEntity>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n\n public selectedTask: MJTaskEntity | null = null;\n\n public IsTaskSelected(task: MJTaskEntity): boolean {\n return UUIDsEqual(this.selectedTask?.ID, task.ID);\n }\n public detailPanelWidth: number = 400;\n\n private isResizing = false;\n private resizeStartX = 0;\n private resizeStartWidth = 0;\n\n ngOnChanges() {\n // Tasks are already loaded\n }\n\n public onTaskClick(task: MJTaskEntity): void {\n this.selectedTask = task;\n this.taskClicked.emit(task);\n }\n\n public getAgentRunId(task: MJTaskEntity): string | null {\n return this.agentRunMap?.get(task.ID) || null;\n }\n\n public closeDetailPanel(): void {\n this.selectedTask = null;\n }\n\n public onOpenEntityRecord(event: { entityName: string; recordId: string }): void {\n this.openEntityRecord.emit(event);\n }\n\n public startResize(event: MouseEvent): void {\n this.isResizing = true;\n this.resizeStartX = event.clientX;\n this.resizeStartWidth = this.detailPanelWidth;\n event.preventDefault();\n }\n\n @HostListener('document:mousemove', ['$event'])\n handleResize(event: MouseEvent): void {\n if (!this.isResizing) return;\n\n const delta = this.resizeStartX - event.clientX;\n const newWidth = this.resizeStartWidth + delta;\n\n // Constrain width between min and max\n this.detailPanelWidth = Math.max(300, Math.min(600, newWidth));\n }\n\n @HostListener('document:mouseup')\n stopResize(): void {\n this.isResizing = false;\n }\n\n public getStatusIcon(status: string): string {\n switch (status) {\n case 'Complete': return 'fa-check-circle';\n case 'In Progress': return 'fa-spinner';\n case 'Pending': return 'fa-clock';\n case 'Blocked': return 'fa-ban';\n case 'Failed': return 'fa-times-circle';\n default: return 'fa-circle';\n }\n }\n\n public formatDate(date: Date | null): string {\n if (!date) return '';\n const d = new Date(date);\n return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });\n }\n}\n"]}
1
+ {"version":3,"file":"simple-task-viewer.component.js","sourceRoot":"","sources":["../../../src/lib/components/simple-task-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnChanges, HostListener } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MJTaskEntity } from '@memberjunction/core-entities';\nimport { TaskDetailPanelComponent } from './task-detail-panel.component';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Simple list view for tasks\n */\n@Component({\n selector: 'mj-simple-task-viewer',\n standalone: true,\n imports: [CommonModule, TaskDetailPanelComponent],\n template: `\n <div class=\"simple-task-viewer\">\n <div class=\"list-layout\">\n <div class=\"task-list\" [class.with-detail]=\"selectedTask\">\n @for (task of tasks; track task) {\n <div\n class=\"task-item\"\n [class.completed]=\"task.Status === 'Complete'\"\n [class.selected]=\"IsTaskSelected(task)\"\n (click)=\"onTaskClick(task)\">\n <!-- Status Icon -->\n <div class=\"status-icon\" [class.complete]=\"task.Status === 'Complete'\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon(task.Status)\"></i>\n </div>\n <!-- Task Content -->\n <div class=\"task-content\">\n <div class=\"task-header\">\n <div class=\"task-title-row\">\n <span class=\"task-title\" [class.completed-text]=\"task.Status === 'Complete'\">\n {{ task.Name }}\n @if (task.Status === 'Complete') {\n <i class=\"fas fa-check completed-check\"></i>\n }\n </span>\n <!-- Compact progress indicator for all tasks -->\n @if (task.PercentComplete != null) {\n <div class=\"task-progress-compact\">\n <div class=\"progress-bar-compact\">\n <div class=\"progress-fill-compact\"\n [style.width.%]=\"task.PercentComplete\"\n [class.complete]=\"task.Status === 'Complete'\"></div>\n </div>\n <span class=\"progress-text-compact\">{{ task.PercentComplete }}%</span>\n </div>\n }\n </div>\n <span class=\"task-meta\">\n @if (task.DueAt) {\n <span class=\"due-date\">\n <i class=\"far fa-calendar\"></i>\n {{ formatDate(task.DueAt) }}\n </span>\n }\n @if (task.User) {\n <span class=\"assigned-to\">\n <i class=\"far fa-user\"></i>\n {{ task.User }}\n </span>\n }\n </span>\n </div>\n </div>\n </div>\n }\n \n @if (!tasks || tasks.length === 0) {\n <div class=\"no-tasks\">\n <i class=\"fas fa-tasks\"></i>\n <p>No tasks to display</p>\n </div>\n }\n </div>\n \n @if (selectedTask) {\n <div class=\"list-resizer\"\n (mousedown)=\"startResize($event)\"></div>\n }\n \n @if (selectedTask) {\n <div class=\"task-detail-panel\" [style.width.px]=\"detailPanelWidth\">\n <mj-task-detail-panel\n [task]=\"selectedTask\"\n [agentRunId]=\"getAgentRunId(selectedTask)\"\n (closePanel)=\"closeDetailPanel()\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-task-detail-panel>\n </div>\n }\n </div>\n </div>\n `,\n styles: [`\n .simple-task-viewer {\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .list-layout {\n display: flex;\n height: 100%;\n position: relative;\n }\n\n .task-list {\n flex: 1;\n min-width: 400px;\n padding: 16px;\n overflow-y: auto;\n }\n\n .task-list.with-detail {\n border-right: 1px solid var(--mj-border-default);\n }\n\n .list-resizer {\n width: 4px;\n background: var(--mj-border-default);\n cursor: col-resize;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .list-resizer:hover {\n background: var(--mj-brand-primary);\n }\n\n .task-detail-panel {\n min-width: 300px;\n max-width: 600px;\n height: 100%;\n flex-shrink: 0;\n }\n\n .task-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 8px;\n transition: all 0.2s;\n cursor: pointer;\n }\n\n .task-item:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n transform: translateY(-1px);\n }\n\n .task-item.selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n box-shadow: var(--mj-shadow-sm);\n }\n\n .task-item.completed {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n }\n\n .status-icon {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n flex-shrink: 0;\n }\n\n .status-icon.complete {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n }\n\n .task-content {\n flex: 1;\n min-width: 0;\n }\n\n .task-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 12px;\n margin-bottom: 6px;\n }\n\n .task-title-row {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n }\n\n .task-title {\n font-weight: 600;\n color: var(--mj-text-primary);\n font-size: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .task-title.completed-text {\n color: var(--mj-text-muted);\n text-decoration: line-through;\n text-decoration-thickness: 1.5px;\n }\n\n .completed-check {\n color: var(--mj-status-success);\n font-size: 12px;\n }\n\n .task-meta {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n .task-meta i {\n margin-right: 4px;\n }\n\n .task-description {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n line-height: 1.5;\n }\n\n .task-progress-compact {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n }\n\n .progress-bar-compact {\n width: 80px;\n height: 4px;\n background: var(--mj-border-default);\n border-radius: 2px;\n overflow: hidden;\n }\n\n .progress-fill-compact {\n height: 100%;\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n }\n\n .progress-fill-compact.complete {\n background: var(--mj-status-success);\n }\n\n .progress-text-compact {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-muted);\n min-width: 30px;\n text-align: right;\n }\n\n .no-tasks {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-disabled);\n }\n\n .no-tasks i {\n font-size: 48px;\n opacity: 0.3;\n margin-bottom: 12px;\n }\n\n .no-tasks p {\n margin: 0;\n font-size: 14px;\n }\n `]\n})\nexport class SimpleTaskViewerComponent implements OnChanges {\n @Input() tasks: MJTaskEntity[] = [];\n @Input() agentRunMap?: Map<string, string>; // Maps TaskID -> AgentRunID\n @Output() taskClicked = new EventEmitter<MJTaskEntity>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n\n public selectedTask: MJTaskEntity | null = null;\n\n public IsTaskSelected(task: MJTaskEntity): boolean {\n return UUIDsEqual(this.selectedTask?.ID, task.ID);\n }\n public detailPanelWidth: number = 400;\n\n private isResizing = false;\n private resizeStartX = 0;\n private resizeStartWidth = 0;\n\n ngOnChanges() {\n // Tasks are already loaded\n }\n\n public onTaskClick(task: MJTaskEntity): void {\n this.selectedTask = task;\n this.taskClicked.emit(task);\n }\n\n public getAgentRunId(task: MJTaskEntity): string | null {\n return this.agentRunMap?.get(task.ID) || null;\n }\n\n public closeDetailPanel(): void {\n this.selectedTask = null;\n }\n\n public onOpenEntityRecord(event: { entityName: string; recordId: string }): void {\n this.openEntityRecord.emit(event);\n }\n\n public startResize(event: MouseEvent): void {\n this.isResizing = true;\n this.resizeStartX = event.clientX;\n this.resizeStartWidth = this.detailPanelWidth;\n event.preventDefault();\n }\n\n @HostListener('document:mousemove', ['$event'])\n handleResize(event: MouseEvent): void {\n if (!this.isResizing) return;\n\n const delta = this.resizeStartX - event.clientX;\n const newWidth = this.resizeStartWidth + delta;\n\n // Constrain width between min and max\n this.detailPanelWidth = Math.max(300, Math.min(600, newWidth));\n }\n\n @HostListener('document:mouseup')\n stopResize(): void {\n this.isResizing = false;\n }\n\n public getStatusIcon(status: string): string {\n switch (status) {\n case 'Complete': return 'fa-check-circle';\n case 'In Progress': return 'fa-spinner';\n case 'Pending': return 'fa-clock';\n case 'Blocked': return 'fa-ban';\n case 'Failed': return 'fa-times-circle';\n default: return 'fa-circle';\n }\n }\n\n public formatDate(date: Date | null): string {\n if (!date) return '';\n const d = new Date(date);\n return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });\n }\n}\n"]}
@@ -211,7 +211,7 @@ export class TaskDetailPanelComponent {
211
211
  i0.ɵɵconditional(ctx.agent ? 18 : -1);
212
212
  i0.ɵɵadvance();
213
213
  i0.ɵɵconditional(ctx.agentRunId ? 19 : -1);
214
- } }, styles: [".task-detail-panel[_ngcontent-%COMP%] {\n width: 100%;\n height: calc(100% - 45px);\n background: white;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .detail-header[_ngcontent-%COMP%] {\n padding: 20px;\n border-bottom: 1px solid #E5E7EB;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n background: #F9FAFB;\n flex-shrink: 0;\n }\n\n .detail-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #111827;\n flex: 1;\n padding-right: 12px;\n }\n\n .close-detail-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: #6B7280;\n cursor: pointer;\n padding: 4px;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .close-detail-btn[_ngcontent-%COMP%]:hover {\n background: #E5E7EB;\n color: #111827;\n }\n\n .detail-content[_ngcontent-%COMP%] {\n padding: 20px;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n }\n\n .detail-field[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n }\n\n .detail-field[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n }\n\n .detail-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #6B7280;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n }\n\n .detail-field[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: #111827;\n line-height: 1.5;\n }\n\n .detail-progress[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .progress-bar-detail[_ngcontent-%COMP%] {\n flex: 1;\n height: 8px;\n background: #E5E7EB;\n border-radius: 4px;\n overflow: hidden;\n }\n\n .progress-fill-detail[_ngcontent-%COMP%] {\n height: calc(100% - 69px);\n background: #3B82F6;\n transition: width 0.3s ease;\n }\n\n .detail-progress[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: #6B7280;\n min-width: 40px;\n }\n\n .agent-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: #F3F4F6;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-info[_ngcontent-%COMP%]:hover {\n background: #E5E7EB;\n }\n\n .agent-icon[_ngcontent-%COMP%] {\n font-size: 18px;\n color: #3B82F6;\n }\n\n .agent-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: #111827;\n }\n\n .link-icon[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #6B7280;\n }\n\n .agent-run-link[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n background: #F3F4F6;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-run-link[_ngcontent-%COMP%]:hover {\n background: #E5E7EB;\n }\n\n .agent-run-link[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: #111827;\n }"] });
214
+ } }, styles: [".task-detail-panel[_ngcontent-%COMP%] {\n width: 100%;\n height: calc(100% - 45px);\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .detail-header[_ngcontent-%COMP%] {\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n }\n\n .detail-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex: 1;\n padding-right: 12px;\n }\n\n .close-detail-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .close-detail-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n }\n\n .detail-content[_ngcontent-%COMP%] {\n padding: 20px;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n }\n\n .detail-field[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n }\n\n .detail-field[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n }\n\n .detail-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n }\n\n .detail-field[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-primary);\n line-height: 1.5;\n }\n\n .detail-progress[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .progress-bar-detail[_ngcontent-%COMP%] {\n flex: 1;\n height: 8px;\n background: var(--mj-border-default);\n border-radius: 4px;\n overflow: hidden;\n }\n\n .progress-fill-detail[_ngcontent-%COMP%] {\n height: calc(100% - 69px);\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n }\n\n .detail-progress[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-muted);\n min-width: 40px;\n }\n\n .agent-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-info[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n }\n\n .agent-icon[_ngcontent-%COMP%] {\n font-size: 18px;\n color: var(--mj-brand-primary);\n }\n\n .agent-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n\n .link-icon[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n\n .agent-run-link[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-run-link[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n }\n\n .agent-run-link[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n }"] });
215
215
  }
216
216
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TaskDetailPanelComponent, [{
217
217
  type: Component,
@@ -301,7 +301,7 @@ export class TaskDetailPanelComponent {
301
301
  }
302
302
  </div>
303
303
  </div>
304
- `, styles: ["\n .task-detail-panel {\n width: 100%;\n height: calc(100% - 45px);\n background: white;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .detail-header {\n padding: 20px;\n border-bottom: 1px solid #E5E7EB;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n background: #F9FAFB;\n flex-shrink: 0;\n }\n\n .detail-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #111827;\n flex: 1;\n padding-right: 12px;\n }\n\n .close-detail-btn {\n background: none;\n border: none;\n color: #6B7280;\n cursor: pointer;\n padding: 4px;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .close-detail-btn:hover {\n background: #E5E7EB;\n color: #111827;\n }\n\n .detail-content {\n padding: 20px;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n }\n\n .detail-field {\n margin-bottom: 20px;\n }\n\n .detail-field:last-child {\n margin-bottom: 0;\n }\n\n .detail-field label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #6B7280;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n }\n\n .detail-field p {\n margin: 0;\n font-size: 14px;\n color: #111827;\n line-height: 1.5;\n }\n\n .detail-progress {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .progress-bar-detail {\n flex: 1;\n height: 8px;\n background: #E5E7EB;\n border-radius: 4px;\n overflow: hidden;\n }\n\n .progress-fill-detail {\n height: calc(100% - 69px);\n background: #3B82F6;\n transition: width 0.3s ease;\n }\n\n .detail-progress span {\n font-size: 13px;\n font-weight: 600;\n color: #6B7280;\n min-width: 40px;\n }\n\n .agent-info {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: #F3F4F6;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-info:hover {\n background: #E5E7EB;\n }\n\n .agent-icon {\n font-size: 18px;\n color: #3B82F6;\n }\n\n .agent-name {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: #111827;\n }\n\n .link-icon {\n font-size: 12px;\n color: #6B7280;\n }\n\n .agent-run-link {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n background: #F3F4F6;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-run-link:hover {\n background: #E5E7EB;\n }\n\n .agent-run-link span {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: #111827;\n }\n "] }]
304
+ `, styles: ["\n .task-detail-panel {\n width: 100%;\n height: calc(100% - 45px);\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .detail-header {\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n }\n\n .detail-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex: 1;\n padding-right: 12px;\n }\n\n .close-detail-btn {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .close-detail-btn:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n }\n\n .detail-content {\n padding: 20px;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n }\n\n .detail-field {\n margin-bottom: 20px;\n }\n\n .detail-field:last-child {\n margin-bottom: 0;\n }\n\n .detail-field label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n }\n\n .detail-field p {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-primary);\n line-height: 1.5;\n }\n\n .detail-progress {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .progress-bar-detail {\n flex: 1;\n height: 8px;\n background: var(--mj-border-default);\n border-radius: 4px;\n overflow: hidden;\n }\n\n .progress-fill-detail {\n height: calc(100% - 69px);\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n }\n\n .detail-progress span {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-muted);\n min-width: 40px;\n }\n\n .agent-info {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-info:hover {\n background: var(--mj-border-default);\n }\n\n .agent-icon {\n font-size: 18px;\n color: var(--mj-brand-primary);\n }\n\n .agent-name {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n\n .link-icon {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n\n .agent-run-link {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-run-link:hover {\n background: var(--mj-border-default);\n }\n\n .agent-run-link span {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n "] }]
305
305
  }], null, { task: [{
306
306
  type: Input
307
307
  }], agentRunId: [{
@@ -1 +1 @@
1
- {"version":3,"file":"task-detail-panel.component.js","sourceRoot":"","sources":["../../../src/lib/components/task-detail-panel.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnChanges } from '@angular/core';\n\nimport { MJTaskEntity } from '@memberjunction/core-entities';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Task detail panel showing task information, agent details, and agent run\n * Reusable across list and Gantt views\n */\n@Component({\n selector: 'mj-task-detail-panel',\n standalone: true,\n imports: [],\n template: `\n <div class=\"task-detail-panel\">\n <div class=\"detail-header\">\n <h3>{{ task.Name }}</h3>\n <button class=\"close-detail-btn\" (click)=\"closePanel.emit()\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n \n <div class=\"detail-content\">\n @if (task.Description) {\n <div class=\"detail-field\">\n <label>Description</label>\n <p>{{ task.Description }}</p>\n </div>\n }\n \n <div class=\"detail-field\">\n <label>Status</label>\n <p>{{ task.Status }}</p>\n </div>\n \n @if (task.PercentComplete != null) {\n <div class=\"detail-field\">\n <label>Progress</label>\n <div class=\"detail-progress\">\n <div class=\"progress-bar-detail\">\n <div class=\"progress-fill-detail\" [style.width.%]=\"task.PercentComplete\"></div>\n </div>\n <span>{{ task.PercentComplete }}%</span>\n </div>\n </div>\n }\n \n @if (task.StartedAt) {\n <div class=\"detail-field\">\n <label>Started</label>\n <p>{{ formatDateTime(task.StartedAt) }}</p>\n </div>\n }\n \n @if (task.DueAt) {\n <div class=\"detail-field\">\n <label>Due</label>\n <p>{{ formatDateTime(task.DueAt) }}</p>\n </div>\n }\n \n @if (task.CompletedAt) {\n <div class=\"detail-field\">\n <label>Completed</label>\n <p>{{ formatDateTime(task.CompletedAt) }}</p>\n </div>\n }\n \n @if (task.User) {\n <div class=\"detail-field\">\n <label>Assigned User</label>\n <p>{{ task.User }}</p>\n </div>\n }\n \n <!-- Agent Information -->\n @if (agent) {\n <div class=\"detail-field\">\n <label>Agent</label>\n <div class=\"agent-info\" (click)=\"openAgent()\">\n <i [class]=\"'fas fa-' + ('robot')\" class=\"agent-icon\"></i>\n <span class=\"agent-name\">{{ agent.Name }}</span>\n <i class=\"fas fa-external-link-alt link-icon\"></i>\n </div>\n </div>\n }\n \n <!-- Agent Run Information -->\n @if (agentRunId) {\n <div class=\"detail-field\">\n <label>Agent Run</label>\n <div class=\"agent-run-link\" (click)=\"openAgentRun()\">\n <span>View Run Details</span>\n <i class=\"fas fa-external-link-alt link-icon\"></i>\n </div>\n </div>\n }\n </div>\n </div>\n `,\n styles: [`\n .task-detail-panel {\n width: 100%;\n height: calc(100% - 45px);\n background: white;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .detail-header {\n padding: 20px;\n border-bottom: 1px solid #E5E7EB;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n background: #F9FAFB;\n flex-shrink: 0;\n }\n\n .detail-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #111827;\n flex: 1;\n padding-right: 12px;\n }\n\n .close-detail-btn {\n background: none;\n border: none;\n color: #6B7280;\n cursor: pointer;\n padding: 4px;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .close-detail-btn:hover {\n background: #E5E7EB;\n color: #111827;\n }\n\n .detail-content {\n padding: 20px;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n }\n\n .detail-field {\n margin-bottom: 20px;\n }\n\n .detail-field:last-child {\n margin-bottom: 0;\n }\n\n .detail-field label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #6B7280;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n }\n\n .detail-field p {\n margin: 0;\n font-size: 14px;\n color: #111827;\n line-height: 1.5;\n }\n\n .detail-progress {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .progress-bar-detail {\n flex: 1;\n height: 8px;\n background: #E5E7EB;\n border-radius: 4px;\n overflow: hidden;\n }\n\n .progress-fill-detail {\n height: calc(100% - 69px);\n background: #3B82F6;\n transition: width 0.3s ease;\n }\n\n .detail-progress span {\n font-size: 13px;\n font-weight: 600;\n color: #6B7280;\n min-width: 40px;\n }\n\n .agent-info {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: #F3F4F6;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-info:hover {\n background: #E5E7EB;\n }\n\n .agent-icon {\n font-size: 18px;\n color: #3B82F6;\n }\n\n .agent-name {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: #111827;\n }\n\n .link-icon {\n font-size: 12px;\n color: #6B7280;\n }\n\n .agent-run-link {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n background: #F3F4F6;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-run-link:hover {\n background: #E5E7EB;\n }\n\n .agent-run-link span {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: #111827;\n }\n `]\n})\nexport class TaskDetailPanelComponent implements OnInit, OnChanges {\n @Input() task!: MJTaskEntity;\n @Input() agentRunId: string | null = null;\n @Output() closePanel = new EventEmitter<void>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n\n public agent: MJAIAgentEntityExtended | null = null;\n\n ngOnInit(): void {\n this.loadAgentInfo();\n }\n\n ngOnChanges(): void {\n this.loadAgentInfo();\n }\n\n private loadAgentInfo(): void {\n if (!this.task?.AgentID) {\n this.agent = null;\n return;\n }\n\n // Get agent from AIEngineBase\n const agents = AIEngineBase.Instance.Agents;\n this.agent = agents.find((a: MJAIAgentEntityExtended) => UUIDsEqual(a.ID, this.task.AgentID)) || null;\n }\n\n public formatDateTime(date: Date | null): string {\n if (!date) return '';\n const d = new Date(date);\n return d.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n }\n\n public openAgent(): void {\n if (this.task.AgentID) {\n this.openEntityRecord.emit({\n entityName: 'MJ: AI Agents',\n recordId: this.task.AgentID\n });\n }\n }\n\n public openAgentRun(): void {\n if (this.agentRunId) {\n this.openEntityRecord.emit({\n entityName: 'MJ: AI Agent Runs',\n recordId: this.agentRunId\n });\n }\n }\n}\n"]}
1
+ {"version":3,"file":"task-detail-panel.component.js","sourceRoot":"","sources":["../../../src/lib/components/task-detail-panel.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnChanges } from '@angular/core';\n\nimport { MJTaskEntity } from '@memberjunction/core-entities';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Task detail panel showing task information, agent details, and agent run\n * Reusable across list and Gantt views\n */\n@Component({\n selector: 'mj-task-detail-panel',\n standalone: true,\n imports: [],\n template: `\n <div class=\"task-detail-panel\">\n <div class=\"detail-header\">\n <h3>{{ task.Name }}</h3>\n <button class=\"close-detail-btn\" (click)=\"closePanel.emit()\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n \n <div class=\"detail-content\">\n @if (task.Description) {\n <div class=\"detail-field\">\n <label>Description</label>\n <p>{{ task.Description }}</p>\n </div>\n }\n \n <div class=\"detail-field\">\n <label>Status</label>\n <p>{{ task.Status }}</p>\n </div>\n \n @if (task.PercentComplete != null) {\n <div class=\"detail-field\">\n <label>Progress</label>\n <div class=\"detail-progress\">\n <div class=\"progress-bar-detail\">\n <div class=\"progress-fill-detail\" [style.width.%]=\"task.PercentComplete\"></div>\n </div>\n <span>{{ task.PercentComplete }}%</span>\n </div>\n </div>\n }\n \n @if (task.StartedAt) {\n <div class=\"detail-field\">\n <label>Started</label>\n <p>{{ formatDateTime(task.StartedAt) }}</p>\n </div>\n }\n \n @if (task.DueAt) {\n <div class=\"detail-field\">\n <label>Due</label>\n <p>{{ formatDateTime(task.DueAt) }}</p>\n </div>\n }\n \n @if (task.CompletedAt) {\n <div class=\"detail-field\">\n <label>Completed</label>\n <p>{{ formatDateTime(task.CompletedAt) }}</p>\n </div>\n }\n \n @if (task.User) {\n <div class=\"detail-field\">\n <label>Assigned User</label>\n <p>{{ task.User }}</p>\n </div>\n }\n \n <!-- Agent Information -->\n @if (agent) {\n <div class=\"detail-field\">\n <label>Agent</label>\n <div class=\"agent-info\" (click)=\"openAgent()\">\n <i [class]=\"'fas fa-' + ('robot')\" class=\"agent-icon\"></i>\n <span class=\"agent-name\">{{ agent.Name }}</span>\n <i class=\"fas fa-external-link-alt link-icon\"></i>\n </div>\n </div>\n }\n \n <!-- Agent Run Information -->\n @if (agentRunId) {\n <div class=\"detail-field\">\n <label>Agent Run</label>\n <div class=\"agent-run-link\" (click)=\"openAgentRun()\">\n <span>View Run Details</span>\n <i class=\"fas fa-external-link-alt link-icon\"></i>\n </div>\n </div>\n }\n </div>\n </div>\n `,\n styles: [`\n .task-detail-panel {\n width: 100%;\n height: calc(100% - 45px);\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .detail-header {\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n }\n\n .detail-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex: 1;\n padding-right: 12px;\n }\n\n .close-detail-btn {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .close-detail-btn:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n }\n\n .detail-content {\n padding: 20px;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n }\n\n .detail-field {\n margin-bottom: 20px;\n }\n\n .detail-field:last-child {\n margin-bottom: 0;\n }\n\n .detail-field label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n }\n\n .detail-field p {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-primary);\n line-height: 1.5;\n }\n\n .detail-progress {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .progress-bar-detail {\n flex: 1;\n height: 8px;\n background: var(--mj-border-default);\n border-radius: 4px;\n overflow: hidden;\n }\n\n .progress-fill-detail {\n height: calc(100% - 69px);\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n }\n\n .detail-progress span {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-muted);\n min-width: 40px;\n }\n\n .agent-info {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-info:hover {\n background: var(--mj-border-default);\n }\n\n .agent-icon {\n font-size: 18px;\n color: var(--mj-brand-primary);\n }\n\n .agent-name {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n\n .link-icon {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n\n .agent-run-link {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-run-link:hover {\n background: var(--mj-border-default);\n }\n\n .agent-run-link span {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n `]\n})\nexport class TaskDetailPanelComponent implements OnInit, OnChanges {\n @Input() task!: MJTaskEntity;\n @Input() agentRunId: string | null = null;\n @Output() closePanel = new EventEmitter<void>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n\n public agent: MJAIAgentEntityExtended | null = null;\n\n ngOnInit(): void {\n this.loadAgentInfo();\n }\n\n ngOnChanges(): void {\n this.loadAgentInfo();\n }\n\n private loadAgentInfo(): void {\n if (!this.task?.AgentID) {\n this.agent = null;\n return;\n }\n\n // Get agent from AIEngineBase\n const agents = AIEngineBase.Instance.Agents;\n this.agent = agents.find((a: MJAIAgentEntityExtended) => UUIDsEqual(a.ID, this.task.AgentID)) || null;\n }\n\n public formatDateTime(date: Date | null): string {\n if (!date) return '';\n const d = new Date(date);\n return d.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n }\n\n public openAgent(): void {\n if (this.task.AgentID) {\n this.openEntityRecord.emit({\n entityName: 'MJ: AI Agents',\n recordId: this.task.AgentID\n });\n }\n }\n\n public openAgentRun(): void {\n if (this.agentRunId) {\n this.openEntityRecord.emit({\n entityName: 'MJ: AI Agent Runs',\n recordId: this.agentRunId\n });\n }\n }\n}\n"]}
@@ -118,7 +118,7 @@ export class TaskComponent {
118
118
  i0.ɵɵconditional(ctx.viewMode === "simple" ? 3 : -1);
119
119
  i0.ɵɵadvance();
120
120
  i0.ɵɵconditional(ctx.viewMode === "gantt" ? 4 : -1);
121
- } }, dependencies: [SimpleTaskViewerComponent, GanttTaskViewerComponent], styles: [".task-component[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #FAFAFA;\n }\n\n .task-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 20px;\n padding: 20px 24px;\n background: white;\n border-bottom: 1px solid #E5E7EB;\n }\n\n .header-left[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n\n .task-title[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 700;\n color: #111827;\n }\n\n .task-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: #6B7280;\n line-height: 1.5;\n }\n\n .view-toggle[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n background: #F3F4F6;\n padding: 4px;\n border-radius: 8px;\n }\n\n .toggle-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n background: transparent;\n color: #6B7280;\n font-size: 13px;\n font-weight: 600;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .toggle-btn[_ngcontent-%COMP%]:hover {\n color: #111827;\n background: rgba(255, 255, 255, 0.5);\n }\n\n .toggle-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #3B82F6;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n\n .toggle-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .task-viewer[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n }"] });
121
+ } }, dependencies: [SimpleTaskViewerComponent, GanttTaskViewerComponent], styles: [".task-component[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n }\n\n .task-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 20px;\n padding: 20px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n .header-left[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n\n .task-title[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n }\n\n .task-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n }\n\n .view-toggle[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n background: var(--mj-bg-surface-sunken);\n padding: 4px;\n border-radius: 8px;\n }\n\n .toggle-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 600;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .toggle-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: color-mix(in srgb, var(--mj-bg-surface) 50%, transparent);\n }\n\n .toggle-btn.active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n }\n\n .toggle-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .task-viewer[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n }"] });
122
122
  }
123
123
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TaskComponent, [{
124
124
  type: Component,
@@ -180,7 +180,7 @@ export class TaskComponent {
180
180
  }
181
181
  </div>
182
182
  </div>
183
- `, styles: ["\n .task-component {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #FAFAFA;\n }\n\n .task-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 20px;\n padding: 20px 24px;\n background: white;\n border-bottom: 1px solid #E5E7EB;\n }\n\n .header-left {\n flex: 1;\n min-width: 0;\n }\n\n .task-title {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 700;\n color: #111827;\n }\n\n .task-description {\n margin: 0;\n font-size: 14px;\n color: #6B7280;\n line-height: 1.5;\n }\n\n .view-toggle {\n display: flex;\n gap: 8px;\n background: #F3F4F6;\n padding: 4px;\n border-radius: 8px;\n }\n\n .toggle-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n background: transparent;\n color: #6B7280;\n font-size: 13px;\n font-weight: 600;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .toggle-btn:hover {\n color: #111827;\n background: rgba(255, 255, 255, 0.5);\n }\n\n .toggle-btn.active {\n background: white;\n color: #3B82F6;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n\n .toggle-btn i {\n font-size: 14px;\n }\n\n .task-viewer {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n }\n "] }]
183
+ `, styles: ["\n .task-component {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n }\n\n .task-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 20px;\n padding: 20px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n .header-left {\n flex: 1;\n min-width: 0;\n }\n\n .task-title {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n }\n\n .task-description {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n }\n\n .view-toggle {\n display: flex;\n gap: 8px;\n background: var(--mj-bg-surface-sunken);\n padding: 4px;\n border-radius: 8px;\n }\n\n .toggle-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 600;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .toggle-btn:hover {\n color: var(--mj-text-primary);\n background: color-mix(in srgb, var(--mj-bg-surface) 50%, transparent);\n }\n\n .toggle-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n }\n\n .toggle-btn i {\n font-size: 14px;\n }\n\n .task-viewer {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n }\n "] }]
184
184
  }], null, { tasks: [{
185
185
  type: Input
186
186
  }], ganttTasks: [{
@@ -1 +1 @@
1
- {"version":3,"file":"task.component.js","sourceRoot":"","sources":["../../../src/lib/components/task.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAIvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;;;;IAiB3D,6BAAuB;IAAA,YAAW;IAAA,iBAAK;;;IAAhB,cAAW;IAAX,kCAAW;;;IAGlC,4BAA4B;IAAA,YAAiB;IAAA,iBAAI;;;IAArB,cAAiB;IAAjB,wCAAiB;;;;IAK7C,AADF,8BAAyB,gBAKD;IADpB,gMAAS,mBAAY,OAAO,CAAC,KAAC;IAE9B,wBAAkC;IAClC,4BAAM;IAAA,qBAAK;IACb,AADa,iBAAO,EACX;IACT,kCAIoB;IADlB,gMAAS,mBAAY,QAAQ,CAAC,KAAC;IAE/B,wBAA2B;IAC3B,4BAAM;IAAA,oBAAI;IAEd,AADE,AADY,iBAAO,EACV,EACL;;;IAdF,cAAqC;IAArC,qDAAqC;IAQrC,eAAsC;IAAtC,sDAAsC;;;IApB5C,AADF,8BAAyB,aACE;IACvB,4FAAa;IAGb,2FAAmB;IAGrB,iBAAM;IACN,6FAAsB;IAoBxB,iBAAM;;;IA3BF,eAEC;IAFD,uCAEC;IACD,cAEC;IAFD,6CAEC;IAEH,cAmBC;IAnBD,gDAmBC;;;;IAOD,iDAIkD;IAAhD,AADA,kNAAe,4BAAqB,KAAC,+MACjB,iCAA0B,KAAC;IACjD,iBAAwB;;;IAHtB,AADA,oCAAe,mCACY;;;;IAO7B,gDAKkD;IAAhD,AADA,iNAAe,4BAAqB,KAAC,8MACjB,iCAA0B,KAAC;IACjD,iBAAuB;;;IAHrB,AADA,AADA,yDAA6B,2EACc,mCAChB;;AA3DvC;;;GAGG;AAkJH,MAAM,OAAO,aAAa;IACf,KAAK,GAAmB,EAAE,CAAC;IAC3B,UAAU,CAAkB,CAAC,0DAA0D;IACvF,gBAAgB,CAA4B,CAAC,oCAAoC;IACjF,WAAW,CAAuB,CAAC,4BAA4B;IAC/D,KAAK,CAAU;IACf,WAAW,CAAU;IACrB,UAAU,GAAY,IAAI,CAAC;IAC3B,cAAc,GAAY,IAAI,CAAC,CAAC,yBAAyB;IACzD,QAAQ,GAAiB,QAAQ,CAAC;IAEjC,eAAe,GAAG,IAAI,YAAY,EAAgB,CAAC;IACnD,WAAW,GAAG,IAAI,YAAY,EAAgB,CAAC;IAC/C,gBAAgB,GAAG,IAAI,YAAY,EAA4C,CAAC;IAEnF,WAAW,CAAC,IAAkB;QACnC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAEM,aAAa,CAAC,IAAkB;QACrC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAEM,kBAAkB,CAAC,KAA+C;QACvE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;uGA1BU,aAAa;6DAAb,aAAa;YA5ItB,8BAA4B;YAE1B,+EAAkB;YAkClB,8BAAyB;YACvB,iGAA6B;YAS7B,gGAA4B;YAUhC,AADE,iBAAM,EACF;;YAtDJ,cA+BC;YA/BD,yCA+BC;YAIC,eAOC;YAPD,oDAOC;YAED,cAQC;YARD,mDAQC;4BAxDG,yBAAyB,EAAE,wBAAwB;;iFA8IlD,aAAa;cAjJzB,SAAS;2BACE,SAAS,cACP,IAAI,WACP,CAAC,yBAAyB,EAAE,wBAAwB,CAAC,YACpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA0DP;;kBAoFF,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBAEL,MAAM;;kBACN,MAAM;;kBACN,MAAM;;kFAbI,aAAa","sourcesContent":["import { Component, Input, Output, EventEmitter } from '@angular/core';\n\nimport { MJTaskEntity, MJTaskDependencyEntity } from '@memberjunction/core-entities';\nimport { TaskViewMode } from '../models/task-view.models';\nimport { SimpleTaskViewerComponent } from './simple-task-viewer.component';\nimport { GanttTaskViewerComponent } from './gantt-task-viewer.component';\n\n/**\n * Main task component that composes SimpleTaskViewer and GanttTaskViewer\n * Allows switching between list and Gantt chart views\n */\n@Component({\n selector: 'mj-task',\n standalone: true,\n imports: [SimpleTaskViewerComponent, GanttTaskViewerComponent],\n template: `\n <div class=\"task-component\">\n <!-- Header with View Toggle -->\n @if (showHeader) {\n <div class=\"task-header\">\n <div class=\"header-left\">\n @if (title) {\n <h2 class=\"task-title\">{{ title }}</h2>\n }\n @if (description) {\n <p class=\"task-description\">{{ description }}</p>\n }\n </div>\n @if (showViewToggle) {\n <div class=\"view-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'gantt'\"\n (click)=\"setViewMode('gantt')\"\n title=\"Gantt Chart\">\n <i class=\"fas fa-chart-gantt\"></i>\n <span>Gantt</span>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'simple'\"\n (click)=\"setViewMode('simple')\"\n title=\"List View\">\n <i class=\"fas fa-list\"></i>\n <span>List</span>\n </button>\n </div>\n }\n </div>\n }\n \n <!-- Task Viewer (Simple or Gantt) -->\n <div class=\"task-viewer\">\n @if (viewMode === 'simple') {\n <mj-simple-task-viewer\n [tasks]=\"tasks\"\n [agentRunMap]=\"agentRunMap\"\n (taskClicked)=\"onTaskClicked($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-simple-task-viewer>\n }\n \n @if (viewMode === 'gantt') {\n <mj-gantt-task-viewer\n [tasks]=\"ganttTasks || tasks\"\n [taskDependencies]=\"taskDependencies || []\"\n [agentRunMap]=\"agentRunMap\"\n (taskClicked)=\"onTaskClicked($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-gantt-task-viewer>\n }\n </div>\n </div>\n `,\n styles: [`\n .task-component {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #FAFAFA;\n }\n\n .task-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 20px;\n padding: 20px 24px;\n background: white;\n border-bottom: 1px solid #E5E7EB;\n }\n\n .header-left {\n flex: 1;\n min-width: 0;\n }\n\n .task-title {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 700;\n color: #111827;\n }\n\n .task-description {\n margin: 0;\n font-size: 14px;\n color: #6B7280;\n line-height: 1.5;\n }\n\n .view-toggle {\n display: flex;\n gap: 8px;\n background: #F3F4F6;\n padding: 4px;\n border-radius: 8px;\n }\n\n .toggle-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n background: transparent;\n color: #6B7280;\n font-size: 13px;\n font-weight: 600;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .toggle-btn:hover {\n color: #111827;\n background: rgba(255, 255, 255, 0.5);\n }\n\n .toggle-btn.active {\n background: white;\n color: #3B82F6;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n\n .toggle-btn i {\n font-size: 14px;\n }\n\n .task-viewer {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n }\n `]\n})\nexport class TaskComponent {\n @Input() tasks: MJTaskEntity[] = [];\n @Input() ganttTasks?: MJTaskEntity[]; // Optional separate task list for Gantt (includes parent)\n @Input() taskDependencies?: MJTaskDependencyEntity[]; // Task dependencies for Gantt links\n @Input() agentRunMap?: Map<string, string>; // Maps TaskID -> AgentRunID\n @Input() title?: string;\n @Input() description?: string;\n @Input() showHeader: boolean = true;\n @Input() showViewToggle: boolean = true; // Show Gantt/List toggle\n @Input() viewMode: TaskViewMode = 'simple';\n\n @Output() viewModeChanged = new EventEmitter<TaskViewMode>();\n @Output() taskClicked = new EventEmitter<MJTaskEntity>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n\n public setViewMode(mode: TaskViewMode): void {\n this.viewMode = mode;\n this.viewModeChanged.emit(mode);\n }\n\n public onTaskClicked(task: MJTaskEntity): void {\n this.taskClicked.emit(task);\n }\n\n public onOpenEntityRecord(event: { entityName: string; recordId: string }): void {\n this.openEntityRecord.emit(event);\n }\n}\n"]}
1
+ {"version":3,"file":"task.component.js","sourceRoot":"","sources":["../../../src/lib/components/task.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAIvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;;;;IAiB3D,6BAAuB;IAAA,YAAW;IAAA,iBAAK;;;IAAhB,cAAW;IAAX,kCAAW;;;IAGlC,4BAA4B;IAAA,YAAiB;IAAA,iBAAI;;;IAArB,cAAiB;IAAjB,wCAAiB;;;;IAK7C,AADF,8BAAyB,gBAKD;IADpB,gMAAS,mBAAY,OAAO,CAAC,KAAC;IAE9B,wBAAkC;IAClC,4BAAM;IAAA,qBAAK;IACb,AADa,iBAAO,EACX;IACT,kCAIoB;IADlB,gMAAS,mBAAY,QAAQ,CAAC,KAAC;IAE/B,wBAA2B;IAC3B,4BAAM;IAAA,oBAAI;IAEd,AADE,AADY,iBAAO,EACV,EACL;;;IAdF,cAAqC;IAArC,qDAAqC;IAQrC,eAAsC;IAAtC,sDAAsC;;;IApB5C,AADF,8BAAyB,aACE;IACvB,4FAAa;IAGb,2FAAmB;IAGrB,iBAAM;IACN,6FAAsB;IAoBxB,iBAAM;;;IA3BF,eAEC;IAFD,uCAEC;IACD,cAEC;IAFD,6CAEC;IAEH,cAmBC;IAnBD,gDAmBC;;;;IAOD,iDAIkD;IAAhD,AADA,kNAAe,4BAAqB,KAAC,+MACjB,iCAA0B,KAAC;IACjD,iBAAwB;;;IAHtB,AADA,oCAAe,mCACY;;;;IAO7B,gDAKkD;IAAhD,AADA,iNAAe,4BAAqB,KAAC,8MACjB,iCAA0B,KAAC;IACjD,iBAAuB;;;IAHrB,AADA,AADA,yDAA6B,2EACc,mCAChB;;AA3DvC;;;GAGG;AAkJH,MAAM,OAAO,aAAa;IACf,KAAK,GAAmB,EAAE,CAAC;IAC3B,UAAU,CAAkB,CAAC,0DAA0D;IACvF,gBAAgB,CAA4B,CAAC,oCAAoC;IACjF,WAAW,CAAuB,CAAC,4BAA4B;IAC/D,KAAK,CAAU;IACf,WAAW,CAAU;IACrB,UAAU,GAAY,IAAI,CAAC;IAC3B,cAAc,GAAY,IAAI,CAAC,CAAC,yBAAyB;IACzD,QAAQ,GAAiB,QAAQ,CAAC;IAEjC,eAAe,GAAG,IAAI,YAAY,EAAgB,CAAC;IACnD,WAAW,GAAG,IAAI,YAAY,EAAgB,CAAC;IAC/C,gBAAgB,GAAG,IAAI,YAAY,EAA4C,CAAC;IAEnF,WAAW,CAAC,IAAkB;QACnC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAEM,aAAa,CAAC,IAAkB;QACrC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAEM,kBAAkB,CAAC,KAA+C;QACvE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;uGA1BU,aAAa;6DAAb,aAAa;YA5ItB,8BAA4B;YAE1B,+EAAkB;YAkClB,8BAAyB;YACvB,iGAA6B;YAS7B,gGAA4B;YAUhC,AADE,iBAAM,EACF;;YAtDJ,cA+BC;YA/BD,yCA+BC;YAIC,eAOC;YAPD,oDAOC;YAED,cAQC;YARD,mDAQC;4BAxDG,yBAAyB,EAAE,wBAAwB;;iFA8IlD,aAAa;cAjJzB,SAAS;2BACE,SAAS,cACP,IAAI,WACP,CAAC,yBAAyB,EAAE,wBAAwB,CAAC,YACpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA0DP;;kBAoFF,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBAEL,MAAM;;kBACN,MAAM;;kBACN,MAAM;;kFAbI,aAAa","sourcesContent":["import { Component, Input, Output, EventEmitter } from '@angular/core';\n\nimport { MJTaskEntity, MJTaskDependencyEntity } from '@memberjunction/core-entities';\nimport { TaskViewMode } from '../models/task-view.models';\nimport { SimpleTaskViewerComponent } from './simple-task-viewer.component';\nimport { GanttTaskViewerComponent } from './gantt-task-viewer.component';\n\n/**\n * Main task component that composes SimpleTaskViewer and GanttTaskViewer\n * Allows switching between list and Gantt chart views\n */\n@Component({\n selector: 'mj-task',\n standalone: true,\n imports: [SimpleTaskViewerComponent, GanttTaskViewerComponent],\n template: `\n <div class=\"task-component\">\n <!-- Header with View Toggle -->\n @if (showHeader) {\n <div class=\"task-header\">\n <div class=\"header-left\">\n @if (title) {\n <h2 class=\"task-title\">{{ title }}</h2>\n }\n @if (description) {\n <p class=\"task-description\">{{ description }}</p>\n }\n </div>\n @if (showViewToggle) {\n <div class=\"view-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'gantt'\"\n (click)=\"setViewMode('gantt')\"\n title=\"Gantt Chart\">\n <i class=\"fas fa-chart-gantt\"></i>\n <span>Gantt</span>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"viewMode === 'simple'\"\n (click)=\"setViewMode('simple')\"\n title=\"List View\">\n <i class=\"fas fa-list\"></i>\n <span>List</span>\n </button>\n </div>\n }\n </div>\n }\n \n <!-- Task Viewer (Simple or Gantt) -->\n <div class=\"task-viewer\">\n @if (viewMode === 'simple') {\n <mj-simple-task-viewer\n [tasks]=\"tasks\"\n [agentRunMap]=\"agentRunMap\"\n (taskClicked)=\"onTaskClicked($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-simple-task-viewer>\n }\n \n @if (viewMode === 'gantt') {\n <mj-gantt-task-viewer\n [tasks]=\"ganttTasks || tasks\"\n [taskDependencies]=\"taskDependencies || []\"\n [agentRunMap]=\"agentRunMap\"\n (taskClicked)=\"onTaskClicked($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-gantt-task-viewer>\n }\n </div>\n </div>\n `,\n styles: [`\n .task-component {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n }\n\n .task-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 20px;\n padding: 20px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n .header-left {\n flex: 1;\n min-width: 0;\n }\n\n .task-title {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n }\n\n .task-description {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n }\n\n .view-toggle {\n display: flex;\n gap: 8px;\n background: var(--mj-bg-surface-sunken);\n padding: 4px;\n border-radius: 8px;\n }\n\n .toggle-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 600;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .toggle-btn:hover {\n color: var(--mj-text-primary);\n background: color-mix(in srgb, var(--mj-bg-surface) 50%, transparent);\n }\n\n .toggle-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n }\n\n .toggle-btn i {\n font-size: 14px;\n }\n\n .task-viewer {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n }\n `]\n})\nexport class TaskComponent {\n @Input() tasks: MJTaskEntity[] = [];\n @Input() ganttTasks?: MJTaskEntity[]; // Optional separate task list for Gantt (includes parent)\n @Input() taskDependencies?: MJTaskDependencyEntity[]; // Task dependencies for Gantt links\n @Input() agentRunMap?: Map<string, string>; // Maps TaskID -> AgentRunID\n @Input() title?: string;\n @Input() description?: string;\n @Input() showHeader: boolean = true;\n @Input() showViewToggle: boolean = true; // Show Gantt/List toggle\n @Input() viewMode: TaskViewMode = 'simple';\n\n @Output() viewModeChanged = new EventEmitter<TaskViewMode>();\n @Output() taskClicked = new EventEmitter<MJTaskEntity>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n\n public setViewMode(mode: TaskViewMode): void {\n this.viewMode = mode;\n this.viewModeChanged.emit(mode);\n }\n\n public onTaskClicked(task: MJTaskEntity): void {\n this.taskClicked.emit(task);\n }\n\n public onOpenEntityRecord(event: { entityName: string; recordId: string }): void {\n this.openEntityRecord.emit(event);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-tasks",
3
- "version": "5.11.0",
3
+ "version": "5.13.0",
4
4
  "description": "MemberJunction: Angular components for task visualization and management with Gantt chart support",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -15,10 +15,10 @@
15
15
  "@angular/common": "21.1.3",
16
16
  "@angular/core": "21.1.3",
17
17
  "@angular/platform-browser": "21.1.3",
18
- "@memberjunction/core": "5.11.0",
19
- "@memberjunction/core-entities": "5.11.0",
20
- "@memberjunction/ai-core-plus": "5.11.0",
21
- "@memberjunction/ai-engine-base": "5.11.0",
18
+ "@memberjunction/core": "5.13.0",
19
+ "@memberjunction/core-entities": "5.13.0",
20
+ "@memberjunction/ai-core-plus": "5.13.0",
21
+ "@memberjunction/ai-engine-base": "5.13.0",
22
22
  "dhtmlx-gantt": "^9.1.1",
23
23
  "rxjs": "^7.8.2"
24
24
  },
@@ -45,7 +45,7 @@ import { UUIDsEqual } from '@memberjunction/global';
45
45
  styles: [`
46
46
  .gantt-task-viewer {
47
47
  height: 100%;
48
- background: white;
48
+ background: var(--mj-bg-surface);
49
49
  overflow: hidden;
50
50
  display: flex;
51
51
  flex-direction: column;
@@ -66,21 +66,21 @@ import { UUIDsEqual } from '@memberjunction/global';
66
66
 
67
67
  .gantt-resizer {
68
68
  width: 4px;
69
- background: #E5E7EB;
69
+ background: var(--mj-border-default);
70
70
  cursor: col-resize;
71
71
  flex-shrink: 0;
72
72
  transition: background 0.2s;
73
73
  }
74
74
 
75
75
  .gantt-resizer:hover {
76
- background: #3B82F6;
76
+ background: var(--mj-brand-primary);
77
77
  }
78
78
 
79
79
  .task-detail-panel {
80
80
  min-width: 300px;
81
81
  max-width: 600px;
82
82
  height: 100%;
83
- border-left: 1px solid #E5E7EB;
83
+ border-left: 1px solid var(--mj-border-default);
84
84
  flex-shrink: 0;
85
85
  }
86
86
 
@@ -92,8 +92,8 @@ import { UUIDsEqual } from '@memberjunction/global';
92
92
 
93
93
  :host ::ng-deep .gantt_grid_scale,
94
94
  :host ::ng-deep .gantt_task_scale {
95
- background: #F9FAFB;
96
- border-bottom: 2px solid #E5E7EB;
95
+ background: var(--mj-bg-surface-sunken);
96
+ border-bottom: 2px solid var(--mj-border-default);
97
97
  }
98
98
 
99
99
  :host ::ng-deep .gantt_task .gantt_task_content {
@@ -103,7 +103,7 @@ import { UUIDsEqual } from '@memberjunction/global';
103
103
  .no-tasks {
104
104
  text-align: center;
105
105
  padding: 80px 20px;
106
- color: #9CA3AF;
106
+ color: var(--mj-text-disabled);
107
107
  }
108
108
 
109
109
  .no-tasks i {
@@ -95,7 +95,7 @@ import { UUIDsEqual } from '@memberjunction/global';
95
95
  styles: [`
96
96
  .simple-task-viewer {
97
97
  height: 100%;
98
- background: #FAFAFA;
98
+ background: var(--mj-bg-surface-sunken);
99
99
  overflow: hidden;
100
100
  display: flex;
101
101
  flex-direction: column;
@@ -115,19 +115,19 @@ import { UUIDsEqual } from '@memberjunction/global';
115
115
  }
116
116
 
117
117
  .task-list.with-detail {
118
- border-right: 1px solid #E5E7EB;
118
+ border-right: 1px solid var(--mj-border-default);
119
119
  }
120
120
 
121
121
  .list-resizer {
122
122
  width: 4px;
123
- background: #E5E7EB;
123
+ background: var(--mj-border-default);
124
124
  cursor: col-resize;
125
125
  flex-shrink: 0;
126
126
  transition: background 0.2s;
127
127
  }
128
128
 
129
129
  .list-resizer:hover {
130
- background: #3B82F6;
130
+ background: var(--mj-brand-primary);
131
131
  }
132
132
 
133
133
  .task-detail-panel {
@@ -142,8 +142,8 @@ import { UUIDsEqual } from '@memberjunction/global';
142
142
  align-items: flex-start;
143
143
  gap: 12px;
144
144
  padding: 16px;
145
- background: white;
146
- border: 1px solid #E5E7EB;
145
+ background: var(--mj-bg-surface-card);
146
+ border: 1px solid var(--mj-border-default);
147
147
  border-radius: 8px;
148
148
  margin-bottom: 8px;
149
149
  transition: all 0.2s;
@@ -151,20 +151,20 @@ import { UUIDsEqual } from '@memberjunction/global';
151
151
  }
152
152
 
153
153
  .task-item:hover {
154
- border-color: #3B82F6;
155
- box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1);
154
+ border-color: var(--mj-brand-primary);
155
+ box-shadow: var(--mj-shadow-sm);
156
156
  transform: translateY(-1px);
157
157
  }
158
158
 
159
159
  .task-item.selected {
160
- border-color: #3B82F6;
161
- background: #EFF6FF;
162
- box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);
160
+ border-color: var(--mj-brand-primary);
161
+ background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));
162
+ box-shadow: var(--mj-shadow-sm);
163
163
  }
164
164
 
165
165
  .task-item.completed {
166
- background: #F9FAFB;
167
- border-color: #D1D5DB;
166
+ background: var(--mj-bg-surface-sunken);
167
+ border-color: var(--mj-border-strong);
168
168
  }
169
169
 
170
170
  .status-icon {
@@ -174,14 +174,14 @@ import { UUIDsEqual } from '@memberjunction/global';
174
174
  display: flex;
175
175
  align-items: center;
176
176
  justify-content: center;
177
- background: #FEF3C7;
178
- color: #F59E0B;
177
+ background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));
178
+ color: var(--mj-status-warning);
179
179
  flex-shrink: 0;
180
180
  }
181
181
 
182
182
  .status-icon.complete {
183
- background: #D1FAE5;
184
- color: #10B981;
183
+ background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));
184
+ color: var(--mj-status-success);
185
185
  }
186
186
 
187
187
  .task-content {
@@ -207,7 +207,7 @@ import { UUIDsEqual } from '@memberjunction/global';
207
207
 
208
208
  .task-title {
209
209
  font-weight: 600;
210
- color: #111827;
210
+ color: var(--mj-text-primary);
211
211
  font-size: 14px;
212
212
  display: flex;
213
213
  align-items: center;
@@ -215,13 +215,13 @@ import { UUIDsEqual } from '@memberjunction/global';
215
215
  }
216
216
 
217
217
  .task-title.completed-text {
218
- color: #6B7280;
218
+ color: var(--mj-text-muted);
219
219
  text-decoration: line-through;
220
220
  text-decoration-thickness: 1.5px;
221
221
  }
222
222
 
223
223
  .completed-check {
224
- color: #10B981;
224
+ color: var(--mj-status-success);
225
225
  font-size: 12px;
226
226
  }
227
227
 
@@ -229,7 +229,7 @@ import { UUIDsEqual } from '@memberjunction/global';
229
229
  display: flex;
230
230
  gap: 12px;
231
231
  font-size: 12px;
232
- color: #6B7280;
232
+ color: var(--mj-text-muted);
233
233
  white-space: nowrap;
234
234
  }
235
235
 
@@ -239,7 +239,7 @@ import { UUIDsEqual } from '@memberjunction/global';
239
239
 
240
240
  .task-description {
241
241
  font-size: 13px;
242
- color: #6B7280;
242
+ color: var(--mj-text-muted);
243
243
  margin-bottom: 8px;
244
244
  line-height: 1.5;
245
245
  }
@@ -254,25 +254,25 @@ import { UUIDsEqual } from '@memberjunction/global';
254
254
  .progress-bar-compact {
255
255
  width: 80px;
256
256
  height: 4px;
257
- background: #E5E7EB;
257
+ background: var(--mj-border-default);
258
258
  border-radius: 2px;
259
259
  overflow: hidden;
260
260
  }
261
261
 
262
262
  .progress-fill-compact {
263
263
  height: 100%;
264
- background: #3B82F6;
264
+ background: var(--mj-brand-primary);
265
265
  transition: width 0.3s ease;
266
266
  }
267
267
 
268
268
  .progress-fill-compact.complete {
269
- background: #10B981;
269
+ background: var(--mj-status-success);
270
270
  }
271
271
 
272
272
  .progress-text-compact {
273
273
  font-size: 10px;
274
274
  font-weight: 600;
275
- color: #6B7280;
275
+ color: var(--mj-text-muted);
276
276
  min-width: 30px;
277
277
  text-align: right;
278
278
  }
@@ -280,7 +280,7 @@ import { UUIDsEqual } from '@memberjunction/global';
280
280
  .no-tasks {
281
281
  text-align: center;
282
282
  padding: 60px 20px;
283
- color: #9CA3AF;
283
+ color: var(--mj-text-disabled);
284
284
  }
285
285
 
286
286
  .no-tasks i {
@@ -104,7 +104,7 @@ import { UUIDsEqual } from '@memberjunction/global';
104
104
  .task-detail-panel {
105
105
  width: 100%;
106
106
  height: calc(100% - 45px);
107
- background: white;
107
+ background: var(--mj-bg-surface);
108
108
  display: flex;
109
109
  flex-direction: column;
110
110
  overflow: hidden;
@@ -112,11 +112,11 @@ import { UUIDsEqual } from '@memberjunction/global';
112
112
 
113
113
  .detail-header {
114
114
  padding: 20px;
115
- border-bottom: 1px solid #E5E7EB;
115
+ border-bottom: 1px solid var(--mj-border-default);
116
116
  display: flex;
117
117
  justify-content: space-between;
118
118
  align-items: flex-start;
119
- background: #F9FAFB;
119
+ background: var(--mj-bg-surface-sunken);
120
120
  flex-shrink: 0;
121
121
  }
122
122
 
@@ -124,7 +124,7 @@ import { UUIDsEqual } from '@memberjunction/global';
124
124
  margin: 0;
125
125
  font-size: 18px;
126
126
  font-weight: 600;
127
- color: #111827;
127
+ color: var(--mj-text-primary);
128
128
  flex: 1;
129
129
  padding-right: 12px;
130
130
  }
@@ -132,7 +132,7 @@ import { UUIDsEqual } from '@memberjunction/global';
132
132
  .close-detail-btn {
133
133
  background: none;
134
134
  border: none;
135
- color: #6B7280;
135
+ color: var(--mj-text-muted);
136
136
  cursor: pointer;
137
137
  padding: 4px;
138
138
  width: 28px;
@@ -145,8 +145,8 @@ import { UUIDsEqual } from '@memberjunction/global';
145
145
  }
146
146
 
147
147
  .close-detail-btn:hover {
148
- background: #E5E7EB;
149
- color: #111827;
148
+ background: var(--mj-border-default);
149
+ color: var(--mj-text-primary);
150
150
  }
151
151
 
152
152
  .detail-content {
@@ -168,7 +168,7 @@ import { UUIDsEqual } from '@memberjunction/global';
168
168
  display: block;
169
169
  font-size: 12px;
170
170
  font-weight: 600;
171
- color: #6B7280;
171
+ color: var(--mj-text-muted);
172
172
  text-transform: uppercase;
173
173
  letter-spacing: 0.5px;
174
174
  margin-bottom: 6px;
@@ -177,7 +177,7 @@ import { UUIDsEqual } from '@memberjunction/global';
177
177
  .detail-field p {
178
178
  margin: 0;
179
179
  font-size: 14px;
180
- color: #111827;
180
+ color: var(--mj-text-primary);
181
181
  line-height: 1.5;
182
182
  }
183
183
 
@@ -190,21 +190,21 @@ import { UUIDsEqual } from '@memberjunction/global';
190
190
  .progress-bar-detail {
191
191
  flex: 1;
192
192
  height: 8px;
193
- background: #E5E7EB;
193
+ background: var(--mj-border-default);
194
194
  border-radius: 4px;
195
195
  overflow: hidden;
196
196
  }
197
197
 
198
198
  .progress-fill-detail {
199
199
  height: calc(100% - 69px);
200
- background: #3B82F6;
200
+ background: var(--mj-brand-primary);
201
201
  transition: width 0.3s ease;
202
202
  }
203
203
 
204
204
  .detail-progress span {
205
205
  font-size: 13px;
206
206
  font-weight: 600;
207
- color: #6B7280;
207
+ color: var(--mj-text-muted);
208
208
  min-width: 40px;
209
209
  }
210
210
 
@@ -213,31 +213,31 @@ import { UUIDsEqual } from '@memberjunction/global';
213
213
  align-items: center;
214
214
  gap: 10px;
215
215
  padding: 10px 12px;
216
- background: #F3F4F6;
216
+ background: var(--mj-bg-surface-sunken);
217
217
  border-radius: 6px;
218
218
  cursor: pointer;
219
219
  transition: all 0.15s;
220
220
  }
221
221
 
222
222
  .agent-info:hover {
223
- background: #E5E7EB;
223
+ background: var(--mj-border-default);
224
224
  }
225
225
 
226
226
  .agent-icon {
227
227
  font-size: 18px;
228
- color: #3B82F6;
228
+ color: var(--mj-brand-primary);
229
229
  }
230
230
 
231
231
  .agent-name {
232
232
  flex: 1;
233
233
  font-size: 14px;
234
234
  font-weight: 500;
235
- color: #111827;
235
+ color: var(--mj-text-primary);
236
236
  }
237
237
 
238
238
  .link-icon {
239
239
  font-size: 12px;
240
- color: #6B7280;
240
+ color: var(--mj-text-muted);
241
241
  }
242
242
 
243
243
  .agent-run-link {
@@ -245,21 +245,21 @@ import { UUIDsEqual } from '@memberjunction/global';
245
245
  align-items: center;
246
246
  gap: 8px;
247
247
  padding: 10px 12px;
248
- background: #F3F4F6;
248
+ background: var(--mj-bg-surface-sunken);
249
249
  border-radius: 6px;
250
250
  cursor: pointer;
251
251
  transition: all 0.15s;
252
252
  }
253
253
 
254
254
  .agent-run-link:hover {
255
- background: #E5E7EB;
255
+ background: var(--mj-border-default);
256
256
  }
257
257
 
258
258
  .agent-run-link span {
259
259
  flex: 1;
260
260
  font-size: 14px;
261
261
  font-weight: 500;
262
- color: #111827;
262
+ color: var(--mj-text-primary);
263
263
  }
264
264
  `]
265
265
  })
@@ -77,7 +77,7 @@ import { GanttTaskViewerComponent } from './gantt-task-viewer.component';
77
77
  display: flex;
78
78
  flex-direction: column;
79
79
  height: 100%;
80
- background: #FAFAFA;
80
+ background: var(--mj-bg-surface-sunken);
81
81
  }
82
82
 
83
83
  .task-header {
@@ -86,8 +86,8 @@ import { GanttTaskViewerComponent } from './gantt-task-viewer.component';
86
86
  align-items: flex-start;
87
87
  gap: 20px;
88
88
  padding: 20px 24px;
89
- background: white;
90
- border-bottom: 1px solid #E5E7EB;
89
+ background: var(--mj-bg-surface);
90
+ border-bottom: 1px solid var(--mj-border-default);
91
91
  }
92
92
 
93
93
  .header-left {
@@ -99,20 +99,20 @@ import { GanttTaskViewerComponent } from './gantt-task-viewer.component';
99
99
  margin: 0 0 8px 0;
100
100
  font-size: 20px;
101
101
  font-weight: 700;
102
- color: #111827;
102
+ color: var(--mj-text-primary);
103
103
  }
104
104
 
105
105
  .task-description {
106
106
  margin: 0;
107
107
  font-size: 14px;
108
- color: #6B7280;
108
+ color: var(--mj-text-muted);
109
109
  line-height: 1.5;
110
110
  }
111
111
 
112
112
  .view-toggle {
113
113
  display: flex;
114
114
  gap: 8px;
115
- background: #F3F4F6;
115
+ background: var(--mj-bg-surface-sunken);
116
116
  padding: 4px;
117
117
  border-radius: 8px;
118
118
  }
@@ -124,7 +124,7 @@ import { GanttTaskViewerComponent } from './gantt-task-viewer.component';
124
124
  padding: 8px 16px;
125
125
  border: none;
126
126
  background: transparent;
127
- color: #6B7280;
127
+ color: var(--mj-text-muted);
128
128
  font-size: 13px;
129
129
  font-weight: 600;
130
130
  border-radius: 6px;
@@ -133,14 +133,14 @@ import { GanttTaskViewerComponent } from './gantt-task-viewer.component';
133
133
  }
134
134
 
135
135
  .toggle-btn:hover {
136
- color: #111827;
137
- background: rgba(255, 255, 255, 0.5);
136
+ color: var(--mj-text-primary);
137
+ background: color-mix(in srgb, var(--mj-bg-surface) 50%, transparent);
138
138
  }
139
139
 
140
140
  .toggle-btn.active {
141
- background: white;
142
- color: #3B82F6;
143
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
141
+ background: var(--mj-bg-surface);
142
+ color: var(--mj-brand-primary);
143
+ box-shadow: var(--mj-shadow-sm);
144
144
  }
145
145
 
146
146
  .toggle-btn i {