📯 tRaNsFeR lOgS 📯
This commit is contained in:
parent
e6c4a68e4a
commit
5c5e2e24f1
12 changed files with 149 additions and 65 deletions
|
@ -8,7 +8,6 @@ use Prologue\Alerts\AlertsMessageBag;
|
||||||
use Pterodactyl\Models\ServerTransfer;
|
use Pterodactyl\Models\ServerTransfer;
|
||||||
use Pterodactyl\Http\Controllers\Controller;
|
use Pterodactyl\Http\Controllers\Controller;
|
||||||
use Pterodactyl\Services\Servers\TransferService;
|
use Pterodactyl\Services\Servers\TransferService;
|
||||||
use Pterodactyl\Services\Servers\SuspensionService;
|
|
||||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
||||||
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
||||||
use Pterodactyl\Repositories\Eloquent\LocationRepository;
|
use Pterodactyl\Repositories\Eloquent\LocationRepository;
|
||||||
|
@ -42,11 +41,6 @@ class ServerTransferController extends Controller
|
||||||
*/
|
*/
|
||||||
private $nodeRepository;
|
private $nodeRepository;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Servers\SuspensionService
|
|
||||||
*/
|
|
||||||
private $suspensionService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Pterodactyl\Services\Servers\TransferService
|
* @var \Pterodactyl\Services\Servers\TransferService
|
||||||
*/
|
*/
|
||||||
|
@ -65,7 +59,6 @@ class ServerTransferController extends Controller
|
||||||
* @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository
|
* @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository
|
||||||
* @param \Pterodactyl\Repositories\Eloquent\LocationRepository $locationRepository
|
* @param \Pterodactyl\Repositories\Eloquent\LocationRepository $locationRepository
|
||||||
* @param \Pterodactyl\Repositories\Eloquent\NodeRepository $nodeRepository
|
* @param \Pterodactyl\Repositories\Eloquent\NodeRepository $nodeRepository
|
||||||
* @param \Pterodactyl\Services\Servers\SuspensionService $suspensionService
|
|
||||||
* @param \Pterodactyl\Services\Servers\TransferService $transferService
|
* @param \Pterodactyl\Services\Servers\TransferService $transferService
|
||||||
* @param \Pterodactyl\Repositories\Wings\DaemonConfigurationRepository $daemonConfigurationRepository
|
* @param \Pterodactyl\Repositories\Wings\DaemonConfigurationRepository $daemonConfigurationRepository
|
||||||
*/
|
*/
|
||||||
|
@ -75,7 +68,6 @@ class ServerTransferController extends Controller
|
||||||
ServerRepository $repository,
|
ServerRepository $repository,
|
||||||
LocationRepository $locationRepository,
|
LocationRepository $locationRepository,
|
||||||
NodeRepository $nodeRepository,
|
NodeRepository $nodeRepository,
|
||||||
SuspensionService $suspensionService,
|
|
||||||
TransferService $transferService,
|
TransferService $transferService,
|
||||||
DaemonConfigurationRepository $daemonConfigurationRepository
|
DaemonConfigurationRepository $daemonConfigurationRepository
|
||||||
) {
|
) {
|
||||||
|
@ -84,7 +76,6 @@ class ServerTransferController extends Controller
|
||||||
$this->repository = $repository;
|
$this->repository = $repository;
|
||||||
$this->locationRepository = $locationRepository;
|
$this->locationRepository = $locationRepository;
|
||||||
$this->nodeRepository = $nodeRepository;
|
$this->nodeRepository = $nodeRepository;
|
||||||
$this->suspensionService = $suspensionService;
|
|
||||||
$this->transferService = $transferService;
|
$this->transferService = $transferService;
|
||||||
$this->daemonConfigurationRepository = $daemonConfigurationRepository;
|
$this->daemonConfigurationRepository = $daemonConfigurationRepository;
|
||||||
}
|
}
|
||||||
|
@ -98,8 +89,7 @@ class ServerTransferController extends Controller
|
||||||
*
|
*
|
||||||
* @throws \Throwable
|
* @throws \Throwable
|
||||||
*/
|
*/
|
||||||
public function transfer(Request $request, Server $server)
|
public function transfer(Request $request, Server $server) {
|
||||||
{
|
|
||||||
$validatedData = $request->validate([
|
$validatedData = $request->validate([
|
||||||
'node_id' => 'required|exists:nodes,id',
|
'node_id' => 'required|exists:nodes,id',
|
||||||
'allocation_id' => 'required|bail|unique:servers|exists:allocations,id',
|
'allocation_id' => 'required|bail|unique:servers|exists:allocations,id',
|
||||||
|
@ -116,9 +106,6 @@ class ServerTransferController extends Controller
|
||||||
// Check if the selected daemon is online.
|
// Check if the selected daemon is online.
|
||||||
$this->daemonConfigurationRepository->setNode($node)->getSystemInformation();
|
$this->daemonConfigurationRepository->setNode($node)->getSystemInformation();
|
||||||
|
|
||||||
// Suspend the server and request an archive to be created.
|
|
||||||
//$this->suspensionService->toggle($server, 'suspend');
|
|
||||||
|
|
||||||
// Create a new ServerTransfer entry.
|
// Create a new ServerTransfer entry.
|
||||||
$transfer = new ServerTransfer;
|
$transfer = new ServerTransfer;
|
||||||
|
|
||||||
|
|
|
@ -58,16 +58,32 @@ class WebsocketController extends ClientApiController
|
||||||
throw new HttpException(Response::HTTP_FORBIDDEN, 'You do not have permission to connect to this server\'s websocket.');
|
throw new HttpException(Response::HTTP_FORBIDDEN, 'You do not have permission to connect to this server\'s websocket.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$permissions = $this->permissionsService->handle($server, $user);
|
||||||
|
|
||||||
|
$node = null;
|
||||||
|
|
||||||
|
// Check if there is a transfer query param asking to connect to the target node's websocket.
|
||||||
|
if ($request->query('transfer', 'false') === 'true') {
|
||||||
|
// Check if the user has permissions to receive transfer logs.
|
||||||
|
if (! in_array('admin.websocket.transfer', $permissions)) {
|
||||||
|
throw new HttpException(Response::HTTP_FORBIDDEN, 'You do not have permission to get transfer logs');
|
||||||
|
}
|
||||||
|
|
||||||
|
$node = $server->transfer->newNode;
|
||||||
|
} else {
|
||||||
|
$node = $server->node;
|
||||||
|
}
|
||||||
|
|
||||||
$token = $this->jwtService
|
$token = $this->jwtService
|
||||||
->setExpiresAt(CarbonImmutable::now()->addMinutes(10))
|
->setExpiresAt(CarbonImmutable::now()->addMinutes(10))
|
||||||
->setClaims([
|
->setClaims([
|
||||||
'user_id' => $request->user()->id,
|
'user_id' => $request->user()->id,
|
||||||
'server_uuid' => $server->uuid,
|
'server_uuid' => $server->uuid,
|
||||||
'permissions' => $this->permissionsService->handle($server, $user),
|
'permissions' => $permissions,
|
||||||
])
|
])
|
||||||
->handle($server->node, $user->id . $server->uuid);
|
->handle($node, $user->id . $server->uuid);
|
||||||
|
|
||||||
$socket = str_replace(['https://', 'http://'], ['wss://', 'ws://'], $server->node->getConnectionAddress());
|
$socket = str_replace(['https://', 'http://'], ['wss://', 'ws://'], $node->getConnectionAddress());
|
||||||
|
|
||||||
return new JsonResponse([
|
return new JsonResponse([
|
||||||
'data' => [
|
'data' => [
|
||||||
|
|
|
@ -58,11 +58,6 @@ class ServerTransferController extends Controller
|
||||||
*/
|
*/
|
||||||
private $configurationStructureService;
|
private $configurationStructureService;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Servers\SuspensionService
|
|
||||||
*/
|
|
||||||
private $suspensionService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Psr\Log\LoggerInterface
|
* @var \Psr\Log\LoggerInterface
|
||||||
*/
|
*/
|
||||||
|
@ -78,7 +73,6 @@ class ServerTransferController extends Controller
|
||||||
* @param \Pterodactyl\Repositories\Wings\DaemonServerRepository $daemonServerRepository
|
* @param \Pterodactyl\Repositories\Wings\DaemonServerRepository $daemonServerRepository
|
||||||
* @param \Pterodactyl\Repositories\Wings\DaemonTransferRepository $daemonTransferRepository
|
* @param \Pterodactyl\Repositories\Wings\DaemonTransferRepository $daemonTransferRepository
|
||||||
* @param \Pterodactyl\Services\Servers\ServerConfigurationStructureService $configurationStructureService
|
* @param \Pterodactyl\Services\Servers\ServerConfigurationStructureService $configurationStructureService
|
||||||
* @param \Pterodactyl\Services\Servers\SuspensionService $suspensionService
|
|
||||||
* @param \Psr\Log\LoggerInterface $writer
|
* @param \Psr\Log\LoggerInterface $writer
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
@ -89,7 +83,6 @@ class ServerTransferController extends Controller
|
||||||
DaemonServerRepository $daemonServerRepository,
|
DaemonServerRepository $daemonServerRepository,
|
||||||
DaemonTransferRepository $daemonTransferRepository,
|
DaemonTransferRepository $daemonTransferRepository,
|
||||||
ServerConfigurationStructureService $configurationStructureService,
|
ServerConfigurationStructureService $configurationStructureService,
|
||||||
SuspensionService $suspensionService,
|
|
||||||
LoggerInterface $writer
|
LoggerInterface $writer
|
||||||
) {
|
) {
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
|
@ -99,7 +92,6 @@ class ServerTransferController extends Controller
|
||||||
$this->daemonServerRepository = $daemonServerRepository;
|
$this->daemonServerRepository = $daemonServerRepository;
|
||||||
$this->daemonTransferRepository = $daemonTransferRepository;
|
$this->daemonTransferRepository = $daemonTransferRepository;
|
||||||
$this->configurationStructureService = $configurationStructureService;
|
$this->configurationStructureService = $configurationStructureService;
|
||||||
$this->suspensionService = $suspensionService;
|
|
||||||
$this->writer = $writer;
|
$this->writer = $writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,9 +179,6 @@ class ServerTransferController extends Controller
|
||||||
// Remove the new allocations.
|
// Remove the new allocations.
|
||||||
$this->allocationRepository->updateWhereIn('id', $allocationIds, ['server_id' => null]);
|
$this->allocationRepository->updateWhereIn('id', $allocationIds, ['server_id' => null]);
|
||||||
|
|
||||||
// Unsuspend the server.
|
|
||||||
//$this->suspensionService->toggle($server, 'unsuspend');
|
|
||||||
|
|
||||||
return new JsonResponse([], Response::HTTP_NO_CONTENT);
|
return new JsonResponse([], Response::HTTP_NO_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +225,6 @@ class ServerTransferController extends Controller
|
||||||
|
|
||||||
// Unsuspend the server
|
// Unsuspend the server
|
||||||
$server->load('node');
|
$server->load('node');
|
||||||
//$this->suspensionService->toggle($server, $this->suspensionService::ACTION_UNSUSPEND);
|
|
||||||
|
|
||||||
return new JsonResponse([], Response::HTTP_NO_CONTENT);
|
return new JsonResponse([], Response::HTTP_NO_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ namespace Pterodactyl\Models;
|
||||||
* @property \Carbon\Carbon $updated_at
|
* @property \Carbon\Carbon $updated_at
|
||||||
*
|
*
|
||||||
* @property \Pterodactyl\Models\Server $server
|
* @property \Pterodactyl\Models\Server $server
|
||||||
|
* @property \Pterodactyl\Models\Node $oldNode
|
||||||
|
* @property \Pterodactyl\Models\Node $newNode
|
||||||
*/
|
*/
|
||||||
class ServerTransfer extends Model
|
class ServerTransfer extends Model
|
||||||
{
|
{
|
||||||
|
@ -78,4 +80,24 @@ class ServerTransfer extends Model
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Server::class);
|
return $this->belongsTo(Server::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the source node associated with a server transfer.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||||
|
*/
|
||||||
|
public function oldNode()
|
||||||
|
{
|
||||||
|
return $this->hasOne(Node::class, 'id', 'old_node');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the target node associated with a server transfer.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||||
|
*/
|
||||||
|
public function newNode()
|
||||||
|
{
|
||||||
|
return $this->hasOne(Node::class, 'id', 'new_node');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use Webmozart\Assert\Assert;
|
||||||
use Pterodactyl\Models\Server;
|
use Pterodactyl\Models\Server;
|
||||||
use Illuminate\Database\ConnectionInterface;
|
use Illuminate\Database\ConnectionInterface;
|
||||||
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
|
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
|
||||||
|
|
||||||
class SuspensionService
|
class SuspensionService
|
||||||
{
|
{
|
||||||
|
@ -56,6 +57,11 @@ class SuspensionService
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the server is currently being transferred.
|
||||||
|
if ($server->transfer !== null) {
|
||||||
|
throw new ConflictHttpException('Server is currently being transferred');
|
||||||
|
}
|
||||||
|
|
||||||
$this->connection->transaction(function () use ($action, $server) {
|
$this->connection->transaction(function () use ($action, $server) {
|
||||||
$server->update([
|
$server->update([
|
||||||
'suspended' => $action === self::ACTION_SUSPEND,
|
'suspended' => $action === self::ACTION_SUSPEND,
|
||||||
|
|
|
@ -5,9 +5,13 @@ interface Response {
|
||||||
socket: string;
|
socket: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (server: string): Promise<Response> => {
|
export default (server: string, transfer: boolean): Promise<Response> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
http.get(`/api/client/servers/${server}/websocket`)
|
http.get(`/api/client/servers/${server}/websocket`, {
|
||||||
|
params: {
|
||||||
|
transfer,
|
||||||
|
},
|
||||||
|
})
|
||||||
.then(({ data }) => resolve({
|
.then(({ data }) => resolve({
|
||||||
token: data.data.token,
|
token: data.data.token,
|
||||||
socket: data.data.socket,
|
socket: data.data.socket,
|
||||||
|
|
|
@ -84,8 +84,6 @@ export default () => {
|
||||||
// Sent by the source node whenever the server was archived successfully.
|
// Sent by the source node whenever the server was archived successfully.
|
||||||
case 'archive':
|
case 'archive':
|
||||||
terminal.writeln(TERMINAL_PRELUDE + 'Server has been archived successfully, attempting connection to target node..\u001b[0m');
|
terminal.writeln(TERMINAL_PRELUDE + 'Server has been archived successfully, attempting connection to target node..\u001b[0m');
|
||||||
// TODO: Get WebSocket information for the target node.
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -167,7 +165,7 @@ export default () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (connected && instance) {
|
if (connected && instance) {
|
||||||
terminal.clear();
|
// terminal.clear();
|
||||||
|
|
||||||
instance.addListener('status', handlePowerChangeEvent);
|
instance.addListener('status', handlePowerChangeEvent);
|
||||||
instance.addListener('console output', handleConsoleOutput);
|
instance.addListener('console output', handleConsoleOutput);
|
||||||
|
|
28
resources/scripts/components/server/TransferListener.tsx
Normal file
28
resources/scripts/components/server/TransferListener.tsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import useWebsocketEvent from '@/plugins/useWebsocketEvent';
|
||||||
|
import { ServerContext } from '@/state/server';
|
||||||
|
|
||||||
|
const TransferListener = () => {
|
||||||
|
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
|
||||||
|
const getServer = ServerContext.useStoreActions(actions => actions.server.getServer);
|
||||||
|
const setServerFromState = ServerContext.useStoreActions(actions => actions.server.setServerFromState);
|
||||||
|
|
||||||
|
// Listen for the installation completion event and then fire off a request to fetch the updated
|
||||||
|
// server information. This allows the server to automatically become available to the user if they
|
||||||
|
// just sit on the page.
|
||||||
|
useWebsocketEvent('transfer status', (status: string) => {
|
||||||
|
if (status === 'starting') {
|
||||||
|
setServerFromState(s => ({ ...s, isTransferring: true }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status !== 'success') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getServer(uuid).catch(error => console.error(error));
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TransferListener;
|
|
@ -15,39 +15,14 @@ const reconnectErrors = [
|
||||||
export default () => {
|
export default () => {
|
||||||
let updatingToken = false;
|
let updatingToken = false;
|
||||||
const [ error, setError ] = useState<'connecting' | string>('');
|
const [ error, setError ] = useState<'connecting' | string>('');
|
||||||
|
const [ transfer, setTransfer ] = useState<boolean>(false);
|
||||||
const { connected, instance } = ServerContext.useStoreState(state => state.socket);
|
const { connected, instance } = ServerContext.useStoreState(state => state.socket);
|
||||||
const uuid = ServerContext.useStoreState(state => state.server.data?.uuid);
|
const uuid = ServerContext.useStoreState(state => state.server.data?.uuid);
|
||||||
const setServerStatus = ServerContext.useStoreActions(actions => actions.status.setServerStatus);
|
const setServerStatus = ServerContext.useStoreActions(actions => actions.status.setServerStatus);
|
||||||
const { setInstance, setConnectionState } = ServerContext.useStoreActions(actions => actions.socket);
|
const { setInstance, setConnectionState } = ServerContext.useStoreActions(actions => actions.socket);
|
||||||
|
|
||||||
const updateToken = (uuid: string, socket: Websocket) => {
|
const connect = (uuid: string, transfer = false) => {
|
||||||
if (updatingToken) return;
|
setTransfer(transfer);
|
||||||
|
|
||||||
updatingToken = true;
|
|
||||||
getWebsocketToken(uuid)
|
|
||||||
.then(data => socket.setToken(data.token, true))
|
|
||||||
.catch(error => console.error(error))
|
|
||||||
.then(() => {
|
|
||||||
updatingToken = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
connected && setError('');
|
|
||||||
}, [ connected ]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
return () => {
|
|
||||||
instance && instance.close();
|
|
||||||
};
|
|
||||||
}, [ instance ]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// If there is already an instance or there is no server, just exit out of this process
|
|
||||||
// since we don't need to make a new connection.
|
|
||||||
if (instance || !uuid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const socket = new Websocket();
|
const socket = new Websocket();
|
||||||
|
|
||||||
|
@ -76,7 +51,34 @@ export default () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
getWebsocketToken(uuid)
|
socket.on('transfer status', (status: string) => {
|
||||||
|
if (status === 'success') {
|
||||||
|
setTransfer(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status === 'starting') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This doesn't use the `setTransfer` hook as it doesn't want to work properly in this context,
|
||||||
|
// and causes all kinds of fuckery with the websocket.
|
||||||
|
let transfer = false;
|
||||||
|
if (status === 'archived') {
|
||||||
|
transfer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the current websocket connection.
|
||||||
|
socket.close();
|
||||||
|
|
||||||
|
setError('connecting');
|
||||||
|
setConnectionState(false);
|
||||||
|
setInstance(null);
|
||||||
|
|
||||||
|
connect(uuid, transfer);
|
||||||
|
});
|
||||||
|
|
||||||
|
getWebsocketToken(uuid, transfer)
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// Connect and then set the authentication token.
|
// Connect and then set the authentication token.
|
||||||
socket.setToken(data.token).connect(data.socket);
|
socket.setToken(data.token).connect(data.socket);
|
||||||
|
@ -85,6 +87,38 @@ export default () => {
|
||||||
setInstance(socket);
|
setInstance(socket);
|
||||||
})
|
})
|
||||||
.catch(error => console.error(error));
|
.catch(error => console.error(error));
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateToken = (uuid: string, socket: Websocket) => {
|
||||||
|
if (updatingToken) return;
|
||||||
|
|
||||||
|
updatingToken = true;
|
||||||
|
getWebsocketToken(uuid, transfer)
|
||||||
|
.then(data => socket.setToken(data.token, true))
|
||||||
|
.catch(error => console.error(error))
|
||||||
|
.then(() => {
|
||||||
|
updatingToken = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
connected && setError('');
|
||||||
|
}, [ connected ]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
instance && instance.close();
|
||||||
|
};
|
||||||
|
}, [ instance ]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// If there is already an instance or there is no server, just exit out of this process
|
||||||
|
// since we don't need to make a new connection.
|
||||||
|
if (instance || !uuid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(uuid);
|
||||||
}, [ uuid ]);
|
}, [ uuid ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -42,7 +42,6 @@ export default () => {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log(error);
|
|
||||||
addError({ key: 'database:create', message: httpErrorToHuman(error) });
|
addError({ key: 'database:create', message: httpErrorToHuman(error) });
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import TransferListener from '@/components/server/TransferListener';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { NavLink, Route, RouteComponentProps, Switch } from 'react-router-dom';
|
import { NavLink, Route, RouteComponentProps, Switch } from 'react-router-dom';
|
||||||
import NavigationBar from '@/components/NavigationBar';
|
import NavigationBar from '@/components/NavigationBar';
|
||||||
|
@ -128,6 +129,7 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>)
|
||||||
</SubNavigation>
|
</SubNavigation>
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
<InstallListener/>
|
<InstallListener/>
|
||||||
|
<TransferListener/>
|
||||||
<WebsocketHandler/>
|
<WebsocketHandler/>
|
||||||
{((installing || transferring) && (!rootAdmin || (rootAdmin && !location.pathname.endsWith(`/server/${id}`)))) ?
|
{((installing || transferring) && (!rootAdmin || (rootAdmin && !location.pathname.endsWith(`/server/${id}`)))) ?
|
||||||
<ScreenBlock
|
<ScreenBlock
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
<form action="{{ route('admin.servers.view.manage.suspension', $server->id) }}" method="POST">
|
<form action="{{ route('admin.servers.view.manage.suspension', $server->id) }}" method="POST">
|
||||||
{!! csrf_field() !!}
|
{!! csrf_field() !!}
|
||||||
<input type="hidden" name="action" value="suspend" />
|
<input type="hidden" name="action" value="suspend" />
|
||||||
<button type="submit" class="btn btn-warning">Suspend Server</button>
|
<button type="submit" class="btn btn-warning @if($server->transfer !== null) disabled @endif">Suspend Server</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue