228 lines
7.1 KiB
TypeScript
228 lines
7.1 KiB
TypeScript
import PageForm from "./Form";
|
|
import Pages from "./List";
|
|
import Prompt from "./Prompt";
|
|
import * as React from 'react';
|
|
import {Alert, AlertTitle, Button, Divider} from "@mui/material";
|
|
import {EncryptStorage} from "storage-encryption";
|
|
import {
|
|
Switch,
|
|
Route,
|
|
Link,
|
|
Redirect,
|
|
withRouter,
|
|
useHistory
|
|
} from "react-router-dom";
|
|
import {IList} from "../../interfaces/IList";
|
|
import {isAllLoadedLocally} from "../../utils";
|
|
import CalendarHeatmap from "../calendar/CalendarHeatmap";
|
|
import {CalendarHeatmapValuesProp} from "../calendar/CalendarHeatmapValuesProp";
|
|
|
|
const app = document.getElementById('app');
|
|
const word = "shikiryu"; // FIXME should be in db and ≠between users
|
|
|
|
const sessionPassphrase = sessionStorage.getItem("key") as string;
|
|
let pages: IList[] = [];
|
|
let getPageContentUrl,
|
|
postUrl,
|
|
settings,
|
|
removeUrl,
|
|
checkword,
|
|
startDate,
|
|
csrf = "";
|
|
|
|
if (app) {
|
|
getPageContentUrl = "" + app.getAttribute('data-url');
|
|
pages = JSON.parse("" + app.getAttribute('data-list')) as IList[];
|
|
postUrl = "" + app.getAttribute('data-post');
|
|
startDate = "" + app.getAttribute('data-start');
|
|
settings = JSON.parse("" + app.getAttribute('data-settings'));
|
|
removeUrl = "" + app.getAttribute('data-remove');
|
|
csrf = "" + app.getAttribute('data-csrf');
|
|
checkword = "" + app.getAttribute('data-checkword');
|
|
}
|
|
|
|
function App() {
|
|
const [listPages, setListPages] = React.useState<IList[]>(pages);
|
|
const [passphrase, setPassphrase] = React.useState<string>(sessionPassphrase);
|
|
const history = useHistory();
|
|
const [user, setUser] = React.useState(checkPassphrase());
|
|
const [error, isError] = React.useState(!checkPassphrase());
|
|
const [allLoaded, setAllLoaded] = React.useState<boolean>(isAllLoadedLocally(pages));
|
|
|
|
const loadPages = React.useRef(() => {return ;});
|
|
|
|
const signin = cb => {
|
|
const isAuthenticated = checkPassphrase();
|
|
setUser(isAuthenticated);
|
|
if (isAuthenticated) {
|
|
isError(false);
|
|
cb();
|
|
} else {
|
|
isError(true);
|
|
}
|
|
};
|
|
|
|
const signout = cb => {
|
|
sessionStorage.removeItem("key");
|
|
setUser(false);
|
|
cb();
|
|
};
|
|
|
|
function checkPassphrase() {
|
|
if (checkword === "" || checkword === null || checkword === "null") {
|
|
console.error("checkword is empty !");
|
|
return false;
|
|
}
|
|
localStorage.setItem("checkword", checkword);
|
|
|
|
const key = ""+sessionStorage.getItem("key");
|
|
if (key === "" || key === null || key === "null") {
|
|
console.error("key is empty 🤔 !");
|
|
return false;
|
|
}
|
|
const encryptStorage = new EncryptStorage(key);
|
|
const decrypted_word = encryptStorage.decrypt("checkword");
|
|
|
|
return decrypted_word === word;
|
|
}
|
|
|
|
const Error = function() {
|
|
if (error) {
|
|
return (
|
|
<Alert severity="error">
|
|
<AlertTitle>Erreur</AlertTitle>
|
|
La phrase de passe ne correspond pas.
|
|
</Alert>
|
|
);
|
|
}
|
|
return (<div></div>);
|
|
}
|
|
|
|
const LoadButton = function() {
|
|
return allLoaded ? (<></>) : (
|
|
<Button variant="outlined" size="small" sx={{align: "right"}} onClick={() => loadPages.current()}>
|
|
Charger les pages localement
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
const AuthButton = function() {
|
|
const history = useHistory();
|
|
|
|
return user ? (
|
|
<p>
|
|
Bienvenue !{" "}
|
|
<Button variant="outlined" size="small" sx={{align: "right"}} onClick={() => {
|
|
signout(() => history.push("/diary/public"));
|
|
}}>
|
|
Fermer mon carnet à clef
|
|
</Button>
|
|
</p>
|
|
) : (
|
|
<p>
|
|
Votre carnet est fermé.{" "}
|
|
<Link to="/diary/public/pages">Voir vos pages</Link>
|
|
</p>
|
|
);
|
|
}
|
|
|
|
function updatePassphrase(newPassphrase) {
|
|
setPassphrase(newPassphrase);
|
|
if (checkPassphrase()) {
|
|
isError(false);
|
|
setUser(true);
|
|
signin(() => {
|
|
history.push({ pathname: "/diary/public/pages" });
|
|
})
|
|
} else {
|
|
isError(true);
|
|
}
|
|
}
|
|
|
|
function PrivateRoute({ children, ...rest }) {
|
|
return (
|
|
<Route
|
|
{...rest}
|
|
render={({ location }) =>
|
|
user ? (
|
|
children
|
|
) : (
|
|
<Redirect
|
|
to={{
|
|
pathname: "/diary/public/pass",
|
|
state: { from: location }
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function PromptPage() {
|
|
return (<Prompt open={true} setOpen={updatePassphrase}/>);
|
|
}
|
|
|
|
function getCalendarValuesFromPagesList(pages: IList[]): CalendarHeatmapValuesProp[] {
|
|
return pages.map(page => {
|
|
const [date, ] = page.date.split(" ");
|
|
const splittedDate = date.split("/").map(part => { return parseInt(part, 10);});
|
|
return {
|
|
id: page.id,
|
|
date: new Date(splittedDate[2] as number, splittedDate[1] - 1, splittedDate[0] as number),
|
|
event: page.id
|
|
};
|
|
});
|
|
}
|
|
|
|
function ListPage() {
|
|
return (
|
|
<div className="col-md-12">
|
|
<CalendarHeatmap
|
|
values={getCalendarValuesFromPagesList(listPages)}
|
|
startDate={startDate}
|
|
endDate={new Date()}
|
|
showMonthLabels={true}
|
|
showWeekdayLabels={true}
|
|
showOutOfRangeDays={true}
|
|
horizontal={true}
|
|
gutterSize={4}
|
|
onClick={(value) => alert(value)}
|
|
tooltipDataAttrs={{}}
|
|
/>
|
|
<Pages
|
|
pages={listPages}
|
|
url={getPageContentUrl}
|
|
passphrase={passphrase}
|
|
csrf={csrf}
|
|
removeUrl={removeUrl}
|
|
loadPages={loadPages}
|
|
settings={settings}
|
|
setAllLoaded={setAllLoaded}
|
|
/>
|
|
<Divider/>
|
|
<PageForm setListPages={setListPages} csrf={csrf} url={postUrl} passphrase={passphrase}/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<AuthButton />
|
|
<LoadButton />
|
|
<Error/>
|
|
<Divider sx={{height: "20px", mb: "20px", mt:"10px"}}/>
|
|
<Switch>
|
|
<Route path="/diary/public/pass">
|
|
<PromptPage />
|
|
</Route>
|
|
<PrivateRoute path="/diary/public/pages">
|
|
<ListPage />
|
|
</PrivateRoute>
|
|
</Switch>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default withRouter(App);
|