diff --git a/resources/scripts/api/admin/eggs/getEgg.ts b/resources/scripts/api/admin/eggs/getEgg.ts index 622317419..48e139301 100644 --- a/resources/scripts/api/admin/eggs/getEgg.ts +++ b/resources/scripts/api/admin/eggs/getEgg.ts @@ -41,8 +41,8 @@ export interface Egg { description: string | null; features: string[] | null; dockerImages: string[]; - configFiles: string | null; - configStartup: string | null; + configFiles: Record | null; + configStartup: Record | null; configStop: string | null; configFrom: number | null; startup: string; diff --git a/resources/scripts/components/admin/nests/NestEditContainer.tsx b/resources/scripts/components/admin/nests/NestEditContainer.tsx index d9e9c42fb..3e92d7f63 100644 --- a/resources/scripts/components/admin/nests/NestEditContainer.tsx +++ b/resources/scripts/components/admin/nests/NestEditContainer.tsx @@ -104,24 +104,21 @@ const EditInformationContainer = () => { -
-
- -
+ + -
- -
+
diff --git a/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx b/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx new file mode 100644 index 000000000..454a6e12e --- /dev/null +++ b/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx @@ -0,0 +1,58 @@ +import deleteEgg from '@/api/admin/eggs/deleteEgg'; +import React, { useState } from 'react'; +import { Actions, useStoreActions } from 'easy-peasy'; +import { ApplicationStore } from '@/state'; +import tw from 'twin.macro'; +import Button from '@/components/elements/Button'; +import ConfirmationModal from '@/components/elements/ConfirmationModal'; + +interface Props { + eggId: number; + onDeleted: () => void; +} + +export default ({ eggId, onDeleted }: Props) => { + const [ visible, setVisible ] = useState(false); + const [ loading, setLoading ] = useState(false); + + const { clearFlashes, clearAndAddHttpError } = useStoreActions((actions: Actions) => actions.flashes); + + const onDelete = () => { + setLoading(true); + clearFlashes('egg'); + + deleteEgg(eggId) + .then(() => { + setLoading(false); + onDeleted(); + }) + .catch(error => { + console.error(error); + clearAndAddHttpError({ key: 'egg', error }); + + setLoading(false); + setVisible(false); + }); + }; + + return ( + <> + setVisible(false)} + > + Are you sure you want to delete this egg? You may only delete an egg with no servers using it. + + + + + ); +}; diff --git a/resources/scripts/components/admin/nests/eggs/EggRouter.tsx b/resources/scripts/components/admin/nests/eggs/EggRouter.tsx index 3bd8f1dba..8ac6f15de 100644 --- a/resources/scripts/components/admin/nests/eggs/EggRouter.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggRouter.tsx @@ -93,11 +93,11 @@ const EggRouter = () => { - + - + diff --git a/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx b/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx index e19544f66..c36c9109c 100644 --- a/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx @@ -1,19 +1,182 @@ +import Editor from '@/components/elements/Editor'; +import Field from '@/components/elements/Field'; +import Input from '@/components/elements/Input'; +import Label from '@/components/elements/Label'; +import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; +import useFlash from '@/plugins/useFlash'; +import { jsonLanguage } from '@codemirror/lang-json'; +import { faEgg, faTerminal } from '@fortawesome/free-solid-svg-icons'; import React from 'react'; import AdminBox from '@/components/admin/AdminBox'; -import { Context } from '@/components/admin/nests/eggs/EggRouter'; +import { Egg } from '@/api/admin/eggs/getEgg'; +import tw from 'twin.macro'; +import { object } from 'yup'; +import { Form, Formik, useFormikContext } from 'formik'; -export default () => { - const egg = Context.useStoreState(state => state.egg); - - if (egg === undefined) { - return ( - <> - ); - } +function EggInformationContainer () { + const { isSubmitting } = useFormikContext(); return ( - + + + + + ); -}; +} + +function EggDetailsContainer ({ egg }: { egg: Egg }) { + return ( + +
+ + +
+ +
+ + +
+
+ ); +} + +function EggStartupContainer ({ className }: { className?: string }) { + const { isSubmitting } = useFormikContext(); + + return ( + + + + + + ); +} + +function EggImageContainer () { + const { isSubmitting } = useFormikContext(); + + return ( + + + + ); +} + +function EggStopContainer () { + const { isSubmitting } = useFormikContext(); + + return ( + + + + + + ); +} + +function EggProcessContainer ({ egg }: { egg: Egg }) { + const { isSubmitting } = useFormikContext(); + + return ( + + + +
+ + +
+ +
+ + +
+
+ ); +} + +export default function EggSettingsContainer ({ egg }: { egg: Egg }) { + const { clearFlashes } = useFlash(); + + const submit = () => { + clearFlashes('egg'); + }; + + return ( + + +
+ + +
+ + + +
+ + +
+ + + +
+ ); +} diff --git a/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx b/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx index d4df3dcf0..76a88ed33 100644 --- a/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx @@ -1,19 +1,11 @@ import React from 'react'; import AdminBox from '@/components/admin/AdminBox'; -import { Context } from '@/components/admin/nests/eggs/EggRouter'; - -export default () => { - const egg = Context.useStoreState(state => state.egg); - - if (egg === undefined) { - return ( - <> - ); - } +import { Egg } from '@/api/admin/eggs/getEgg'; +export default ({ egg }: { egg: Egg }) => { return ( - + {egg.name} ); }; diff --git a/resources/scripts/components/elements/Editor.tsx b/resources/scripts/components/elements/Editor.tsx index 4dd7bd510..5fa2dfe81 100644 --- a/resources/scripts/components/elements/Editor.tsx +++ b/resources/scripts/components/elements/Editor.tsx @@ -6,7 +6,7 @@ import { foldGutter, foldKeymap } from '@codemirror/fold'; import { lineNumbers, highlightActiveLineGutter } from '@codemirror/gutter'; import { defaultHighlightStyle } from '@codemirror/highlight'; import { history, historyKeymap } from '@codemirror/history'; -import { indentOnInput, LanguageSupport, LRLanguage } from '@codemirror/language'; +import { indentOnInput, LanguageSupport, LRLanguage, indentUnit } from '@codemirror/language'; import { lintKeymap } from '@codemirror/lint'; import { bracketMatching } from '@codemirror/matchbrackets'; import { rectangularSelection } from '@codemirror/rectangular-selection'; @@ -167,12 +167,13 @@ const defaultExtensions: Extension = [ ...lintKeymap, indentWithTab, ]), - EditorState.tabSize.of(4), + // This is gonna piss people off, but that isn't my problem. + indentUnit.of('\t'), ]; const EditorContainer = styled.div<{ overrides?: TwStyle }>` - min-height: 12rem; + //min-height: 12rem; ${tw`relative`}; & > div { @@ -207,6 +208,7 @@ export default ({ className, style, overrides, initialContent, extensions, mode, extensions: [ ...defaultExtensions, ...(extensions !== undefined ? extensions : []), + languageConfig.of(mode !== undefined ? modeToExtension(mode) : findLanguageExtensionByMode(findModeByFilename(filename || ''))), keybinds.of([]), ],