ui(admin): implement basic server editing
This commit is contained in:
parent
d0a78ec067
commit
6362731d55
11 changed files with 220 additions and 90 deletions
|
@ -8,6 +8,8 @@ use Illuminate\Http\JsonResponse;
|
||||||
use Spatie\QueryBuilder\QueryBuilder;
|
use Spatie\QueryBuilder\QueryBuilder;
|
||||||
use Pterodactyl\Services\Servers\ServerCreationService;
|
use Pterodactyl\Services\Servers\ServerCreationService;
|
||||||
use Pterodactyl\Services\Servers\ServerDeletionService;
|
use Pterodactyl\Services\Servers\ServerDeletionService;
|
||||||
|
use Pterodactyl\Services\Servers\BuildModificationService;
|
||||||
|
use Pterodactyl\Services\Servers\DetailsModificationService;
|
||||||
use Pterodactyl\Transformers\Api\Application\ServerTransformer;
|
use Pterodactyl\Transformers\Api\Application\ServerTransformer;
|
||||||
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
use Pterodactyl\Exceptions\Http\QueryValueOutOfRangeHttpException;
|
||||||
use Pterodactyl\Http\Requests\Api\Application\Servers\GetServerRequest;
|
use Pterodactyl\Http\Requests\Api\Application\Servers\GetServerRequest;
|
||||||
|
@ -15,23 +17,32 @@ use Pterodactyl\Http\Requests\Api\Application\Servers\GetServersRequest;
|
||||||
use Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest;
|
use Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest;
|
||||||
use Pterodactyl\Http\Requests\Api\Application\Servers\StoreServerRequest;
|
use Pterodactyl\Http\Requests\Api\Application\Servers\StoreServerRequest;
|
||||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||||
|
use Pterodactyl\Http\Requests\Api\Application\Servers\UpdateServerRequest;
|
||||||
|
|
||||||
class ServerController extends ApplicationApiController
|
class ServerController extends ApplicationApiController
|
||||||
{
|
{
|
||||||
private ServerCreationService $creationService;
|
private ServerCreationService $creationService;
|
||||||
private ServerDeletionService $deletionService;
|
private ServerDeletionService $deletionService;
|
||||||
|
|
||||||
|
private BuildModificationService $buildModificationService;
|
||||||
|
private DetailsModificationService $detailsModificationService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ServerController constructor.
|
* ServerController constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ServerCreationService $creationService,
|
ServerCreationService $creationService,
|
||||||
ServerDeletionService $deletionService
|
ServerDeletionService $deletionService,
|
||||||
|
BuildModificationService $buildModificationService,
|
||||||
|
DetailsModificationService $detailsModificationService
|
||||||
) {
|
) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->creationService = $creationService;
|
$this->creationService = $creationService;
|
||||||
$this->deletionService = $deletionService;
|
$this->deletionService = $deletionService;
|
||||||
|
|
||||||
|
$this->buildModificationService = $buildModificationService;
|
||||||
|
$this->detailsModificationService = $detailsModificationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,4 +110,24 @@ class ServerController extends ApplicationApiController
|
||||||
|
|
||||||
return $this->returnNoContent();
|
return $this->returnNoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a server.
|
||||||
|
*
|
||||||
|
* @throws \Throwable
|
||||||
|
* @throws \Illuminate\Validation\ValidationException
|
||||||
|
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||||
|
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||||
|
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableAllocationException
|
||||||
|
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableNodeException
|
||||||
|
*/
|
||||||
|
public function update(UpdateServerRequest $request, Server $server): array
|
||||||
|
{
|
||||||
|
$server = $this->buildModificationService->handle($server, $request->validated());
|
||||||
|
$server = $this->detailsModificationService->returnUpdatedModel()->handle($server, $request->validated());
|
||||||
|
|
||||||
|
return $this->fractal->item($server)
|
||||||
|
->transformWith(ServerTransformer::class)
|
||||||
|
->toArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ class UpdateServerBuildConfigurationRequest extends ServerWriteRequest
|
||||||
'limits.threads' => $this->requiredToOptional('threads', $rules['threads'], true),
|
'limits.threads' => $this->requiredToOptional('threads', $rules['threads'], true),
|
||||||
'limits.disk' => $this->requiredToOptional('disk', $rules['disk'], true),
|
'limits.disk' => $this->requiredToOptional('disk', $rules['disk'], true),
|
||||||
|
|
||||||
// Legacy rules to maintain backwards compatable API support without requiring
|
// Legacy rules to maintain backwards compatible API support without requiring
|
||||||
// a major version bump.
|
// a major version bump.
|
||||||
//
|
//
|
||||||
// @see https://github.com/pterodactyl/panel/issues/1500
|
// @see https://github.com/pterodactyl/panel/issues/1500
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Http\Requests\Api\Application\Servers;
|
||||||
|
|
||||||
|
use Pterodactyl\Models\Server;
|
||||||
|
use Pterodactyl\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||||
|
|
||||||
|
class UpdateServerRequest extends ApplicationApiRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$rules = Server::getRules();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'external_id' => $rules['external_id'],
|
||||||
|
'name' => $rules['name'],
|
||||||
|
'description' => array_merge(['nullable'], $rules['description']),
|
||||||
|
'owner_id' => $rules['owner_id'],
|
||||||
|
'oom_killer' => 'sometimes|boolean',
|
||||||
|
|
||||||
|
'memory' => $rules['memory'],
|
||||||
|
'swap' => $rules['swap'],
|
||||||
|
'disk' => $rules['disk'],
|
||||||
|
'io' => $rules['io'],
|
||||||
|
'threads' => $rules['threads'],
|
||||||
|
'cpu' => $rules['cpu'],
|
||||||
|
|
||||||
|
'databases' => $rules['database_limit'],
|
||||||
|
'allocations' => $rules['allocation_limit'],
|
||||||
|
'backups' => $rules['backup_limit'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validated(): array
|
||||||
|
{
|
||||||
|
$data = parent::validated();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'external_id' => array_get($data, 'external_id'),
|
||||||
|
'name' => array_get($data, 'name'),
|
||||||
|
'description' => array_get($data, 'description'),
|
||||||
|
'owner_id' => array_get($data, 'owner_id'),
|
||||||
|
'oom_disabled' => !array_get($data, 'oom_killer'),
|
||||||
|
|
||||||
|
'memory' => array_get($data, 'memory'),
|
||||||
|
'swap' => array_get($data, 'swap'),
|
||||||
|
'disk' => array_get($data, 'disk'),
|
||||||
|
'io' => array_get($data, 'io'),
|
||||||
|
'threads' => array_get($data, 'threads'),
|
||||||
|
'cpu' => array_get($data, 'cpu'),
|
||||||
|
|
||||||
|
'database_limit' => array_get($data, 'databases'),
|
||||||
|
'allocation_limit' => array_get($data, 'allocations'),
|
||||||
|
'backup_limit' => array_get($data, 'backups'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,6 +72,7 @@ class ServerTransformer extends Transformer
|
||||||
'image' => $model->image,
|
'image' => $model->image,
|
||||||
'environment' => $this->environmentService->handle($model),
|
'environment' => $this->environmentService->handle($model),
|
||||||
],
|
],
|
||||||
|
'oom_killer' => !$model->oom_disabled,
|
||||||
'updated_at' => self::formatTimestamp($model->updated_at),
|
'updated_at' => self::formatTimestamp($model->updated_at),
|
||||||
'created_at' => self::formatTimestamp($model->created_at),
|
'created_at' => self::formatTimestamp($model->created_at),
|
||||||
];
|
];
|
||||||
|
|
|
@ -43,6 +43,8 @@ export interface Server {
|
||||||
environment: Map<string, string>;
|
environment: Map<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oomKiller: boolean;
|
||||||
|
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
|
|
||||||
|
@ -90,6 +92,8 @@ export const rawDataToServer = ({ attributes }: FractalResponseData): Server =>
|
||||||
environment: attributes.container.environment,
|
environment: attributes.container.environment,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
oomKiller: attributes.oom_killer,
|
||||||
|
|
||||||
createdAt: new Date(attributes.created_at),
|
createdAt: new Date(attributes.created_at),
|
||||||
updatedAt: new Date(attributes.updated_at),
|
updatedAt: new Date(attributes.updated_at),
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,36 @@
|
||||||
import http from '@/api/http';
|
import http from '@/api/http';
|
||||||
import { Server, rawDataToServer } from '@/api/admin/servers/getServers';
|
import { Server, rawDataToServer } from '@/api/admin/servers/getServers';
|
||||||
|
|
||||||
export default (id: number, server: Partial<Server>, include: string[] = []): Promise<Server> => {
|
export interface Values {
|
||||||
|
externalId: string;
|
||||||
|
name: string;
|
||||||
|
ownerId: number;
|
||||||
|
oomKiller: boolean;
|
||||||
|
|
||||||
|
memory: number;
|
||||||
|
swap: number;
|
||||||
|
disk: number;
|
||||||
|
io: number;
|
||||||
|
cpu: number;
|
||||||
|
threads: string;
|
||||||
|
|
||||||
|
databases: number;
|
||||||
|
allocations: number;
|
||||||
|
backups: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (id: number, server: Partial<Values>, include: string[] = []): Promise<Server> => {
|
||||||
|
const data = {};
|
||||||
|
|
||||||
|
Object.keys(server).forEach((key) => {
|
||||||
|
const key2 = key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
||||||
|
// @ts-ignore
|
||||||
|
data[key2] = server[key];
|
||||||
|
});
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
http.patch(`/api/application/servers/${id}`, {
|
http.patch(`/api/application/servers/${id}`, data, { params: { include: include.join(',') } })
|
||||||
...server,
|
|
||||||
}, { params: { include: include.join(',') } })
|
|
||||||
.then(({ data }) => resolve(rawDataToServer(data)))
|
.then(({ data }) => resolve(rawDataToServer(data)))
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
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';
|
||||||
|
import deleteServer from '@/api/admin/servers/deleteServer';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
serverId: number;
|
||||||
|
onDeleted: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ({ serverId, onDeleted }: Props) => {
|
||||||
|
const [ visible, setVisible ] = useState(false);
|
||||||
|
const [ loading, setLoading ] = useState(false);
|
||||||
|
|
||||||
|
const { clearFlashes, clearAndAddHttpError } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
|
||||||
|
|
||||||
|
const onDelete = () => {
|
||||||
|
setLoading(true);
|
||||||
|
clearFlashes('server');
|
||||||
|
|
||||||
|
deleteServer(serverId)
|
||||||
|
.then(() => {
|
||||||
|
setLoading(false);
|
||||||
|
onDeleted();
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
clearAndAddHttpError({ key: 'server', error });
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
setVisible(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ConfirmationModal
|
||||||
|
visible={visible}
|
||||||
|
title={'Delete server?'}
|
||||||
|
buttonText={'Yes, delete server'}
|
||||||
|
onConfirmed={onDelete}
|
||||||
|
showSpinnerOverlay={loading}
|
||||||
|
onModalDismissed={() => setVisible(false)}
|
||||||
|
>
|
||||||
|
Are you sure you want to delete this server?
|
||||||
|
</ConfirmationModal>
|
||||||
|
|
||||||
|
<Button type={'button'} size={'xsmall'} color={'red'} onClick={() => setVisible(true)}>
|
||||||
|
<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>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -40,7 +40,7 @@ const ServerRouter = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
clearFlashes('server');
|
clearFlashes('server');
|
||||||
|
|
||||||
getServer(Number(match.params?.id), [ 'egg' ])
|
getServer(Number(match.params?.id), [ 'user' ])
|
||||||
.then(server => setServer(server))
|
.then(server => setServer(server))
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
@ -52,7 +52,7 @@ const ServerRouter = () => {
|
||||||
if (loading || server === undefined) {
|
if (loading || server === undefined) {
|
||||||
return (
|
return (
|
||||||
<AdminContentBlock>
|
<AdminContentBlock>
|
||||||
<FlashMessageRender byKey={'node'} css={tw`mb-4`}/>
|
<FlashMessageRender byKey={'server'} css={tw`mb-4`}/>
|
||||||
|
|
||||||
<div css={tw`w-full flex flex-col items-center justify-center`} style={{ height: '24rem' }}>
|
<div css={tw`w-full flex flex-col items-center justify-center`} style={{ height: '24rem' }}>
|
||||||
<Spinner size={'base'}/>
|
<Spinner size={'base'}/>
|
||||||
|
@ -62,7 +62,7 @@ const ServerRouter = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AdminContentBlock title={'Node - ' + server.name}>
|
<AdminContentBlock title={'Server - ' + server.name}>
|
||||||
<div css={tw`w-full flex flex-row items-center mb-4`}>
|
<div css={tw`w-full flex flex-row items-center mb-4`}>
|
||||||
<div css={tw`flex flex-col flex-shrink`} style={{ minWidth: '0' }}>
|
<div css={tw`flex flex-col flex-shrink`} style={{ minWidth: '0' }}>
|
||||||
<h2 css={tw`text-2xl text-neutral-50 font-header font-medium`}>{server.name}</h2>
|
<h2 css={tw`text-2xl text-neutral-50 font-header font-medium`}>{server.name}</h2>
|
||||||
|
@ -70,7 +70,7 @@ const ServerRouter = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FlashMessageRender byKey={'node'} css={tw`mb-4`}/>
|
<FlashMessageRender byKey={'server'} css={tw`mb-4`}/>
|
||||||
|
|
||||||
<SubNavigation>
|
<SubNavigation>
|
||||||
<SubNavigationLink to={`${match.url}`} name={'Settings'}>
|
<SubNavigationLink to={`${match.url}`} name={'Settings'}>
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
import { Server } from '@/api/admin/servers/getServers';
|
||||||
|
import ServerDeleteButton from '@/components/admin/servers/ServerDeleteButton';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import AdminBox from '@/components/admin/AdminBox';
|
import AdminBox from '@/components/admin/AdminBox';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
import { object } from 'yup';
|
import { object } from 'yup';
|
||||||
import updateServer from '@/api/admin/servers/updateServer';
|
import updateServer, { Values } from '@/api/admin/servers/updateServer';
|
||||||
import Field from '@/components/elements/Field';
|
import Field from '@/components/elements/Field';
|
||||||
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
||||||
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
||||||
|
@ -13,42 +16,9 @@ import OwnerSelect from '@/components/admin/servers/OwnerSelect';
|
||||||
import Button from '@/components/elements/Button';
|
import Button from '@/components/elements/Button';
|
||||||
import FormikSwitch from '@/components/elements/FormikSwitch';
|
import FormikSwitch from '@/components/elements/FormikSwitch';
|
||||||
|
|
||||||
interface Values {
|
export function ServerFeatureContainer () {
|
||||||
id: number;
|
|
||||||
externalId: string;
|
|
||||||
uuid: string;
|
|
||||||
identifier: string;
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
memory: number;
|
|
||||||
swap: number;
|
|
||||||
disk: number;
|
|
||||||
io: number;
|
|
||||||
cpu: number;
|
|
||||||
threads: string;
|
|
||||||
|
|
||||||
databases: number;
|
|
||||||
allocations: number;
|
|
||||||
backups: number;
|
|
||||||
|
|
||||||
ownerId: number;
|
|
||||||
nodeId: number;
|
|
||||||
allocationId: number;
|
|
||||||
nestId: number;
|
|
||||||
eggId: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ServerFeatureContainer = () => {
|
|
||||||
const { isSubmitting } = useFormikContext();
|
const { isSubmitting } = useFormikContext();
|
||||||
|
|
||||||
const server = Context.useStoreState(state => state.server);
|
|
||||||
|
|
||||||
if (server === undefined) {
|
|
||||||
return (
|
|
||||||
<></>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AdminBox title={'Feature Limits'} css={tw`relative w-full`}>
|
<AdminBox title={'Feature Limits'} css={tw`relative w-full`}>
|
||||||
<SpinnerOverlay visible={isSubmitting}/>
|
<SpinnerOverlay visible={isSubmitting}/>
|
||||||
|
@ -77,7 +47,7 @@ const ServerFeatureContainer = () => {
|
||||||
<div css={tw`mb-6 md:w-full md:flex md:flex-col md:ml-4 md:mb-0`}>
|
<div css={tw`mb-6 md:w-full md:flex md:flex-col md:ml-4 md:mb-0`}>
|
||||||
<Field
|
<Field
|
||||||
id={'backups'}
|
id={'backups'}
|
||||||
name={'backup'}
|
name={'backups'}
|
||||||
label={'Backup Limit'}
|
label={'Backup Limit'}
|
||||||
type={'number'}
|
type={'number'}
|
||||||
description={'The total number of backups that can be created for this server.'}
|
description={'The total number of backups that can be created for this server.'}
|
||||||
|
@ -86,19 +56,11 @@ const ServerFeatureContainer = () => {
|
||||||
</div>
|
</div>
|
||||||
</AdminBox>
|
</AdminBox>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
const ServerResourceContainer = () => {
|
export function ServerResourceContainer () {
|
||||||
const { isSubmitting } = useFormikContext();
|
const { isSubmitting } = useFormikContext();
|
||||||
|
|
||||||
const server = Context.useStoreState(state => state.server);
|
|
||||||
|
|
||||||
if (server === undefined) {
|
|
||||||
return (
|
|
||||||
<></>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AdminBox title={'Resource Management'} css={tw`relative w-full`}>
|
<AdminBox title={'Resource Management'} css={tw`relative w-full`}>
|
||||||
<SpinnerOverlay visible={isSubmitting}/>
|
<SpinnerOverlay visible={isSubmitting}/>
|
||||||
|
@ -171,7 +133,7 @@ const ServerResourceContainer = () => {
|
||||||
<div css={tw`mb-6 md:w-full md:flex md:flex-row`}>
|
<div css={tw`mb-6 md:w-full md:flex md:flex-row`}>
|
||||||
<div css={tw`mt-6 bg-neutral-800 border border-neutral-900 shadow-inner p-4 rounded`}>
|
<div css={tw`mt-6 bg-neutral-800 border border-neutral-900 shadow-inner p-4 rounded`}>
|
||||||
<FormikSwitch
|
<FormikSwitch
|
||||||
name={'oom'}
|
name={'oomKiller'}
|
||||||
label={'Out of Memory Killer'}
|
label={'Out of Memory Killer'}
|
||||||
description={'Enabling OOM killer may cause server processes to exit unexpectedly. '}
|
description={'Enabling OOM killer may cause server processes to exit unexpectedly. '}
|
||||||
/>
|
/>
|
||||||
|
@ -179,19 +141,11 @@ const ServerResourceContainer = () => {
|
||||||
</div>
|
</div>
|
||||||
</AdminBox>
|
</AdminBox>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
const ServerSettingsContainer = () => {
|
export function ServerSettingsContainer ({ server }: { server?: Server }) {
|
||||||
const { isSubmitting } = useFormikContext();
|
const { isSubmitting } = useFormikContext();
|
||||||
|
|
||||||
const server = Context.useStoreState(state => state.server);
|
|
||||||
|
|
||||||
if (server === undefined) {
|
|
||||||
return (
|
|
||||||
<></>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AdminBox title={'Settings'} css={tw`relative w-full`}>
|
<AdminBox title={'Settings'} css={tw`relative w-full`}>
|
||||||
<SpinnerOverlay visible={isSubmitting}/>
|
<SpinnerOverlay visible={isSubmitting}/>
|
||||||
|
@ -218,14 +172,16 @@ const ServerSettingsContainer = () => {
|
||||||
|
|
||||||
<div css={tw`mb-6 md:w-full md:flex md:flex-row`}>
|
<div css={tw`mb-6 md:w-full md:flex md:flex-row`}>
|
||||||
<div css={tw`mb-6 w-full md:w-1/2 md:flex md:flex-col md:pr-4 md:mb-0`}>
|
<div css={tw`mb-6 w-full md:w-1/2 md:flex md:flex-col md:pr-4 md:mb-0`}>
|
||||||
<OwnerSelect selected={null}/>
|
<OwnerSelect selected={server?.relations.user || null}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AdminBox>
|
</AdminBox>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
export default function ServerSettingsContainer2 () {
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
export default () => {
|
|
||||||
const { clearFlashes, clearAndAddHttpError } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
|
const { clearFlashes, clearAndAddHttpError } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
|
||||||
|
|
||||||
const server = Context.useStoreState(state => state.server);
|
const server = Context.useStoreState(state => state.server);
|
||||||
|
@ -239,6 +195,7 @@ export default () => {
|
||||||
|
|
||||||
const submit = (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
|
const submit = (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
|
||||||
clearFlashes('server');
|
clearFlashes('server');
|
||||||
|
console.log(values);
|
||||||
|
|
||||||
updateServer(server.id, values)
|
updateServer(server.id, values)
|
||||||
.then(() => setServer({ ...server, ...values }))
|
.then(() => setServer({ ...server, ...values }))
|
||||||
|
@ -253,11 +210,10 @@ export default () => {
|
||||||
<Formik
|
<Formik
|
||||||
onSubmit={submit}
|
onSubmit={submit}
|
||||||
initialValues={{
|
initialValues={{
|
||||||
id: server.id,
|
|
||||||
externalId: server.externalId || '',
|
externalId: server.externalId || '',
|
||||||
uuid: server.uuid,
|
|
||||||
identifier: server.identifier,
|
|
||||||
name: server.name,
|
name: server.name,
|
||||||
|
ownerId: server.ownerId,
|
||||||
|
oomKiller: server.oomKiller,
|
||||||
|
|
||||||
memory: server.limits.memory,
|
memory: server.limits.memory,
|
||||||
swap: server.limits.swap,
|
swap: server.limits.swap,
|
||||||
|
@ -269,12 +225,6 @@ export default () => {
|
||||||
databases: server.featureLimits.databases,
|
databases: server.featureLimits.databases,
|
||||||
allocations: server.featureLimits.allocations,
|
allocations: server.featureLimits.allocations,
|
||||||
backups: server.featureLimits.backups,
|
backups: server.featureLimits.backups,
|
||||||
|
|
||||||
ownerId: server.ownerId,
|
|
||||||
nodeId: server.nodeId,
|
|
||||||
allocationId: server.allocationId,
|
|
||||||
nestId: server.nestId,
|
|
||||||
eggId: server.eggId,
|
|
||||||
}}
|
}}
|
||||||
validationSchema={object().shape({
|
validationSchema={object().shape({
|
||||||
})}
|
})}
|
||||||
|
@ -285,7 +235,7 @@ export default () => {
|
||||||
<div css={tw`flex flex-col lg:flex-row`}>
|
<div css={tw`flex flex-col lg:flex-row`}>
|
||||||
<div css={tw`flex flex-col w-full mt-4 ml-0 lg:w-1/2 lg:ml-2 lg:mt-0`}>
|
<div css={tw`flex flex-col w-full mt-4 ml-0 lg:w-1/2 lg:ml-2 lg:mt-0`}>
|
||||||
<div css={tw`flex flex-col w-full mr-0 lg:mr-2`}>
|
<div css={tw`flex flex-col w-full mr-0 lg:mr-2`}>
|
||||||
<ServerSettingsContainer/>
|
<ServerSettingsContainer server={server}/>
|
||||||
</div>
|
</div>
|
||||||
<div css={tw`flex flex-col w-full mt-4 mr-0 lg:mr-2`}>
|
<div css={tw`flex flex-col w-full mt-4 mr-0 lg:mr-2`}>
|
||||||
<ServerFeatureContainer/>
|
<ServerFeatureContainer/>
|
||||||
|
@ -295,8 +245,12 @@ export default () => {
|
||||||
<div css={tw`flex flex-col w-full mr-0 lg:mr-2`}>
|
<div css={tw`flex flex-col w-full mr-0 lg:mr-2`}>
|
||||||
<ServerResourceContainer/>
|
<ServerResourceContainer/>
|
||||||
</div>
|
</div>
|
||||||
<div css={tw`py-2 pr-6 mt-4 rounded shadow-md bg-neutral-700`}>
|
<div css={tw`rounded shadow-md bg-neutral-700 mt-4 py-2 px-6`}>
|
||||||
<div css={tw`flex flex-row`}>
|
<div css={tw`flex flex-row`}>
|
||||||
|
<ServerDeleteButton
|
||||||
|
serverId={server?.id}
|
||||||
|
onDeleted={() => history.push('/admin/servers')}
|
||||||
|
/>
|
||||||
<Button type="submit" size="small" css={tw`ml-auto`} disabled={isSubmitting || !isValid}>
|
<Button type="submit" size="small" css={tw`ml-auto`} disabled={isSubmitting || !isValid}>
|
||||||
Save Changes
|
Save Changes
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -309,4 +263,4 @@ export default () => {
|
||||||
}
|
}
|
||||||
</Formik>
|
</Formik>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
|
@ -158,13 +158,13 @@ export default () => {
|
||||||
const submit = (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
|
const submit = (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
|
||||||
clearFlashes('server');
|
clearFlashes('server');
|
||||||
|
|
||||||
updateServer(server.id, values)
|
// updateServer(server.id, values)
|
||||||
.then(() => setServer({ ...server, ...values }))
|
// .then(() => setServer({ ...server, ...values }))
|
||||||
.catch(error => {
|
// .catch(error => {
|
||||||
console.error(error);
|
// console.error(error);
|
||||||
clearAndAddHttpError({ key: 'server', error });
|
// clearAndAddHttpError({ key: 'server', error });
|
||||||
})
|
// })
|
||||||
.then(() => setSubmitting(false));
|
// .then(() => setSubmitting(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -164,7 +164,7 @@ Route::group(['prefix' => '/servers'], function () {
|
||||||
Route::get('/{server}', [\Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController::class, 'view']);
|
Route::get('/{server}', [\Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController::class, 'view']);
|
||||||
Route::get('/external/{external_id}', [\Pterodactyl\Http\Controllers\Api\Application\Servers\ExternalServerController::class, 'index']);
|
Route::get('/external/{external_id}', [\Pterodactyl\Http\Controllers\Api\Application\Servers\ExternalServerController::class, 'index']);
|
||||||
|
|
||||||
Route::patch('/{server}/details', [\Pterodactyl\Http\Controllers\Api\Application\Servers\ServerDetailsController::class, 'details']);
|
Route::patch('/{server}', [\Pterodactyl\Http\Controllers\Api\Application\Servers\ServerController::class, 'update']);
|
||||||
Route::patch('/{server}/build', [\Pterodactyl\Http\Controllers\Api\Application\Servers\ServerDetailsController::class, 'build']);
|
Route::patch('/{server}/build', [\Pterodactyl\Http\Controllers\Api\Application\Servers\ServerDetailsController::class, 'build']);
|
||||||
Route::patch('/{server}/startup', [\Pterodactyl\Http\Controllers\Api\Application\Servers\StartupController::class, 'index']);
|
Route::patch('/{server}/startup', [\Pterodactyl\Http\Controllers\Api\Application\Servers\StartupController::class, 'index']);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue