import React, { useState } from 'react'; import Modal from '@/components/elements/Modal'; import { Form, Formik, FormikHelpers } from 'formik'; import Field from '@/components/elements/Field'; import { object, string } from 'yup'; import createServerDatabase from '@/api/server/databases/createServerDatabase'; import { ServerContext } from '@/state/server'; import { httpErrorToHuman } from '@/api/http'; import FlashMessageRender from '@/components/FlashMessageRender'; import useFlash from '@/plugins/useFlash'; import Button from '@/components/elements/Button'; import tw from 'twin.macro'; interface Values { databaseName: string; connectionsFrom: string; } const schema = object().shape({ databaseName: string() .required('A database name must be provided.') .min(3, 'Database name must be at least 3 characters.') .max(48, 'Database name must not exceed 48 characters.') .matches( /^[\w\-.]{3,48}$/, 'Database name should only contain alphanumeric characters, underscores, dashes, and/or periods.' ), connectionsFrom: string().matches(/^[\w\-/.%:]+$/, 'A valid host address must be provided.'), }); export default () => { const uuid = ServerContext.useStoreState((state) => state.server.data!.uuid); const { addError, clearFlashes } = useFlash(); const [visible, setVisible] = useState(false); const appendDatabase = ServerContext.useStoreActions((actions) => actions.databases.appendDatabase); const submit = (values: Values, { setSubmitting }: FormikHelpers<Values>) => { clearFlashes('database:create'); createServerDatabase(uuid, { databaseName: values.databaseName, connectionsFrom: values.connectionsFrom || '%', }) .then((database) => { appendDatabase(database); setVisible(false); }) .catch((error) => { addError({ key: 'database:create', message: httpErrorToHuman(error) }); setSubmitting(false); }); }; return ( <> <Formik onSubmit={submit} initialValues={{ databaseName: '', connectionsFrom: '' }} validationSchema={schema} > {({ isSubmitting, resetForm }) => ( <Modal visible={visible} dismissable={!isSubmitting} showSpinnerOverlay={isSubmitting} onDismissed={() => { resetForm(); setVisible(false); }} > <FlashMessageRender byKey={'database:create'} css={tw`mb-6`} /> <h2 css={tw`text-2xl mb-6`}>Create new database</h2> <Form css={tw`m-0`}> <Field type={'string'} id={'database_name'} name={'databaseName'} label={'Database Name'} description={'A descriptive name for your database instance.'} /> <div css={tw`mt-6`}> <Field type={'string'} id={'connections_from'} name={'connectionsFrom'} label={'Connections From'} description={ 'Where connections should be allowed from. Leave blank to allow connections from anywhere.' } /> </div> <div css={tw`flex flex-wrap justify-end mt-6`}> <Button type={'button'} isSecondary css={tw`w-full sm:w-auto sm:mr-2`} onClick={() => setVisible(false)} > Cancel </Button> <Button css={tw`w-full mt-4 sm:w-auto sm:mt-0`} type={'submit'}> Create Database </Button> </div> </Form> </Modal> )} </Formik> <Button onClick={() => setVisible(true)}>New Database</Button> </> ); };