mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
144 lines
4.6 KiB
TypeScript
144 lines
4.6 KiB
TypeScript
|
import { useForm } from "react-hook-form";
|
||
|
|
||
|
import { addDays, renderDateFormat } from "helpers/date-time.helper";
|
||
|
import { IApiToken } from "types/api_token";
|
||
|
import { csvDownload } from "helpers/download.helper";
|
||
|
import { useRouter } from "next/router";
|
||
|
import { Dispatch, SetStateAction, useState } from "react";
|
||
|
import useToast from "hooks/use-toast";
|
||
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||
|
import { ApiTokenService } from "services/api_token.service";
|
||
|
import { ApiTokenTitle } from "./ApiTokenTitle";
|
||
|
import { ApiTokenDescription } from "./ApiTokenDescription";
|
||
|
import { ApiTokenExpiry, expiryOptions } from "./ApiTokenExpiry";
|
||
|
import { Button } from "@plane/ui";
|
||
|
import { ApiTokenKeySection } from "./ApiTokenKeySection";
|
||
|
|
||
|
interface IApiTokenForm {
|
||
|
generatedToken: IApiToken | null | undefined;
|
||
|
setGeneratedToken: Dispatch<SetStateAction<IApiToken | null | undefined>>;
|
||
|
setDeleteTokenModal: Dispatch<SetStateAction<boolean>>;
|
||
|
}
|
||
|
|
||
|
const apiTokenService = new ApiTokenService();
|
||
|
export const ApiTokenForm = ({ generatedToken, setGeneratedToken, setDeleteTokenModal }: IApiTokenForm) => {
|
||
|
const [loading, setLoading] = useState<boolean>(false);
|
||
|
const [neverExpires, setNeverExpire] = useState<boolean>(false);
|
||
|
const [focusTitle, setFocusTitle] = useState<boolean>(false);
|
||
|
const [focusDescription, setFocusDescription] = useState<boolean>(false);
|
||
|
const [selectedExpiry, setSelectedExpiry] = useState<number>(1);
|
||
|
|
||
|
const { setToastAlert } = useToast();
|
||
|
const { theme: themStore } = useMobxStore();
|
||
|
|
||
|
const router = useRouter();
|
||
|
const { workspaceSlug } = router.query;
|
||
|
|
||
|
const {
|
||
|
control,
|
||
|
handleSubmit,
|
||
|
formState: { errors },
|
||
|
} = useForm({
|
||
|
defaultValues: {
|
||
|
never_expires: false,
|
||
|
title: "",
|
||
|
description: "",
|
||
|
},
|
||
|
});
|
||
|
|
||
|
const getExpiryDate = (): string | null => {
|
||
|
if (neverExpires === true) return null;
|
||
|
return addDays({ date: new Date(), days: expiryOptions[selectedExpiry].days }).toISOString();
|
||
|
};
|
||
|
|
||
|
function renderExpiry(): string {
|
||
|
return renderDateFormat(addDays({ date: new Date(), days: expiryOptions[selectedExpiry].days }), true);
|
||
|
}
|
||
|
|
||
|
const downloadSecretKey = (token: IApiToken) => {
|
||
|
const csvData = {
|
||
|
Label: token.label,
|
||
|
Description: token.description,
|
||
|
Expiry: renderDateFormat(token.expired_at ?? null),
|
||
|
"Secret Key": token.token,
|
||
|
};
|
||
|
csvDownload(csvData, `Secret-key-${Date.now()}`);
|
||
|
};
|
||
|
|
||
|
const generateToken = async (data: any) => {
|
||
|
if (!workspaceSlug) return;
|
||
|
setLoading(true);
|
||
|
await apiTokenService
|
||
|
.createApiToken(workspaceSlug.toString(), {
|
||
|
label: data.title,
|
||
|
description: data.description,
|
||
|
expired_at: getExpiryDate(),
|
||
|
})
|
||
|
.then((res) => {
|
||
|
setGeneratedToken(res);
|
||
|
downloadSecretKey(res);
|
||
|
setLoading(false);
|
||
|
})
|
||
|
.catch((err) => {
|
||
|
setToastAlert({
|
||
|
message: err.message,
|
||
|
type: "error",
|
||
|
title: "Error",
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<form
|
||
|
onSubmit={handleSubmit(generateToken, (err) => {
|
||
|
if (err.title) {
|
||
|
setFocusTitle(true);
|
||
|
}
|
||
|
})}
|
||
|
className={`${themStore.sidebarCollapsed ? "xl:w-[50%] lg:w-[60%] " : "w-[60%]"} mx-auto py-8`}
|
||
|
>
|
||
|
<div className="border-b border-custom-border-200 pb-4">
|
||
|
<ApiTokenTitle
|
||
|
generatedToken={generatedToken}
|
||
|
control={control}
|
||
|
errors={errors}
|
||
|
focusTitle={focusTitle}
|
||
|
setFocusTitle={setFocusTitle}
|
||
|
setFocusDescription={setFocusDescription}
|
||
|
/>
|
||
|
{errors.title && focusTitle && <p className=" text-red-600">{errors.title.message}</p>}
|
||
|
<ApiTokenDescription
|
||
|
generatedToken={generatedToken}
|
||
|
control={control}
|
||
|
focusDescription={focusDescription}
|
||
|
setFocusTitle={setFocusTitle}
|
||
|
setFocusDescription={setFocusDescription}
|
||
|
/>
|
||
|
</div>
|
||
|
|
||
|
{!generatedToken && (
|
||
|
<div className="mt-12">
|
||
|
<>
|
||
|
<ApiTokenExpiry
|
||
|
neverExpires={neverExpires}
|
||
|
selectedExpiry={selectedExpiry}
|
||
|
setSelectedExpiry={setSelectedExpiry}
|
||
|
setNeverExpire={setNeverExpire}
|
||
|
renderExpiry={renderExpiry}
|
||
|
control={control}
|
||
|
/>
|
||
|
<Button variant="primary" type="submit">
|
||
|
{loading ? "generating..." : "Add Api key"}
|
||
|
</Button>
|
||
|
</>
|
||
|
</div>
|
||
|
)}
|
||
|
<ApiTokenKeySection
|
||
|
generatedToken={generatedToken}
|
||
|
renderExpiry={renderExpiry}
|
||
|
setDeleteTokenModal={setDeleteTokenModal}
|
||
|
/>
|
||
|
</form>
|
||
|
);
|
||
|
};
|