pull/84/head
jimmys-box 2 years ago
parent f11ee7b535
commit 2dbad2a117

@ -1,6 +1,6 @@
/* eslint react/prop-types: 0 */
import React from "react";
import { Button } from "reactstrap";
import { Button, UncontrolledTooltip } from "reactstrap";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faClone,
@ -8,27 +8,25 @@ import {
faExclamationTriangle,
faExternalLinkAlt,
} from "@fortawesome/free-solid-svg-icons";
import ClipboardJS from 'clipboard';
const CopyField = (props) => {
const ref = React.createRef();
const handleClickOnField = (event) => {
event.target.focus();
event.target.select();
};
const handleClickOnButton = () => {
const input = ref.current;
input.focus();
input.select();
document.execCommand("copy");
};
const { t, value, iconCopy, text } = props;
if (typeof window !== "undefined") {
new ClipboardJS('.btn');
}
const { t, value, iconCopy, iconOpen } = props;
return (
<div className="input-group my-4 ">
<input
type="text"
style={{display:"none"}}
style={{ display: "none" }}
className="form-control"
ref={ref}
value={value}
@ -37,8 +35,8 @@ const CopyField = (props) => {
/>
<div className="input-group-append copy">
{/*
<Button
{/* <Button
href={value}
target="_blank"
rel="noreferrer"
@ -47,17 +45,25 @@ const CopyField = (props) => {
>
<FontAwesomeIcon icon={iconOpen} className="mr-2" />
{t("Go")}
</Button>
*/}
</Button> */}
<Button
data-clipboard-text={value}
id="tooltip"
target="_blank"
rel="noreferrer"
className="btn btn-copy"
onClick={handleClickOnButton}
type="button"
>
{t("Copy")}
{text}
<FontAwesomeIcon icon={iconCopy} className="ml-2" />
</Button>
</div>
<UncontrolledTooltip
placement="top"
target="tooltip"
trigger="click"
>Lien copié</UncontrolledTooltip>
</div>
);
};

@ -53,24 +53,19 @@ useEffect(() => {
const addFunction = () => {
addCandidate();
setSelectedState(!selected);
};
const deleteFunction = () => {
onDelete();
toggle();
}
const [image, setImage] = useState(null);
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));
}
};
@ -154,7 +149,7 @@ const addFunction = () => {
/>
<Row className="removeAddButtons">
<ButtonWithConfirm className="removeButton" label={label} onDelete={onDelete, toggle}/>
<ButtonWithConfirm className="removeButton" label={label} onDelete={deleteFunction}/>
<Button className="addButton" label={label} onClick={addFunction}>
<FontAwesomeIcon icon={faPlus} />
<span>Ajouter</span>

@ -13,16 +13,16 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
const ConfirmModal = ({ tabIndex, title, candidates, grades, isTimeLimited, start, finish, emails, restrictResult, className, confirmCallback }) => {
const [visibled, setVisibility] = useState(false);
const { t } = useTranslation();
const toggle = () => setVisibility(!visibled)
const toggleConfirm = () => setVisibility(!visibled)
return (
<div className="input-group-append">
<Button onClick={toggle}
<Button onClick={toggleConfirm}
tabIndex={tabIndex} className={"mt-5 componentDesktop btn-transparent cursorPointer btn-validation mb-5 mx-auto" + className} >{t("Confirm")}<img src="/arrow-white.svg" /></Button>
<Button
className={"componentMobile btn-confirm-mobile mb-5" + className}
onClick={toggle}
onClick={toggleConfirm}
tabIndex={tabIndex}>
<FontAwesomeIcon className="mr-2" icon={faCheck} />
{t("Valider")}
@ -30,11 +30,11 @@ const ConfirmModal = ({ tabIndex, title, candidates, grades, isTimeLimited, star
<Modal
isOpen={!visibled}
toggle={toggle}
toggleConfirm={toggleConfirm}
className="modal-dialog-centered settings-modal"
>
<ModalHeader className="modal-header-settings">
<div onClick={toggle} className="btn-return-candidates"><FontAwesomeIcon icon={faArrowLeft} className="mr-2" />Retour aux paramètres</div>
<div onClick={toggleConfirm} className="btn-return-candidates"><FontAwesomeIcon icon={faArrowLeft} className="mr-2" />Retour aux paramètres</div>
<Row>
<Row className="stepForm">
<Col className="stepFormCol">

@ -25,7 +25,7 @@ const Header = () => {
<Navbar light className="nav-mobile" expand="lg">
<div className="navbar-header">
<Button onClick={toggle} className="navbar-toggle">
<Button onClick={toggle} className="navbar-toggle pt-0 mt-0">
<img src="/open-menu-icon.svg" alt="" height="50" />
</Button>
</div>

67
package-lock.json generated

@ -18,6 +18,7 @@
"array-move": "^3.0.1",
"bootstrap": "^4.6.0",
"bootstrap-scss": "^4.6.0",
"clipboard": "^2.0.10",
"d3": "^7.3.0",
"d3-require": "^1.2.4",
"domexception": "^2.0.1",
@ -3367,6 +3368,16 @@
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
},
"node_modules/clipboard": {
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.10.tgz",
"integrity": "sha512-cz3m2YVwFz95qSEbCDi2fzLN/epEN9zXBvfgAoGkvGOJZATMl9gtTDVOtBYkx2ODUJl2kvmud7n32sV2BpYR4g==",
"dependencies": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"node_modules/clone-deep": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
@ -4342,6 +4353,11 @@
"node": ">=0.4.0"
}
},
"node_modules/delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
},
"node_modules/dequal": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz",
@ -5186,6 +5202,14 @@
"resolve": "^1.0.0"
}
},
"node_modules/good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
"dependencies": {
"delegate": "^3.1.2"
}
},
"node_modules/graceful-fs": {
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
@ -7284,6 +7308,11 @@
"object-assign": "^4.1.1"
}
},
"node_modules/select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
},
"node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@ -7596,6 +7625,11 @@
"safe-buffer": "~5.1.0"
}
},
"node_modules/tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"node_modules/tinycolor2": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
@ -10438,6 +10472,16 @@
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
},
"clipboard": {
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.10.tgz",
"integrity": "sha512-cz3m2YVwFz95qSEbCDi2fzLN/epEN9zXBvfgAoGkvGOJZATMl9gtTDVOtBYkx2ODUJl2kvmud7n32sV2BpYR4g==",
"requires": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"clone-deep": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
@ -11217,6 +11261,11 @@
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
},
"dequal": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz",
@ -11941,6 +11990,14 @@
"resolve": "^1.0.0"
}
},
"good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
"requires": {
"delegate": "^3.1.2"
}
},
"graceful-fs": {
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
@ -13590,6 +13647,11 @@
"object-assign": "^4.1.1"
}
},
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@ -13848,6 +13910,11 @@
}
}
},
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"tinycolor2": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",

@ -19,6 +19,7 @@
"array-move": "^3.0.1",
"bootstrap": "^4.6.0",
"bootstrap-scss": "^4.6.0",
"clipboard": "^2.0.10",
"d3": "^7.3.0",
"d3-require": "^1.2.4",
"domexception": "^2.0.1",

@ -44,12 +44,15 @@ const Home = () => {
placeholder={t("resource.writeQuestion")}
autoFocus
required
className="mt-2 sectionOneHomeInput"
className="mt-2 mb-0 sectionOneHomeInput"
name="title"
value={title ? title : ""}
onChange={(e) => setTitle(e.target.value)}
maxLength="250"
maxLength="100"
/>
<p className="pt-0 mt-0 mr-0 maxLength">100</p>
</Row>
<Row>
<Link href={{ pathname: "/new/", query: { title: title } }}>
@ -58,7 +61,7 @@ const Home = () => {
className="btn btn-block btn-secondary mt-2"
>
{t("resource.start")}
<img src="/arrow-white.svg" className="mr-2" />
<img src="/arrow-white.svg" className="m-2" />
</Button>
</Link>
</Row>

@ -88,7 +88,7 @@ const ConfirmElection = ({
value={urlVote.href}
iconCopy={faCopy}
iconOpen={faExternalLinkAlt}
t={t}
text={''}
/>
</>
);
@ -206,13 +206,18 @@ const ConfirmElection = ({
<Row className="mb-4">
<Col className=" mx-auto" lg="4">
<div className="p-4 pb-5">
{electionLink}
<CopyField
value={urlVote}
iconCopy={faCopy}
iconOpen={faExternalLinkAlt}
text={t("Copier le lien du vote")}
/>
<CopyField
value={urlResult}
iconCopy={faCopy}
iconOpen={faExternalLinkAlt}
t={t}
text={t("Copier le lien des résultats")}
/>
</div>
</Col>

@ -96,7 +96,7 @@ const CreateElection = (props) => {
const now = new Date();
const [title, setTitle] = useState("");
const [candidates, setCandidates] = useState([{ label: "" }, { description: "" }]);
const [numGrades, setNumGrades] = useState(5);
const [numGrades, setNumGrades] = useState(6);
const [waiting, setWaiting] = useState(false);
const [isGradesOpen, setGradesOpen] = useState(false);
const [isAddCandidateMOpen, setAddCandidateMOpen] = useState(false);
@ -130,11 +130,11 @@ const CreateElection = (props) => {
const handleRestrictVote = (event) => {
setRestrictVote(event.target.value === "1");
};
const toggleMails = () => setVisibilityMails(!visibledMails)
const toggleGrades = () => setVisibilityGrades(!visibledGrades)
const toggle = () => setVisibility(!visibled)
const toggleAddCandidateM = () => {
setAddCandidateMOpen(!isAddCandidateMOpen);
@ -170,9 +170,7 @@ const CreateElection = (props) => {
const handleSubmit = () => {
const check = checkFields();
if (!check.ok) {
toast.error(t(check.msg), {
position: toast.POSITION.TOP_CENTER,
});
alert("Saisissez ici le nom d'au moins deux candidats.");
return;
}
@ -202,6 +200,7 @@ const CreateElection = (props) => {
}
);
};
const [visibled, setVisibility] = useState(false);
const [visibledGrades, setVisibilityGrades] = useState(false);
const [visibledMails, setVisibilityMails] = useState(false);
@ -227,7 +226,18 @@ const CreateElection = (props) => {
}, [selected]);
const changeDisplay = () => {
setSelectedState(!selected);
}
};
const badgesValues = [5, 6, 7];
const [badgesValue, setbadgesValue] = useState(6);
const handleFirstSubmit = () => {
const check = checkFields();
if (!check.ok) {
alert("Saisissez ici le nom d'au moins deux candidats.");
return;
}
changeDisplay();
};
return (
<Container className="addCandidatePage">
<Head>
@ -271,7 +281,7 @@ const CreateElection = (props) => {
<Row className="justify-content-center">
<div className="mx-auto mt-5">
<Button onClick={changeDisplay} className="cursorPointer btn-opacity btn-validation mb-5" >{t("Confirm")}<img src="/arrow-white.svg" /></Button>
<Button onClick={handleFirstSubmit} className="cursorPointer btn-opacity btn-validation mb-5" >{t("Confirm")}<img src="/arrow-white.svg" /></Button>
</div>
</Row>
</div>
@ -297,16 +307,16 @@ const CreateElection = (props) => {
</Col>
</Row>
<div className="settings-modal-body ">
<div className="mobile-title">{t("Vos paramètres")}</div>
<div className="mobile-title">{t("Vos paramètres")}</div>
<Row>
<Col>
<Row className="row-label">
<Col xs="10" lg="10">
<Label for="title">{t("Access to results")} {t("Immediately")}</Label>
<Label htmlFor="title">{t("Access to results")} {t("Immediately")}</Label>
</Col>
<Col l xs="2" lg="2">
<div class="radio-group">
<div className="radio-group">
<input
className="radio"
type="radio"
@ -316,7 +326,7 @@ const CreateElection = (props) => {
defaultChecked={!restrictResult}
value="0"
/>
<label for="restrict_result_false" />
<label htmlFor="restrict_result_false" />
<input
className="radio"
type="radio"
@ -326,8 +336,8 @@ const CreateElection = (props) => {
defaultChecked={!restrictResult}
value="1"
/>
<label for="restrict_result_true" />
<div class="radio-switch"></div>
<label htmlFor="restrict_result_true" />
<div className="radio-switch"></div>
</div>
</Col>
</Row>
@ -343,10 +353,10 @@ const CreateElection = (props) => {
<Row>
<Col xs="10">
<Label for="title">{t("Voting time")}</Label>
<Label htmlFor="title">{t("Voting time")}</Label>
</Col>
<Col l xs="2">
<div class="radio-group">
<div className="radio-group">
<input
className="radio"
type="radio"
@ -355,7 +365,7 @@ const CreateElection = (props) => {
onClick={handleIsTimeLimited}
defaultChecked={isTimeLimited}
value="0"
/><label for="is_time_limited_false" />
/><label htmlFor="is_time_limited_false" />
<input
className="radio"
type="radio"
@ -365,8 +375,8 @@ const CreateElection = (props) => {
defaultChecked={isTimeLimited}
value="1"
/>
<label for="is_time_limited_true" />
<div class="radio-switch"></div>
<label htmlFor="is_time_limited_true" />
<div className="radio-switch"></div>
</div>
</Col>
@ -472,20 +482,16 @@ const CreateElection = (props) => {
</ModalHeader>
<ModalBody>
<p>{t("Choisissez le nombre de mentions des votes.")}</p>
<div className="numGradesContainer justify-content-center" tabIndex={candidates.length + 3}
onChange={(e) => setNumGrades(e.target.value)}>
<Label className="numGrades numGradesMobile">
<Input type="radio" name="radio" value="5" />
<div className="customCheckmarck customCheckmarckMobile numGradeFive"></div>
</Label>
<Label className="numGrades numGradesMobile">
<Input type="radio" checked="checked" name="radio" value="6" />
<div className="customCheckmarck customCheckmarckMobile numGradeSix"></div>
</Label>
<Label className="numGrades numGradesMobile">
<Input type="radio" name="radio" value="7" />
<div className="customCheckmarck customCheckmarckMobile numGradeSeven"></div>
</Label>
<div className="numGradesContainer justify-content-center" tabIndex={candidates.length + 3}>
{badgesValues.map(f => (
<Label className="numGrades numGradesMobile">
<Input type="radio" name="radio" value={f} checked={badgesValue === f}
onChange={e => setNumGrades(e.currentTarget.value)} />
<div className="customCheckmarck customCheckmarckMobile"><p>{f}</p></div>
</Label>
))}
</div>
<p className="mt-2">{t("Voici la liste des mentions de votre vote")}</p>
{grades.map((mention, i) => {
@ -523,20 +529,19 @@ const CreateElection = (props) => {
<p>{t("You can select here the number of grades for your election")}</p>
</Col>
<Col xs="3">
<div className="numGradesContainer justify-content-end" tabIndex={candidates.length + 3}
onChange={(e) => setNumGrades(e.target.value)}>
<Label className="numGrades">
<Input type="radio" name="radio" value="5" />
<div className="customCheckmarck numGradeFive"></div>
</Label>
<Label className="numGrades">
<Input type="radio" checked="checked" name="radio" value="6" />
<div className="customCheckmarck numGradeSix"></div>
</Label>
<Label className="numGrades">
<Input type="radio" name="radio" value="7" />
<div className="customCheckmarck numGradeSeven"></div>
</Label>
<div className="numGradesContainer justify-content-end" tabIndex={candidates.length + 3}>
{badgesValues.map(f => (
<Label className="numGrades ">
<Input type="radio" name="radio" value={f} checked={badgesValue === f}
onChange={e => setNumGrades(e.currentTarget.value)} />
<div className="customCheckmarck"><p>{f}</p></div>
</Label>
))}
</div>
</Col>
<Col
@ -566,11 +571,11 @@ const CreateElection = (props) => {
<Col>
<Row className="row-label">
<Col xs="10" lg="10">
<Label for="title">{t("Vote privée")}</Label>
<Label htmlFor="title">{t("Vote privée")}</Label>
</Col>
<Col l xs="2" lg="2">
<div class="radio-group">
<div className="radio-group">
<input
className="radio"
type="radio"
@ -580,7 +585,7 @@ const CreateElection = (props) => {
defaultChecked={!restrictResult}
value="0"
/>
<label for="restrict_result_false" />
<label htmlFor="restrict_result_false" />
<input
className="radio"
type="radio"
@ -590,8 +595,8 @@ const CreateElection = (props) => {
defaultChecked={!restrictResult}
value="1"
/>
<label for="restrict_result_true" />
<div class="radio-switch"></div>
<label htmlFor="restrict_result_true" />
<div className="radio-switch"></div>
</div>
</Col>
</Row>

@ -51,9 +51,15 @@
border-radius: 0%;
color: #FFFFFF;
}
.sectionOneHomeInput::after {
content: '100';
}
.sectionOneHomeInput::placeholder {
color: #C3BFD8;
}
.maxLength {
color: #C3BFD8;
}
.noAds p {
font-size: 12px;
line-height: 16px;

@ -10,6 +10,9 @@
background-position: center;
padding: 0px;
}
.candidate-placeholder {
pointer-events: none;
}
.stepForm {
width: 650px;
margin: auto;
@ -341,6 +344,9 @@ text-align: right;
left: 50px;
top: 50px;
}
.avatarThumb {
width: 80%;
}
.avatarThumb input {
background-color: transparent;
color: white;
@ -394,12 +400,14 @@ line-height: 24px;
width: 44px;
height: 44px;
}
.numGrades:hover input ~ .customCheckmarck {
background-color: #ccc;
}
.numGrades input:checked ~ .customCheckmarck {
background-color: #2400FD;
}
.numGrades input:checked ~ .customCheckmarck p {
color: white;
opacity: 1;
}
.numGrades input:checked ~ .customCheckmarck::after {
display: block;
color: white;
@ -574,6 +582,22 @@ z-index: 3;
width: 100%;
height: 100%;
}
.customCheckmarck p {
margin: auto!important;
color: #0A004C;
opacity: 0.4;
font-weight: 500!important;
font-size: 16px!important;
line-height: 24px!important;
}
.customCheckmarckMobile p {
margin: auto!important;
color: #0A004C;
opacity: 0.4;
font-weight: 700!important;
font-size: 24px!important;
line-height: 24px!important;
}
.form-control {
color: #0A004C;
}

Loading…
Cancel
Save