Skip to content

Commit

Permalink
Merge branch 'interface-rewrite' of https://github.com/KelvinTegelaar…
Browse files Browse the repository at this point in the history
…/CIPP into interface-rewrite
  • Loading branch information
KelvinTegelaar committed Oct 23, 2024
2 parents 1d18206 + 8f96c36 commit 7899cfe
Show file tree
Hide file tree
Showing 3 changed files with 271 additions and 12 deletions.
14 changes: 6 additions & 8 deletions src/components/CippSettings/CippBackupSettings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import CippButtonCard from "/src/components/CippCards/CippButtonCard";
import { ApiPostCall } from "/src/api/ApiCall";
import { useDialog } from "/src/hooks/use-dialog";
import { SettingsBackupRestore } from "@mui/icons-material";
import Link from "next/link";

const CippBackupSettings = () => {
const createDialog = useDialog();
Expand All @@ -16,12 +17,9 @@ const CippBackupSettings = () => {
<Button
variant="contained"
size="small"
onClick={() =>
console.log(
"open backup dialog, table with create backup, download backup and restore backup options"
)
}
component={Link}
disabled={backupAction.isPending}
href="/cipp/settings/backup"
>
<SvgIcon fontSize="small" style={{ marginRight: 4 }}>
<SettingsBackupRestore />
Expand All @@ -36,9 +34,9 @@ const CippBackupSettings = () => {
<>
<CippButtonCard title="Backup" cardSx={{ height: "100%" }} CardButton={<BackupButtons />}>
<Typography variant="body2">
Use this button to backup the system configuration for CIPP. This will not include
authentication information or extension configuration. You can also set an automated daily
backup schedule by clicking the button below. This will create a scheduled task for you.s
Manage the system configuration backups for CIPP. This will not include authentication
information or extension configuration. You can also set an automated daily backup
schedule.
</Typography>
</CippButtonCard>
</>
Expand Down
261 changes: 261 additions & 0 deletions src/pages/cipp/settings/backup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
import { Box, Button, CardContent, Grid, Stack, Typography, Skeleton } from "@mui/material";
import { Layout as DashboardLayout } from "/src/layouts/index.js";

import CippPageCard from "../../../components/CippCards/CippPageCard";
import { ApiGetCall, ApiPostCall } from "../../../api/ApiCall";
import { CippInfoBar } from "../../../components/CippCards/CippInfoBar";
import {
ArrowCircleRight,
CloudDownload,
CloudUpload,
EventRepeat,
History,
ManageHistory,
NextPlan,
SettingsBackupRestore,
Storage,
} from "@mui/icons-material";
import ReactTimeAgo from "react-time-ago";
import { CippDataTable } from "../../../components/CippTable/CippDataTable";
import { CippApiResults } from "../../../components/CippComponents/CippApiResults";

const Page = () => {
const backupList = ApiGetCall({
url: "/api/ExecListBackup",
data: {
NameOnly: true,
},
queryKey: "BackupList",
});

const scheduledBackup = ApiGetCall({
url: "/api/ListScheduledItems",
data: {
Name: "Automated CIPP Backup",
},
queryKey: "ScheduledBackup",
});

const backupAction = ApiPostCall({
urlFromData: true,
});

const runBackup = ApiPostCall({
urlFromData: true,
relatedQueryKeys: ["BackupList", "ScheduledBackup"],
});

const enableBackupSchedule = ApiPostCall({
urlFromData: true,
relatedQueryKeys: ["ScheduledBackup"],
});

const NextBackupRun = (props) => {
const date = new Date(props.date * 1000);
console.log(date);
if (isNaN(date)) {
return "Not Scheduled";
} else {
return <ReactTimeAgo date={date} />;
}
};

const handleCreateBackup = () => {
runBackup.mutate({
url: "/api/ExecRunBackup",
data: {},
});
};

const handleEnableScheduledBackup = () => {
enableBackupSchedule.mutate({
url: "/api/ExecSetCIPPAutoBackup",
data: {
Enabled: true,
},
});
};

const handleRestoreBackupUpload = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (e) => {
const backup = JSON.parse(e.target.result);
backupAction.mutate(
{
url: "/api/ExecRestoreBackup",
data: backup,
},
{
onSuccess: () => {
e.target.value = null;
},
}
);
};
reader.readAsText(file);
};

const handleDownloadBackupAction = (row) => {
backupAction.mutate(
{
url: `/api/ExecListBackup?BackupName=${row.BackupName}`,
data: {},
},
{
onSuccess: (data) => {
console.log(data.data);
const jsonString = data?.data?.[0]?.Backup;
if (!jsonString) {
return;
}
console.log(jsonString);
const blob = new Blob([jsonString], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `${row.BackupName}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
},
}
);
};

const actions = [
{
label: "Restore Backup",
icon: <SettingsBackupRestore />,
type: "POST",
url: "/api/ExecRestoreBackup",
data: { BackupName: "BackupName" },
confirmText: "Are you sure you want to restore this backup?",
relatedQueryKeys: ["BackupList"],
multiPost: false,
},
{
label: "Download Backup",
icon: <CloudDownload />,
confirmText: "Do you want to download this backup?",
customFunction: handleDownloadBackupAction,
},
];

return (
<>
<CippPageCard title="CIPP Backup" backButtonTitle="Settings">
<CardContent>
<Grid container spacing={2}>
<Grid item xs={12}>
<CippInfoBar
isFetching={backupList.isFetching}
data={[
{
icon: <Storage />,
name: "Backup Count",
data: backupList.data?.length,
},
{
icon: <History />,
name: "Last Backup",
data: backupList.data?.[0]?.Timestamp ? (
<ReactTimeAgo date={backupList.data?.[0]?.Timestamp} />
) : (
"No Backups"
),
},
{
icon: <EventRepeat />,
name: "Automatic Backups",
data:
scheduledBackup.data?.[0]?.Name === "Automated CIPP Backup"
? "Enabled"
: "Disabled",
},
{
icon: <NextPlan />,
name: "Next Backup",
data: <NextBackupRun date={scheduledBackup.data?.[0]?.ScheduledTime} />,
},
]}
/>
</Grid>
</Grid>
<Typography variant="body2" sx={{ mt: 3, px: 3 }}>
Backups are stored in the storage account associated with your CIPP instance. You can
download or restore specific points in time from the list below. Enable automatic
updates to have CIPP create daily backups.
</Typography>
{backupList.isSuccess ? (
<Box sx={{ mt: 3 }}>
<CippApiResults apiObject={runBackup} />
<CippApiResults apiObject={enableBackupSchedule} />
<CippApiResults apiObject={backupAction} />
<CippDataTable
title="Backup List"
data={backupList.data}
simpleColumns={["BackupName", "Timestamp"]}
actions={actions}
cardButton={
<>
<Stack spacing={2} direction="row">
<Button
variant="contained"
color="primary"
startIcon={<ArrowCircleRight />}
onClick={handleCreateBackup}
>
Run Backup
</Button>
<Button
component="label"
variant="contained"
color="primary"
startIcon={<CloudUpload />}
>
Restore From File
<input
hidden
accept=".json"
type="file"
id="backup-upload"
onChange={handleRestoreBackupUpload}
/>
</Button>
{scheduledBackup.isSuccess &&
scheduledBackup.data?.[0]?.Name !== "Automated CIPP Backup" && (
<>
<Button
variant="contained"
color="primary"
startIcon={<ManageHistory />}
onClick={handleEnableScheduledBackup}
>
Schedule Backups
</Button>
</>
)}
</Stack>
</>
}
/>
</Box>
) : (
<Box sx={{ mt: 3 }}>
<Stack spacing={2}>
<Skeleton variant="rectangular" width="100%" height={100} />
<Skeleton variant="rectangular" width="100%" height={400} />
</Stack>
</Box>
)}
</CardContent>
</CippPageCard>
</>
);
};

Page.getLayout = (page) => <DashboardLayout>{page}</DashboardLayout>;

export default Page;
8 changes: 4 additions & 4 deletions src/utils/get-cipp-formatting.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ export const getCippFormatting = (data, cellName, type) => {
);
}

const timeAgoArray = ["ExecutedTime", "ScheduledTime"];
const timeAgoArray = ["ExecutedTime", "ScheduledTime", "Timestamp"];
if (timeAgoArray.includes(cellName)) {
//convert data from unixtime to date. If conversion fails, return "No Data".
const date = new Date(data * 1000);
if (isNaN(date)) {
// Convert data from Unix time to date. If conversion fails, return "No Data".
const date = typeof data === "number" ? new Date(data * 1000) : new Date(data);
if (isNaN(date.getTime())) {
return isText ? (
"No Data"
) : (
Expand Down

0 comments on commit 7899cfe

Please sign in to comment.