@memberjunction/ng-tasks 6.1.4 → 6.2.0-edge.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +94 -49
- package/dist/lib/components/gantt-task-viewer.component.d.ts +61 -7
- package/dist/lib/components/gantt-task-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/gantt-task-viewer.component.js +127 -37
- package/dist/lib/components/gantt-task-viewer.component.js.map +1 -1
- package/dist/lib/components/simple-task-viewer.component.d.ts +55 -5
- package/dist/lib/components/simple-task-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/simple-task-viewer.component.js +98 -18
- package/dist/lib/components/simple-task-viewer.component.js.map +1 -1
- package/dist/lib/components/task-detail-panel.component.d.ts +36 -3
- package/dist/lib/components/task-detail-panel.component.d.ts.map +1 -1
- package/dist/lib/components/task-detail-panel.component.js +66 -16
- package/dist/lib/components/task-detail-panel.component.js.map +1 -1
- package/dist/lib/components/task.component.d.ts +82 -10
- package/dist/lib/components/task.component.d.ts.map +1 -1
- package/dist/lib/components/task.component.js +150 -18
- package/dist/lib/components/task.component.js.map +1 -1
- package/package.json +8 -8
- package/src/lib/components/gantt-task-viewer.component.ts +125 -33
- package/src/lib/components/simple-task-viewer.component.ts +100 -16
- package/src/lib/components/task-detail-panel.component.ts +65 -14
- package/src/lib/components/task.component.ts +140 -17
|
@@ -135,16 +135,88 @@ import { UUIDsEqual } from '@memberjunction/global';
|
|
|
135
135
|
`]
|
|
136
136
|
})
|
|
137
137
|
export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDestroy {
|
|
138
|
-
@Input()
|
|
139
|
-
@Input() taskDependencies: MJTaskDependencyEntity[] = [];
|
|
140
|
-
@Input() agentRunMap?: Map<string, string>; // Maps TaskID -> AgentRunID
|
|
141
|
-
@Output() taskClicked = new EventEmitter<MJTaskEntity>();
|
|
142
|
-
@Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();
|
|
138
|
+
@Input() Tasks: MJTaskEntity[] = [];
|
|
143
139
|
|
|
144
|
-
@
|
|
140
|
+
/** @deprecated Use {@link Tasks}. */
|
|
141
|
+
@Input() set tasks(value: MJTaskEntity[]) {
|
|
142
|
+
this.Tasks = value;
|
|
143
|
+
}
|
|
144
|
+
/** @deprecated Use {@link Tasks}. */
|
|
145
|
+
get tasks(): MJTaskEntity[] {
|
|
146
|
+
return this.Tasks;
|
|
147
|
+
}
|
|
148
|
+
@Input() TaskDependencies: MJTaskDependencyEntity[] = [];
|
|
149
|
+
|
|
150
|
+
/** @deprecated Use {@link TaskDependencies}. */
|
|
151
|
+
@Input() set taskDependencies(value: MJTaskDependencyEntity[]) {
|
|
152
|
+
this.TaskDependencies = value;
|
|
153
|
+
}
|
|
154
|
+
/** @deprecated Use {@link TaskDependencies}. */
|
|
155
|
+
get taskDependencies(): MJTaskDependencyEntity[] {
|
|
156
|
+
return this.TaskDependencies;
|
|
157
|
+
}
|
|
158
|
+
@Input() AgentRunMap?: Map<string, string>;
|
|
159
|
+
|
|
160
|
+
/** @deprecated Use {@link AgentRunMap}. */
|
|
161
|
+
@Input() set agentRunMap(value: Map<string, string> | undefined) {
|
|
162
|
+
this.AgentRunMap = value;
|
|
163
|
+
}
|
|
164
|
+
/** @deprecated Use {@link AgentRunMap}. */
|
|
165
|
+
get agentRunMap(): Map<string, string> | undefined {
|
|
166
|
+
return this.AgentRunMap;
|
|
167
|
+
} // Maps TaskID -> AgentRunID
|
|
168
|
+
@Output() TaskClicked = new EventEmitter<MJTaskEntity>();
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @deprecated Use {@link TaskClicked}.
|
|
172
|
+
*
|
|
173
|
+
* The same emitter under the old binding name, so a template still binding
|
|
174
|
+
* (taskClicked) keeps working. Must stay AFTER TaskClicked: class fields
|
|
175
|
+
* initialise in order, and the other way round this captures undefined.
|
|
176
|
+
*/
|
|
177
|
+
@Output() taskClicked = this.TaskClicked;
|
|
178
|
+
@Output() OpenEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @deprecated Use {@link OpenEntityRecord}.
|
|
182
|
+
*
|
|
183
|
+
* The same emitter under the old binding name, so a template still binding
|
|
184
|
+
* (openEntityRecord) keeps working. Must stay AFTER OpenEntityRecord: class fields
|
|
185
|
+
* initialise in order, and the other way round this captures undefined.
|
|
186
|
+
*/
|
|
187
|
+
@Output() openEntityRecord = this.OpenEntityRecord;
|
|
188
|
+
|
|
189
|
+
@ViewChild('ganttContainer', { static: false }) GanttContainer!: ElementRef<HTMLDivElement>;
|
|
190
|
+
|
|
191
|
+
/** @deprecated Use {@link GanttContainer}. */
|
|
192
|
+
get ganttContainer(): ElementRef<HTMLDivElement> {
|
|
193
|
+
return this.GanttContainer;
|
|
194
|
+
}
|
|
195
|
+
/** @deprecated Use {@link GanttContainer}. */
|
|
196
|
+
set ganttContainer(value: ElementRef<HTMLDivElement>) {
|
|
197
|
+
this.GanttContainer = value;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
public SelectedTask: MJTaskEntity | null = null;
|
|
201
|
+
|
|
202
|
+
/** @deprecated Use {@link SelectedTask}. */
|
|
203
|
+
public get selectedTask(): MJTaskEntity | null {
|
|
204
|
+
return this.SelectedTask;
|
|
205
|
+
}
|
|
206
|
+
/** @deprecated Use {@link SelectedTask}. */
|
|
207
|
+
public set selectedTask(value: MJTaskEntity | null) {
|
|
208
|
+
this.SelectedTask = value;
|
|
209
|
+
}
|
|
210
|
+
public DetailPanelWidth: number = 400;
|
|
145
211
|
|
|
146
|
-
|
|
147
|
-
public detailPanelWidth: number
|
|
212
|
+
/** @deprecated Use {@link DetailPanelWidth}. */
|
|
213
|
+
public get detailPanelWidth(): number {
|
|
214
|
+
return this.DetailPanelWidth;
|
|
215
|
+
}
|
|
216
|
+
/** @deprecated Use {@link DetailPanelWidth}. */
|
|
217
|
+
public set detailPanelWidth(value: number) {
|
|
218
|
+
this.DetailPanelWidth = value;
|
|
219
|
+
}
|
|
148
220
|
public IsGanttLoading = true;
|
|
149
221
|
|
|
150
222
|
private ganttLib: GanttStatic | null = null;
|
|
@@ -155,8 +227,8 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
155
227
|
|
|
156
228
|
async ngAfterViewInit() {
|
|
157
229
|
console.log('🔧 ngAfterViewInit called', {
|
|
158
|
-
taskCount: this.
|
|
159
|
-
hasContainer: !!this.
|
|
230
|
+
taskCount: this.Tasks?.length || 0,
|
|
231
|
+
hasContainer: !!this.GanttContainer
|
|
160
232
|
});
|
|
161
233
|
|
|
162
234
|
try {
|
|
@@ -164,7 +236,7 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
164
236
|
this.ganttLib = module.gantt;
|
|
165
237
|
this.IsGanttLoading = false;
|
|
166
238
|
|
|
167
|
-
if (this.
|
|
239
|
+
if (this.Tasks && this.Tasks.length > 0 && this.GanttContainer) {
|
|
168
240
|
this.initGantt();
|
|
169
241
|
}
|
|
170
242
|
} catch (error) {
|
|
@@ -176,15 +248,15 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
176
248
|
ngOnChanges() {
|
|
177
249
|
console.log('🔄 ngOnChanges called', {
|
|
178
250
|
initialized: this.ganttInitialized,
|
|
179
|
-
hasContainer: !!this.
|
|
180
|
-
taskCount: this.
|
|
251
|
+
hasContainer: !!this.GanttContainer,
|
|
252
|
+
taskCount: this.Tasks?.length || 0
|
|
181
253
|
});
|
|
182
254
|
|
|
183
255
|
if (!this.ganttLib) return; // Library not yet loaded
|
|
184
256
|
|
|
185
|
-
if (this.ganttInitialized && this.
|
|
257
|
+
if (this.ganttInitialized && this.GanttContainer) {
|
|
186
258
|
this.updateGanttData();
|
|
187
|
-
} else if (!this.ganttInitialized && this.
|
|
259
|
+
} else if (!this.ganttInitialized && this.GanttContainer && this.Tasks && this.Tasks.length > 0) {
|
|
188
260
|
// Initialize if we have container and tasks but haven't initialized yet
|
|
189
261
|
console.log('🎨 Late initialization - gantt not initialized but container and tasks available');
|
|
190
262
|
this.initGantt();
|
|
@@ -247,15 +319,15 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
247
319
|
];
|
|
248
320
|
|
|
249
321
|
// Initialize Gantt in the container
|
|
250
|
-
g.init(this.
|
|
322
|
+
g.init(this.GanttContainer.nativeElement);
|
|
251
323
|
this.ganttInitialized = true;
|
|
252
324
|
|
|
253
325
|
// Attach click event
|
|
254
326
|
g.attachEvent('onTaskClick', (id: string) => {
|
|
255
|
-
const originalTask = this.
|
|
327
|
+
const originalTask = this.Tasks.find(t => UUIDsEqual(t.ID, id));
|
|
256
328
|
if (originalTask) {
|
|
257
|
-
this.
|
|
258
|
-
this.
|
|
329
|
+
this.SelectedTask = originalTask;
|
|
330
|
+
this.TaskClicked.emit(originalTask);
|
|
259
331
|
}
|
|
260
332
|
return true;
|
|
261
333
|
});
|
|
@@ -283,10 +355,10 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
283
355
|
if (!this.ganttInitialized) return;
|
|
284
356
|
|
|
285
357
|
try {
|
|
286
|
-
console.log('📊 Updating Gantt data with', this.
|
|
358
|
+
console.log('📊 Updating Gantt data with', this.Tasks.length, 'tasks');
|
|
287
359
|
const g = this.ganttLib!;
|
|
288
360
|
|
|
289
|
-
const ganttData = this.convertToGanttFormat(this.
|
|
361
|
+
const ganttData = this.convertToGanttFormat(this.Tasks);
|
|
290
362
|
g.clearAll();
|
|
291
363
|
g.parse(ganttData);
|
|
292
364
|
|
|
@@ -317,7 +389,7 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
317
389
|
const links: GanttLink[] = [];
|
|
318
390
|
|
|
319
391
|
console.log('🔍 Converting tasks:', tasks);
|
|
320
|
-
console.log('🔗 Task dependencies:', this.
|
|
392
|
+
console.log('🔗 Task dependencies:', this.TaskDependencies);
|
|
321
393
|
|
|
322
394
|
// Build a map of task ID to task for quick lookup
|
|
323
395
|
const taskMap = new Map<string, MJTaskEntity>();
|
|
@@ -325,7 +397,7 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
325
397
|
|
|
326
398
|
// Build dependency map: taskId -> array of tasks it depends on
|
|
327
399
|
const dependencyMap = new Map<string, string[]>();
|
|
328
|
-
this.
|
|
400
|
+
this.TaskDependencies.forEach(dep => {
|
|
329
401
|
if (!dependencyMap.has(dep.TaskID)) {
|
|
330
402
|
dependencyMap.set(dep.TaskID, []);
|
|
331
403
|
}
|
|
@@ -456,7 +528,7 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
456
528
|
});
|
|
457
529
|
|
|
458
530
|
// Create links from MJTaskDependencyEntity records
|
|
459
|
-
this.
|
|
531
|
+
this.TaskDependencies.forEach((dep, index) => {
|
|
460
532
|
links.push({
|
|
461
533
|
id: dep.ID || `link_${index}`,
|
|
462
534
|
source: dep.DependsOnTaskID, // The task being depended on
|
|
@@ -486,25 +558,45 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
486
558
|
return `${year}-${month}-${day} 00:00`;
|
|
487
559
|
}
|
|
488
560
|
|
|
561
|
+
public GetAgentRunId(task: MJTaskEntity): string | null {
|
|
562
|
+
return this.AgentRunMap?.get(task.ID) || null;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/** @deprecated Use {@link GetAgentRunId}. */
|
|
489
566
|
public getAgentRunId(task: MJTaskEntity): string | null {
|
|
490
|
-
return this.
|
|
567
|
+
return this.GetAgentRunId(task);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
public CloseDetailPanel(): void {
|
|
571
|
+
this.SelectedTask = null;
|
|
491
572
|
}
|
|
492
573
|
|
|
574
|
+
/** @deprecated Use {@link CloseDetailPanel}. */
|
|
493
575
|
public closeDetailPanel(): void {
|
|
494
|
-
this.
|
|
576
|
+
return this.CloseDetailPanel();
|
|
495
577
|
}
|
|
496
578
|
|
|
579
|
+
public OnOpenEntityRecord(event: { entityName: string; recordId: string }): void {
|
|
580
|
+
this.OpenEntityRecord.emit(event);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/** @deprecated Use {@link OnOpenEntityRecord}. */
|
|
497
584
|
public onOpenEntityRecord(event: { entityName: string; recordId: string }): void {
|
|
498
|
-
this.
|
|
585
|
+
return this.OnOpenEntityRecord(event);
|
|
499
586
|
}
|
|
500
587
|
|
|
501
|
-
public
|
|
588
|
+
public StartResize(event: MouseEvent): void {
|
|
502
589
|
this.isResizing = true;
|
|
503
590
|
this.resizeStartX = event.clientX;
|
|
504
|
-
this.resizeStartWidth = this.
|
|
591
|
+
this.resizeStartWidth = this.DetailPanelWidth;
|
|
505
592
|
event.preventDefault();
|
|
506
593
|
}
|
|
507
594
|
|
|
595
|
+
/** @deprecated Use {@link StartResize}. */
|
|
596
|
+
public startResize(event: MouseEvent): void {
|
|
597
|
+
return this.StartResize(event);
|
|
598
|
+
}
|
|
599
|
+
|
|
508
600
|
@HostListener('document:mousemove', ['$event'])
|
|
509
601
|
handleResize(event: MouseEvent): void {
|
|
510
602
|
if (!this.isResizing) return;
|
|
@@ -513,7 +605,7 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
513
605
|
const newWidth = this.resizeStartWidth + delta;
|
|
514
606
|
|
|
515
607
|
// Constrain width between min and max
|
|
516
|
-
this.
|
|
608
|
+
this.DetailPanelWidth = Math.max(300, Math.min(600, newWidth));
|
|
517
609
|
}
|
|
518
610
|
|
|
519
611
|
@HostListener('document:mouseup')
|
|
@@ -550,10 +642,10 @@ export class GanttTaskViewerComponent implements OnChanges, AfterViewInit, OnDes
|
|
|
550
642
|
if (rootTaskId != null) {
|
|
551
643
|
g.selectTask(rootTaskId);
|
|
552
644
|
// Trigger task click event to open detail panel
|
|
553
|
-
const originalTask = this.
|
|
645
|
+
const originalTask = this.Tasks.find(t => UUIDsEqual(t.ID, String(rootTaskId)));
|
|
554
646
|
if (originalTask) {
|
|
555
|
-
this.
|
|
556
|
-
this.
|
|
647
|
+
this.SelectedTask = originalTask;
|
|
648
|
+
this.TaskClicked.emit(originalTask);
|
|
557
649
|
}
|
|
558
650
|
}
|
|
559
651
|
|
|
@@ -312,17 +312,71 @@ import { UUIDsEqual } from '@memberjunction/global';
|
|
|
312
312
|
`]
|
|
313
313
|
})
|
|
314
314
|
export class SimpleTaskViewerComponent implements OnChanges {
|
|
315
|
-
@Input()
|
|
316
|
-
@Input() agentRunMap?: Map<string, string>; // Maps TaskID -> AgentRunID
|
|
317
|
-
@Output() taskClicked = new EventEmitter<MJTaskEntity>();
|
|
318
|
-
@Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();
|
|
315
|
+
@Input() Tasks: MJTaskEntity[] = [];
|
|
319
316
|
|
|
320
|
-
|
|
317
|
+
/** @deprecated Use {@link Tasks}. */
|
|
318
|
+
@Input() set tasks(value: MJTaskEntity[]) {
|
|
319
|
+
this.Tasks = value;
|
|
320
|
+
}
|
|
321
|
+
/** @deprecated Use {@link Tasks}. */
|
|
322
|
+
get tasks(): MJTaskEntity[] {
|
|
323
|
+
return this.Tasks;
|
|
324
|
+
}
|
|
325
|
+
@Input() AgentRunMap?: Map<string, string>;
|
|
326
|
+
|
|
327
|
+
/** @deprecated Use {@link AgentRunMap}. */
|
|
328
|
+
@Input() set agentRunMap(value: Map<string, string> | undefined) {
|
|
329
|
+
this.AgentRunMap = value;
|
|
330
|
+
}
|
|
331
|
+
/** @deprecated Use {@link AgentRunMap}. */
|
|
332
|
+
get agentRunMap(): Map<string, string> | undefined {
|
|
333
|
+
return this.AgentRunMap;
|
|
334
|
+
} // Maps TaskID -> AgentRunID
|
|
335
|
+
@Output() TaskClicked = new EventEmitter<MJTaskEntity>();
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* @deprecated Use {@link TaskClicked}.
|
|
339
|
+
*
|
|
340
|
+
* The same emitter under the old binding name, so a template still binding
|
|
341
|
+
* (taskClicked) keeps working. Must stay AFTER TaskClicked: class fields
|
|
342
|
+
* initialise in order, and the other way round this captures undefined.
|
|
343
|
+
*/
|
|
344
|
+
@Output() taskClicked = this.TaskClicked;
|
|
345
|
+
@Output() OpenEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* @deprecated Use {@link OpenEntityRecord}.
|
|
349
|
+
*
|
|
350
|
+
* The same emitter under the old binding name, so a template still binding
|
|
351
|
+
* (openEntityRecord) keeps working. Must stay AFTER OpenEntityRecord: class fields
|
|
352
|
+
* initialise in order, and the other way round this captures undefined.
|
|
353
|
+
*/
|
|
354
|
+
@Output() openEntityRecord = this.OpenEntityRecord;
|
|
355
|
+
|
|
356
|
+
public SelectedTask: MJTaskEntity | null = null;
|
|
357
|
+
|
|
358
|
+
/** @deprecated Use {@link SelectedTask}. */
|
|
359
|
+
public get selectedTask(): MJTaskEntity | null {
|
|
360
|
+
return this.SelectedTask;
|
|
361
|
+
}
|
|
362
|
+
/** @deprecated Use {@link SelectedTask}. */
|
|
363
|
+
public set selectedTask(value: MJTaskEntity | null) {
|
|
364
|
+
this.SelectedTask = value;
|
|
365
|
+
}
|
|
321
366
|
|
|
322
367
|
public IsTaskSelected(task: MJTaskEntity): boolean {
|
|
323
|
-
return UUIDsEqual(this.
|
|
368
|
+
return UUIDsEqual(this.SelectedTask?.ID, task.ID);
|
|
369
|
+
}
|
|
370
|
+
public DetailPanelWidth: number = 400;
|
|
371
|
+
|
|
372
|
+
/** @deprecated Use {@link DetailPanelWidth}. */
|
|
373
|
+
public get detailPanelWidth(): number {
|
|
374
|
+
return this.DetailPanelWidth;
|
|
375
|
+
}
|
|
376
|
+
/** @deprecated Use {@link DetailPanelWidth}. */
|
|
377
|
+
public set detailPanelWidth(value: number) {
|
|
378
|
+
this.DetailPanelWidth = value;
|
|
324
379
|
}
|
|
325
|
-
public detailPanelWidth: number = 400;
|
|
326
380
|
|
|
327
381
|
private isResizing = false;
|
|
328
382
|
private resizeStartX = 0;
|
|
@@ -332,30 +386,55 @@ export class SimpleTaskViewerComponent implements OnChanges {
|
|
|
332
386
|
// Tasks are already loaded
|
|
333
387
|
}
|
|
334
388
|
|
|
389
|
+
public OnTaskClick(task: MJTaskEntity): void {
|
|
390
|
+
this.SelectedTask = task;
|
|
391
|
+
this.TaskClicked.emit(task);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/** @deprecated Use {@link OnTaskClick}. */
|
|
335
395
|
public onTaskClick(task: MJTaskEntity): void {
|
|
336
|
-
this.
|
|
337
|
-
|
|
396
|
+
return this.OnTaskClick(task);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
public GetAgentRunId(task: MJTaskEntity): string | null {
|
|
400
|
+
return this.AgentRunMap?.get(task.ID) || null;
|
|
338
401
|
}
|
|
339
402
|
|
|
403
|
+
/** @deprecated Use {@link GetAgentRunId}. */
|
|
340
404
|
public getAgentRunId(task: MJTaskEntity): string | null {
|
|
341
|
-
return this.
|
|
405
|
+
return this.GetAgentRunId(task);
|
|
342
406
|
}
|
|
343
407
|
|
|
408
|
+
public CloseDetailPanel(): void {
|
|
409
|
+
this.SelectedTask = null;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/** @deprecated Use {@link CloseDetailPanel}. */
|
|
344
413
|
public closeDetailPanel(): void {
|
|
345
|
-
this.
|
|
414
|
+
return this.CloseDetailPanel();
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
public OnOpenEntityRecord(event: { entityName: string; recordId: string }): void {
|
|
418
|
+
this.OpenEntityRecord.emit(event);
|
|
346
419
|
}
|
|
347
420
|
|
|
421
|
+
/** @deprecated Use {@link OnOpenEntityRecord}. */
|
|
348
422
|
public onOpenEntityRecord(event: { entityName: string; recordId: string }): void {
|
|
349
|
-
this.
|
|
423
|
+
return this.OnOpenEntityRecord(event);
|
|
350
424
|
}
|
|
351
425
|
|
|
352
|
-
public
|
|
426
|
+
public StartResize(event: MouseEvent): void {
|
|
353
427
|
this.isResizing = true;
|
|
354
428
|
this.resizeStartX = event.clientX;
|
|
355
|
-
this.resizeStartWidth = this.
|
|
429
|
+
this.resizeStartWidth = this.DetailPanelWidth;
|
|
356
430
|
event.preventDefault();
|
|
357
431
|
}
|
|
358
432
|
|
|
433
|
+
/** @deprecated Use {@link StartResize}. */
|
|
434
|
+
public startResize(event: MouseEvent): void {
|
|
435
|
+
return this.StartResize(event);
|
|
436
|
+
}
|
|
437
|
+
|
|
359
438
|
@HostListener('document:mousemove', ['$event'])
|
|
360
439
|
handleResize(event: MouseEvent): void {
|
|
361
440
|
if (!this.isResizing) return;
|
|
@@ -364,7 +443,7 @@ export class SimpleTaskViewerComponent implements OnChanges {
|
|
|
364
443
|
const newWidth = this.resizeStartWidth + delta;
|
|
365
444
|
|
|
366
445
|
// Constrain width between min and max
|
|
367
|
-
this.
|
|
446
|
+
this.DetailPanelWidth = Math.max(300, Math.min(600, newWidth));
|
|
368
447
|
}
|
|
369
448
|
|
|
370
449
|
@HostListener('document:mouseup')
|
|
@@ -372,7 +451,7 @@ export class SimpleTaskViewerComponent implements OnChanges {
|
|
|
372
451
|
this.isResizing = false;
|
|
373
452
|
}
|
|
374
453
|
|
|
375
|
-
public
|
|
454
|
+
public GetStatusIcon(status: string): string {
|
|
376
455
|
switch (status) {
|
|
377
456
|
case 'Complete': return 'fa-check-circle';
|
|
378
457
|
case 'In Progress': return 'fa-spinner';
|
|
@@ -383,6 +462,11 @@ export class SimpleTaskViewerComponent implements OnChanges {
|
|
|
383
462
|
}
|
|
384
463
|
}
|
|
385
464
|
|
|
465
|
+
/** @deprecated Use {@link GetStatusIcon}. */
|
|
466
|
+
public getStatusIcon(status: string): string {
|
|
467
|
+
return this.GetStatusIcon(status);
|
|
468
|
+
}
|
|
469
|
+
|
|
386
470
|
public formatDate(date: Date | null): string {
|
|
387
471
|
if (!date) return '';
|
|
388
472
|
const d = new Date(date);
|
|
@@ -264,12 +264,48 @@ import { UUIDsEqual } from '@memberjunction/global';
|
|
|
264
264
|
`]
|
|
265
265
|
})
|
|
266
266
|
export class TaskDetailPanelComponent implements OnInit, OnChanges {
|
|
267
|
-
@Input()
|
|
267
|
+
@Input() Task!: MJTaskEntity;
|
|
268
|
+
|
|
269
|
+
/** @deprecated Use {@link Task}. */
|
|
270
|
+
@Input() set task(value: MJTaskEntity) {
|
|
271
|
+
this.Task = value;
|
|
272
|
+
}
|
|
273
|
+
/** @deprecated Use {@link Task}. */
|
|
274
|
+
get task(): MJTaskEntity {
|
|
275
|
+
return this.Task;
|
|
276
|
+
}
|
|
268
277
|
@Input() agentRunId: string | null = null;
|
|
269
|
-
@Output()
|
|
270
|
-
|
|
278
|
+
@Output() ClosePanel = new EventEmitter<void>();
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* @deprecated Use {@link ClosePanel}.
|
|
282
|
+
*
|
|
283
|
+
* The same emitter under the old binding name, so a template still binding
|
|
284
|
+
* (closePanel) keeps working. Must stay AFTER ClosePanel: class fields
|
|
285
|
+
* initialise in order, and the other way round this captures undefined.
|
|
286
|
+
*/
|
|
287
|
+
@Output() closePanel = this.ClosePanel;
|
|
288
|
+
@Output() OpenEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* @deprecated Use {@link OpenEntityRecord}.
|
|
292
|
+
*
|
|
293
|
+
* The same emitter under the old binding name, so a template still binding
|
|
294
|
+
* (openEntityRecord) keeps working. Must stay AFTER OpenEntityRecord: class fields
|
|
295
|
+
* initialise in order, and the other way round this captures undefined.
|
|
296
|
+
*/
|
|
297
|
+
@Output() openEntityRecord = this.OpenEntityRecord;
|
|
271
298
|
|
|
272
|
-
public
|
|
299
|
+
public Agent: MJAIAgentEntityExtended | null = null;
|
|
300
|
+
|
|
301
|
+
/** @deprecated Use {@link Agent}. */
|
|
302
|
+
public get agent(): MJAIAgentEntityExtended | null {
|
|
303
|
+
return this.Agent;
|
|
304
|
+
}
|
|
305
|
+
/** @deprecated Use {@link Agent}. */
|
|
306
|
+
public set agent(value: MJAIAgentEntityExtended | null) {
|
|
307
|
+
this.Agent = value;
|
|
308
|
+
}
|
|
273
309
|
|
|
274
310
|
ngOnInit(): void {
|
|
275
311
|
this.loadAgentInfo();
|
|
@@ -280,18 +316,18 @@ export class TaskDetailPanelComponent implements OnInit, OnChanges {
|
|
|
280
316
|
}
|
|
281
317
|
|
|
282
318
|
private async loadAgentInfo(): Promise<void> {
|
|
283
|
-
if (!this.
|
|
284
|
-
this.
|
|
319
|
+
if (!this.Task?.AgentID) {
|
|
320
|
+
this.Agent = null;
|
|
285
321
|
return;
|
|
286
322
|
}
|
|
287
323
|
|
|
288
324
|
// AIEngineBase is deferred at startup; ensure loaded before reading .Agents.
|
|
289
325
|
await AIEngineBase.Instance.EnsureLoaded();
|
|
290
326
|
const agents = AIEngineBase.Instance.Agents;
|
|
291
|
-
this.
|
|
327
|
+
this.Agent = agents.find((a: MJAIAgentEntityExtended) => UUIDsEqual(a.ID, this.Task.AgentID)) || null;
|
|
292
328
|
}
|
|
293
329
|
|
|
294
|
-
public
|
|
330
|
+
public FormatDateTime(date: Date | null): string {
|
|
295
331
|
if (!date) return '';
|
|
296
332
|
const d = new Date(date);
|
|
297
333
|
return d.toLocaleDateString('en-US', {
|
|
@@ -303,21 +339,36 @@ export class TaskDetailPanelComponent implements OnInit, OnChanges {
|
|
|
303
339
|
});
|
|
304
340
|
}
|
|
305
341
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
342
|
+
/** @deprecated Use {@link FormatDateTime}. */
|
|
343
|
+
public formatDateTime(date: Date | null): string {
|
|
344
|
+
return this.FormatDateTime(date);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
public OpenAgent(): void {
|
|
348
|
+
if (this.Task.AgentID) {
|
|
349
|
+
this.OpenEntityRecord.emit({
|
|
309
350
|
entityName: 'MJ: AI Agents',
|
|
310
|
-
recordId: this.
|
|
351
|
+
recordId: this.Task.AgentID
|
|
311
352
|
});
|
|
312
353
|
}
|
|
313
354
|
}
|
|
314
355
|
|
|
315
|
-
|
|
356
|
+
/** @deprecated Use {@link OpenAgent}. */
|
|
357
|
+
public openAgent(): void {
|
|
358
|
+
return this.OpenAgent();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
public OpenAgentRun(): void {
|
|
316
362
|
if (this.agentRunId) {
|
|
317
|
-
this.
|
|
363
|
+
this.OpenEntityRecord.emit({
|
|
318
364
|
entityName: 'MJ: AI Agent Runs',
|
|
319
365
|
recordId: this.agentRunId
|
|
320
366
|
});
|
|
321
367
|
}
|
|
322
368
|
}
|
|
369
|
+
|
|
370
|
+
/** @deprecated Use {@link OpenAgentRun}. */
|
|
371
|
+
public openAgentRun(): void {
|
|
372
|
+
return this.OpenAgentRun();
|
|
373
|
+
}
|
|
323
374
|
}
|