ui(admin): add "working" React admin ui
This commit is contained in:
parent
d1c7494933
commit
5402584508
199 changed files with 13387 additions and 151 deletions
|
@ -0,0 +1,31 @@
|
|||
import { faCogs } from '@fortawesome/free-solid-svg-icons';
|
||||
import { useFormikContext } from 'formik';
|
||||
import type { ReactNode } from 'react';
|
||||
import tw from 'twin.macro';
|
||||
|
||||
import { useServerFromRoute } from '@/api/admin/server';
|
||||
import AdminBox from '@/components/admin/AdminBox';
|
||||
import OwnerSelect from '@/components/admin/servers/OwnerSelect';
|
||||
import Field from '@/components/elements/Field';
|
||||
|
||||
export default ({ children }: { children?: ReactNode }) => {
|
||||
const { data: server } = useServerFromRoute();
|
||||
const { isSubmitting } = useFormikContext();
|
||||
|
||||
return (
|
||||
<AdminBox icon={faCogs} title={'Settings'} isLoading={isSubmitting}>
|
||||
<div css={tw`grid grid-cols-1 xl:grid-cols-2 gap-4 lg:gap-6`}>
|
||||
<Field
|
||||
id={'name'}
|
||||
name={'name'}
|
||||
label={'Server Name'}
|
||||
type={'text'}
|
||||
placeholder={'My Amazing Server'}
|
||||
/>
|
||||
<Field id={'externalId'} name={'externalId'} label={'External Identifier'} type={'text'} />
|
||||
<OwnerSelect selected={server?.relationships.user} />
|
||||
{children}
|
||||
</div>
|
||||
</AdminBox>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,38 @@
|
|||
import { faConciergeBell } from '@fortawesome/free-solid-svg-icons';
|
||||
import { useFormikContext } from 'formik';
|
||||
import tw from 'twin.macro';
|
||||
|
||||
import AdminBox from '@/components/admin/AdminBox';
|
||||
import Field from '@/components/elements/Field';
|
||||
|
||||
export default () => {
|
||||
const { isSubmitting } = useFormikContext();
|
||||
|
||||
return (
|
||||
<AdminBox icon={faConciergeBell} title={'Feature Limits'} isLoading={isSubmitting}>
|
||||
<div css={tw`grid grid-cols-1 xl:grid-cols-2 gap-4 lg:gap-6`}>
|
||||
<Field
|
||||
id={'featureLimits.allocations'}
|
||||
name={'featureLimits.allocations'}
|
||||
label={'Allocation Limit'}
|
||||
type={'number'}
|
||||
description={'The total number of allocations a user is allowed to create for this server.'}
|
||||
/>
|
||||
<Field
|
||||
id={'featureLimits.backups'}
|
||||
name={'featureLimits.backups'}
|
||||
label={'Backup Limit'}
|
||||
type={'number'}
|
||||
description={'The total number of backups that can be created for this server.'}
|
||||
/>
|
||||
<Field
|
||||
id={'featureLimits.databases'}
|
||||
name={'featureLimits.databases'}
|
||||
label={'Database Limit'}
|
||||
type={'number'}
|
||||
description={'The total number of databases a user is allowed to create for this server.'}
|
||||
/>
|
||||
</div>
|
||||
</AdminBox>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,68 @@
|
|||
import { faNetworkWired } from '@fortawesome/free-solid-svg-icons';
|
||||
import { useFormikContext } from 'formik';
|
||||
import tw from 'twin.macro';
|
||||
|
||||
import getAllocations from '@/api/admin/nodes/getAllocations';
|
||||
import { useServerFromRoute } from '@/api/admin/server';
|
||||
import AdminBox from '@/components/admin/AdminBox';
|
||||
import Label from '@/components/elements/Label';
|
||||
import Select from '@/components/elements/Select';
|
||||
import type { Option } from '@/components/elements/SelectField';
|
||||
import SelectField, { AsyncSelectField } from '@/components/elements/SelectField';
|
||||
|
||||
export default () => {
|
||||
const { isSubmitting } = useFormikContext();
|
||||
const { data: server } = useServerFromRoute();
|
||||
|
||||
const loadOptions = async (inputValue: string, callback: (options: Option[]) => void) => {
|
||||
if (!server) {
|
||||
// eslint-disable-next-line node/no-callback-literal
|
||||
callback([] as Option[]);
|
||||
return;
|
||||
}
|
||||
|
||||
const allocations = await getAllocations(server.nodeId, { ip: inputValue, server_id: '0' });
|
||||
|
||||
callback(
|
||||
allocations.map(a => {
|
||||
return { value: a.id.toString(), label: a.getDisplayText() };
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AdminBox icon={faNetworkWired} title={'Networking'} isLoading={isSubmitting}>
|
||||
<div css={tw`grid grid-cols-1 gap-4 lg:gap-6`}>
|
||||
<div>
|
||||
<Label htmlFor={'allocationId'}>Primary Allocation</Label>
|
||||
<Select id={'allocationId'} name={'allocationId'}>
|
||||
{server?.relationships.allocations?.map(a => (
|
||||
<option key={a.id} value={a.id}>
|
||||
{a.getDisplayText()}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
<AsyncSelectField
|
||||
id={'addAllocations'}
|
||||
name={'addAllocations'}
|
||||
label={'Add Allocations'}
|
||||
loadOptions={loadOptions}
|
||||
isMulti
|
||||
/>
|
||||
<SelectField
|
||||
id={'removeAllocations'}
|
||||
name={'removeAllocations'}
|
||||
label={'Remove Allocations'}
|
||||
options={
|
||||
server?.relationships.allocations?.map(a => {
|
||||
return { value: a.id.toString(), label: a.getDisplayText() };
|
||||
}) || []
|
||||
}
|
||||
isMulti
|
||||
isSearchable
|
||||
/>
|
||||
</div>
|
||||
</AdminBox>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,73 @@
|
|||
import { faBalanceScale } from '@fortawesome/free-solid-svg-icons';
|
||||
import { useFormikContext } from 'formik';
|
||||
import tw from 'twin.macro';
|
||||
|
||||
import AdminBox from '@/components/admin/AdminBox';
|
||||
import Field from '@/components/elements/Field';
|
||||
import FormikSwitch from '@/components/elements/FormikSwitch';
|
||||
|
||||
export default () => {
|
||||
const { isSubmitting } = useFormikContext();
|
||||
|
||||
return (
|
||||
<AdminBox icon={faBalanceScale} title={'Resources'} isLoading={isSubmitting}>
|
||||
<div css={tw`grid grid-cols-1 xl:grid-cols-2 gap-4 lg:gap-6`}>
|
||||
<Field
|
||||
id={'limits.cpu'}
|
||||
name={'limits.cpu'}
|
||||
label={'CPU Limit'}
|
||||
type={'text'}
|
||||
description={
|
||||
'Each thread on the system is considered to be 100%. Setting this value to 0 will allow the server to use CPU time without restriction.'
|
||||
}
|
||||
/>
|
||||
<Field
|
||||
id={'limits.threads'}
|
||||
name={'limits.threads'}
|
||||
label={'CPU Pinning'}
|
||||
type={'text'}
|
||||
description={
|
||||
'Advanced: Enter the specific CPU cores that this server can run on, or leave blank to allow all cores. This can be a single number, and or a comma seperated list, and or a dashed range. Example: 0, 0-1,3, or 0,1,3,4. It is recommended to leave this value blank and let the CPU handle balancing the load.'
|
||||
}
|
||||
/>
|
||||
<Field
|
||||
id={'limits.memory'}
|
||||
name={'limits.memory'}
|
||||
label={'Memory Limit'}
|
||||
type={'number'}
|
||||
description={
|
||||
'The maximum amount of memory allowed for this container. Setting this to 0 will allow unlimited memory in a container.'
|
||||
}
|
||||
/>
|
||||
<Field id={'limits.swap'} name={'limits.swap'} label={'Swap Limit'} type={'number'} />
|
||||
<Field
|
||||
id={'limits.disk'}
|
||||
name={'limits.disk'}
|
||||
label={'Disk Limit'}
|
||||
type={'number'}
|
||||
description={
|
||||
'This server will not be allowed to boot if it is using more than this amount of space. If a server goes over this limit while running it will be safely stopped and locked until enough space is available. Set to 0 to allow unlimited disk usage.'
|
||||
}
|
||||
/>
|
||||
<Field
|
||||
id={'limits.io'}
|
||||
name={'limits.io'}
|
||||
label={'Block IO Proportion'}
|
||||
type={'number'}
|
||||
description={
|
||||
'Advanced: The IO performance of this server relative to other running containers on the system. Value should be between 10 and 1000.'
|
||||
}
|
||||
/>
|
||||
<div css={tw`xl:col-span-2 bg-neutral-800 border border-neutral-900 shadow-inner p-4 rounded`}>
|
||||
<FormikSwitch
|
||||
name={'limits.oomDisabled'}
|
||||
label={'Out of Memory Killer'}
|
||||
description={
|
||||
'Enabling the Out of Memory Killer may cause server processes to exit unexpectedly.'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</AdminBox>
|
||||
);
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue