copy-past code of election_form from moje_react project (need to be cleaned)

pull/4/head
Clement G 5 years ago committed by guhur
parent 0aaec02b84
commit 03d28c2007

@ -16,6 +16,8 @@
"react-dom": "^16.8.6",
"react-router-dom": "^5.0.0",
"react-scripts": "3.0.1",
"react-sortable-hoc": "^1.9.1",
"react-toastify": "^5.2.1",
"reactstrap": "^8.0.0"
},
"scripts": {

@ -0,0 +1,53 @@
import React, {Component} from "react";
import ModalConfirm from "./ModalConfirm";
class ButtonWithConfirm extends Component {
constructor(props) {
super(props);
this._modalConfirm=React.createRef();
this.state={
focused:false
}
}
getComponent= (key) => {
return this.props.children.filter( (comp) => {
return comp.key === key;
});
};
render() {
const classNames=this.props.className.split(" ");
let classNameForDiv="";
let classNameForButton="";
classNames.forEach(function(className){
if(className==="input-group-prepend" || className==="input-group-append" ){
classNameForDiv+=" "+className;
}else{
classNameForButton+=" "+className;
}
});
return (
<div className={classNameForDiv}>
<button
className={classNameForButton}
onClick={() => { this._modalConfirm.current.toggle() }}
>{this.getComponent("button")}
</button>
<ModalConfirm className={this.props.modalClassName} ref={this._modalConfirm}>
<div key="title">{this.getComponent("modal-title")}</div>
<div key="body">{this.getComponent("modal-body")}</div>
<div key="confirm">{this.getComponent("modal-confirm")}</div>
<div key="cancel">{this.getComponent("modal-cancel")}</div>
</ModalConfirm>
</div>
);
}
}
export default ButtonWithConfirm;

@ -0,0 +1,40 @@
import React, {Component} from "react";
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
class ModalConfirm extends Component {
constructor(props) {
super(props);
this.state = {
modal: false
};
}
toggle = () => {
this.setState({
modal: !this.state.modal
});
};
getComponent= (key) => {
return this.props.children.filter( (comp) => {
return comp.key === key;
});
};
render() {
return (
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className+" modal-dialog-centered"} >
<ModalHeader toggle={this.toggle}>{this.getComponent("title")}</ModalHeader>
<ModalBody>
{this.getComponent("body")}
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>{this.getComponent("confirm")}</Button>{' '}
<Button color="secondary" onClick={this.toggle}>{this.getComponent("cancel")}</Button>
</ModalFooter>
</Modal>
);
}
}
export default ModalConfirm;

@ -1,24 +1,108 @@
import React, {Component} from "react";
import { Container, Row, Col, Input, Label } from 'reactstrap';
import { Container, Row, Col, Input, Label, Card, CardHeader, CardBody, Collapse } from 'reactstrap';
import {toast, ToastContainer} from 'react-toastify';
import HelpButton from "../form/HelpButton";
import {arrayMove, sortableContainer, sortableElement, sortableHandle} from 'react-sortable-hoc';
import ButtonWithConfirm from "../form/ButtonWithConfirm";
const DragHandle = sortableHandle(({children}) => <span className="input-group-text indexNumber">{children}</span>);
const SortableCandidate = sortableElement(({candidate, sortIndex, form}) => <li className="sortable">
<div key={"rowCandidate" + sortIndex}>
<div className="row">
<div className="col-12">
<div className="input-group ">
<div className="input-group-prepend">
<DragHandle>
<span>{sortIndex + 1}</span>
</DragHandle>
</div>
<input type="text" className="form-control" value={candidate.label}
onChange={(event) => form.editCandidateLabel(event, sortIndex)}
maxLength="250"/>
<ButtonWithConfirm className="btn btn-outline-danger input-group-append">
<div key="button"><i className="fas fa-trash-alt"/></div>
<div key="modal-title">Suppression ?</div>
<div key="modal-body">Êtes-vous sûr de vouloir supprimer la
proposition <b>"{candidate.label}"</b> ?
</div>
<div key="modal-confirm" onClick={() => form.removeCandidate(sortIndex)}>Oui</div>
<div key="modal-cancel">Non</div>
</ButtonWithConfirm>
</div>
</div>
</div>
</div>
</li>);
const SortableCandidatesContainer = sortableContainer(({items, form}) => {
return <ul className="sortable">{items.map((candidate, index) => (
<SortableCandidate key={`item-${index}`} index={index} sortIndex={index} candidate={candidate} form={form}/>
))}</ul>;
});
class CreateBallot extends Component {
constructor(props) {
super(props);
this.state = {
}
candidates:[]
};
this._candidateLabelInput = React.createRef();
this._addCandidateButton = React.createRef();
this.focusInput= React.createRef();
}
addCandidate = (evt) => {
if (evt.type === "click" || (evt.type === "keydown" && evt.keyCode === 13)) {
const candidateFieldLabel = this._candidateLabelInput.current.value;
let candidates = this.state.candidates;
if (candidates.length < 100) {
candidates.push({label: candidateFieldLabel});
this._candidateLabelInput.current.value = '';
this.setState({isAddCandidateOpen: false, candidates: candidates});
}
}
};
removeCandidate = (index) => {
let candidates = this.state.candidates;
candidates.splice(index, 1);
this.setState({candidates: candidates});
};
editCandidateLabel = (event, index) => {
let candidates = this.state.candidates;
candidates[index].label = event.currentTarget.value;
this.setState({candidates: candidates});
};
toggleAddCandidate = () => {
if (this.state.candidates.length >= 100) {
toast.error("Vous ne pouvez plus ajouter de proposition ! (100 max.)", {
position: toast.POSITION.TOP_CENTER
});
} else {
this._candidateLabelInput.current.value = "";
this.setState({
isAddCandidateOpen: !this.state.isAddCandidateOpen
});
}
};
render(){
const params = new URLSearchParams(this.props.location.search);
return(
<Container>
<ToastContainer/>
<form onSubmit={this.handleSubmit} autoComplete="off">
<Row>
<Col ><h3>Démarrer un vote</h3></Col>
@ -26,20 +110,107 @@ class CreateBallot extends Component {
<Row>
<hr />
</Row>
<Row className="mt-2">
<Row className="mt-4">
<Col xs="12" >
<Label for="title">Question du vote :</Label>
</Col>
<Col >
<Col>
<Input placeholder="Saisissez ici la question de votre vote" name="title" id="title" innerRef={this.focusInput} autoFocus defaultValue={params.get("title")?params.get("title"):""} maxlength="250" />
</Col>
<Col xs="auto" className="align-self-center pl-0">
<HelpButton id="helpTitle">
Posez ici votre question ou introduisez simplement votre vote.
Posez ici votre question ou introduisez simplement votre vote (250 caractères max.)
<br /><u>Par exemple :</u> <em>Pour être mon représentant, je juge ce candidat ...</em>
</HelpButton>
</Col>
</Row>
<div className="row mt-5">
<div className="col-12">
<b>{this.state.candidates.length}
{(this.state.candidates.length < 2) ? <span> Proposition soumise </span> :
<span> Propositions soumises </span>}
au vote</b>
</div>
</div>
<div className="row mt-2">
<div className="col-12">
<SortableCandidatesContainer items={this.state.candidates} onSortEnd={this.onCandidatesSortEnd}
form={this} useDragHandle/>
</div>
</div>
{(this.state.candidates.length > 2 && this.state.isVisibleTipsDragndropCandidate === true) ?
<div className="row alert alert-info">
<div className="col pl-0 ">
<i className="fas fa-lightbulb mr-2"/><b>Astuce :</b> Vous pouvez changer l'ordre des
propositions par glisser-déposer du numéro !
</div>
<div className="col-auto">
<a className="text-info pointer" onClick={this.hideTipsDragndropCandidate}><i
className="fas fa-window-close"/></a>
</div>
</div> : <div/>}
<div className="row mt-2">
<div className="col-12">
<Collapse isOpen={this.state.isAddCandidateOpen}
onEntered={() => {
this._candidateLabelInput.current.focus()
}}
onExited={() => {
this._addCandidateButton.current.focus()
}}>
<Card>
<CardHeader>Ajout d'une proposition
(100 max.) </CardHeader>
<CardBody>
<div className="row">
<div className="col-12">
<label htmlFor="candidate_label"><b>Libellé</b> <span
className="text-muted">(obligatoire)</span></label>
<input type="text" className="form-control" name="candidate_label"
id="candidate_label" onKeyDown={evt => this.addCandidate(evt)}
ref={this._candidateLabelInput}
placeholder="Nom de la proposition, nom du candidat, etc..."
maxLength="250"/>
</div>
</div>
<div className="row mt-4">
<div className="col-md-12 text-right">
<button type="button" className="btn btn-secondary mr-2"
onClick={this.toggleAddCandidate}>
<i className="fas fa-times mr-2"/>Annuler
</button>
<button type="button" className="btn btn-success "
onClick={evt => this.addCandidate(evt)}>
<i className="fas fa-plus mr-2"/>Ajouter
</button>
</div>
</div>
</CardBody>
</Card>
</Collapse>
</div>
<div className="col-12">
{this.state.isAddCandidateOpen ? null :
<button className="btn btn-secondary" tabIndex="3" ref={this._addCandidateButton}
name="collapseAddCandidate"
id="collapseAddCandidate" onClick={this.toggleAddCandidate}>
<i className="fas fa-plus-square mr-2"/>Ajouter une proposition</button>}
</div>
</div>
</form>
</Container>
)

@ -2556,7 +2556,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
classnames@^2.2.3:
classnames@^2.2.3, classnames@^2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
@ -8443,7 +8443,7 @@ prop-types-exact@^1.2.0:
object.assign "^4.1.0"
reflect.ownkeys "^0.2.0"
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@ -8788,6 +8788,15 @@ react-scripts@3.0.1:
optionalDependencies:
fsevents "2.0.6"
react-sortable-hoc@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/react-sortable-hoc/-/react-sortable-hoc-1.9.1.tgz#ae3d28c3cff87fb862be3ddcde9c76b5b5bd2152"
integrity sha512-2VeofjRav8+eZeE5Nm/+b8mrA94rQ+gBsqhXi8pRBSjOWNqslU3ZEm+0XhSlfoXJY2lkgHipfYAUuJbDtCixRg==
dependencies:
"@babel/runtime" "^7.2.0"
invariant "^2.2.4"
prop-types "^15.5.7"
react-test-renderer@^16.0.0-0:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.6.tgz#188d8029b8c39c786f998aa3efd3ffe7642d5ba1"
@ -8798,7 +8807,17 @@ react-test-renderer@^16.0.0-0:
react-is "^16.8.6"
scheduler "^0.13.6"
react-transition-group@^2.3.1:
react-toastify@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-5.2.1.tgz#faa05bc4cd5066ee50bf56c7f8b8fd1492e71aca"
integrity sha512-OEZQld/jvjFCQnmXShb73dxVgslEuVz6Jb9/K22x+OcpQH5abtb278tO+Z9FwWsnu8aOvKiPuEYRrSfXC0HF8w==
dependencies:
"@babel/runtime" "^7.4.2"
classnames "^2.2.6"
prop-types "^15.7.2"
react-transition-group "^2.6.1"
react-transition-group@^2.3.1, react-transition-group@^2.6.1:
version "2.9.0"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==

Loading…
Cancel
Save