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/no-unstable-nested-components": "error",
Comment thread
carderne marked this conversation as resolved.
"react/rules-of-hooks": "error",
"trigger-runops/no-control-plane-run-graph-access": "error",
"trigger-runops/no-control-plane-in-runops-slot": "error"
Expand Down
24 changes: 16 additions & 8 deletions apps/webapp/app/components/code/TSQLResultsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ const DebouncedInput = forwardRef<
interface ColumnMeta {
outputColumn: OutputColumnMetadata;
alignment: "left" | "right";
prettyFormatting: boolean;
}

/**
Expand Down Expand Up @@ -489,6 +490,19 @@ function CellValueWrapper({
/**
* Render a cell value based on its type and optional customRenderType
*/
function TSQLResultsCell(info: CellContext<RowData, unknown>) {
const meta = info.column.columnDef.meta as ColumnMeta;

return (
<CellValueWrapper
value={info.getValue()}
column={meta.outputColumn}
prettyFormatting={meta.prettyFormatting}
row={info.row.original}
/>
);
}
Comment thread
carderne marked this conversation as resolved.

function CellValue({
value,
column,
Expand Down Expand Up @@ -1053,17 +1067,11 @@ export const TSQLResultsTable = memo(function TSQLResultsTable({
id: col.name,
accessorKey: col.name,
header: () => col.name,
cell: (info: CellContext<RowData, unknown>) => (
<CellValueWrapper
value={info.getValue()}
column={col}
prettyFormatting={prettyFormatting}
row={info.row.original}
/>
),
cell: TSQLResultsCell,
meta: {
outputColumn: col,
alignment: isRightAlignedColumn(col) ? "right" : "left",
prettyFormatting,
} as ColumnMeta,
size: calculateColumnWidth(col.name, rows, col),
filterFn: fuzzyFilter,
Expand Down
23 changes: 14 additions & 9 deletions apps/webapp/app/components/errors/ConfigureErrorAlerts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@ export const ErrorAlertsFormSchema = z.object({
}, z.string().url().array()),
});

type SlackChannel = { id?: string; name?: string; is_private?: boolean };

function renderSlackChannel(channels: SlackChannel[], value: string) {
const channel = channels.find((channel) => value === `${channel.id}/${channel.name}`);
if (!channel) return;

return (
<span className="text-text-bright">
<SlackChannelTitle {...channel} />
</span>
);
}

type ConfigureErrorAlertsProps = ErrorAlertChannelData & {
connectToSlackHref?: string;
formAction: string;
Expand Down Expand Up @@ -196,15 +209,7 @@ export function ConfigureErrorAlerts({
filter={(channel, search) =>
channel.name?.toLowerCase().includes(search.toLowerCase()) ?? false
}
text={(value) => {
const channel = slack.channels.find((s) => value === `${s.id}/${s.name}`);
if (!channel) return;
return (
<span className="text-text-bright">
<SlackChannelTitle {...channel} />
</span>
);
}}
text={(value) => renderSlackChannel(slack.channels, value)}
>
{(matches) => (
<>
Expand Down
3 changes: 2 additions & 1 deletion apps/webapp/app/components/primitives/charts/ChartLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,8 @@ export function ChartLineRenderer({
// own dot on top where it's active.
activeDot={
gradientLine
? (props: ActiveDotProps) => (
? // oxlint-disable-next-line react/no-unstable-nested-components -- Recharts invokes this renderer with hover coordinates; an element would rely on cloneElement prop injection.
(props: ActiveDotProps) => (
<ThresholdActiveDot
{...props}
dataKey={key}
Expand Down
25 changes: 17 additions & 8 deletions apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,22 @@ function ReplayContent({ runFriendlyId, failedRedirect }: ReplayRunDialogProps)
const startingJson = "{\n\n}";
const machinePresets = Object.values(MachinePresetName.enum);

type ReplayEnvironment = UseDataFunctionReturn<typeof loader>["environments"][number];

function renderReplayEnvironment(
environments: ReplayEnvironment[],
value: string
): React.ReactNode {
const environment = environments.find((environment) => environment.id === value);
if (!environment) return;

return (
<div className="flex items-center pl-1 pr-2">
<EnvironmentCombo environment={environment} />
</div>
);
}

function ReplayForm({
failedRedirect,
runFriendlyId,
Expand Down Expand Up @@ -572,14 +588,7 @@ function ReplayForm({
(item) => item.branchName?.replace(/\//g, " ").replace(/_/g, " ") ?? "",
],
}}
text={(value) => {
const env = replayData.environments.find((env) => env.id === value)!;
return (
<div className="flex items-center pl-1 pr-2">
<EnvironmentCombo environment={env} />
</div>
);
}}
text={(value) => renderReplayEnvironment(replayData.environments, value)}
>
{(matches) =>
matches.map((env) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ import {
} from "~/v3/services/alerts/safeWebhookUrl.server";
import { pageMeta } from "~/utils/pageTitle";

type SlackChannel = { id?: string; name?: string; is_private?: boolean };

function renderSlackChannel(channels: SlackChannel[], value: string | string[]) {
if (typeof value !== "string") return;
const channel = channels.find((channel) => value === `${channel.id}/${channel.name}`);
return channel ? <SlackChannelTitle {...channel} /> : undefined;
}

export const meta = pageMeta("New alert");

const FormSchema = z
Expand Down Expand Up @@ -342,11 +350,7 @@ export default function Page() {
filter={(channel, search) =>
channel.name?.toLowerCase().includes(search.toLowerCase()) ?? false
}
text={(value) => {
const channel = slack.channels.find((s) => value === `${s.id}/${s.name}`);
if (!channel) return;
return <SlackChannelTitle {...channel} />;
}}
text={(value) => renderSlackChannel(slack.channels, value)}
>
{(matches) => (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@ import { Form, useFetcher, useRevalidator } from "@remix-run/react";
import { type LoaderFunctionArgs } from "@remix-run/server-runtime";
import { ErrorId } from "@trigger.dev/core/v3/isomorphic";
import { type ErrorGroupStatus } from "@trigger.dev/database";
import { Suspense, useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
import {
Suspense,
useCallback,
useEffect,
useMemo,
useRef,
useState,
type ComponentProps,
type ReactNode,
} from "react";
import {
Bar,
BarChart,
Expand Down Expand Up @@ -628,6 +637,17 @@ function ErrorGroupRow({
);
}

function renderErrorActionsPopoverContent(props: ComponentProps<typeof ErrorStatusMenuItems>) {
return (
<>
<PopoverSectionHeader title="Mark error as…" />
<div className="flex flex-col gap-1 p-1">
<ErrorStatusMenuItems {...props} />
</div>
</>
);
}

function ErrorActionsCell({
errorGroup,
organizationSlug,
Expand Down Expand Up @@ -664,26 +684,21 @@ function ErrorActionsCell({
<>
<TableCellMenu
isSticky
popoverContent={(close) => (
<>
<PopoverSectionHeader title="Mark error as…" />
<div className="flex flex-col gap-1 p-1">
<ErrorStatusMenuItems
status={errorGroup.status}
taskIdentifier={errorGroup.taskIdentifier}
onAction={(data) => {
close();
pendingToast.current = statusActionToastMessage(data);
fetcher.submit(data, { method: "post", action: actionUrl });
}}
onCustomIgnore={() => {
close();
setCustomIgnoreOpen(true);
}}
/>
</div>
</>
)}
popoverContent={(close) =>
renderErrorActionsPopoverContent({
status: errorGroup.status,
taskIdentifier: errorGroup.taskIdentifier,
onAction: (data) => {
close();
pendingToast.current = statusActionToastMessage(data);
fetcher.submit(data, { method: "post", action: actionUrl });
},
onCustomIgnore: () => {
close();
setCustomIgnoreOpen(true);
},
})
}
/>
<CustomIgnoreDialog
open={customIgnoreOpen}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ function shuffleArray<T>(arr: T[]): T[] {
return shuffled;
}

function renderMultiSelectValue(value: string[]) {
if (value.length === 0) return;

return (
<span className="flex min-w-0 items-center text-text-bright">
<span className="truncate">{value.slice(0, 2).join(", ")}</span>
{value.length > 2 && <span className="ml-1 flex-none">+{value.length - 2} more</span>}
</span>
);
}

function MultiSelectField({
value,
setValue,
Expand All @@ -97,14 +108,7 @@ function MultiSelectField({
icon={icon}
items={items}
className="h-8 min-w-0 border-0 bg-background-hover pl-2 text-sm text-text-dimmed ring-border-bright transition hover:bg-secondary hover:text-text-dimmed hover:ring-1"
text={(v) =>
v.length === 0 ? undefined : (
<span className="flex min-w-0 items-center text-text-bright">
<span className="truncate">{v.slice(0, 2).join(", ")}</span>
{v.length > 2 && <span className="ml-1 flex-none">+{v.length - 2} more</span>}
</span>
)
}
text={renderMultiSelectValue}
>
{(items) =>
items.map((item) => (
Expand Down
16 changes: 10 additions & 6 deletions apps/webapp/app/routes/account._index/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ function themeIcon(value: ThemePreference) {
}
}

function renderTheme(value: ThemePreference) {
return (
<span className="flex items-center gap-1.5">
{themeIcon(value)}
{themeLabel(value)}
</span>
);
}

export const meta = pageMeta("Your profile");

function createSchema(
Expand Down Expand Up @@ -320,12 +329,7 @@ export default function Page() {
variant="secondary/small"
dropdownIcon
items={["classic", "system", "dark", "light"]}
text={(value) => (
<span className="flex items-center gap-1.5">
{themeIcon(value)}
{themeLabel(value)}
</span>
)}
text={renderTheme}
className="w-44"
>
{(items) =>
Expand Down
6 changes: 5 additions & 1 deletion apps/webapp/app/routes/confirm-basic-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ const HandIcon = forwardRef<HTMLDivElement, {}>(({}, ref) => {
});
const MotionHand = motion(HandIcon);

function renderRole(value: string) {
return value ? <span className="text-text-bright">{value}</span> : undefined;
}

export default function Page() {
const user = useUser();
const lastSubmission = useActionData();
Expand Down Expand Up @@ -390,7 +394,7 @@ export default function Page() {
icon={<UserGroupIcon className="mr-1 size-4.5 text-text-dimmed" />}
items={shuffledRoles}
className="h-8 min-w-0 border-0 bg-background-hover pl-2 text-sm text-text-dimmed ring-border-bright transition hover:bg-secondary hover:text-text-dimmed hover:ring-1"
text={(v) => (v ? <span className="text-text-bright">{v}</span> : undefined)}
text={renderRole}
>
{(items) =>
items.map((item) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,14 @@ function VercelAppInstalledRow() {
);
}

function VercelLeadingIcon() {
return <VercelLogo className="-mx-1 size-3.5 text-text-bright" />;
}

function VercelLoadingIcon() {
return <Spinner color="blue" className="size-4" />;
}

function VercelSettingsRows({
organizationSlug,
projectSlug,
Expand Down Expand Up @@ -577,7 +585,7 @@ function VercelSettingsRows({
noPermissionTooltip={noPermissionTooltip}
to={vercelAppInstallPath(organizationSlug, projectSlug)}
variant="secondary/small"
LeadingIcon={() => <VercelLogo className="-mx-1 size-3.5 text-text-bright" />}
LeadingIcon={VercelLeadingIcon}
>
Install Vercel app
</PermissionLink>
Expand All @@ -595,11 +603,7 @@ function VercelSettingsRows({
onClick={() => onOpenModal?.()}
disabled={isLoadingProjects || !onOpenModal || !canManageVercel}
tooltip={canManageVercel ? undefined : noPermissionTooltip}
LeadingIcon={
isLoadingProjects
? () => <Spinner color="blue" className="size-4" />
: () => <VercelLogo className="-mx-1 size-3.5 text-text-bright" />
}
LeadingIcon={isLoadingProjects ? VercelLoadingIcon : VercelLeadingIcon}
>
{isLoadingProjects ? "Loading projects…" : "Connect Vercel project"}
</Button>
Expand Down
Loading
Loading