diff --git a/resources/scripts/api/admin/nodes/getAllocations.ts b/resources/scripts/api/admin/nodes/getAllocations.ts index 791af342c..4809d2703 100644 --- a/resources/scripts/api/admin/nodes/getAllocations.ts +++ b/resources/scripts/api/admin/nodes/getAllocations.ts @@ -18,9 +18,9 @@ export const rawDataToAllocation = (data: FractalResponseData): Allocation => ({ assigned: data.attributes.assigned, }); -export default (uuid: string): Promise => { +export default (id: string | number): Promise => { return new Promise((resolve, reject) => { - http.get(`/api/application/nodes/${uuid}/allocations`) + http.get(`/api/application/nodes/${id}/allocations`) .then(({ data }) => resolve((data.data || []).map(rawDataToAllocation))) .catch(reject); }); diff --git a/resources/scripts/components/admin/databases/DatabasesContainer.tsx b/resources/scripts/components/admin/databases/DatabasesContainer.tsx index 5cdc057e5..93ffc86b4 100644 --- a/resources/scripts/components/admin/databases/DatabasesContainer.tsx +++ b/resources/scripts/components/admin/databases/DatabasesContainer.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext, useEffect } from 'react'; import getDatabases, { Context as DatabasesContext, Filters } from '@/api/admin/databases/getDatabases'; import FlashMessageRender from '@/components/FlashMessageRender'; import useFlash from '@/plugins/useFlash'; @@ -7,17 +7,7 @@ import { NavLink, useRouteMatch } from 'react-router-dom'; import tw from 'twin.macro'; import AdminContentBlock from '@/components/admin/AdminContentBlock'; import AdminCheckbox from '@/components/admin/AdminCheckbox'; -import AdminTable, { - TableBody, - TableHead, - TableHeader, - TableRow, - Pagination, - Loading, - NoItems, - ContentWrapper, - useTableHooks -} from '@/components/admin/AdminTable'; +import AdminTable, { TableBody, TableHead, TableHeader, TableRow, Pagination, Loading, NoItems, ContentWrapper, useTableHooks } from '@/components/admin/AdminTable'; import Button from '@/components/elements/Button'; import CopyOnClick from '@/components/elements/CopyOnClick'; diff --git a/resources/scripts/components/admin/locations/LocationsContainer.tsx b/resources/scripts/components/admin/locations/LocationsContainer.tsx index 190843740..9cc11bb2b 100644 --- a/resources/scripts/components/admin/locations/LocationsContainer.tsx +++ b/resources/scripts/components/admin/locations/LocationsContainer.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext, useEffect } from 'react'; import getLocations, { Context as LocationsContext, Filters } from '@/api/admin/locations/getLocations'; import FlashMessageRender from '@/components/FlashMessageRender'; import useFlash from '@/plugins/useFlash'; @@ -7,17 +7,7 @@ import { NavLink, useRouteMatch } from 'react-router-dom'; import tw from 'twin.macro'; import AdminContentBlock from '@/components/admin/AdminContentBlock'; import AdminCheckbox from '@/components/admin/AdminCheckbox'; -import AdminTable, { - TableBody, - TableHead, - TableHeader, - TableRow, - Pagination, - Loading, - NoItems, - ContentWrapper, - useTableHooks -} from '@/components/admin/AdminTable'; +import AdminTable, { TableBody, TableHead, TableHeader, TableRow, Pagination, Loading, NoItems, ContentWrapper, useTableHooks } from '@/components/admin/AdminTable'; import NewLocationButton from '@/components/admin/locations/NewLocationButton'; import CopyOnClick from '@/components/elements/CopyOnClick'; diff --git a/resources/scripts/components/admin/mounts/MountsContainer.tsx b/resources/scripts/components/admin/mounts/MountsContainer.tsx index 415a69078..e627a3a85 100644 --- a/resources/scripts/components/admin/mounts/MountsContainer.tsx +++ b/resources/scripts/components/admin/mounts/MountsContainer.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext, useEffect } from 'react'; import getMounts, { Context as MountsContext, Filters } from '@/api/admin/mounts/getMounts'; import FlashMessageRender from '@/components/FlashMessageRender'; import useFlash from '@/plugins/useFlash'; @@ -7,17 +7,7 @@ import { NavLink, useRouteMatch } from 'react-router-dom'; import tw from 'twin.macro'; import AdminContentBlock from '@/components/admin/AdminContentBlock'; import AdminCheckbox from '@/components/admin/AdminCheckbox'; -import AdminTable, { - TableBody, - TableHead, - TableHeader, - TableRow, - Pagination, - Loading, - NoItems, - ContentWrapper, - useTableHooks -} from '@/components/admin/AdminTable'; +import AdminTable, { TableBody, TableHead, TableHeader, TableRow, Pagination, Loading, NoItems, ContentWrapper, useTableHooks } from '@/components/admin/AdminTable'; import Button from '@/components/elements/Button'; import CopyOnClick from '@/components/elements/CopyOnClick'; diff --git a/resources/scripts/components/admin/nests/NestEggTable.tsx b/resources/scripts/components/admin/nests/NestEggTable.tsx index 4bb573b32..b13d122f5 100644 --- a/resources/scripts/components/admin/nests/NestEggTable.tsx +++ b/resources/scripts/components/admin/nests/NestEggTable.tsx @@ -1,21 +1,11 @@ import CopyOnClick from '@/components/elements/CopyOnClick'; -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext, useEffect } from 'react'; import getEggs, { Context as EggsContext, Filters } from '@/api/admin/nests/getEggs'; import useFlash from '@/plugins/useFlash'; import { NavLink, useRouteMatch } from 'react-router-dom'; import tw from 'twin.macro'; import AdminCheckbox from '@/components/admin/AdminCheckbox'; -import AdminTable, { - TableBody, - TableHead, - TableHeader, - TableRow, - Pagination, - Loading, - NoItems, - ContentWrapper, - useTableHooks -} from '@/components/admin/AdminTable'; +import AdminTable, { TableBody, TableHead, TableHeader, TableRow, Pagination, Loading, NoItems, ContentWrapper, useTableHooks } from '@/components/admin/AdminTable'; import { Context } from '@/components/admin/nests/NestEditContainer'; const RowCheckbox = ({ id }: { id: number}) => { diff --git a/resources/scripts/components/admin/nests/NestsContainer.tsx b/resources/scripts/components/admin/nests/NestsContainer.tsx index 6b89518da..6654aa28d 100644 --- a/resources/scripts/components/admin/nests/NestsContainer.tsx +++ b/resources/scripts/components/admin/nests/NestsContainer.tsx @@ -1,5 +1,5 @@ import CopyOnClick from '@/components/elements/CopyOnClick'; -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext, useEffect } from 'react'; import getNests, { Context as NestsContext, Filters } from '@/api/admin/nests/getNests'; import NewNestButton from '@/components/admin/nests/NewNestButton'; import FlashMessageRender from '@/components/FlashMessageRender'; @@ -9,17 +9,7 @@ import { NavLink, useRouteMatch } from 'react-router-dom'; import tw from 'twin.macro'; import AdminContentBlock from '@/components/admin/AdminContentBlock'; import AdminCheckbox from '@/components/admin/AdminCheckbox'; -import AdminTable, { - TableBody, - TableHead, - TableHeader, - TableRow, - Pagination, - Loading, - NoItems, - ContentWrapper, - useTableHooks -} from '@/components/admin/AdminTable'; +import AdminTable, { TableBody, TableHead, TableHeader, TableRow, Pagination, Loading, NoItems, ContentWrapper, useTableHooks } from '@/components/admin/AdminTable'; const RowCheckbox = ({ id }: { id: number}) => { const isChecked = AdminContext.useStoreState(state => state.nests.selectedNests.indexOf(id) >= 0); diff --git a/resources/scripts/components/admin/nodes/CreateAllocationForm.tsx b/resources/scripts/components/admin/nodes/CreateAllocationForm.tsx new file mode 100644 index 000000000..3da5ac7c2 --- /dev/null +++ b/resources/scripts/components/admin/nodes/CreateAllocationForm.tsx @@ -0,0 +1,97 @@ +import { Form, Formik, FormikHelpers } from 'formik'; +import React, { useEffect, useState } from 'react'; +import tw from 'twin.macro'; +import { array, number, object, string } from 'yup'; +import getAllocations from '@/api/admin/nodes/getAllocations'; +import Button from '@/components/elements/Button'; +import SelectField, { Option } from '@/components/elements/SelectField'; + +interface Values { + ips: string[]; + ports: number[]; +} + +const distinct = (value: any, index: any, self: any) => { + return self.indexOf(value) === index; +}; + +function CreateAllocationForm ({ nodeId }: { nodeId: string | number }) { + const [ ips, setIPs ] = useState([]); + const [ ports ] = useState([]); + + useEffect(() => { + getAllocations(nodeId) + .then(allocations => { + setIPs(allocations.map(a => a.ip).filter(distinct).map(ip => { + return { value: ip, label: ip }; + })); + }); + }, [ nodeId ]); + + const isValidIP = (inputValue: string): boolean => { + // TODO: Better way of checking for a valid ip (and CIDR). + return inputValue.match(/^([0-9a-f.:/]+)$/) !== null; + }; + + const isValidPort = (inputValue: string): boolean => { + // TODO: Better way of checking for a valid port (and port range) + return inputValue.match(/^([0-9-]+)$/) !== null; + }; + + const submit = (values: Values, { setSubmitting }: FormikHelpers) => { + setSubmitting(false); + }; + + return ( + + { + ({ isSubmitting, isValid }) => ( +
+ + + + +
+
+ +
+
+ + ) + } +
+ ); +} + +export default CreateAllocationForm; diff --git a/resources/scripts/components/admin/nodes/NodeAllocationContainer.tsx b/resources/scripts/components/admin/nodes/NodeAllocationContainer.tsx index d28f5ffc7..92b3fecb7 100644 --- a/resources/scripts/components/admin/nodes/NodeAllocationContainer.tsx +++ b/resources/scripts/components/admin/nodes/NodeAllocationContainer.tsx @@ -1,90 +1,14 @@ -import Label from '@/components/elements/Label'; -import React, { useEffect, useState } from 'react'; -import AdminBox from '@/components/admin/AdminBox'; -import Creatable from 'react-select/creatable'; -import { ActionMeta, GroupTypeBase, InputActionMeta, ValueType } from 'react-select/src/types'; -import { SelectStyle } from '@/components/elements/Select2'; -import tw from 'twin.macro'; -import getAllocations from '@/api/admin/nodes/getAllocations'; +import React from 'react'; import { useRouteMatch } from 'react-router-dom'; - -interface Option { - value: string; - label: string; -} - -const distinct = (value: any, index: any, self: any) => { - return self.indexOf(value) === index; -}; +import AdminBox from '@/components/admin/AdminBox'; +import CreateAllocationForm from '@/components/admin/nodes/CreateAllocationForm'; export default () => { const match = useRouteMatch<{ id: string }>(); - const [ ips, setIPs ] = useState([]); - const [ ports ] = useState([]); - - useEffect(() => { - getAllocations(match.params.id) - .then(allocations => { - setIPs(allocations.map(a => a.ip).filter(distinct).map(ip => { - return { value: ip, label: ip }; - })); - }); - }, []); - - const onChange = (value: ValueType, action: ActionMeta) => { - console.log({ - event: 'onChange', - value, - action, - }); - }; - - const onInputChange = (newValue: string, actionMeta: InputActionMeta) => { - console.log({ - event: 'onInputChange', - newValue, - actionMeta, - }); - }; - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const isValidNewOption1 = (inputValue: string, selectValue: ValueType, selectOptions: ReadonlyArray