add: provide backup archive feature
This commit is contained in:
@@ -32,7 +32,7 @@ const Footer = () => {
|
||||
<a href="https://git.hangman-lab.top/hzhang/HangmanLab">git</a>
|
||||
|
||||
|
||||
v0.0.8
|
||||
v0.0.10
|
||||
</span>
|
||||
)}</p>
|
||||
{
|
||||
|
||||
@@ -1,10 +1,54 @@
|
||||
import React, { useContext } from "react";
|
||||
import React, {useContext, useState} from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { AuthContext } from "../../AuthProvider";
|
||||
import "bulma/css/bulma.min.css";
|
||||
import {useConfig} from "../../ConfigProvider";
|
||||
|
||||
const MainNavigation = () => {
|
||||
const { user, login, logout } = useContext(AuthContext);
|
||||
const config = useConfig();
|
||||
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||
if (config===undefined) {
|
||||
return <div>Loading ...</div>;
|
||||
}
|
||||
const handleGetBackup = async () => {
|
||||
try{
|
||||
const response = await fetch(
|
||||
`${config.BACKEND_HOST}/api/backup/`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("accessToken")}`,
|
||||
}
|
||||
}
|
||||
);
|
||||
if(response.ok){
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
const contentDisposition = response.headers.get("Content-Disposition");
|
||||
let filename = "backup.zip";
|
||||
console.log(response.headers);
|
||||
console.log(contentDisposition);
|
||||
if (contentDisposition) {
|
||||
const match = contentDisposition.match(/filename="?([^"]+)"?/);
|
||||
console.log(match);
|
||||
if (match && match[1]) {
|
||||
console.log(match[1]);
|
||||
filename = match[1];
|
||||
}
|
||||
}
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
}else{
|
||||
alert("Failed to get backup");
|
||||
}
|
||||
} catch(err){
|
||||
console.log(err);
|
||||
alert("An error occurred while retrieving backup");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<nav className="navbar is-dark" role="navigation" aria-label="main navigation">
|
||||
@@ -54,18 +98,32 @@ const MainNavigation = () => {
|
||||
|
||||
<div className="navbar-end">
|
||||
{user && user.profile ? (
|
||||
<div className="navbar-item">
|
||||
<div className="navbar-item has-dropdown is-hoverable">
|
||||
<div className="buttons">
|
||||
<span className="button is-primary is-light">
|
||||
<span
|
||||
className="button is-primary is-light"
|
||||
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
|
||||
>
|
||||
{user.profile.name}
|
||||
</span>
|
||||
<button
|
||||
className="button is-danger"
|
||||
onClick={logout}
|
||||
type="button"
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
<div className={`navbar-dropdown ${isDropdownOpen ? "is-active" : ""}`}>
|
||||
<button
|
||||
className="button is-primary"
|
||||
onClick={handleGetBackup}
|
||||
type="button"
|
||||
>
|
||||
Get Backup
|
||||
</button>
|
||||
<button
|
||||
className="button is-danger"
|
||||
onClick={logout}
|
||||
type="button"
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user