mirror of
https://github.com/tachiyomiorg/tachiyomi-extensions-inspector.git
synced 2025-02-03 11:02:34 +01:00
front-end UI done
This commit is contained in:
parent
0c79f207c3
commit
455a35f8ae
@ -192,7 +192,6 @@ object LegacyBackupImport : LegacyBackupBase() {
|
||||
it[status] = fetchedManga.status
|
||||
if (fetchedManga.thumbnail_url != null && fetchedManga.thumbnail_url!!.isNotEmpty())
|
||||
it[MangaTable.thumbnail_url] = fetchedManga.thumbnail_url
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,8 @@ import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.future.future
|
||||
import mu.KotlinLogging
|
||||
import java.io.IOException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/*
|
||||
@ -326,7 +328,7 @@ object JavalinSetup {
|
||||
ctx.json(getCategoryMangaList(categoryId))
|
||||
}
|
||||
|
||||
// expects a Tachiyomi legacy backup json to be uploaded
|
||||
// expects a Tachiyomi legacy backup json in the body
|
||||
app.post("/api/v1/backup/legacy/import") { ctx ->
|
||||
ctx.result(
|
||||
future {
|
||||
@ -335,7 +337,16 @@ object JavalinSetup {
|
||||
)
|
||||
}
|
||||
|
||||
// returns a Tachiyomi legacy backup json created from the current database
|
||||
// expects a Tachiyomi legacy backup json as a file upload, the file must be named "backup.json"
|
||||
app.post("/api/v1/backup/legacy/import/file") { ctx ->
|
||||
ctx.result(
|
||||
future {
|
||||
restoreLegacyBackup(ctx.uploadedFile("backup.json")!!.content)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// returns a Tachiyomi legacy backup json created from the current database as a json body
|
||||
app.get("/api/v1/backup/legacy/export") { ctx ->
|
||||
ctx.contentType("application/json")
|
||||
ctx.result(
|
||||
@ -352,5 +363,27 @@ object JavalinSetup {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// returns a Tachiyomi legacy backup json created from the current database as a file
|
||||
app.get("/api/v1/backup/legacy/export/file") { ctx ->
|
||||
ctx.contentType("application/json")
|
||||
val sdf = SimpleDateFormat("yyyy-MM-dd_HH-mm")
|
||||
val currentDate = sdf.format(Date())
|
||||
|
||||
ctx.header("Content-Disposition", "attachment; filename=\"tachidesk_$currentDate.json\"")
|
||||
ctx.result(
|
||||
future {
|
||||
createLegacyBackup(
|
||||
BackupFlags(
|
||||
includeManga = true,
|
||||
includeCategories = true,
|
||||
includeChapters = true,
|
||||
includeTracking = true,
|
||||
includeHistory = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
"@types/react-lazyload": "^3.1.0",
|
||||
"axios": "^0.21.1",
|
||||
"file-selector": "^0.2.4",
|
||||
"fontsource-roboto": "^4.0.0",
|
||||
"react": "^17.0.1",
|
||||
"react-beautiful-dnd": "^13.0.0",
|
||||
|
@ -25,6 +25,7 @@ import DarkTheme from './context/DarkTheme';
|
||||
import Library from './screens/Library';
|
||||
import Settings from './screens/Settings';
|
||||
import Categories from './screens/settings/Categories';
|
||||
import Backup from './screens/settings/Backup';
|
||||
import useLocalStorage from './util/useLocalStorage';
|
||||
|
||||
export default function App() {
|
||||
@ -103,6 +104,9 @@ export default function App() {
|
||||
<Route path="/settings/categories">
|
||||
<Categories />
|
||||
</Route>
|
||||
<Route path="/settings/backup">
|
||||
<Backup />
|
||||
</Route>
|
||||
<Route path="/settings">
|
||||
<DarkTheme.Provider value={darkThemeContext}>
|
||||
<Settings />
|
||||
|
@ -16,15 +16,11 @@ import {
|
||||
DialogContentText, IconButton, ListItemSecondaryAction, Switch, TextField,
|
||||
ListItemIcon, ListItemText,
|
||||
} from '@material-ui/core';
|
||||
import ListItem, { ListItemProps } from '@material-ui/core/ListItem';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import NavbarContext from '../context/NavbarContext';
|
||||
import DarkTheme from '../context/DarkTheme';
|
||||
import useLocalStorage from '../util/useLocalStorage';
|
||||
|
||||
function ListItemLink(props: ListItemProps<'a', { button?: true }>) {
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
return <ListItem button component="a" {...props} />;
|
||||
}
|
||||
import ListItemLink from '../util/ListItemLink';
|
||||
|
||||
export default function Settings() {
|
||||
const { setTitle, setAction } = useContext(NavbarContext);
|
||||
@ -58,6 +54,12 @@ export default function Settings() {
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Categories" />
|
||||
</ListItemLink>
|
||||
<ListItemLink href="/settings/backup">
|
||||
<ListItemIcon>
|
||||
<InboxIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Backup" />
|
||||
</ListItemLink>
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<Brightness6Icon />
|
||||
|
91
webUI/react/src/screens/settings/Backup.tsx
Normal file
91
webUI/react/src/screens/settings/Backup.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import { ListItemIcon } from '@material-ui/core';
|
||||
import List from '@material-ui/core/List';
|
||||
import InboxIcon from '@material-ui/icons/Inbox';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import ListItemText from '@material-ui/core/ListItemText';
|
||||
import { fromEvent } from 'file-selector';
|
||||
import ListItemLink from '../../util/ListItemLink';
|
||||
import NavbarContext from '../../context/NavbarContext';
|
||||
import client from '../../util/client';
|
||||
|
||||
export default function Backup() {
|
||||
const { setTitle, setAction } = useContext(NavbarContext);
|
||||
useEffect(() => { setTitle('Backup'); setAction(<></>); }, []);
|
||||
|
||||
const { baseURL } = client.defaults;
|
||||
|
||||
const submitBackup = (file: File) => {
|
||||
file.text()
|
||||
.then(
|
||||
(fileContent: string) => {
|
||||
client.post('/api/v1/backup/legacy/import',
|
||||
fileContent, { headers: { 'Content-Type': 'application/json' } });
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const dropHandler = async (e: Event) => {
|
||||
e.preventDefault();
|
||||
const files = await fromEvent(e);
|
||||
|
||||
submitBackup(files[0] as File);
|
||||
};
|
||||
|
||||
const dragOverHandler = (e: Event) => {
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('drop', dropHandler);
|
||||
document.addEventListener('dragover', dragOverHandler);
|
||||
|
||||
const input = document.getElementById('backup-file');
|
||||
input?.addEventListener('change', async (evt) => {
|
||||
const files = await fromEvent(evt);
|
||||
submitBackup(files[0] as File);
|
||||
});
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('drop', dropHandler);
|
||||
document.removeEventListener('dragover', dragOverHandler);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<List style={{ padding: 0 }}>
|
||||
<ListItemLink href={`${baseURL}/api/v1/backup/legacy/export/file`}>
|
||||
<ListItemIcon>
|
||||
<InboxIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="Create Legacy Backup"
|
||||
secondary="Backup library as a Tachiyomi legacy backup"
|
||||
/>
|
||||
</ListItemLink>
|
||||
<ListItem button onClick={() => document.getElementById('backup-file')?.click()}>
|
||||
<ListItemIcon>
|
||||
<InboxIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="Restore Legacy Backup"
|
||||
secondary="You can also drop the backup file anywhere to restore"
|
||||
/>
|
||||
<input
|
||||
type="file"
|
||||
name="backup.json"
|
||||
id="backup-file"
|
||||
style={{ display: 'none' }}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
|
||||
);
|
||||
}
|
14
webUI/react/src/util/ListItemLink.tsx
Normal file
14
webUI/react/src/util/ListItemLink.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import React from 'react';
|
||||
import ListItem, { ListItemProps } from '@material-ui/core/ListItem';
|
||||
|
||||
export default function ListItemLink(props: ListItemProps<'a', { button?: true }>) {
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
return <ListItem button component="a" {...props} />;
|
||||
}
|
@ -5136,6 +5136,13 @@ file-loader@6.1.1:
|
||||
loader-utils "^2.0.0"
|
||||
schema-utils "^3.0.0"
|
||||
|
||||
file-selector@^0.2.4:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-0.2.4.tgz#7b98286f9dbb9925f420130ea5ed0a69238d4d80"
|
||||
integrity sha512-ZDsQNbrv6qRi1YTDOEWzf5J2KjZ9KMI1Q2SGeTkCJmNNW25Jg4TW4UMcmoqcg4WrAyKRcpBXdbWRxkfrOzVRbA==
|
||||
dependencies:
|
||||
tslib "^2.0.3"
|
||||
|
||||
file-uri-to-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||
|
Loading…
x
Reference in New Issue
Block a user