Skip to content

Commit aa2dc21

Browse files
Reenable most dashboard linters (#262)
1 parent 5a0a0fc commit aa2dc21

14 files changed

Lines changed: 115 additions & 132 deletions

File tree

eslint.config.js

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export default defineConfig(
3030
"prettier.config.js",
3131
"examples/workflow-discovery/openworkflow.config.js",
3232
"packages/dashboard/.output",
33+
"packages/dashboard/src/routeTree.gen.ts",
3334
],
3435
},
3536
{
@@ -136,52 +137,31 @@ export default defineConfig(
136137
},
137138
{
138139
files: ["packages/dashboard/**/*.{ts,tsx,js,jsx}"],
139-
// massive, but temporary, will need to come back and enable these a few at
140-
// a time
141140
rules: {
142-
"@cspell/spellchecker": "off",
143-
"@typescript-eslint/array-type": "off",
144-
"@typescript-eslint/consistent-type-definitions": "off",
145-
"@typescript-eslint/explicit-function-return-type": "off",
146-
"@typescript-eslint/no-confusing-void-expression": "off",
147-
"@typescript-eslint/no-deprecated": "off",
148-
"@typescript-eslint/no-explicit-any": "off",
149-
"@typescript-eslint/no-floating-promises": "off",
150-
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "off",
151-
"@typescript-eslint/no-unnecessary-condition": "off",
152-
"@typescript-eslint/no-unsafe-assignment": "off",
153-
"@typescript-eslint/no-unsafe-member-access": "off",
154-
"@typescript-eslint/no-unsafe-return": "off",
155-
"@typescript-eslint/no-unused-vars": "off",
156-
"@typescript-eslint/prefer-nullish-coalescing": "off",
157-
"@typescript-eslint/restrict-template-expressions": "off",
158-
"@typescript-eslint/unified-signatures": "off",
159-
"func-style": "off",
160-
"functional/prefer-property-signatures": "off",
161-
"import/no-cycle": "off",
162-
"import/no-extraneous-dependencies": "off",
163141
"import/no-relative-parent-imports": "off",
164-
"import/no-unresolved": "off",
165-
"import/no-useless-path-segments": "off",
166-
"import/order": "off",
167-
"jsdoc/check-indentation": "off",
168142
"jsdoc/require-jsdoc": "off",
169-
"jsdoc/require-throws": "off",
170-
"jsdoc/sort-tags": "off",
171-
"no-unused-vars": "off",
172-
"no-void": "off",
173-
"sonarjs/cognitive-complexity": "off",
174-
"sonarjs/deprecation": "off",
175-
"sonarjs/function-return-type": "off",
176-
"sonarjs/no-nested-conditional": "off",
177143
"sonarjs/prefer-read-only-props": "off",
178-
"sonarjs/pseudo-random": "off",
179-
"sonarjs/unused-import": "off",
144+
},
145+
},
146+
{
147+
files: [
148+
"packages/dashboard/**/*.test.ts",
149+
"packages/dashboard/**/*.test.tsx",
150+
],
151+
rules: {
152+
"import/no-extraneous-dependencies": [
153+
"error",
154+
{
155+
devDependencies: true,
156+
packageDir: [".", "packages/dashboard"],
157+
},
158+
],
159+
},
160+
},
161+
{
162+
files: ["packages/dashboard/src/routes/runs/$runId.tsx"],
163+
rules: {
180164
"unicorn/filename-case": "off",
181-
"unicorn/no-abusive-eslint-disable": "off",
182-
"unicorn/no-null": "off",
183-
"unicorn/prevent-abbreviations": "off",
184-
"unicorn/text-encoding-identifier-case": "off",
185165
},
186166
},
187167
);

packages/dashboard/src/components/mode-switcher.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import {
99
export function ModeSwitcher() {
1010
const { setTheme, theme } = useTheme();
1111

12-
const toggleTheme = () => {
12+
function toggleTheme() {
1313
setTheme(theme === "dark" ? "light" : "dark");
14-
};
14+
}
1515

1616
return (
1717
<Tooltip>

packages/dashboard/src/components/providers/theme-provider.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,28 @@ import { useRouter } from "@tanstack/react-router";
44
import type { PropsWithChildren } from "react";
55
import { createContext, use } from "react";
66

7-
type ThemeContextVal = { theme: Theme; setTheme: (val: Theme) => void };
7+
interface ThemeContextValue {
8+
theme: Theme;
9+
setTheme: (theme: Theme) => void;
10+
}
11+
812
type Props = PropsWithChildren<{ theme: Theme }>;
913

10-
const ThemeContext = createContext<ThemeContextVal | null>(null);
14+
const ThemeContext = createContext<ThemeContextValue | null>(null);
1115

1216
export function ThemeProvider({ children, theme }: Props) {
1317
const router = useRouter();
1418

15-
function setTheme(val: Theme) {
16-
setThemeServerFn({ data: val }).then(() => router.invalidate());
19+
function setTheme(theme: Theme) {
20+
void setThemeServerFn({ data: theme }).then(() => router.invalidate());
1721
}
1822

1923
return <ThemeContext value={{ theme, setTheme }}>{children}</ThemeContext>;
2024
}
2125

2226
export function useTheme() {
23-
const val = use(ThemeContext);
24-
if (!val) throw new Error("useTheme called outside of ThemeProvider!");
25-
return val;
27+
const themeContext = use(ThemeContext);
28+
if (!themeContext)
29+
throw new Error("useTheme called outside of ThemeProvider!");
30+
return themeContext;
2631
}

packages/dashboard/src/components/run-list.tsx

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Badge } from "@/components/ui/badge";
22
import { Card } from "@/components/ui/card";
33
import { STATUS_CONFIG } from "@/lib/status";
44
import { computeDuration, formatRelativeTime } from "@/utils";
5-
import { CaretRight } from "@phosphor-icons/react";
5+
import { CaretRightIcon } from "@phosphor-icons/react";
66
import { Link } from "@tanstack/react-router";
77
import type { WorkflowRun } from "openworkflow/internal";
88

@@ -78,20 +78,7 @@ export function RunList({ runs, title = "Workflow Runs" }: RunListProps) {
7878
<div className="text-muted-foreground flex items-center gap-4 text-xs">
7979
<Badge
8080
variant="outline"
81-
className={`border-border text-xs capitalize ${
82-
run.status === "completed" ||
83-
run.status === "succeeded"
84-
? "border-green-500/20 bg-green-500/10 text-green-500"
85-
: run.status === "running"
86-
? "border-blue-500/20 bg-blue-500/10 text-blue-500"
87-
: run.status === "failed"
88-
? "border-red-500/20 bg-red-500/10 text-red-500"
89-
: run.status === "sleeping"
90-
? "border-purple-500/20 bg-purple-500/10 text-purple-500"
91-
: run.status === "canceled"
92-
? "border-gray-500/20 bg-gray-500/10 text-gray-500"
93-
: "border-yellow-500/20 bg-yellow-500/10 text-yellow-500"
94-
}`}
81+
className={`text-xs capitalize ${config.badgeClass}`}
9582
>
9683
{config.label}
9784
</Badge>
@@ -111,7 +98,7 @@ export function RunList({ runs, title = "Workflow Runs" }: RunListProps) {
11198
</div>
11299
</div>
113100

114-
<CaretRight className="text-muted-foreground ml-4 size-5" />
101+
<CaretRightIcon className="text-muted-foreground ml-4 size-5" />
115102
</div>
116103
</Link>
117104
);

packages/dashboard/src/components/ui/field.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,9 @@ function FieldError({
176176
errors,
177177
...props
178178
}: React.ComponentProps<"div"> & {
179-
errors?: Array<{ message?: string } | undefined>;
179+
errors?: ({ message?: string } | undefined)[];
180180
}) {
181+
// eslint-disable-next-line sonarjs/function-return-type
181182
const content = useMemo(() => {
182183
if (children) {
183184
return children;
@@ -191,7 +192,7 @@ function FieldError({
191192
...new Map(errors.map((error) => [error?.message, error])).values(),
192193
];
193194

194-
if (uniqueErrors?.length == 1) {
195+
if (uniqueErrors.length == 1) {
195196
return uniqueErrors[0]?.message;
196197
}
197198

packages/dashboard/src/components/ui/slider.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ function Slider({
1212
}: SliderPrimitive.Root.Props) {
1313
const _values = React.useMemo(
1414
() =>
15+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
1516
Array.isArray(value)
1617
? value
17-
: Array.isArray(defaultValue)
18+
: // eslint-disable-next-line sonarjs/no-nested-conditional
19+
Array.isArray(defaultValue)
1820
? defaultValue
1921
: [min, max],
2022
[value, defaultValue, min, max],

packages/dashboard/src/components/workflow-stats.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Card } from "@/components/ui/card";
22
import {
3-
CheckCircle,
4-
Clock,
5-
Hourglass,
6-
Pulse,
7-
XCircle,
3+
CheckCircleIcon,
4+
ClockIcon,
5+
HourglassIcon,
6+
PulseIcon,
7+
XCircleIcon,
88
} from "@phosphor-icons/react";
99
import type { WorkflowRun } from "openworkflow/internal";
1010

@@ -28,22 +28,22 @@ export function WorkflowStats({ runs }: WorkflowStatsProps) {
2828
{
2929
label: "Total Runs",
3030
value: runs.length.toLocaleString(),
31-
icon: Pulse,
31+
icon: PulseIcon,
3232
},
3333
{
3434
label: "Completed",
3535
value: completed.toLocaleString(),
36-
icon: CheckCircle,
36+
icon: CheckCircleIcon,
3737
},
3838
{
3939
label: "Running",
4040
value: running.toLocaleString(),
41-
icon: Clock,
41+
icon: ClockIcon,
4242
},
4343
{
4444
label: "Failed",
4545
value: failed.toLocaleString(),
46-
icon: XCircle,
46+
icon: XCircleIcon,
4747
},
4848
];
4949

@@ -52,21 +52,21 @@ export function WorkflowStats({ runs }: WorkflowStatsProps) {
5252
additionalStats.push({
5353
label: "Sleeping",
5454
value: sleeping.toLocaleString(),
55-
icon: Hourglass,
55+
icon: HourglassIcon,
5656
});
5757
}
5858
if (pending > 0) {
5959
additionalStats.push({
6060
label: "Pending",
6161
value: pending.toLocaleString(),
62-
icon: Clock,
62+
icon: ClockIcon,
6363
});
6464
}
6565
if (canceled > 0) {
6666
additionalStats.push({
6767
label: "Canceled",
6868
value: canceled.toLocaleString(),
69-
icon: XCircle,
69+
icon: XCircleIcon,
7070
});
7171
}
7272

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {
2-
CheckCircle,
3-
CircleNotch,
4-
Clock,
5-
Hourglass,
6-
Prohibit,
7-
XCircle,
2+
CheckCircleIcon,
3+
CircleNotchIcon,
4+
ClockIcon,
5+
HourglassIcon,
6+
ProhibitIcon,
7+
XCircleIcon,
88
} from "@phosphor-icons/react";
99
import type {
1010
WorkflowRunStatus,
@@ -14,51 +14,51 @@ import type {
1414
export const STATUS_CONFIG: Record<
1515
WorkflowRunStatus,
1616
{
17-
icon: typeof CheckCircle;
17+
icon: typeof CheckCircleIcon;
1818
color: string;
1919
label: string;
2020
badgeClass: string;
2121
}
2222
> = {
2323
completed: {
24-
icon: CheckCircle,
24+
icon: CheckCircleIcon,
2525
color: "text-green-500",
2626
label: "Completed",
2727
badgeClass: "bg-green-500/10 text-green-500 border-green-500/20",
2828
},
2929
succeeded: {
30-
icon: CheckCircle,
30+
icon: CheckCircleIcon,
3131
color: "text-green-500",
3232
label: "Completed",
3333
badgeClass: "bg-green-500/10 text-green-500 border-green-500/20",
3434
},
3535
running: {
3636
// use the spinning notch for running states to match existing UI patterns
37-
icon: CircleNotch,
37+
icon: CircleNotchIcon,
3838
color: "text-blue-500",
3939
label: "Running",
4040
badgeClass: "bg-blue-500/10 text-blue-500 border-blue-500/20",
4141
},
4242
failed: {
43-
icon: XCircle,
43+
icon: XCircleIcon,
4444
color: "text-red-500",
4545
label: "Failed",
4646
badgeClass: "bg-red-500/10 text-red-500 border-red-500/20",
4747
},
4848
pending: {
49-
icon: Clock,
49+
icon: ClockIcon,
5050
color: "text-yellow-500",
5151
label: "Pending",
5252
badgeClass: "bg-yellow-500/10 text-yellow-500 border-yellow-500/20",
5353
},
5454
sleeping: {
55-
icon: Hourglass,
55+
icon: HourglassIcon,
5656
color: "text-purple-500",
5757
label: "Sleeping",
5858
badgeClass: "bg-purple-500/10 text-purple-500 border-purple-500/20",
5959
},
6060
canceled: {
61-
icon: Prohibit,
61+
icon: ProhibitIcon,
6262
color: "text-gray-500",
6363
label: "Canceled",
6464
badgeClass: "bg-gray-500/10 text-gray-500 border-gray-500/20",
@@ -67,7 +67,7 @@ export const STATUS_CONFIG: Record<
6767

6868
export const STEP_STATUS_CONFIG: Record<
6969
StepAttemptStatus,
70-
{ icon: typeof CheckCircle; color: string }
70+
{ icon: typeof CheckCircleIcon; color: string }
7171
> = {
7272
completed: {
7373
icon: STATUS_CONFIG.completed.icon,
@@ -87,15 +87,22 @@ export const STEP_STATUS_CONFIG: Record<
8787
},
8888
};
8989

90+
const fallbackStatusColor = "text-yellow-500";
91+
const fallbackStatusBadgeClass =
92+
"bg-yellow-500/10 text-yellow-500 border-yellow-500/20";
93+
94+
function getStatusConfig(status: string) {
95+
if (!(status in STATUS_CONFIG)) {
96+
return;
97+
}
98+
99+
return STATUS_CONFIG[status as WorkflowRunStatus];
100+
}
101+
90102
export function getStatusColor(status: string): string {
91-
return (
92-
(STATUS_CONFIG as Record<string, any>)[status]?.color ?? "text-yellow-500"
93-
);
103+
return getStatusConfig(status)?.color ?? fallbackStatusColor;
94104
}
95105

96106
export function getStatusBadgeClass(status: string): string {
97-
return (
98-
(STATUS_CONFIG as Record<string, any>)[status]?.badgeClass ??
99-
"bg-yellow-500/10 text-yellow-500 border-yellow-500/20"
100-
);
107+
return getStatusConfig(status)?.badgeClass ?? fallbackStatusBadgeClass;
101108
}

packages/dashboard/src/lib/theme.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ export type T = z.infer<typeof postThemeValidator>;
77
const storageKey = "_preferred-theme";
88

99
export const getThemeServerFn = createServerFn().handler(
10-
() => (getCookie(storageKey) || "light") as T,
10+
() => (getCookie(storageKey) ?? "light") as T,
1111
);
1212

1313
export const setThemeServerFn = createServerFn({ method: "POST" })
1414
.inputValidator(postThemeValidator)
15-
.handler(({ data }) => setCookie(storageKey, data));
15+
.handler(({ data }) => {
16+
setCookie(storageKey, data);
17+
});

0 commit comments

Comments
 (0)