From 3f5e940ecc46bfa55bc1feb5d78ec336f98babe1 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Thu, 9 Nov 2023 13:26:01 +0100 Subject: [PATCH 1/4] fix(web): some code smells --- src/bootstrap/dataloader.js | 14 ++--- src/components/case-card.js | 4 +- src/components/case-details-card.jsx | 83 +++++++++++-------------- src/components/case-round-history.js | 2 +- src/components/evidence-timeline.js | 19 +++--- src/components/notification-settings.js | 25 ++++---- 6 files changed, 68 insertions(+), 79 deletions(-) diff --git a/src/bootstrap/dataloader.js b/src/bootstrap/dataloader.js index 435496d..d0fc4ff 100644 --- a/src/bootstrap/dataloader.js +++ b/src/bootstrap/dataloader.js @@ -7,12 +7,7 @@ import { displaySubgraph } from "./subgraph"; const getURIProtocol = (uri) => { const uriParts = uri.replace(":", "").split("/"); - switch (uri.substr(0, 1)) { - case "/": - return uriParts[1]; - default: - return uriParts[0]; - } + return uri.startsWith("/") ? uriParts[1] : uriParts[0]; }; const getHttpUri = (uri) => { @@ -169,13 +164,14 @@ const funcs = { } }, async loadPolicy(URI) { - URI = `https://ipfs.kleros.io${URI.startsWith("/ipfs/") ? URI : `/ipfs/${URI}`}`; + const prefix = URI.startsWith("/ipfs/") ? "" : "/ipfs/"; + const policyURL = `https://ipfs.kleros.io${prefix}${URI}`; try { - const res = await axios.get(URI); + const res = await axios.get(policyURL); if (res.status !== 200) - throw new Error(`HTTP Error: Unable to fetch file at ${URI}. Returned status code ${res.status}`); + throw new Error(`HTTP Error: Unable to fetch file at ${policyURL}. Returned status code ${res.status}`); return res.data; } catch { diff --git a/src/components/case-card.js b/src/components/case-card.js index a82f851..1889967 100644 --- a/src/components/case-card.js +++ b/src/components/case-card.js @@ -213,12 +213,12 @@ const CaseCard = ({ ID, draws }) => { title={ <> - {metaEvidence && metaEvidence.category} + {metaEvidence?.category} } >
- {metaEvidence && metaEvidence.title} + {metaEvidence?.title} diff --git a/src/components/case-details-card.jsx b/src/components/case-details-card.jsx index 4519aa7..c68afb2 100644 --- a/src/components/case-details-card.jsx +++ b/src/components/case-details-card.jsx @@ -36,6 +36,22 @@ const JustificationBox = ({ onChange, justification }) => { return ; }; +const getVotingStatus = (disputePeriod, votesData, hiddenVotes) => { + if (disputePeriod === "0") { + return "Waiting for evidence."; + } else if (disputePeriod === "1") { + return !votesData.committed + ? "You did not commit your vote yet." + : "You committed your vote. You will be able to reveal your vote when the period ends."; + } else if (hiddenVotes) { + return votesData.committed + ? "You did not reveal your vote yet." + : "You did not commit a vote in the previous period. You cannot vote anymore."; + } else { + return "You did not cast a vote."; + } +}; + export default function CaseDetailsCard({ ID }) { const { drizzle, useCacheCall, useCacheSend } = useDrizzle(); const drizzleState = useDrizzleState((drizzleState) => ({ @@ -220,11 +236,9 @@ export default function CaseDetailsCard({ ID }) { let choice; const typeSwitch = id !== "0" && - !Object.keys( - metaEvidence.rulingOptions && metaEvidence.rulingOptions.reserved ? metaEvidence.rulingOptions.reserved : {} - ).includes(id) && - metaEvidence.rulingOptions && - metaEvidence.rulingOptions.type; + !Object.keys(metaEvidence.rulingOptions?.reserved ?? {}).includes(id) && + metaEvidence.rulingOptions?.type; + switch (typeSwitch) { case "multiple-select": choice = metaEvidence.rulingOptions.titles @@ -389,24 +403,8 @@ export default function CaseDetailsCard({ ID }) { Waiting for the vote result. ) : null} - ) : dispute.period === "0" ? ( - "Waiting for evidence." - ) : dispute.period === "1" ? ( - !votesData.committed ? ( - "You did not commit your vote yet." - ) : ( - - You committed your vote. You will be able to reveal your vote when the period ends. - - ) - ) : subcourts[subcourts.length - 1].hiddenVotes ? ( - votesData.committed ? ( - "You did not reveal your vote yet." - ) : ( - "You did not commit a vote in the previous period. You cannot vote anymore." - ) ) : ( - "You did not cast a vote." + getVotingStatus(dispute.period, votesData, subcourts[subcourts.length - 1].hiddenVotes) )} ) : ( @@ -490,9 +488,7 @@ export default function CaseDetailsCard({ ID }) { disabled={!votesData.canVote} name="ruling" onChange={setComplexRuling} - options={ - metaEvidence.rulingOptions.titles && metaEvidence.rulingOptions.titles.slice(0, 255) - } + options={metaEvidence.rulingOptions.titles?.slice(0, 255)} value={complexRuling} />
@@ -532,8 +528,7 @@ export default function CaseDetailsCard({ ID }) { )} {metaEvidence.rulingOptions.type === "single-select" ? ( - metaEvidence.rulingOptions.titles && - metaEvidence.rulingOptions.titles.slice(0, 2 ** 256 - 1).map((t, i) => ( + metaEvidence.rulingOptions.titles?.slice(0, 2 ** 256 - 1).map((t, i) => ( - {metaEvidence.rulingOptions && - metaEvidence.rulingOptions.reserved && - Object.entries(metaEvidence.rulingOptions.reserved).map(([ruling, title]) => ( -
- {Number(dispute.period) < "3" && !votesData.voted ? ( - - ) : null} -
- ))} + {Object.entries(metaEvidence.rulingOptions?.reserved ?? {}).map(([ruling, title]) => ( +
+ {Number(dispute.period) < "3" && !votesData.voted ? ( + + ) : null} +
+ ))} ) : ( @@ -609,7 +602,7 @@ export default function CaseDetailsCard({ ID }) { loading={!metaEvidence} title={ <> - {metaEvidence && metaEvidence.title} + {metaEvidence?.title} {subcourts && s.name)} />} } diff --git a/src/components/case-round-history.js b/src/components/case-round-history.js index 4ccc286..1c06b1a 100644 --- a/src/components/case-round-history.js +++ b/src/components/case-round-history.js @@ -43,7 +43,7 @@ export default function CaseRoundHistory({ ID, dispute, ruling }) { return justs.reduce( (acc, j) => { const vote = call("KlerosLiquid", "getVote", ID, i, j.voteID); - if (vote && vote.voted) acc[acc.length > vote.choice ? vote.choice : acc.length - 1].push(j.justification); + if (vote?.voted) acc[acc.length > vote.choice ? vote.choice : acc.length - 1].push(j.justification); return acc; }, [...new Array(2 + (metaEvidence.rulingOptions?.titles?.length || 0))].map(() => []) diff --git a/src/components/evidence-timeline.js b/src/components/evidence-timeline.js index 51ccbd6..9323b19 100644 --- a/src/components/evidence-timeline.js +++ b/src/components/evidence-timeline.js @@ -44,6 +44,15 @@ const StyledEvidenceTimelineArea = styled.div` padding: 35px 10%; `; +const getRulingText = (ruling, metaEvidence) => { + if (!ruling) { + return "Jurors refused to make a ruling"; + } + const rulingIndex = Number(ruling) - 1; + const rulingTitle = metaEvidence.rulingOptions?.titles?.[rulingIndex]; + return `Jurors ruled: ${rulingTitle || ruling}`; +}; + // eslint-disable-next-line react/prop-types const EvidenceTimeline = ({ evidence = [], metaEvidence = {}, ruling = null, chainId = 1 }) => { // Sort so most recent is first @@ -61,15 +70,7 @@ const EvidenceTimeline = ({ evidence = [], metaEvidence = {}, ruling = null, cha Latest - {ruling && ( - - {ruling - ? `Jurors ruled: ${ - metaEvidence.rulingOptions ? metaEvidence.rulingOptions.titles[Number(ruling) - 1] : ruling - }` - : "Jurors refused to make a ruling"} - - )} + {ruling && {getRulingText(ruling, metaEvidence)}} ({ ...acc, [`${key}NotificationSetting${`${v[0].toUpperCase()}${v.slice(1)}`}`]: true }), - {} - ), + ...Object.keys(settings).reduce((acc, setting) => { + const settingKey = `${key}NotificationSetting${setting.charAt(0).toUpperCase() + setting.slice(1)}`; + acc[settingKey] = true; + return acc; + }, {}), }, }), { errorRetryCount: 0, revalidateOnFocus: false } @@ -78,15 +79,13 @@ const NotificationSettings = Form.create()(({ form, settings: { key, ...settings pushNotificationsData: { S: pushNotificationsData ? JSON.stringify(pushNotificationsData) : " ", }, - ...Object.keys(rest).reduce( - (acc, v) => ({ - ...acc, - [`${key}NotificationSetting${`${v[0].toUpperCase()}${v.slice(1)}`}`]: { - BOOL: rest[v] || false, - }, - }), - {} - ), + ...Object.keys(rest).reduce((acc, setting) => { + const settingKey = `${key}NotificationSetting${setting + .charAt(0) + .toUpperCase()}${setting.slice(1)}`; + acc[settingKey] = { BOOL: rest[setting] || false }; + return acc; + }, {}), }, }) ); From 5978074d7d9cfc57c3adaba6a03bcd6e4ed41d2d Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Thu, 9 Nov 2023 16:53:06 +0100 Subject: [PATCH 2/4] fix(web): code smell in return statements --- src/bootstrap/dataloader.js | 4 + src/components/case-details-card.jsx | 203 ++++++++++++++++----------- 2 files changed, 124 insertions(+), 83 deletions(-) diff --git a/src/bootstrap/dataloader.js b/src/bootstrap/dataloader.js index d0fc4ff..0ef52e3 100644 --- a/src/bootstrap/dataloader.js +++ b/src/bootstrap/dataloader.js @@ -164,6 +164,10 @@ const funcs = { } }, async loadPolicy(URI) { + if (!URI) { + console.error("No URI provided"); + return; + } const prefix = URI.startsWith("/ipfs/") ? "" : "/ipfs/"; const policyURL = `https://ipfs.kleros.io${prefix}${URI}`; diff --git a/src/components/case-details-card.jsx b/src/components/case-details-card.jsx index c68afb2..98c328c 100644 --- a/src/components/case-details-card.jsx +++ b/src/components/case-details-card.jsx @@ -52,6 +52,102 @@ const getVotingStatus = (disputePeriod, votesData, hiddenVotes) => { } }; +const VoteOptions = ({ metaEvidence, votesData, complexRuling, setComplexRuling, onVoteClick, disabledDate }) => { + const isSingleSelect = metaEvidence.rulingOptions.type === "single-select"; + const isMultipleSelect = metaEvidence.rulingOptions.type === "multiple-select"; + const isDateTime = metaEvidence.rulingOptions.type === "datetime"; + + let inputComponent; + + if (isMultipleSelect) { + inputComponent = ( +
+ +
+ ); + } else if (isDateTime) { + inputComponent = ( + + ); + } else if (isSingleSelect) { + inputComponent = metaEvidence.rulingOptions.titles?.slice(0, 2 ** 256 - 1).map((title, index) => ( + + {title} + + )); + } else { + inputComponent = ( + + ); + } + + return ( + + {inputComponent} + {!isSingleSelect && ( + + Submit + + )} + + ); +}; + +const RevealVoteButton = ({ onRevealClick, votesData, dispute }) => { + return ( + + + Reveal Vote + + + ); +}; + export default function CaseDetailsCard({ ID }) { const { drizzle, useCacheCall, useCacheSend } = useDrizzle(); const drizzleState = useDrizzleState((drizzleState) => ({ @@ -468,90 +564,16 @@ export default function CaseDetailsCard({ ID }) { )} {Number(dispute.period) < 3 && !votesData.voted && metaEvidence.rulingOptions ? ( votesData.committed && committedVote !== undefined ? ( - - - Reveal Vote - - + ) : ( - <> - {metaEvidence.rulingOptions.type !== "single-select" && ( - - {metaEvidence.rulingOptions.type === "multiple-select" ? ( -
- -
- ) : metaEvidence.rulingOptions.type === "datetime" ? ( - - ) : ( - - )} -
- )} - - {metaEvidence.rulingOptions.type === "single-select" ? ( - metaEvidence.rulingOptions.titles?.slice(0, 2 ** 256 - 1).map((t, i) => ( - - {t} - - )) - ) : ( - - Submit - - )} - - + ) ) : null} @@ -763,6 +785,21 @@ CaseDetailsCard.propTypes = { ID: PropTypes.string.isRequired, }; +VoteOptions.propTypes = { + disabledDate: PropTypes.func, + metaEvidence: PropTypes.object, + votesData: PropTypes.object, + onVoteClick: PropTypes.func, + setComplexRuling: PropTypes.func, + complexRuling: PropTypes.any, +}; + +RevealVoteButton.propTypes = { + dispute: PropTypes.object, + onRevealClick: PropTypes.func, + votesData: PropTypes.object, +}; + JustificationBox.propTypes = { onChange: PropTypes.func, justification: PropTypes.string, From baf5e40658328a389ff85f4d1e4a0ea1d4407c4b Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Fri, 10 Nov 2023 13:32:59 +0100 Subject: [PATCH 3/4] fix(web): changes requested --- src/components/case-details-card.jsx | 2 +- src/components/notification-settings.js | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/components/case-details-card.jsx b/src/components/case-details-card.jsx index 98c328c..fa68236 100644 --- a/src/components/case-details-card.jsx +++ b/src/components/case-details-card.jsx @@ -124,7 +124,7 @@ const VoteOptions = ({ metaEvidence, votesData, complexRuling, setComplexRuling, return ( {inputComponent} - {!isSingleSelect && ( + {isSingleSelect ? null : ( Submit diff --git a/src/components/notification-settings.js b/src/components/notification-settings.js index b0ac24b..a38cb5b 100644 --- a/src/components/notification-settings.js +++ b/src/components/notification-settings.js @@ -19,6 +19,14 @@ const StyledMail = styled(Mail)` min-width: 16px; `; +const configureNotificationSettings = (settings, key, isSubmitting) => { + return Object.keys(settings).reduce((acc, setting) => { + const settingKey = `${key}NotificationSetting${setting.charAt(0).toUpperCase() + setting.slice(1)}`; + acc[settingKey] = isSubmitting ? { BOOL: settings[setting] || false } : true; + return acc; + }, {}); +}; + const NotificationSettings = Form.create()(({ form, settings: { key, ...settings } }) => { const { drizzle } = useDrizzle(); const drizzleState = useDrizzleState((drizzleState) => ({ @@ -38,11 +46,7 @@ const NotificationSettings = Form.create()(({ form, settings: { key, ...settings fullName: true, phone: true, pushNotifications: true, - ...Object.keys(settings).reduce((acc, setting) => { - const settingKey = `${key}NotificationSetting${setting.charAt(0).toUpperCase() + setting.slice(1)}`; - acc[settingKey] = true; - return acc; - }, {}), + ...configureNotificationSettings(settings, key, false), }, }), { errorRetryCount: 0, revalidateOnFocus: false } @@ -79,13 +83,7 @@ const NotificationSettings = Form.create()(({ form, settings: { key, ...settings pushNotificationsData: { S: pushNotificationsData ? JSON.stringify(pushNotificationsData) : " ", }, - ...Object.keys(rest).reduce((acc, setting) => { - const settingKey = `${key}NotificationSetting${setting - .charAt(0) - .toUpperCase()}${setting.slice(1)}`; - acc[settingKey] = { BOOL: rest[setting] || false }; - return acc; - }, {}), + ...configureNotificationSettings(rest, key, true), }, }) ); From 7fd3aaf1276782e8a078bd3920cce1a412b946b2 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Fri, 10 Nov 2023 14:09:49 +0100 Subject: [PATCH 4/4] feat(web): a bit more abstraction, clearer code --- src/components/notification-settings.js | 60 +++++++++++++++++-------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/components/notification-settings.js b/src/components/notification-settings.js index a38cb5b..1a75ebd 100644 --- a/src/components/notification-settings.js +++ b/src/components/notification-settings.js @@ -19,7 +19,7 @@ const StyledMail = styled(Mail)` min-width: 16px; `; -const configureNotificationSettings = (settings, key, isSubmitting) => { +const configureRestOfSettings = (settings, key, isSubmitting) => { return Object.keys(settings).reduce((acc, setting) => { const settingKey = `${key}NotificationSetting${setting.charAt(0).toUpperCase() + setting.slice(1)}`; acc[settingKey] = isSubmitting ? { BOOL: settings[setting] || false } : true; @@ -27,6 +27,36 @@ const configureNotificationSettings = (settings, key, isSubmitting) => { }, {}); }; +const prepareSettings = ( + dynamicSettings, + key, + isSubmitting, + email, + fullName, + phone, + pushNotifications, + pushNotificationsData +) => { + return isSubmitting + ? { + email: { S: email }, + fullName: { S: fullName }, + phone: { S: phone || " " }, + pushNotifications: { BOOL: pushNotifications || false }, + pushNotificationsData: { + S: pushNotificationsData ? JSON.stringify(pushNotificationsData) : " ", + }, + ...configureRestOfSettings(dynamicSettings, key, true), + } + : { + email: true, + fullName: true, + phone: true, + pushNotifications: true, + ...configureRestOfSettings(dynamicSettings, key, false), + }; +}; + const NotificationSettings = Form.create()(({ form, settings: { key, ...settings } }) => { const { drizzle } = useDrizzle(); const drizzleState = useDrizzleState((drizzleState) => ({ @@ -41,13 +71,7 @@ const NotificationSettings = Form.create()(({ form, settings: { key, ...settings await accessSettings({ web3: drizzle.web3, address, - settings: { - email: true, - fullName: true, - phone: true, - pushNotifications: true, - ...configureNotificationSettings(settings, key, false), - }, + settings: prepareSettings(settings, key, false), }), { errorRetryCount: 0, revalidateOnFocus: false } ); @@ -75,16 +99,16 @@ const NotificationSettings = Form.create()(({ form, settings: { key, ...settings patch: true, web3: drizzle.web3, address: drizzleState.account, - settings: { - email: { S: email }, - fullName: { S: fullName }, - phone: { S: phone || " " }, - pushNotifications: { BOOL: pushNotifications || false }, - pushNotificationsData: { - S: pushNotificationsData ? JSON.stringify(pushNotificationsData) : " ", - }, - ...configureNotificationSettings(rest, key, true), - }, + settings: prepareSettings( + rest, + key, + true, + email, + fullName, + phone, + pushNotifications, + pushNotificationsData + ), }) ); } catch (err) {