forked from cerc-io/snowballtools-base
218 lines
5.7 KiB
TypeScript
218 lines
5.7 KiB
TypeScript
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
import { Controller, useForm, SubmitHandler } from 'react-hook-form';
|
|
import toast from 'react-hot-toast';
|
|
import { Domain } from 'gql-client';
|
|
|
|
import {
|
|
Button,
|
|
Dialog,
|
|
DialogHeader,
|
|
DialogBody,
|
|
DialogFooter,
|
|
Input,
|
|
Typography,
|
|
Select,
|
|
Option,
|
|
} from '@material-tailwind/react';
|
|
|
|
import { useGQLClient } from '../../../../context/GQLClientContext';
|
|
|
|
const DEFAULT_REDIRECT_OPTIONS = ['none'];
|
|
|
|
interface EditDomainDialogProp {
|
|
domains: Domain[];
|
|
open: boolean;
|
|
handleOpen: () => void;
|
|
domain: Domain;
|
|
branches: string[];
|
|
onUpdate: () => Promise<void>;
|
|
}
|
|
|
|
type EditDomainValues = {
|
|
name: string;
|
|
branch: string;
|
|
redirectedTo: string;
|
|
};
|
|
|
|
const EditDomainDialog = ({
|
|
domains,
|
|
open,
|
|
handleOpen,
|
|
domain,
|
|
branches,
|
|
onUpdate,
|
|
}: EditDomainDialogProp) => {
|
|
const client = useGQLClient();
|
|
|
|
const getRedirectUrl = (domain: Domain) => {
|
|
const redirectDomain = domain.redirectTo;
|
|
|
|
if (redirectDomain !== null) {
|
|
return redirectDomain?.name;
|
|
} else {
|
|
return 'none';
|
|
}
|
|
};
|
|
|
|
const redirectOptions = useMemo(() => {
|
|
const domainNames = domains
|
|
.filter((domainData) => domainData.id !== domain.id)
|
|
.map((domain) => domain.name);
|
|
return ['none', ...domainNames];
|
|
}, [domain, domains]);
|
|
|
|
const domainRedirectedFrom = useMemo(() => {
|
|
return domains.find(
|
|
(domainData) => domainData.redirectTo?.id === domain.id,
|
|
);
|
|
}, [domains, domain]);
|
|
|
|
const isDisableDropdown = useMemo(() => {
|
|
return domainRedirectedFrom !== undefined;
|
|
}, [domain, domains]);
|
|
|
|
const {
|
|
handleSubmit,
|
|
register,
|
|
control,
|
|
watch,
|
|
reset,
|
|
formState: { isValid, isDirty },
|
|
} = useForm({
|
|
defaultValues: {
|
|
name: domain.name,
|
|
branch: domain.branch,
|
|
redirectedTo: getRedirectUrl(domain),
|
|
},
|
|
});
|
|
|
|
const updateDomainHandler: SubmitHandler<EditDomainValues> = useCallback(
|
|
async (data) => {
|
|
const domainRedirectTo = domains.find(
|
|
(domainData) => data.redirectedTo === domainData.name,
|
|
);
|
|
|
|
const updates = {
|
|
name: data.name ? data.name : domain.name,
|
|
branch: data.branch ? data.branch : domain.branch,
|
|
redirectToId: domainRedirectTo ? domainRedirectTo.id : null,
|
|
};
|
|
|
|
const { updateDomain } = await client.updateDomain(domain.id, updates);
|
|
|
|
if (updateDomain) {
|
|
await onUpdate();
|
|
toast.success(`Domain ${domain.name} has been updated`);
|
|
} else {
|
|
reset();
|
|
toast.error(`Error updating domain ${domain.name}`);
|
|
}
|
|
|
|
handleOpen();
|
|
},
|
|
[client, domains, domain],
|
|
);
|
|
|
|
useEffect(() => {
|
|
reset({
|
|
name: domain.name,
|
|
branch: domain.branch,
|
|
redirectedTo: getRedirectUrl(domain),
|
|
});
|
|
}, [domain]);
|
|
|
|
return (
|
|
<Dialog open={open} handler={handleOpen} placeholder={''}>
|
|
<DialogHeader className="flex justify-between" placeholder={''}>
|
|
<div>Edit domain</div>
|
|
<Button
|
|
variant="outlined"
|
|
onClick={handleOpen}
|
|
className="mr-1 rounded-3xl"
|
|
placeholder={''}
|
|
>
|
|
X
|
|
</Button>
|
|
</DialogHeader>
|
|
<form onSubmit={handleSubmit(updateDomainHandler)}>
|
|
<DialogBody className="flex flex-col gap-2 p-4" placeholder={''}>
|
|
<Typography variant="small" placeholder={''}>
|
|
Domain name
|
|
</Typography>
|
|
<Input crossOrigin={undefined} {...register('name')} />
|
|
<Typography variant="small" placeholder={''}>
|
|
Redirect to
|
|
</Typography>
|
|
<Controller
|
|
name="redirectedTo"
|
|
control={control}
|
|
render={({ field }) => (
|
|
<Select {...field} disabled={isDisableDropdown} placeholder={''}>
|
|
{redirectOptions.map((option, key) => (
|
|
<Option key={key} value={option}>
|
|
^ {option}
|
|
</Option>
|
|
))}
|
|
</Select>
|
|
)}
|
|
/>
|
|
{isDisableDropdown && (
|
|
<div className="flex p-2 gap-2 text-black bg-gray-300 rounded-lg">
|
|
<div>^</div>
|
|
<Typography variant="small" placeholder={''}>
|
|
Domain “{domainRedirectedFrom ? domainRedirectedFrom.name : ''}”
|
|
redirects to this domain so you can not redirect this doman
|
|
further.
|
|
</Typography>
|
|
</div>
|
|
)}
|
|
<Typography variant="small" placeholder={''}>
|
|
Git branch
|
|
</Typography>
|
|
<Input
|
|
crossOrigin={undefined}
|
|
{...register('branch', {
|
|
validate: (value) =>
|
|
Boolean(branches.length) ? branches.includes(value) : true,
|
|
})}
|
|
disabled={
|
|
!Boolean(branches.length) ||
|
|
watch('redirectedTo') !== DEFAULT_REDIRECT_OPTIONS[0]
|
|
}
|
|
/>
|
|
{!isValid && (
|
|
<Typography
|
|
variant="small"
|
|
className="text-red-500"
|
|
placeholder={''}
|
|
>
|
|
We couldn't find this branch in the connected Git repository.
|
|
</Typography>
|
|
)}
|
|
</DialogBody>
|
|
<DialogFooter className="flex justify-start" placeholder={''}>
|
|
<Button
|
|
variant="outlined"
|
|
onClick={handleOpen}
|
|
className="mr-1"
|
|
placeholder={''}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
variant="gradient"
|
|
color="blue"
|
|
type="submit"
|
|
disabled={!isDirty}
|
|
placeholder={''}
|
|
>
|
|
Save changes
|
|
</Button>
|
|
</DialogFooter>
|
|
</form>
|
|
</Dialog>
|
|
);
|
|
};
|
|
|
|
export default EditDomainDialog;
|