138 lines
4.7 KiB
TypeScript
138 lines
4.7 KiB
TypeScript
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>
|
|
);
|
|
}
|