Skip to content

Commit 1fdb2e3

Browse files
authored
Merge pull request #983 from kleros/feat(web)/improve-voting-logic
Feat(web): use round index when voting
2 parents cacabbb + d77cdcf commit 1fdb2e3

File tree

12 files changed

+91
-34
lines changed

12 files changed

+91
-34
lines changed

web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
},
6161
"dependencies": {
6262
"@kleros/kleros-v2-contracts": "workspace:^",
63-
"@kleros/ui-components-library": "^1.9.2",
63+
"@kleros/ui-components-library": "^2.5.2",
6464
"@sentry/react": "^7.55.2",
6565
"@sentry/tracing": "^7.55.2",
6666
"@types/react-modal": "^3.16.0",

web/src/graphql/gql.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ const documents = {
2323
types.CourtPolicyUriDocument,
2424
'\n query CourtTree {\n court(id: "1") {\n name\n id\n children(orderBy: name) {\n name\n id\n children {\n name\n id\n children {\n name\n id\n children {\n name\n id\n children {\n name\n id\n }\n }\n }\n }\n }\n }\n }\n':
2525
types.CourtTreeDocument,
26-
"\n query DisputeDetails($disputeID: ID!) {\n dispute(id: $disputeID) {\n court {\n id\n timesPerPeriod\n hiddenVotes\n feeForJuror\n }\n arbitrated {\n id\n }\n period\n ruled\n lastPeriodChange\n }\n }\n":
26+
"\n query DisputeDetails($disputeID: ID!) {\n dispute(id: $disputeID) {\n court {\n id\n timesPerPeriod\n hiddenVotes\n feeForJuror\n }\n arbitrated {\n id\n }\n period\n ruled\n lastPeriodChange\n currentRound {\n id\n }\n currentRoundIndex\n }\n }\n":
2727
types.DisputeDetailsDocument,
28-
"\n query Draw($address: String, $disputeID: String) {\n draws(where: { dispute: $disputeID, juror: $address }) {\n voteID\n }\n }\n":
28+
"\n query Draw($address: String, $disputeID: String, $roundID: String) {\n draws(where: { dispute: $disputeID, juror: $address, round: $roundID }) {\n voteID\n }\n }\n":
2929
types.DrawDocument,
3030
"\n query Evidences($evidenceGroup: String) {\n evidences(where: { evidenceGroup: $evidenceGroup }, orderBy: id, orderDirection: asc) {\n id\n evidence\n sender {\n id\n }\n }\n }\n":
3131
types.EvidencesDocument,
@@ -83,14 +83,14 @@ export function graphql(
8383
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
8484
*/
8585
export function graphql(
86-
source: "\n query DisputeDetails($disputeID: ID!) {\n dispute(id: $disputeID) {\n court {\n id\n timesPerPeriod\n hiddenVotes\n feeForJuror\n }\n arbitrated {\n id\n }\n period\n ruled\n lastPeriodChange\n }\n }\n"
87-
): (typeof documents)["\n query DisputeDetails($disputeID: ID!) {\n dispute(id: $disputeID) {\n court {\n id\n timesPerPeriod\n hiddenVotes\n feeForJuror\n }\n arbitrated {\n id\n }\n period\n ruled\n lastPeriodChange\n }\n }\n"];
86+
source: "\n query DisputeDetails($disputeID: ID!) {\n dispute(id: $disputeID) {\n court {\n id\n timesPerPeriod\n hiddenVotes\n feeForJuror\n }\n arbitrated {\n id\n }\n period\n ruled\n lastPeriodChange\n currentRound {\n id\n }\n currentRoundIndex\n }\n }\n"
87+
): (typeof documents)["\n query DisputeDetails($disputeID: ID!) {\n dispute(id: $disputeID) {\n court {\n id\n timesPerPeriod\n hiddenVotes\n feeForJuror\n }\n arbitrated {\n id\n }\n period\n ruled\n lastPeriodChange\n currentRound {\n id\n }\n currentRoundIndex\n }\n }\n"];
8888
/**
8989
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
9090
*/
9191
export function graphql(
92-
source: "\n query Draw($address: String, $disputeID: String) {\n draws(where: { dispute: $disputeID, juror: $address }) {\n voteID\n }\n }\n"
93-
): (typeof documents)["\n query Draw($address: String, $disputeID: String) {\n draws(where: { dispute: $disputeID, juror: $address }) {\n voteID\n }\n }\n"];
92+
source: "\n query Draw($address: String, $disputeID: String, $roundID: String) {\n draws(where: { dispute: $disputeID, juror: $address, round: $roundID }) {\n voteID\n }\n }\n"
93+
): (typeof documents)["\n query Draw($address: String, $disputeID: String, $roundID: String) {\n draws(where: { dispute: $disputeID, juror: $address, round: $roundID }) {\n voteID\n }\n }\n"];
9494
/**
9595
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
9696
*/

web/src/graphql/graphql.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3661,14 +3661,17 @@ export type DisputeDetailsQuery = {
36613661
period: Period;
36623662
ruled: boolean;
36633663
lastPeriodChange: any;
3664+
currentRoundIndex: any;
36643665
court: { __typename?: "Court"; id: string; timesPerPeriod: Array<any>; hiddenVotes: boolean; feeForJuror: any };
36653666
arbitrated: { __typename?: "Arbitrable"; id: string };
3667+
currentRound: { __typename?: "Round"; id: string };
36663668
} | null;
36673669
};
36683670

36693671
export type DrawQueryVariables = Exact<{
36703672
address?: InputMaybe<Scalars["String"]["input"]>;
36713673
disputeID?: InputMaybe<Scalars["String"]["input"]>;
3674+
roundID?: InputMaybe<Scalars["String"]["input"]>;
36723675
}>;
36733676

36743677
export type DrawQuery = { __typename?: "Query"; draws: Array<{ __typename?: "Draw"; voteID: any }> };
@@ -4142,6 +4145,15 @@ export const DisputeDetailsDocument = {
41424145
{ kind: "Field", name: { kind: "Name", value: "period" } },
41434146
{ kind: "Field", name: { kind: "Name", value: "ruled" } },
41444147
{ kind: "Field", name: { kind: "Name", value: "lastPeriodChange" } },
4148+
{
4149+
kind: "Field",
4150+
name: { kind: "Name", value: "currentRound" },
4151+
selectionSet: {
4152+
kind: "SelectionSet",
4153+
selections: [{ kind: "Field", name: { kind: "Name", value: "id" } }],
4154+
},
4155+
},
4156+
{ kind: "Field", name: { kind: "Name", value: "currentRoundIndex" } },
41454157
],
41464158
},
41474159
},
@@ -4168,6 +4180,11 @@ export const DrawDocument = {
41684180
variable: { kind: "Variable", name: { kind: "Name", value: "disputeID" } },
41694181
type: { kind: "NamedType", name: { kind: "Name", value: "String" } },
41704182
},
4183+
{
4184+
kind: "VariableDefinition",
4185+
variable: { kind: "Variable", name: { kind: "Name", value: "roundID" } },
4186+
type: { kind: "NamedType", name: { kind: "Name", value: "String" } },
4187+
},
41714188
],
41724189
selectionSet: {
41734190
kind: "SelectionSet",
@@ -4192,6 +4209,11 @@ export const DrawDocument = {
41924209
name: { kind: "Name", value: "juror" },
41934210
value: { kind: "Variable", name: { kind: "Name", value: "address" } },
41944211
},
4212+
{
4213+
kind: "ObjectField",
4214+
name: { kind: "Name", value: "round" },
4215+
value: { kind: "Variable", name: { kind: "Name", value: "roundID" } },
4216+
},
41954217
],
41964218
},
41974219
},

web/src/hooks/queries/useDisputeDetailsQuery.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ const disputeDetailsQuery = graphql(`
1818
period
1919
ruled
2020
lastPeriodChange
21+
currentRound {
22+
id
23+
}
24+
currentRoundIndex
2125
}
2226
}
2327
`);

web/src/hooks/queries/useDisputeTemplate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import useSWRImmutable from "swr/immutable";
22
import { usePublicClient } from "wagmi";
33
import { getIArbitrableV2 } from "hooks/contracts/generated";
44

5-
export const useDisputeTemplate = (disputeID?: string, arbitrableAddress?: `0x{string}`) => {
5+
export const useDisputeTemplate = (disputeID?: string, arbitrableAddress?: `0x${string}`) => {
66
const publicClient = usePublicClient();
77
return useSWRImmutable(
88
() => (arbitrableAddress ? `DisputeTemplate${disputeID}${arbitrableAddress}` : false),

web/src/hooks/queries/useDrawQuery.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ import { DrawQuery } from "src/graphql/graphql";
44
export type { DrawQuery };
55

66
const drawQuery = graphql(`
7-
query Draw($address: String, $disputeID: String) {
8-
draws(where: { dispute: $disputeID, juror: $address }) {
7+
query Draw($address: String, $disputeID: String, $roundID: String) {
8+
draws(where: { dispute: $disputeID, juror: $address, round: $roundID }) {
99
voteID
1010
}
1111
}
1212
`);
1313

14-
export const useDrawQuery = (address?: string | null, disputeID?: string) => {
14+
export const useDrawQuery = (address?: string | null, disputeID?: string, roundID?: string) => {
1515
return useSWR<DrawQuery>({
1616
query: drawQuery,
17-
variables: { address, disputeID },
17+
variables: { address, disputeID, roundID },
1818
});
1919
};

web/src/pages/Cases/CaseDetails/Voting/Binary.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import React, { useMemo, useState } from "react";
22
import styled from "styled-components";
33
import { useParams } from "react-router-dom";
4+
import { useWalletClient } from "wagmi";
45
import { Button, Textarea } from "@kleros/ui-components-library";
5-
import { useDisputeTemplate } from "queries/useDisputeTemplate";
6+
import { prepareWriteDisputeKitClassic } from "hooks/contracts/generated";
67
import { wrapWithToast } from "utils/wrapWithToast";
7-
import { useWalletClient } from "wagmi";
8+
import { useDisputeTemplate } from "queries/useDisputeTemplate";
9+
import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery";
810
import { EnsureChain } from "components/EnsureChain";
9-
import { prepareWriteDisputeKitClassic } from "hooks/contracts/generated";
1011

1112
const Container = styled.div`
1213
width: 100%;
@@ -43,11 +44,12 @@ const RefuseToArbitrateContainer = styled.div`
4344
justify-content: center;
4445
`;
4546

46-
const Binary: React.FC<{ arbitrable?: string; voteIDs: string[] }> = ({ arbitrable, voteIDs }) => {
47+
const Binary: React.FC<{ arbitrable: `0x${string}`; voteIDs: string[] }> = ({ arbitrable, voteIDs }) => {
4748
const { id } = useParams();
4849
const parsedDisputeID = BigInt(id ?? 0);
4950
const parsedVoteIDs = useMemo(() => voteIDs.map((voteID) => BigInt(voteID)), [voteIDs]);
5051
const { data: disputeTemplate } = useDisputeTemplate(id, arbitrable);
52+
const { data: disputeData } = useDisputeDetailsQuery(id);
5153
const [chosenOption, setChosenOption] = useState(-1);
5254
const [isSending, setIsSending] = useState(false);
5355
const [justification, setJustification] = useState("");
@@ -58,7 +60,13 @@ const Binary: React.FC<{ arbitrable?: string; voteIDs: string[] }> = ({ arbitrab
5860
setChosenOption(voteOption);
5961
const { request } = await prepareWriteDisputeKitClassic({
6062
functionName: "castVote",
61-
args: [parsedDisputeID, parsedVoteIDs, BigInt(voteOption), 0n, justification],
63+
args: [
64+
parsedDisputeID,
65+
parsedVoteIDs,
66+
BigInt(voteOption),
67+
BigInt(disputeData?.dispute?.currentRoundIndex),
68+
justification,
69+
],
6270
});
6371
if (walletClient) {
6472
wrapWithToast(walletClient.writeContract(request)).finally(() => {

web/src/pages/Cases/CaseDetails/Voting/VotingHistory.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,18 @@ const StyledBox = styled(Box)`
3535
const StyledAccordion = styled(Accordion)`
3636
width: 100%;
3737
> * > button {
38+
justify-content: unset;
39+
padding: 11.5px 18px;
3840
background-color: ${({ theme }) => theme.whiteBackground} !important;
3941
border: 1px solid ${({ theme }) => theme.stroke} !important;
42+
> p {
43+
margin-left: 12px;
44+
margin-right: auto;
45+
color: ${({ theme }) => theme.primaryText};
46+
}
47+
> svg {
48+
fill: ${({ theme }) => theme.primaryText} !important;
49+
}
4050
}
4151
> * > div > div {
4252
padding: 8px 16px;
@@ -75,7 +85,7 @@ const JustificationContainer = styled.div`
7585
}
7686
`;
7787

78-
const VotingHistory: React.FC<{ arbitrable?: string }> = ({ arbitrable }) => {
88+
const VotingHistory: React.FC<{ arbitrable?: `0x${string}` }> = ({ arbitrable }) => {
7989
const { id } = useParams();
8090
const { data: votingHistory } = useVotingHistory(id);
8191
const [currentTab, setCurrentTab] = useState(0);
@@ -108,7 +118,7 @@ const VotingHistory: React.FC<{ arbitrable?: string }> = ({ arbitrable }) => {
108118
items={
109119
localRounds.at(currentTab)?.votes.map((vote) => ({
110120
title: shortenAddress(vote.juror.id),
111-
Icon: <Jazzicon diameter={24} seed={jsNumberForAddress(vote.juror.id)} />,
121+
icon: <Jazzicon diameter={20} seed={jsNumberForAddress(vote.juror.id)} />,
112122
body: (
113123
<AccordionContent
114124
choice={vote.choice === 0 ? "Refuse to arbitrate" : disputeTemplate.answers[vote.choice - 1].title}

web/src/pages/Cases/CaseDetails/Voting/index.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
11
import React from "react";
22
import { useParams } from "react-router-dom";
33
import { useAccount } from "wagmi";
4+
import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery";
45
import { useDrawQuery } from "queries/useDrawQuery";
56
import Binary from "./Binary";
67
import VotingHistory from "./VotingHistory";
78
import { Periods } from "consts/periods";
9+
import { isUndefined } from "utils/index";
810

911
const Voting: React.FC<{
10-
arbitrable?: string;
12+
arbitrable?: `0x${string}`;
1113
currentPeriodIndex?: number;
1214
}> = ({ arbitrable, currentPeriodIndex }) => {
1315
const { address } = useAccount();
1416
const { id } = useParams();
15-
const { data } = useDrawQuery(address?.toLowerCase(), id);
16-
return data &&
17-
currentPeriodIndex === Periods.vote &&
18-
data.draws?.length > 0 ? (
19-
<Binary
20-
{...{ arbitrable }}
21-
voteIDs={data.draws.map((draw) => draw.voteID)}
22-
/>
17+
const { data: disputeData } = useDisputeDetailsQuery(id);
18+
const { data } = useDrawQuery(address?.toLowerCase(), id, disputeData?.dispute?.currentRound.id);
19+
return data && !isUndefined(arbitrable) && currentPeriodIndex === Periods.vote && data.draws?.length > 0 ? (
20+
<Binary {...{ arbitrable }} voteIDs={data.draws.map((draw) => draw.voteID)} />
2321
) : (
2422
<VotingHistory {...{ arbitrable }} />
2523
);

web/src/pages/Cases/CaseDetails/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const CaseDetails: React.FC = () => {
1616
const { data } = useDisputeDetailsQuery(id);
1717
const dispute = data?.dispute;
1818
const currentPeriodIndex = dispute ? Periods[dispute.period] : 0;
19-
const arbitrable = dispute?.arbitrated.id;
19+
const arbitrable = dispute?.arbitrated.id as `0x${string}`;
2020

2121
return (
2222
<Container>

web/src/styles/themes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import { lightTheme as componentsLightTheme, darkTheme as componentsDarkTheme } from "@kleros/ui-components-library";
2+
13
export const lightTheme = {
4+
...componentsLightTheme,
25
primaryPurple: "#4D00B4",
36
secondaryPurple: "#9013FE",
47
mediumPurple: "#F8F1FF",
@@ -34,6 +37,7 @@ export const lightTheme = {
3437
};
3538

3639
export const darkTheme = {
40+
...componentsDarkTheme,
3741
primaryPurple: "#7E1BD4",
3842
secondaryPurple: "#B45FFF",
3943
mediumPurple: "#390F6C",

yarn.lock

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4042,7 +4042,7 @@ __metadata:
40424042
"@kleros/kleros-v2-eslint-config": "workspace:^"
40434043
"@kleros/kleros-v2-prettier-config": "workspace:^"
40444044
"@kleros/kleros-v2-tsconfig": "workspace:^"
4045-
"@kleros/ui-components-library": ^1.9.2
4045+
"@kleros/ui-components-library": ^2.5.2
40464046
"@netlify/functions": ^1.6.0
40474047
"@parcel/transformer-svg-react": ~2.8.0
40484048
"@parcel/watcher": ~2.1.0
@@ -4094,9 +4094,9 @@ __metadata:
40944094
languageName: unknown
40954095
linkType: soft
40964096

4097-
"@kleros/ui-components-library@npm:^1.9.2":
4098-
version: 1.9.2
4099-
resolution: "@kleros/ui-components-library@npm:1.9.2"
4097+
"@kleros/ui-components-library@npm:^2.5.2":
4098+
version: 2.5.2
4099+
resolution: "@kleros/ui-components-library@npm:2.5.2"
41004100
dependencies:
41014101
"@datepicker-react/hooks": ^2.8.4
41024102
"@swc/helpers": ^0.3.2
@@ -4107,12 +4107,13 @@ __metadata:
41074107
simplebar: ^5.3.6
41084108
simplebar-react: ^2.3.6
41094109
smooth-scroll-into-view-if-needed: ^1.1.33
4110+
usehooks-ts: ^2.9.1
41104111
peerDependencies:
41114112
react: ^18.0.0
41124113
react-dom: ^18.0.0
41134114
react-is: ^18.0.0
41144115
styled-components: ^5.3.3
4115-
checksum: 42dfddf1bf2e09be7f9350c173b371b29fdf22b25fb56c6500685d33bc63369ef316c05f0a8b7e81217abbab82557f8300de45357c6ec0d388882ca9d9c3c849
4116+
checksum: 159a999c4e13fb288f1594a677f325002552a06cf3c01e5139a16e2749a795934c3876e7e62eb0401ebeec85dec3ae9c66d9a14ff83de8134c58b0eadbbe6883
41164117
languageName: node
41174118
linkType: hard
41184119

@@ -28259,6 +28260,16 @@ __metadata:
2825928260
languageName: node
2826028261
linkType: hard
2826128262

28263+
"usehooks-ts@npm:^2.9.1":
28264+
version: 2.9.1
28265+
resolution: "usehooks-ts@npm:2.9.1"
28266+
peerDependencies:
28267+
react: ^16.8.0 || ^17.0.0 || ^18.0.0
28268+
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
28269+
checksum: 36f1e4142ce23bc019b81d2e93aefd7f2c350abcf255598c21627114a69a2f2f116b35dc3a353375f09c6e4c9b704a04f104e3d10e98280545c097feca66c30a
28270+
languageName: node
28271+
linkType: hard
28272+
2826228273
"utf-8-validate@npm:^5.0.2":
2826328274
version: 5.0.10
2826428275
resolution: "utf-8-validate@npm:5.0.10"

0 commit comments

Comments
 (0)