From 2653321fc20d09fd5d47e54f34496d003b462279 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 11 Jul 2020 16:00:30 -0700 Subject: [PATCH] Support renaming multiple files at once --- .../Api/Client/Servers/FileController.php | 16 ++++++++-------- .../Client/Servers/Files/RenameFileRequest.php | 7 +++++-- app/Repositories/Wings/DaemonFileRepository.php | 12 ++++++------ .../files/{renameFile.ts => renameFiles.ts} | 6 +++--- .../components/server/files/RenameFileModal.tsx | 9 ++++++--- routes/api-client.php | 14 +++++++------- 6 files changed, 35 insertions(+), 29 deletions(-) rename resources/scripts/api/server/files/{renameFile.ts => renameFiles.ts} (60%) diff --git a/app/Http/Controllers/Api/Client/Servers/FileController.php b/app/Http/Controllers/Api/Client/Servers/FileController.php index b6e2eed56..60fc88777 100644 --- a/app/Http/Controllers/Api/Client/Servers/FileController.php +++ b/app/Http/Controllers/Api/Client/Servers/FileController.php @@ -67,7 +67,7 @@ class FileController extends ClientApiController * * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException */ - public function listDirectory(ListFilesRequest $request, Server $server): array + public function directory(ListFilesRequest $request, Server $server): array { try { $contents = $this->fileRepository @@ -90,7 +90,7 @@ class FileController extends ClientApiController * @return \Illuminate\Http\Response * @throws \Pterodactyl\Exceptions\Http\Server\FileSizeTooLargeException */ - public function getFileContents(GetFileContentsRequest $request, Server $server): Response + public function contents(GetFileContentsRequest $request, Server $server): Response { return new Response( $this->fileRepository->setServer($server)->getContent( @@ -140,7 +140,7 @@ class FileController extends ClientApiController * @param \Pterodactyl\Models\Server $server * @return \Illuminate\Http\JsonResponse */ - public function writeFileContents(WriteFileContentRequest $request, Server $server): JsonResponse + public function write(WriteFileContentRequest $request, Server $server): JsonResponse { $this->fileRepository->setServer($server)->putContent( $request->get('file'), @@ -157,7 +157,7 @@ class FileController extends ClientApiController * @param \Pterodactyl\Models\Server $server * @return \Illuminate\Http\JsonResponse */ - public function createFolder(CreateFolderRequest $request, Server $server): JsonResponse + public function create(CreateFolderRequest $request, Server $server): JsonResponse { $this->fileRepository ->setServer($server) @@ -173,11 +173,11 @@ class FileController extends ClientApiController * @param \Pterodactyl\Models\Server $server * @return \Illuminate\Http\JsonResponse */ - public function renameFile(RenameFileRequest $request, Server $server): JsonResponse + public function rename(RenameFileRequest $request, Server $server): JsonResponse { $this->fileRepository ->setServer($server) - ->renameFile($request->input('rename_from'), $request->input('rename_to')); + ->renameFiles($request->input('root'), $request->input('files')); return new JsonResponse([], Response::HTTP_NO_CONTENT); } @@ -189,7 +189,7 @@ class FileController extends ClientApiController * @param \Pterodactyl\Models\Server $server * @return \Illuminate\Http\JsonResponse */ - public function copyFile(CopyFileRequest $request, Server $server): JsonResponse + public function copy(CopyFileRequest $request, Server $server): JsonResponse { $this->fileRepository ->setServer($server) @@ -203,7 +203,7 @@ class FileController extends ClientApiController * @param \Pterodactyl\Models\Server $server * @return array */ - public function compressFiles(CompressFilesRequest $request, Server $server): array + public function compress(CompressFilesRequest $request, Server $server): array { $file = $this->fileRepository->setServer($server) ->compressFiles( diff --git a/app/Http/Requests/Api/Client/Servers/Files/RenameFileRequest.php b/app/Http/Requests/Api/Client/Servers/Files/RenameFileRequest.php index 2e828754b..c8529a35e 100644 --- a/app/Http/Requests/Api/Client/Servers/Files/RenameFileRequest.php +++ b/app/Http/Requests/Api/Client/Servers/Files/RenameFileRequest.php @@ -25,8 +25,11 @@ class RenameFileRequest extends ClientApiRequest implements ClientPermissionsReq public function rules(): array { return [ - 'rename_from' => 'string|required', - 'rename_to' => 'string|required', + 'root' => 'required|nullable|string', + 'files' => 'required|array', + 'files.*' => 'array', + 'files.*.to' => 'required|string', + 'files.*.from' => 'required|string', ]; } } diff --git a/app/Repositories/Wings/DaemonFileRepository.php b/app/Repositories/Wings/DaemonFileRepository.php index 3f506d149..7a0934b10 100644 --- a/app/Repositories/Wings/DaemonFileRepository.php +++ b/app/Repositories/Wings/DaemonFileRepository.php @@ -109,11 +109,11 @@ class DaemonFileRepository extends DaemonRepository /** * Renames or moves a file on the remote machine. * - * @param string $from - * @param string $to + * @param string|null $root + * @param array $files * @return \Psr\Http\Message\ResponseInterface */ - public function renameFile(string $from, string $to): ResponseInterface + public function renameFiles(?string $root, array $files): ResponseInterface { Assert::isInstanceOf($this->server, Server::class); @@ -121,8 +121,8 @@ class DaemonFileRepository extends DaemonRepository sprintf('/api/servers/%s/files/rename', $this->server->uuid), [ 'json' => [ - 'rename_from' => urldecode($from), - 'rename_to' => urldecode($to), + 'root' => $root ?? '/', + 'files' => $files, ], ] ); @@ -163,7 +163,7 @@ class DaemonFileRepository extends DaemonRepository sprintf('/api/servers/%s/files/delete', $this->server->uuid), [ 'json' => [ - 'root' => $root, + 'root' => $root ?? '/', 'files' => $files, ], ] diff --git a/resources/scripts/api/server/files/renameFile.ts b/resources/scripts/api/server/files/renameFiles.ts similarity index 60% rename from resources/scripts/api/server/files/renameFile.ts rename to resources/scripts/api/server/files/renameFiles.ts index 6b307c837..d106a8e71 100644 --- a/resources/scripts/api/server/files/renameFile.ts +++ b/resources/scripts/api/server/files/renameFiles.ts @@ -5,11 +5,11 @@ interface Data { renameTo: string; } -export default (uuid: string, { renameFrom, renameTo }: Data): Promise => { +export default (uuid: string, directory: string, files: Data[]): Promise => { return new Promise((resolve, reject) => { http.put(`/api/client/servers/${uuid}/files/rename`, { - rename_from: renameFrom, - rename_to: renameTo, + root: directory, + files: files.map(f => ({ from: f.renameFrom, to: f.renameTo })), }) .then(() => resolve()) .catch(reject); diff --git a/resources/scripts/components/server/files/RenameFileModal.tsx b/resources/scripts/components/server/files/RenameFileModal.tsx index d7b9d3e8a..c124da318 100644 --- a/resources/scripts/components/server/files/RenameFileModal.tsx +++ b/resources/scripts/components/server/files/RenameFileModal.tsx @@ -3,7 +3,7 @@ import Modal, { RequiredModalProps } from '@/components/elements/Modal'; import { Form, Formik, FormikHelpers } from 'formik'; import Field from '@/components/elements/Field'; import { join } from 'path'; -import renameFile from '@/api/server/files/renameFile'; +import renameFiles from '@/api/server/files/renameFiles'; import { ServerContext } from '@/state/server'; import { FileObject } from '@/api/server/files/loadDirectory'; import tw from 'twin.macro'; @@ -21,10 +21,12 @@ type Props = RequiredModalProps & { file: FileObject; useMoveTerminology?: boole export default ({ file, useMoveTerminology, ...props }: Props) => { const { uuid } = useServer(); const { mutate } = useFileManagerSwr(); - const { clearAndAddHttpError } = useFlash(); + const { clearFlashes, clearAndAddHttpError } = useFlash(); const directory = ServerContext.useStoreState(state => state.files.directory); const submit = ({ name }: FormikValues, { setSubmitting }: FormikHelpers) => { + clearFlashes('files'); + const len = name.split('/').length; if (!useMoveTerminology && len === 1) { // Rename the file within this directory. @@ -36,7 +38,8 @@ export default ({ file, useMoveTerminology, ...props }: Props) => { const renameFrom = join(directory, file.name); const renameTo = join(directory, name); - renameFile(uuid, { renameFrom, renameTo }) + + renameFiles(uuid, directory, [ { renameFrom, renameTo } ]) .then(() => props.onDismissed()) .catch(error => { mutate(); diff --git a/routes/api-client.php b/routes/api-client.php index f9d84545a..9b57cf0c4 100644 --- a/routes/api-client.php +++ b/routes/api-client.php @@ -53,15 +53,15 @@ Route::group(['prefix' => '/servers/{server}', 'middleware' => [AuthenticateServ }); Route::group(['prefix' => '/files'], function () { - Route::get('/list', 'Servers\FileController@listDirectory'); - Route::get('/contents', 'Servers\FileController@getFileContents'); + Route::get('/list', 'Servers\FileController@directory'); + Route::get('/contents', 'Servers\FileController@contents'); Route::get('/download', 'Servers\FileController@download'); - Route::put('/rename', 'Servers\FileController@renameFile'); - Route::post('/copy', 'Servers\FileController@copyFile'); - Route::post('/write', 'Servers\FileController@writeFileContents'); - Route::post('/compress', 'Servers\FileController@compressFiles'); + Route::put('/rename', 'Servers\FileController@rename'); + Route::post('/copy', 'Servers\FileController@copy'); + Route::post('/write', 'Servers\FileController@write'); + Route::post('/compress', 'Servers\FileController@compress'); Route::post('/delete', 'Servers\FileController@delete'); - Route::post('/create-folder', 'Servers\FileController@createFolder'); + Route::post('/create-folder', 'Servers\FileController@create'); }); Route::group(['prefix' => '/schedules'], function () {