import React, { useState, useEffect } from 'react'; import { message, Input, Modal, Typography, Form, Select } from 'antd'; import styled from 'styled-components'; import { red } from '@ant-design/colors'; import { Button } from '@src/alchemy-components'; import { useEnterKeyListener } from '../shared/useEnterKeyListener'; import { ACCESS_TOKEN_DURATIONS, getTokenExpireDate } from './utils'; import { useCreateAccessTokenMutation } from '../../graphql/auth.generated'; import { AccessTokenDuration, AccessTokenType, CreateAccessTokenInput } from '../../types.generated'; import { AccessTokenModal } from './AccessTokenModal'; import analytics, { EventType } from '../analytics'; import { ModalButtonContainer } from '../shared/button/styledComponents'; 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'))} )}
); }