frontend/app/ProjectEntryList/AssetFolderProjectBackups.tsx (217 lines of code) (raw):
import React, { useEffect, useState } from "react";
import { RouteComponentProps, useHistory } from "react-router";
import { Helmet } from "react-helmet";
import {
Button,
Dialog,
DialogActions,
DialogContentText,
DialogTitle,
Grid,
IconButton,
List,
Paper,
Tooltip,
Typography,
DialogContent,
} from "@material-ui/core";
import { Breadcrumb } from "@guardian/pluto-headers";
import { ArrowBack, PermMedia, WarningRounded } from "@material-ui/icons";
import { getProject, getAssetFolderProjectFiles } from "./helpers";
import clsx from "clsx";
import AssetFolderBackupEntry from "./AssetFolderBackupEntry";
import { useGuardianStyles } from "~/misc/utils";
import axios from "axios";
import {
SystemNotification,
SystemNotifcationKind,
} from "@guardian/pluto-headers";
declare var deploymentRootPath: string;
const AssetFolderProjectBackups: React.FC<RouteComponentProps<{
itemid: string;
}>> = (props) => {
const [project, setProject] = useState<Project | undefined>(undefined);
const [dialogErrString, setDialogErrString] = useState<string | undefined>(
undefined
);
const [openDialog, setOpenDialog] = useState(false);
const [backupFiles, setBackupFiles] = useState<AssetFolderFileEntry[]>([]);
const history = useHistory();
const classes = useGuardianStyles();
useEffect(() => {
const loadProject = async () => {
const p = await getProject(Number(props.match.params.itemid));
setProject(p);
};
loadProject().catch((err) => {
console.error(err);
setDialogErrString(
`Could not load backups for project ${props.match.params.itemid}, it probably does not exist. See the javascript console for more details.`
);
});
}, [props.match.params.itemid]);
const sortFileEntryFunc = (
a: AssetFolderFileEntry,
b: AssetFolderFileEntry
) => a.mtime.localeCompare(b.mtime);
useEffect(() => {
if (project) {
getAssetFolderProjectFiles(project.id).then((fileList) => {
setBackupFiles(fileList.sort(sortFileEntryFunc));
});
}
}, [project]);
const handleClickOpenDialog = () => {
setOpenDialog(true);
};
const handleCloseDialog = () => {
setOpenDialog(false);
};
const handleConfirmUpload = () => {
handleCloseDialog();
handleRestore();
};
const handleRestore = async () => {
try {
const request =
"/api/project/" + props.match.params.itemid + "/restoreForAssetFolder";
const response = await axios.put(request, null, {
headers: {
"Content-Type": "application/json",
},
});
console.log(response.data);
SystemNotification.open(
SystemNotifcationKind.Success,
`${response.data.detail}`
);
} catch (error) {
console.error("Error restoring file:", error);
SystemNotification.open(
SystemNotifcationKind.Error,
`Failed to restore project: ${error}`
);
}
};
return (
<>
{project ? (
<Helmet>
<title>[{project.title}] Backups</title>
</Helmet>
) : null}
<Grid
container
justifyContent="space-between"
style={{ marginBottom: "0.8em" }}
>
<Grid item>
{project ? (
<Breadcrumb
projectId={project?.id}
plutoCoreBaseUri={`${deploymentRootPath.replace(/\/+$/, "")}`}
/>
) : undefined}
</Grid>
<Grid item>
<Button
color="secondary"
variant="contained"
onClick={handleClickOpenDialog}
>
Restore
</Button>
{/* Confirmation Dialog */}
<Dialog
open={openDialog}
onClose={handleCloseDialog}
aria-labelledby="update-file-dialog-title"
aria-describedby="update-file-dialog-description"
>
<DialogTitle id="update-file-dialog-title">
Confirm Restoration of Backed up Project Files:
</DialogTitle>
<DialogContent>
<DialogContentText id="update-file-dialog-description">
You are about to restore all the backed up project files shown
on this page. This will result in a folder being created in the
project's asset folder named "RestoredProjectFiles", and within
that a list of all Cubase/Audition files we have backed up. Once
you have identified which project file you need, please move it
out of this folder and into the root of project’s asset folder,
before you carry on working with it.
<br />
<br />
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleCloseDialog} color="primary">
Cancel
</Button>
<Button onClick={handleConfirmUpload} color="primary" autoFocus>
Proceed
</Button>
</DialogActions>
</Dialog>
</Grid>
<Grid item>
<Grid container spacing={2}>
<Grid item>
<Tooltip title="Back to project page">
<IconButton
onClick={() => history.push(`/project/${project?.id}`)}
>
<ArrowBack />
</IconButton>
</Tooltip>
</Grid>
<Grid item>
<Tooltip title="See project's media">
<IconButton
onClick={() =>
window.location.assign(`/vs/project/${project?.id}`)
}
>
<PermMedia />
</IconButton>
</Tooltip>
</Grid>
</Grid>
</Grid>
</Grid>
{project ? (
<Paper elevation={3}>
<List>
{backupFiles.map((f, idx) => (
<AssetFolderBackupEntry
key={idx}
fileId={f.id}
filepath={f.filepath}
version={f.version}
/>
))}
</List>
<Grid
container
className={classes.centeredDiv}
justifyContent="space-around"
>
<Grid item>
{backupFiles.length == 0 ? (
<Typography className={classes.emphasised}>
<WarningRounded
className={clsx(classes.warningIcon, classes.inlineIcon)}
/>
This project has not been backed up yet
</Typography>
) : undefined}
</Grid>
</Grid>
</Paper>
) : undefined}
{dialogErrString ? (
<Dialog open={!!dialogErrString}>
<DialogTitle>Could not load backups information</DialogTitle>
<DialogContentText>{dialogErrString}</DialogContentText>
<DialogActions>
<Button variant="contained" onClick={() => history.goBack()}>
Go back
</Button>
</DialogActions>
</Dialog>
) : undefined}
</>
);
};
export default AssetFolderProjectBackups;