ui(admin): add delete confirmation for egg variables

This commit is contained in:
Matthew Penner 2021-10-23 12:29:17 -06:00
parent a3572006cb
commit 3b5fa34d85
No known key found for this signature in database
GPG Key ID: BAB67850901908A8
2 changed files with 54 additions and 23 deletions

View File

@ -1,6 +1,7 @@
import deleteEggVariable from '@/api/admin/eggs/deleteEggVariable'; import deleteEggVariable from '@/api/admin/eggs/deleteEggVariable';
import ConfirmationModal from '@/components/elements/ConfirmationModal';
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik'; import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
import React from 'react'; import React, { useState } from 'react';
import tw from 'twin.macro'; import tw from 'twin.macro';
import { array, boolean, object, string } from 'yup'; import { array, boolean, object, string } from 'yup';
import getEgg, { Egg, EggVariable } from '@/api/admin/eggs/getEgg'; import getEgg, { Egg, EggVariable } from '@/api/admin/eggs/getEgg';
@ -12,6 +13,7 @@ import Checkbox from '@/components/elements/Checkbox';
import Field, { FieldRow, TextareaField } from '@/components/elements/Field'; import Field, { FieldRow, TextareaField } from '@/components/elements/Field';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import useFlash from '@/plugins/useFlash'; import useFlash from '@/plugins/useFlash';
import { TrashIcon } from '@heroicons/react/outline';
export const validationSchema = object().shape({ export const validationSchema = object().shape({
name: string().required().min(1).max(191), name: string().required().min(1).max(191),
@ -84,25 +86,51 @@ export function EggVariableForm ({ prefix }: { prefix: string }) {
); );
} }
function EggVariableBox ({ onDeleteClick, variable, prefix }: { onDeleteClick: () => void, variable: EggVariable, prefix: string }) { function EggVariableDeleteButton ({ onClick }: { onClick: (success: () => void) => void }) {
const [ visible, setVisible ] = useState(false);
const [ loading, setLoading ] = useState(false);
const onDelete = () => {
setLoading(true);
onClick(() => {
setLoading(false);
});
};
return (
<>
<ConfirmationModal
visible={visible}
title={'Delete variable?'}
buttonText={'Yes, delete variable'}
onConfirmed={onDelete}
showSpinnerOverlay={loading}
onModalDismissed={() => setVisible(false)}
>
Are you sure you want to delete this variable? Deleting this variable will delete it from every server
using this egg.
</ConfirmationModal>
<button
type={'button'}
css={tw`ml-auto text-neutral-500 hover:text-neutral-300`}
onClick={() => setVisible(true)}
>
<TrashIcon css={tw`h-5 w-5`}/>
</button>
</>
);
}
function EggVariableBox ({ onDeleteClick, variable, prefix }: { onDeleteClick: (success: () => void) => void, variable: EggVariable, prefix: string }) {
const { isSubmitting } = useFormikContext(); const { isSubmitting } = useFormikContext();
return ( return (
<AdminBox <AdminBox
css={tw`relative w-full`} css={tw`relative w-full`}
title={<p css={tw`text-sm uppercase`}>{variable.name}</p>} title={<p css={tw`text-sm uppercase`}>{variable.name}</p>}
button={ button={<EggVariableDeleteButton onClick={onDeleteClick}/>}
<button
type={'button'}
css={tw`ml-auto text-neutral-500 hover:text-neutral-300`}
onClick={onDeleteClick}
>
{/* TODO: Change to heroicon 'x' */}
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" css={tw`h-5 w-5`}>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
</button>
}
> >
<SpinnerOverlay visible={isSubmitting}/> <SpinnerOverlay visible={isSubmitting}/>
@ -138,14 +166,17 @@ export default function EggVariablesContainer ({ egg }: { egg: Egg }) {
key={i} key={i}
prefix={`[${i}].`} prefix={`[${i}].`}
variable={v} variable={v}
onDeleteClick={() => { onDeleteClick={(success) => {
deleteEggVariable(egg.id, v.id) deleteEggVariable(egg.id, v.id)
.then(async () => await mutate(egg => ({ .then(async () => {
...egg!, await mutate(egg => ({
relations: { ...egg!,
variables: egg!.relations.variables!.filter(v2 => v.id === v2.id), relations: {
}, variables: egg!.relations.variables!.filter(v2 => v.id === v2.id),
}))) },
}));
success();
})
.catch(error => clearAndAddHttpError({ key: 'egg', error })); .catch(error => clearAndAddHttpError({ key: 'egg', error }));
}} }}
/> />

View File

@ -13,7 +13,7 @@ import NetworkingBox from '@/components/admin/servers/settings/NetworkingBox';
import ServerResourceBox from '@/components/admin/servers/settings/ServerResourceBox'; import ServerResourceBox from '@/components/admin/servers/settings/ServerResourceBox';
export default () => { export default () => {
const { data: server, mutate } = useServerFromRoute(); const { data: server } = useServerFromRoute();
const { clearFlashes, clearAndAddHttpError } = useStoreActions(actions => actions.flashes); const { clearFlashes, clearAndAddHttpError } = useStoreActions(actions => actions.flashes);
if (!server) return null; if (!server) return null;
@ -26,7 +26,7 @@ export default () => {
values.limits.oomDisabled = !values.limits.oomDisabled; values.limits.oomDisabled = !values.limits.oomDisabled;
updateServer(server.id, values) updateServer(server.id, values)
.then(s => { .then(() => {
// setServer({ ...server, ...s }); // setServer({ ...server, ...s });
// TODO: Figure out how to properly clear react-selects for allocations. // TODO: Figure out how to properly clear react-selects for allocations.