From 9af2feb31433fef88e9669c92a2796421112cec3 Mon Sep 17 00:00:00 2001 From: manuconcepbrito <manu041196@gmail.com> Date: Sun, 17 Oct 2021 15:45:52 +0200 Subject: [PATCH] refactor router and first version of AddSession Component --- wahlfang_web/src/App.js | 18 +- wahlfang_web/src/api/management.js | 11 ++ .../src/components/AuthenticatedRoute.js | 2 +- .../components/ManagerAuthenticatedRoute.js | 16 ++ wahlfang_web/src/pages/ManagementApp.js | 27 +-- wahlfang_web/src/pages/VoteApp.js | 23 ++- .../src/pages/management/AddSession.js | 183 +++++++++++++++++- wahlfang_web/src/pages/management/Login.js | 6 +- wahlfang_web/src/pages/vote/Login.js | 1 + wahlfang_web/src/state/management.js | 5 + 10 files changed, 251 insertions(+), 41 deletions(-) create mode 100644 wahlfang_web/src/components/ManagerAuthenticatedRoute.js diff --git a/wahlfang_web/src/App.js b/wahlfang_web/src/App.js index e222040..a16e146 100644 --- a/wahlfang_web/src/App.js +++ b/wahlfang_web/src/App.js @@ -5,6 +5,7 @@ import VoteApp from "./pages/VoteApp"; import ManagementApp from "./pages/ManagementApp"; import SpectatorView from "./pages/SpectatorView"; import About from "./pages/About"; +import Help from "./pages/management/Help"; function App() { @@ -28,12 +29,17 @@ function App() { <ManagementApp/> </Suspense> </Route> - <Route path="/"> - <Suspense fallback={<Loading/>}> - <VoteApp/> - </Suspense> - </Route> - <Route path="*">404</Route> + {/*<Route path="/vote" exact={true}>*/} + {/* <Suspense fallback={<Loading/>}>*/} + {/* <VoteApp/>*/} + {/* </Suspense>*/} + {/*</Route>*/} + {/*<Route exact path="/">*/} + {/* <Suspense fallback={<Loading/>}>*/} + {/* <Help/>*/} + {/* </Suspense>*/} + {/*</Route>*/} + {/*<Route>404</Route>*/} </Switch> </Router> )} diff --git a/wahlfang_web/src/api/management.js b/wahlfang_web/src/api/management.js index 1295df9..7493da1 100644 --- a/wahlfang_web/src/api/management.js +++ b/wahlfang_web/src/api/management.js @@ -4,6 +4,7 @@ export const managementAPIRoutes = { login: "/auth/token/", refreshToken: "/auth/token/refresh/", verifyToken: "/auth/token/verify/", + createSession: "management/add-session", } export const loadManagerToken = () => { @@ -25,6 +26,7 @@ export const refreshManagerToken = async () => { } export const loginManager = async (username, password) => { + console.log(managementAPIRoutes.login) const response = await makeRequest(managementAPIRoutes.login, 'POST', { username: username, password: password @@ -41,4 +43,13 @@ export const loginManager = async (username, password) => { export const logoutManager = async () => { localStorage.removeItem("managerToken"); return true; +} + +export const createSession = async (form_values) => { + const response = await makeRequest(managementAPIRoutes.createSession, 'POST', form_values); + if (response.status === 204) { + return true; + } else { + throw Error(await response.json()) + } } \ No newline at end of file diff --git a/wahlfang_web/src/components/AuthenticatedRoute.js b/wahlfang_web/src/components/AuthenticatedRoute.js index c273f62..3b493e5 100644 --- a/wahlfang_web/src/components/AuthenticatedRoute.js +++ b/wahlfang_web/src/components/AuthenticatedRoute.js @@ -3,7 +3,7 @@ import {useRecoilValue} from "recoil"; import {isVoterAuthenticated} from "../state"; import {Redirect} from "react-router-dom"; -export default function AuthenticatedRoute({authFallback = "/code", children}) { +export default function AuthenticatedRoute({authFallback = "/vote/code", children}) { const authenticated = useRecoilValue(isVoterAuthenticated); if (!authenticated) { console.log("redirecting to login") diff --git a/wahlfang_web/src/components/ManagerAuthenticatedRoute.js b/wahlfang_web/src/components/ManagerAuthenticatedRoute.js new file mode 100644 index 0000000..8b0fd3d --- /dev/null +++ b/wahlfang_web/src/components/ManagerAuthenticatedRoute.js @@ -0,0 +1,16 @@ +import React from "react"; +import {useRecoilValue} from "recoil"; +import {Redirect} from "react-router-dom"; +import {isManagerAuthenticated} from "../state/management" + +export default function ManagerAuthenticatedRoute({authFallback = "/management/login", children}) { + const authenticated = useRecoilValue(isManagerAuthenticated); + if (!authenticated) { + console.log("Manager not authenticated. Redirecting to manager login") + } + return ( + <> + {!authenticated ? <Redirect to={authFallback}/> : children} + </> + ) +} \ No newline at end of file diff --git a/wahlfang_web/src/pages/ManagementApp.js b/wahlfang_web/src/pages/ManagementApp.js index a7a09f6..02fe1ac 100644 --- a/wahlfang_web/src/pages/ManagementApp.js +++ b/wahlfang_web/src/pages/ManagementApp.js @@ -10,14 +10,14 @@ import Help from "./management/Help"; import {managementWS} from "../websocket"; import Header from "../components/Header"; import Logout from "./vote/Logout"; -import AuthenticatedRoute from "../components/AuthenticatedRoute"; +import ManagerAuthenticatedRoute from "../components/ManagerAuthenticatedRoute"; +import AddSession from "./management/AddSession" export default function ManagementApp() { const [authenticated, setAuthenticated] = useRecoilState(isManagerAuthenticated); const [loading, setLoading] = useState(!authenticated); const {path} = useRouteMatch(); - useEffect(() => { const authToken = loadManagerToken(); if (authToken && isTokenValid(authToken.access)) { @@ -47,24 +47,27 @@ export default function ManagementApp() { <div id="content"> <Header/> <Switch> + <Route exact path={path}> + <Help/> + </Route> <Route exact path={`${path}/login`}> <Suspense fallback={<Loading/>}> <LoginManager/> </Suspense> </Route> - <Route exact path={path}> - <Help/> - </Route> <Route exact path={`${path}/help`}> <Help/> </Route> - <AuthenticatedRoute> - <Route exact path="/logout"> - <Suspense fallback={<Loading/>}> - <Logout/> - </Suspense> - </Route> - </AuthenticatedRoute> + <Route exact path={`${path}/add-session`}> + <AddSession/> + </Route> + <ManagerAuthenticatedRoute> + <Route exact path={`${path}/logout`}> + <Suspense fallback={<Loading/>}> + <Logout/> + </Suspense> + </Route> + </ManagerAuthenticatedRoute> </Switch> </div> )} diff --git a/wahlfang_web/src/pages/VoteApp.js b/wahlfang_web/src/pages/VoteApp.js index aee0e6f..199ad4c 100644 --- a/wahlfang_web/src/pages/VoteApp.js +++ b/wahlfang_web/src/pages/VoteApp.js @@ -1,5 +1,5 @@ import React, {Suspense, useEffect, useState} from 'react'; -import {Route, Switch} from "react-router-dom"; +import {Route, Switch, useRouteMatch} from "react-router-dom"; import {useRecoilState} from "recoil"; import Login from './vote/Login'; @@ -19,6 +19,9 @@ import Header from "../components/Header"; export default function VoteApp() { const [authenticated, setAuthenticated] = useRecoilState(isVoterAuthenticated); const [loading, setLoading] = useState(!authenticated); + const {path} = useRouteMatch(); + console.log(path) + useEffect(() => { const authToken = loadVoterToken(); @@ -49,35 +52,35 @@ export default function VoteApp() { <div id="content"> <Header/> <Switch> - <Route exact path="/code"> + <Route exact path={`${path}/code`}> <Suspense fallback={<Loading/>}> <Login/> </Suspense> </Route> - <Route exact path="/help"> + <Route exact path={`${path}/help`}> <Help/> </Route> <AuthenticatedRoute> + <Route path={path} exact={true}> + <Suspense fallback={<Loading/>}> + <Home/> + </Suspense> + </Route> <Route exact path="/logout"> <Suspense fallback={<Loading/>}> <Logout/> </Suspense> </Route> - <Route exact path="/election/:id/vote"> + <Route exact path={`${path}/election/:id/vote`}> <Suspense fallback={<Loading/>}> <PerformVote/> </Suspense> </Route> - <Route exact path="/election/:id/application"> + <Route exact path={`${path}/election/:id/application`} > <Suspense fallback={<Loading/>}> <Application/> </Suspense> </Route> - <Route exact path="/"> - <Suspense fallback={<Loading/>}> - <Home/> - </Suspense> - </Route> </AuthenticatedRoute> </Switch> </div> diff --git a/wahlfang_web/src/pages/management/AddSession.js b/wahlfang_web/src/pages/management/AddSession.js index 3c53d5e..32fecb6 100644 --- a/wahlfang_web/src/pages/management/AddSession.js +++ b/wahlfang_web/src/pages/management/AddSession.js @@ -1,16 +1,181 @@ import React from "react"; -import {useHistory, useParams} from "react-router-dom"; +import { Collapse } from 'reactstrap'; +// import {useHistory, useParams} from "react-router-dom"; import Layout from "../../components/Layout"; -import {useFormik} from "formik"; -import {useRecoilValue} from "recoil"; -import {performVote} from "../../api"; +// import {useFormik} from "formik"; +// import {useRecoilValue} from "recoil"; +// import {createSession} from "../../api/management"; +import {toggleAddSession} from "../../state/management" +import { Formik, Form, Field } from 'formik'; +import {useRecoilState} from "recoil"; export default function AddSession() { - const history = useHistory(); + const [toggle, setToggle] = useRecoilState(toggleAddSession); - const formik = useFormik({ - onSubmit: values => { - // TO be defined is a function that calls the endpoint to create the session - }) + + const handleSubmit = (values, {setSubmitting}) => { + console.log("Adding session submit") + } + + // const formik = useFormik({ + // onSubmit: values => { + // createSession(values) + // .then(result => { + // history.push('/') + // }) + // .catch(err => { + // // TODO + // }) + // } + // + // }) + // Render Prop + + const handleToggle = () => { + if (toggle) { + console.log("Value toggle " + toggle) + setToggle(false) + } else { + console.log("Value toggle " + toggle) + setToggle(true) + } + } + + const Basic = () => ( + <div className="p-5"> + <Formik + initialValues={{ title: '', start_date: '', meeting_link: ''}} + onSubmit={handleSubmit} + > + {({ + values, + errors, + touched, + handleChange, + handleBlur, + handleSubmit, + isSubmitting + }) => ( + <form onSubmit={handleSubmit}> + <div className="form-group"> + <label>Create Session</label> + </div> + <div className="mt-3 form-group"> + <input type="text" + className="form-control form-control-user text-center" + name="sessionTitle" + placeholder="Session's Title" + autoFocus={true} + onChange={handleChange} + onBlur={handleBlur} + value={values.accessCode} + required={true}/> + {errors.sessionTitle && touched.sessionTitle && errors.sessionTitle} + </div> + <div className="mt-3 form-group"> + <input type="text" + className="form-control form-control-user text-center" + name="startDate" + placeholder="Start Date, e.g. 12/12/2020 02:23 PM" + autoFocus={true} + onChange={handleChange} + onBlur={handleBlur} + value={values.accessCode} + required={true}/> + {errors.startDate && touched.startDate && errors.startDate} + </div> + <div className="mt-3 form-group"> + <input type="text" + className="form-control form-control-user text-center" + name="meetingLink" + placeholder="Start Date, e.g. 12/12/2020 02:23 PM" + autoFocus={true} + onChange={handleChange} + onBlur={handleBlur} + value={values.accessCode} + required={true}/> + {errors.meetingLink && touched.meetingLink && errors.meetingLink} + </div> + <div className="card mb-0" onClick={handleToggle}> + <div + className="mycard-header card-header" + > + <span className="card-title">Advanced Options</span> + </div> + <Collapse isOpen={toggle}> + <div id="collapseOne" + className="card-body "> + <h5>Invite email template text</h5> + The template has be written the python format string format. The following variables are + available:<br/> + <table className="table table-responsive"> + <thead> + <tr> + <th scope="col">Name</th> + <th scope="col">Meaning</th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row" className="monospace">name</th> + <td>Voter's name if set</td> + </tr> + </tbody> + </table> + + Here is an example:<br/> + <p className="monospace">Dear,<br/><br/>You have been invited to our awesome meeting title. + We are meeting + on {meeting_link}. It + takes place on the {start_date_en} at {start_time_en}. You can login with the following + link: + <a href="{login_url}"> {login_url} </a>. + You can also use the following access code on {base_url}: {access_code}<br/><br/> + Best regards,<br/> + Your awesome Organizers + </p> + + <p> + Invite Text + </p> + <br/><br/> + <h6>Send test mail</h6> + <div className="form-row"> + <div className="col-8"> + Email + </div> + <div className="col"> + <button type="submit" id="id_btn_send_test" + className="btn btn-warning btn-block" name="submit_type" + value="test"> + Send test mail + </button> + </div> + </div> + </div> + </div> + </Collapse> + <div className="d-grid mt-2"> + <button type="submit" id="id_btn_start" className="btn btn-success">Create Session</button> + </div> + </form> + )} + </Formik> + </div> + ); + + return ( + <Layout title="addSession"> + <div className="row justify-content-center"> + <div className="col-12"> + <div className="card shadow"> + <div className="card-body"> + <Basic/> + </div> + </div> + </div> + </div> + </Layout> + ) } \ No newline at end of file diff --git a/wahlfang_web/src/pages/management/Login.js b/wahlfang_web/src/pages/management/Login.js index ae2076b..b55ec8b 100644 --- a/wahlfang_web/src/pages/management/Login.js +++ b/wahlfang_web/src/pages/management/Login.js @@ -6,7 +6,6 @@ import {loginManager} from "../../api/management"; import {useRecoilState} from "recoil"; import {isManagerAuthenticated} from "../../state/management"; - export default function LoginManager() { const [authenticated, setAuthenticated] = useRecoilState(isManagerAuthenticated); const history = useHistory(); @@ -16,7 +15,8 @@ export default function LoginManager() { .then(res => { setAuthenticated(true); setSubmitting(false); - history.push("/"); + console.log("Successful manager logging attempt") + history.push("/management/add-session"); }) .catch(err => { setSubmitting(false); @@ -24,7 +24,7 @@ export default function LoginManager() { } if (authenticated) { - return <Redirect to="/"/> + return <Redirect to="/help"/> } return ( diff --git a/wahlfang_web/src/pages/vote/Login.js b/wahlfang_web/src/pages/vote/Login.js index ea93e0e..55aa5cc 100644 --- a/wahlfang_web/src/pages/vote/Login.js +++ b/wahlfang_web/src/pages/vote/Login.js @@ -9,6 +9,7 @@ import {isVoterAuthenticated} from "../../state"; export default function Login() { const [authenticated, setAuthenticated] = useRecoilState(isVoterAuthenticated); const history = useHistory(); + console.log("getting to login") const handleSubmit = (values, {setSubmitting}) => { loginVoter(values.accessCode) diff --git a/wahlfang_web/src/state/management.js b/wahlfang_web/src/state/management.js index fb33c27..d350367 100644 --- a/wahlfang_web/src/state/management.js +++ b/wahlfang_web/src/state/management.js @@ -4,3 +4,8 @@ export const isManagerAuthenticated = atom({ key: 'isManagerAuthenticated', default: false, }) + +export const toggleAddSession = atom({ + key: 'toggleAddSession', + default: false, +}) -- GitLab