You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
5.0 KiB
TypeScript

// SPDX-FileCopyrightText: © 2017 EteSync Authors
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from "react";
import * as Etebase from "etebase";
import { Redirect, useLocation } from "react-router";
import Button from "@material-ui/core/Button";
import Alert from "@material-ui/lab/Alert";
import { routeResolver } from "./App";
import Container from "./widgets/Container";
import LoadingIndicator from "./widgets/LoadingIndicator";
import Wizard, { WizardNavigationBar, PagePropsType } from "./widgets/Wizard";
import { SyncManager } from "./sync/SyncManager";
import { store } from "./store";
import { useCredentials } from "./credentials";
import wizardWelcome from "./images/wizard-welcome.svg";
import wizardCreate from "./images/wizard-create.svg";
interface LocationState {
from: {
pathname: string;
};
}
const wizardPages = [
(props: PagePropsType) => (
<>
<div style={{ display: "flex", flexDirection: "column", flex: 1, justifyContent: "center", alignItems: "center" }}>
<h2 style={{ textAlign: "center" }}>Welcome to EteSync!</h2>
<p style={{ textAlign: "center" }}>
Please follow these few quick steps to help you get started.
</p>
<img src={wizardWelcome} style={{ maxWidth: "30em", marginTop: "2em" }} />
</div>
<WizardNavigationBar {...props} />
</>
),
(props: PagePropsType) => (
<SetupCollectionsPage {...props} />
),
];
function SetupCollectionsPage(props: PagePropsType) {
const etebase = useCredentials()!;
const [error, setError] = React.useState<Error>();
const [loading, setLoading] = React.useState(false);
async function onNext() {
setLoading(true);
try {
const colMgr = etebase.getCollectionManager();
const types = [
["etebase.vcard", "My Contacts"],
["etebase.vevent", "My Calendar"],
["etebase.vtodo", "My Tasks"],
];
for (const [type, name] of types) {
const meta: Etebase.ItemMetadata = {
name,
mtime: (new Date()).getTime(),
};
const collection = await colMgr.create(type, meta, "");
await colMgr.upload(collection);
}
props.next?.();
} catch (e) {
setError(e);
} finally {
setLoading(false);
}
}
const next = (loading) ? undefined : onNext;
return (
<>
<div style={{ display: "flex", flexDirection: "column", flex: 1, justifyContent: "center", alignItems: "center" }}>
<h2 style={{ textAlign: "center" }}>Setup Collections</h2>
<p style={{ textAlign: "center", maxWidth: "50em" }}>
In order to start using EteSync you need to create collections to store your data. Clicking <i>Finish</i> below will create a default calendar, address book and a task list for you.
</p>
{(loading) ? (
<LoadingIndicator style={{ display: "block", margin: "40px auto" }} />
) : (error) ? (
<Alert severity="error">{error.message}</Alert>
) : (
<img src={wizardCreate} style={{ maxWidth: "30em", marginTop: "2em" }} />
)}
</div>
<WizardNavigationBar {...props} next={next} />
</>
);
}
export default function WizardPage() {
const [tryCount, setTryCount] = React.useState(0);
const [ranWizard, setRanWizard] = React.useState(false);
const [syncError, setSyncError] = React.useState<Error>();
const etebase = useCredentials();
const location = useLocation();
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
setLoading(true);
setSyncError(undefined);
(async () => {
const syncManager = SyncManager.getManager(etebase!);
const sync = syncManager.sync(true);
try {
await sync;
const cachedCollection = store.getState().cache.collections;
// XXX new account - though should change test to see if there are any PIM types
if (cachedCollection.size > 0) {
setRanWizard(true);
}
} catch (e) {
setSyncError(e);
}
setLoading(false);
})();
}, [tryCount]);
if (syncError) {
return (
<Container>
<div style={{ display: "flex", flexDirection: "column", flex: 1, justifyContent: "center", alignItems: "center" }}>
<h2 style={{ textAlign: "center" }}>Important</h2>
<p style={{ textAlign: "center" }}>
{syncError?.message}
</p>
<Button
variant="contained"
color="primary"
onClick={() => setTryCount(tryCount + 1)}
>
Retry
</Button>
</div>
</Container>
);
}
if (loading) {
return (<LoadingIndicator style={{ display: "block", margin: "40px auto" }} />);
}
if (!ranWizard) {
return (
<Wizard pages={wizardPages} onFinish={() => setRanWizard(true)} style={{ display: "flex", flexDirection: "column", flex: 1 }} />
);
}
const { from } = location.state as LocationState || { from: { pathname: routeResolver.getRoute("home") } };
return (
<Redirect to={from.pathname} />
);
}