feat: Import improvements (#3064)
* feat: Split and simplify import/export pages in prep for more options * minor fixes * File operations for imports * test * icons
This commit is contained in:
105
app/scenes/Settings/Export.tsx
Normal file
105
app/scenes/Settings/Export.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { DownloadIcon } from "outline-icons";
|
||||
import * as React from "react";
|
||||
import { useTranslation, Trans } from "react-i18next";
|
||||
import FileOperation from "~/models/FileOperation";
|
||||
import Button from "~/components/Button";
|
||||
import Heading from "~/components/Heading";
|
||||
import HelpText from "~/components/HelpText";
|
||||
import PaginatedList from "~/components/PaginatedList";
|
||||
import Scene from "~/components/Scene";
|
||||
import Subheading from "~/components/Subheading";
|
||||
import useCurrentUser from "~/hooks/useCurrentUser";
|
||||
import useStores from "~/hooks/useStores";
|
||||
import useToasts from "~/hooks/useToasts";
|
||||
import FileOperationListItem from "./components/FileOperationListItem";
|
||||
|
||||
function Export() {
|
||||
const { t } = useTranslation();
|
||||
const user = useCurrentUser();
|
||||
const { fileOperations, collections } = useStores();
|
||||
const { showToast } = useToasts();
|
||||
const [isLoading, setLoading] = React.useState(false);
|
||||
const [isExporting, setExporting] = React.useState(false);
|
||||
|
||||
const handleExport = React.useCallback(
|
||||
async (ev: React.SyntheticEvent) => {
|
||||
ev.preventDefault();
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
await collections.export();
|
||||
setExporting(true);
|
||||
showToast(t("Export in progress…"));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
},
|
||||
[t, collections, showToast]
|
||||
);
|
||||
|
||||
const handleDelete = React.useCallback(
|
||||
async (fileOperation: FileOperation) => {
|
||||
try {
|
||||
await fileOperations.delete(fileOperation);
|
||||
showToast(t("Export deleted"));
|
||||
} catch (err) {
|
||||
showToast(err.message, {
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
},
|
||||
[fileOperations, showToast, t]
|
||||
);
|
||||
|
||||
return (
|
||||
<Scene title={t("Export")} icon={<DownloadIcon color="currentColor" />}>
|
||||
<Heading>{t("Export")}</Heading>
|
||||
<HelpText>
|
||||
<Trans
|
||||
defaults="A full export might take some time, consider exporting a single document or collection. The exported data is a zip of your documents in Markdown format. You may leave this page once the export has started – we will email a link to <em>{{ userEmail }}</em> when it’s complete."
|
||||
values={{
|
||||
userEmail: user.email,
|
||||
}}
|
||||
components={{
|
||||
em: <strong />,
|
||||
}}
|
||||
/>
|
||||
</HelpText>
|
||||
<Button
|
||||
type="submit"
|
||||
onClick={handleExport}
|
||||
disabled={isLoading || isExporting}
|
||||
primary
|
||||
>
|
||||
{isExporting
|
||||
? t("Export Requested")
|
||||
: isLoading
|
||||
? `${t("Requesting Export")}…`
|
||||
: t("Export Data")}
|
||||
</Button>
|
||||
<br />
|
||||
<PaginatedList
|
||||
items={fileOperations.exports}
|
||||
fetch={fileOperations.fetchPage}
|
||||
options={{
|
||||
type: "export",
|
||||
}}
|
||||
heading={
|
||||
<Subheading>
|
||||
<Trans>Recent exports</Trans>
|
||||
</Subheading>
|
||||
}
|
||||
renderItem={(item) => (
|
||||
<FileOperationListItem
|
||||
key={item.id}
|
||||
fileOperation={item}
|
||||
handleDelete={handleDelete}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Scene>
|
||||
);
|
||||
}
|
||||
|
||||
export default observer(Export);
|
||||
Reference in New Issue
Block a user