Initial commit: timeline-elements-ui library
Angular 19 component library for timelines and event tracking: timeline, Gantt chart, event cards, date markers, connectors, and custom event templates. Includes signal-based services, SCSS design tokens with dark mode, and TypeScript type definitions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
102
src/components/tl-gantt-chart/tl-gantt-chart.component.ts
Normal file
102
src/components/tl-gantt-chart/tl-gantt-chart.component.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { Component, ChangeDetectionStrategy, input, output, computed } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ButtonComponent, IconComponent, TooltipDirective, SkeletonComponent } from '@sda/base-ui';
|
||||
import { TlGanttRowComponent } from '../tl-gantt-row';
|
||||
import { TlTimelineToolbarComponent } from '../tl-timeline-toolbar';
|
||||
import { GanttService } from '../../services/gantt.service';
|
||||
import type { TlGanttTask, TlGanttDependency, TlDateTick } from '../../types/gantt.types';
|
||||
import type { TlGanttTaskClickEvent, TlGanttTaskResizeEvent, TlGanttTaskMoveEvent, TlGanttZoomChangeEvent, TlGanttScrollEvent } from '../../types/event.types';
|
||||
import { calculateDateRange, sortTasksHierarchically, calculateChartWidth } from '../../utils/gantt.utils';
|
||||
|
||||
@Component({
|
||||
selector: 'tl-gantt-chart',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
ButtonComponent,
|
||||
IconComponent,
|
||||
TooltipDirective,
|
||||
SkeletonComponent,
|
||||
TlGanttRowComponent,
|
||||
TlTimelineToolbarComponent,
|
||||
],
|
||||
providers: [GanttService],
|
||||
templateUrl: './tl-gantt-chart.component.html',
|
||||
styleUrl: './tl-gantt-chart.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class TlGanttChartComponent {
|
||||
constructor(protected readonly ganttService: GanttService) {}
|
||||
|
||||
readonly tasks = input.required<TlGanttTask[]>();
|
||||
readonly dependencies = input<TlGanttDependency[]>([]);
|
||||
readonly zoomLevel = input<'day' | 'week' | 'month' | 'quarter' | 'year'>('week');
|
||||
readonly rowHeight = input(40);
|
||||
readonly showDependencies = input(true);
|
||||
readonly showProgress = input(true);
|
||||
readonly showTodayLine = input(true);
|
||||
readonly loading = input(false);
|
||||
readonly emptyMessage = input('No tasks');
|
||||
|
||||
readonly taskClick = output<TlGanttTaskClickEvent>();
|
||||
readonly taskResize = output<TlGanttTaskResizeEvent>();
|
||||
readonly taskMove = output<TlGanttTaskMoveEvent>();
|
||||
readonly zoomChange = output<TlGanttZoomChangeEvent>();
|
||||
readonly scroll = output<TlGanttScrollEvent>();
|
||||
|
||||
protected readonly dateRange = computed(() => {
|
||||
if (this.tasks().length === 0) {
|
||||
return { start: new Date(), end: new Date() };
|
||||
}
|
||||
return calculateDateRange(this.tasks());
|
||||
});
|
||||
|
||||
protected readonly dateAxis = computed(() => {
|
||||
const range = this.dateRange();
|
||||
return this.ganttService.calculateDateAxis(range.start, range.end);
|
||||
});
|
||||
|
||||
protected readonly sortedTasks = computed(() => {
|
||||
return sortTasksHierarchically(this.tasks());
|
||||
});
|
||||
|
||||
protected readonly taskPositions = computed(() => {
|
||||
const range = this.dateRange();
|
||||
return this.sortedTasks().map(task =>
|
||||
this.ganttService.calculateTaskPosition(task, range.start)
|
||||
);
|
||||
});
|
||||
|
||||
protected readonly todayPosition = computed(() => {
|
||||
if (!this.showTodayLine()) return null;
|
||||
const range = this.dateRange();
|
||||
return this.ganttService.calculateTodayPosition(range.start);
|
||||
});
|
||||
|
||||
protected readonly totalWidth = computed(() => {
|
||||
const range = this.dateRange();
|
||||
return calculateChartWidth(range.start, range.end, this.ganttService.pixelsPerDay());
|
||||
});
|
||||
|
||||
protected onZoomIn(): void {
|
||||
this.ganttService.zoomIn();
|
||||
this.zoomChange.emit({ level: this.ganttService.zoomLevel() });
|
||||
}
|
||||
|
||||
protected onZoomOut(): void {
|
||||
this.ganttService.zoomOut();
|
||||
this.zoomChange.emit({ level: this.ganttService.zoomLevel() });
|
||||
}
|
||||
|
||||
protected onTaskClick(event: TlGanttTaskClickEvent): void {
|
||||
this.taskClick.emit(event);
|
||||
}
|
||||
|
||||
protected onTaskResize(event: TlGanttTaskResizeEvent): void {
|
||||
this.taskResize.emit(event);
|
||||
}
|
||||
|
||||
protected getLoadingItems(): number[] {
|
||||
return Array.from({ length: 5 }, (_, i) => i);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user