From 4c2759d8c9c3e12337bd3e5a921fb4db9698a33c Mon Sep 17 00:00:00 2001
From: guhur <12297742+guhur@users.noreply.github.com>
Date: Sun, 16 May 2021 17:15:29 +0200
Subject: [PATCH] fix: api connection (#72)
* fix: api connection
* fix: confirm page with delayed election
* fix: fr translation
---
components/Error.jsx | 65 +++++++++++++++++--------------
components/layouts/Footer.jsx | 2 +-
next-i18next.config.js | 10 ++---
pages/new/confirm/[pid].jsx | 39 ++++++++++++-------
pages/result/[pid]/[[...tid]].jsx | 29 ++++++--------
pages/vote/[pid]/[[...tid]].jsx | 39 ++++++++-----------
pages/vote/[pid]/confirm.jsx | 35 ++++++++++-------
public/locales/de/resource.json | 2 +-
public/locales/en/error.json | 11 ++++++
public/locales/en/resource.json | 2 +-
public/locales/es/resource.json | 2 +-
public/locales/fr/error.json | 11 ++++++
public/locales/fr/resource.json | 4 +-
public/locales/ru/resource.json | 2 +-
services/api.js | 36 ++++++++---------
15 files changed, 158 insertions(+), 131 deletions(-)
create mode 100644 public/locales/en/error.json
create mode 100644 public/locales/fr/error.json
diff --git a/components/Error.jsx b/components/Error.jsx
index 5ece508..dc855db 100644
--- a/components/Error.jsx
+++ b/components/Error.jsx
@@ -1,35 +1,40 @@
-import Link from 'next/link'
-import {Container, Row, Col} from "reactstrap";
-import {useTranslation} from "next-i18next";
+import Link from "next/link";
+import { Container, Row, Col } from "reactstrap";
+import { useTranslation } from "next-i18next";
-
-const Error = props => {
- const {t} = useTranslation();
+const Error = (props) => {
+ const { t } = useTranslation();
return (
-
-
-
-
-
-
-
-
-
-
- {props.value}
-
-
-
-
+
+
-
- { t("common.backHomepage") }
-
+
+
+
-
-
-
-);
-}
+
+
+
+ {props.value}
+
+
+
+
+
+ {t("common.backHomepage")}
+
+
+
+
+ {t("resource.help")}
+
+
+
+
+ );
+};
-export default Error
+export default Error;
diff --git a/components/layouts/Footer.jsx b/components/layouts/Footer.jsx
index 3163ac4..ab22ec0 100644
--- a/components/layouts/Footer.jsx
+++ b/components/layouts/Footer.jsx
@@ -40,7 +40,7 @@ const Footer = () => {
className={bboxLink3.top === bboxLink4.top ? "" : "no-tack"}
>
- {t("Need help?")}
+ {t("resource.help")}
({ ok: true, ...res }),
- (err) => ({ ok: false, err })
- ),
+ let [details, translations] = await Promise.all([
+ getDetails(pid),
serverSideTranslations(locale, [], config),
]);
- if (!res.ok) {
- return { props: { err: res.err, ...translations } };
+ if (details.includes(ELECTION_NOT_STARTED_ERROR)) {
+ details = { title: "", on_invitation_only: true, restrict_results: true };
+ } else {
+ if (typeof details === "string" || details instanceof String) {
+ return { props: { err: details, ...translations } };
+ }
+
+ if (!details.title) {
+ return { props: { err: "Unknown error", ...translations } };
+ }
}
return {
props: {
- invitationOnly: res.on_invitation_only,
- restrictResults: res.restrict_results,
- title: res.title,
+ invitationOnly: details.on_invitation_only,
+ restrictResults: details.restrict_results,
+ title: details.title,
pid: pid,
...translations,
},
@@ -50,12 +59,12 @@ const ConfirmElection = ({
pid,
err,
}) => {
+ const { t } = useTranslation();
+
if (err) {
- return ;
+ return ;
}
- const { t } = useTranslation();
-
const origin =
typeof window !== "undefined" && window.location.origin
? window.location.origin
diff --git a/pages/result/[pid]/[[...tid]].jsx b/pages/result/[pid]/[[...tid]].jsx
index 001c5b1..c206c53 100644
--- a/pages/result/[pid]/[[...tid]].jsx
+++ b/pages/result/[pid]/[[...tid]].jsx
@@ -24,33 +24,28 @@ export async function getServerSideProps({ query, locale }) {
const { pid, tid } = query;
const [res, details, translations] = await Promise.all([
- getResults(
- pid,
- (res) => ({ ok: true, res }),
- (err) => {
- return { ok: false, err: "Unknown error" };
- }
- ),
- getDetails(
- pid,
- (res) => ({ ok: true, ...res }),
- (err) => ({ ok: false, err: "Unknown error" })
- ),
+ getResults(pid),
+ getDetails(pid),
serverSideTranslations(locale, [], config),
]);
- if (!res.ok) {
- return { props: { err: res.err, ...translations } };
+ if (typeof res === "string" || res instanceof String) {
+ return { props: { err: res.slice(1, -1), ...translations } };
}
- if (!details.ok) {
- return { props: { err: details.err, ...translations } };
+
+ if (typeof details === "string" || details instanceof String) {
+ return { props: { err: res.slice(1, -1), ...translations } };
+ }
+
+ if (!details.candidates || !Array.isArray(details.candidates)) {
+ return { props: { err: "Unknown error", ...translations } };
}
return {
props: {
title: details.title,
numGrades: details.num_grades,
- candidates: res.res,
+ candidates: res,
pid: pid,
...translations,
},
diff --git a/pages/vote/[pid]/[[...tid]].jsx b/pages/vote/[pid]/[[...tid]].jsx
index 943f472..ffaaa8f 100644
--- a/pages/vote/[pid]/[[...tid]].jsx
+++ b/pages/vote/[pid]/[[...tid]].jsx
@@ -15,37 +15,29 @@ import config from "../../../next-i18next.config.js";
const shuffle = (array) => array.sort(() => Math.random() - 0.5);
export async function getServerSideProps({ query: { pid, tid }, locale }) {
- const [res, translations] = await Promise.all([
- getDetails(
- pid,
- (res) => {
- console.log("DETAILS:", res);
- return { ok: true, ...res };
- },
- (err) => {
- console.log("ERR:", err);
- return { ok: false, err: "Unknown error" };
- }
- ),
+ const [details, translations] = await Promise.all([
+ getDetails(pid),
serverSideTranslations(locale, [], config),
]);
- if (!res.ok) {
- return { props: { err: res.err, ...translations } };
+ if (typeof details === "string" || details instanceof String) {
+ return { props: { err: details, ...translations } };
}
- console.log(res);
+ if (!details.candidates || !Array.isArray(details.candidates)) {
+ return { props: { err: "Unknown error", ...translations } };
+ }
- shuffle(res.candidates);
+ shuffle(details.candidates);
return {
props: {
...translations,
- invitationOnly: res.on_invitation_only,
- restrictResults: res.restrict_results,
- candidates: res.candidates.map((name, i) => ({ id: i, label: name })),
- title: res.title,
- numGrades: res.num_grades,
+ invitationOnly: details.on_invitation_only,
+ restrictResults: details.restrict_results,
+ candidates: details.candidates.map((name, i) => ({ id: i, label: name })),
+ title: details.title,
+ numGrades: details.num_grades,
pid: pid,
token: tid || null,
},
@@ -53,8 +45,10 @@ export async function getServerSideProps({ query: { pid, tid }, locale }) {
}
const VoteBallot = ({ candidates, title, numGrades, pid, err, token }) => {
+ const { t } = useTranslation();
+
if (err) {
- return ;
+ return ;
}
const [judgments, setJudgments] = useState([]);
@@ -67,7 +61,6 @@ const VoteBallot = ({ candidates, title, numGrades, pid, err, token }) => {
const router = useRouter();
- const { t } = useTranslation();
const allGrades = translateGrades(t);
const grades = allGrades.filter(
(grade) => grade.value >= allGrades.length - numGrades
diff --git a/pages/vote/[pid]/confirm.jsx b/pages/vote/[pid]/confirm.jsx
index a02ac0c..7f1ffc2 100644
--- a/pages/vote/[pid]/confirm.jsx
+++ b/pages/vote/[pid]/confirm.jsx
@@ -5,38 +5,43 @@ import { useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import Paypal from "@components/banner/Paypal";
import Gform from "@components/banner/Gform";
-import { getDetails } from "@services/api";
+import Error from "@components/Error";
+import { getDetails, apiErrors } from "@services/api";
import config from "../../../next-i18next.config.js";
export async function getServerSideProps({ query: { pid }, locale }) {
- const [res, translations] = await Promise.all([
- getDetails(
- pid,
- (res) => ({ ok: true, ...res }),
- (err) => ({ ok: false, err })
- ),
+ const [details, translations] = await Promise.all([
+ getDetails(pid),
serverSideTranslations(locale, [], config),
]);
- if (!res.ok) {
- return { props: { err: res.err, ...translations } };
+ if (typeof details === "string" || details instanceof String) {
+ return { props: { err: res.slice(1, -1), ...translations } };
+ }
+
+ if (!details.candidates || !Array.isArray(details.candidates)) {
+ return { props: { err: "Unknown error", ...translations } };
}
return {
props: {
...translations,
- invitationOnly: res.on_invitation_only,
- restrictResults: res.restrict_results,
- candidates: res.candidates.map((name, i) => ({ id: i, label: name })),
- title: res.title,
- numGrades: res.num_grades,
+ invitationOnly: details.on_invitation_only,
+ restrictResults: details.restrict_results,
+ candidates: details.candidates.map((name, i) => ({ id: i, label: name })),
+ title: details.title,
+ numGrades: details.num_grades,
pid: pid,
},
};
}
-const VoteSuccess = ({ title, invitationOnly, pid }) => {
+const VoteSuccess = ({ title, invitationOnly, pid, err }) => {
const { t } = useTranslation();
+ if (err && err !== "") {
+ return ;
+ }
+
return (
diff --git a/public/locales/de/resource.json b/public/locales/de/resource.json
index 7c958ad..0d53e1a 100644
--- a/public/locales/de/resource.json
+++ b/public/locales/de/resource.json
@@ -6,7 +6,7 @@
"Privacy policy": "Datenschutzerklärung",
"resource.legalNotices": "Rechtliche Hinweise",
"FAQ": "FAQ",
- "Need help?": "Brauchen Sie Hilfe?",
+ "resource.help": "Brauchen Sie Hilfe?",
"BetterVote": " BetterVote",
"Voting platform": "Wahlplattform",
"Majority Judgment": " Mehrheitswahl ",
diff --git a/public/locales/en/error.json b/public/locales/en/error.json
new file mode 100644
index 0000000..0ef4f28
--- /dev/null
+++ b/public/locales/en/error.json
@@ -0,0 +1,11 @@
+{
+ "error.e1": "Oops... The election is unknown",
+ "error.e2": "The election is still going on. You can't access now to the results.",
+ "error.e3": "No votes have been recorded yet. Come back later.",
+ "error.e4": "The election has not started yet.",
+ "error.e5": "The election is over. You can't vote anymore",
+ "error.e6": "You need a token to vote in this election",
+ "error.e7": "You seem to have already voted.",
+ "error.e8": "The parameters of the election are incorrect.",
+ "error.catch22": "Unknown error"
+}
diff --git a/public/locales/en/resource.json b/public/locales/en/resource.json
index 4502c91..2fef84f 100644
--- a/public/locales/en/resource.json
+++ b/public/locales/en/resource.json
@@ -6,7 +6,7 @@
"Privacy policy": "Privacy policy",
"resource.legalNotices": "Legal notices",
"FAQ": "FAQ",
- "Need help?": "Need help?",
+ "resource.help": "Need help?",
"BetterVote": "BetterVote",
"Voting platform": "Voting platform",
"Majority Judgment": "Majority Judgment",
diff --git a/public/locales/es/resource.json b/public/locales/es/resource.json
index db133b3..610f24d 100644
--- a/public/locales/es/resource.json
+++ b/public/locales/es/resource.json
@@ -6,7 +6,7 @@
"Privacy policy": "Política de privacidad",
"resource.legalNotices": "Avisos legales",
"FAQ": "FAQ",
- "Need help?": "¿Necesitas ayuda?",
+ "resource.help": "¿Necesitas ayuda?",
"BetterVote": "VotarMejor",
"Voting platform": "Plataforma de votación",
"Majority Judgment": "Juicio Mayoritario",
diff --git a/public/locales/fr/error.json b/public/locales/fr/error.json
new file mode 100644
index 0000000..1932725
--- /dev/null
+++ b/public/locales/fr/error.json
@@ -0,0 +1,11 @@
+{
+ "error.e1": "Impossible de retrouver le vote en question",
+ "error.e2": "L'élection est encore en cours. Revenez plus tard.",
+ "error.e3": "Aucun vote n'a encore été enregistré. Revenez plus tard.",
+ "error.e4": "L'élection n'a pas encore démarrée.",
+ "error.e5": "L'élection est terminée. Vous ne pouvez plus voter.",
+ "error.e6": "Vous avez besoin d'un jeton pour participer à cette élection.",
+ "error.e7": "Vous avez déjà voté pour cette élection.",
+ "error.e8": "Les paramètres de l'élection sont inconnues.",
+ "error.catch22": "Erreur inconnue."
+}
diff --git a/public/locales/fr/resource.json b/public/locales/fr/resource.json
index 31adea2..b8abf2b 100644
--- a/public/locales/fr/resource.json
+++ b/public/locales/fr/resource.json
@@ -6,7 +6,7 @@
"Privacy policy": "Politique de confidentialité",
"resource.legalNotices": "Mentions légales",
"FAQ": "FAQ",
- "Need help?": "Besoin d'aide ?",
+ "resource.help": "Besoin d'aide ?",
"BetterVote": "MieuxVoter",
"Voting platform": "Plateforme de vote",
"Majority Judgment": "Jugement Majoritaire",
@@ -15,7 +15,7 @@
"Delete?": "Supprimer ?",
"Are you sure to delete": "Êtes-vous sûr(e) de supprimer",
"the row": "la ligne",
- "resource.writeQuestion": "Décrire ici votre question ou introduire simplement votre vote (250 caractères max.)",
+ "resource.writeQuestionHere": "Décrire ici votre question ou introduire simplement votre vote (250 caractères max.)",
"Enter the name of your candidate or proposal here (250 characters max.)": "Saisissez ici le nom de votre candidat ou de votre proposition (250 caractères max.)",
"Please add at least 2 candidates.": "Merci d'ajouter au moins 2 candidats.",
"resource.questionLabel": "Question de votre vote",
diff --git a/public/locales/ru/resource.json b/public/locales/ru/resource.json
index 26de7e8..785664d 100644
--- a/public/locales/ru/resource.json
+++ b/public/locales/ru/resource.json
@@ -6,7 +6,7 @@
"Privacy policy": "Политика конфиденциальности",
"resource.legalNotices": "Официальные уведомления",
"FAQ": "Часто задаваемые вопросы",
- "Need help?": "Нужна помощь?",
+ "resource.help": "Нужна помощь?",
"BetterVote": "BetterVote",
"Voting platform": "Платформа голосования",
"Majority Judgment": "Решение Большинства",
diff --git a/services/api.js b/services/api.js
index 5939a14..bb5489c 100644
--- a/services/api.js
+++ b/services/api.js
@@ -16,7 +16,7 @@ const sendInviteMail = (res) => {
/**
* Send an invitation mail using a micro-service with Netlify
*/
- const { title, mails, tokens, locale } = res;
+ const { id, title, mails, tokens, locale } = res;
if (!mails || !mails.length) {
throw new Error("No emails are provided.");
@@ -30,14 +30,14 @@ const sendInviteMail = (res) => {
typeof window !== "undefined" && window.location.origin
? window.location.origin
: "http://localhost";
- const urlVote = (pid) => new URL(`/vote/${pid}`, origin);
+ const urlVote = (pid, token) => new URL(`/vote/${pid}/${token}`, origin);
const urlResult = (pid) => new URL(`/result/${pid}`, origin);
const recipientVariables = {};
tokens.forEach((token, index) => {
recipientVariables[mails[index]] = {
- urlVote: urlVote(token),
- urlResult: urlResult(token),
+ urlVote: urlVote(id, token),
+ urlResult: urlResult(id),
};
});
@@ -146,15 +146,13 @@ const getDetails = (pid, successCallback, failureCallback) => {
return fetch(detailsEndpoint.href)
.then((response) => {
if (!response.ok) {
- console.log("NOK", response);
return Promise.reject(response.text());
}
- const res = response.json();
- console.log("OK", res);
- return res;
+ return response.json();
})
.then(successCallback || ((res) => res))
- .catch(failureCallback || ((err) => err));
+ .catch(failureCallback || ((err) => err))
+ .then((res) => res);
};
const castBallot = (judgments, pid, token, callbackSuccess, callbackError) => {
@@ -193,30 +191,30 @@ export const WRONG_ELECTION_ERROR = "E9:";
export const apiErrors = (error, t) => {
if (error.includes(UNKNOWN_ELECTION_ERROR)) {
- return t("Oops... The election is unknown.");
+ return t("error.e1");
}
if (error.includes(ONGOING_ELECTION_ERROR)) {
- return t(
- "The election is still going on. You can't access now to the results."
- );
+ return t("error.e2");
}
if (error.includes(NO_VOTE_ERROR)) {
- return t("No votes have been recorded yet. Come back later.");
+ return t("error.e3");
}
if (error.includes(ELECTION_NOT_STARTED_ERROR)) {
- return t("The election has not started yet.");
+ return t("error.e4");
}
if (error.includes(ELECTION_FINISHED_ERROR)) {
- return t("The election is over. You can't vote anymore");
+ return t("error.e5");
}
if (error.includes(INVITATION_ONLY_ERROR)) {
- return t("You need a token to vote in this election");
+ return t("error.e6");
}
if (error.includes(USED_TOKEN_ERROR)) {
- return t("You seem to have already voted.");
+ return t("error.e7");
}
if (error.includes(WRONG_ELECTION_ERROR)) {
- return t("The parameters of the election are incorrect.");
+ return t("error.e8");
+ } else {
+ return t("error.catch22");
}
};