diff --git a/package.json b/package.json index 664a824..4ee7fe4 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "react-app-polyfill": "^1.0.1", "react-dev-utils": "^9.0.1", "react-dom": "^16.8.6", + "react-multi-email": "^0.5.3", "react-router-dom": "^5.0.0", "react-sortable-hoc": "^1.9.1", "react-toastify": "^5.2.1", diff --git a/src/components/views/CreateElection.jsx b/src/components/views/CreateElection.jsx index c5023e0..491e4db 100644 --- a/src/components/views/CreateElection.jsx +++ b/src/components/views/CreateElection.jsx @@ -23,6 +23,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import {faPlus, faTrashAlt, faCheck, faCogs } from '@fortawesome/free-solid-svg-icons'; import { grades } from '../../Util'; +import { ReactMultiEmail, isEmail } from 'react-multi-email'; +import 'react-multi-email/style.css'; const DragHandle = sortableHandle(({children}) => {children}); @@ -73,6 +75,12 @@ class CreateElection extends Component { constructor(props) { super(props); + //default value : start now + const startedAt = new Date(); + const startedHour= startedAt.getHours(); + //default value : finish in one week + const finishedAt = new Date(startedAt.getTime() + 7 * 24 * 60 * 60 * 1000); + this.state = { candidates:[{label:""},{label:""}], numCandidatesWithLabel:0, @@ -81,7 +89,12 @@ class CreateElection extends Component { numGrades:7, successCreate: false, redirectTo: null, - isAdvancedOptionsOpen:false + isAdvancedOptionsOpen:false, + startedDayAt:startedAt.toISOString().substring(0, 10), + finishedDayAt:finishedAt.toISOString().substring(0, 10), + startedTimeAt:(Math.floor(startedHour/2)*2)+":00:00", + finishedTimeAt:"23:59:59", + electorEmails:[] }; this.candidateInputs = []; this.focusInput= React.createRef(); @@ -183,9 +196,12 @@ class CreateElection extends Component { body: JSON.stringify({ title: title, candidates: candidates.map(c => c.label), - on_invitation_only: false, + on_invitation_only: (this.state.electorEmails.length>0), num_grades: numGrades, - elector_emails: [] + elector_emails: this.state.electorEmails, + started_at:this.state.startedDayAt+" "+this.state.startedTimeAt, + finished_at:this.state.finishedDayAt+" "+this.state.finishedTimeAt, + time_offset:new Date().getTimezoneOffset() }) }) .then(response => response.json()) @@ -202,10 +218,41 @@ class CreateElection extends Component { }); }; + formatDate = (dateIsoStr,timeIsoStr) => { + let date= new Date(dateIsoStr+"T"+timeIsoStr); + let day = date.getDate(); + let month = date.getMonth() + 1; //Months are zero based + let year = date.getFullYear(); + let hours = date.getHours(); + let minutes = date.getMinutes(); + + if(month<10){ + month="0"+month; + } + if(day<10){ + day="0"+day; + } + if(hours<10){ + hours="0"+hours; + } + if(minutes<10){ + minutes="0"+minutes; + } + let hoursString=hours+"h"+minutes; + if(hoursString==="23h59"){ + hoursString="minuit"; + } + + return day+"/"+month+"/"+year+" à "+hoursString; + }; + render(){ const { successCreate, redirectTo } = this.state; + const { electorEmails } = this.state; const params = new URLSearchParams(this.props.location.search); + + if (successCreate) return ; return( @@ -261,8 +308,27 @@ class CreateElection extends Component { - - + + this.setState({ startedDayAt: e.target.value })} /> + + +
@@ -270,8 +336,28 @@ class CreateElection extends Component { - - + + this.setState({ finishedDayAt: e.target.value })} /> + + +
@@ -305,7 +391,29 @@ class CreateElection extends Component { - + { + this.setState({ electorEmails: _emails }); + }} + validateEmail={email => { + return isEmail(email); // return boolean + }} + getLabel={( + email: string, + index: number, + removeEmail: (index: number) => void, + ) => { + return ( +
+ {email} + removeEmail(index)}>× +
+ ); + }} + /> +
Liste des e-mails à préciser si vous désirez réaliser un vote fermé.

@@ -319,9 +427,9 @@ class CreateElection extends Component {
Confirmez votre vote
-
Question du vote :
+
Question du vote
{this.state.title}
-
Candidats/Propositions :
+
Candidats/Propositions
    { this.state.candidates.map((candidate,i) => { @@ -334,11 +442,18 @@ class CreateElection extends Component { }) }
-
Mentions :
+
Dates
+

Le vote se déroulera du {this.formatDate(this.state.startedDayAt,this.state.startedTimeAt)} au {this.formatDate(this.state.finishedDayAt,this.state.finishedTimeAt)}

+
Mentions
{ grades.map((mention,i) => { return (i{mention.label}: }) }
+
Liste des électeurs
+
+ {(electorEmails.length>0)?electorEmails.join(', '):

Aucune adresse e-mail précisée.
Le vote sera ouvert à tous les utilisateurs ayant le lien du vote

} + +
Lancer le vote
diff --git a/src/scss/_app.scss b/src/scss/_app.scss index d7bb2b5..08211f5 100644 --- a/src/scss/_app.scss +++ b/src/scss/_app.scss @@ -311,3 +311,9 @@ li.sortable{ margin-left: 50%; margin-top: -15px; } + + +/** react multi email **/ +.react-multi-email > span[data-placeholder] { + padding: 0.25em !important; +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 4db8783..066bf30 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8698,6 +8698,11 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-multi-email@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/react-multi-email/-/react-multi-email-0.5.3.tgz#734a0d4d1af23feef5cb5e635bde23963b0a9e8b" + integrity sha512-1AneeJlAwjvzkPV740q2SXes/kW3HKOzR3gs+U7whrHN5nz+yH5Unosf/rvz8kRj/eFwBf6fTzMqlJiupu7S5Q== + react-popper@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.3.tgz#2c6cef7515a991256b4f0536cd4bdcb58a7b6af6"