import { FC, useState } from "react"; import isEmpty from "lodash/isEmpty"; import Link from "next/link"; import { useForm } from "react-hook-form"; // types import { IFormattedInstanceConfiguration, TInstanceGithubAuthenticationConfigurationKeys } from "@plane/types"; // ui import { Button, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui"; // components import { ConfirmDiscardModal, ControllerInput, CopyField, TControllerInputFormField, TCopyField, } from "@/components/common"; // helpers import { API_BASE_URL, cn } from "@/helpers/common.helper"; // hooks import { useInstance } from "@/hooks/store"; type Props = { config: IFormattedInstanceConfiguration; }; type GithubConfigFormValues = Record<TInstanceGithubAuthenticationConfigurationKeys, string>; export const InstanceGithubConfigForm: FC<Props> = (props) => { const { config } = props; // states const [isDiscardChangesModalOpen, setIsDiscardChangesModalOpen] = useState(false); // store hooks const { updateInstanceConfigurations } = useInstance(); // form data const { handleSubmit, control, reset, formState: { errors, isDirty, isSubmitting }, } = useForm<GithubConfigFormValues>({ defaultValues: { GITHUB_CLIENT_ID: config["GITHUB_CLIENT_ID"], GITHUB_CLIENT_SECRET: config["GITHUB_CLIENT_SECRET"], }, }); const originURL = !isEmpty(API_BASE_URL) ? API_BASE_URL : typeof window !== "undefined" ? window.location.origin : ""; const GITHUB_FORM_FIELDS: TControllerInputFormField[] = [ { key: "GITHUB_CLIENT_ID", type: "text", label: "Client ID", description: ( <> You will get this from your{" "} <a tabIndex={-1} href="https://github.com/settings/applications/new" target="_blank" className="text-custom-primary-100 hover:underline" rel="noreferrer" > GitHub OAuth application settings. </a> </> ), placeholder: "70a44354520df8bd9bcd", error: Boolean(errors.GITHUB_CLIENT_ID), required: true, }, { key: "GITHUB_CLIENT_SECRET", type: "password", label: "Client secret", description: ( <> Your client secret is also found in your{" "} <a tabIndex={-1} href="https://github.com/settings/applications/new" target="_blank" className="text-custom-primary-100 hover:underline" rel="noreferrer" > GitHub OAuth application settings. </a> </> ), placeholder: "9b0050f94ec1b744e32ce79ea4ffacd40d4119cb", error: Boolean(errors.GITHUB_CLIENT_SECRET), required: true, }, ]; const GITHUB_SERVICE_FIELD: TCopyField[] = [ { key: "Origin_URL", label: "Origin URL", url: originURL, description: ( <> We will auto-generate this. Paste this into the Authorized origin URL field{" "} <a tabIndex={-1} href="https://github.com/settings/applications/new" target="_blank" className="text-custom-primary-100 hover:underline" rel="noreferrer" > here. </a> </> ), }, { key: "Callback_URI", label: "Callback URI", url: `${originURL}/auth/github/callback/`, description: ( <> We will auto-generate this. Paste this into your Authorized Callback URI field{" "} <a tabIndex={-1} href="https://github.com/settings/applications/new" target="_blank" className="text-custom-primary-100 hover:underline" rel="noreferrer" > here. </a> </> ), }, ]; const onSubmit = async (formData: GithubConfigFormValues) => { const payload: Partial<GithubConfigFormValues> = { ...formData }; await updateInstanceConfigurations(payload) .then((response = []) => { setToast({ type: TOAST_TYPE.SUCCESS, title: "Success", message: "Github Configuration Settings updated successfully", }); reset({ GITHUB_CLIENT_ID: response.find((item) => item.key === "GITHUB_CLIENT_ID")?.value, GITHUB_CLIENT_SECRET: response.find((item) => item.key === "GITHUB_CLIENT_SECRET")?.value, }); }) .catch((err) => console.error(err)); }; const handleGoBack = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => { if (isDirty) { e.preventDefault(); setIsDiscardChangesModalOpen(true); } }; return ( <> <ConfirmDiscardModal isOpen={isDiscardChangesModalOpen} onDiscardHref="/authentication" handleClose={() => setIsDiscardChangesModalOpen(false)} /> <div className="flex flex-col gap-8"> <div className="grid grid-cols-2 gap-x-12 gap-y-8 w-full"> <div className="flex flex-col gap-y-4 col-span-2 md:col-span-1"> <div className="pt-2 text-xl font-medium">Configuration</div> {GITHUB_FORM_FIELDS.map((field) => ( <ControllerInput key={field.key} control={control} type={field.type} name={field.key} label={field.label} description={field.description} placeholder={field.placeholder} error={field.error} required={field.required} /> ))} <div className="flex flex-col gap-1 pt-4"> <div className="flex items-center gap-4"> <Button variant="primary" onClick={handleSubmit(onSubmit)} loading={isSubmitting} disabled={!isDirty}> {isSubmitting ? "Saving..." : "Save changes"} </Button> <Link href="/authentication" className={cn(getButtonStyling("link-neutral", "md"), "font-medium")} onClick={handleGoBack} > Go back </Link> </div> </div> </div> <div className="col-span-2 md:col-span-1"> <div className="flex flex-col gap-y-4 px-6 py-4 my-2 bg-custom-background-80/60 rounded-lg"> <div className="pt-2 text-xl font-medium">Service provider details</div> {GITHUB_SERVICE_FIELD.map((field) => ( <CopyField key={field.key} label={field.label} url={field.url} description={field.description} /> ))} </div> </div> </div> </div> </> ); };