2022-04-07 01:29:07 +00:00
|
|
|
import { PencilAltIcon, TrashIcon } from "@heroicons/react/outline";
|
2022-04-07 23:36:47 +00:00
|
|
|
import { ExclamationIcon } from "@heroicons/react/solid";
|
|
|
|
import dayjs from "dayjs";
|
|
|
|
import relativeTime from "dayjs/plugin/relativeTime";
|
2022-04-07 01:29:07 +00:00
|
|
|
|
|
|
|
import classNames from "@calcom/lib/classNames";
|
|
|
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|
|
|
import Button from "@calcom/ui/Button";
|
|
|
|
import { Dialog, DialogTrigger } from "@calcom/ui/Dialog";
|
|
|
|
|
|
|
|
import { inferQueryOutput, trpc } from "@lib/trpc";
|
|
|
|
|
|
|
|
import { ListItem } from "@components/List";
|
|
|
|
import { Tooltip } from "@components/Tooltip";
|
|
|
|
import ConfirmationDialogContent from "@components/dialog/ConfirmationDialogContent";
|
|
|
|
import Badge from "@components/ui/Badge";
|
|
|
|
|
2022-04-07 23:36:47 +00:00
|
|
|
dayjs.extend(relativeTime);
|
|
|
|
|
2022-04-07 01:29:07 +00:00
|
|
|
export type TApiKeys = inferQueryOutput<"viewer.apiKeys.list">[number];
|
|
|
|
|
|
|
|
export default function ApiKeyListItem(props: { apiKey: TApiKeys; onEditApiKey: () => void }) {
|
|
|
|
const { t } = useLocale();
|
|
|
|
const utils = trpc.useContext();
|
2022-04-14 20:13:14 +00:00
|
|
|
const isExpired = props?.apiKey?.expiresAt ? props.apiKey.expiresAt < new Date() : null;
|
2022-04-07 23:36:47 +00:00
|
|
|
const neverExpires = props?.apiKey?.expiresAt === null;
|
2022-04-07 01:29:07 +00:00
|
|
|
const deleteApiKey = trpc.useMutation("viewer.apiKeys.delete", {
|
|
|
|
async onSuccess() {
|
|
|
|
await utils.invalidateQueries(["viewer.apiKeys.list"]);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<ListItem className="-mt-px flex w-full p-4">
|
|
|
|
<div className="flex w-full justify-between">
|
|
|
|
<div className="flex max-w-full flex-col truncate">
|
|
|
|
<div className="flex space-x-2">
|
2022-04-12 23:43:22 +00:00
|
|
|
<span className="text-gray-900">
|
2022-04-14 17:10:33 +00:00
|
|
|
{props?.apiKey?.note ? props.apiKey.note : t("api_key_no_note")}
|
2022-04-07 01:29:07 +00:00
|
|
|
</span>
|
2022-04-13 13:57:43 +00:00
|
|
|
{!neverExpires && isExpired && (
|
2022-04-12 23:43:22 +00:00
|
|
|
<Badge className="-p-2" variant="default">
|
|
|
|
{t("expired")}
|
|
|
|
</Badge>
|
2022-04-13 13:57:43 +00:00
|
|
|
)}
|
2022-04-07 01:29:07 +00:00
|
|
|
</div>
|
|
|
|
<div className="mt-2 flex">
|
|
|
|
<span
|
|
|
|
className={classNames(
|
|
|
|
"flex flex-col space-x-2 space-y-1 text-xs sm:flex-row sm:space-y-0 sm:rtl:space-x-reverse",
|
2022-04-12 23:43:22 +00:00
|
|
|
isExpired ? "text-red-600" : "text-gray-500",
|
2022-04-07 23:36:47 +00:00
|
|
|
neverExpires ? "text-yellow-600" : ""
|
2022-04-07 01:29:07 +00:00
|
|
|
)}>
|
2022-04-07 23:36:47 +00:00
|
|
|
{neverExpires ? (
|
2022-04-14 18:11:06 +00:00
|
|
|
<div className="flex flex-row space-x-3 text-gray-500">
|
2022-04-07 23:36:47 +00:00
|
|
|
<ExclamationIcon className="w-4" />
|
2022-04-12 23:43:22 +00:00
|
|
|
{t("api_key_never_expires")}
|
2022-04-07 23:36:47 +00:00
|
|
|
</div>
|
|
|
|
) : (
|
2022-04-12 23:43:22 +00:00
|
|
|
`${isExpired ? t("expired") : t("expires")} ${dayjs(
|
2022-04-07 23:36:47 +00:00
|
|
|
props?.apiKey?.expiresAt?.toString()
|
|
|
|
).fromNow()}`
|
|
|
|
)}
|
2022-04-07 01:29:07 +00:00
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="flex">
|
|
|
|
<Tooltip content={t("edit_api_key")}>
|
|
|
|
<Button
|
|
|
|
onClick={() => props.onEditApiKey()}
|
|
|
|
color="minimal"
|
|
|
|
size="icon"
|
|
|
|
StartIcon={PencilAltIcon}
|
2022-04-13 13:47:15 +00:00
|
|
|
className="ml-4 w-full self-center p-2"
|
|
|
|
/>
|
2022-04-07 01:29:07 +00:00
|
|
|
</Tooltip>
|
|
|
|
<Dialog>
|
|
|
|
<Tooltip content={t("delete_api_key")}>
|
|
|
|
<DialogTrigger asChild>
|
|
|
|
<Button
|
|
|
|
onClick={(e) => {
|
|
|
|
e.stopPropagation();
|
|
|
|
}}
|
|
|
|
color="minimal"
|
|
|
|
size="icon"
|
|
|
|
StartIcon={TrashIcon}
|
2022-04-13 13:48:05 +00:00
|
|
|
className="ml-2 w-full self-center p-2"
|
|
|
|
/>
|
2022-04-07 01:29:07 +00:00
|
|
|
</DialogTrigger>
|
|
|
|
</Tooltip>
|
|
|
|
<ConfirmationDialogContent
|
|
|
|
variety="danger"
|
2022-04-12 23:43:22 +00:00
|
|
|
title={t("confirm_delete_api_key")}
|
2022-04-14 16:38:55 +00:00
|
|
|
confirmBtnText={t("revoke_api_key")}
|
2022-04-07 01:29:07 +00:00
|
|
|
cancelBtnText={t("cancel")}
|
|
|
|
onConfirm={() =>
|
|
|
|
deleteApiKey.mutate({
|
|
|
|
id: props.apiKey.id,
|
|
|
|
})
|
|
|
|
}>
|
2022-04-12 23:43:22 +00:00
|
|
|
{t("delete_api_key_confirm_title")}
|
2022-04-07 01:29:07 +00:00
|
|
|
</ConfirmationDialogContent>
|
|
|
|
</Dialog>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</ListItem>
|
|
|
|
);
|
|
|
|
}
|