Add UI for restoring backup checkpoint text
This commit is contained in:
parent
ddc4c8e54b
commit
187df97590
3 changed files with 41 additions and 4 deletions
|
@ -7,18 +7,19 @@ import ModalContext from '@/context/ModalContext';
|
||||||
type Props = {
|
type Props = {
|
||||||
title: string;
|
title: string;
|
||||||
buttonText: string;
|
buttonText: string;
|
||||||
children: string;
|
|
||||||
onConfirmed: () => void;
|
onConfirmed: () => void;
|
||||||
showSpinnerOverlay?: boolean;
|
showSpinnerOverlay?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ConfirmationModal = ({ title, children, buttonText, onConfirmed }: Props) => {
|
const ConfirmationModal: React.FC<Props> = ({ title, children, buttonText, onConfirmed }) => {
|
||||||
const { dismiss } = useContext(ModalContext);
|
const { dismiss } = useContext(ModalContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h2 css={tw`text-2xl mb-6`}>{title}</h2>
|
<h2 css={tw`text-2xl mb-6`}>{title}</h2>
|
||||||
<p css={tw`text-sm`}>{children}</p>
|
<div css={tw`text-neutral-300`}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
<div css={tw`flex flex-wrap items-center justify-end mt-8`}>
|
<div css={tw`flex flex-wrap items-center justify-end mt-8`}>
|
||||||
<Button isSecondary onClick={() => dismiss()} css={tw`w-full sm:w-auto border-transparent`}>
|
<Button isSecondary onClick={() => dismiss()} css={tw`w-full sm:w-auto border-transparent`}>
|
||||||
Cancel
|
Cancel
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { faCloudDownloadAlt, faEllipsisH, faLock, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
import { faBoxOpen, faCloudDownloadAlt, faEllipsisH, faLock, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import DropdownMenu, { DropdownButtonRow } from '@/components/elements/DropdownMenu';
|
import DropdownMenu, { DropdownButtonRow } from '@/components/elements/DropdownMenu';
|
||||||
import getBackupDownloadUrl from '@/api/server/backups/getBackupDownloadUrl';
|
import getBackupDownloadUrl from '@/api/server/backups/getBackupDownloadUrl';
|
||||||
|
@ -13,6 +13,7 @@ import tw from 'twin.macro';
|
||||||
import getServerBackups from '@/api/swr/getServerBackups';
|
import getServerBackups from '@/api/swr/getServerBackups';
|
||||||
import { ServerBackup } from '@/api/server/types';
|
import { ServerBackup } from '@/api/server/types';
|
||||||
import { ServerContext } from '@/state/server';
|
import { ServerContext } from '@/state/server';
|
||||||
|
import Input from '@/components/elements/Input';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
backup: ServerBackup;
|
backup: ServerBackup;
|
||||||
|
@ -23,6 +24,7 @@ export default ({ backup }: Props) => {
|
||||||
const [ loading, setLoading ] = useState(false);
|
const [ loading, setLoading ] = useState(false);
|
||||||
const [ visible, setVisible ] = useState(false);
|
const [ visible, setVisible ] = useState(false);
|
||||||
const [ deleteVisible, setDeleteVisible ] = useState(false);
|
const [ deleteVisible, setDeleteVisible ] = useState(false);
|
||||||
|
const [ restoreVisible, setRestoreVisible ] = useState(false);
|
||||||
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
||||||
const { mutate } = getServerBackups();
|
const { mutate } = getServerBackups();
|
||||||
|
|
||||||
|
@ -69,6 +71,33 @@ export default ({ backup }: Props) => {
|
||||||
checksum={backup.checksum}
|
checksum={backup.checksum}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
<ConfirmationModal
|
||||||
|
visible={restoreVisible}
|
||||||
|
title={'Restore this backup?'}
|
||||||
|
buttonText={'Restore backup'}
|
||||||
|
onConfirmed={() => null}
|
||||||
|
onModalDismissed={() => setRestoreVisible(false)}
|
||||||
|
>
|
||||||
|
<p css={tw`text-neutral-300`}>
|
||||||
|
This server will be stopped in order to restore the backup. Once the backup has started you will
|
||||||
|
not be able to control the server power state, access the file manager, or create additional backups
|
||||||
|
until it has completed.
|
||||||
|
</p>
|
||||||
|
<p css={tw`text-neutral-300 mt-4`}>
|
||||||
|
Are you sure you want to continue?
|
||||||
|
</p>
|
||||||
|
<p css={tw`mt-4 -mb-2 bg-neutral-900 p-3 rounded`}>
|
||||||
|
<label htmlFor={'restore_truncate'} css={tw`text-base text-neutral-200 flex items-center cursor-pointer`}>
|
||||||
|
<Input
|
||||||
|
type={'checkbox'}
|
||||||
|
css={tw`text-red-500! w-5! h-5! mr-2`}
|
||||||
|
id={'restore_truncate'}
|
||||||
|
value={'true'}
|
||||||
|
/>
|
||||||
|
Remove all files and folders before restoring this backup.
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</ConfirmationModal>
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
visible={deleteVisible}
|
visible={deleteVisible}
|
||||||
title={'Delete this backup?'}
|
title={'Delete this backup?'}
|
||||||
|
@ -98,6 +127,12 @@ export default ({ backup }: Props) => {
|
||||||
<span css={tw`ml-2`}>Download</span>
|
<span css={tw`ml-2`}>Download</span>
|
||||||
</DropdownButtonRow>
|
</DropdownButtonRow>
|
||||||
</Can>
|
</Can>
|
||||||
|
<Can action={'backup.restore'}>
|
||||||
|
<DropdownButtonRow onClick={() => setRestoreVisible(true)}>
|
||||||
|
<FontAwesomeIcon fixedWidth icon={faBoxOpen} css={tw`text-xs`}/>
|
||||||
|
<span css={tw`ml-2`}>Restore</span>
|
||||||
|
</DropdownButtonRow>
|
||||||
|
</Can>
|
||||||
<DropdownButtonRow onClick={() => setVisible(true)}>
|
<DropdownButtonRow onClick={() => setVisible(true)}>
|
||||||
<FontAwesomeIcon fixedWidth icon={faLock} css={tw`text-xs`}/>
|
<FontAwesomeIcon fixedWidth icon={faLock} css={tw`text-xs`}/>
|
||||||
<span css={tw`ml-2`}>Checksum</span>
|
<span css={tw`ml-2`}>Checksum</span>
|
||||||
|
|
|
@ -104,6 +104,7 @@ Route::group(['prefix' => '/servers/{server}', 'middleware' => [AuthenticateServ
|
||||||
Route::post('/', 'Servers\BackupController@store');
|
Route::post('/', 'Servers\BackupController@store');
|
||||||
Route::get('/{backup}', 'Servers\BackupController@view');
|
Route::get('/{backup}', 'Servers\BackupController@view');
|
||||||
Route::get('/{backup}/download', 'Servers\BackupController@download');
|
Route::get('/{backup}/download', 'Servers\BackupController@download');
|
||||||
|
Route::post('/{backup}/restore', 'Servers\BackupController@restore');
|
||||||
Route::delete('/{backup}', 'Servers\BackupController@delete');
|
Route::delete('/{backup}', 'Servers\BackupController@delete');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue