Feature/fix limited result (#62)

* fix(restrict-results): fix typo in variables name

* fix(restrict-results): add error message if user try to create an election with restricted result but without voting time.
develop
Clément 4 years ago committed by GitHub
parent fb75f9a742
commit b2a7942db4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -17,6 +17,7 @@
"Write here your question or introduce simple your election (250 characters max.)": "Schreiben Sie hier Ihre Frage oder erklären Sie kurz ihre Wahl (bis 250 Zeichen)", "Write here your question or introduce simple your election (250 characters max.)": "Schreiben Sie hier Ihre Frage oder erklären Sie kurz ihre Wahl (bis 250 Zeichen)",
"Enter the name of your candidate or proposal here (250 characters max.)": "Geben Sie hier den Namen Ihres Kandidaten oder Antrags ein (max. 250 Zeichen)", "Enter the name of your candidate or proposal here (250 characters max.)": "Geben Sie hier den Namen Ihres Kandidaten oder Antrags ein (max. 250 Zeichen)",
"Please add at least 2 candidates.": "Bitte geben Sie mindestens zwei Kandidaten vor. ", "Please add at least 2 candidates.": "Bitte geben Sie mindestens zwei Kandidaten vor. ",
"You can't limit access results without specify a voting time.": "Sie können die Zugriffsergebnisse nicht einschränken, ohne eine Abstimmungszeit anzugeben.",
"Question of the election": "Zur Wahl stehende Frage", "Question of the election": "Zur Wahl stehende Frage",
"Write here the question of your election": "Schreiben Sie hier die zur Wahl stehenden Frage", "Write here the question of your election": "Schreiben Sie hier die zur Wahl stehenden Frage",
"For example:": "Zum Beispiel", "For example:": "Zum Beispiel",

@ -17,6 +17,7 @@
"Write here your question or introduce simple your election (250 characters max.)": "Write here your question or introduce simple your election (250 characters max.)", "Write here your question or introduce simple your election (250 characters max.)": "Write here your question or introduce simple your election (250 characters max.)",
"Enter the name of your candidate or proposal here (250 characters max.)":"Enter the name of your candidate or proposal here (250 characters max.)", "Enter the name of your candidate or proposal here (250 characters max.)":"Enter the name of your candidate or proposal here (250 characters max.)",
"Please add at least 2 candidates.": "Please add at least 2 candidates.", "Please add at least 2 candidates.": "Please add at least 2 candidates.",
"You can't limit access results without specify a voting time.": "You can't limit access results without specify a voting time.",
"Question of the election": "Question of the election", "Question of the election": "Question of the election",
"Write here the question of your election": "Write here the question of your election", "Write here the question of your election": "Write here the question of your election",
"For example:": "For example:", "For example:": "For example:",

@ -17,6 +17,7 @@
"Write here your question or introduce simple your election (250 characters max.)": "Escriba aquí su pregunta o introduzca simplemente su elección (250 caracteres máx.)", "Write here your question or introduce simple your election (250 characters max.)": "Escriba aquí su pregunta o introduzca simplemente su elección (250 caracteres máx.)",
"Enter the name of your candidate or proposal here (250 characters max.)": "Escriba aquí el nombre de su candidato o propuesta (250 caracteres como máximo)", "Enter the name of your candidate or proposal here (250 characters max.)": "Escriba aquí el nombre de su candidato o propuesta (250 caracteres como máximo)",
"Please add at least 2 candidates.": "Por favor, añada al menos dos canidatos(as).", "Please add at least 2 candidates.": "Por favor, añada al menos dos canidatos(as).",
"You can't limit access results without specify a voting time." : "No se puede limitar el acceso a los resultados sin especificar un tiempo de votación.",
"Question of the election": "Pregunta de su elección", "Question of the election": "Pregunta de su elección",
"Write here the question of your election": "Escriba aquí la pregunta de su elección", "Write here the question of your election": "Escriba aquí la pregunta de su elección",
"For example:": "Por ejemplo:", "For example:": "Por ejemplo:",

@ -17,6 +17,7 @@
"Write here your question or introduce simple your election (250 characters max.)": "Décrire ici votre question ou introduire simplement votre vote (250 caractères max.)", "Write here your question or introduce simple your election (250 characters max.)": "Décrire ici votre question ou introduire simplement votre vote (250 caractères max.)",
"Enter the name of your candidate or proposal here (250 characters max.)": "Saisissez ici le nom de votre candidat ou de votre proposition (250 caractères max.)", "Enter the name of your candidate or proposal here (250 characters max.)": "Saisissez ici le nom de votre candidat ou de votre proposition (250 caractères max.)",
"Please add at least 2 candidates.": "Merci d'ajouter au moins 2 candidats.", "Please add at least 2 candidates.": "Merci d'ajouter au moins 2 candidats.",
"You can't limit access results without specify a voting time." : "Vous ne pouvez pas limiter l'accès aux résultats sans spécifier une durée de vote.",
"Question of the election": "Question de votre vote", "Question of the election": "Question de votre vote",
"Write here the question of your election": "Ecrire ici la question de votre vote", "Write here the question of your election": "Ecrire ici la question de votre vote",
"For example:": "Par exemple", "For example:": "Par exemple",

@ -17,6 +17,7 @@
"Write here your question or introduce simple your election (250 characters max.)": "Напишите свой вопрос или опишите голосование (250 символов максимум.)", "Write here your question or introduce simple your election (250 characters max.)": "Напишите свой вопрос или опишите голосование (250 символов максимум.)",
"Enter the name of your candidate or proposal here (250 characters max.)": "Введите имя вашего кандидата или предложение здесь (не более 250 символов).", "Enter the name of your candidate or proposal here (250 characters max.)": "Введите имя вашего кандидата или предложение здесь (не более 250 символов).",
"Please add at least 2 candidates.": "Пожалуйста добавьте как минимум 2 кандидатов", "Please add at least 2 candidates.": "Пожалуйста добавьте как минимум 2 кандидатов",
"You can't limit access results without specify a voting time." : "Вы не можете ограничить результаты доступа без указания времени голосования.",
"Question of the election": "Суть голосования", "Question of the election": "Суть голосования",
"Write here the question of your election": "Напишите вопрос вашего голосования", "Write here the question of your election": "Напишите вопрос вашего голосования",
"For example:": "Например:", "For example:": "Например:",

@ -12,7 +12,7 @@ import {
InputGroupAddon, InputGroupAddon,
Button, Button,
Card, Card,
CardBody CardBody,
} from "reactstrap"; } from "reactstrap";
import { withTranslation } from "react-i18next"; import { withTranslation } from "react-i18next";
import { ReactMultiEmail, isEmail } from "react-multi-email"; import { ReactMultiEmail, isEmail } from "react-multi-email";
@ -25,7 +25,7 @@ import {
arrayMove, arrayMove,
sortableContainer, sortableContainer,
sortableElement, sortableElement,
sortableHandle sortableHandle,
} from "react-sortable-hoc"; } from "react-sortable-hoc";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { import {
@ -33,7 +33,7 @@ import {
faTrashAlt, faTrashAlt,
faCheck, faCheck,
faCogs, faCogs,
faExclamationTriangle faExclamationTriangle,
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import { i18nGrades } from "../../Util"; import { i18nGrades } from "../../Util";
import { AppContext } from "../../AppContext"; import { AppContext } from "../../AppContext";
@ -45,32 +45,32 @@ import i18n from "../../i18n";
// Error messages // Error messages
const AT_LEAST_2_CANDIDATES_ERROR = "Please add at least 2 candidates."; 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 RESTRICTED_RESULTS_NEED_LIMITED_TIME =
"You can't limit access results without specify a voting time.";
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 => const dateToISO = (date) =>
getOnlyValidDate(date) getOnlyValidDate(date).toISOString().substring(0, 10);
.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 => const time = (date) =>
hours(getOnlyValidDate(date)) + hours(getOnlyValidDate(date)) +
minutes(getOnlyValidDate(date)) + minutes(getOnlyValidDate(date)) +
seconds(getOnlyValidDate(date)) + seconds(getOnlyValidDate(date)) +
ms(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 => const dateMinusTime = (date) =>
new Date(getOnlyValidDate(date).getTime() - time(getOnlyValidDate(date))); new Date(getOnlyValidDate(date).getTime() - time(getOnlyValidDate(date)));
const DragHandle = sortableHandle(({ children }) => ( const DragHandle = sortableHandle(({ children }) => (
@ -100,13 +100,13 @@ const SortableCandidate = sortableElement(
<Input <Input
type="text" type="text"
value={candidate.label} value={candidate.label}
onChange={event => form.editCandidateLabel(event, sortIndex)} onChange={(event) => form.editCandidateLabel(event, sortIndex)}
onKeyPress={event => onKeyPress={(event) =>
form.handleKeypressOnCandidateLabel(event, sortIndex) form.handleKeypressOnCandidateLabel(event, sortIndex)
} }
placeholder={t("Candidate/proposal name...")} placeholder={t("Candidate/proposal name...")}
tabIndex={sortIndex + 1} tabIndex={sortIndex + 1}
innerRef={ref => (form.candidateInputs[sortIndex] = ref)} innerRef={(ref) => (form.candidateInputs[sortIndex] = ref)}
maxLength="250" maxLength="250"
/> />
<ButtonWithConfirm className="btn btn-primary input-group-append border-light"> <ButtonWithConfirm className="btn btn-primary input-group-append border-light">
@ -184,33 +184,35 @@ class CreateElection extends Component {
successCreate: false, successCreate: false,
redirectTo: null, redirectTo: null,
isAdvancedOptionsOpen: false, isAdvancedOptionsOpen: false,
restrictResult: false, restrictResults: false,
isTimeLimited: false, isTimeLimited: false,
start, start,
// by default, the election ends in a week // by default, the election ends in a week
finish: new Date(start.getTime() + 7 * 24 * 3600 * 1000), finish: new Date(start.getTime() + 7 * 24 * 3600 * 1000),
electorEmails: [] electorEmails: [],
}; };
this.candidateInputs = []; this.candidateInputs = [];
this.focusInput = React.createRef(); this.focusInput = React.createRef();
this.handleSubmit = this.handleSubmit.bind(this); this.handleSubmit = this.handleSubmit.bind(this);
this.handleRestrictResultCheck = this.handleRestrictResultCheck.bind(this); this.handleRestrictResultsCheck = this.handleRestrictResultsCheck.bind(
this
);
this.handleIsTimeLimited = this.handleIsTimeLimited.bind(this); this.handleIsTimeLimited = this.handleIsTimeLimited.bind(this);
} }
handleChangeTitle = event => { handleChangeTitle = (event) => {
this.setState({ title: event.target.value }); this.setState({ title: event.target.value });
}; };
handleIsTimeLimited = event => { handleIsTimeLimited = (event) => {
this.setState({ isTimeLimited: event.target.value === "1" }); this.setState({ isTimeLimited: event.target.value === "1" });
}; };
handleRestrictResultCheck = event => { handleRestrictResultsCheck = (event) => {
this.setState({ restrictResult: event.target.value === "1" }); this.setState({ restrictResults: event.target.value === "1" });
}; };
addCandidate = event => { addCandidate = (event) => {
let candidates = this.state.candidates; let candidates = this.state.candidates;
if (candidates.length < 100) { if (candidates.length < 100) {
candidates.push({ label: "" }); candidates.push({ label: "" });
@ -223,7 +225,7 @@ class CreateElection extends Component {
} }
}; };
removeCandidate = index => { removeCandidate = (index) => {
let candidates = this.state.candidates; let candidates = this.state.candidates;
candidates.splice(index, 1); candidates.splice(index, 1);
if (candidates.length === 0) { if (candidates.length === 0) {
@ -235,11 +237,11 @@ class CreateElection extends Component {
editCandidateLabel = (event, index) => { editCandidateLabel = (event, index) => {
let candidates = this.state.candidates; let candidates = this.state.candidates;
candidates[index].label = event.currentTarget.value; candidates[index].label = event.currentTarget.value;
candidates.map(candidate => { candidates.map((candidate) => {
return candidate.label; return candidate.label;
}); });
this.setState({ this.setState({
candidates: candidates candidates: candidates,
}); });
}; };
@ -260,7 +262,7 @@ class CreateElection extends Component {
this.setState({ candidates: candidates }); this.setState({ candidates: candidates });
}; };
handleChangeNumGrades = event => { handleChangeNumGrades = (event) => {
this.setState({ numGrades: event.target.value }); this.setState({ numGrades: event.target.value });
}; };
@ -269,13 +271,16 @@ class CreateElection extends Component {
}; };
checkFields() { checkFields() {
const { candidates, title } = this.state; const { candidates, title, restrictResults, isTimeLimited } = this.state;
if (!candidates) { if (!candidates) {
return { ok: false, msg: AT_LEAST_2_CANDIDATES_ERROR }; return { ok: false, msg: AT_LEAST_2_CANDIDATES_ERROR };
} }
if (restrictResults && !isTimeLimited) {
return { ok: false, msg: RESTRICTED_RESULTS_NEED_LIMITED_TIME };
}
let numCandidates = 0; let numCandidates = 0;
candidates.forEach(c => { candidates.forEach((c) => {
if (c.label !== "") numCandidates += 1; if (c.label !== "") numCandidates += 1;
}); });
if (numCandidates < 2) { if (numCandidates < 2) {
@ -290,29 +295,19 @@ class CreateElection extends Component {
} }
handleSubmit() { handleSubmit() {
const { const { candidates, title, numGrades, electorEmails } = this.state;
candidates,
title,
numGrades,
electorEmails
} = this.state;
let { let { start, finish } = this.state;
start,
finish,
} = this.state;
const endpoint = resolve( const endpoint = resolve(
this.context.urlServer, this.context.urlServer,
this.context.routesServer.setElection this.context.routesServer.setElection
); );
if(!this.state.isTimeLimited){ if (!this.state.isTimeLimited) {
let now = new Date(); let now = new Date();
start = new Date( start = new Date(now.getTime() - minutes(now) - seconds(now) - ms(now));
now.getTime() - minutes(now) - seconds(now) - ms(now) finish = new Date(start.getTime() + 10 * 365 * 24 * 3600 * 1000);
);
finish=new Date(start.getTime() + 10 * 365 * 24 * 3600 * 1000);
} }
const { t } = this.props; const { t } = this.props;
@ -322,7 +317,7 @@ class CreateElection extends Component {
const check = this.checkFields(); const check = this.checkFields();
if (!check.ok) { if (!check.ok) {
toast.error(t(check.msg), { toast.error(t(check.msg), {
position: toast.POSITION.TOP_CENTER position: toast.POSITION.TOP_CENTER,
}); });
return; return;
} }
@ -332,11 +327,11 @@ class CreateElection extends Component {
fetch(endpoint, { fetch(endpoint, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json" "Content-Type": "application/json",
}, },
body: JSON.stringify({ body: JSON.stringify({
title: title, title: title,
candidates: candidates.map(c => c.label).filter(c => c !== ""), candidates: candidates.map((c) => c.label).filter((c) => c !== ""),
on_invitation_only: electorEmails.length > 0, on_invitation_only: electorEmails.length > 0,
num_grades: numGrades, num_grades: numGrades,
elector_emails: electorEmails, elector_emails: electorEmails,
@ -344,11 +339,11 @@ class CreateElection extends Component {
finish_at: finish.getTime() / 1000, finish_at: finish.getTime() / 1000,
select_language: locale, select_language: locale,
front_url: window.location.origin, front_url: window.location.origin,
restrict_result: this.state.restrictResult restrict_results: this.state.restrictResults,
}) }),
}) })
.then(response => response.json()) .then((response) => response.json())
.then(result => { .then((result) => {
if (result.id) { if (result.id) {
const nextPage = const nextPage =
electorEmails && electorEmails.length electorEmails && electorEmails.length
@ -357,23 +352,26 @@ class CreateElection extends Component {
this.setState(() => ({ this.setState(() => ({
redirectTo: nextPage, redirectTo: nextPage,
successCreate: true, successCreate: true,
waiting: false waiting: false,
})); }));
} else { } else {
toast.error(t("Unknown error. Try again please."), { toast.error(t("Unknown error. Try again please."), {
position: toast.POSITION.TOP_CENTER position: toast.POSITION.TOP_CENTER,
}); });
this.setState({ waiting: false }); this.setState({ waiting: false });
} }
}) })
.catch(error => error); .catch((error) => error);
} }
handleSendNotReady = msg => { handleSendNotReady = () => {
const { t } = this.props; const { t } = this.props;
toast.error(t(msg), { const check = this.checkFields();
position: toast.POSITION.TOP_CENTER if (!check.ok) {
}); toast.error(t(check.msg), {
position: toast.POSITION.TOP_CENTER,
});
}
}; };
render() { render() {
@ -387,7 +385,7 @@ class CreateElection extends Component {
candidates, candidates,
numGrades, numGrades,
isAdvancedOptionsOpen, isAdvancedOptionsOpen,
electorEmails electorEmails,
} = this.state; } = this.state;
const { t } = this.props; const { t } = this.props;
@ -460,7 +458,7 @@ class CreateElection extends Component {
className="btn-block mt-2" className="btn-block mt-2"
tabIndex={candidates.length + 2} tabIndex={candidates.length + 2}
type="button" type="button"
onClick={event => this.addCandidate(event)} onClick={(event) => this.addCandidate(event)}
> >
<FontAwesomeIcon icon={faPlus} className="mr-2" /> <FontAwesomeIcon icon={faPlus} className="mr-2" />
{t("Add a proposal")} {t("Add a proposal")}
@ -490,24 +488,24 @@ class CreateElection extends Component {
<Label for="title">{t("Access to results")}</Label> <Label for="title">{t("Access to results")}</Label>
</Col> </Col>
<Col xs="12" md="4" lg="3"> <Col xs="12" md="4" lg="3">
<Label className="radio " htmlFor="restrict_result_false"> <Label className="radio " htmlFor="restrict_results_false">
<span className="small text-dark"> <span className="small text-dark">
{t("Immediately")} {t("Immediately")}
</span> </span>
<input <input
className="radio" className="radio"
type="radio" type="radio"
name="restrict_result" name="restrict_results"
id="restrict_result_false" id="restrict_results_false"
onClick={this.handleRestrictResultCheck} onClick={this.handleRestrictResultsCheck}
defaultChecked={!this.state.restrictResult} defaultChecked={!this.state.restrictResults}
value="0" value="0"
/> />
<span className="checkround checkround-gray" /> <span className="checkround checkround-gray" />
</Label> </Label>
</Col> </Col>
<Col xs="12" md="4" lg="3"> <Col xs="12" md="4" lg="3">
<Label className="radio" htmlFor="restrict_result_true"> <Label className="radio" htmlFor="restrict_results_true">
<span className="small"> <span className="small">
<span className="text-dark"> <span className="text-dark">
{t("At the end of the election")} {t("At the end of the election")}
@ -521,10 +519,10 @@ class CreateElection extends Component {
<input <input
className="radio" className="radio"
type="radio" type="radio"
name="restrict_result" name="restrict_results"
id="restrict_result_true" id="restrict_results_true"
onClick={this.handleRestrictResultCheck} onClick={this.handleRestrictResultsCheck}
defaultChecked={this.state.restrictResult} defaultChecked={this.state.restrictResults}
value="1" value="1"
/> />
<span className="checkround checkround-gray" /> <span className="checkround checkround-gray" />
@ -554,9 +552,7 @@ class CreateElection extends Component {
<Col xs="12" md="4" lg="3"> <Col xs="12" md="4" lg="3">
<Label className="radio" htmlFor="is_time_limited_true"> <Label className="radio" htmlFor="is_time_limited_true">
<span className="small"> <span className="small">
<span className="text-dark"> <span className="text-dark">{t("Defined period")}</span>
{t("Defined period")}
</span>
</span> </span>
<input <input
className="radio" className="radio"
@ -572,9 +568,12 @@ class CreateElection extends Component {
</Col> </Col>
</Row> </Row>
<div <div
className={(this.state.isTimeLimited ? "d-block " : "d-none")+" bg-light p-3"} className={
(this.state.isTimeLimited ? "d-block " : "d-none") +
" bg-light p-3"
}
> >
<Row > <Row>
<Col xs="12" md="3" lg="3"> <Col xs="12" md="3" lg="3">
<span className="label">- {t("Starting date")}</span> <span className="label">- {t("Starting date")}</span>
</Col> </Col>
@ -583,12 +582,12 @@ class CreateElection extends Component {
className="form-control" className="form-control"
type="date" type="date"
value={dateToISO(start)} value={dateToISO(start)}
onChange={e => { onChange={(e) => {
this.setState({ this.setState({
start: new Date( start: new Date(
timeMinusDate(start) + timeMinusDate(start) +
new Date(e.target.valueAsNumber).getTime() new Date(e.target.valueAsNumber).getTime()
) ),
}); });
}} }}
/> />
@ -597,12 +596,12 @@ class CreateElection extends Component {
<select <select
className="form-control" className="form-control"
value={getOnlyValidDate(start).getHours()} value={getOnlyValidDate(start).getHours()}
onChange={e => onChange={(e) =>
this.setState({ this.setState({
start: new Date( start: new Date(
dateMinusTime(start).getTime() + dateMinusTime(start).getTime() +
e.target.value * 3600000 e.target.value * 3600000
) ),
}) })
} }
> >
@ -621,12 +620,12 @@ class CreateElection extends Component {
type="date" type="date"
value={dateToISO(finish)} value={dateToISO(finish)}
min={dateToISO(start)} min={dateToISO(start)}
onChange={e => { onChange={(e) => {
this.setState({ this.setState({
finish: new Date( finish: new Date(
timeMinusDate(finish) + timeMinusDate(finish) +
new Date(e.target.valueAsNumber).getTime() new Date(e.target.valueAsNumber).getTime()
) ),
}); });
}} }}
/> />
@ -635,12 +634,12 @@ class CreateElection extends Component {
<select <select
className="form-control" className="form-control"
value={getOnlyValidDate(finish).getHours()} value={getOnlyValidDate(finish).getHours()}
onChange={e => onChange={(e) =>
this.setState({ this.setState({
finish: new Date( finish: new Date(
dateMinusTime(finish).getTime() + dateMinusTime(finish).getTime() +
e.target.value * 3600000 e.target.value * 3600000
) ),
}) })
} }
> >
@ -693,7 +692,7 @@ class CreateElection extends Component {
style={{ style={{
backgroundColor: mention.color, backgroundColor: mention.color,
color: "#fff", color: "#fff",
opacity: i < numGrades ? 1 : 0.3 opacity: i < numGrades ? 1 : 0.3,
}} }}
> >
{mention.label} {mention.label}
@ -711,10 +710,10 @@ class CreateElection extends Component {
<ReactMultiEmail <ReactMultiEmail
placeholder={t("Add here participants' emails")} placeholder={t("Add here participants' emails")}
emails={electorEmails} emails={electorEmails}
onChange={_emails => { onChange={(_emails) => {
this.setState({ electorEmails: _emails }); this.setState({ electorEmails: _emails });
}} }}
validateEmail={email => { validateEmail={(email) => {
return isEmail(email); // return boolean return isEmail(email); // return boolean
}} }}
getLabel={(email, index, removeEmail) => { getLabel={(email, index, removeEmail) => {
@ -782,22 +781,26 @@ class CreateElection extends Component {
})} })}
</ul> </ul>
</div> </div>
<div className={(this.state.isTimeLimited ? "d-block " : "d-none")} > <div
<div className="text-white bg-primary p-2 pl-3 pr-3 rounded"> className={
{t("Dates")} this.state.isTimeLimited ? "d-block " : "d-none"
</div> }
<div className="p-2 pl-3 pr-3 bg-light mb-3"> >
{t("The election will take place from")}{" "} <div className="text-white bg-primary p-2 pl-3 pr-3 rounded">
<b> {t("Dates")}
{start.toLocaleDateString()}, {t("at")}{" "} </div>
{start.toLocaleTimeString()} <div className="p-2 pl-3 pr-3 bg-light mb-3">
</b>{" "} {t("The election will take place from")}{" "}
{t("to")}{" "} <b>
<b> {start.toLocaleDateString()}, {t("at")}{" "}
{finish.toLocaleDateString()}, {t("at")}{" "} {start.toLocaleTimeString()}
{finish.toLocaleTimeString()} </b>{" "}
</b> {t("to")}{" "}
</div> <b>
{finish.toLocaleDateString()}, {t("at")}{" "}
{finish.toLocaleTimeString()}
</b>
</div>
</div> </div>
<div className="text-white bg-primary p-2 pl-3 pr-3 rounded"> <div className="text-white bg-primary p-2 pl-3 pr-3 rounded">
{t("Grades")} {t("Grades")}
@ -810,7 +813,7 @@ class CreateElection extends Component {
className="badge badge-light mr-2 mt-2" className="badge badge-light mr-2 mt-2"
style={{ style={{
backgroundColor: mention.color, backgroundColor: mention.color,
color: "#fff" color: "#fff",
}} }}
> >
{mention.label} {mention.label}
@ -838,7 +841,7 @@ class CreateElection extends Component {
</p> </p>
)} )}
</div> </div>
{this.state.restrictResult ? ( {this.state.restrictResults ? (
<div> <div>
<div className="small bg-primary text-white p-3 mt-2 rounded"> <div className="small bg-primary text-white p-3 mt-2 rounded">
<h6 className="m-0 p-0"> <h6 className="m-0 p-0">
@ -846,7 +849,11 @@ class CreateElection extends Component {
icon={faExclamationTriangle} icon={faExclamationTriangle}
className="mr-2" className="mr-2"
/> />
<u>{t("Results available at the close of the vote")}</u> <u>
{t(
"Results available at the close of the vote"
)}
</u>
</h6> </h6>
<p className="m-2 p-0"> <p className="m-2 p-0">
{electorEmails.length > 0 ? ( {electorEmails.length > 0 ? (
@ -861,7 +868,7 @@ class CreateElection extends Component {
"The results page will not be accessible until the end date is reached." "The results page will not be accessible until the end date is reached."
)}{" "} )}{" "}
({finish.toLocaleDateString()} {t("at")}{" "} ({finish.toLocaleDateString()} {t("at")}{" "}
{finish.toLocaleTimeString()}) {finish.toLocaleTimeString()})
</span> </span>
)} )}
</p> </p>
@ -879,7 +886,7 @@ class CreateElection extends Component {
<Button <Button
type="button" type="button"
className="btn btn-dark float-right btn-block" className="btn btn-dark float-right btn-block"
onClick={this.handleSendWithoutCandidate} onClick={this.handleSendNotReady}
> >
<FontAwesomeIcon icon={faCheck} className="mr-2" /> <FontAwesomeIcon icon={faCheck} className="mr-2" />
{t("Confirm")} {t("Confirm")}
@ -893,4 +900,4 @@ class CreateElection extends Component {
} }
} }
export default withTranslation()(withRouter(CreateElection)); export default withTranslation()(withRouter(CreateElection));

Loading…
Cancel
Save