import type { Actions } from 'easy-peasy'; import { useStoreActions } from 'easy-peasy'; import type { FormikHelpers } from 'formik'; import { Form, Formik, useField, useFormikContext } from 'formik'; import { useEffect, useState } from 'react'; import tw from 'twin.macro'; import { object } from 'yup'; import type { InferModel } from '@/api/admin'; import type { Egg, EggVariable } from '@/api/admin/egg'; import { getEgg } from '@/api/admin/egg'; import type { Server } from '@/api/admin/server'; import { useServerFromRoute } from '@/api/admin/server'; import type { Values } from '@/api/admin/servers/updateServerStartup'; import updateServerStartup from '@/api/admin/servers/updateServerStartup'; import EggSelect from '@/components/admin/servers/EggSelect'; import NestSelector from '@/components/admin/servers/NestSelector'; import FormikSwitch from '@/components/elements/FormikSwitch'; import Button from '@/components/elements/Button'; import Input from '@/components/elements/Input'; import AdminBox from '@/components/admin/AdminBox'; import Field from '@/components/elements/Field'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; import Label from '@/components/elements/Label'; import type { ApplicationStore } from '@/state'; function ServerStartupLineContainer({ egg, server }: { egg: Egg | null; server: Server }) { const { isSubmitting, setFieldValue } = useFormikContext(); useEffect(() => { if (egg === null) { return; } if (server.eggId === egg.id) { setFieldValue('image', server.container.image); setFieldValue('startup', server.container.startup || ''); return; } // Whenever the egg is changed, set the server's startup command to the egg's default. setFieldValue('image', Object.values(egg.dockerImages)[0] ?? ''); setFieldValue('startup', ''); }, [egg]); return (
); } export function ServerServiceContainer({ egg, setEgg, nestId: _nestId, }: { egg: Egg | null; setEgg: (value: Egg | null) => void; nestId: number; }) { const { isSubmitting } = useFormikContext(); const [nestId, setNestId] = useState(_nestId); return (
); } export function ServerImageContainer() { const { isSubmitting } = useFormikContext(); return (
{/* TODO: make this a proper select but allow a custom image to be specified if needed. */}
); } export function ServerVariableContainer({ variable, value }: { variable: EggVariable; value?: string }) { const key = 'environment.' + variable.environmentVariable; const [, , { setValue, setTouched }] = useField(key); const { isSubmitting } = useFormikContext(); useEffect(() => { if (value === undefined) { return; } setValue(value); setTouched(true); }, [value]); return ( {variable.name}

}>
); } function ServerStartupForm({ egg, setEgg, server, }: { egg: Egg | null; setEgg: (value: Egg | null) => void; server: Server; }) { const { isSubmitting, isValid, values: { environment }, } = useFormikContext(); return (
{/* This ensures that no variables are rendered unless the environment has a value for the variable. */} {egg?.relationships.variables ?.filter(v => Object.keys(environment).find(e => e === v.environmentVariable) !== undefined) .map((v, i) => ( v.eggId === v2.eggId && v.environmentVariable === v2.environmentVariable, )?.serverValue } /> ))}
); } export default () => { const { data: server } = useServerFromRoute(); const { clearFlashes, clearAndAddHttpError } = useStoreActions( (actions: Actions) => actions.flashes, ); const [egg, setEgg] = useState | null>(null); useEffect(() => { if (!server) return; getEgg(server.eggId) .then(egg => setEgg(egg)) .catch(error => console.error(error)); }, [server?.eggId]); if (!server) return null; const submit = (values: Values, { setSubmitting }: FormikHelpers) => { clearFlashes('server'); updateServerStartup(server.id, values) // .then(s => { // mutate(data => { ...data, ...s }); // }) .catch(error => { console.error(error); clearAndAddHttpError({ key: 'server', error }); }) .then(() => setSubmitting(false)); }; return ( , image: server.container.image, eggId: server.eggId, skipScripts: false, }} validationSchema={object().shape({})} > ); };