parent
be07a76b04
commit
15183fe3d4
@ -1,60 +1,66 @@
|
||||
/**
|
||||
* This component displays a bar releaving the current step
|
||||
*/
|
||||
import {useTranslation} from "next-i18next";
|
||||
import {faArrowLeft, faCheck} from "@fortawesome/free-solid-svg-icons";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
const {Row, Col, Container} = require("reactstrap")
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { faArrowLeft, faCheck } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
const { Row, Col, Container } = require('reactstrap');
|
||||
|
||||
|
||||
const Step = ({name, position, active, check}) => {
|
||||
const {t} = useTranslation();
|
||||
const disabled = !active && !check
|
||||
return <Col
|
||||
className="col-auto">
|
||||
<Row className={`align-items-center creation-step ${active ? 'active' : ''} ${disabled ? 'disabled' : ''}`}>
|
||||
<Col className='col-auto badge align-items-center justify-content-center d-flex'>
|
||||
<div>{check ? <FontAwesomeIcon icon={faCheck} /> : position}</div>
|
||||
</Col>
|
||||
<Col className='col-auto name'>
|
||||
{t(`admin.step-${name}`)}
|
||||
</Col>
|
||||
</Row >
|
||||
</Col >
|
||||
}
|
||||
const Step = ({ name, position, active, check }) => {
|
||||
const { t } = useTranslation();
|
||||
const disabled = !active && !check;
|
||||
return (
|
||||
<Col className="col-auto">
|
||||
<Row
|
||||
className={`align-items-center creation-step ${
|
||||
active ? 'active' : ''
|
||||
} ${disabled ? 'disabled' : ''}`}
|
||||
>
|
||||
<Col className="col-auto badge align-items-center justify-content-center d-flex">
|
||||
<div>{check ? <FontAwesomeIcon icon={faCheck} /> : position}</div>
|
||||
</Col>
|
||||
<Col className="col-auto name">{t(`admin.step-${name}`)}</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
);
|
||||
};
|
||||
|
||||
export const creationSteps = ['candidate', 'params', 'confirm'];
|
||||
|
||||
export const ProgressSteps = ({step, className, ...props}) => {
|
||||
const {t} = useTranslation();
|
||||
export const ProgressSteps = ({ step, className, ...props }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!creationSteps.includes(step)) {
|
||||
throw Error(`Unknown step {step}`);
|
||||
}
|
||||
const stepId = creationSteps.indexOf(step);
|
||||
|
||||
return <Row className={`w-100 m-5 d-flex ${className}`} {...props}>
|
||||
<Col className='col-lg-3 col-6 mb-3'>
|
||||
{step === 'candidate' ? null : (
|
||||
<Row className='gx-2 align-items-end'>
|
||||
<Col className='col-auto'>
|
||||
<FontAwesomeIcon icon={faArrowLeft} />
|
||||
</Col>
|
||||
<Col className='col-auto'>
|
||||
{t('admin.candidates-back-step')}
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
</Col>
|
||||
<Col className='col-lg-6 col-12'>
|
||||
<Row className='w-100 gx-5 justify-content-center'>
|
||||
{creationSteps.map((name, i) => <Step name={name} active={step === name} check={i < stepId} key={i} position={i + 1} />
|
||||
return (
|
||||
<Row className={`w-100 m-5 d-flex ${className}`} {...props}>
|
||||
<Col className="col-lg-3 col-6 mb-3">
|
||||
{step === 'candidate' ? null : (
|
||||
<Row className="gx-2 align-items-end">
|
||||
<Col className="col-auto">
|
||||
<FontAwesomeIcon icon={faArrowLeft} />
|
||||
</Col>
|
||||
<Col className="col-auto">{t('admin.candidates-back-step')}</Col>
|
||||
</Row>
|
||||
)}
|
||||
</Row >
|
||||
</Col>
|
||||
<Col className='col-3'>
|
||||
</Col>
|
||||
</Row >
|
||||
}
|
||||
|
||||
</Col>
|
||||
<Col className="col-lg-6 col-12">
|
||||
<Row className="w-100 gx-5 justify-content-center">
|
||||
{creationSteps.map((name, i) => (
|
||||
<Step
|
||||
name={name}
|
||||
active={step === name}
|
||||
check={i < stepId}
|
||||
key={i}
|
||||
position={i + 1}
|
||||
/>
|
||||
))}
|
||||
</Row>
|
||||
</Col>
|
||||
<Col className="col-3"></Col>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
@ -1,38 +1,38 @@
|
||||
import * as d3 from 'd3';
|
||||
|
||||
const url = "https://udemy-react-d3.firebaseio.com/tallest_men.json";
|
||||
const url = 'https://udemy-react-d3.firebaseio.com/tallest_men.json';
|
||||
|
||||
const WIDTH = 800;
|
||||
const HEIGHT = 500;
|
||||
|
||||
export default class D3Chart {
|
||||
constructor(element) {
|
||||
const svg = d3.select(element)
|
||||
.append("svg")
|
||||
.attr("width", 800)
|
||||
.attr("height", 500)
|
||||
constructor(element) {
|
||||
const svg = d3
|
||||
.select(element)
|
||||
.append('svg')
|
||||
.attr('width', 800)
|
||||
.attr('height', 500);
|
||||
|
||||
d3.json(url).then(data => {
|
||||
const max = d3.max(data, d => d.height)
|
||||
const y = d3.scaleLinear()
|
||||
.domain([0, max])
|
||||
.range([0, HEIGHT])
|
||||
d3.json(url).then((data) => {
|
||||
const max = d3.max(data, (d) => d.height);
|
||||
const y = d3.scaleLinear().domain([0, max]).range([0, HEIGHT]);
|
||||
|
||||
const x = d3.scaleBand()
|
||||
.domain(data.map(d => d.name))
|
||||
.range([0, WIDTH])
|
||||
.padding(0.4)
|
||||
const x = d3
|
||||
.scaleBand()
|
||||
.domain(data.map((d) => d.name))
|
||||
.range([0, WIDTH])
|
||||
.padding(0.4);
|
||||
|
||||
const rects = svg.selectAll("rect")
|
||||
.data(data)
|
||||
const rects = svg.selectAll('rect').data(data);
|
||||
|
||||
rects.enter()
|
||||
.append("rect")
|
||||
.attr("x", d => x(d.name))
|
||||
.attr("y", d => HEIGHT - y(d.height))
|
||||
.attr("width", x.bandwidth)
|
||||
.attr("height", d => y(d.height))
|
||||
.attr("fill", "grey")
|
||||
})
|
||||
}
|
||||
}
|
||||
rects
|
||||
.enter()
|
||||
.append('rect')
|
||||
.attr('x', (d) => x(d.name))
|
||||
.attr('y', (d) => HEIGHT - y(d.height))
|
||||
.attr('width', x.bandwidth)
|
||||
.attr('height', (d) => y(d.height))
|
||||
.attr('fill', 'grey');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,21 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import Image from 'next/image'
|
||||
import logoWithText from '../public/logos/logo.svg'
|
||||
import logo from '../public/logos/logo-footer.svg'
|
||||
import {useTranslation} from "next-i18next";
|
||||
import Image from 'next/image';
|
||||
import logoWithText from '../public/logos/logo.svg';
|
||||
import logo from '../public/logos/logo-footer.svg';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
|
||||
const Logo = ({title, ...props}) => {
|
||||
const {t} = useTranslation();
|
||||
const Logo = ({ title, ...props }) => {
|
||||
const { t } = useTranslation();
|
||||
const src = title ? logoWithText : logo;
|
||||
return (
|
||||
<Image
|
||||
src={src}
|
||||
alt={t('logo.alt')}
|
||||
className="d-block"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
return <Image src={src} alt={t('logo.alt')} className="d-block" {...props} />;
|
||||
};
|
||||
|
||||
Logo.propTypes = {
|
||||
title: PropTypes.bool
|
||||
title: PropTypes.bool,
|
||||
};
|
||||
|
||||
Logo.defaultProps = {
|
||||
title: true
|
||||
title: true,
|
||||
};
|
||||
|
||||
export default Logo;
|
||||
|
@ -1,33 +1,27 @@
|
||||
// TODO use bootstrap modal
|
||||
// https://getbootstrap.com/docs/5.0/components/modal/
|
||||
//
|
||||
const Modal = ({show, onClose, children, title}) => {
|
||||
|
||||
const Modal = ({ show, onClose, children, title }) => {
|
||||
const handleCloseClick = (e) => {
|
||||
e.preventDefault();
|
||||
onClose();
|
||||
};
|
||||
|
||||
const modalContent = show ? (
|
||||
<div className='vh-100 modal overlay'>
|
||||
<div className='modal body'>
|
||||
<div className='modal header'>
|
||||
<div className="vh-100 modal overlay">
|
||||
<div className="modal body">
|
||||
<div className="modal header">
|
||||
<a href="#" onClick={handleCloseClick}>
|
||||
x
|
||||
</a>
|
||||
</div>
|
||||
{title && <div>{title}</div>}
|
||||
<div className='pt-5'>{children}</div>
|
||||
<div className="pt-5">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
|
||||
return (
|
||||
modalContent
|
||||
);
|
||||
|
||||
return modalContent;
|
||||
};
|
||||
|
||||
|
||||
export default Modal;
|
||||
|
@ -1,9 +1,15 @@
|
||||
|
||||
const Switch = ({toggle, state}) => {
|
||||
return (<div className="form-check form-switch">
|
||||
<input onChange={toggle} className="form-check-input" type="checkbox" role="switch" checked={state} />
|
||||
</div>)
|
||||
}
|
||||
|
||||
const Switch = ({ toggle, state }) => {
|
||||
return (
|
||||
<div className="form-check form-switch">
|
||||
<input
|
||||
onChange={toggle}
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
checked={state}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Switch;
|
||||
|
@ -1,33 +1,35 @@
|
||||
import {useTranslation} from "next-i18next";
|
||||
import {useElection, useElectionDispatch} from './ElectionContext';
|
||||
import {Container, Row, Col} from 'reactstrap'
|
||||
import Switch from '@components/Switch'
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useElection, useElectionDispatch } from './ElectionContext';
|
||||
import { Container, Row, Col } from 'reactstrap';
|
||||
import Switch from '@components/Switch';
|
||||
|
||||
const AccessResults = () => {
|
||||
const {t} = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const election = useElection();
|
||||
const dispatch = useElectionDispatch();
|
||||
|
||||
const toggle = () => {
|
||||
dispatch({
|
||||
'type': 'set',
|
||||
'field': 'restrictResult',
|
||||
'value': !election.restrictResult
|
||||
})
|
||||
}
|
||||
type: 'set',
|
||||
field: 'restrictResult',
|
||||
value: !election.restrictResult,
|
||||
});
|
||||
};
|
||||
|
||||
return (<Container className='bg-white container-fluid p-4'>
|
||||
<Row>
|
||||
<Col className='col-auto me-auto'>
|
||||
<h4 className='text-dark'>{t('admin.access-results')}</h4>
|
||||
<p className='text-muted'>{t('admin.access-results-desc')}</p>
|
||||
</Col>
|
||||
<Col className='col-auto d-flex align-items-center'>
|
||||
<Switch toggle={toggle} state={election.restrictResult} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>)
|
||||
}
|
||||
return (
|
||||
<Container className="bg-white container-fluid p-4">
|
||||
<Row>
|
||||
<Col className="col-auto me-auto">
|
||||
<h4 className="text-dark">{t('admin.access-results')}</h4>
|
||||
<p className="text-muted">{t('admin.access-results-desc')}</p>
|
||||
</Col>
|
||||
<Col className="col-auto d-flex align-items-center">
|
||||
<Switch toggle={toggle} state={election.restrictResult} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default AccessResults
|
||||
export default AccessResults;
|
||||
|
@ -1,59 +1,56 @@
|
||||
import {useState} from "react";
|
||||
import {
|
||||
faTrashAlt,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import {Button, Modal, ModalHeader, ModalBody, ModalFooter} from "reactstrap";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {useTranslation} from "next-i18next";
|
||||
import { useState } from 'react';
|
||||
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
const ButtonWithConfirm = ({className, label, onDelete}) => {
|
||||
const ButtonWithConfirm = ({ className, label, onDelete }) => {
|
||||
const [visibled, setVisibility] = useState(false);
|
||||
const {t} = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const toggle = () => setVisibility(!visibled)
|
||||
const toggle = () => setVisibility(!visibled);
|
||||
|
||||
return (
|
||||
<div className="input-group-append cancelButton">
|
||||
<button
|
||||
type="button"
|
||||
className={"btn " + className}
|
||||
onClick={toggle}
|
||||
>
|
||||
<div className="annuler"><img className="ml-0" src="/arrow-dark-left.svg" /><p className="ml-0" >Annuler</p></div>
|
||||
<button type="button" className={'btn ' + className} onClick={toggle}>
|
||||
<div className="annuler">
|
||||
<img className="ml-0" src="/arrow-dark-left.svg" />
|
||||
<p className="ml-0">Annuler</p>
|
||||
</div>
|
||||
</button>
|
||||
<Modal
|
||||
isOpen={visibled}
|
||||
toggle={toggle}
|
||||
className="modal-dialog-centered cancelForm"
|
||||
>
|
||||
<ModalHeader><FontAwesomeIcon icon={faTrashAlt} /></ModalHeader>
|
||||
<ModalHeader>
|
||||
<FontAwesomeIcon icon={faTrashAlt} />
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
{t("Are you sure to delete")}{<br />}
|
||||
{label && label !== "" ? (
|
||||
<b>{label}</b>
|
||||
) : (
|
||||
<>{t("the row")}</>
|
||||
)}
|
||||
{t('Are you sure to delete')}
|
||||
{<br />}
|
||||
{label && label !== '' ? <b>{label}</b> : <>{t('the row')}</>}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
|
||||
className={className}
|
||||
onClick={toggle}>
|
||||
<div className="annuler"><img src="/arrow-dark-left.svg" /> {t("No")}</div>
|
||||
|
||||
<Button className={className} onClick={toggle}>
|
||||
<div className="annuler">
|
||||
<img src="/arrow-dark-left.svg" /> {t('No')}
|
||||
</div>
|
||||
</Button>
|
||||
<Button
|
||||
className="new-btn-confirm"
|
||||
onClick={() => {toggle(); onDelete();}}
|
||||
className="new-btn-confirm"
|
||||
onClick={() => {
|
||||
toggle();
|
||||
onDelete();
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faTrashAlt} className="mr-2"/>
|
||||
{t("Yes")}
|
||||
<FontAwesomeIcon icon={faTrashAlt} className="mr-2" />
|
||||
{t('Yes')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
</div >
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default ButtonWithConfirm;
|
||||
|
@ -1,72 +1,83 @@
|
||||
/**
|
||||
* This is the candidate field used during election creation
|
||||
*/
|
||||
import {useState} from 'react'
|
||||
import Image from 'next/image'
|
||||
import {useTranslation} from "next-i18next";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
faPlus,
|
||||
faTrashCan,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import {Row, Col} from "reactstrap";
|
||||
import {useElection, useElectionDispatch} from './ElectionContext';
|
||||
import defaultAvatar from '../../public/avatar.svg'
|
||||
import { useState } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faPlus, faTrashCan } from '@fortawesome/free-solid-svg-icons';
|
||||
import { Row, Col } from 'reactstrap';
|
||||
import { useElection, useElectionDispatch } from './ElectionContext';
|
||||
import defaultAvatar from '../../public/avatar.svg';
|
||||
import CandidateModalSet from './CandidateModalSet';
|
||||
import CandidateModalDel from './CandidateModalDel';
|
||||
|
||||
|
||||
const CandidateField = ({position, className = '', ...inputProps}) => {
|
||||
const {t} = useTranslation();
|
||||
const CandidateField = ({ position, className = '', ...inputProps }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const election = useElection();
|
||||
const dispatch = useElectionDispatch();
|
||||
const candidate = election.candidates[position];
|
||||
const image = candidate && candidate.image ? candidate.image : defaultAvatar;
|
||||
const active = candidate && candidate.active === true
|
||||
const active = candidate && candidate.active === true;
|
||||
|
||||
const [modalDel, setModalDel] = useState(false);
|
||||
const [modalSet, setModalSet] = useState(false);
|
||||
|
||||
const addCandidate = () => {
|
||||
dispatch({'type': 'candidate-push', 'value': "default"})
|
||||
dispatch({ type: 'candidate-push', value: 'default' });
|
||||
};
|
||||
|
||||
const toggleSet = () => setModalSet(m => !m)
|
||||
const toggleDel = () => setModalDel(m => !m)
|
||||
const toggleSet = () => setModalSet((m) => !m);
|
||||
const toggleDel = () => setModalDel((m) => !m);
|
||||
|
||||
return (
|
||||
<Row
|
||||
className={`${className || ""} p-2 my-3 border border-dashed border-2 border-light border-opacity-25 align-items-center ${active ? "active" : ""}`}
|
||||
className={`${
|
||||
className || ''
|
||||
} p-2 my-3 border border-dashed border-2 border-light border-opacity-25 align-items-center ${
|
||||
active ? 'active' : ''
|
||||
}`}
|
||||
{...inputProps}
|
||||
>
|
||||
<Col onClick={toggleSet} className='cursor-pointer col-auto me-auto'>
|
||||
<Row className='gx-3'>
|
||||
<Col className='col-auto'>
|
||||
<Image src={image} width={24} height={24} className={image == defaultAvatar ? "default-avatar" : ""} alt={t('common.thumbnail')} />
|
||||
<Col onClick={toggleSet} className="cursor-pointer col-auto me-auto">
|
||||
<Row className="gx-3">
|
||||
<Col className="col-auto">
|
||||
<Image
|
||||
src={image}
|
||||
width={24}
|
||||
height={24}
|
||||
className={image == defaultAvatar ? 'default-avatar' : ''}
|
||||
alt={t('common.thumbnail')}
|
||||
/>
|
||||
</Col>
|
||||
<Col className='col-auto fw-bold'>
|
||||
{candidate.name ? candidate.name : t("admin.add-candidate")}
|
||||
<Col className="col-auto fw-bold">
|
||||
{candidate.name ? candidate.name : t('admin.add-candidate')}
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col className='col-auto cursor-pointer'>
|
||||
{active ?
|
||||
<Col className="col-auto cursor-pointer">
|
||||
{active ? (
|
||||
<FontAwesomeIcon
|
||||
icon={faTrashCan}
|
||||
onClick={() => setModalDel(m => !m)}
|
||||
/> :
|
||||
<FontAwesomeIcon
|
||||
icon={faPlus}
|
||||
onClick={addCandidate}
|
||||
onClick={() => setModalDel((m) => !m)}
|
||||
/>
|
||||
}
|
||||
|
||||
) : (
|
||||
<FontAwesomeIcon icon={faPlus} onClick={addCandidate} />
|
||||
)}
|
||||
</Col>
|
||||
<CandidateModalSet toggle={toggleSet} isOpen={modalSet} position={position} />
|
||||
<CandidateModalDel toggle={toggleDel} isOpen={modalDel} position={position} />
|
||||
</Row >
|
||||
<CandidateModalSet
|
||||
toggle={toggleSet}
|
||||
isOpen={modalSet}
|
||||
position={position}
|
||||
/>
|
||||
<CandidateModalDel
|
||||
toggle={toggleDel}
|
||||
isOpen={modalDel}
|
||||
position={position}
|
||||
/>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default CandidateField;
|
||||
|
@ -1,72 +1,73 @@
|
||||
import {
|
||||
Row,
|
||||
Col,
|
||||
Label,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
Form
|
||||
} from "reactstrap";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import { Row, Col, Label, Input, Modal, ModalBody, Form } from 'reactstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
faTrashCan,
|
||||
faTrashAlt,
|
||||
faArrowLeft,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import {useTranslation} from "next-i18next";
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import Image from 'next/image';
|
||||
import {useElection, useElectionDispatch} from './ElectionContext';
|
||||
import Button from '@components/Button'
|
||||
import {upload} from '@services/imgpush';
|
||||
import {IMGPUSH_URL} from '@services/constants';
|
||||
import defaultAvatar from '../../public/default-avatar.svg'
|
||||
import {useEffect} from "react";
|
||||
|
||||
import { useElection, useElectionDispatch } from './ElectionContext';
|
||||
import Button from '@components/Button';
|
||||
import { upload } from '@services/imgpush';
|
||||
import { IMGPUSH_URL } from '@services/constants';
|
||||
import defaultAvatar from '../../public/default-avatar.svg';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const CandidateModal = ({isOpen, position, toggle}) => {
|
||||
|
||||
const {t} = useTranslation();
|
||||
const CandidateModal = ({ isOpen, position, toggle }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const election = useElection();
|
||||
const dispatch = useElectionDispatch();
|
||||
const candidate = election.candidates[position];
|
||||
|
||||
const removeCandidate = () => {
|
||||
dispatch({'type': 'candidate-rm', 'position': position})
|
||||
}
|
||||
|
||||
dispatch({ type: 'candidate-rm', position: position });
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
toggle={toggle}
|
||||
keyboard={true}
|
||||
className='modal_candidate'
|
||||
className="modal_candidate"
|
||||
>
|
||||
<ModalBody className='flex-column justify-contenter-center d-flex p-4'>
|
||||
<Row className='justify-content-center'>
|
||||
<Col className='col-auto px-4 py-4 rounded-circle bg-light'>
|
||||
<ModalBody className="flex-column justify-contenter-center d-flex p-4">
|
||||
<Row className="justify-content-center">
|
||||
<Col className="col-auto px-4 py-4 rounded-circle bg-light">
|
||||
<FontAwesomeIcon size="2x" icon={faTrashCan} />
|
||||
</Col>
|
||||
</Row>
|
||||
<p className='text-danger fw-bold text-center mt-4'>{t('admin.candidate-confirm-del')}
|
||||
<p className="text-danger fw-bold text-center mt-4">
|
||||
{t('admin.candidate-confirm-del')}
|
||||
</p>
|
||||
{candidate.name ? <h4 className='text-center'>{candidate.name}</h4> : null}
|
||||
<Row className='mt-5 mb-3'>
|
||||
<Col className='col-auto me-auto'>
|
||||
<Button onClick={toggle} color='dark' icon={faArrowLeft} outline={true}>
|
||||
{candidate.name ? (
|
||||
<h4 className="text-center">{candidate.name}</h4>
|
||||
) : null}
|
||||
<Row className="mt-5 mb-3">
|
||||
<Col className="col-auto me-auto">
|
||||
<Button
|
||||
onClick={toggle}
|
||||
color="dark"
|
||||
icon={faArrowLeft}
|
||||
outline={true}
|
||||
>
|
||||
{t('admin.candidate-confirm-back')}
|
||||
</Button>
|
||||
</Col>
|
||||
<Col className='col-auto '>
|
||||
<Button icon={faTrashAlt} outline={true} color="primary" onClick={removeCandidate}>
|
||||
<Col className="col-auto ">
|
||||
<Button
|
||||
icon={faTrashAlt}
|
||||
outline={true}
|
||||
color="primary"
|
||||
onClick={removeCandidate}
|
||||
>
|
||||
{t('admin.candidate-confirm-ok')}
|
||||
</Button>
|
||||
</Col>
|
||||
|
||||
</Row >
|
||||
</ModalBody >
|
||||
</Modal >);
|
||||
|
||||
}
|
||||
</Row>
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
export default CandidateModal;
|
||||
|
@ -1,57 +1,56 @@
|
||||
import {useState, useEffect, createRef} from 'react'
|
||||
import {useTranslation} from "next-i18next";
|
||||
import {Container} from 'reactstrap';
|
||||
import {faArrowRight} from "@fortawesome/free-solid-svg-icons";
|
||||
import {MAX_NUM_CANDIDATES} from '@services/constants';
|
||||
import Alert from '@components/Alert'
|
||||
import Button from '@components/Button'
|
||||
import {useElection, useElectionDispatch} from './ElectionContext';
|
||||
import CandidateField from './CandidateField'
|
||||
|
||||
|
||||
const CandidatesField = ({onSubmit}) => {
|
||||
const {t} = useTranslation();
|
||||
import { useState, useEffect, createRef } from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { Container } from 'reactstrap';
|
||||
import { faArrowRight } from '@fortawesome/free-solid-svg-icons';
|
||||
import { MAX_NUM_CANDIDATES } from '@services/constants';
|
||||
import Alert from '@components/Alert';
|
||||
import Button from '@components/Button';
|
||||
import { useElection, useElectionDispatch } from './ElectionContext';
|
||||
import CandidateField from './CandidateField';
|
||||
|
||||
const CandidatesField = ({ onSubmit }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const election = useElection();
|
||||
const dispatch = useElectionDispatch();
|
||||
const candidates = election.candidates;
|
||||
const [error, setError] = useState(null)
|
||||
const disabled = candidates.filter(c => c.name !== "").length < 2;
|
||||
const [error, setError] = useState(null);
|
||||
const disabled = candidates.filter((c) => c.name !== '').length < 2;
|
||||
|
||||
// What to do when we change the candidates
|
||||
useEffect(() => {
|
||||
// Initialize the list with at least two candidates
|
||||
if (candidates.length < 2) {
|
||||
dispatch({'type': 'candidate-push', 'value': "default"})
|
||||
dispatch({ type: 'candidate-push', value: 'default' });
|
||||
}
|
||||
if (candidates.length > MAX_NUM_CANDIDATES) {
|
||||
setError('error.too-many-candidates')
|
||||
setError('error.too-many-candidates');
|
||||
}
|
||||
}, [candidates])
|
||||
}, [candidates]);
|
||||
|
||||
return (
|
||||
<Container className="candidate flex-grow-1 mt-5 flex-column d-flex justify-content-between">
|
||||
<div className="d-flex flex-column">
|
||||
<h4 className='mb-4'>{t('admin.add-candidates')}</h4>
|
||||
<h4 className="mb-4">{t('admin.add-candidates')}</h4>
|
||||
<Alert msg={error} />
|
||||
{candidates.map((candidate, index) => {
|
||||
return (
|
||||
<CandidateField
|
||||
key={index}
|
||||
position={index}
|
||||
/>
|
||||
)
|
||||
return <CandidateField key={index} position={index} />;
|
||||
})}
|
||||
</div>
|
||||
<div className="mb-5 d-flex justify-content-center">
|
||||
<Button outline={true} color="secondary" onClick={onSubmit} disabled={disabled} icon={faArrowRight} position="right">
|
||||
<Button
|
||||
outline={true}
|
||||
color="secondary"
|
||||
onClick={onSubmit}
|
||||
disabled={disabled}
|
||||
icon={faArrowRight}
|
||||
position="right"
|
||||
>
|
||||
{t('admin.candidates-submit')}
|
||||
</Button>
|
||||
</div>
|
||||
</Container >
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default CandidatesField
|
||||
};
|
||||
|
||||
export default CandidatesField;
|
||||
|
@ -1,71 +1,78 @@
|
||||
import {useTranslation} from "next-i18next";
|
||||
import Footer from "@components/layouts/Footer";
|
||||
import TrashButton from "./TrashButton";
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import Footer from '@components/layouts/Footer';
|
||||
import TrashButton from './TrashButton';
|
||||
import {
|
||||
faExclamationTriangle,
|
||||
faCheck,
|
||||
faArrowLeft,
|
||||
faPen,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import {Button, Modal, ModalHeader, ModalBody, ModalFooter, Row, Col, Label, Container} from "reactstrap";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {useElection} from "./ElectionContext";
|
||||
import CandidateField from "./CandidateField";
|
||||
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
Row,
|
||||
Col,
|
||||
Label,
|
||||
Container,
|
||||
} from 'reactstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useElection } from './ElectionContext';
|
||||
import CandidateField from './CandidateField';
|
||||
|
||||
const TitleField = () => {
|
||||
const {t} = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
const election = useElection();
|
||||
return <Container className='bg-white container-fluid p-4'>
|
||||
<Row>
|
||||
<Col className='col-auto me-auto'>
|
||||
<h4 className='text-dark'>{t('admin.access-results')}</h4>
|
||||
</Col>
|
||||
</Row>
|
||||
<h4 className='text-primary'>
|
||||
{election.title}
|
||||
</h4>
|
||||
</Container>
|
||||
}
|
||||
|
||||
return (
|
||||
<Container className="bg-white container-fluid p-4">
|
||||
<Row>
|
||||
<Col className="col-auto me-auto">
|
||||
<h4 className="text-dark">{t('admin.access-results')}</h4>
|
||||
</Col>
|
||||
</Row>
|
||||
<h4 className="text-primary">{election.title}</h4>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
const CandidatesField = () => {
|
||||
const {t} = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
const election = useElection();
|
||||
return <Container className='bg-white container-fluid p-4'>
|
||||
<Row>
|
||||
<Col className='col-auto me-auto'>
|
||||
<h4 className='text-dark'>{t('admin.access-results')}</h4>
|
||||
</Col>
|
||||
<Col className='col-auto d-flex align-items-center'>
|
||||
<FontAwesomeIcon icon={faPen} />
|
||||
</Col>
|
||||
</Row>
|
||||
{election.candidates.map((_, i) =>
|
||||
<CandidateField position={i} />
|
||||
)}
|
||||
</Container>
|
||||
}
|
||||
|
||||
return (
|
||||
<Container className="bg-white container-fluid p-4">
|
||||
<Row>
|
||||
<Col className="col-auto me-auto">
|
||||
<h4 className="text-dark">{t('admin.access-results')}</h4>
|
||||
</Col>
|
||||
<Col className="col-auto d-flex align-items-center">
|
||||
<FontAwesomeIcon icon={faPen} />
|
||||
</Col>
|
||||
</Row>
|
||||
{election.candidates.map((_, i) => (
|
||||
<CandidateField position={i} />
|
||||
))}
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
const ConfirmField = ({onSubmit, goToCandidates, goToParams}) => {
|
||||
const {t} = useTranslation();
|
||||
const ConfirmField = ({ onSubmit, goToCandidates, goToParams }) => {
|
||||
const { t } = useTranslation();
|
||||
const election = useElection();
|
||||
|
||||
return (
|
||||
<Container className="params flex-grow-1 my-5 mt-5 flex-column d-flex justify-content-between">
|
||||
<Row>
|
||||
<Col className='col-md-auto col-12'>
|
||||
<h4 className='mb-3'>{t('common.the-vote')}</h4>
|
||||
<Col className="col-md-auto col-12">
|
||||
<h4 className="mb-3">{t('common.the-vote')}</h4>
|
||||
<TitleField />
|
||||
<CandidatesField />
|
||||
</Col>
|
||||
<Col className='col-md-auto col-12'>
|
||||
|
||||
</Col>
|
||||
<Col className="col-md-auto col-12"></Col>
|
||||
</Row>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfirmField
|
||||
export default ConfirmField;
|
||||
|
@ -1,70 +1,79 @@
|
||||
/**
|
||||
* A field to update the grades
|
||||
*/
|
||||
import {useState, useEffect} from 'react'
|
||||
import {useTranslation} from "next-i18next";
|
||||
import {Container, Row, Col} from 'reactstrap';
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { Container, Row, Col } from 'reactstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
faPlus, faPen, faXmark, faCheck
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import {DEFAULT_GRADES, GRADE_COLORS} from '@services/constants';
|
||||
import {useElection, useElectionDispatch} from './ElectionContext';
|
||||
faPlus,
|
||||
faPen,
|
||||
faXmark,
|
||||
faCheck,
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { DEFAULT_GRADES, GRADE_COLORS } from '@services/constants';
|
||||
import { useElection, useElectionDispatch } from './ElectionContext';
|
||||
import GradeField from './GradeField';
|
||||
|
||||
const AddField = () => {
|
||||
const {t} = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [modal, setModal] = useState(false);
|
||||
const toggle = () => setModal(m => !m)
|
||||
const toggle = () => setModal((m) => !m);
|
||||
|
||||
const dispatch = useElectionDispatch();
|
||||
|
||||
return <Row
|
||||
onClick={toggle}
|
||||
className='border border-2 border-primary text-black p-2 m-1 rounded-pill'
|
||||
>
|
||||
<Col className='col-auto'>
|
||||
<FontAwesomeIcon icon={faPlus} />
|
||||
</Col>
|
||||
</Row >
|
||||
}
|
||||
return (
|
||||
<Row
|
||||
onClick={toggle}
|
||||
className="border border-2 border-primary text-black p-2 m-1 rounded-pill"
|
||||
>
|
||||
<Col className="col-auto">
|
||||
<FontAwesomeIcon icon={faPlus} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
const Grades = () => {
|
||||
const {t} = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
const defaultEndDate = new Date();
|
||||
defaultEndDate.setUTCDate(defaultEndDate.getUTCDate() + 15)
|
||||
defaultEndDate.setUTCDate(defaultEndDate.getUTCDate() + 15);
|
||||
const [endDate, setEndDate] = useState(defaultEndDate);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({
|
||||
type: "set",
|
||||
field: "grades",
|
||||
type: 'set',
|
||||
field: 'grades',
|
||||
value: DEFAULT_GRADES.map((g, i) => ({
|
||||
name: t(g),
|
||||
active: true,
|
||||
color: GRADE_COLORS[i]
|
||||
}))
|
||||
})
|
||||
console.log('foo')
|
||||
}, [])
|
||||
color: GRADE_COLORS[i],
|
||||
})),
|
||||
});
|
||||
console.log('foo');
|
||||
}, []);
|
||||
|
||||
const election = useElection();
|
||||
const grades = election.grades;
|
||||
const dispatch = useElectionDispatch();
|
||||
|
||||
return (<Container className='bg-white container-fluid p-4 mt-1'>
|
||||
<Row>
|
||||
<Col className='col-auto me-auto'>
|
||||
<h4 className='text-dark'>{t('common.grades')}</h4>
|
||||
<p className='text-muted'>{t('admin.grades-desc')}</p>
|
||||
</Col>
|
||||
<Col className='col-auto d-flex align-items-center'>
|
||||
{grades.map((_, i) => <GradeField value={i} key={i} />)}
|
||||
{ /* <AddField /> */}
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>)
|
||||
}
|
||||
return (
|
||||
<Container className="bg-white container-fluid p-4 mt-1">
|
||||
<Row>
|
||||
<Col className="col-auto me-auto">
|
||||
<h4 className="text-dark">{t('common.grades')}</h4>
|
||||
<p className="text-muted">{t('admin.grades-desc')}</p>
|
||||
</Col>
|
||||
<Col className="col-auto d-flex align-items-center">
|
||||
{grades.map((_, i) => (
|
||||
<GradeField value={i} key={i} />
|
||||
))}
|
||||
{/* <AddField /> */}
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default Grades;
|
||||
|
@ -1,53 +1,55 @@
|
||||
import {useState} from "react";
|
||||
import {
|
||||
faTrashAlt,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import {Button, Modal, ModalHeader, ModalBody, ModalFooter} from "reactstrap";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {useTranslation} from "next-i18next";
|
||||
import { useState } from 'react';
|
||||
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
const TrashButton = ({className, label, onClick}) => {
|
||||
const TrashButton = ({ className, label, onClick }) => {
|
||||
const [visibled, setVisibility] = useState(false);
|
||||
const {t} = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const toggle = () => setVisibility(!visibled)
|
||||
const toggle = () => setVisibility(!visibled);
|
||||
|
||||
return (
|
||||
<div className="input-group-append cancelButton">
|
||||
<FontAwesomeIcon onClick={toggle} icon={faTrashAlt} className="mr-2 cursorPointer" />
|
||||
<FontAwesomeIcon
|
||||
onClick={toggle}
|
||||
icon={faTrashAlt}
|
||||
className="mr-2 cursorPointer"
|
||||
/>
|
||||
<Modal
|
||||
isOpen={visibled}
|
||||
toggle={toggle}
|
||||
className="modal-dialog-centered cancelForm"
|
||||
>
|
||||
<ModalHeader><FontAwesomeIcon icon={faTrashAlt} /></ModalHeader>
|
||||
<ModalHeader>
|
||||
<FontAwesomeIcon icon={faTrashAlt} />
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
{t("Are you sure to delete")}{<br />}
|
||||
{label && label !== "" ? (
|
||||
<b>{label}</b>
|
||||
) : (
|
||||
<>{t("the row")}</>
|
||||
)}
|
||||
{t('Are you sure to delete')}
|
||||
{<br />}
|
||||
{label && label !== '' ? <b>{label}</b> : <>{t('the row')}</>}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
type="button"
|
||||
className={className}
|
||||
onClick={toggle}>
|
||||
<div className="annuler"><img src="/arrow-dark-left.svg" /> {t("No")}</div>
|
||||
|
||||
<Button type="button" className={className} onClick={toggle}>
|
||||
<div className="annuler">
|
||||
<img src="/arrow-dark-left.svg" /> {t('No')}
|
||||
</div>
|
||||
</Button>
|
||||
<Button
|
||||
className="new-btn-confirm"
|
||||
onClick={() => {toggle(); onClick();}}
|
||||
onClick={() => {
|
||||
toggle();
|
||||
onClick();
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faTrashAlt} className="mr-2" />
|
||||
{t("Yes")}
|
||||
{t('Yes')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
</div >
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default TrashButton;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import * as React from "react";
|
||||
import FlagIconFactory from "react-flag-icon-css";
|
||||
import * as React from 'react';
|
||||
import FlagIconFactory from 'react-flag-icon-css';
|
||||
|
||||
export const FlagIcon = FlagIconFactory(React, { useCssModules: false });
|
||||
|
@ -1,14 +1,11 @@
|
||||
|
||||
import React from 'react';
|
||||
import HeaderDesktopResult from './HeaderDesktopResult';
|
||||
import HeaderMobileResult from './HeaderMobileResult';
|
||||
import { useMediaQuery } from "react-responsive";
|
||||
import { useMediaQuery } from 'react-responsive';
|
||||
|
||||
export default function HeaderResult() {
|
||||
const isMobile = useMediaQuery({ query: '(max-width: 800px)' });
|
||||
|
||||
const isMobile = useMediaQuery({ query: "(max-width: 800px)" });
|
||||
|
||||
if (isMobile) return <HeaderMobileResult />;
|
||||
|
||||
else return <HeaderDesktopResult />;
|
||||
}
|
||||
if (isMobile) return <HeaderMobileResult />;
|
||||
else return <HeaderDesktopResult />;
|
||||
}
|
||||
|
@ -1,41 +1,44 @@
|
||||
import Head from 'next/head'
|
||||
import '@styles/globals.css'
|
||||
import '@styles/loader.css'
|
||||
import "@styles/scss/config.scss";
|
||||
import '@fortawesome/fontawesome-svg-core/styles.css'
|
||||
import Head from 'next/head';
|
||||
import '@styles/globals.css';
|
||||
import '@styles/loader.css';
|
||||
import '@styles/scss/config.scss';
|
||||
import '@fortawesome/fontawesome-svg-core/styles.css';
|
||||
|
||||
// import nextI18NextConfig from '../next-i18next.config.js'
|
||||
|
||||
import {appWithTranslation} from 'next-i18next'
|
||||
import {AppProvider} from '@services/context'
|
||||
import Header from '@components/layouts/Header'
|
||||
import Footer from '@components/layouts/Footer'
|
||||
import { appWithTranslation } from 'next-i18next';
|
||||
import { AppProvider } from '@services/context';
|
||||
import Header from '@components/layouts/Header';
|
||||
import Footer from '@components/layouts/Footer';
|
||||
|
||||
|
||||
function Application({Component, pageProps}) {
|
||||
const origin = typeof window !== 'undefined' && window.location.origin ? window.location.origin : 'http://localhost';
|
||||
return (<AppProvider><Head>
|
||||
<link rel="icon" key="favicon" href="/favicon.ico" />
|
||||
<meta property="og:type" content="website" key="og:type" />
|
||||
<meta property="og:url" content={origin} key="og:url" />
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://app.mieuxvoter.fr/app-mieux-voter.png"
|
||||
key="og:image"
|
||||
/>
|
||||
</Head>
|
||||
<main className='d-flex flex-column justify-content-between'>
|
||||
<div className='d-flex flex-grow-1 justify-content-center'>
|
||||
<Header />
|
||||
<div className="d-flex flex-column w-100 align-items-start">
|
||||
<Component {...pageProps} />
|
||||
function Application({ Component, pageProps }) {
|
||||
const origin =
|
||||
typeof window !== 'undefined' && window.location.origin
|
||||
? window.location.origin
|
||||
: 'http://localhost';
|
||||
return (
|
||||
<AppProvider>
|
||||
<Head>
|
||||
<link rel="icon" key="favicon" href="/favicon.ico" />
|
||||
<meta property="og:type" content="website" key="og:type" />
|
||||
<meta property="og:url" content={origin} key="og:url" />
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://app.mieuxvoter.fr/app-mieux-voter.png"
|
||||
key="og:image"
|
||||
/>
|
||||
</Head>
|
||||
<main className="d-flex flex-column justify-content-between">
|
||||
<div className="d-flex flex-grow-1 justify-content-center">
|
||||
<Header />
|
||||
<div className="d-flex flex-column w-100 align-items-start">
|
||||
<Component {...pageProps} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
</AppProvider>);
|
||||
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
</AppProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default appWithTranslation(Application)
|
||||
export default appWithTranslation(Application);
|
||||
|
@ -1,28 +1,25 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
// import Plot from 'react-plotly.js';
|
||||
import React, {Component} from 'react';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
class BarChart extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
return <div></div>;
|
||||
}
|
||||
}
|
||||
|
||||
export default BarChart;
|
||||
|
||||
// <Plot
|
||||
// data={[
|
||||
// {
|
||||
// type: 'bar',
|
||||
// x: ['Taubira', 'Hidalgo', 'Mélenchon'],
|
||||
// y: [29, 150, 85]
|
||||
// }
|
||||
// ]}
|
||||
// layout={{width: 1000, height: 500, title: 'Nombre de voix par candidat'}}
|
||||
// config={{
|
||||
// displayModeBar: false // this is the line that hides the bar.
|
||||
// }}
|
||||
// />
|
||||
// <Plot
|
||||
// data={[
|
||||
// {
|
||||
// type: 'bar',
|
||||
// x: ['Taubira', 'Hidalgo', 'Mélenchon'],
|
||||
// y: [29, 150, 85]
|
||||
// }
|
||||
// ]}
|
||||
// layout={{width: 1000, height: 500, title: 'Nombre de voix par candidat'}}
|
||||
// config={{
|
||||
// displayModeBar: false // this is the line that hides the bar.
|
||||
// }}
|
||||
// />
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue