From 03a365a948434f30eae040bd2b6b099e061efbd7 Mon Sep 17 00:00:00 2001 From: Ibrahim Ansari Date: Sat, 26 Aug 2023 01:24:48 +0530 Subject: [PATCH] Support new tar compression APIs. --- imports/dashboard/files/fileManager.tsx | 10 +++--- imports/dashboard/files/fileUtils.ts | 2 ++ imports/dashboard/files/massActionDialog.tsx | 34 ++++++++++++++++++-- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/imports/dashboard/files/fileManager.tsx b/imports/dashboard/files/fileManager.tsx index 44ad3fa..96c4428 100644 --- a/imports/dashboard/files/fileManager.tsx +++ b/imports/dashboard/files/fileManager.tsx @@ -21,7 +21,7 @@ import useKy from '../../helpers/useKy' import Editor from './editor' import Overlay from './overlay' -import { joinPath, normalisePath, parentPath, uploadFormData } from './fileUtils' +import { archiveRegex, joinPath, normalisePath, parentPath, uploadFormData } from './fileUtils' import UploadButton from './uploadButton' import FileList, { type File } from './fileList' import MassActionDialog from './massActionDialog' @@ -283,10 +283,12 @@ const FileManager = (props: { setMenuOpen('') setFetching(true) const a = await ky.post(`server/${server}/decompress?path=${euc(path + menuOpen)}`, { - body: path + menuOpen.split('.').slice(0, -1).join('.') + body: path + menuOpen.replace(archiveRegex, '') }) .json<{ error: string }>() - if (a.error) setMessage(a.error) + if (a.error?.includes('ZIP file') && !menuOpen.endsWith('.zip')) { + setMessage('Archive failed to decompress! Update Octyne to v1.2+ to decompress this file.') + } else if (a.error) setMessage(a.error) setFetching(false) setMenuOpen('') fetchFiles() @@ -535,7 +537,7 @@ const FileManager = (props: { setModifyFileDialogOpen('copy')}>Copy Delete {!selectedFile.folder && Download} - {!selectedFile.folder && selectedFile.name.endsWith('.zip') && ( + {!selectedFile.folder && archiveRegex.test(selectedFile.name) && ( Decompress )} diff --git a/imports/dashboard/files/fileUtils.ts b/imports/dashboard/files/fileUtils.ts index 8af5806..cc2848f 100644 --- a/imports/dashboard/files/fileUtils.ts +++ b/imports/dashboard/files/fileUtils.ts @@ -34,3 +34,5 @@ export const uploadFormData = async ( xhr.setRequestHeader('Authorization', localStorage.getItem('ecthelion:token') ?? '') xhr.send(formData) }) + +export const archiveRegex = /(\.zip|\.tar(\.(gz|bz2|bz|xz|zst))?|\.tgz|\.tbz2|\.tbz|\.txz|\.tzst)$/i diff --git a/imports/dashboard/files/massActionDialog.tsx b/imports/dashboard/files/massActionDialog.tsx index bc0304d..efa679f 100644 --- a/imports/dashboard/files/massActionDialog.tsx +++ b/imports/dashboard/files/massActionDialog.tsx @@ -1,7 +1,8 @@ import React, { useState } from 'react' import { type KyInstance } from 'ky/distribution/types/ky' import { - Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Button, TextField + Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Button, TextField, + Select, InputLabel, FormControl, MenuItem } from '@mui/material' const MassActionDialog = ({ @@ -17,6 +18,7 @@ const MassActionDialog = ({ path: string ky: KyInstance }): JSX.Element => { + const [archiveType, setArchiveType] = useState<'zip' | 'tar' | 'tar.gz' | 'tar.xz' | 'tar.zst'>('zip') const [newPath, setNewPath] = useState('') const move = operation === 'move' ? 'Move' : operation === 'compress' ? 'Compress' : 'Copy' const moved = operation === 'move' ? 'Moved' : operation === 'compress' ? 'Compressed' : 'Copied' @@ -27,13 +29,22 @@ const MassActionDialog = ({ if (operation === 'compress') { setOverlay(`Compressing ${files.length} files on the server.`) const json = files.map(f => path + f) - ky.post(`${endpoint}?path=${encodeURIComponent(path + newPath + '.zip')}`, { json }).then(res => { + const archiveTypeParam = archiveType.startsWith('tar') ? '&archiveType=tar&compress=' + ( + archiveType === 'tar.gz' ? 'gzip' + : archiveType === 'tar.xz' ? 'xz' + : archiveType === 'tar.zst' ? 'zstd' + : 'false' + ) : '' + const uri = archiveTypeParam === 'zip' ? endpoint : endpoint + '/v2' + ky.post(`${uri}?path=${encodeURIComponent(path + newPath + '.' + archiveType)}${archiveTypeParam}`, { json }).then(res => { setOverlay('') if (res.ok) { reload() setMessage('Compressed all files successfully!') + } else if (res.status === 404 && archiveTypeParam !== 'zip') { + setMessage('Compressing `tar` archives requires Octyne v1.2 or newer!') } else setMessage('Failed to compress the files!') - }).catch(() => setMessage('Failed to compress the files!')) + }).catch(() => { setOverlay(''); setMessage('Failed to compress the files!') }) return } let left = files.length @@ -80,6 +91,23 @@ const MassActionDialog = ({ onChange={e => setNewPath(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); handleOperation() } }} /> + {operation === 'compress' && ( + + Archive Type + + + )}