import { red } from '@ant-design/colors'; import { Form, Input, Modal, Select, Typography, message } from 'antd'; import React, { useEffect, useState } from 'react'; import styled from 'styled-components'; import analytics, { EventType } from '@app/analytics'; import { AccessTokenModal } from '@app/settingsV2/AccessTokenModal'; import { ACCESS_TOKEN_DURATIONS, getTokenExpireDate } from '@app/settingsV2/utils'; import { ModalButtonContainer } from '@app/shared/button/styledComponents'; import { useEnterKeyListener } from '@app/shared/useEnterKeyListener'; import { Button } from '@src/alchemy-components'; import { useCreateAccessTokenMutation } from '@graphql/auth.generated'; import { AccessTokenDuration, AccessTokenType, CreateAccessTokenInput } from '@types'; type Props = { currentUserUrn: string; visible: boolean; forRemoteExecutor?: boolean; onClose: () => void; onCreateToken: () => void; }; type FormProps = { name: string; description?: string; duration: AccessTokenDuration; }; const ExpirationSelectContainer = styled.div` padding: 1px; `; const ExpirationDurationSelect = styled(Select)` && { width: 100%; margin-top: 1em; margin-bottom: 1em; } `; const OptionText = styled.span<{ isRed: boolean }>` ${(props) => props.isRed && `color: ${red[5]}`} `; export default function CreateTokenModal({ currentUserUrn, forRemoteExecutor, visible, onClose, onCreateToken, }: Props) { const [selectedTokenDuration, setSelectedTokenDuration] = useState(null); const [showModal, setShowModal] = useState(false); const [createButtonEnabled, setCreateButtonEnabled] = useState(true); const [createAccessToken, { data }] = useCreateAccessTokenMutation(); const [form] = Form.useForm(); // For remote executors they default to never useEffect(() => { if (forRemoteExecutor) { form.setFieldValue('duration', AccessTokenDuration.NoExpiry); } }, [forRemoteExecutor, form]); // Check and show the modal once the data for createAccessToken will generate useEffect(() => { if (data && data.createAccessToken?.accessToken) { setShowModal(true); } }, [data, setShowModal]); // Function to handle the close or cross button of Access Token Modal const onDetailModalClose = () => { setSelectedTokenDuration(null); setShowModal(false); onClose(); }; // Function to handle the close or cross button of Create Token Modal const onModalClose = () => { form.resetFields(); onClose(); }; const onCreateNewToken = () => { const { duration, name, description } = form.getFieldsValue(); const input: CreateAccessTokenInput = { actorUrn: currentUserUrn, type: AccessTokenType.Personal, duration, name, description, }; createAccessToken({ variables: { input } }) .then(({ errors }) => { if (!errors) { setSelectedTokenDuration(duration); analytics.event({ type: EventType.CreateAccessTokenEvent, accessTokenType: AccessTokenType.Personal, duration, }); } }) .catch((e) => { message.destroy(); message.error({ content: `Failed to create Token!: \n ${e.message || ''}`, duration: 3 }); }) .finally(() => { onCreateToken(); }); onModalClose(); }; const accessToken = data && data.createAccessToken?.accessToken; const selectedExpiresInText = selectedTokenDuration && getTokenExpireDate(selectedTokenDuration); // Handle the Enter press useEnterKeyListener({ querySelectorToExecuteClick: '#createTokenButton', }); const hasSelectedNoExpiration = selectedTokenDuration === AccessTokenDuration.NoExpiry; return ( <> } >
setCreateButtonEnabled(form.getFieldsError().some((field) => field.errors.length > 0)) } > Name}> Give your new token a name. Description}> An optional description for your new token. Expires in {ACCESS_TOKEN_DURATIONS.map((duration) => ( {duration.text} ))} prev.duration !== cur.duration} noStyle> {({ getFieldValue }) => ( {getFieldValue('duration') && getTokenExpireDate(getFieldValue('duration'))} )}
); }