import { useEffect, useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { faCheck, faCopy, faKey, faPlus, faTrashCan } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { yupResolver } from '@hookform/resolvers/yup'; import * as yup from 'yup'; import { Button, Checkbox, DeleteActionModal, EmptyState, FormControl, IconButton, Input, Modal, ModalClose, ModalContent, ModalTrigger, Select, SelectItem, Table, TableContainer, TableSkeleton, TBody, Td, Th, THead, Tr } from '@app/components/v2'; import { usePopUp, useToggle } from '@app/hooks'; import { ServiceToken, WorkspaceEnv } from '@app/hooks/api/types'; const apiTokenExpiry = [ { label: '1 Day', value: 86400 }, { label: '7 Days', value: 604800 }, { label: '1 Month', value: 2592000 }, { label: '6 months', value: 15552000 }, { label: '12 months', value: 31104000 }, { label: 'Never', value: null } ]; const createServiceTokenSchema = yup.object({ name: yup.string().required().label('Service Token Name'), environment: yup.string().required().label('Environment'), expiresIn: yup.string().optional().label('Service Token Expiration'), permissions: yup .object() .shape({ read: yup.boolean().required(), write: yup.boolean().required() }) .defined() .required() }); export type CreateServiceToken = yup.InferType; type Props = { tokens: ServiceToken[]; isLoading?: boolean; workspaceName: string; environments: WorkspaceEnv[]; onDeleteToken: (serviceTokenID: string) => Promise; onCreateToken: (data: CreateServiceToken) => Promise; }; type DeleteModalData = { name: string; id: string }; export const ServiceTokenSection = ({ tokens = [], isLoading, onDeleteToken, workspaceName, environments = [], onCreateToken }: Props): JSX.Element => { const [newToken, setToken] = useState(''); const { t } = useTranslation(); const [isTokenCopied, setIsTokenCopied] = useToggle(false); useEffect(() => { let timer: NodeJS.Timeout; if (isTokenCopied) { timer = setTimeout(() => setIsTokenCopied.off(), 2000); } return () => clearTimeout(timer); }, [isTokenCopied]); const copyTokenToClipboard = () => { navigator.clipboard.writeText(newToken); setIsTokenCopied.on(); }; const { popUp, handlePopUpToggle, handlePopUpClose, handlePopUpOpen } = usePopUp([ 'createAPIToken', 'deleteAPITokenConfirmation' ] as const); const { control, reset, handleSubmit, formState: { isSubmitting } } = useForm({ resolver: yupResolver(createServiceTokenSchema) }); const hasServiceToken = Boolean(newToken); const onFormSubmit = async (data: CreateServiceToken) => { const token = await onCreateToken(data); setToken(token); }; const onDeleteApproved = async () => { await onDeleteToken((popUp?.deleteAPITokenConfirmation?.data as DeleteModalData)?.id); handlePopUpClose('deleteAPITokenConfirmation'); }; return (

{t('section.token.service-tokens')}

{t('section.token.service-tokens-description')}

Please, make sure you are on the latest version of CLI .

{ handlePopUpToggle('createAPIToken', open); reset(); setToken(''); }} > {!hasServiceToken ? (
( )} /> ( )} /> ( )} /> { const options = [ { label: 'Read (default)', value: 'read' }, { label: 'Write (optional)', value: 'write' } ]; return ( <> {options.map(({ label, value: optionValue }) => { // TODO: refactor return ( { onChange({ ...value, [optionValue]: state }); }} > {label} ); })} ); }} />
) : (

{newToken}

{t('common.click-to-copy')}
)}
handlePopUpToggle('deleteAPITokenConfirmation', isOpen)} deleteKey={(popUp?.deleteAPITokenConfirmation?.data as DeleteModalData)?.name} onClose={() => handlePopUpClose('deleteAPITokenConfirmation')} onDeleteApproved={onDeleteApproved} /> {isLoading && } {!isLoading && tokens.map((row) => ( ))} {!isLoading && tokens?.length === 0 && ( )}
Token Name Environment Valid Until
{row.name} {row.environment} {row.expiresAt && new Date(row.expiresAt).toUTCString()} handlePopUpOpen('deleteAPITokenConfirmation', { name: row.name, id: row._id }) } colorSchema="danger" ariaLabel="delete" >
); };