feat(pettier) : eslintrc.json and format all files

pull/73/head
Clement G 4 years ago
parent e3300e2d9b
commit e6482a7962

@ -0,0 +1,26 @@
{
"env": {
"browser": true,
"es6": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
}
}

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

@ -1,7 +1,6 @@
import React, { createContext, Suspense } from "react"; import React, { createContext, Suspense } from "react";
import {BrowserRouter as Router} from 'react-router-dom'; import { BrowserRouter as Router } from "react-router-dom";
import Loader from './components/loader'; import Loader from "./components/loader";
export const AppContext = createContext(); export const AppContext = createContext();
@ -16,12 +15,12 @@ const AppContextProvider = ({ children }) => {
} }
}; };
return ( return (
<Suspense fallback={<Loader/>} > <Suspense fallback={<Loader />}>
<Router> <Router>
<AppContext.Provider value={defaultState}> <AppContext.Provider value={defaultState}>
{children} {children}
</AppContext.Provider> </AppContext.Provider>
</Router> </Router>
</Suspense> </Suspense>
); );
}; };

@ -10,7 +10,6 @@ import UnknownElection from "./components/views/UnknownElection";
import CreateSuccess from "./components/views/CreateSuccess"; import CreateSuccess from "./components/views/CreateSuccess";
import VoteSuccess from "./components/views/VoteSuccess"; import VoteSuccess from "./components/views/VoteSuccess";
function Routes() { function Routes() {
return ( return (
<main className="d-flex flex-column justify-content-center"> <main className="d-flex flex-column justify-content-center">
@ -19,8 +18,18 @@ function Routes() {
<Route path="/create-election" component={CreateElection} /> <Route path="/create-election" component={CreateElection} />
<Route path="/vote/:slug" component={Vote} /> <Route path="/vote/:slug" component={Vote} />
<Route path="/result/:slug" component={Result} /> <Route path="/result/:slug" component={Result} />
<Route path="/link/:slug" component={props => <CreateSuccess invitationOnly={true} {...props} />} /> <Route
<Route path="/links/:slug" component={props => <CreateSuccess invitationOnly={false} {...props} />} /> path="/link/:slug"
component={props => (
<CreateSuccess invitationOnly={true} {...props} />
)}
/>
<Route
path="/links/:slug"
component={props => (
<CreateSuccess invitationOnly={false} {...props} />
)}
/>
<Route path="/vote-success/:slug" component={VoteSuccess} /> <Route path="/vote-success/:slug" component={VoteSuccess} />
<Route path="/unknown-election/:slug" component={UnknownElection} /> <Route path="/unknown-election/:slug" component={UnknownElection} />
<Route component={UnknownView} /> <Route component={UnknownView} />

@ -1,34 +1,26 @@
import i18n from './i18n.jsx'; import i18n from "./i18n.jsx";
const colors = [ const colors = [
'#015411', "#015411",
'#019812', "#019812",
'#6bca24', "#6bca24",
'#ffb200', "#ffb200",
'#ff5d00', "#ff5d00",
'#b20616', "#b20616",
'#6f0214', "#6f0214"
]; ];
const gradeNames = [ const gradeNames = [
'Excellent', "Excellent",
'Very good', "Very good",
'Good', "Good",
'Fair', "Fair",
'Passable', "Passable",
'Insufficient', "Insufficient",
'To reject', "To reject"
]; ];
const gradeValues = [ const gradeValues = [6, 5, 4, 3, 2, 1, 0];
6,
5,
4,
3,
2,
1,
0
];
export const grades = gradeNames.map((name, i) => ({ export const grades = gradeNames.map((name, i) => ({
label: name, label: name,

@ -1,7 +1,6 @@
import React from 'react'; import React from "react";
import {Button} from 'reactstrap'; import { Button } from "reactstrap";
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
const CopyField = props => { const CopyField = props => {
const ref = React.createRef(); const ref = React.createRef();
@ -13,10 +12,10 @@ const CopyField = props => {
const input = ref.current; const input = ref.current;
input.focus(); input.focus();
input.select(); input.select();
document.execCommand('copy'); document.execCommand("copy");
}; };
const {t, value, icon} = props; const { t, value, icon } = props;
return ( return (
<div className="input-group "> <div className="input-group ">
@ -33,9 +32,10 @@ const CopyField = props => {
<Button <Button
className="btn btn-outline-light" className="btn btn-outline-light"
onClick={handleClickOnButton} onClick={handleClickOnButton}
type="button"> type="button"
>
<FontAwesomeIcon icon={icon} className="mr-2" /> <FontAwesomeIcon icon={icon} className="mr-2" />
{t('Copy')} {t("Copy")}
</Button> </Button>
</div> </div>
</div> </div>

@ -1,17 +1,23 @@
import React from 'react'; import React from "react";
import i18n from '../../i18n' import i18n from "../../i18n";
const Helloasso = props => {
const locale =
i18n.language.substring(0, 2).toLowerCase() === "fr" ? "fr" : "en";
const linkHelloAssoBanner =
locale === "fr"
? "https://www.helloasso.com/associations/mieux-voter/formulaires/1/widget"
: "https://www.helloasso.com/associations/mieux-voter/formulaires/1/widget/en";
return (
const Helloasso = (props) => { <a href={linkHelloAssoBanner} target="_blank" rel="noopener noreferrer">
const locale=i18n.language.substring(0,2).toLowerCase()==="fr"?"fr":"en"; <img
const linkHelloAssoBanner=(locale==="fr")?"https://www.helloasso.com/associations/mieux-voter/formulaires/1/widget":"https://www.helloasso.com/associations/mieux-voter/formulaires/1/widget/en"; src={"/banner/" + locale + "/helloasso.png"}
alt="support us on helloasso"
return ( style={{ width: props.width }}
<a href={linkHelloAssoBanner} target="_blank" rel="noopener noreferrer"> />
<img src={"/banner/"+locale+"/helloasso.png"} alt="support us on helloasso" style={{width:props.width}} /> </a>
</a>); );
}; };
export default Helloasso;
export default Helloasso;

@ -1,29 +1,43 @@
import React from 'react'; import React from "react";
import i18n from '../../i18n' import i18n from "../../i18n";
import {withTranslation} from 'react-i18next'; import { withTranslation } from "react-i18next";
import { faPaypal } from "@fortawesome/free-brands-svg-icons"; import { faPaypal } from "@fortawesome/free-brands-svg-icons";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
const Paypal = props => {
const { t } = props;
let localeStringShort = i18n.language.substring(0, 2);
let localeStringComplete =
localeStringShort.toLowerCase() + "_" + localeStringShort.toUpperCase();
if (localeStringComplete === "en_EN") {
localeStringComplete = "en_US";
}
const pixelLink =
"https://www.paypal.com/" + localeStringComplete + "/i/scr/pixel.gif";
const Paypal = (props) => { return (
const {t} = props; <div className="d-inline-block m-auto">
let localeStringShort=i18n.language.substring(0,2); <form
let localeStringComplete=localeStringShort.toLowerCase()+"_"+localeStringShort.toUpperCase(); action="https://www.paypal.com/cgi-bin/webscr"
if(localeStringComplete==="en_EN"){ method="post"
localeStringComplete="en_US"; target="_top"
} >
const pixelLink="https://www.paypal.com/"+localeStringComplete+"/i/scr/pixel.gif"; <button
type="submit"
return ( className={"btn " + props.btnColor}
<div className="d-inline-block m-auto"> title={t("PayPal - The safer, easier way to pay online!")}
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top"> >
<button type="submit" className={"btn "+props.btnColor} title={t("PayPal - The safer, easier way to pay online!")} > <FontAwesomeIcon icon={faPaypal} className="mr-2" />{t("Support us !")}</button> {" "}
<input type="hidden" name="cmd" value="_s-xclick" /> <FontAwesomeIcon icon={faPaypal} className="mr-2" />
<input type="hidden" name="hosted_button_id" value="KB2Z7L9KARS7C" /> {t("Support us !")}
<img alt="" border="0" src={pixelLink} width="1" height="1" /> </button>
</form></div>); <input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="hosted_button_id" value="KB2Z7L9KARS7C" />
<img alt="" border="0" src={pixelLink} width="1" height="1" />
</form>
</div>
);
}; };
export default withTranslation()(Paypal);
export default withTranslation()(Paypal);

@ -1,7 +1,7 @@
import React, {Component} from 'react'; import React, { Component } from "react";
import {withTranslation} from 'react-i18next'; import { withTranslation } from "react-i18next";
import {Link} from 'react-router-dom'; import { Link } from "react-router-dom";
import Paypal from '../banner/Paypal'; import Paypal from "../banner/Paypal";
class Footer extends Component { class Footer extends Component {
constructor(props) { constructor(props) {
@ -10,28 +10,30 @@ class Footer extends Component {
} }
render() { render() {
const linkStyle = {whiteSpace: 'nowrap'}; const linkStyle = { whiteSpace: "nowrap" };
const {t} = this.props; const { t } = this.props;
return ( return (
<footer className="text-center"> <footer className="text-center">
<Link to="/" style={linkStyle}> <Link to="/" style={linkStyle}>
{t('Homepage')} {t("Homepage")}
</Link> </Link>
<span className="m-2">-</span> <span className="m-2">-</span>
<a <a
href="https://github.com/MieuxVoter" href="https://github.com/MieuxVoter"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
style={linkStyle}> style={linkStyle}
{t('Source code')} >
{t("Source code")}
</a> </a>
<span className="m-2">-</span> <span className="m-2">-</span>
<a <a
href="https://mieuxvoter.fr/" href="https://mieuxvoter.fr/"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
style={linkStyle}> style={linkStyle}
{t('Who are we?')} >
{t("Who are we?")}
</a> </a>
<div className="mt-3"> <div className="mt-3">
<Paypal btnColor="btn-primary" /> <Paypal btnColor="btn-primary" />

@ -1,8 +1,7 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { Collapse, Navbar, NavbarToggler, Nav, NavItem } from "reactstrap"; import { Collapse, Navbar, NavbarToggler, Nav, NavItem } from "reactstrap";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { withTranslation } from 'react-i18next'; import { withTranslation } from "react-i18next";
import logo from "../../logos/logo-color.svg"; import logo from "../../logos/logo-color.svg";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@ -10,15 +9,15 @@ import { faRocket } from "@fortawesome/free-solid-svg-icons";
import LanguageSelector from "./LanguageSelector"; import LanguageSelector from "./LanguageSelector";
class Header extends Component { class Header extends Component {
state = { state = {
isOpen: false isOpen: false
}; };
toggle = () => { toggle = () => {
this.setState({ this.setState({
isOpen: !this.state.isOpen isOpen: !this.state.isOpen
}); });
} };
render() { render() {
const { t } = this.props; const { t } = this.props;
@ -33,7 +32,7 @@ class Header extends Component {
<div className="align-self-center ml-2"> <div className="align-self-center ml-2">
<div className="logo-text"> <div className="logo-text">
<h1> <h1>
{t("Voting platform")} {t("Voting platform")}
<small>{t("Majority Judgment")}</small> <small>{t("Majority Judgment")}</small>
</h1> </h1>
</div> </div>
@ -49,7 +48,7 @@ class Header extends Component {
{t("Start an election")} {t("Start an election")}
</Link> </Link>
</NavItem> </NavItem>
<NavItem style={{width:"150px"}}> <NavItem style={{ width: "150px" }}>
<LanguageSelector /> <LanguageSelector />
</NavItem> </NavItem>
</Nav> </Nav>

@ -1,30 +1,29 @@
import React from 'react'; import React from "react";
import ReactFlagsSelect from 'react-flags-select'; import ReactFlagsSelect from "react-flags-select";
import 'react-flags-select/css/react-flags-select.css'; import "react-flags-select/css/react-flags-select.css";
import i18n from '../../i18n'
import i18n from "../../i18n";
const LanguageSelector = () => { const LanguageSelector = () => {
const selectHandler = e => {
const selectHandler = (e) => { let locale = e.toLowerCase();
let locale=e.toLowerCase(); if (locale === "gb") locale = "en";
if(locale==="gb")locale="en"; i18n.changeLanguage(locale);
i18n.changeLanguage(locale); };
};
let locale = i18n.language.substring(0, 2).toUpperCase();
let locale=i18n.language.substring(0,2).toUpperCase(); if (locale === "EN") locale = "GB";
if(locale==="EN")locale="GB"; return (
return (<ReactFlagsSelect onSelect={selectHandler} <ReactFlagsSelect
countries={["GB", "FR", "ES", "DE", "RU"]} onSelect={selectHandler}
showOptionLabel={false} countries={["GB", "FR", "ES", "DE", "RU"]}
defaultCountry={locale} showOptionLabel={false}
selectedSize={15} defaultCountry={locale}
optionsSize={22} selectedSize={15}
showSelectedLabel={false} optionsSize={22}
/>); showSelectedLabel={false}
/>
);
}; };
export default LanguageSelector; export default LanguageSelector;

@ -1,13 +1,13 @@
import React from 'react'; import React from "react";
import logo from './loader-pulse-2.gif'; import logo from "./loader-pulse-2.gif";
import './style.css'; import "./style.css";
const Loader = () => { const Loader = () => {
return ( return (
<div className="loader bg-primary"> <div className="loader bg-primary">
<img src={logo} alt="Loading..." /> <img src={logo} alt="Loading..." />
</div>); </div>
);
}; };
export default Loader; export default Loader;

@ -46,23 +46,31 @@ const AT_LEAST_2_CANDIDATES_ERROR = "Please add at least 2 candidates.";
const NO_TITLE_ERROR = "Please add a title."; const NO_TITLE_ERROR = "Please add a title.";
const isValidDate = date => date instanceof Date && !isNaN(date); const isValidDate = date => date instanceof Date && !isNaN(date);
const getOnlyValidDate = date => isValidDate(date)?date:new Date(); const getOnlyValidDate = date => (isValidDate(date) ? date : new Date());
// Convert a Date object into YYYY-MM-DD // Convert a Date object into YYYY-MM-DD
const dateToISO = date => getOnlyValidDate(date).toISOString().substring(0, 10); const dateToISO = date =>
getOnlyValidDate(date)
.toISOString()
.substring(0, 10);
// Retrieve the current hour, minute, sec, ms, time into a timestamp // Retrieve the current hour, minute, sec, ms, time into a timestamp
const hours = date => getOnlyValidDate(date).getHours() * 3600 * 1000; const hours = date => getOnlyValidDate(date).getHours() * 3600 * 1000;
const minutes = date => getOnlyValidDate(date).getMinutes() * 60 * 1000; const minutes = date => getOnlyValidDate(date).getMinutes() * 60 * 1000;
const seconds = date => getOnlyValidDate(date).getSeconds() * 1000; const seconds = date => getOnlyValidDate(date).getSeconds() * 1000;
const ms = date => getOnlyValidDate(date).getMilliseconds(); const ms = date => getOnlyValidDate(date).getMilliseconds();
const time = date => hours(getOnlyValidDate(date)) + minutes(getOnlyValidDate(date)) + seconds(getOnlyValidDate(date)) + ms(getOnlyValidDate(date)); const time = date =>
hours(getOnlyValidDate(date)) +
minutes(getOnlyValidDate(date)) +
seconds(getOnlyValidDate(date)) +
ms(getOnlyValidDate(date));
// Retrieve the time part from a timestamp and remove the day. Return a int. // Retrieve the time part from a timestamp and remove the day. Return a int.
const timeMinusDate = date => time(getOnlyValidDate(date)); const timeMinusDate = date => time(getOnlyValidDate(date));
// Retrieve the day and remove the time. Return a Date // Retrieve the day and remove the time. Return a Date
const dateMinusTime = date => new Date(getOnlyValidDate(date).getTime() - time(getOnlyValidDate(date))); const dateMinusTime = date =>
new Date(getOnlyValidDate(date).getTime() - time(getOnlyValidDate(date)));
const DragHandle = sortableHandle(({ children }) => ( const DragHandle = sortableHandle(({ children }) => (
<span className="input-group-text indexNumber">{children}</span> <span className="input-group-text indexNumber">{children}</span>
@ -558,7 +566,9 @@ class CreateElection extends Component {
this.setState({ this.setState({
finish: new Date( finish: new Date(
timeMinusDate(finish) + timeMinusDate(finish) +
new Date(getOnlyValidDate(e.target.valueAsNumber)).getTime() new Date(
getOnlyValidDate(e.target.valueAsNumber)
).getTime()
) )
}); });
}} }}

@ -1,15 +1,16 @@
import React, {Component} from 'react'; import React, { Component } from "react";
import {Col, Container, Row} from 'reactstrap'; import { Col, Container, Row } from "reactstrap";
import {Link} from 'react-router-dom'; import { Link } from "react-router-dom";
import {withTranslation, Trans} from 'react-i18next'; import { withTranslation, Trans } from "react-i18next";
import {faCopy, faUsers, faExclamationTriangle} from '@fortawesome/free-solid-svg-icons'; import {
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; faCopy,
import logoLine from '../../logos/logo-line-white.svg'; faUsers,
import {AppContext} from '../../AppContext'; faExclamationTriangle
import CopyField from '../CopyField'; } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import logoLine from "../../logos/logo-line-white.svg";
import { AppContext } from "../../AppContext";
import CopyField from "../CopyField";
class CreateSuccess extends Component { class CreateSuccess extends Component {
static contextType = AppContext; static contextType = AppContext;
@ -17,10 +18,8 @@ class CreateSuccess extends Component {
super(props); super(props);
const electionSlug = this.props.match.params.slug; const electionSlug = this.props.match.params.slug;
this.state = { this.state = {
urlOfVote: urlOfVote: window.location.origin + "/vote/" + electionSlug,
window.location.origin + '/vote/' + electionSlug, urlOfResult: window.location.origin + "/result/" + electionSlug
urlOfResult:
window.location.origin + '/result/' + electionSlug,
}; };
this.urlVoteField = React.createRef(); this.urlVoteField = React.createRef();
this.urlResultField = React.createRef(); this.urlResultField = React.createRef();
@ -30,27 +29,25 @@ class CreateSuccess extends Component {
const input = this.urlResultField.current; const input = this.urlResultField.current;
input.focus(); input.focus();
input.select(); input.select();
document.execCommand('copy'); document.execCommand("copy");
}; };
render() { render() {
const {t} = this.props; const { t } = this.props;
const electionLink = this.props.invitationOnly ? ( const electionLink = this.props.invitationOnly ? (
<> <>
<p className="mt-4 mb-1"> <p className="mt-4 mb-1">
{t('Voters received a link to vote by email. Each link can be used only once!')} {t(
"Voters received a link to vote by email. Each link can be used only once!"
)}
</p> </p>
</> </>
) : ( ) : (
<> <>
<p className="mt-4 mb-1"> <p className="mt-4 mb-1">
{t('You can now share the election link to participants:')} {t("You can now share the election link to participants:")}
</p> </p>
<CopyField <CopyField value={this.state.urlOfVote} icon={faCopy} t={t} />
value={this.state.urlOfVote}
icon={faCopy}
t={t}
/>
</> </>
); );
@ -63,27 +60,25 @@ class CreateSuccess extends Component {
</Row> </Row>
<Row className="mt-4"> <Row className="mt-4">
<Col className="text-center offset-lg-3" lg="6"> <Col className="text-center offset-lg-3" lg="6">
<h2>{t('Successful election creation!')}</h2> <h2>{t("Successful election creation!")}</h2>
{electionLink} {electionLink}
<p className="mt-4 mb-1"> <p className="mt-4 mb-1">
{t('Here is the link for the results in real time:')} {t("Here is the link for the results in real time:")}
</p> </p>
<CopyField <CopyField value={this.state.urlOfResult} icon={faCopy} t={t} />
value={this.state.urlOfResult}
icon={faCopy}
t={t}
/>
</Col> </Col>
</Row> </Row>
<Row className="mt-4 mb-4"> <Row className="mt-4 mb-4">
<Col className="text-center offset-lg-3" lg="6"> <Col className="text-center offset-lg-3" lg="6">
<div className=" bg-danger text-white p-2 "> <div className=" bg-danger text-white p-2 ">
<h4 className="m-0 p-0 text-center"> <h4 className="m-0 p-0 text-center">
<FontAwesomeIcon icon={faExclamationTriangle} className="mr-2" /> <FontAwesomeIcon
{t('Keep these links carefully')} icon={faExclamationTriangle}
className="mr-2"
/>
{t("Keep these links carefully")}
</h4> </h4>
<p className="small m-2 p-0"> <p className="small m-2 p-0">
<Trans i18nKey="t"> <Trans i18nKey="t">
@ -99,10 +94,11 @@ class CreateSuccess extends Component {
<Row className="mt-4 mb-4"> <Row className="mt-4 mb-4">
<Col className="text-center"> <Col className="text-center">
<Link <Link
to={'/vote/' + this.props.match.params.slug} to={"/vote/" + this.props.match.params.slug}
className="btn btn-success"> className="btn btn-success"
>
<FontAwesomeIcon icon={faUsers} className="mr-2" /> <FontAwesomeIcon icon={faUsers} className="mr-2" />
{t('Participate now!')} {t("Participate now!")}
</Link> </Link>
</Col> </Col>
</Row> </Row>

@ -1,14 +1,12 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { withTranslation } from 'react-i18next'; import { withTranslation } from "react-i18next";
import { Container, Row, Col, Button, Input } from "reactstrap"; import { Container, Row, Col, Button, Input } from "reactstrap";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faRocket } from "@fortawesome/free-solid-svg-icons"; import { faRocket } from "@fortawesome/free-solid-svg-icons";
import { Redirect } from "react-router-dom"; import { Redirect } from "react-router-dom";
import logoLine from "../../logos/logo-line-white.svg"; import logoLine from "../../logos/logo-line-white.svg";
class Home extends Component { class Home extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -29,7 +27,7 @@ class Home extends Component {
}; };
render() { render() {
const {t} = this.props; const { t } = this.props;
const redirect = this.state.redirect; const redirect = this.state.redirect;
if (redirect) { if (redirect) {
@ -53,7 +51,9 @@ class Home extends Component {
<Row> <Row>
<Col className="text-center"> <Col className="text-center">
<h3> <h3>
{t("Simple and free: organize an election with Majority Judgment.")} {t(
"Simple and free: organize an election with Majority Judgment."
)}
</h3> </h3>
</Col> </Col>
</Row> </Row>
@ -77,7 +77,7 @@ class Home extends Component {
className="btn btn-block btn-secondary mt-2" className="btn btn-block btn-secondary mt-2"
> >
<FontAwesomeIcon icon={faRocket} className="mr-2" /> <FontAwesomeIcon icon={faRocket} className="mr-2" />
{t("Start")} {t("Start")}
</Button> </Button>
</Col> </Col>
</Row> </Row>

@ -1,6 +1,6 @@
import React, {Component} from 'react'; import React, { Component } from "react";
import {withTranslation} from 'react-i18next'; import { withTranslation } from "react-i18next";
import {resolve} from 'url'; import { resolve } from "url";
import { import {
Container, Container,
Row, Row,
@ -9,12 +9,11 @@ import {
Card, Card,
CardHeader, CardHeader,
CardBody, CardBody,
Table, Table
} from 'reactstrap'; } from "reactstrap";
import {i18nGrades} from '../../Util'; import { i18nGrades } from "../../Util";
import {AppContext} from '../../AppContext'; import { AppContext } from "../../AppContext";
import {errorMessage, Error} from '../../Errors'; import { errorMessage, Error } from "../../Errors";
class Result extends Component { class Result extends Component {
static contextType = AppContext; static contextType = AppContext;
@ -34,7 +33,7 @@ class Result extends Component {
collapseGraphics: false, collapseGraphics: false,
collapseProfiles: false, collapseProfiles: false,
electionGrades: i18nGrades(), electionGrades: i18nGrades(),
errorMessage: '', errorMessage: ""
}; };
} }
@ -42,7 +41,7 @@ class Result extends Component {
if (!response.ok) { if (!response.ok) {
response.json().then(response => { response.json().then(response => {
this.setState(state => ({ this.setState(state => ({
errorMessage: errorMessage(response, this.props.t), errorMessage: errorMessage(response, this.props.t)
})); }));
}); });
throw Error(response); throw Error(response);
@ -55,22 +54,22 @@ class Result extends Component {
id: c.id, id: c.id,
name: c.name, name: c.name,
profile: c.profile, profile: c.profile,
grade: c.grade, grade: c.grade
})); }));
this.setState(state => ({candidates: candidates})); this.setState(state => ({ candidates: candidates }));
return response; return response;
}; };
detailsToState = response => { detailsToState = response => {
const numGrades = response.num_grades; const numGrades = response.num_grades;
const colSizeGradeLg = Math.floor( const colSizeGradeLg = Math.floor(
(12 - this.state.colSizeCandidateLg) / numGrades, (12 - this.state.colSizeCandidateLg) / numGrades
); );
const colSizeGradeMd = Math.floor( const colSizeGradeMd = Math.floor(
(12 - this.state.colSizeCandidateMd) / numGrades, (12 - this.state.colSizeCandidateMd) / numGrades
); );
const colSizeGradeXs = Math.floor( const colSizeGradeXs = Math.floor(
(12 - this.state.colSizeCandidateXs) / numGrades, (12 - this.state.colSizeCandidateXs) / numGrades
); );
this.setState(state => ({ this.setState(state => ({
title: response.title, title: response.title,
@ -90,7 +89,7 @@ class Result extends Component {
12 - colSizeGradeXs * numGrades > 0 12 - colSizeGradeXs * numGrades > 0
? 12 - colSizeGradeXs * numGrades ? 12 - colSizeGradeXs * numGrades
: 12, : 12,
electionGrades: i18nGrades().slice(0, numGrades), electionGrades: i18nGrades().slice(0, numGrades)
})); }));
return response; return response;
}; };
@ -98,38 +97,38 @@ class Result extends Component {
componentDidMount() { componentDidMount() {
// get details of the election // get details of the election
const electionSlug = this.props.match.params.slug; const electionSlug = this.props.match.params.slug;
if (electionSlug === 'dev') { if (electionSlug === "dev") {
const dataTest = [ const dataTest = [
{ {
name: 'BB', name: "BB",
id: 1, id: 1,
score: 1.0, score: 1.0,
profile: [1, 1, 0, 0, 0, 0, 0], profile: [1, 1, 0, 0, 0, 0, 0],
grade: 1, grade: 1
}, },
{ {
name: 'CC', name: "CC",
id: 2, id: 2,
score: 1.0, score: 1.0,
profile: [0, 0, 2, 0, 0, 0, 0], profile: [0, 0, 2, 0, 0, 0, 0],
grade: 2, grade: 2
}, },
{ {
name: 'AA', name: "AA",
id: 0, id: 0,
score: 1.0, score: 1.0,
profile: [1, 1, 0, 0, 0, 0, 0], profile: [1, 1, 0, 0, 0, 0, 0],
grade: 1, grade: 1
}, }
]; ];
this.setState({candidates: dataTest}); this.setState({ candidates: dataTest });
} else { } else {
const detailsEndpoint = resolve( const detailsEndpoint = resolve(
this.context.urlServer, this.context.urlServer,
this.context.routesServer.getElection.replace( this.context.routesServer.getElection.replace(
new RegExp(':slug', 'g'), new RegExp(":slug", "g"),
electionSlug, electionSlug
), )
); );
fetch(detailsEndpoint) fetch(detailsEndpoint)
@ -142,9 +141,9 @@ class Result extends Component {
const resultsEndpoint = resolve( const resultsEndpoint = resolve(
this.context.urlServer, this.context.urlServer,
this.context.routesServer.getResultsElection.replace( this.context.routesServer.getResultsElection.replace(
new RegExp(':slug', 'g'), new RegExp(":slug", "g"),
electionSlug, electionSlug
), )
); );
fetch(resultsEndpoint) fetch(resultsEndpoint)
@ -156,21 +155,20 @@ class Result extends Component {
} }
toggleGraphics = () => { toggleGraphics = () => {
this.setState(state => ({collapseGraphics: !state.collapseGraphics})); this.setState(state => ({ collapseGraphics: !state.collapseGraphics }));
}; };
toggleProfiles = () => { toggleProfiles = () => {
this.setState(state => ({collapseProfiles: !state.collapseProfiles})); this.setState(state => ({ collapseProfiles: !state.collapseProfiles }));
}; };
render() { render() {
const {errorMessage, candidates, electionGrades} = this.state; const { errorMessage, candidates, electionGrades } = this.state;
const {t} = this.props; const { t } = this.props;
const i18nGradesObject = i18nGrades(); const i18nGradesObject = i18nGrades();
const offsetGrade = i18nGradesObject.length-(this.state.numGrades); const offsetGrade = i18nGradesObject.length - this.state.numGrades;
if (errorMessage && errorMessage !== '') { if (errorMessage && errorMessage !== "") {
return <Error value={errorMessage} />; return <Error value={errorMessage} />;
} }
@ -192,26 +190,29 @@ class Result extends Component {
<Row className="mt-5"> <Row className="mt-5">
<Col> <Col>
<h1>{t('Results of the election:')}</h1> <h1>{t("Results of the election:")}</h1>
<h5> <h5>
<small> <small>
{t('Number of votes:')} {t("Number of votes:")}
{' ' + numVotes} {" " + numVotes}
</small> </small>
</h5> </h5>
<hr className="mb-5" /> <hr className="mb-5" />
<ol> <ol>
{candidates.map((candidate, i) => { {candidates.map((candidate, i) => {
const gradeValue=candidate.grade+offsetGrade; const gradeValue = candidate.grade + offsetGrade;
return ( return (
<li key={i} className="mt-2"> <li key={i} className="mt-2">
<span className="mt-2 ml-2">{candidate.name}</span> <span className="mt-2 ml-2">{candidate.name}</span>
<span <span
className="badge badge-light ml-2 mt-2" className="badge badge-light ml-2 mt-2"
style={{ style={{
backgroundColor: electionGrades.slice(0).reverse()[(candidate.grade)].color, backgroundColor: electionGrades.slice(0).reverse()[
color: '#fff', candidate.grade
}}> ].color,
color: "#fff"
}}
>
{i18nGradesObject.slice(0).reverse()[gradeValue].label} {i18nGradesObject.slice(0).reverse()[gradeValue].label}
</span> </span>
{/* <span className="badge badge-dark mt-2 ml-2"> {/* <span className="badge badge-dark mt-2 ml-2">
@ -230,10 +231,11 @@ class Result extends Component {
<CardHeader className="pointer" onClick={this.toggleGraphics}> <CardHeader className="pointer" onClick={this.toggleGraphics}>
<h4 <h4
className={ className={
'm-0 panel-title ' + "m-0 panel-title " +
(this.state.collapseGraphics ? 'collapsed' : '') (this.state.collapseGraphics ? "collapsed" : "")
}> }
{t('Graph')} >
{t("Graph")}
</h4> </h4>
</CardHeader> </CardHeader>
<Collapse isOpen={this.state.collapseGraphics}> <Collapse isOpen={this.state.collapseGraphics}>
@ -241,42 +243,46 @@ class Result extends Component {
<div> <div>
<div <div
className="median" className="median"
style={{height: candidates.length * 28 + 30}} style={{ height: candidates.length * 28 + 30 }}
/> />
<table style={{width: '100%'}}> <table style={{ width: "100%" }}>
<tbody> <tbody>
{candidates.map((candidate, i) => { {candidates.map((candidate, i) => {
return ( return (
<tr key={i}> <tr key={i}>
<td style={{width: '30px'}}>{i + 1}</td> <td style={{ width: "30px" }}>{i + 1}</td>
{/*candidate.label*/} {/*candidate.label*/}
<td> <td>
<table style={{width: '100%'}}> <table style={{ width: "100%" }}>
<tbody> <tbody>
<tr> <tr>
{gradeIds.slice(0).reverse().map((id, i) => { {gradeIds
const value = candidate.profile[id]; .slice(0)
if (value > 0) { .reverse()
let percent = .map((id, i) => {
(value * 100) / numVotes + '%'; const value = candidate.profile[id];
if (i === 0) { if (value > 0) {
percent = 'auto'; let percent =
(value * 100) / numVotes + "%";
if (i === 0) {
percent = "auto";
}
return (
<td
key={i}
style={{
width: percent,
backgroundColor: this.state
.electionGrades[i].color
}}
>
&nbsp;
</td>
);
} else {
return null;
} }
return ( })}
<td
key={i}
style={{
width: percent,
backgroundColor: this.state
.electionGrades[i].color,
}}>
&nbsp;
</td>
);
} else {
return null;
}
})}
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -292,7 +298,7 @@ class Result extends Component {
{candidates.map((candidate, i) => { {candidates.map((candidate, i) => {
return ( return (
<span key={i}> <span key={i}>
{i > 0 ? ', ' : ''} {i > 0 ? ", " : ""}
<b>{i + 1}</b>: {candidate.name} <b>{i + 1}</b>: {candidate.name}
</span> </span>
); );
@ -308,8 +314,9 @@ class Result extends Component {
className="badge badge-light mr-2 mt-2" className="badge badge-light mr-2 mt-2"
style={{ style={{
backgroundColor: grade.color, backgroundColor: grade.color,
color: '#fff', color: "#fff"
}}> }}
>
{grade.label} {grade.label}
</span> </span>
); );
@ -327,10 +334,11 @@ class Result extends Component {
<CardHeader className="pointer" onClick={this.toggleProfiles}> <CardHeader className="pointer" onClick={this.toggleProfiles}>
<h4 <h4
className={ className={
'm-0 panel-title ' + "m-0 panel-title " +
(this.state.collapseProfiles ? 'collapsed' : '') (this.state.collapseProfiles ? "collapsed" : "")
}> }
{t('Preference profile')} >
{t("Preference profile")}
</h4> </h4>
</CardHeader> </CardHeader>
<Collapse isOpen={this.state.collapseProfiles}> <Collapse isOpen={this.state.collapseProfiles}>
@ -347,9 +355,10 @@ class Result extends Component {
className="badge badge-light" className="badge badge-light"
style={{ style={{
backgroundColor: grade.color, backgroundColor: grade.color,
color: '#fff', color: "#fff"
}}> }}
{grade.label}{' '} >
{grade.label}{" "}
</span> </span>
</th> </th>
); );
@ -361,14 +370,17 @@ class Result extends Component {
return ( return (
<tr key={i}> <tr key={i}>
<td>{i + 1}</td> <td>{i + 1}</td>
{gradeIds.slice(0).reverse().map((id, i) => { {gradeIds
const value = candidate.profile[id]; .slice(0)
const percent = ( .reverse()
(value / numVotes) * .map((id, i) => {
100 const value = candidate.profile[id];
).toFixed(1); const percent = (
return <td key={i}>{percent} %</td>; (value / numVotes) *
})} 100
).toFixed(1);
return <td key={i}>{percent} %</td>;
})}
</tr> </tr>
); );
})} })}
@ -379,7 +391,7 @@ class Result extends Component {
{candidates.map((candidate, i) => { {candidates.map((candidate, i) => {
return ( return (
<span key={i}> <span key={i}>
{i > 0 ? ', ' : ''} {i > 0 ? ", " : ""}
<b>{i + 1}</b>: {candidate.name} <b>{i + 1}</b>: {candidate.name}
</span> </span>
); );

@ -13,7 +13,7 @@ class UnknownElection extends Component {
} }
render() { render() {
const {t} = this.props; const { t } = this.props;
return ( return (
<Container> <Container>
<Row> <Row>
@ -23,14 +23,18 @@ class UnknownElection extends Component {
</Row> </Row>
<Row className="mt-4"> <Row className="mt-4">
<Col className="text-center"> <Col className="text-center">
<h2>{t("Oops! This election does not exist or it is not available anymore.")}</h2> <h2>
{t(
"Oops! This election does not exist or it is not available anymore."
)}
</h2>
<p>{t("You can start another election.")}</p> <p>{t("You can start another election.")}</p>
</Col> </Col>
</Row> </Row>
<Row className="mt-4"> <Row className="mt-4">
<Col className="text-center"> <Col className="text-center">
<Link to="/" className="btn btn-secondary"> <Link to="/" className="btn btn-secondary">
{t("Go back to homepage")} {t("Go back to homepage")}
</Link> </Link>
</Col> </Col>
</Row> </Row>

@ -1,14 +1,14 @@
import React, {Component} from 'react'; import React, { Component } from "react";
import {Redirect} from 'react-router-dom'; import { Redirect } from "react-router-dom";
import {withTranslation} from 'react-i18next'; import { withTranslation } from "react-i18next";
import {Button, Col, Container, Row} from 'reactstrap'; import { Button, Col, Container, Row } from "reactstrap";
import {toast, ToastContainer} from 'react-toastify'; import { toast, ToastContainer } from "react-toastify";
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {faCheck} from '@fortawesome/free-solid-svg-icons'; import { faCheck } from "@fortawesome/free-solid-svg-icons";
import {resolve} from 'url'; import { resolve } from "url";
import {i18nGrades} from '../../Util'; import { i18nGrades } from "../../Util";
import {AppContext} from '../../AppContext'; import { AppContext } from "../../AppContext";
import {errorMessage} from '../../Errors'; import { errorMessage } from "../../Errors";
const shuffle = array => array.sort(() => Math.random() - 0.5); const shuffle = array => array.sort(() => Math.random() - 0.5);
@ -29,7 +29,7 @@ class Vote extends Component {
colSizeGradeXs: 1, colSizeGradeXs: 1,
redirectTo: null, redirectTo: null,
electionGrades: i18nGrades(), electionGrades: i18nGrades(),
errorMsg: "", errorMsg: ""
}; };
} }
@ -37,9 +37,9 @@ class Vote extends Component {
if (!response.ok) { if (!response.ok) {
response.json().then(response => { response.json().then(response => {
console.log(response); console.log(response);
const {t} = this.props; const { t } = this.props;
this.setState(state => ({ this.setState(state => ({
errorMsg: errorMessage(response, t) errorMsg: errorMessage(response, t)
})); }));
}); });
throw Error(response); throw Error(response);
@ -51,18 +51,18 @@ class Vote extends Component {
const numGrades = response.num_grades; const numGrades = response.num_grades;
const candidates = response.candidates.map((c, i) => ({ const candidates = response.candidates.map((c, i) => ({
id: i, id: i,
label: c, label: c
})); }));
shuffle(candidates); shuffle(candidates);
const colSizeGradeLg = Math.floor( const colSizeGradeLg = Math.floor(
(12 - this.state.colSizeCandidateLg) / numGrades, (12 - this.state.colSizeCandidateLg) / numGrades
); );
const colSizeGradeMd = Math.floor( const colSizeGradeMd = Math.floor(
(12 - this.state.colSizeCandidateMd) / numGrades, (12 - this.state.colSizeCandidateMd) / numGrades
); );
const colSizeGradeXs = Math.floor( const colSizeGradeXs = Math.floor(
(12 - this.state.colSizeCandidateXs) / numGrades, (12 - this.state.colSizeCandidateXs) / numGrades
); );
this.setState(state => ({ this.setState(state => ({
@ -83,7 +83,7 @@ class Vote extends Component {
colSizeCandidateXs: colSizeCandidateXs:
12 - colSizeGradeXs * numGrades > 0 12 - colSizeGradeXs * numGrades > 0
? 12 - colSizeGradeXs * numGrades ? 12 - colSizeGradeXs * numGrades
: 12, : 12
})); }));
return response; return response;
}; };
@ -94,9 +94,9 @@ class Vote extends Component {
const detailsEndpoint = resolve( const detailsEndpoint = resolve(
this.context.urlServer, this.context.urlServer,
this.context.routesServer.getElection.replace( this.context.routesServer.getElection.replace(
new RegExp(':slug', 'g'), new RegExp(":slug", "g"),
electionSlug, electionSlug
), )
); );
fetch(detailsEndpoint) fetch(detailsEndpoint)
.then(this.handleErrors) .then(this.handleErrors)
@ -107,33 +107,33 @@ class Vote extends Component {
handleGradeClick = event => { handleGradeClick = event => {
let data = { let data = {
id: parseInt(event.currentTarget.getAttribute('data-id')), id: parseInt(event.currentTarget.getAttribute("data-id")),
value: parseInt(event.currentTarget.value), value: parseInt(event.currentTarget.value)
}; };
//remove candidate //remove candidate
let ratedCandidates = this.state.ratedCandidates.filter( let ratedCandidates = this.state.ratedCandidates.filter(
ratedCandidate => ratedCandidate.id !== data.id, ratedCandidate => ratedCandidate.id !== data.id
); );
ratedCandidates.push(data); ratedCandidates.push(data);
this.setState({ratedCandidates}); this.setState({ ratedCandidates });
}; };
handleSubmitWithoutAllRate = () => { handleSubmitWithoutAllRate = () => {
const {t} = this.props; const { t } = this.props;
toast.error(t('You have to judge every candidate/proposal!'), { toast.error(t("You have to judge every candidate/proposal!"), {
position: toast.POSITION.TOP_CENTER, position: toast.POSITION.TOP_CENTER
}); });
}; };
handleSubmit = event => { handleSubmit = event => {
event.preventDefault(); event.preventDefault();
const {ratedCandidates} = this.state; const { ratedCandidates } = this.state;
const electionSlug = this.props.match.params.slug; const electionSlug = this.props.match.params.slug;
const token = this.props.location.search.substr(7); const token = this.props.location.search.substr(7);
const endpoint = resolve( const endpoint = resolve(
this.context.urlServer, this.context.urlServer,
this.context.routesServer.voteElection, this.context.routesServer.voteElection
); );
const gradesById = {}; const gradesById = {};
@ -147,29 +147,29 @@ class Vote extends Component {
const payload = { const payload = {
election: electionSlug, election: electionSlug,
grades_by_candidate: gradesByCandidate, grades_by_candidate: gradesByCandidate
}; };
if (token !== '') { if (token !== "") {
payload['token'] = token; payload["token"] = token;
} }
fetch(endpoint, { fetch(endpoint, {
method: 'POST', method: "POST",
headers: {'Content-Type': 'application/json'}, headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload), body: JSON.stringify(payload)
}) })
.then(this.handleErrors) .then(this.handleErrors)
.then(result => .then(result =>
this.setState({redirectTo: '/vote-success/' + electionSlug}), this.setState({ redirectTo: "/vote-success/" + electionSlug })
) )
.catch(error => error); .catch(error => error);
}; };
render() { render() {
const {t} = this.props; const { t } = this.props;
const {candidates, errorMsg, redirectTo} = this.state; const { candidates, errorMsg, redirectTo } = this.state;
const grades = i18nGrades(); const grades = i18nGrades();
const offsetGrade = grades.length-this.state.numGrades; const offsetGrade = grades.length - this.state.numGrades;
const electionGrades = grades.slice(0, this.state.numGrades); const electionGrades = grades.slice(0, this.state.numGrades);
if (redirectTo) { if (redirectTo) {
@ -177,15 +177,15 @@ class Vote extends Component {
} }
if (errorMsg !== "") { if (errorMsg !== "") {
return( return (
<Container> <Container>
<Row> <Row>
<Col> <Col>
<h3>{errorMsg}</h3> <h3>{errorMsg}</h3>
</Col> </Col>
</Row> </Row>
</Container> </Container>
); );
} }
return ( return (
@ -201,7 +201,8 @@ class Vote extends Component {
<Col <Col
xs={this.state.colSizeCandidateXs} xs={this.state.colSizeCandidateXs}
md={this.state.colSizeCandidateMd} md={this.state.colSizeCandidateMd}
lg={this.state.colSizeCandidateLg}> lg={this.state.colSizeCandidateLg}
>
<h5>&nbsp;</h5> <h5>&nbsp;</h5>
</Col> </Col>
{electionGrades.map((grade, gradeId) => { {electionGrades.map((grade, gradeId) => {
@ -212,10 +213,12 @@ class Vote extends Component {
lg={this.state.colSizeGradeLg} lg={this.state.colSizeGradeLg}
key={gradeId} key={gradeId}
className="text-center p-0" className="text-center p-0"
style={{lineHeight: 2}}> style={{ lineHeight: 2 }}
>
<small <small
className="nowrap bold badge" className="nowrap bold badge"
style={{backgroundColor: grade.color, color: '#fff'}}> style={{ backgroundColor: grade.color, color: "#fff" }}
>
{grade.label} {grade.label}
</small> </small>
</Col> </Col>
@ -229,81 +232,95 @@ class Vote extends Component {
<Col <Col
xs={this.state.colSizeCandidateXs} xs={this.state.colSizeCandidateXs}
md={this.state.colSizeCandidateMd} md={this.state.colSizeCandidateMd}
lg={this.state.colSizeCandidateLg}> lg={this.state.colSizeCandidateLg}
>
<h5 className="m-0">{candidate.label}</h5> <h5 className="m-0">{candidate.label}</h5>
<hr className="d-lg-none" /> <hr className="d-lg-none" />
</Col> </Col>
{electionGrades.map((grade, gradeId) => { {electionGrades.map((grade, gradeId) => {
console.assert(gradeId < this.state.numGrades) console.assert(gradeId < this.state.numGrades);
const gradeValue = grade.value-offsetGrade; const gradeValue = grade.value - offsetGrade;
return ( return (
<Col <Col
xs={this.state.colSizeGradeXs} xs={this.state.colSizeGradeXs}
md={this.state.colSizeGradeMd} md={this.state.colSizeGradeMd}
lg={this.state.colSizeGradeLg} lg={this.state.colSizeGradeLg}
key={gradeId} key={gradeId}
className="text-lg-center"> className="text-lg-center"
>
<label <label
htmlFor={'candidateGrade' + candidateId + '-' + gradeValue} htmlFor={
className="check"> "candidateGrade" + candidateId + "-" + gradeValue
}
className="check"
>
<small <small
className="nowrap d-lg-none ml-2 bold badge" className="nowrap d-lg-none ml-2 bold badge"
style={ style={
this.state.ratedCandidates.find(function( this.state.ratedCandidates.find(function(
ratedCandidat, ratedCandidat
) { ) {
return ( return (
JSON.stringify(ratedCandidat) === JSON.stringify(ratedCandidat) ===
JSON.stringify({id: candidate.id, value: gradeValue}) JSON.stringify({
id: candidate.id,
value: gradeValue
})
); );
}) })
? {backgroundColor: grade.color, color: '#fff'} ? { backgroundColor: grade.color, color: "#fff" }
: { : {
backgroundColor: 'transparent', backgroundColor: "transparent",
color: '#000', color: "#000"
} }
}> }
>
{grade.label} {grade.label}
</small> </small>
<input <input
type="radio" type="radio"
name={'candidate' + candidateId} name={"candidate" + candidateId}
id={'candidateGrade' + candidateId + '-' + gradeValue} id={"candidateGrade" + candidateId + "-" + gradeValue}
data-index={candidateId} data-index={candidateId}
data-id={candidate.id} data-id={candidate.id}
value={grade.value-offsetGrade} value={grade.value - offsetGrade}
onClick={this.handleGradeClick} onClick={this.handleGradeClick}
defaultChecked={this.state.ratedCandidates.find( defaultChecked={this.state.ratedCandidates.find(
function(element) { function(element) {
return ( return (
JSON.stringify(element) === JSON.stringify(element) ===
JSON.stringify({id: candidate.id, value: gradeValue}) JSON.stringify({
id: candidate.id,
value: gradeValue
})
); );
}, }
)} )}
/> />
<span <span
className="checkmark" className="checkmark"
style={ style={
this.state.ratedCandidates.find(function( this.state.ratedCandidates.find(function(
ratedCandidat, ratedCandidat
) { ) {
return ( return (
JSON.stringify(ratedCandidat) === JSON.stringify(ratedCandidat) ===
JSON.stringify({id: candidate.id, value: gradeValue}) JSON.stringify({
id: candidate.id,
value: gradeValue
})
); );
}) })
? {backgroundColor: grade.color, color: '#fff'} ? { backgroundColor: grade.color, color: "#fff" }
: { : {
backgroundColor: 'transparent', backgroundColor: "transparent",
color: '#000', color: "#000"
} }
} }
/> />
</label> </label>
</Col> </Col>
);
)
})} })}
</Row> </Row>
); );
@ -316,14 +333,15 @@ class Vote extends Component {
<Button <Button
type="button" type="button"
onClick={this.handleSubmitWithoutAllRate} onClick={this.handleSubmitWithoutAllRate}
className="btn btn-dark "> className="btn btn-dark "
>
<FontAwesomeIcon icon={faCheck} className="mr-2" /> <FontAwesomeIcon icon={faCheck} className="mr-2" />
{t('Validate')} {t("Validate")}
</Button> </Button>
) : ( ) : (
<Button type="submit" className="btn btn-success "> <Button type="submit" className="btn btn-success ">
<FontAwesomeIcon icon={faCheck} className="mr-2" /> <FontAwesomeIcon icon={faCheck} className="mr-2" />
{t('Validate')} {t("Validate")}
</Button> </Button>
)} )}
</Col> </Col>

@ -1,6 +1,6 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { Col, Container, Row } from "reactstrap"; import { Col, Container, Row } from "reactstrap";
import {withTranslation} from 'react-i18next'; import { withTranslation } from "react-i18next";
import logoLine from "../../logos/logo-line-white.svg"; import logoLine from "../../logos/logo-line-white.svg";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { AppContext } from "../../AppContext"; import { AppContext } from "../../AppContext";
@ -9,7 +9,7 @@ import Paypal from "../banner/Paypal";
class VoteSuccess extends Component { class VoteSuccess extends Component {
static contextType = AppContext; static contextType = AppContext;
render() { render() {
const {t} = this.props; const { t } = this.props;
return ( return (
<Container> <Container>
<Row> <Row>
@ -21,16 +21,16 @@ class VoteSuccess extends Component {
<Col className="text-center offset-lg-3" lg="6"> <Col className="text-center offset-lg-3" lg="6">
<h2>{t("Your participation was recorded with success!")}</h2> <h2>{t("Your participation was recorded with success!")}</h2>
<p>{t("Thanks for your participation.")}</p> <p>{t("Thanks for your participation.")}</p>
<div className="mt-3"> <div className="mt-3">
<Paypal btnColor="btn-success"/> <Paypal btnColor="btn-success" />
</div> </div>
</Col> </Col>
</Row> </Row>
<Row className="mt-4"> <Row className="mt-4">
<Col className="text-center"> <Col className="text-center">
<Link to="/" className="btn btn-secondary"> <Link to="/" className="btn btn-secondary">
{t("Go back to homepage")} {t("Go back to homepage")}
</Link> </Link>
</Col> </Col>
</Row> </Row>

@ -1,9 +1,8 @@
import React from 'react'; import React from "react";
import Loader from '../loader'; import Loader from "../loader";
const Wait = () => { const Wait = () => {
return (<Loader />); return <Loader />;
}; };
export default Wait; export default Wait;

@ -1,29 +1,28 @@
import i18n from 'i18next'; import i18n from "i18next";
import XHR from 'i18next-xhr-backend'; import XHR from "i18next-xhr-backend";
import LanguageDetector from 'i18next-browser-languagedetector'; import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from 'react-i18next'; import { initReactI18next } from "react-i18next";
i18n i18n
.use(XHR) .use(XHR)
.use(LanguageDetector) .use(LanguageDetector)
.use(initReactI18next) // bind react-i18next to the instance .use(initReactI18next) // bind react-i18next to the instance
.init({ .init({
fallbackLng: 'en', fallbackLng: "en",
debug: true, debug: true,
saveMissing: true, // send not translated keys to endpoint saveMissing: true, // send not translated keys to endpoint
defaultValue: "__STRING_NOT_TRANSLATED__", defaultValue: "__STRING_NOT_TRANSLATED__",
keySeparator: '>', keySeparator: ">",
nsSeparator: '|', nsSeparator: "|",
backend: { backend: {
loadPath: '/locale/i18n/{{lng}}/resource.json', loadPath: "/locale/i18n/{{lng}}/resource.json"
// path to post missing resources // path to post missing resources
}, },
interpolation: { interpolation: {
escapeValue: false, // not needed for react!! escapeValue: false // not needed for react!!
}, }
// react i18next special options (optional) // react i18next special options (optional)
// override if needed - omit if ok with defaults // override if needed - omit if ok with defaults
@ -39,5 +38,4 @@ i18n
*/ */
}); });
export default i18n; export default i18n;

@ -154,7 +154,7 @@ li.sortable {
border-radius: 50%; border-radius: 50%;
} }
.checkround.checkround-gray{ .checkround.checkround-gray {
border-color: $gray-600; border-color: $gray-600;
} }
@ -319,22 +319,21 @@ li.sortable {
padding: 0.25em !important; padding: 0.25em !important;
} }
/** flag selector **/ /** flag selector **/
.flag-select > button { .flag-select > button {
height:35px; height: 35px;
} }
.flag-select__options{ .flag-select__options {
width:65px; width: 65px;
text-align:center; text-align: center;
background-color: $mv-light-color !important; background-color: $mv-light-color !important;
} }
.flag-select__options .flag-select__option{ .flag-select__options .flag-select__option {
padding:0; padding: 0;
margin:0; margin: 0;
} }
.flag-select__options .flag-select__option__icon{ .flag-select__options .flag-select__option__icon {
top:0; top: 0;
} }

Loading…
Cancel
Save