} />
diff --git a/src/components/CopyField.jsx b/src/components/CopyField.jsx
new file mode 100644
index 0000000..9eabab2
--- /dev/null
+++ b/src/components/CopyField.jsx
@@ -0,0 +1,45 @@
+import React, {Component} from 'react';
+import {Button} from 'reactstrap';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
+
+
+const CopyField = props => {
+ const ref = React.createRef();
+ const handleClickOnField = event => {
+ event.target.focus();
+ event.target.select();
+ };
+ const handleClickOnButton = event => {
+ const input = ref.current;
+ input.focus();
+ input.select();
+ document.execCommand('copy');
+ };
+
+ const {t, value, icon} = props;
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+export default CopyField;
diff --git a/src/components/views/CreateElection.jsx b/src/components/views/CreateElection.jsx
index b5047a8..7635a8d 100644
--- a/src/components/views/CreateElection.jsx
+++ b/src/components/views/CreateElection.jsx
@@ -267,7 +267,7 @@ class CreateElection extends Component {
},
body: JSON.stringify({
title: title,
- candidates: candidates.map(c => c.label),
+ candidates: candidates.map(c => c.label).filter( c => c !== ""),
on_invitation_only: electorEmails.length > 0,
num_grades: numGrades,
elector_emails: electorEmails,
@@ -279,13 +279,16 @@ class CreateElection extends Component {
.then(result => {
console.log(result);
if (result.id) {
+ const nextPage =
+ electorEmails && electorEmails.length
+ ? `/link/${result.id}`
+ : `/links/${result.id}`;
this.setState(state => ({
- redirectTo: '/create-success/' + result.id,
+ redirectTo: nextPage,
successCreate: true,
- waiting: false
- }))
- }
- else {
+ waiting: false,
+ }));
+ } else {
toast.error(t('Unknown error. Try again please.'), {
position: toast.POSITION.TOP_CENTER,
});
@@ -314,7 +317,7 @@ class CreateElection extends Component {
numGrades,
isAdvancedOptionsOpen,
numCandidatesWithLabel,
- electorEmails
+ electorEmails,
} = this.state;
const {t} = this.props;
diff --git a/src/components/views/CreateSuccess.jsx b/src/components/views/CreateSuccess.jsx
index d48d458..9163660 100644
--- a/src/components/views/CreateSuccess.jsx
+++ b/src/components/views/CreateSuccess.jsx
@@ -6,34 +6,25 @@ 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';
+import CopyField from '../CopyField';
+
+
+
class CreateSuccess extends Component {
static contextType = AppContext;
constructor(props) {
super(props);
+ console.log(props);
const electionSlug = this.props.match.params.slug;
this.state = {
- urlOfVote:
- 'https://' + window.location.hostname + '/vote/' + electionSlug,
- urlOfResult:
- 'https://' + window.location.hostname + '/result/' + electionSlug,
+ urlOfVote: `https://${window.location.hostname}/vote/${electionSlug}`,
+ urlOfResult: `https://${window.location.hostname}/result/${electionSlug}`,
};
this.urlVoteField = React.createRef();
this.urlResultField = React.createRef();
}
- handleClickOnField = event => {
- event.target.focus();
- event.target.select();
- };
-
- handleClickOnCopyVote = event => {
- const input = this.urlVoteField.current;
- input.focus();
- input.select();
- document.execCommand('copy');
- };
-
handleClickOnCopyResult = event => {
const input = this.urlResultField.current;
input.focus();
@@ -43,6 +34,26 @@ class CreateSuccess extends Component {
render() {
const {t} = this.props;
+ console.log(this.props)
+ const electionLink = this.props.invitationOnly ? (
+ <>
+
+ {t('Voters received a link to vote by email. Each link can be used only once!')}
+
+ >
+ ) : (
+ <>
+
+ {t('You can now share the election link to participants:')}
+
+
+ >
+ );
+
return (
@@ -53,54 +64,17 @@ class CreateSuccess extends Component {
{t('Successful election creation!')}
-
- {t('You can now share the election link to participants:')}
-
-
-
-
-
-
-
-
+ {electionLink}
{t('Here is the link for the results in real time:')}
-
-
-
-
-
-
-
+
@@ -126,7 +100,7 @@ class CreateSuccess extends Component {
to={'/vote/' + this.props.match.params.slug}
className="btn btn-success">
- {t("Participate now!")}
+ {t('Participate now!')}
diff --git a/src/components/views/Vote.jsx b/src/components/views/Vote.jsx
index a1c5d30..6ceca6a 100644
--- a/src/components/views/Vote.jsx
+++ b/src/components/views/Vote.jsx
@@ -1,19 +1,17 @@
-import React, { Component } from "react";
-import { Redirect } from "react-router-dom";
-import { withTranslation } from 'react-i18next';
-import { Button, Col, Container, Row } from "reactstrap";
-import { toast, ToastContainer } from "react-toastify";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { faCheck } from "@fortawesome/free-solid-svg-icons";
-import { resolve } from "url";
-import { i18nGrades } from "../../Util";
-import { AppContext } from "../../AppContext";
-import { errorMessage } from "../../Errors";
-
+import React, {Component} from 'react';
+import {Redirect} from 'react-router-dom';
+import {withTranslation} from 'react-i18next';
+import {Button, Col, Container, Row} from 'reactstrap';
+import {toast, ToastContainer} from 'react-toastify';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
+import {faCheck} from '@fortawesome/free-solid-svg-icons';
+import {resolve} from 'url';
+import {i18nGrades} from '../../Util';
+import {AppContext} from '../../AppContext';
+import {errorMessage} from '../../Errors';
const shuffle = array => array.sort(() => Math.random() - 0.5);
-
class Vote extends Component {
static contextType = AppContext;
constructor(props) {
@@ -30,7 +28,7 @@ class Vote extends Component {
colSizeGradeMd: 1,
colSizeGradeXs: 1,
redirectTo: null,
- electionGrades: i18nGrades()
+ electionGrades: i18nGrades(),
};
}
@@ -53,18 +51,18 @@ class Vote extends Component {
const numGrades = response.num_grades;
const candidates = response.candidates.map((c, i) => ({
id: i,
- label: c
+ label: c,
}));
shuffle(candidates);
const colSizeGradeLg = Math.floor(
- (12 - this.state.colSizeCandidateLg) / numGrades
+ (12 - this.state.colSizeCandidateLg) / numGrades,
);
const colSizeGradeMd = Math.floor(
- (12 - this.state.colSizeCandidateMd) / numGrades
+ (12 - this.state.colSizeCandidateMd) / numGrades,
);
const colSizeGradeXs = Math.floor(
- (12 - this.state.colSizeCandidateXs) / numGrades
+ (12 - this.state.colSizeCandidateXs) / numGrades,
);
this.setState(state => ({
@@ -86,7 +84,7 @@ class Vote extends Component {
12 - colSizeGradeXs * numGrades > 0
? 12 - colSizeGradeXs * numGrades
: 12,
- electionGrades: i18nGrades().slice(0, numGrades)
+ electionGrades: i18nGrades().slice(0, numGrades),
}));
return response;
};
@@ -97,9 +95,9 @@ class Vote extends Component {
const detailsEndpoint = resolve(
this.context.urlServer,
this.context.routesServer.getElection.replace(
- new RegExp(":slug", "g"),
- electionSlug
- )
+ new RegExp(':slug', 'g'),
+ electionSlug,
+ ),
);
fetch(detailsEndpoint)
.then(this.handleErrors)
@@ -110,33 +108,33 @@ class Vote extends Component {
handleGradeClick = event => {
let data = {
- id: parseInt(event.currentTarget.getAttribute("data-id")),
- value: parseInt(event.currentTarget.value)
+ id: parseInt(event.currentTarget.getAttribute('data-id')),
+ value: parseInt(event.currentTarget.value),
};
//remove candidate
let ratedCandidates = this.state.ratedCandidates.filter(
- ratedCandidate => ratedCandidate.id !== data.id
+ ratedCandidate => ratedCandidate.id !== data.id,
);
ratedCandidates.push(data);
- this.setState({ ratedCandidates: ratedCandidates });
+ this.setState({ratedCandidates});
};
handleSubmitWithoutAllRate = () => {
const {t} = this.props;
- toast.error(t("You have to judge every candidate/proposal!"), {
- position: toast.POSITION.TOP_CENTER
+ toast.error(t('You have to judge every candidate/proposal!'), {
+ position: toast.POSITION.TOP_CENTER,
});
};
handleSubmit = event => {
event.preventDefault();
- const { ratedCandidates } = this.state;
+ const {ratedCandidates} = this.state;
const electionSlug = this.props.match.params.slug;
const token = this.props.location.search.substr(7);
const endpoint = resolve(
this.context.urlServer,
- this.context.routesServer.voteElection
+ this.context.routesServer.voteElection,
);
const gradesById = {};
@@ -144,34 +142,33 @@ class Vote extends Component {
gradesById[c.id] = c.value;
});
const gradesByCandidate = [];
- Object.keys(gradesById)
- .forEach(id => {
- gradesByCandidate.push(gradesById[id]);
- });
+ Object.keys(gradesById).forEach(id => {
+ gradesByCandidate.push(gradesById[id]);
+ });
const payload = {
- election: electionSlug,
- grades_by_candidate: gradesByCandidate,
- }
- if (token !== ""){
- payload["token"] = token;
+ election: electionSlug,
+ grades_by_candidate: gradesByCandidate,
+ };
+ if (token !== '') {
+ payload['token'] = token;
}
fetch(endpoint, {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(payload)
+ method: 'POST',
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify(payload),
})
.then(this.handleErrors)
.then(result =>
- this.setState({ redirectTo: "/vote-success/" + electionSlug })
+ this.setState({redirectTo: '/vote-success/' + electionSlug}),
)
.catch(error => error);
};
render() {
const {t} = this.props;
- const { redirectTo, candidates, electionGrades } = this.state;
+ const {redirectTo, candidates, electionGrades} = this.state;
if (redirectTo) {
return ;
@@ -190,8 +187,7 @@ class Vote extends Component {
+ lg={this.state.colSizeCandidateLg}>
{electionGrades.map((grade, j) => {
@@ -202,12 +198,10 @@ class Vote extends Component {
lg={this.state.colSizeGradeLg}
key={j}
className="text-center p-0"
- style={{ lineHeight: 2 }}
- >
+ style={{lineHeight: 2}}>
+ style={{backgroundColor: grade.color, color: '#fff'}}>
{grade.label}
@@ -221,8 +215,7 @@ class Vote extends Component {
+ lg={this.state.colSizeCandidateLg}>
{candidate.label}
@@ -233,36 +226,33 @@ class Vote extends Component {
md={this.state.colSizeGradeMd}
lg={this.state.colSizeGradeLg}
key={j}
- className="text-lg-center"
- >
+ className="text-lg-center">