Skip to content

Commit 9929697

Browse files
authored
Merge pull request #133 from dedis/front-preview-election
Preview election form & fix UI bugs
2 parents 7d5e383 + c693e3c commit 9929697

File tree

11 files changed

+44
-45
lines changed

11 files changed

+44
-45
lines changed

web/frontend/src/components/utils/useConfiguration.tsx

+3-26
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import { useEffect, useState } from 'react';
22
import { Answers, Configuration } from 'types/configuration';
3-
import { emptyConfiguration, newAnswer } from 'types/getObjectType';
4-
import {
5-
unmarshalConfig,
6-
unmarshalConfigAndCreateAnswers,
7-
unmarshalSubjectAndCreateAnswers,
8-
} from 'types/JSONparser';
3+
import { emptyConfiguration } from 'types/getObjectType';
4+
import { unmarshalConfig, unmarshalConfigAndCreateAnswers } from 'types/JSONparser';
95

106
// Returns a Configuration and the initialized Answers
117
const useConfiguration = (configObj: any) => {
@@ -40,23 +36,4 @@ const useConfigurationOnly = (configObj: any) => {
4036
return configuration;
4137
};
4238

43-
// Custom hook to create answers from a Configuration.
44-
const useAnswers = (configuration: Configuration) => {
45-
const [answers, setAnswers] = useState<Answers>(null);
46-
47-
useEffect(() => {
48-
if (configuration !== null) {
49-
const newAnswers: Answers = newAnswer();
50-
51-
for (const subjectObj of configuration.Scaffold) {
52-
unmarshalSubjectAndCreateAnswers(subjectObj, newAnswers);
53-
}
54-
55-
setAnswers(newAnswers);
56-
}
57-
}, [configuration]);
58-
59-
return { answers, setAnswers };
60-
};
61-
62-
export { useConfiguration, useConfigurationOnly, useAnswers };
39+
export { useConfiguration, useConfigurationOnly };

web/frontend/src/language/en.json

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"combineShares": "Combine shares",
7070
"createElec": "Create election",
7171
"clearElec": "Clear election",
72+
"elecName": "Election title",
7273
"confirmRemovesubject": "Do you really want to remove this subject?",
7374
"confirmRemovetext": "Do you really want to remove this text?",
7475
"confirmRemoverank": "Do you really want to remove this rank?",

web/frontend/src/pages/ballot/Show.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ const Ballot: FC = () => {
137137
</h2>
138138
<div className="mt-2 text-sm text-gray-500">{t('voteExplanation')}</div>
139139
</div>
140-
140+
<div className="border-t mt-3" />
141141
<BallotDisplay
142142
configuration={configuration}
143143
answers={answers}

web/frontend/src/pages/ballot/components/BallotDisplay.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const BallotDisplay: FC<BallotDisplayProps> = ({
4040
const SubjectTree = (subject: types.Subject) => {
4141
return (
4242
<div key={subject.ID}>
43-
<h3 className="text-xl pt-1 pb-1 sm:pt-2 sm:pb-2 border-t font-bold text-gray-600">
43+
<h3 className="text-xl break-all pt-1 pb-1 sm:pt-2 sm:pb-2 border-t font-bold text-gray-600">
4444
{subject.Title}
4545
</h3>
4646
{subject.Order.map((id: ID) => (
@@ -61,7 +61,7 @@ const BallotDisplay: FC<BallotDisplayProps> = ({
6161
return (
6262
<DragDropContext onDragEnd={(dropRes) => handleOnDragEnd(dropRes, answers, setAnswers)}>
6363
<div className="w-full mb-0 sm:mb-4 mt-4 sm:mt-6">
64-
<h3 className="py-6 border-t text-2xl text-center text-gray-700">
64+
<h3 className="pb-6 break-all text-2xl text-center text-gray-700">
6565
{configuration.MainTitle}
6666
</h3>
6767
<div className="flex flex-col">

web/frontend/src/pages/ballot/components/Rank.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ const Rank: FC<RankProps> = ({ rank, answers }) => {
7878

7979
return (
8080
<div className="mb-6">
81-
<h3 className="text-lg text-gray-600">{rank.Title}</h3>
81+
<h3 className="text-lg break-words text-gray-600">{rank.Title}</h3>
8282
<div className="mt-5 px-4 max-w-[300px] sm:pl-8 sm:max-w-md">
8383
<>
8484
<Droppable droppableId={String(rank.ID)}>

web/frontend/src/pages/ballot/components/Select.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const Select: FC<SelectProps> = ({ select, answers, setAnswers }) => {
6666
checked={isChecked}
6767
onChange={(e) => handleChecks(e, choiceIndex)}
6868
/>
69-
<label htmlFor={choice} className="pl-2 text-gray-600 cursor-pointer">
69+
<label htmlFor={choice} className="pl-2 break-words text-gray-600 cursor-pointer">
7070
{choice}
7171
</label>
7272
</div>
@@ -75,7 +75,7 @@ const Select: FC<SelectProps> = ({ select, answers, setAnswers }) => {
7575

7676
return (
7777
<div>
78-
<h3 className="text-lg text-gray-600">{select.Title}</h3>
78+
<h3 className="text-lg break-words text-gray-600">{select.Title}</h3>
7979
{hintDisplay()}
8080
<div className="sm:pl-8 pl-6">
8181
{Array.from(answers.SelectAnswers.get(select.ID).entries()).map(

web/frontend/src/pages/ballot/components/Text.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -73,23 +73,23 @@ const Text: FC<TextProps> = ({ text, answers, setAnswers }) => {
7373
const newCount = new Array<number>();
7474
answers.TextAnswers.get(text.ID).map((answer) => newCount.push(answer.length));
7575
setCharCounts(newCount);
76+
// eslint-disable-next-line react-hooks/exhaustive-deps
7677
}, [answers]);
7778

7879
const choiceDisplay = (choice: string, choiceIndex: number) => {
7980
const columns = text.MaxLength > 50 ? 50 : text.MaxLength;
8081
return (
81-
<div className="flex mb-2 " key={choice}>
82-
<label htmlFor={choice} className="text-gray-600 text-md">
83-
{choice == '' ? '' : choice + ': '}
82+
<div className="flex mb-2 md:flex-row flex-col" key={choice}>
83+
<label htmlFor={choice} className="text-gray-600 mr-2 w-24 break-words text-md">
84+
{choice + ': '}
8485
</label>
8586

8687
<textarea
8788
id={choice}
88-
className="mx-2 sm:text-md border rounded-md text-gray-600 "
89+
className="mx-2 w-[50%] sm:text-md resize-none border rounded-md text-gray-600 "
8990
rows={charCounts[choiceIndex] > 0 ? Math.ceil(charCounts[choiceIndex] / columns) : 1}
9091
//rows={text.MaxLength > 0 ? Math.ceil(text.MaxLength / columns) : 1}
9192
cols={columns}
92-
style={{ resize: 'none' }}
9393
onChange={(e) => handleTextInput(e, choiceIndex)}></textarea>
9494
<div className="self-end">{charCountDisplay(choiceIndex)}</div>
9595
</div>
@@ -98,7 +98,7 @@ const Text: FC<TextProps> = ({ text, answers, setAnswers }) => {
9898

9999
return (
100100
<div>
101-
<h3 className="text-lg text-gray-600">{text.Title}</h3>
101+
<h3 className="text-lg break-words text-gray-600">{text.Title}</h3>
102102
{hintDisplay()}
103103
<div className="sm:pl-8 mt-2 pl-6">
104104
{text.Choices.map((choice, index) => choiceDisplay(choice, index))}

web/frontend/src/pages/election/Index.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const ElectionIndex: FC = () => {
1616
const [statusToKeep, setStatusToKeep] = useState<Status>(null);
1717
const [elections, setElections] = useState<LightElectionInfo[]>(null);
1818
const [loading, setLoading] = useState(true);
19+
const [pageIndex, setPageIndex] = useState(0);
1920

2021
const request = {
2122
method: 'GET',
@@ -46,6 +47,7 @@ const ElectionIndex: FC = () => {
4647
(election) => election.Status === statusToKeep
4748
);
4849

50+
setPageIndex(0);
4951
setElections(filteredElections);
5052
}, [data, statusToKeep]);
5153

@@ -68,7 +70,7 @@ const ElectionIndex: FC = () => {
6870
</div>
6971

7072
<ElectionTableFilter setStatusToKeep={setStatusToKeep} />
71-
<ElectionTable elections={elections} />
73+
<ElectionTable pageIndex={pageIndex} setPageIndex={setPageIndex} elections={elections} />
7274
</div>
7375
) : (
7476
<Loading />

web/frontend/src/pages/election/components/ElectionForm.tsx

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FC, Fragment, useState } from 'react';
1+
import { FC, Fragment, useEffect, useState } from 'react';
22
import { useTranslation } from 'react-i18next';
33
import { newElection } from 'components/utils/Endpoints';
44

@@ -17,6 +17,8 @@ import RedirectToModal from 'components/modal/RedirectToModal';
1717
import { CheckIcon, PlusSmIcon } from '@heroicons/react/outline';
1818
import Tabs from './Tabs';
1919
import RemoveElementModal from './RemoveElementModal';
20+
import { useConfiguration } from 'components/utils/useConfiguration';
21+
import BallotDisplay from 'pages/ballot/components/BallotDisplay';
2022

2123
// notifyParent must be used by the child to tell the parent if the subject's
2224
// schema changed.
@@ -40,8 +42,15 @@ const ElectionForm: FC<ElectionFormProps> = () => {
4042
const [subjectIdToRemove, setSubjectIdToRemove] = useState<ID>('');
4143
const [titleChanging, setTitleChanging] = useState<boolean>(true);
4244
const [navigateDestination, setNavigateDestination] = useState(null);
45+
const [marshalledConf, setMarshalledConf] = useState<any>(marshalConfig(conf));
46+
const { configuration: previewConf, answers, setAnswers } = useConfiguration(marshalledConf);
47+
4348
const { MainTitle, Scaffold } = conf;
4449

50+
useEffect(() => {
51+
setMarshalledConf(marshalConfig(conf));
52+
}, [conf]);
53+
4554
async function createHandler() {
4655
const data = {
4756
Configuration: marshalConfig(conf),
@@ -149,7 +158,9 @@ const ElectionForm: FC<ElectionFormProps> = () => {
149158
</>
150159
) : (
151160
<>
152-
<div className="mt-1 ml-3" onClick={() => setTitleChanging(true)}>
161+
<div
162+
className="mt-1 ml-3 w-[90%] break-words"
163+
onClick={() => setTitleChanging(true)}>
153164
{MainTitle}
154165
</div>
155166
<div className="ml-1">
@@ -214,7 +225,14 @@ const ElectionForm: FC<ElectionFormProps> = () => {
214225
return (
215226
<div className="w-screen px-4 md:px-0 mb-4 md:w-auto">
216227
<div className="border rounded-md">
217-
<div className="h-[calc(100vh-265px)] ml-2">preview</div>
228+
<div className="ml-2 w-[95%]">
229+
<BallotDisplay
230+
configuration={previewConf}
231+
answers={answers}
232+
setAnswers={setAnswers}
233+
userErrors=""
234+
/>
235+
</div>
218236
</div>
219237
</div>
220238
);

web/frontend/src/pages/election/components/ElectionRow.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ type ElectionRowProps = {
1111
const ElectionRow: FC<ElectionRowProps> = ({ election }) => {
1212
return (
1313
<tr className="bg-white border-b hover:bg-gray-50 ">
14-
<td scope="row" className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
14+
<td className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
1515
<Link
1616
className="election-link text-gray-700 hover:text-indigo-500"
1717
to={`/elections/${election.ElectionID}`}>

web/frontend/src/pages/election/components/ElectionTable.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ import ElectionRow from './ElectionRow';
66

77
type ElectionTableProps = {
88
elections: LightElectionInfo[];
9+
setPageIndex: (index: number) => void;
10+
pageIndex: number;
911
};
1012

1113
// Returns a table where each line corresponds to an election with
1214
// its name, status and a quickAction if available
1315
const ELECTION_PER_PAGE = 10;
1416

15-
const ElectionTable: FC<ElectionTableProps> = ({ elections }) => {
17+
const ElectionTable: FC<ElectionTableProps> = ({ elections, pageIndex, setPageIndex }) => {
1618
const { t } = useTranslation();
17-
const [pageIndex, setPageIndex] = useState(0);
1819
const [electionsToDisplay, setElectionsToDisplay] = useState<LightElectionInfo[]>([]);
1920

2021
const partitionArray = (array: LightElectionInfo[], size: number) => {

0 commit comments

Comments
 (0)