fix: Resolve all ESLint errors and warnings in web package
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Fixes all 542 ESLint problems in the web package to achieve 0 errors and 0 warnings. Changes: - Fixed 144 issues: nullish coalescing, return types, unused variables - Fixed 118 issues: unnecessary conditions, type safety, template literals - Fixed 79 issues: non-null assertions, unsafe assignments, empty functions - Fixed 67 issues: explicit return types, promise handling, enum comparisons - Fixed 45 final warnings: missing return types, optional chains - Fixed 25 typecheck-related issues: async/await, type assertions, formatting - Fixed JSX.Element namespace errors across 90+ files All Quality Rails violations resolved. Lint and typecheck both pass with 0 problems. Files modified: 118 components, tests, hooks, and utilities Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ describe("GanttChart", (): void => {
|
||||
const baseDate = new Date("2026-02-01T00:00:00Z");
|
||||
|
||||
const createGanttTask = (overrides: Partial<GanttTask> = {}): GanttTask => ({
|
||||
id: `task-${Math.random()}`,
|
||||
id: `task-${String(Math.random())}`,
|
||||
workspaceId: "workspace-1",
|
||||
title: "Sample Task",
|
||||
description: null,
|
||||
@@ -90,7 +90,8 @@ describe("GanttChart", (): void => {
|
||||
|
||||
render(<GanttChart tasks={tasks} />);
|
||||
|
||||
const taskRow = screen.getAllByText("Completed Task")[0]!.closest("[role='row']");
|
||||
const taskElements = screen.getAllByText("Completed Task");
|
||||
const taskRow = taskElements[0]?.closest("[role='row']");
|
||||
expect(taskRow?.className).toMatch(/Completed/i);
|
||||
});
|
||||
|
||||
@@ -105,7 +106,8 @@ describe("GanttChart", (): void => {
|
||||
|
||||
render(<GanttChart tasks={tasks} />);
|
||||
|
||||
const taskRow = screen.getAllByText("Active Task")[0]!.closest("[role='row']");
|
||||
const taskElements = screen.getAllByText("Active Task");
|
||||
const taskRow = taskElements[0]?.closest("[role='row']");
|
||||
expect(taskRow?.className).toMatch(/InProgress/i);
|
||||
});
|
||||
});
|
||||
@@ -219,8 +221,8 @@ describe("GanttChart", (): void => {
|
||||
expect(bars).toHaveLength(2);
|
||||
|
||||
// Second bar should be wider (more days)
|
||||
const bar1Width = bars[0]!.style.width;
|
||||
const bar2Width = bars[1]!.style.width;
|
||||
const bar1Width = bars[0]?.style.width;
|
||||
const bar2Width = bars[1]?.style.width;
|
||||
|
||||
// Basic check that widths are set (exact values depend on implementation)
|
||||
expect(bar1Width).toBeTruthy();
|
||||
@@ -344,11 +346,15 @@ describe("GanttChart", (): void => {
|
||||
|
||||
render(<GanttChart tasks={tasks} />);
|
||||
|
||||
const taskNames = screen.getAllByRole("row").map((row) => row.textContent);
|
||||
const taskNames = screen.getAllByRole("row").map((row): string | null => row.textContent);
|
||||
|
||||
// Early Task should appear first
|
||||
const earlyIndex = taskNames.findIndex((name) => name?.includes("Early Task"));
|
||||
const lateIndex = taskNames.findIndex((name) => name?.includes("Late Task"));
|
||||
const earlyIndex = taskNames.findIndex(
|
||||
(name): boolean => name?.includes("Early Task") ?? false
|
||||
);
|
||||
const lateIndex = taskNames.findIndex(
|
||||
(name): boolean => name?.includes("Late Task") ?? false
|
||||
);
|
||||
|
||||
expect(earlyIndex).toBeLessThan(lateIndex);
|
||||
});
|
||||
|
||||
@@ -34,10 +34,22 @@ function calculateTimelineRange(tasks: GanttTask[]): TimelineRange {
|
||||
};
|
||||
}
|
||||
|
||||
let earliest = tasks[0]!.startDate;
|
||||
let latest = tasks[0]!.endDate;
|
||||
const firstTask = tasks[0];
|
||||
if (!firstTask) {
|
||||
// This should not happen due to the check above, but makes TS happy
|
||||
const now = new Date();
|
||||
const oneMonthLater = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);
|
||||
return {
|
||||
start: now,
|
||||
end: oneMonthLater,
|
||||
totalDays: 30,
|
||||
};
|
||||
}
|
||||
|
||||
tasks.forEach((task) => {
|
||||
let earliest = firstTask.startDate;
|
||||
let latest = firstTask.endDate;
|
||||
|
||||
tasks.forEach((task): void => {
|
||||
if (task.startDate < earliest) {
|
||||
earliest = task.startDate;
|
||||
}
|
||||
@@ -82,8 +94,8 @@ function calculateBarPosition(
|
||||
const widthPercent = (taskDuration / totalDays) * 100;
|
||||
|
||||
const result: GanttBarPosition = {
|
||||
left: `${leftPercent}%`,
|
||||
width: `${widthPercent}%`,
|
||||
left: `${String(leftPercent)}%`,
|
||||
width: `${String(widthPercent)}%`,
|
||||
top: rowIndex * 48, // 48px row height
|
||||
};
|
||||
|
||||
@@ -114,11 +126,11 @@ function getStatusClass(status: TaskStatus): string {
|
||||
function getRowStatusClass(status: TaskStatus): string {
|
||||
switch (status) {
|
||||
case TaskStatus.COMPLETED:
|
||||
return styles.rowCompleted || "";
|
||||
return styles.rowCompleted ?? "";
|
||||
case TaskStatus.IN_PROGRESS:
|
||||
return styles.rowInProgress || "";
|
||||
return styles.rowInProgress ?? "";
|
||||
case TaskStatus.PAUSED:
|
||||
return styles.rowPaused || "";
|
||||
return styles.rowPaused ?? "";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
@@ -172,13 +184,16 @@ function calculateDependencyLines(
|
||||
return;
|
||||
}
|
||||
|
||||
task.dependencies.forEach((depId) => {
|
||||
task.dependencies.forEach((depId): void => {
|
||||
const fromIndex = taskIndexMap.get(depId);
|
||||
if (fromIndex === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fromTask = tasks[fromIndex]!;
|
||||
const fromTask = tasks[fromIndex];
|
||||
if (!fromTask) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate positions (as percentages)
|
||||
const fromEndOffset = Math.max(
|
||||
|
||||
@@ -201,8 +201,8 @@ describe("Gantt Types Helpers", (): void => {
|
||||
const ganttTasks = toGanttTasks(tasks);
|
||||
|
||||
expect(ganttTasks).toHaveLength(2);
|
||||
expect(ganttTasks[0]!.id).toBe("task-1");
|
||||
expect(ganttTasks[1]!.id).toBe("task-2");
|
||||
expect(ganttTasks[0]?.id).toBe("task-1");
|
||||
expect(ganttTasks[1]?.id).toBe("task-2");
|
||||
});
|
||||
|
||||
it("should filter out tasks that cannot be converted", (): void => {
|
||||
@@ -240,9 +240,9 @@ describe("Gantt Types Helpers", (): void => {
|
||||
|
||||
const ganttTasks = toGanttTasks(tasks);
|
||||
|
||||
expect(ganttTasks[0]!.id).toBe("first");
|
||||
expect(ganttTasks[1]!.id).toBe("second");
|
||||
expect(ganttTasks[2]!.id).toBe("third");
|
||||
expect(ganttTasks[0]?.id).toBe("first");
|
||||
expect(ganttTasks[1]?.id).toBe("second");
|
||||
expect(ganttTasks[2]?.id).toBe("third");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -78,25 +78,20 @@ function isStringArray(value: unknown): value is string[] {
|
||||
*/
|
||||
export function toGanttTask(task: Task): GanttTask | null {
|
||||
// For Gantt chart, we need both start and end dates
|
||||
const metadataStartDate = task.metadata?.startDate;
|
||||
const metadataStartDate = task.metadata.startDate;
|
||||
const startDate = isDateString(metadataStartDate) ? new Date(metadataStartDate) : task.createdAt;
|
||||
|
||||
const endDate = task.dueDate ?? new Date();
|
||||
|
||||
// Validate dates
|
||||
if (!startDate || !endDate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract dependencies with type guard
|
||||
const metadataDependencies = task.metadata?.dependencies;
|
||||
const metadataDependencies = task.metadata.dependencies;
|
||||
const dependencies = isStringArray(metadataDependencies) ? metadataDependencies : undefined;
|
||||
|
||||
const ganttTask: GanttTask = {
|
||||
...task,
|
||||
startDate,
|
||||
endDate,
|
||||
isMilestone: task.metadata?.isMilestone === true,
|
||||
isMilestone: task.metadata.isMilestone === true,
|
||||
};
|
||||
|
||||
if (dependencies) {
|
||||
|
||||
Reference in New Issue
Block a user