Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
{
"files": ["apps/webapp/app/**/*.ts", "apps/webapp/app/**/*.tsx"],
"rules": {
"react/jsx-no-useless-fragment": "error",
Comment thread
carderne marked this conversation as resolved.
Comment thread
carderne marked this conversation as resolved.
"react/no-unstable-nested-components": "error",
"react/rules-of-hooks": "error",
"trigger-runops/no-control-plane-run-graph-access": "error",
Expand Down
26 changes: 10 additions & 16 deletions apps/webapp/app/components/ErrorDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,16 @@ export function RouteErrorDisplay(options?: ErrorDisplayOptions) {
);
}

return (
<>
{isRouteErrorResponse(error) ? (
<ErrorDisplay
title={friendlyErrorDisplay(error.status, error.statusText).title}
message={
error.data.message ?? friendlyErrorDisplay(error.status, error.statusText).message
}
{...options}
/>
) : error instanceof Error ? (
<ErrorDisplay title={error.name} message={error.message} {...options} />
) : (
<ErrorDisplay title="Oops" message={JSON.stringify(error)} {...options} />
)}
</>
return isRouteErrorResponse(error) ? (
<ErrorDisplay
title={friendlyErrorDisplay(error.status, error.statusText).title}
message={error.data.message ?? friendlyErrorDisplay(error.status, error.statusText).message}
{...options}
/>
) : error instanceof Error ? (
<ErrorDisplay title={error.name} message={error.message} {...options} />
) : (
<ErrorDisplay title="Oops" message={JSON.stringify(error)} {...options} />
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function AskAgentButton({
fallback?: React.ReactNode;
}) {
const available = useDashboardAgentAvailable();
if (!available) return <>{fallback}</>;
if (!available) return fallback;

const button = (
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ export function WhenAgentUnavailable({ children }: { children: React.ReactNode }
return null;
}

return <>{children}</>;
return children;
}
2 changes: 1 addition & 1 deletion apps/webapp/app/components/primitives/Buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ export function ButtonContent(props: ButtonContentPropsType) {
{text}
</span>
) : (
<>{text}</>
text
))}

{shortcut &&
Expand Down
34 changes: 16 additions & 18 deletions apps/webapp/app/components/primitives/SegmentedControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,25 +129,23 @@ export default function SegmentedControl({
}
>
{({ checked }) => (
<>
<div
className={cn(
"relative flex h-full w-full items-center justify-between",
variantStyle.option
)}
>
<div className="z-10 flex h-full w-full items-center justify-center">
<RadioGroup.Label as="p">{option.label}</RadioGroup.Label>
</div>
{checked && (
<motion.div
layoutId={`segmented-control-${name}`}
transition={{ duration: 0.4, type: "spring" }}
className={variantStyle.selected}
/>
)}
<div
className={cn(
"relative flex h-full w-full items-center justify-between",
variantStyle.option
)}
>
<div className="z-10 flex h-full w-full items-center justify-center">
<RadioGroup.Label as="p">{option.label}</RadioGroup.Label>
</div>
</>
{checked && (
<motion.div
layoutId={`segmented-control-${name}`}
transition={{ duration: 0.4, type: "spring" }}
className={variantStyle.selected}
/>
)}
</div>
)}
</RadioGroup.Option>
))}
Expand Down
20 changes: 9 additions & 11 deletions apps/webapp/app/components/primitives/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ export function Select<TValue extends string | string[], TItem>({
{...props}
/>
<SelectPopover className={popoverClassName}>
{!searchable && showHeading && heading && <SelectHeading render={<>{heading}</>} />}
{!searchable && showHeading && heading && <SelectHeading render={<span>{heading}</span>} />}
Comment thread
carderne marked this conversation as resolved.
{searchable && <ComboBox placeholder={heading} shortcut={shortcut} value={searchValue} />}

<SelectList>
Expand Down Expand Up @@ -313,22 +313,20 @@ export function SelectTrigger({
content = children;
} else if (text !== undefined) {
if (typeof text === "function") {
content = <SelectValue>{(value) => <>{text(value) ?? placeholder}</>}</SelectValue>;
content = <SelectValue>{(value) => text(value) ?? placeholder}</SelectValue>;
} else {
content = text;
}
} else {
content = (
<SelectValue>
{(value) => (
<>
{typeof value === "string"
? (value ?? placeholder)
: value.length === 0
? placeholder
: value.join(", ")}
</>
)}
{(value) =>
typeof value === "string"
? (value ?? placeholder)
: value.length === 0
? placeholder
: value.join(", ")
}
</SelectValue>
);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/webapp/app/components/primitives/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ export const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>(
{trailingContent}
</div>
) : (
<>{children}</>
children
)}
</td>
);
Expand Down
62 changes: 30 additions & 32 deletions apps/webapp/app/components/primitives/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,38 +258,36 @@ export function TabButton({
ref={ref}
{...props}
>
<>
<div className={cn("flex items-center gap-1", title && "flex-1")}>
<span
className={cn(
"transition duration-200",
title
? cn(
headerVariants.header2.text,
isActive ? "text-text-bright" : "text-text-dimmed group-hover:text-text-bright"
)
: "text-sm text-text-bright"
)}
>
{props.children}
</span>
{shortcut && <ShortcutKey className={cn("")} shortcut={shortcut} variant={"small"} />}
</div>
{isActive ? (
<motion.div
layoutId={layoutId}
transition={{ type: "spring", stiffness: 500, damping: 30 }}
className={cn("h-0.5 w-full bg-indigo-500", !title && "mt-1")}
/>
) : (
<div
className={cn(
"h-0.5 w-full bg-surface-control-active opacity-0 transition duration-200 group-hover:opacity-100",
!title && "mt-1"
)}
/>
)}
</>
<div className={cn("flex items-center gap-1", title && "flex-1")}>
<span
className={cn(
"transition duration-200",
title
? cn(
headerVariants.header2.text,
isActive ? "text-text-bright" : "text-text-dimmed group-hover:text-text-bright"
)
: "text-sm text-text-bright"
)}
>
{props.children}
</span>
{shortcut && <ShortcutKey className={cn("")} shortcut={shortcut} variant={"small"} />}
</div>
{isActive ? (
<motion.div
layoutId={layoutId}
transition={{ type: "spring", stiffness: 500, damping: 30 }}
className={cn("h-0.5 w-full bg-indigo-500", !title && "mt-1")}
/>
) : (
<div
className={cn(
"h-0.5 w-full bg-surface-control-active opacity-0 transition duration-200 group-hover:opacity-100",
!title && "mt-1"
)}
/>
)}
</button>
);
}
6 changes: 1 addition & 5 deletions apps/webapp/app/components/runs/v3/TaskRunsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,7 @@ export function TaskRunsTable({
>
Duration
</TableHeaderCell>
{showCompute && (
<>
<TableHeaderCell>Compute</TableHeaderCell>
</>
)}
{showCompute && <TableHeaderCell>Compute</TableHeaderCell>}
<TableHeaderCell className="pl-4" tooltip={<MachineTooltipInfo />}>
Machine
</TableHeaderCell>
Expand Down
106 changes: 51 additions & 55 deletions apps/webapp/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,27 +146,25 @@ export const shouldRevalidate: ShouldRevalidateFunction = (options) => {

export function ErrorBoundary() {
return (
<>
<html lang="en" className="h-full" data-theme="classic">
<head>
<meta charSet="utf-8" />

<StaleAssetRecovery isProduction={isProduction} />
<Meta />
<Links />
</head>
<body className="h-full overflow-hidden bg-background-dimmed antialiased">
<ShortcutsProvider>
<AppContainer>
<MainCenteredContainer>
<RouteErrorDisplay />
</MainCenteredContainer>
</AppContainer>
</ShortcutsProvider>
<Scripts />
</body>
</html>
</>
<html lang="en" className="h-full" data-theme="classic">
<head>
<meta charSet="utf-8" />

<StaleAssetRecovery isProduction={isProduction} />
<Meta />
<Links />
</head>
<body className="h-full overflow-hidden bg-background-dimmed antialiased">
<ShortcutsProvider>
<AppContainer>
<MainCenteredContainer>
<RouteErrorDisplay />
</MainCenteredContainer>
</AppContainer>
</ShortcutsProvider>
<Scripts />
</body>
</html>
);
}

Expand All @@ -180,39 +178,37 @@ export default function App() {
const resolvedTheme = themePreference === "system" ? "dark" : themePreference;

return (
<>
<html
lang="en"
className="h-full"
// The pre-paint script below may flip data-theme before hydration
suppressHydrationWarning
data-theme={resolvedTheme}
data-theme-preference={themePreference}
// Contrast overlay input for the System themes; Classic never reads it
style={{ "--theme-contrast": themeContrast / 100 } as CSSProperties}
>
<head>
<script
dangerouslySetInnerHTML={{
__html: `try{if(document.documentElement.getAttribute("data-theme-preference")==="system"){document.documentElement.setAttribute("data-theme",matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")}}catch(e){}`,
}}
/>
<StaleAssetRecovery isProduction={isProduction} />
<Meta />
<Links />
</head>
<body className="h-full overflow-hidden bg-background-dimmed antialiased">
<ShortcutsProvider>
<TimezoneSetter />
<GlobalShortcuts />
<Outlet />
<Toast />
</ShortcutsProvider>
<ScrollRestoration />
<ExternalScripts />
<Scripts />
</body>
</html>
</>
<html
lang="en"
className="h-full"
// The pre-paint script below may flip data-theme before hydration
suppressHydrationWarning
data-theme={resolvedTheme}
data-theme-preference={themePreference}
// Contrast overlay input for the System themes; Classic never reads it
style={{ "--theme-contrast": themeContrast / 100 } as CSSProperties}
>
<head>
<script
dangerouslySetInnerHTML={{
__html: `try{if(document.documentElement.getAttribute("data-theme-preference")==="system"){document.documentElement.setAttribute("data-theme",matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")}}catch(e){}`,
}}
/>
<StaleAssetRecovery isProduction={isProduction} />
<Meta />
<Links />
</head>
<body className="h-full overflow-hidden bg-background-dimmed antialiased">
<ShortcutsProvider>
<TimezoneSetter />
<GlobalShortcuts />
<Outlet />
<Toast />
</ShortcutsProvider>
<ScrollRestoration />
<ExternalScripts />
<Scripts />
</body>
</html>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ function RunningCell({ state }: { state: UnifiedRunningState | undefined }) {
if (!state) {
return <span className="text-text-dimmed">–</span>;
}
return <>{state.running ?? 0}</>;
return state.running ?? 0;
}

function TaskTypeFilter() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,15 +352,13 @@ export default function Page() {
}
text={(value) => renderSlackChannel(slack.channels, value)}
>
{(matches) => (
<>
{matches?.map((channel) => (
<SelectItem key={channel.id} value={`${channel.id}/${channel.name}`}>
<SlackChannelTitle {...channel} />
</SelectItem>
))}
</>
)}
{(matches) =>
matches?.map((channel) => (
<SelectItem key={channel.id} value={`${channel.id}/${channel.name}`}>
<SlackChannelTitle {...channel} />
</SelectItem>
))
}
</Select>
{selectedSlackChannel && selectedSlackChannel.is_private && (
<Callout
Expand Down
Loading
Loading