add restore functionality
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { CharacterContext } from "@/app/context/Context";
|
||||
import { CharacterContext, SessionContext } from "@/app/context/Context";
|
||||
import { Button } from "@mui/material";
|
||||
import { useContext } from "react";
|
||||
|
||||
@@ -9,7 +9,7 @@ export const DowloadButton = () => {
|
||||
href={`data:text/json;charset=utf-8,${encodeURIComponent(
|
||||
JSON.stringify(characters)
|
||||
)}`}
|
||||
download="pi-avanto-tk-characters.json"
|
||||
download={`eve-pi-characters.json`}
|
||||
>
|
||||
Backup
|
||||
</Button>
|
||||
|
21
src/app/components/Backup/UploadButton.tsx
Normal file
21
src/app/components/Backup/UploadButton.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Box, Button } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { UploadDialog } from "./UploadDialog";
|
||||
|
||||
export const UploadButton = () => {
|
||||
const [uploadDialogOpen, setUploadDialogOpen] = useState(false);
|
||||
return (
|
||||
<Box>
|
||||
<Button
|
||||
style={{ width: "100%" }}
|
||||
onClick={() => setUploadDialogOpen(true)}
|
||||
>
|
||||
Restore
|
||||
</Button>
|
||||
<UploadDialog
|
||||
open={uploadDialogOpen}
|
||||
closeDialog={() => setUploadDialogOpen(false)}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
72
src/app/components/Backup/UploadDialog.tsx
Normal file
72
src/app/components/Backup/UploadDialog.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import DialogTitle from "@mui/material/DialogTitle";
|
||||
import Dialog from "@mui/material/Dialog";
|
||||
import Button from "@mui/material/Button";
|
||||
import { DialogActions, DialogContent, Typography } from "@mui/material";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { CharacterContext } from "@/app/context/Context";
|
||||
import { AccessToken } from "@/types";
|
||||
|
||||
export const UploadDialog = ({
|
||||
open,
|
||||
closeDialog,
|
||||
}: {
|
||||
open: boolean;
|
||||
closeDialog: () => void;
|
||||
}) => {
|
||||
const [file, setFile] = useState();
|
||||
|
||||
const fileReader = new FileReader();
|
||||
const { restoreCharacters } = useContext(CharacterContext);
|
||||
|
||||
const error = new Error("Invalid input");
|
||||
|
||||
const validate = (characters: AccessToken[]) => {
|
||||
characters.forEach((c) => {
|
||||
if (!c.access_token) throw error;
|
||||
if (!c.expires_at) throw error;
|
||||
if (!c.refresh_token) throw error;
|
||||
if (!c.character) throw error;
|
||||
if (!c.character.characterId) throw error;
|
||||
if (!c.character.name) throw error;
|
||||
});
|
||||
|
||||
return characters;
|
||||
};
|
||||
useEffect(() => {
|
||||
if (file) {
|
||||
fileReader.onload = (event) => {
|
||||
if (!event || event.target === null) return;
|
||||
const jsonOutput = event.target.result?.toString();
|
||||
if (jsonOutput) restoreCharacters(validate(JSON.parse(jsonOutput)));
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
fileReader.readAsText(file);
|
||||
}
|
||||
}, [file]);
|
||||
|
||||
const changeHandler = (event: any) => {
|
||||
setFile(event.target.files[0]);
|
||||
};
|
||||
return (
|
||||
<Dialog open={open} onClose={closeDialog}>
|
||||
<DialogTitle>Restore your character list</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography>
|
||||
The list must be exported from the same EVE PI instance to work!
|
||||
</Typography>
|
||||
<input
|
||||
type="file"
|
||||
name="file"
|
||||
accept=".json"
|
||||
onChange={changeHandler}
|
||||
style={{ paddingTop: "1rem" }}
|
||||
/>
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions>
|
||||
<Button onClick={closeDialog}>Close</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
@@ -7,6 +7,7 @@ import { CharacterContext } from "../context/Context";
|
||||
import { DowloadButton } from "./Backup/DowloadButton";
|
||||
import { DiscordButton } from "./Discord/DiscordButton";
|
||||
import { GitHubButton } from "./Github/GitHubButton";
|
||||
import { UploadButton } from "./Backup/UploadButton";
|
||||
|
||||
interface Grouped {
|
||||
[key: string]: AccessToken[];
|
||||
@@ -28,6 +29,7 @@ export const MainGrid = ({ sessionReady }: { sessionReady: boolean }) => {
|
||||
<Stack direction="row" spacing={1}>
|
||||
<LoginButton />
|
||||
<DowloadButton />
|
||||
<UploadButton />
|
||||
<DiscordButton />
|
||||
<GitHubButton />
|
||||
</Stack>
|
||||
|
@@ -5,10 +5,12 @@ export const CharacterContext = createContext<{
|
||||
characters: AccessToken[];
|
||||
deleteCharacter: (character: AccessToken) => void;
|
||||
updateCharacter: (character: AccessToken, update: CharacterUpdate) => void;
|
||||
restoreCharacters: (characters: AccessToken[]) => void;
|
||||
}>({
|
||||
characters: [],
|
||||
deleteCharacter: () => {},
|
||||
updateCharacter: () => {},
|
||||
restoreCharacters: () => {},
|
||||
});
|
||||
|
||||
export const SessionContext = createContext<{
|
||||
|
@@ -73,6 +73,10 @@ const Home = () => {
|
||||
return characters;
|
||||
};
|
||||
|
||||
const restoreCharacters = (characters: AccessToken[]) => {
|
||||
refreshSession(characters).then(saveCharacters).then(setCharacters);
|
||||
};
|
||||
|
||||
// Initialize EVE PI
|
||||
useEffect(() => {
|
||||
fetch("api/env")
|
||||
@@ -106,6 +110,7 @@ const Home = () => {
|
||||
characters,
|
||||
deleteCharacter,
|
||||
updateCharacter,
|
||||
restoreCharacters,
|
||||
}}
|
||||
>
|
||||
<MainGrid sessionReady={sessionReady} />
|
||||
|
Reference in New Issue
Block a user