diff --git a/resources/scripts/components/admin/AdminBox.tsx b/resources/scripts/components/admin/AdminBox.tsx new file mode 100644 index 000000000..9519dbdc0 --- /dev/null +++ b/resources/scripts/components/admin/AdminBox.tsx @@ -0,0 +1,31 @@ +import React, { memo } from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import tw from 'twin.macro'; +import isEqual from 'react-fast-compare'; + +interface Props { + icon?: IconProp; + title: string | React.ReactNode; + className?: string; + children: React.ReactNode; +} + +const AdminBox = ({ icon, title, children, className }: Props) => ( +
+
+ {typeof title === 'string' ? +

+ {icon && }{title} +

+ : + title + } +
+
+ {children} +
+
+); + +export default memo(AdminBox, isEqual); diff --git a/resources/scripts/components/admin/databases/DatabasesContainer.tsx b/resources/scripts/components/admin/databases/DatabasesContainer.tsx index 0410da1e0..acf34297e 100644 --- a/resources/scripts/components/admin/databases/DatabasesContainer.tsx +++ b/resources/scripts/components/admin/databases/DatabasesContainer.tsx @@ -44,7 +44,7 @@ const DatabasesContainer = () => { return; } - clearAndAddHttpError({ error, key: 'databases' }); + clearAndAddHttpError({ key: 'databases', error }); }, [ error ]); const length = databases?.items?.length || 0; diff --git a/resources/scripts/components/admin/locations/LocationsContainer.tsx b/resources/scripts/components/admin/locations/LocationsContainer.tsx index dcd3ed758..af37bc326 100644 --- a/resources/scripts/components/admin/locations/LocationsContainer.tsx +++ b/resources/scripts/components/admin/locations/LocationsContainer.tsx @@ -44,7 +44,7 @@ const LocationsContainer = () => { return; } - clearAndAddHttpError({ error, key: 'locations' }); + clearAndAddHttpError({ key: 'locations', error }); }, [ error ]); const length = locations?.items?.length || 0; diff --git a/resources/scripts/components/admin/locations/NewLocationButton.tsx b/resources/scripts/components/admin/locations/NewLocationButton.tsx index 915db921c..8ed4aab02 100644 --- a/resources/scripts/components/admin/locations/NewLocationButton.tsx +++ b/resources/scripts/components/admin/locations/NewLocationButton.tsx @@ -38,7 +38,7 @@ export default () => { setVisible(false); }) .catch(error => { - clearAndAddHttpError(error); + clearAndAddHttpError({ key: 'location:create', error }); setSubmitting(false); }); }; diff --git a/resources/scripts/components/admin/mounts/MountsContainer.tsx b/resources/scripts/components/admin/mounts/MountsContainer.tsx index 7a0319a33..b78b97282 100644 --- a/resources/scripts/components/admin/mounts/MountsContainer.tsx +++ b/resources/scripts/components/admin/mounts/MountsContainer.tsx @@ -44,7 +44,7 @@ const MountsContainer = () => { return; } - clearAndAddHttpError({ error, key: 'mounts' }); + clearAndAddHttpError({ key: 'mounts', error }); }, [ error ]); const length = mounts?.items?.length || 0; diff --git a/resources/scripts/components/admin/nests/NestEditContainer.tsx b/resources/scripts/components/admin/nests/NestEditContainer.tsx index 78e034f72..803da829f 100644 --- a/resources/scripts/components/admin/nests/NestEditContainer.tsx +++ b/resources/scripts/components/admin/nests/NestEditContainer.tsx @@ -1,20 +1,113 @@ -import React, { useEffect, useState } from 'react'; +import React, { createContext, useContext, useEffect, useState } from 'react'; import { useRouteMatch } from 'react-router-dom'; import tw from 'twin.macro'; -import useFlash from '@/plugins/useFlash'; import AdminContentBlock from '@/components/admin/AdminContentBlock'; import Spinner from '@/components/elements/Spinner'; import FlashMessageRender from '@/components/FlashMessageRender'; import { Nest } from '@/api/admin/nests/getNests'; import getNest from '@/api/admin/nests/getNest'; +import updateNest from '@/api/admin/nests/updateNest'; +import { object, string } from 'yup'; +import Button from '@/components/elements/Button'; +import Field from '@/components/elements/Field'; +import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; +import { ApplicationStore } from '@/state'; +import { Actions, useStoreActions } from 'easy-peasy'; +import { Form, Formik, FormikHelpers } from 'formik'; +import AdminBox from '@/components/admin/AdminBox'; -export default () => { +interface ctx { + nest: Nest | undefined; + setNest: (value: Nest | undefined) => void; +} + +export const Context = createContext({ nest: undefined, setNest: () => 1 }); + +interface Values { + name: string; + description: string | null; +} + +const NestEditBox = () => { + const { clearFlashes, clearAndAddHttpError } = useStoreActions((actions: Actions) => actions.flashes); + const { nest, setNest } = useContext(Context); + + if (nest === undefined) { + return ( + <> + ); + } + + const submit = ({ name, description }: Values, { setSubmitting }: FormikHelpers) => { + clearFlashes('nest'); + + updateNest(nest.id, name, description || undefined) + .then(() => setNest({ ...nest, name, description })) + .catch(error => { + console.error(error); + clearAndAddHttpError({ key: 'nest', error }); + }) + .then(() => setSubmitting(false)); + }; + + return ( + + { + ({ isSubmitting, isValid }) => ( + + + + +
+
+ +
+ +
+ +
+ +
+ +
+
+
+
+ ) + } +
+ ); +}; + +const NestEditContainer = () => { const match = useRouteMatch<{ nestId?: string }>(); - const { clearFlashes, clearAndAddHttpError } = useFlash(); + const { clearFlashes, clearAndAddHttpError } = useStoreActions((actions: Actions) => actions.flashes); const [ loading, setLoading ] = useState(true); - const [ nest, setNest ] = useState(undefined); + const { nest, setNest } = useContext(Context); useEffect(() => { clearFlashes('nest'); @@ -23,7 +116,7 @@ export default () => { .then(nest => setNest(nest)) .catch(error => { console.error(error); - clearAndAddHttpError(error); + clearAndAddHttpError({ key: 'nest', error }); }) .then(() => setLoading(false)); }, []); @@ -31,11 +124,11 @@ export default () => { if (loading || nest === undefined) { return ( + +
- -
); } @@ -49,7 +142,19 @@ export default () => { -

{JSON.stringify(nest.relations.eggs)}

+ + + ); }; + +export default () => { + const [ nest, setNest ] = useState(undefined); + + return ( + + + + ); +}; diff --git a/resources/scripts/components/admin/nests/NestsContainer.tsx b/resources/scripts/components/admin/nests/NestsContainer.tsx index 56201656a..3baa14d95 100644 --- a/resources/scripts/components/admin/nests/NestsContainer.tsx +++ b/resources/scripts/components/admin/nests/NestsContainer.tsx @@ -44,7 +44,7 @@ const NestsContainer = () => { return; } - clearAndAddHttpError({ error, key: 'nests' }); + clearAndAddHttpError({ key: 'nests', error }); }, [ error ]); const length = nests?.items?.length || 0; diff --git a/resources/scripts/components/admin/nodes/NodesContainer.tsx b/resources/scripts/components/admin/nodes/NodesContainer.tsx index baafede68..11fc70a9d 100644 --- a/resources/scripts/components/admin/nodes/NodesContainer.tsx +++ b/resources/scripts/components/admin/nodes/NodesContainer.tsx @@ -45,7 +45,7 @@ const NodesContainer = () => { return; } - clearAndAddHttpError({ error, key: 'nodes' }); + clearAndAddHttpError({ key: 'nodes', error }); }, [ error ]); const length = nodes?.items?.length || 0; diff --git a/resources/scripts/components/admin/overview/OverviewContainer.tsx b/resources/scripts/components/admin/overview/OverviewContainer.tsx index 7db8f0e9b..91141f037 100644 --- a/resources/scripts/components/admin/overview/OverviewContainer.tsx +++ b/resources/scripts/components/admin/overview/OverviewContainer.tsx @@ -26,7 +26,7 @@ export default () => { .then(versionData => setVersionData(versionData)) .catch(error => { console.error(error); - clearAndAddHttpError(error); + clearAndAddHttpError({ key: 'overview', error }); }) .then(() => setLoading(false)); }, []); diff --git a/resources/scripts/components/admin/roles/NewRoleButton.tsx b/resources/scripts/components/admin/roles/NewRoleButton.tsx index 2e2119fa0..5259dfe0a 100644 --- a/resources/scripts/components/admin/roles/NewRoleButton.tsx +++ b/resources/scripts/components/admin/roles/NewRoleButton.tsx @@ -1,6 +1,5 @@ import React, { useState } from 'react'; import createRole from '@/api/admin/roles/createRole'; -import { httpErrorToHuman } from '@/api/http'; import { AdminContext } from '@/state/admin'; import Button from '@/components/elements/Button'; import Field from '@/components/elements/Field'; @@ -26,7 +25,7 @@ const schema = object().shape({ export default () => { const [ visible, setVisible ] = useState(false); - const { addError, clearFlashes } = useFlash(); + const { clearFlashes, clearAndAddHttpError } = useFlash(); const appendRole = AdminContext.useStoreActions(actions => actions.roles.appendRole); @@ -40,7 +39,7 @@ export default () => { setVisible(false); }) .catch(error => { - addError({ key: 'role:create', message: httpErrorToHuman(error) }); + clearAndAddHttpError({ key: 'role:create', error }); setSubmitting(false); }); }; diff --git a/resources/scripts/components/admin/roles/RolesContainer.tsx b/resources/scripts/components/admin/roles/RolesContainer.tsx index fb7cc4380..9c87a348d 100644 --- a/resources/scripts/components/admin/roles/RolesContainer.tsx +++ b/resources/scripts/components/admin/roles/RolesContainer.tsx @@ -52,7 +52,7 @@ export default () => { .then(roles => setRoles(roles)) .catch(error => { console.error(error); - clearAndAddHttpError(error); + clearAndAddHttpError({ key: 'roles', error }); }) .then(() => setLoading(false)); }, []); diff --git a/resources/scripts/components/admin/servers/ServersContainer.tsx b/resources/scripts/components/admin/servers/ServersContainer.tsx index 3ea269374..3fbb21b76 100644 --- a/resources/scripts/components/admin/servers/ServersContainer.tsx +++ b/resources/scripts/components/admin/servers/ServersContainer.tsx @@ -44,7 +44,7 @@ const UsersContainer = () => { return; } - clearAndAddHttpError({ error, key: 'servers' }); + clearAndAddHttpError({ key: 'servers', error }); }, [ error ]); const length = servers?.items?.length || 0; diff --git a/resources/scripts/components/admin/users/UsersContainer.tsx b/resources/scripts/components/admin/users/UsersContainer.tsx index 83d5fbddb..7c83960b2 100644 --- a/resources/scripts/components/admin/users/UsersContainer.tsx +++ b/resources/scripts/components/admin/users/UsersContainer.tsx @@ -44,7 +44,7 @@ const UsersContainer = () => { return; } - clearAndAddHttpError({ error, key: 'users' }); + clearAndAddHttpError({ key: 'users', error }); }, [ error ]); const length = users?.items?.length || 0;