Skip to content

Commit 7c03409

Browse files
committed
Rearrange the layout of the replay modal
1 parent 1a64013 commit 7c03409

File tree

1 file changed

+106
-75
lines changed

1 file changed

+106
-75
lines changed

apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx

Lines changed: 106 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { DialogClose } from "@radix-ui/react-dialog";
22
import { Form, useNavigation, useSubmit } from "@remix-run/react";
3-
import { useCallback, useEffect, useRef } from "react";
3+
import { useCallback, useEffect, useRef, useState } from "react";
44
import { type UseDataFunctionReturn, useTypedFetcher } from "remix-typedjson";
55
import { JSONEditor } from "~/components/code/JSONEditor";
66
import { EnvironmentCombo } from "~/components/environments/EnvironmentLabel";
@@ -12,6 +12,7 @@ import { Label } from "~/components/primitives/Label";
1212
import { Paragraph } from "~/components/primitives/Paragraph";
1313
import { Select, SelectItem } from "~/components/primitives/Select";
1414
import { Spinner, SpinnerWhite } from "~/components/primitives/Spinner";
15+
import { TabButton, TabContainer } from "~/components/primitives/Tabs";
1516
import { type loader } from "~/routes/resources.taskruns.$runParam.replay";
1617

1718
type ReplayRunDialogProps = {
@@ -21,7 +22,7 @@ type ReplayRunDialogProps = {
2122

2223
export function ReplayRunDialog({ runFriendlyId, failedRedirect }: ReplayRunDialogProps) {
2324
return (
24-
<DialogContent key={`replay`} className="md:max-w-xl">
25+
<DialogContent key={`replay`} className="h-full md:max-h-[85vh] md:max-w-3xl lg:max-w-5xl">
2526
<ReplayContent runFriendlyId={runFriendlyId} failedRedirect={failedRedirect} />
2627
</DialogContent>
2728
);
@@ -36,7 +37,7 @@ function ReplayContent({ runFriendlyId, failedRedirect }: ReplayRunDialogProps)
3637
}, [runFriendlyId]);
3738

3839
return (
39-
<>
40+
<div className="flex h-full flex-col">
4041
<DialogHeader>Replay this run</DialogHeader>
4142
{isLoading ? (
4243
<div className="grid place-items-center p-6">
@@ -51,7 +52,7 @@ function ReplayContent({ runFriendlyId, failedRedirect }: ReplayRunDialogProps)
5152
) : (
5253
<>Failed to get run data</>
5354
)}
54-
</>
55+
</div>
5556
);
5657
}
5758

@@ -93,82 +94,112 @@ function ReplayForm({
9394
[currentJson]
9495
);
9596

97+
const [tab, setTab] = useState<"payload" | "metadata">("payload");
98+
9699
return (
97-
<Form action={formAction} method="post" onSubmit={(e) => submitForm(e)} className="pt-2">
98-
{editablePayload ? (
99-
<>
100-
<Paragraph className="mb-3">
101-
Replaying will create a new run using the same or modified payload, executing against
102-
the latest version in your selected environment.
103-
</Paragraph>
104-
<Header3 spacing>Payload</Header3>
105-
<div className="mb-3 max-h-[70vh] min-h-40 overflow-y-auto rounded-sm border border-grid-dimmed bg-charcoal-900 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600">
106-
<JSONEditor
107-
autoFocus
108-
defaultValue={currentJson.current}
109-
readOnly={false}
110-
basicSetup
111-
onChange={(v) => {
112-
currentJson.current = v;
113-
}}
114-
showClearButton={false}
115-
showCopyButton={false}
116-
height="100%"
117-
min-height="100%"
118-
max-height="100%"
119-
/>
120-
</div>
121-
</>
122-
) : null}
123-
<InputGroup>
124-
<Label>Environment</Label>
125-
<Select
126-
id="environment"
127-
name="environment"
128-
placeholder="Select an environment"
129-
defaultValue={environment.id}
130-
items={environments}
131-
dropdownIcon
132-
variant="tertiary/medium"
133-
className="w-fit pl-1"
134-
filter={{
135-
keys: [
136-
(item) => item.type.replace(/\//g, " ").replace(/_/g, " "),
137-
(item) => item.branchName?.replace(/\//g, " ").replace(/_/g, " ") ?? "",
138-
],
139-
}}
140-
text={(value) => {
141-
const env = environments.find((env) => env.id === value)!;
142-
return (
143-
<div className="flex items-center pl-1 pr-2">
144-
<EnvironmentCombo environment={env} />
145-
</div>
146-
);
147-
}}
148-
>
149-
{(matches) =>
150-
matches.map((env) => (
151-
<SelectItem key={env.id} value={env.id}>
152-
<EnvironmentCombo environment={env} />
153-
</SelectItem>
154-
))
155-
}
156-
</Select>
157-
</InputGroup>
100+
<Form
101+
action={formAction}
102+
method="post"
103+
onSubmit={(e) => submitForm(e)}
104+
className="flex grow flex-col gap-3"
105+
>
158106
<input type="hidden" name="failedRedirect" value={failedRedirect} />
159-
<div className="mt-3 flex items-center justify-between gap-2 border-t border-grid-dimmed pt-3.5">
107+
108+
<Paragraph className="pt-6">
109+
Replaying will create a new run using the same or modified payload, executing against the
110+
latest version in your selected environment.
111+
</Paragraph>
112+
<div className="grow">
113+
<div className="mb-3 h-full min-h-40 overflow-y-auto rounded-sm border border-grid-dimmed bg-charcoal-900 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600">
114+
<JSONEditor
115+
autoFocus
116+
defaultValue={currentJson.current}
117+
readOnly={false}
118+
basicSetup
119+
onChange={(v) => {
120+
currentJson.current = v;
121+
}}
122+
height="100%"
123+
min-height="100%"
124+
max-height="100%"
125+
additionalActions={
126+
<TabContainer className="flex grow items-baseline justify-between self-end border-none">
127+
<div className="flex gap-5">
128+
<TabButton
129+
isActive={!tab || tab === "payload"}
130+
layoutId="replay-editor"
131+
onClick={() => {
132+
setTab("payload");
133+
}}
134+
>
135+
Payload
136+
</TabButton>
137+
<TabButton
138+
isActive={tab === "metadata"}
139+
layoutId="replay-editor"
140+
onClick={() => {
141+
setTab("metadata");
142+
}}
143+
>
144+
Metadata
145+
</TabButton>
146+
</div>
147+
</TabContainer>
148+
}
149+
/>
150+
</div>
151+
</div>
152+
153+
<div className="flex items-center justify-between gap-2 border-t border-grid-dimmed pt-3.5">
160154
<DialogClose asChild>
161155
<Button variant="tertiary/medium">Cancel</Button>
162156
</DialogClose>
163-
<Button
164-
type="submit"
165-
variant="primary/medium"
166-
LeadingIcon={isSubmitting ? SpinnerWhite : undefined}
167-
disabled={isSubmitting}
168-
shortcut={{ modifiers: ["mod"], key: "enter", enabledOnInputElements: true }}
169-
>
170-
{isSubmitting ? "Replaying..." : "Replay run"}
171-
</Button>
157+
<div className="flex items-center gap-3">
158+
<InputGroup className="flex flex-row items-center">
159+
<Label>Replay this run in</Label>
160+
<Select
161+
id="environment"
162+
name="environment"
163+
placeholder="Select an environment"
164+
defaultValue={environment.id}
165+
items={environments}
166+
dropdownIcon
167+
variant="tertiary/medium"
168+
className="w-fit pl-1"
169+
filter={{
170+
keys: [
171+
(item) => item.type.replace(/\//g, " ").replace(/_/g, " "),
172+
(item) => item.branchName?.replace(/\//g, " ").replace(/_/g, " ") ?? "",
173+
],
174+
}}
175+
text={(value) => {
176+
const env = environments.find((env) => env.id === value)!;
177+
return (
178+
<div className="flex items-center pl-1 pr-2">
179+
<EnvironmentCombo environment={env} />
180+
</div>
181+
);
182+
}}
183+
>
184+
{(matches) =>
185+
matches.map((env) => (
186+
<SelectItem key={env.id} value={env.id}>
187+
<EnvironmentCombo environment={env} />
188+
</SelectItem>
189+
))
190+
}
191+
</Select>
192+
</InputGroup>
193+
<Button
194+
type="submit"
195+
variant="primary/medium"
196+
LeadingIcon={isSubmitting ? SpinnerWhite : undefined}
197+
disabled={isSubmitting}
198+
shortcut={{ modifiers: ["mod"], key: "enter", enabledOnInputElements: true }}
199+
>
200+
{isSubmitting ? "Replaying..." : "Replay run"}
201+
</Button>
202+
</div>
172203
</div>
173204
</Form>
174205
);

0 commit comments

Comments
 (0)