parent
56836e5ea1
commit
c8ae7147e6
@ -0,0 +1,30 @@
|
||||
import {UncontrolledAlert} from 'reactstrap';
|
||||
import {useTranslation} from "next-i18next";
|
||||
|
||||
const AlertDismissible = ({msg, color}) => {
|
||||
const {t} = useTranslation();
|
||||
|
||||
if (msg) {
|
||||
return (
|
||||
<UncontrolledAlert color={color}>
|
||||
<h4 className={`${color}-heading`}>{t(msg)}</h4>
|
||||
<p>
|
||||
<a
|
||||
href={`mailto:${CONTACT_MAIL}?subject=[HELP]`}
|
||||
className="btn btn-success m-auto"
|
||||
>
|
||||
{t("error.help")}
|
||||
</a>
|
||||
</p>
|
||||
</UncontrolledAlert >
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
AlertDismissible.defaultProps = {
|
||||
color: 'danger'
|
||||
};
|
||||
|
||||
export default AlertDismissible;
|
@ -1,24 +0,0 @@
|
||||
import { useState } from 'react'
|
||||
import { Alert, Button } from 'react-bootstrap';
|
||||
import { faTimes, faExclamationCircle } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
export default function AlertDismissibleExample() {
|
||||
const [show, setShow] = useState(true);
|
||||
|
||||
if (show) {
|
||||
return (
|
||||
<Alert className="preventWarning">
|
||||
<Alert.Heading>
|
||||
<div>
|
||||
<FontAwesomeIcon icon={faExclamationCircle} className="mr-2" />
|
||||
<span>2 candidats minimum</span>
|
||||
</div>
|
||||
<FontAwesomeIcon onClick={() => setShow(false)} icon={faTimes} className="mr-2" />
|
||||
</Alert.Heading>
|
||||
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -1,186 +1,170 @@
|
||||
import {useState, useEffect} from 'react'
|
||||
import ButtonWithConfirm from "./ButtonWithConfirm";
|
||||
import TrashButton from "./TrashButton";
|
||||
import {
|
||||
Row,
|
||||
Col,
|
||||
Label,
|
||||
Input,
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
Button, Modal, ModalHeader, ModalBody, Form
|
||||
} from "reactstrap";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {
|
||||
sortableHandle
|
||||
} from "react-sortable-hoc";
|
||||
import HelpButton from "@components/form/HelpButton";
|
||||
import AddPicture from "@components/form/AddPicture";
|
||||
import {
|
||||
faPlus, faCogs, faCheck, faTrash
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
const DragHandle = sortableHandle(({children}) => (
|
||||
<span className="input-group-text indexNumber">{children}</span>
|
||||
));
|
||||
|
||||
const CandidateField = ({avatar, label, description, candIndex, onDelete, onAdd, ...inputProps}) => {
|
||||
const {t} = useTranslation();
|
||||
const [visibled, setVisibility] = useState(false);
|
||||
const toggle = () => setVisibility(!visibled)
|
||||
|
||||
|
||||
|
||||
const [selected, setSelectedState] = useState(false);
|
||||
const [className, setClassName] = useState("none");
|
||||
const [trashIcon, setTrashIcon] = useState("none");
|
||||
const [plusIcon, setPlusIcon] = useState("none");
|
||||
|
||||
const addCandidate = () => {
|
||||
if (label != "") {
|
||||
toggle();
|
||||
onAdd();
|
||||
setSelectedState(!selected);
|
||||
}
|
||||
else {}
|
||||
}
|
||||
if (label != "") {
|
||||
const type = "button";
|
||||
}
|
||||
else {
|
||||
const type = "submit";
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setClassName("candidateButton " + (selected ? "candidateAdded" : ""))
|
||||
}, [selected]);
|
||||
useEffect(() => {
|
||||
setPlusIcon("mr-2 cursorPointer " + (selected ? "trashIcon" : ""))
|
||||
}, [selected]);
|
||||
useEffect(() => {
|
||||
setTrashIcon("trashIcon " + (selected ? "displayTrash" : ""))
|
||||
}, [selected]);
|
||||
|
||||
const addFunction = () => {
|
||||
addCandidate();
|
||||
setSelectedState(!selected);
|
||||
}
|
||||
const removeCandidate = () => {
|
||||
onDelete();
|
||||
toggle();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const [image, setImage] = useState(null);
|
||||
const [createObjectURL, setCreateObjectURL] = useState(null);
|
||||
|
||||
const uploadToClient = (event) => {
|
||||
if (event.target.files && event.target.files[0]) {
|
||||
const i = event.target.files[0];
|
||||
setImage(i);
|
||||
setCreateObjectURL(URL.createObjectURL(i));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Row className="rowNoMargin">
|
||||
<div className={className}>
|
||||
<div className="avatarThumb">
|
||||
<img src={createObjectURL} alt="" />
|
||||
<input placeholder="Ajouter un candidat" className="candidate-placeholder ml-2" value={label} />
|
||||
</div>
|
||||
|
||||
<FontAwesomeIcon onClick={toggle} icon={faPlus} className={plusIcon} />
|
||||
<div className={trashIcon}><TrashButton label={label} onDelete={onDelete} /></div>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
isOpen={visibled}
|
||||
toggle={toggle}
|
||||
className="modal-dialog-centered"
|
||||
>
|
||||
|
||||
<ModalHeader className='closeModalAddCandidate' toggle={toggle}>
|
||||
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
<Col className="addCandidateCard">
|
||||
<InputGroup className="addCandidateForm">
|
||||
<Form>
|
||||
<InputGroupAddon addonType="prepend" className="addCandidateHeader">
|
||||
<DragHandle>
|
||||
<h6>Ajouter un participant</h6>
|
||||
<p>Ajoutez une photo, le nom et une description au candidat.</p>
|
||||
<div className="ajout-avatar">
|
||||
<div>
|
||||
<div className="avatar-placeholer">
|
||||
<img src={createObjectURL} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="avatar-text">
|
||||
<h4>Photo <span> (facultatif)</span></h4>
|
||||
|
||||
<p>Importer une photo.<br />format : jpg, png, pdf</p>
|
||||
<div className="btn-ajout-avatar">
|
||||
<input type="file" name="myImage" id="myImage" value={avatar} onChange={uploadToClient} />
|
||||
<label className="inputfile" htmlFor="myImage">Importer une photo</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<img src="/avatar.svg" />
|
||||
</DragHandle>
|
||||
</InputGroupAddon>
|
||||
<Label className="addCandidateText">Nom et prenom</Label>
|
||||
<Input
|
||||
type="text"
|
||||
value={label}
|
||||
{...inputProps}
|
||||
placeholder={t("resource.candidatePlaceholder")}
|
||||
tabIndex={candIndex + 1}
|
||||
maxLength="250"
|
||||
autoFocus
|
||||
className="addCandidateText"
|
||||
required
|
||||
/>
|
||||
<Label>Description (Facultatif)</Label>
|
||||
<Input
|
||||
type="text"
|
||||
defaultValue={description}
|
||||
maxLength="250"
|
||||
/>
|
||||
<Row className="removeAddButtons">
|
||||
|
||||
<ButtonWithConfirm className="removeButton" label={label} onDelete={removeCandidate} />
|
||||
|
||||
<Button type={type} className="addButton" label={label} onClick={addCandidate}>
|
||||
<FontAwesomeIcon icon={faPlus} />
|
||||
<span>Ajouter</span>
|
||||
</Button>
|
||||
|
||||
</Row>
|
||||
</Form>
|
||||
</InputGroup>
|
||||
</Col>
|
||||
</ModalBody></Modal>
|
||||
{/* <Col xs="auto" className="align-self-center pl-0">
|
||||
<HelpButton>
|
||||
{t(
|
||||
"Enter the name of your candidate or proposal here (250 characters max.)"
|
||||
)}
|
||||
</HelpButton>
|
||||
</Col> */}
|
||||
</Row>
|
||||
);
|
||||
// import {useState, useEffect} from 'react'
|
||||
// import ButtonWithConfirm from "./ButtonWithConfirm";
|
||||
// import TrashButton from "./TrashButton";
|
||||
// import {
|
||||
// Row,
|
||||
// Col,
|
||||
// Label,
|
||||
// Input,
|
||||
// InputGroup,
|
||||
// InputGroupAddon,
|
||||
// Button, Modal, ModalHeader, ModalBody, Form
|
||||
// } from "reactstrap";
|
||||
// import {useTranslation} from "react-i18next";
|
||||
// import HelpButton from "@components/form/HelpButton";
|
||||
// import AddPicture from "@components/form/AddPicture";
|
||||
// import {
|
||||
// faPlus, faCogs, faCheck, faTrash
|
||||
// } from "@fortawesome/free-solid-svg-icons";
|
||||
// import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
// const DragHandle = sortableHandle(({children}) => (
|
||||
// <span className="input-group-text indexNumber">{children}</span>
|
||||
// ));
|
||||
|
||||
// const CandidateField = ({avatar, label, description, candIndex, onDelete, onAdd, ...inputProps}) => {
|
||||
const CandidateField = (props) => {
|
||||
// const {t} = useTranslation();
|
||||
// const [visibled, setVisibility] = useState(false);
|
||||
// const toggle = () => setVisibility(!visibled)
|
||||
|
||||
// const [selected, setSelectedState] = useState(false);
|
||||
// const [className, setClassName] = useState("none");
|
||||
// const [trashIcon, setTrashIcon] = useState("none");
|
||||
// const [plusIcon, setPlusIcon] = useState("none");
|
||||
|
||||
// const addCandidate = () => {
|
||||
// if (label != "") {
|
||||
// toggle();
|
||||
// onAdd();
|
||||
// setSelectedState(!selected);
|
||||
// }
|
||||
// else {}
|
||||
// }
|
||||
// const type = label != "" ? "button" : "submit";
|
||||
|
||||
// useEffect(() => {
|
||||
// setClassName("candidateButton " + (selected ? "candidateAdded" : ""))
|
||||
// }, [selected]);
|
||||
// useEffect(() => {
|
||||
// setPlusIcon("mr-2 cursorPointer " + (selected ? "trashIcon" : ""))
|
||||
// }, [selected]);
|
||||
// useEffect(() => {
|
||||
// setTrashIcon("trashIcon " + (selected ? "displayTrash" : ""))
|
||||
// }, [selected]);
|
||||
|
||||
// const addFunction = () => {
|
||||
// addCandidate();
|
||||
// setSelectedState(!selected);
|
||||
// }
|
||||
// const removeCandidate = () => {
|
||||
// onDelete();
|
||||
// toggle();
|
||||
|
||||
// }
|
||||
|
||||
//const [image, setImage] = useState(null);
|
||||
// const [createObjectURL, setCreateObjectURL] = useState(null);
|
||||
|
||||
// const uploadToClient = (event) => {
|
||||
// if (event.target.files && event.target.files[0]) {
|
||||
// const i = event.target.files[0];
|
||||
// setImage(i);
|
||||
// setCreateObjectURL(URL.createObjectURL(i));
|
||||
// }
|
||||
// };
|
||||
|
||||
return (<p>FOO</p>);
|
||||
// return (
|
||||
// <Row className="rowNoMargin">
|
||||
// <div className={className}>
|
||||
// <div className="avatarThumb">
|
||||
// <img src={createObjectURL} alt="" />
|
||||
// <input placeholder="Ajouter un candidat" className="candidate-placeholder ml-2" value={label} />
|
||||
// </div>
|
||||
//
|
||||
// <FontAwesomeIcon onClick={toggle} icon={faPlus} className={plusIcon} />
|
||||
// <div className={trashIcon}><TrashButton label={label} onDelete={onDelete} /></div>
|
||||
// </div>
|
||||
//
|
||||
// <Modal
|
||||
// isOpen={visibled}
|
||||
// toggle={toggle}
|
||||
// className="modal-dialog-centered"
|
||||
// >
|
||||
//
|
||||
// <ModalHeader className='closeModalAddCandidate' toggle={toggle}>
|
||||
//
|
||||
// </ModalHeader>
|
||||
// <ModalBody>
|
||||
// <Col className="addCandidateCard">
|
||||
// <InputGroup className="addCandidateForm">
|
||||
// <Form>
|
||||
// <InputGroupAddon addonType="prepend" className="addCandidateHeader">
|
||||
// { //<DragHandle>
|
||||
// }
|
||||
// <h6>Ajouter un participant</h6>
|
||||
// <p>Ajoutez une photo, le nom et une description au candidat.</p>
|
||||
// <div className="ajout-avatar">
|
||||
// <div>
|
||||
// <div className="avatar-placeholer">
|
||||
// <img src={createObjectURL} />
|
||||
// </div>
|
||||
// </div>
|
||||
// <div className="avatar-text">
|
||||
// <h4>Photo <span> (facultatif)</span></h4>
|
||||
//
|
||||
// <p>Importer une photo.<br />format : jpg, png, pdf</p>
|
||||
// <div className="btn-ajout-avatar">
|
||||
// <input type="file" name="myImage" id="myImage" value={avatar} onChange={uploadToClient} />
|
||||
// <label className="inputfile" htmlFor="myImage">Importer une photo</label>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// <img src="/avatar.svg" />
|
||||
// { //</InputGroupAddon></DragHandle>
|
||||
// }
|
||||
// </InputGroupAddon>
|
||||
// <Label className="addCandidateText">Nom et prenom</Label>
|
||||
// <Input
|
||||
// type="text"
|
||||
// value={label}
|
||||
// {...inputProps}
|
||||
// placeholder={t("resource.candidatePlaceholder")}
|
||||
// tabIndex={candIndex + 1}
|
||||
// maxLength="250"
|
||||
// autoFocus
|
||||
// className="addCandidateText"
|
||||
// required
|
||||
// />
|
||||
// <Label>Description (Facultatif)</Label>
|
||||
// <Input
|
||||
// type="text"
|
||||
// defaultValue={description}
|
||||
// maxLength="250"
|
||||
// />
|
||||
// <Row className="removeAddButtons">
|
||||
//
|
||||
// <ButtonWithConfirm className="removeButton" label={label} onDelete={removeCandidate} />
|
||||
//
|
||||
// <Button type={type} className="addButton" label={label} onClick={addCandidate}>
|
||||
// <FontAwesomeIcon icon={faPlus} />
|
||||
// <span>Ajouter</span>
|
||||
// </Button>
|
||||
//
|
||||
// </Row>
|
||||
// </Form>
|
||||
// </InputGroup>
|
||||
// </Col>
|
||||
// </ModalBody></Modal>
|
||||
// {/* <Col xs="auto" className="align-self-center pl-0">
|
||||
// <HelpButton>
|
||||
// {t(
|
||||
// "Enter the name of your candidate or proposal here (250 characters max.)"
|
||||
// )}
|
||||
// </HelpButton>
|
||||
// </Col> */}
|
||||
// </Row >
|
||||
// );
|
||||
}
|
||||
|
||||
export default CandidateField
|
||||
|
@ -1,10 +1,36 @@
|
||||
module.exports = {
|
||||
i18n: {
|
||||
defaultLocale: "fr",
|
||||
locales: ["en", "fr"],
|
||||
},
|
||||
react: {
|
||||
useSuspense: false,
|
||||
wait: true
|
||||
}
|
||||
};
|
||||
// https://www.i18next.com/overview/configuration-options#logging
|
||||
debug: process.env.NODE_ENV === 'development',
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'fr'],
|
||||
},
|
||||
ns: ["resource"],
|
||||
defaultNS: "resource",
|
||||
defaultValue: "__STRING_NOT_TRANSLATED__",
|
||||
/** To avoid issues when deploying to some paas (vercel...) */
|
||||
localePath: typeof window === 'undefined' ?
|
||||
require('path').resolve('./public/locales') : '/locales',
|
||||
|
||||
reloadOnPrerender: process.env.NODE_ENV === 'development',
|
||||
|
||||
/**
|
||||
* @link https://github.com/i18next/next-i18next#6-advanced-configuration
|
||||
*/
|
||||
// saveMissing: false,
|
||||
// strictMode: true,
|
||||
// serializeConfig: false,
|
||||
// react: { useSuspense: false }
|
||||
}
|
||||
// const path = require('path')
|
||||
// module.exports = {
|
||||
// i18n: {
|
||||
// defaultLocale: "fr",
|
||||
// locales: ["en", "fr"],
|
||||
// },
|
||||
// localePath: path.resolve('./public/locales'),
|
||||
// // react: {
|
||||
// // useSuspense: false,
|
||||
// // wait: true
|
||||
// // }
|
||||
// };
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
{}
|
@ -1,100 +0,0 @@
|
||||
{
|
||||
"title": "Plattform mit Mehrheitswahl",
|
||||
"Homepage": "Homepage",
|
||||
"Source code": "Quellcode",
|
||||
"Who are we?": "Wer wir sind?",
|
||||
"Privacy policy": "Datenschutzerklärung",
|
||||
"resource.legalNotices": "Rechtliche Hinweise",
|
||||
"FAQ": "FAQ",
|
||||
"resource.help": "Brauchen Sie Hilfe?",
|
||||
"BetterVote": " BetterVote",
|
||||
"Voting platform": "Wahlplattform",
|
||||
"Majority Judgment": " Mehrheitswahl ",
|
||||
"Start an election": "Eine Wahl beginnen",
|
||||
"resource.candidatePlaceholder": "Name des Kandidaten/Abstimmungsvorschlags",
|
||||
"Delete?": "Löschen?",
|
||||
"Are you sure to delete": "Sind Sie sich sicher, dass Sie dies löschen möchten?",
|
||||
"the row": "die Zeile",
|
||||
"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)",
|
||||
"Please add at least 2 candidates.": "Bitte geben Sie mindestens zwei Kandidaten vor. ",
|
||||
"Question of the election": "Zur Wahl stehende Frage",
|
||||
"Write here the question of your election": "Schreiben Sie hier die zur Wahl stehenden Frage",
|
||||
"For example:": "Zum Beispiel",
|
||||
"For the role of my representative, I judge this candidate...": "Meine Einschätzung des Kandidaten als meinen Repräsentanten ist …",
|
||||
"Candidates/Proposals": "Kandidaten/Abstimmungsvorschlag ",
|
||||
"Add a proposal": "Weiteren hinzufügen",
|
||||
"Advanced options": "Weitere Optionen",
|
||||
"Starting date": "Anfangsdatum",
|
||||
"Ending date": "Enddatum",
|
||||
"Defined period" : "Definierte Periode",
|
||||
"Unlimited" : "Unbegrenzt",
|
||||
"Voting time" : "Abstimmungszeit",
|
||||
"Grades": "Note",
|
||||
"You can select here the number of grades for your election": " Sie können hier die Anzahl der Noten für Ihre Wahl auswählen ",
|
||||
"5 = Excellent, Very good, Good, Fair, Passable": "5 = hervorragend, sehr gut, gut, befriedigend, ausreichend",
|
||||
"Participants": "Teilnehmer",
|
||||
"Add here participants' emails": "Fügen Sie hier die Email Adressen der Teilnehmer hinzu.",
|
||||
"List voters' emails in case the election is not opened": "Falls die Wahl noch nicht sofort geöffnet werden soll, fügen Sie die Email Adressen der Teilnehmer hier zu.",
|
||||
"Validate": "Ok",
|
||||
"Submit my vote": "Ok",
|
||||
"Confirm your vote": "Bestätigen Sie Ihre Wahl",
|
||||
"The form contains no address.": "Keine Email Adresse wurde hinzugefügt.",
|
||||
"The election will be opened to anyone with the link": "Die Wahl ist offen afür jeden, der diesen Link hat.",
|
||||
"Start the election": "Mit der Wahl beginnen.",
|
||||
"Cancel": "Abbrechen",
|
||||
"Confirm": "Ok",
|
||||
"Successful election creation!": "Die Wahl wurde erfolgreich erstellt!",
|
||||
"You can now share the election link to participants:": "Sie können nun den Teilnehmern den Link zukommen lassen.",
|
||||
"Copy": "Kopieren",
|
||||
"Here is the link for the results in real time:": " Hier ist der Link für die Ergebnisse in Echtzeit:",
|
||||
"Keep these links carefully": "Speichern Sie diesen Link an einem sicheren Ort.",
|
||||
"resource.participateBtn": "Machen Sie jetzt mit!",
|
||||
"t": "<0>Achtung</0> : Sie werden zu einem späteren Zeitpunkt keine Möglichkeit haben, diese Links abzurufen, auch wir haben keinen Zugriff darauf. Sie können aber beispielsweise diese Seite in Ihrem Browser als Lesezeichen speichern.",
|
||||
"Simple and free: organize an election with Majority Judgment.": "Einfach und kostenlos: Organisation von Mehrheitswahlen.",
|
||||
"Start": "Start",
|
||||
"No advertising or ad cookies": "Keine Werbung und auch keine Cookies zu Werbezwecken.",
|
||||
"Oops! This election does not exist or it is not available anymore.": "Ups! Diese Wahl existiert nicht oder ist nicht mehr verfügbar. ",
|
||||
"You can start another election.": "Sie können eine neue Umfrage starten.",
|
||||
"Go back to homepage": "Zurück zur Hompage",
|
||||
"You have to judge every candidate/proposal!": "Sie müssen jeden Kandidaten/Abstimmungsvorschlag bewerten!",
|
||||
"resource.voteSuccess": " Ihre Teilnahme wurde gespeichert!",
|
||||
"resource.thanks": " Vielen Dank für Ihre Teilnahme.",
|
||||
"Support us !": "Unterstützen Sie uns!",
|
||||
"PayPal - The safer, easier way to pay online!": "PayPal - Die sicherere und einfachere Art, online zu bezahlen!",
|
||||
"resource.numVotes": "Anzahl der Stimmen:",
|
||||
"Unknown error. Try again please.": "Unbekannter Fehler. Bitte versuchen Sie es erneut.",
|
||||
"Ending date:": "Enddatum:",
|
||||
"If you list voters' emails, only them will be able to access the election": "Wenn Sie die E-Mails der Wähler auflisten, haben nur diese Zugriff auf die Wahl",
|
||||
"Dates": "Datum",
|
||||
"The election will take place from": "Die Wahl findet von",
|
||||
"at": "um",
|
||||
"to": "bis",
|
||||
"Voters' list": "Wählerliste",
|
||||
"Voters received a link to vote by email. Each link can be used only once!": "Die Wähler erhielten per E-Mail einen Link zur Stimmabgabe. Jeder Link kann nur einmal verwendet werden!",
|
||||
"Results of the election:": "Ergebnisse der Wahl",
|
||||
"Graph": "Grafik",
|
||||
"Preference profile": "Präferenz-Profil",
|
||||
"Oops... The election is unknown.": "Hoppla... Die Wahl ist unbekannt.",
|
||||
"The election is still going on. You can't access now to the results.": "Die Wahl dauert noch an. Sie können jetzt nicht auf die Ergebnisse zugreifen.",
|
||||
"No votes have been recorded yet. Come back later.": "Es wurden noch keine Abstimmungen registriert. Kommen Sie später wieder.",
|
||||
"The election has not started yet.": "Die Wahlen haben noch nicht begonnen.",
|
||||
"The election is over. You can't vote anymore": "Die Wahl ist vorbei. Sie können nicht mehr wählen",
|
||||
"You need a token to vote in this election": "Sie brauchen eine Wertmarke, um an dieser Wahl teilzunehmen",
|
||||
"You seem to have already voted.": "Sie scheinen bereits abgestimmt zu haben.",
|
||||
"The parameters of the election are incorrect.": "Die Parameter der Wahl sind falsch.",
|
||||
"Access to results" : "Zugang zu den Ergebnissen",
|
||||
"Immediately": "Sofort",
|
||||
"At the end of the election": "Am Ende der Wahl",
|
||||
"Results available at the close of the vote": "Ergebnisse am Ende der Abstimmung verfügbar",
|
||||
"The results page will not be accessible until all participants have voted.":"Die Ergebnisseite wird nicht zugänglich sein, bis alle Teilnehmer abgestimmt haben.",
|
||||
"The results page will not be accessible until the end date is reached.": "Die Ergebnisseite wird nicht zugänglich sein, bis das Enddatum erreicht ist.",
|
||||
"No one will be able to see the result until the end date is reached or until all participants have voted.": "Niemand wird das Ergebnis sehen können, bis das Enddatum erreicht ist oder bis alle Teilnehmer abgestimmt haben.",
|
||||
"Send me this link" : "Senden Sie mir diesen Link",
|
||||
"Send me these links" : "Schicken Sie mir diesen Link",
|
||||
"Open" : "Öffnen Sie",
|
||||
"Voting address" : "Abstimmungs-URL",
|
||||
"Results address" : "Ergebnis-URL",
|
||||
"Share election on Facebook" : "Wahl auf Facebook teilen",
|
||||
"Share results on Facebook" : "Ergebnisse auf Facebook teilen"
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"common.vote": "Vote!",
|
||||
"common.mieuxvoter": "Better Vote",
|
||||
"common.helpus": "Do you want to help us?",
|
||||
"common.valueProp": "Simple and free: organise a vote with Majority Judgment.",
|
||||
"common.candidates": "Candidates/Proposals",
|
||||
"common.backHomepage": "Back to home page"
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"email.hello": "Hi, there! 🙂",
|
||||
"email.why": "This email was sent to you because your email was filled out to participate in the vote on the subject:",
|
||||
"email.linkVote": "The link for the vote is as follows:",
|
||||
"email.linkResult": "The link that will give you the results when they are available is as follows:",
|
||||
"email.happy": "We are happy to send you this email! You will be able to vote using majority judgment.",
|
||||
"email.copyLink": "If that doesn't work, copy and paste the following link into your browser:",
|
||||
"email.aboutjm": "If you require any further information, please visit our site.",
|
||||
"email.bye": "Good vote! 🤗"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"error.e1": "Oops... The election is unknown",
|
||||
"error.e2": "The election is still going on. You can't access now to the results.",
|
||||
"error.e3": "No votes have been recorded yet. Come back later.",
|
||||
"error.e4": "The election has not started yet.",
|
||||
"error.e5": "The election is over. You can't vote anymore",
|
||||
"error.e6": "You need a token to vote in this election",
|
||||
"error.e7": "You seem to have already voted.",
|
||||
"error.e8": "The parameters of the election are incorrect.",
|
||||
"error.catch22": "Unknown error"
|
||||
}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1,108 +0,0 @@
|
||||
{
|
||||
"title": "Plataforma de Juicio Mayoritario",
|
||||
"Homepage": "Página de inicio",
|
||||
"Source code": "Código fuente",
|
||||
"Who are we": "Quiénes somos",
|
||||
"Privacy policy": "Política de privacidad",
|
||||
"resource.legalNotices": "Avisos legales",
|
||||
"FAQ": "FAQ",
|
||||
"resource.help": "¿Necesitas ayuda?",
|
||||
"BetterVote": "VotarMejor",
|
||||
"Voting platform": "Plataforma de votación",
|
||||
"Majority Judgment": "Juicio Mayoritario",
|
||||
"Start an election": "Iniciar una elección",
|
||||
"resource.candidatePlaceholder": "Nombre del(la) candidato(a)/propuesta...",
|
||||
"Delete?": "Borrar?",
|
||||
"Are you sure to delete": "Estás seguro de querer borrar",
|
||||
"the row": "la fila",
|
||||
"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)",
|
||||
"Please add at least 2 candidates.": "Por favor, añada al menos dos canidatos(as).",
|
||||
"Question of the election": "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 the role of my representative, I judge this candidate...": "Para ser mi representante, yo elijo a este(a) candidato(a)....",
|
||||
"Candidates/Proposals": "Candidatos(as)/Propuestas",
|
||||
"Add a proposal": "Añadir una propuesta",
|
||||
"Advanced options": "Opciones avanzadas",
|
||||
"Starting date": "Fecha de inicio",
|
||||
"Ending date": "Fecha de finalización",
|
||||
"Defined period" : "Período definido",
|
||||
"Unlimited" : "Ilimitado",
|
||||
"Voting time" : "Hora de la votación",
|
||||
"Grades": "Escala",
|
||||
"You can select here the number of grades for your election": "Puede seleccionar aquí el número de niveles de la escala para su elección",
|
||||
"5 = Excellent, Very good, Good, Fair, Passable": "5 == Excelente, Muy bien, Bien, Regular, Pasable",
|
||||
"Participants:": "Participantes",
|
||||
"Add here participants' emails": "Añadir aquí los correos electrónicos de los(as) participantes",
|
||||
"List voters' emails in case the election is not opened": "Enumere los correos electrónicos de los(as) votantes en caso de que la elección no se abra",
|
||||
"Validate": "Validar",
|
||||
"Submit my vote": "Validar",
|
||||
"Confirm your vote": "Confirme su voto",
|
||||
"The form contains no address.": "El formulario no contiene ningún correo electrónico",
|
||||
"The election will be opened to anyone with the link": "La elección se abrirá a cualquiera que tenga el enlace",
|
||||
"Start the election": "Iniciar la elección",
|
||||
"Cancel": "Cancelar",
|
||||
"Confirm": "Confirmar",
|
||||
"Successful election creation!": "La elección ha sido creada con éxito!",
|
||||
"You can now share the election link to participants:": "Ahora puede compartir el enlace de la elección con los(as) participantes",
|
||||
"Copy": "Copiar",
|
||||
"Here is the link for the results in real time:": "En este enlace puedes revisar los resultados en tiempo real",
|
||||
"Keep these links carefully": "Guarda cuidadosamente estos enlaces",
|
||||
"resource.participateBtn": "¡Participa ahora!",
|
||||
"t": "<0>Advertencia</0>: No tendrás otras opciones para recuperar los enlaces, y no podremos compartirlos contigo. Por ejemplo, puedes agregarlos a favoritos de tu buscador.",
|
||||
"Simple and free: organize an election with Majority Judgment.": "Simple y gratuito: organiza una elección con Juicio Mayoritario",
|
||||
"Start": "Comenzar",
|
||||
"No advertising or ad cookies": "No contiene publicidad ni cookies publicitarias",
|
||||
"Oops! This election does not exist or it is not available anymore.": "¡Uy! Esta elección no existe o ya no está disponible",
|
||||
"You can start another election.": "Puedes empezar otra elección",
|
||||
"Go back to homepage": "Vuelve a la página de inicio",
|
||||
"You have to judge every candidate/proposal!": "¡Tienes que evaluar a todos(as) los(as) candidatos(as)/propuestas",
|
||||
"resource.voteSuccess": "¡Su participación fue registrada con éxito!",
|
||||
"resource.thanks": "Muchas gracias por participar",
|
||||
"Ending date:": "Fecha de finalización:",
|
||||
"Excellent": "Excelente",
|
||||
"Very good": "Muy bien",
|
||||
"Good": "Bien",
|
||||
"Fair": "Regular",
|
||||
"Passable": "Pasable",
|
||||
"Insufficient": "Insuficiente",
|
||||
"To reject": "Rechazar",
|
||||
"Dates": "Fechas",
|
||||
"The election will take place from": "La elección tendrá lugar desde",
|
||||
"at": "a las",
|
||||
"to": "hasta",
|
||||
"Voters' list": "Lista de votantes",
|
||||
"Graph": "Gráfico",
|
||||
"Preference profile": "Perfil de preferencia",
|
||||
"Results of the election:": "Resultados de la elección",
|
||||
"PayPal - The safer, easier way to pay online!": "PayPal la forma más segura y fácil de pagar en linea!",
|
||||
"Support us !": "¡apórtanos!",
|
||||
"Who are we?": "¿Quiénes somos?",
|
||||
"Unknown error. Try again please.": "Error desconocido. Inténtelo de nuevo, por favor.",
|
||||
"If you list voters' emails, only them will be able to access the election": "Si enumera los correos electrónicos de los votantes, sólo ellos podrán acceder a la elección",
|
||||
"Voters received a link to vote by email. Each link can be used only once!": "Los votantes recibieron un enlace para votar por correo electrónico. ¡Cada enlace puede ser usado sólo una vez!",
|
||||
"resource.numVotes": "Número de votos:",
|
||||
"Oops... The election is unknown.": "Oops... La elección es desconocida",
|
||||
"The election is still going on. You can't access now to the results.": "La elección sigue en marcha. No puedes acceder ahora a los resultados.",
|
||||
"No votes have been recorded yet. Come back later.": "Aún no se han registrado votos. Vuelva más tarde.",
|
||||
"The election has not started yet.": "Las elecciones aún no han comenzado.",
|
||||
"The election is over. You can't vote anymore": "La elección ha terminado. Ya no puedes votar.",
|
||||
"You need a token to vote in this election": "Necesitas una ficha para votar en esta elección",
|
||||
"You seem to have already voted.": "Parece que ya has votado.",
|
||||
"The parameters of the election are incorrect.": "Los parámetros de la elección son incorrectos.",
|
||||
"Access to results" : "Acceso a los resultados",
|
||||
"Immediately": "Inmediatamente",
|
||||
"At the end of the election": "Al final de la elección",
|
||||
"Results available at the close of the vote": "Resultados disponibles al cierre de la votación",
|
||||
"The results page will not be accessible until all participants have voted.":"La página de resultados no será accesible hasta que todos los participantes hayan votado.",
|
||||
"The results page will not be accessible until the end date is reached.": "No se podrá acceder a la página de resultados hasta que se alcance la fecha de finalización.",
|
||||
"No one will be able to see the result until the end date is reached or until all participants have voted.": "Nadie podrá ver el resultado hasta que se alcance la fecha final o hasta que todos los participantes hayan votado.",
|
||||
"Send me this link" : "Envíame este enlace",
|
||||
"Send me these links" : "Envíame estos enlaces",
|
||||
"Open" : "Abrir",
|
||||
"Voting address" : "URL de la votación",
|
||||
"Results address" : "URL de los resultados",
|
||||
"Share election on Facebook" : "Compartir la elección en Facebook",
|
||||
"Share results on Facebook" : "Comparte los resultados en Facebook"
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"common.vote": "Votez !",
|
||||
"common.mieuxvoter": "Mieux Voter",
|
||||
"common.helpus": "Vous souhaitez nous soutenir ?",
|
||||
"common.candidates": "Candidats/Propositions",
|
||||
"common.valueProp": "Simple et gratuit : organisez un vote avec le Jugement Majoritaire",
|
||||
"common.backHomepage": "Retour à la page d'accueil"
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"email.hello": "Bonjour ! 🙂",
|
||||
"email.why": "Vous avez été invité·e à participer à l'élection suivante : ",
|
||||
"email.linkVote": "Le lien pour voter est le suivant :",
|
||||
"email.linkResult": "A la fin de l'élection, vous pourrez accéder aux résultats en cliquant sur ce lien :",
|
||||
"email.happy": "Nous sommes très heureux de vous partager ce lien de vote ! Vous allez pouvoir voter avec le jugement majoritaire.",
|
||||
"email.copyLink": "Si le lien ne fonctionne pas, vous pouvez le copier et le coller dans la barre de navigation de votre navigateur.",
|
||||
"email.bye": "Bon vote ! 🤗",
|
||||
"email.aboutjm": "If you require any further information, please visit our site."
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"error.e1": "Impossible de retrouver le vote en question",
|
||||
"error.e2": "L'élection est encore en cours. Revenez plus tard.",
|
||||
"error.e3": "Aucun vote n'a encore été enregistré. Revenez plus tard.",
|
||||
"error.e4": "L'élection n'a pas encore démarrée.",
|
||||
"error.e5": "L'élection est terminée. Vous ne pouvez plus voter.",
|
||||
"error.e6": "Vous avez besoin d'un jeton pour participer à cette élection.",
|
||||
"error.e7": "Vous avez déjà voté pour cette élection.",
|
||||
"error.e8": "Les paramètres de l'élection sont inconnues.",
|
||||
"error.catch22": "Erreur inconnue."
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
{
|
||||
"Homepage": "Accueil",
|
||||
"Source code": "Code source",
|
||||
"Who are we": "Qui sommes-nous",
|
||||
"BetterVote": "MieuxVoter",
|
||||
"Voting platform": "Plateforme de vote",
|
||||
"Majority Judgment": "Jugement Majoritaire",
|
||||
"Start an election": "Lancer une élection",
|
||||
"resource.candidatePlaceholder": "Name du candidat/proposition",
|
||||
"Delete?": "Supprimer ?",
|
||||
"Are you sure to delete": "Êtes-vous sûr(e) de supprimer",
|
||||
"the row": "la ligne",
|
||||
"Write here your question or introduce simple your election (250 characters max.)": "Décrire ici votre question ou introduire simplement votre élection (250 caractères max.)",
|
||||
"Please add at least 2 candidates.": "Merci d'ajouter au moins 2 candidats.",
|
||||
"Question of the election": "Question de votre élection",
|
||||
"Write here the question of your election": "Ecrire ici la question de votre élection",
|
||||
"For example:": "Par exemple",
|
||||
"For the role of my representative, I judge this candidate...": "Pour être mon représentant, je juge ce candidat...",
|
||||
"Candidates/Proposals": "Candidats/Propositions",
|
||||
"Add a proposal": "Ajouter une proposition",
|
||||
"Advanced options": "Options avancées",
|
||||
"Starting date:": "Date de début :",
|
||||
"Ending date: ": "Date de fin : ",
|
||||
"Grades:": "Mentions",
|
||||
"You can select here the number of grades for your election": "You pouvez choisir ici le nombre de mentions de votre élection",
|
||||
"5 = Excellent, Very good, Good, Fair, Passable": "5 = Excellent, Très bien, Bien, Assez bien, Passable",
|
||||
"Participants:": "Participants :",
|
||||
"Add here participants' emails": "Ajouter ici les emails des participants",
|
||||
"List voters' emails in case the election is not opened": "Lister ici les emails des électeurs dans le cas où l'élection n'est pas ouverte.",
|
||||
"Validate": "Valider",
|
||||
"Confirm your vote": "Confirmer votre vote",
|
||||
"The form contains no address.": "Aucune adresse email n'a été ajoutée.",
|
||||
"The election will be opened to anyone with the link": "L'élection sera accessible à tous ceux qui disposent de ce lien",
|
||||
"Start the election": "Démarrer l'élection",
|
||||
"Cancel": "Annuler",
|
||||
"Confirm": "Valider",
|
||||
"Successful election creation!": "L'élection a été créée avec succès !",
|
||||
"You can now share the election link to participants:": "Vous pouvez maintenant partager ce lien à tous les participants",
|
||||
"Copy": "Copier",
|
||||
"Here is the link for the results in real time:": "Voici le lien pour afficher les résultats en temps réel :",
|
||||
"Keep these links carefully": "Gardez ces liens précieusement",
|
||||
"resource.participateBtn": "Participez maintenant !",
|
||||
"t": "<0>Attention</0> : vous n'aurez pas d'autres moyens pour récupérer ces liens par la suite, et nous ne serons pas capables de les partager avec vous. Vous pouvez, par exemple, ajouter ces liens à vos favoris dans votre navigateur.",
|
||||
"Simple and free: organize an election with Majority Judgment.": "Simple et grauit: organiser une élection avec le Jugement Majoritaire.",
|
||||
"Start": "Démarrer",
|
||||
"No advertising or ad cookies": "Pas de publictés, ni de cookies publicitaires",
|
||||
"Oops! This election does not exist or it is not available anymore.": "Oups ! L'élection n'existe pas ou n'est plus disponible.",
|
||||
"You can start another election.": "Vous pouvez démarrer une autre élection.",
|
||||
"Go back to homepage": "Revenir à la page d'accueil",
|
||||
"You have to judge every candidate/proposal!": "Vous devez évaluer tous les candidats/propositions !",
|
||||
"resource.voteSuccess": "Votre participation a été enregistrée avec succès !",
|
||||
"resource.thanks": "Merci de votre participation."
|
||||
}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This file provides useful constants for the project
|
||||
*/
|
||||
|
||||
const MAX_NUM_CANDIDATES = process.env.MAX_NUM_CANDIDATES || 1000;
|
||||
const CONTACT_MAIL = process.env.CONTACT_MAIL || "app@mieuxvoter.fr";
|
||||
const DEFAULT_GRADES = process.env.DEFAULT_GRADES || ['grades.very-good', 'grades.good', 'grades.passable', 'grades.inadequate', 'grades.mediocre'];
|
@ -0,0 +1,37 @@
|
||||
|
||||
const isValidDate = (date) => date instanceof Date && !isNaN(date);
|
||||
const getOnlyValidDate = (date) => (isValidDate(date) ? date : new Date());
|
||||
|
||||
// Convert a Date object into YYYY-MM-DD
|
||||
const dateToISO = (date) =>
|
||||
getOnlyValidDate(date).toISOString().substring(0, 10);
|
||||
|
||||
/**
|
||||
* Extract only the time from a date.
|
||||
* Date can be a string or a Date.
|
||||
* Return result in timestamp seconds.
|
||||
*/
|
||||
const extractTime = (date) => {
|
||||
if (typeof date === "string") {
|
||||
date = Date.parse(date);
|
||||
}
|
||||
if (!isValidDate) {
|
||||
throw Error("The date is not valid.")
|
||||
}
|
||||
return date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract only the day from a date.
|
||||
* Return result in timestamp seconds.
|
||||
*/
|
||||
const extractDay = (date) => {
|
||||
if (typeof date === "string") {
|
||||
date = Date.parse(date);
|
||||
}
|
||||
if (!isValidDate) {
|
||||
throw Error("The date is not valid.")
|
||||
}
|
||||
return date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds();
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* This file provides the paths to the pages
|
||||
*/
|
||||
|
||||
const CREATE_ELECTION = '/admin/new/';
|
@ -1,2 +1 @@
|
||||
@import "~bootstrap/scss/bootstrap.scss";
|
||||
// @import "~bootstrap/scss/_flex.scss";
|
||||
@import "../../node_modules/bootstrap/scss/bootstrap";
|
||||
|
Loading…
Reference in new issue