ui(server): fix used backup count (#3526)

* ui(server): fix used backup count

* ui(server): refactor backup count code
This commit is contained in:
Matthew Penner 2021-08-04 21:34:00 -06:00 committed by GitHub
parent 7e91a33a67
commit 10b357b71e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 41 additions and 32 deletions

View file

@ -12,6 +12,7 @@ use Illuminate\Auth\Access\AuthorizationException;
use Pterodactyl\Services\Backups\DeleteBackupService; use Pterodactyl\Services\Backups\DeleteBackupService;
use Pterodactyl\Services\Backups\DownloadLinkService; use Pterodactyl\Services\Backups\DownloadLinkService;
use Pterodactyl\Services\Backups\InitiateBackupService; use Pterodactyl\Services\Backups\InitiateBackupService;
use Pterodactyl\Repositories\Eloquent\BackupRepository;
use Pterodactyl\Repositories\Wings\DaemonBackupRepository; use Pterodactyl\Repositories\Wings\DaemonBackupRepository;
use Pterodactyl\Transformers\Api\Client\BackupTransformer; use Pterodactyl\Transformers\Api\Client\BackupTransformer;
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController; use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
@ -20,34 +21,21 @@ use Pterodactyl\Http\Requests\Api\Client\Servers\Backups\StoreBackupRequest;
class BackupController extends ClientApiController class BackupController extends ClientApiController
{ {
/** private InitiateBackupService $initiateBackupService;
* @var \Pterodactyl\Services\Backups\InitiateBackupService private DeleteBackupService $deleteBackupService;
*/ private DownloadLinkService $downloadLinkService;
private $initiateBackupService; private DaemonBackupRepository $daemonRepository;
private BackupRepository $repository;
/**
* @var \Pterodactyl\Services\Backups\DeleteBackupService
*/
private $deleteBackupService;
/**
* @var \Pterodactyl\Services\Backups\DownloadLinkService
*/
private $downloadLinkService;
/**
* @var \Pterodactyl\Repositories\Wings\DaemonBackupRepository
*/
private $repository;
/** /**
* BackupController constructor. * BackupController constructor.
*/ */
public function __construct( public function __construct(
DaemonBackupRepository $repository, DaemonBackupRepository $daemonRepository,
DeleteBackupService $deleteBackupService, DeleteBackupService $deleteBackupService,
InitiateBackupService $initiateBackupService, InitiateBackupService $initiateBackupService,
DownloadLinkService $downloadLinkService DownloadLinkService $downloadLinkService,
BackupRepository $repository
) { ) {
parent::__construct(); parent::__construct();
@ -55,10 +43,11 @@ class BackupController extends ClientApiController
$this->initiateBackupService = $initiateBackupService; $this->initiateBackupService = $initiateBackupService;
$this->deleteBackupService = $deleteBackupService; $this->deleteBackupService = $deleteBackupService;
$this->downloadLinkService = $downloadLinkService; $this->downloadLinkService = $downloadLinkService;
$this->daemonRepository = $daemonRepository;
} }
/** /**
* Returns all of the backups for a given server instance in a paginated * Returns all the backups for a given server instance in a paginated
* result set. * result set.
* *
* @throws \Illuminate\Auth\Access\AuthorizationException * @throws \Illuminate\Auth\Access\AuthorizationException
@ -73,6 +62,9 @@ class BackupController extends ClientApiController
return $this->fractal->collection($server->backups()->paginate($limit)) return $this->fractal->collection($server->backups()->paginate($limit))
->transformWith($this->getTransformer(BackupTransformer::class)) ->transformWith($this->getTransformer(BackupTransformer::class))
->addMeta([
'backup_count' => $this->repository->getNonFailedBackups($server)->count(),
])
->toArray(); ->toArray();
} }
@ -242,7 +234,7 @@ class BackupController extends ClientApiController
// actions against it via the Panel API. // actions against it via the Panel API.
$server->update(['status' => Server::STATUS_RESTORING_BACKUP]); $server->update(['status' => Server::STATUS_RESTORING_BACKUP]);
$this->repository->setServer($server)->restore($backup, $url ?? null, $request->input('truncate')); $this->daemonRepository->setServer($server)->restore($backup, $url ?? null, $request->input('truncate'));
}); });
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT); return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);

View file

@ -4,6 +4,8 @@ namespace Pterodactyl\Repositories\Eloquent;
use Carbon\Carbon; use Carbon\Carbon;
use Pterodactyl\Models\Backup; use Pterodactyl\Models\Backup;
use Pterodactyl\Models\Server;
use Illuminate\Database\Eloquent\Relations\HasMany;
class BackupRepository extends EloquentRepository class BackupRepository extends EloquentRepository
{ {
@ -33,4 +35,17 @@ class BackupRepository extends EloquentRepository
->get() ->get()
->toBase(); ->toBase();
} }
/**
* Returns a query filtering only non-failed backups for a specific server.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function getNonFailedBackups(Server $server): HasMany
{
return $server->backups()->where(function ($query) {
$query->whereNull('completed_at')
->orWhere('is_successful', true);
});
}
} }

View file

@ -9,6 +9,7 @@ use Pterodactyl\Models\Backup;
use Pterodactyl\Models\Server; use Pterodactyl\Models\Server;
use Illuminate\Database\ConnectionInterface; use Illuminate\Database\ConnectionInterface;
use Pterodactyl\Extensions\Backups\BackupManager; use Pterodactyl\Extensions\Backups\BackupManager;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Pterodactyl\Repositories\Eloquent\BackupRepository; use Pterodactyl\Repositories\Eloquent\BackupRepository;
use Pterodactyl\Repositories\Wings\DaemonBackupRepository; use Pterodactyl\Repositories\Wings\DaemonBackupRepository;
use Pterodactyl\Exceptions\Service\Backup\TooManyBackupsException; use Pterodactyl\Exceptions\Service\Backup\TooManyBackupsException;
@ -134,10 +135,7 @@ class InitiateBackupService
// Check if the server has reached or exceeded its backup limit. // Check if the server has reached or exceeded its backup limit.
// completed_at == null will cover any ongoing backups, while is_successful == true will cover any completed backups. // completed_at == null will cover any ongoing backups, while is_successful == true will cover any completed backups.
$successful = $server->backups()->where(function ($query) { $successful = $this->repository->getNonFailedBackups($server);
$query->whereNull('completed_at')
->orWhere('is_successful', true);
});
if (!$server->backup_limit || $successful->count() >= $server->backup_limit) { if (!$server->backup_limit || $successful->count() >= $server->backup_limit) {
// Do not allow the user to continue if this server is already at its limit and can't override. // Do not allow the user to continue if this server is already at its limit and can't override.
if (!$override || $server->backup_limit <= 0) { if (!$override || $server->backup_limit <= 0) {

View file

@ -12,16 +12,19 @@ interface ctx {
export const Context = createContext<ctx>({ page: 1, setPage: () => 1 }); export const Context = createContext<ctx>({ page: 1, setPage: () => 1 });
type BackupResponse = PaginatedResult<ServerBackup> & { backupCount: number };
export default () => { export default () => {
const { page } = useContext(Context); const { page } = useContext(Context);
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid); const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
return useSWR<PaginatedResult<ServerBackup>>([ 'server:backups', uuid, page ], async () => { return useSWR<BackupResponse>([ 'server:backups', uuid, page ], async () => {
const { data } = await http.get(`/api/client/servers/${uuid}/backups`, { params: { page } }); const { data } = await http.get(`/api/client/servers/${uuid}/backups`, { params: { page } });
return ({ return ({
items: (data.data || []).map(rawDataToServerBackup), items: (data.data || []).map(rawDataToServerBackup),
pagination: getPaginationSet(data.meta.pagination), pagination: getPaginationSet(data.meta.pagination),
backupCount: data.meta.backup_count,
}); });
}); });
}; };

View file

@ -65,12 +65,12 @@ const BackupContainer = () => {
} }
<Can action={'backup.create'}> <Can action={'backup.create'}>
<div css={tw`mt-6 sm:flex items-center justify-end`}> <div css={tw`mt-6 sm:flex items-center justify-end`}>
{(backupLimit > 0 && backups.pagination.total > 0) && {(backupLimit > 0 && backups.backupCount > 0) &&
<p css={tw`text-sm text-neutral-300 mb-4 sm:mr-6 sm:mb-0`}> <p css={tw`text-sm text-neutral-300 mb-4 sm:mr-6 sm:mb-0`}>
{backups.pagination.total} of {backupLimit} backups have been created for this server. {backups.backupCount} of {backupLimit} backups have been created for this server.
</p> </p>
} }
{backupLimit > 0 && backupLimit !== backups.pagination.total && {backupLimit > 0 && backupLimit > backups.backupCount &&
<CreateBackupButton css={tw`w-full sm:w-auto`}/> <CreateBackupButton css={tw`w-full sm:w-auto`}/>
} }
</div> </div>

View file

@ -58,6 +58,7 @@ export default ({ backup }: Props) => {
.then(() => mutate(data => ({ .then(() => mutate(data => ({
...data, ...data,
items: data.items.filter(b => b.uuid !== backup.uuid), items: data.items.filter(b => b.uuid !== backup.uuid),
backupCount: data.backupCount - 1,
}), false)) }), false))
.catch(error => { .catch(error => {
console.error(error); console.error(error);

View file

@ -81,7 +81,7 @@ export default () => {
clearFlashes('backups:create'); clearFlashes('backups:create');
createServerBackup(uuid, values) createServerBackup(uuid, values)
.then(backup => { .then(backup => {
mutate(data => ({ ...data, items: data.items.concat(backup) }), false); mutate(data => ({ ...data, items: data.items.concat(backup), backupCount: data.backupCount + 1 }), false);
setVisible(false); setVisible(false);
}) })
.catch(error => { .catch(error => {