ui(admin): add delete egg variable button
This commit is contained in:
parent
b2aa05dc07
commit
6df90a12d8
5 changed files with 65 additions and 5 deletions
|
@ -3,6 +3,9 @@
|
||||||
namespace Pterodactyl\Http\Controllers\Api\Application\Eggs;
|
namespace Pterodactyl\Http\Controllers\Api\Application\Eggs;
|
||||||
|
|
||||||
use Pterodactyl\Models\Egg;
|
use Pterodactyl\Models\Egg;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Pterodactyl\Models\EggVariable;
|
||||||
use Illuminate\Database\ConnectionInterface;
|
use Illuminate\Database\ConnectionInterface;
|
||||||
use Pterodactyl\Services\Eggs\Variables\VariableUpdateService;
|
use Pterodactyl\Services\Eggs\Variables\VariableUpdateService;
|
||||||
use Pterodactyl\Services\Eggs\Variables\VariableCreationService;
|
use Pterodactyl\Services\Eggs\Variables\VariableCreationService;
|
||||||
|
@ -62,4 +65,17 @@ class EggVariableController extends ApplicationApiController
|
||||||
->transformWith(EggVariableTransformer::class)
|
->transformWith(EggVariableTransformer::class)
|
||||||
->toArray();
|
->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a single egg variable.
|
||||||
|
*/
|
||||||
|
public function delete(Request $request, Egg $egg, EggVariable $eggVariable): Response
|
||||||
|
{
|
||||||
|
EggVariable::query()
|
||||||
|
->where('id', $eggVariable->id)
|
||||||
|
->where('egg_id', $egg->id)
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
return $this->returnNoContent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
9
resources/scripts/api/admin/eggs/deleteEggVariable.ts
Normal file
9
resources/scripts/api/admin/eggs/deleteEggVariable.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import http from '@/api/http';
|
||||||
|
|
||||||
|
export default (eggId: number, variableId: number): Promise<void> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
http.delete(`/api/application/eggs/${eggId}/variables/${variableId}`)
|
||||||
|
.then(() => resolve())
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
};
|
|
@ -10,16 +10,17 @@ interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
padding?: boolean;
|
padding?: boolean;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
button?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AdminBox = ({ icon, title, className, padding, children }: Props) => {
|
const AdminBox = ({ icon, title, className, padding, children, button }: Props) => {
|
||||||
if (padding === undefined) {
|
if (padding === undefined) {
|
||||||
padding = true;
|
padding = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div css={tw`rounded shadow-md bg-neutral-700`} className={className}>
|
<div css={tw`rounded shadow-md bg-neutral-700`} className={className}>
|
||||||
<div css={tw`bg-neutral-900 rounded-t px-4 py-3 border-b border-black`}>
|
<div css={tw`flex flex-row bg-neutral-900 rounded-t px-4 py-3 border-b border-black`}>
|
||||||
{typeof title === 'string' ?
|
{typeof title === 'string' ?
|
||||||
<p css={tw`text-sm uppercase`}>
|
<p css={tw`text-sm uppercase`}>
|
||||||
{icon && <FontAwesomeIcon icon={icon} css={tw`mr-2 text-neutral-300`}/>}{title}
|
{icon && <FontAwesomeIcon icon={icon} css={tw`mr-2 text-neutral-300`}/>}{title}
|
||||||
|
@ -27,6 +28,7 @@ const AdminBox = ({ icon, title, className, padding, children }: Props) => {
|
||||||
:
|
:
|
||||||
title
|
title
|
||||||
}
|
}
|
||||||
|
{button}
|
||||||
</div>
|
</div>
|
||||||
<div css={padding ? tw`px-4 py-3` : undefined}>
|
<div css={padding ? tw`px-4 py-3` : undefined}>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import deleteEggVariable from '@/api/admin/eggs/deleteEggVariable';
|
||||||
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
|
@ -83,11 +84,26 @@ export function EggVariableForm ({ prefix }: { prefix: string }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function EggVariableBox ({ variable, prefix }: { variable: EggVariable, prefix: string }) {
|
function EggVariableBox ({ onDeleteClick, variable, prefix }: { onDeleteClick: () => void, variable: EggVariable, prefix: string }) {
|
||||||
const { isSubmitting } = useFormikContext();
|
const { isSubmitting } = useFormikContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AdminBox css={tw`relative w-full`} title={<p css={tw`text-sm uppercase`}>{variable.name}</p>}>
|
<AdminBox
|
||||||
|
css={tw`relative w-full`}
|
||||||
|
title={<p css={tw`text-sm uppercase`}>{variable.name}</p>}
|
||||||
|
button={
|
||||||
|
<button
|
||||||
|
type={'button'}
|
||||||
|
css={tw`ml-auto text-neutral-500 hover:text-neutral-300`}
|
||||||
|
onClick={onDeleteClick}
|
||||||
|
>
|
||||||
|
{/* TODO: Change to heroicon 'x' */}
|
||||||
|
<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>
|
||||||
|
}
|
||||||
|
>
|
||||||
<SpinnerOverlay visible={isSubmitting}/>
|
<SpinnerOverlay visible={isSubmitting}/>
|
||||||
|
|
||||||
<EggVariableForm prefix={prefix}/>
|
<EggVariableForm prefix={prefix}/>
|
||||||
|
@ -117,7 +133,23 @@ export default function EggVariablesContainer ({ egg }: { egg: Egg }) {
|
||||||
<Form>
|
<Form>
|
||||||
<div css={tw`flex flex-col mb-16`}>
|
<div css={tw`flex flex-col mb-16`}>
|
||||||
<div css={tw`grid grid-cols-1 lg:grid-cols-2 gap-x-8 gap-y-6`}>
|
<div css={tw`grid grid-cols-1 lg:grid-cols-2 gap-x-8 gap-y-6`}>
|
||||||
{egg.relations?.variables?.map((v, i) => <EggVariableBox key={i} prefix={`[${i}].`} variable={v}/>)}
|
{egg.relations?.variables?.map((v, i) => (
|
||||||
|
<EggVariableBox
|
||||||
|
key={i}
|
||||||
|
prefix={`[${i}].`}
|
||||||
|
variable={v}
|
||||||
|
onDeleteClick={() => {
|
||||||
|
deleteEggVariable(egg.id, v.id)
|
||||||
|
.then(async () => await mutate(egg => ({
|
||||||
|
...egg!,
|
||||||
|
relations: {
|
||||||
|
variables: egg!.relations.variables!.filter(v2 => v.id === v2.id),
|
||||||
|
},
|
||||||
|
})))
|
||||||
|
.catch(error => clearAndAddHttpError({ key: 'egg', error }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div css={tw`bg-neutral-700 rounded shadow-md py-2 px-4 mt-6`}>
|
<div css={tw`bg-neutral-700 rounded shadow-md py-2 px-4 mt-6`}>
|
||||||
|
|
|
@ -41,6 +41,7 @@ Route::group(['prefix' => '/eggs'], function () {
|
||||||
Route::patch('/{egg}/variables', [\Pterodactyl\Http\Controllers\Api\Application\Eggs\EggVariableController::class, 'update']);
|
Route::patch('/{egg}/variables', [\Pterodactyl\Http\Controllers\Api\Application\Eggs\EggVariableController::class, 'update']);
|
||||||
|
|
||||||
Route::delete('/{egg}', [\Pterodactyl\Http\Controllers\Api\Application\Eggs\EggController::class, 'delete']);
|
Route::delete('/{egg}', [\Pterodactyl\Http\Controllers\Api\Application\Eggs\EggController::class, 'delete']);
|
||||||
|
Route::delete('/{egg}/variables/{eggVariable}', [\Pterodactyl\Http\Controllers\Api\Application\Eggs\EggVariableController::class, 'delete']);
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue