Add UI for restoring backup checkpoint text

This commit is contained in:
Dane Everitt 2021-01-17 18:25:13 -08:00
parent ddc4c8e54b
commit 187df97590
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
3 changed files with 41 additions and 4 deletions

View file

@ -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

View file

@ -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>

View file

@ -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');
}); });