refactor(routes): use react-context to clarify and centralize the management of API routes #12

pull/73/head
Clement G 4 years ago committed by guhur
parent 220ccacdfe
commit c7909388d1

@ -4,16 +4,19 @@ import Routes from "./Routes";
import Header from "./components/layouts/Header";
import Footer from "./components/layouts/Footer";
import AppContextProvider from "./AppContext";
function App() {
return (
<Router>
<div>
<Header />
<Routes />
<Footer />
</div>
</Router>
<AppContextProvider>
<Router>
<div>
<Header />
<Routes />
<Footer />
</div>
</Router>
</AppContextProvider>
);
}

@ -0,0 +1,19 @@
import React, { createContext } from "react";
export const AppContext = createContext();
const AppContextProvider = ({ children }) => {
const defaultState = {
urlServer: process.env.REACT_APP_SERVER_URL,
routesServer: {
setElection: "election/",
getElection: "election/get/:slug",
getResultsElection: "election/results/:slug",
voteElection: "election/vote/:slug"
}
};
return (
<AppContext.Provider value={defaultState}>{children}</AppContext.Provider>
);
};
export default AppContextProvider;

@ -10,96 +10,19 @@ import UnknownElection from "./components/views/UnknownElection";
import CreateSuccess from "./components/views/CreateSuccess";
import VoteSuccess from "./components/views/VoteSuccess";
function Routes() {
const params = new URLSearchParams(window.location.search);
const urlServer = process.env.REACT_APP_SERVER_URL;
const routesServer = {
setElection: "election/",
getElection: "election/get/:slug",
getResultsElection: "election/results/:slug",
voteElection: "election/vote/:slug"
};
function Routes() {
return (
<main className="d-flex flex-column justify-content-center">
<Switch>
<Route exact path="/" component={Home} />
<Route
path="/create-election"
render={props => (
<CreateElection
{...props}
title={params.get("title") ? params.get("title") : ""}
urlServer={urlServer}
routesServer={routesServer}
/>
)}
/>
<Route
path="/vote/:slug"
render={props => (
<Vote
{...props}
slug={props.match.params.slug}
urlServer={urlServer}
routesServer={routesServer}
/>
)}
/>
<Route
path="/result/:handle"
render={props => (
<Result
{...props}
slug={props.match.params.slug}
urlServer={urlServer}
routesServer={routesServer}
/>
)}
/>
<Route
path="/create-success/:handle"
render={props => (
<CreateSuccess
{...props}
slug={props.match.params.slug}
urlServer={urlServer}
routesServer={routesServer}
/>
)}
/>
<Route
path="/vote-success/:handle"
render={props => (
<VoteSuccess
{...props}
slug={props.match.params.slug}
urlServer={urlServer}
routesServer={routesServer}
/>
)}
/>
<Route
path="/unknown-election/:handle"
render={props => (
<UnknownElection
{...props}
slug={props.match.params.slug}
urlServer={urlServer}
routesServer={routesServer}
/>
)}
/>
/>
<Route
render={props => (
<UnknownView
{...props}
urlServer={urlServer}
routesServer={routesServer}
/>
)}
/>
<Route path="/create-election" component={CreateElection} />
<Route path="/vote/:handle" component={Vote} />
<Route path="/result/:handle" component={Result} />
<Route path="/create-success/:handle" component={CreateSuccess} />
<Route path="/vote-success/:handle" component={VoteSuccess} />
<Route path="/unknown-election/:handle" component={UnknownElection} />
<Route component={UnknownView} />
</Switch>
</main>
);

@ -37,6 +37,7 @@ import {
import { grades } from "../../Util";
import { ReactMultiEmail, isEmail } from "react-multi-email";
import "react-multi-email/style.css";
import { AppContext } from "../../AppContext";
const DragHandle = sortableHandle(({ children }) => (
<span className="input-group-text indexNumber">{children}</span>
@ -115,6 +116,7 @@ const SortableCandidatesContainer = sortableContainer(({ items, form }) => {
});
class CreateElection extends Component {
static contextType = AppContext;
constructor(props) {
super(props);
//default value : start now
@ -122,11 +124,11 @@ class CreateElection extends Component {
const startedHour = startedAt.getHours();
//default value : finish in one week
const finishedAt = new Date(startedAt.getTime() + 7 * 24 * 60 * 60 * 1000);
const params = new URLSearchParams(window.location.search);
this.state = {
candidates: [{ label: "" }, { label: "" }],
numCandidatesWithLabel: 0,
title: this.props.title,
title: params.get("title") ? params.get("title") : "A",
isVisibleTipsDragAndDropCandidate: true,
numGrades: 7,
successCreate: false,
@ -163,7 +165,6 @@ class CreateElection extends Component {
removeCandidate = index => {
let candidates = this.state.candidates;
candidates.splice(index, 1);
console.log(candidates.length);
if (candidates.length === 0) {
candidates = [{ label: "" }];
}
@ -215,8 +216,8 @@ class CreateElection extends Component {
const { candidates, title, numGrades } = this.state;
const endpoint = resolve(
this.props.urlServer,
this.props.routesServer.setElection
this.context.urlServer,
this.context.routesServer.setElection
);
fetch(endpoint, {
@ -282,7 +283,6 @@ class CreateElection extends Component {
render() {
const { successCreate, redirectTo } = this.state;
const { electorEmails } = this.state;
const params = new URLSearchParams(this.props.location.search);
if (successCreate) return <Redirect to={redirectTo} />;
@ -308,7 +308,7 @@ class CreateElection extends Component {
id="title"
innerRef={this.focusInput}
autoFocus
defaultValue={this.props.title}
value={this.state.title}
onChange={this.handleChangeTitle}
maxLength="250"
/>

@ -4,11 +4,13 @@ import { Link } from "react-router-dom";
import { faCopy, faUsers } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import logoLine from "../../logos/logo-line-white.svg";
import { AppContext } from "../../AppContext";
class UnknownView extends Component {
class CreateSuccess extends Component {
static contextType = AppContext;
constructor(props) {
super(props);
const electionSlug = this.props.slug;
const electionSlug = this.props.match.params.slug;
this.state = {
urlOfVote:
"https://" + window.location.hostname + "/vote/" + electionSlug,
@ -118,7 +120,7 @@ class UnknownView extends Component {
<Row className="mt-4 mb-4">
<Col className="text-center">
<Link to={"/vote/" + this.props.slug} className="btn btn-success">
<Link to={"/vote/" + this.props.match.params.slug} className="btn btn-success">
<FontAwesomeIcon icon={faUsers} className="mr-2" />
Participer maintenant !
</Link>
@ -128,4 +130,4 @@ class UnknownView extends Component {
);
}
}
export default UnknownView;
export default CreateSuccess;

@ -5,7 +5,9 @@ import { faRocket } from "@fortawesome/free-solid-svg-icons";
import { Redirect } from "react-router-dom";
import logoLine from "../../logos/logo-line-white.svg";
class Home extends Component {
constructor(props) {
super(props);
this.state = {
@ -21,6 +23,7 @@ class Home extends Component {
};
handleChangeTitle = event => {
//console.log(this.context.routesServer.setElection);
this.setState({ title: event.target.value });
};

@ -12,8 +12,10 @@ import {
Table
} from "reactstrap";
import { grades } from "../../Util";
import { AppContext } from "../../AppContext";
class Result extends Component {
static contextType = AppContext;
constructor(props) {
super(props);
this.state = {
@ -95,9 +97,13 @@ class Result extends Component {
// FIXME we should better handling logs
// get details of the election
const electionSlug = this.props.match.params.slug;
const detailsEndpoint = resolve(
this.props.urlServer,
this.props.routesServer.getElection.replace(new RegExp(":slug","g"),(this.props.slug))
this.context.urlServer,
this.context.routesServer.getElection.replace(
new RegExp(":slug", "g"),
electionSlug
)
);
fetch(detailsEndpoint)
@ -108,8 +114,11 @@ class Result extends Component {
// get results of the election
const resultsEndpoint = resolve(
this.props.urlServer,
this.props.routesServer.getResultsElection.replace(new RegExp(":slug","g"),(this.props.slug))
this.context.urlServer,
this.context.routesServer.getResultsElection.replace(
new RegExp(":slug", "g"),
electionSlug
)
);
fetch(resultsEndpoint)

@ -2,8 +2,10 @@ import React, { Component } from "react";
import { Col, Container, Row } from "reactstrap";
import logoLine from "../../logos/logo-line-white.svg";
import { Link } from "react-router-dom";
import { AppContext } from "../../AppContext";
class UnknownElection extends Component {
static contextType = AppContext;
constructor(props) {
super(props);
this.state = {};

@ -2,8 +2,10 @@ import React, { Component } from "react";
import { Col, Container, Row } from "reactstrap";
import logoLine from "../../logos/logo-line-white.svg";
import { Link } from "react-router-dom";
import { AppContext } from "../../AppContext";
class UnknownView extends Component {
static contextType = AppContext;
constructor(props) {
super(props);
this.state = {};

@ -6,8 +6,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheck } from "@fortawesome/free-solid-svg-icons";
import { resolve } from "url";
import { grades } from "../../Util";
import { AppContext } from "../../AppContext";
class Vote extends Component {
static contextType = AppContext;
constructor(props) {
super(props);
this.state = {
@ -89,9 +91,13 @@ class Vote extends Component {
componentDidMount() {
// FIXME we should better handling logs
const electionSlug = this.props.match.params.slug;
const detailsEndpoint = resolve(
this.props.urlServer,
this.props.routesServer.getElection.replace(new RegExp(":slug","g"),(this.props.slug))
this.context.urlServer,
this.context.routesServer.getElection.replace(
new RegExp(":slug", "g"),
electionSlug
)
);
fetch(detailsEndpoint)
.then(this.handleErrors)
@ -123,10 +129,13 @@ class Vote extends Component {
event.preventDefault();
const { ratedCandidates } = this.state;
const electionSlug = this.props.slug;
const electionSlug = this.props.match.params.slug;
const endpoint = resolve(
this.props.urlServer,
this.props.routesServer.voteElection.replace(new RegExp(":slug","g"),(this.props.slug))
this.context.urlServer,
this.context.routesServer.voteElection.replace(
new RegExp(":slug", "g"),
electionSlug
)
);
const gradesById = {};

@ -2,8 +2,10 @@ import React, { Component } from "react";
import { Col, Container, Row } from "reactstrap";
import logoLine from "../../logos/logo-line-white.svg";
import { Link } from "react-router-dom";
import { AppContext } from "../../AppContext";
class UnknownView extends Component {
class VoteSuccess extends Component {
static contextType = AppContext;
render() {
return (
<Container>
@ -30,4 +32,4 @@ class UnknownView extends Component {
);
}
}
export default UnknownView;
export default VoteSuccess;
Loading…
Cancel
Save