chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import { getFormProps, getInputProps, useForm } from "@conform-to/react";
|
||||
import { parseWithZod } from "@conform-to/zod";
|
||||
import { DialogClose } from "@radix-ui/react-dialog";
|
||||
import { Form, useActionData, useLocation } from "@remix-run/react";
|
||||
import { type ActionFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { z } from "zod";
|
||||
import { ArchiveIcon } from "~/assets/icons/ArchiveIcon";
|
||||
import { Button } from "~/components/primitives/Buttons";
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from "~/components/primitives/Dialog";
|
||||
import { FormButtons } from "~/components/primitives/FormButtons";
|
||||
import { FormError } from "~/components/primitives/FormError";
|
||||
import { Paragraph } from "~/components/primitives/Paragraph";
|
||||
import { redirectWithErrorMessage, redirectWithSuccessMessage } from "~/models/message.server";
|
||||
import { ArchiveBranchService } from "~/services/archiveBranch.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
import { branchesDevPath, branchesPath } from "~/utils/pathBuilder";
|
||||
|
||||
const ArchiveBranchOptions = z.object({
|
||||
environmentId: z.string(),
|
||||
});
|
||||
|
||||
const schema = ArchiveBranchOptions.and(
|
||||
z.object({
|
||||
redirectPath: z.string(),
|
||||
})
|
||||
);
|
||||
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
const userId = await requireUserId(request);
|
||||
|
||||
const formData = await request.formData();
|
||||
const submission = parseWithZod(formData, { schema });
|
||||
|
||||
if (submission.status !== "success") {
|
||||
return redirectWithErrorMessage("/", request, "Invalid form data");
|
||||
}
|
||||
|
||||
const archiveBranchService = new ArchiveBranchService();
|
||||
|
||||
const result = await archiveBranchService.call(
|
||||
{ type: "userMembership", userId },
|
||||
{
|
||||
environmentId: submission.value.environmentId,
|
||||
}
|
||||
);
|
||||
|
||||
if (result.success) {
|
||||
return redirectWithSuccessMessage(
|
||||
result.branch.type === "DEVELOPMENT"
|
||||
? branchesDevPath(result.organization, result.project, result.branch)
|
||||
: branchesPath(result.organization, result.project, result.branch),
|
||||
request,
|
||||
`Branch "${result.branch.branchName}" archived`
|
||||
);
|
||||
}
|
||||
|
||||
return redirectWithErrorMessage(submission.value.redirectPath, request, result.error);
|
||||
}
|
||||
|
||||
export function ArchiveButton({
|
||||
environment,
|
||||
disabled,
|
||||
}: {
|
||||
environment: { id: string; branchName: string };
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
const lastSubmission = useActionData<typeof action>();
|
||||
const location = useLocation();
|
||||
|
||||
const [form, { environmentId, redirectPath }] = useForm({
|
||||
id: "archive-branch",
|
||||
lastResult: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
return parseWithZod(formData, { schema });
|
||||
},
|
||||
shouldRevalidate: "onInput",
|
||||
});
|
||||
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
variant="small-menu-item"
|
||||
LeadingIcon={ArchiveIcon}
|
||||
leadingIconClassName="text-error"
|
||||
fullWidth
|
||||
textAlignLeft
|
||||
className="w-full px-1.5 py-[0.9rem]"
|
||||
disabled={disabled}
|
||||
>
|
||||
Archive branch
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>Archive "{environment.branchName}"</DialogHeader>
|
||||
<div className="mt-2 flex flex-col gap-4">
|
||||
<Form
|
||||
method="post"
|
||||
action="/resources/branches/archive"
|
||||
{...getFormProps(form)}
|
||||
className="w-full"
|
||||
>
|
||||
<input value={environment.id} {...getInputProps(environmentId, { type: "hidden" })} />
|
||||
<input
|
||||
value={`${location.pathname}${location.search}`}
|
||||
{...getInputProps(redirectPath, { type: "hidden" })}
|
||||
/>
|
||||
<Paragraph spacing>
|
||||
This will <span className="text-text-bright">permanently</span> make this branch{" "}
|
||||
<span className="text-text-bright">read-only</span>. You won't be able to trigger
|
||||
runs, execute runs, or use the API for this branch.
|
||||
</Paragraph>
|
||||
<Paragraph spacing>
|
||||
You will still be able to view the branch and its associated runs.
|
||||
</Paragraph>
|
||||
<Paragraph spacing>
|
||||
Once archived you can create a new branch with the same name.
|
||||
</Paragraph>
|
||||
<FormError>{form.errors}</FormError>
|
||||
<FormButtons
|
||||
confirmButton={
|
||||
<Button LeadingIcon={ArchiveIcon} type="submit" variant="danger/medium">
|
||||
Archive branch
|
||||
</Button>
|
||||
}
|
||||
cancelButton={
|
||||
<DialogClose asChild>
|
||||
<Button variant="secondary/medium">Cancel</Button>
|
||||
</DialogClose>
|
||||
}
|
||||
/>
|
||||
</Form>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user