Skip to content

Commit 7af5a24

Browse files
authored
Merge pull request #1840 from kleros/feat(web)/jurors-page
feat: jurors page
2 parents 474605b + 2bb0a19 commit 7af5a24

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+766
-256
lines changed

Diff for: subgraph/core/schema.graphql

+2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ interface Evidence {
6969

7070
type User @entity {
7171
id: ID! # address
72+
userAddress: String!
7273
tokens: [JurorTokensPerCourt!]! @derivedFrom(field: "juror")
7374
totalStake: BigInt!
7475
totalDelayed: BigInt!
@@ -237,6 +238,7 @@ type Counter @entity {
237238
casesVoting: BigInt!
238239
casesRuled: BigInt!
239240
casesAppealing: BigInt!
241+
totalLeaderboardJurors: BigInt!
240242
}
241243

242244
type FeeToken @entity {

Diff for: subgraph/core/src/KlerosCore.ts

+22-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ import { createCourtFromEvent } from "./entities/Court";
1818
import { createDisputeKitFromEvent, filterSupportedDisputeKits } from "./entities/DisputeKit";
1919
import { createDisputeFromEvent } from "./entities/Dispute";
2020
import { createRoundFromRoundInfo, updateRoundTimeline } from "./entities/Round";
21-
import { updateCases, updateCasesAppealing, updateCasesRuled, updateCasesVoting } from "./datapoint";
21+
import {
22+
updateCases,
23+
updateCasesAppealing,
24+
updateCasesRuled,
25+
updateCasesVoting,
26+
updateTotalLeaderboardJurors,
27+
} from "./datapoint";
2228
import { addUserActiveDispute, computeCoherenceScore, ensureUser } from "./entities/User";
2329
import { updateJurorStake } from "./entities/JurorTokensPerCourt";
2430
import { createDrawFromEvent } from "./entities/Draw";
@@ -139,13 +145,23 @@ export function handleNewPeriod(event: NewPeriod): void {
139145
const draw = Draw.load(draws[j].id);
140146
if (!draw) continue;
141147

148+
const juror = ensureUser(draw.juror);
149+
juror.totalResolvedVotes = juror.totalResolvedVotes.plus(ONE);
150+
151+
// Increment totalLeaderboardJurors in the Counter entity if this is the first resolved vote for the juror
152+
if (juror.totalResolvedVotes.equals(ONE)) {
153+
updateTotalLeaderboardJurors(ONE, event.block.timestamp);
154+
}
155+
142156
// Since this is a ClassicVote entity, this will only work for the Classic DisputeKit (which has ID "1").
143157
const vote = ClassicVote.load(`${round.disputeKit}-${draw.id}`);
144158

145-
if (!vote) continue;
146-
147-
const juror = ensureUser(draw.juror);
148-
juror.totalResolvedVotes = juror.totalResolvedVotes.plus(ONE);
159+
if (!vote) {
160+
// Recalculate coherenceScore
161+
juror.coherenceScore = computeCoherenceScore(juror.totalCoherentVotes, juror.totalResolvedVotes);
162+
juror.save();
163+
continue;
164+
}
149165

150166
if (vote.choice === null) continue;
151167

@@ -155,9 +171,7 @@ export function handleNewPeriod(event: NewPeriod): void {
155171
}
156172

157173
// Recalculate coherenceScore
158-
if (juror.totalResolvedVotes.gt(ZERO)) {
159-
juror.coherenceScore = computeCoherenceScore(juror.totalCoherentVotes, juror.totalResolvedVotes);
160-
}
174+
juror.coherenceScore = computeCoherenceScore(juror.totalCoherentVotes, juror.totalResolvedVotes);
161175

162176
juror.save();
163177
}

Diff for: subgraph/core/src/datapoint.ts

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const VARIABLES = [
1515
"casesVoting",
1616
"casesRuled",
1717
"casesAppealing",
18+
"totalLeaderboardJurors",
1819
];
1920

2021
function updateDataPoint(delta: BigInt, timestamp: BigInt, variable: string): void {
@@ -43,6 +44,7 @@ function checkFirstDayActivity(): void {
4344
counter.casesVoting = ZERO;
4445
counter.casesRuled = ZERO;
4546
counter.casesAppealing = ZERO;
47+
counter.totalLeaderboardJurors = ZERO;
4648
counter.save();
4749
}
4850
}
@@ -86,3 +88,7 @@ export function updateCasesRuled(delta: BigInt, timestamp: BigInt): void {
8688
export function updateCasesAppealing(delta: BigInt, timestamp: BigInt): void {
8789
updateDataPoint(delta, timestamp, "casesAppealing");
8890
}
91+
92+
export function updateTotalLeaderboardJurors(delta: BigInt, timestamp: BigInt): void {
93+
updateDataPoint(delta, timestamp, "totalLeaderboardJurors");
94+
}

Diff for: subgraph/core/src/entities/User.ts

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export function ensureUser(id: string): User {
2727

2828
export function createUserFromAddress(id: string): User {
2929
const user = new User(id);
30+
user.userAddress = id.toLowerCase();
3031
user.totalStake = ZERO;
3132
user.totalDelayed = ZERO;
3233
user.activeDisputes = ZERO;

Diff for: subgraph/package.json

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "@kleros/kleros-v2-subgraph",
3-
"version": "0.10.1",
3+
"version": "0.10.3",
4+
"drtVersion": "0.11.0",
45
"license": "MIT",
56
"scripts": {
67
"update:core:arbitrum-sepolia-devnet": "./scripts/update.sh arbitrumSepoliaDevnet arbitrum-sepolia core/subgraph.yaml",
@@ -11,9 +12,9 @@
1112
"build:core": "graph build --output-dir core/build/ core/subgraph.yaml",
1213
"test:core": "cd core && graph test",
1314
"clean:core": "graph clean --codegen-dir core/generated/ --build-dir core/build/ ; rm core/subgraph.yaml.bak.*",
14-
"deploy:core:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-core-devnet -l v$npm_package_version core/subgraph.yaml",
15-
"deploy:core:arbitrum-sepolia": "graph deploy --product subgraph-studio kleros-v2-core-testnet -l v$npm_package_version core/subgraph.yaml",
16-
"deploy:core:arbitrum": "graph deploy --product subgraph-studio kleros-v2-core-mainnet -l v$npm_package_version core/subgraph.yaml",
15+
"deploy:core:arbitrum-sepolia-devnet": "graph deploy kleros-v2-core-devnet -l v$npm_package_version core/subgraph.yaml",
16+
"deploy:core:arbitrum-sepolia": "graph deploy kleros-v2-core-testnet -l v$npm_package_version core/subgraph.yaml",
17+
"deploy:core:arbitrum": "graph deploy kleros-v2-core-mainnet -l v$npm_package_version core/subgraph.yaml",
1718
"deploy:core:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-core-local --version-label v$(date +%s) core/subgraph.yaml",
1819
"rebuild-deploy:core:local": "yarn update:core:local && yarn codegen:core && yarn build:core && yarn create:local kleros/kleros-v2-core-local && yarn deploy:core:local",
1920
"": "------------------------------------------------------------------------------------------",
@@ -24,8 +25,8 @@
2425
"build:core-neo": "graph build --output-dir core-neo/build/ core-neo/subgraph.yaml",
2526
"test:core-neo": "cd core-neo && graph test",
2627
"clean:core-neo": "graph clean --codegen-dir core-neo/generated/ --build-dir core-neo/build/ ; rm core-neo/subgraph.yaml.bak.*",
27-
"deploy:core-neo:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-coreneo-devnet -l v$npm_package_version core-neo/subgraph.yaml",
28-
"deploy:core-neo:arbitrum": "graph deploy --product subgraph-studio kleros-v2-coreneo -l v$npm_package_version core-neo/subgraph.yaml",
28+
"deploy:core-neo:arbitrum-sepolia-devnet": "graph deploy kleros-v2-coreneo-devnet -l v$npm_package_version core-neo/subgraph.yaml",
29+
"deploy:core-neo:arbitrum": "graph deploy kleros-v2-coreneo -l v$npm_package_version core-neo/subgraph.yaml",
2930
"deploy:core-neo:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-coreneo-local --version-label v$(date +%s) core-neo/subgraph.yaml",
3031
"rebuild-deploy:core-neo:local": "yarn update:core-neo:local && yarn codegen:core-neo && yarn build:core-neo && yarn create:local kleros/kleros-v2-coreneo-local && yarn deploy:core-neo:local",
3132
"-": "------------------------------------------------------------------------------------------",
@@ -35,7 +36,7 @@
3536
"build:core-university": "graph build --output-dir core-university/build/ core-university/subgraph.yaml",
3637
"test:core-university": "cd core-university && graph test",
3738
"clean:core-university": "graph clean --codegen-dir core-university/generated/ --build-dir core-university/build/ ; rm core-university/subgraph.yaml.bak.*",
38-
"deploy:core-university:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-coreuni-devnet -l v$npm_package_version core-university/subgraph.yaml",
39+
"deploy:core-university:arbitrum-sepolia-devnet": "graph deploy kleros-v2-coreuni-devnet -l v$npm_package_version core-university/subgraph.yaml",
3940
"deploy:core-university:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-coreuni-local --version-label v$(date +%s) core-university/subgraph.yaml",
4041
"rebuild-deploy:core-university:local": "yarn update:core-university:local && yarn codegen:core-university && yarn build:core-university && yarn create:local kleros/kleros-v2-coreuni-local && yarn deploy:core-university:local",
4142
"--": "-----------------------------------------------------------------------------------------",
@@ -47,9 +48,9 @@
4748
"build:drt": "graph build --output-dir dispute-template-registry/generated/ dispute-template-registry/subgraph.yaml",
4849
"test:drt": "cd dispute-template-registry && graph test ",
4950
"clean:drt": "graph clean --codegen-dir dispute-template-registry/generated/ --build-dir dispute-template-registry/build/ ; rm dispute-template-registry/subgraph.yaml.bak.*",
50-
"deploy:drt:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-drt-arbisep-devnet -l v$npm_package_version dispute-template-registry/subgraph.yaml",
51-
"deploy:drt:arbitrum-sepolia": "graph deploy --product subgraph-studio kleros-v2-drt-arbisep-testnet -l v$npm_package_version dispute-template-registry/subgraph.yaml",
52-
"deploy:drt:arbitrum": "graph deploy --product subgraph-studio kleros-v2-drt -l v$npm_package_version dispute-template-registry/subgraph.yaml",
51+
"deploy:drt:arbitrum-sepolia-devnet": "graph deploy kleros-v2-drt-arbisep-devnet -l v$(jq -r .drtVersion $npm_package_json) dispute-template-registry/subgraph.yaml",
52+
"deploy:drt:arbitrum-sepolia": "graph deploy kleros-v2-drt-arbisep-testnet -l v$(jq -r .drtVersion $npm_package_json) dispute-template-registry/subgraph.yaml",
53+
"deploy:drt:arbitrum": "graph deploy kleros-v2-drt -l v$(jq -r .drtVersion $npm_package_json) dispute-template-registry/subgraph.yaml",
5354
"deploy:drt:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-drt-local --version-label v$(date +%s) dispute-template-registry/subgraph.yaml",
5455
"rebuild-deploy:drt:local": "yarn update:drt:local && yarn codegen:drt && yarn build:drt && yarn create:local kleros/kleros-v2-drt-local && yarn deploy:drt:local",
5556
"---": "----------------------------------------------------------------------------------------",

Diff for: web/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<p align="center">
2-
<b style="font-size: 32px;">Kleros Court v2</b>
2+
<b style="font-size: 32px;">Kleros Court v2 </b>
33
</p>
44

55
<p align="center">

Diff for: web/src/app.tsx

+12-3
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import QueryClientProvider from "context/QueryClientProvider";
1414
import StyledComponentsProvider from "context/StyledComponentsProvider";
1515
const Home = lazy(() => import("./pages/Home"));
1616
const Cases = lazy(() => import("./pages/Cases"));
17-
const Dashboard = lazy(() => import("./pages/Dashboard"));
17+
const Profile = lazy(() => import("./pages/Profile"));
1818
const Courts = lazy(() => import("./pages/Courts"));
19+
const Jurors = lazy(() => import("./pages/Jurors"));
1920
const DisputeResolver = lazy(() => import("./pages/Resolver"));
2021
const GetPnk = lazy(() => import("./pages/GetPnk"));
2122
const Settings = lazy(() => import("./pages/Settings"));
@@ -64,10 +65,18 @@ const App: React.FC = () => {
6465
}
6566
/>
6667
<Route
67-
path="dashboard/:page/:order/:filter"
68+
path="jurors/:page/:order/:filter"
6869
element={
6970
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
70-
<Dashboard />
71+
<Jurors />
72+
</Suspense>
73+
}
74+
/>
75+
<Route
76+
path="profile/:page/:order/:filter"
77+
element={
78+
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
79+
<Profile />
7180
</Suspense>
7281
}
7382
/>

Diff for: web/src/assets/svgs/icons/ranking.svg

+3
Loading

Diff for: web/src/components/BlueIconTextButtonContainer.tsx

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import styled from "styled-components";
2+
import { hoverShortTransitionTiming } from "styles/commonStyles";
3+
4+
export const BlueIconTextButtonContainer = styled.div`
5+
${hoverShortTransitionTiming}
6+
display: flex;
7+
align-items: center;
8+
font-size: 14px;
9+
font-weight: 400;
10+
gap: 8px;
11+
cursor: pointer;
12+
color: ${({ theme }) => theme.primaryBlue};
13+
14+
svg path {
15+
fill: ${({ theme }) => theme.primaryBlue};
16+
}
17+
18+
&:hover {
19+
color: ${({ theme }) => theme.secondaryBlue};
20+
svg path {
21+
fill: ${({ theme }) => theme.secondaryBlue};
22+
}
23+
}
24+
`;

Diff for: web/src/components/EvidenceCard.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { Card } from "@kleros/ui-components-library";
88

99
import AttachmentIcon from "svgs/icons/attachment.svg";
1010

11-
import { DEFAULT_CHAIN, getChain } from "consts/chains";
1211
import { formatDate } from "utils/date";
1312
import { getIpfsUrl } from "utils/getIpfsUrl";
1413
import { shortenAddress } from "utils/shortenAddress";
@@ -224,7 +223,7 @@ const EvidenceCard: React.FC<IEvidenceCard> = ({
224223
description,
225224
fileURI,
226225
}) => {
227-
const dashboardLink = `/dashboard/1/desc/all?address=${sender}`;
226+
const profileLink = `/profile/1/desc/all?address=${sender}`;
228227

229228
const transactionExplorerLink = useMemo(() => {
230229
return getTxnExplorerLink(transactionHash ?? "");
@@ -249,7 +248,7 @@ const EvidenceCard: React.FC<IEvidenceCard> = ({
249248
<BottomLeftContent>
250249
<AccountContainer>
251250
<Identicon size="24" string={sender} />
252-
<InternalLink to={dashboardLink}>
251+
<InternalLink to={profileLink}>
253252
<Address>{shortenAddress(sender)}</Address>
254253
</InternalLink>
255254
</AccountContainer>

Diff for: web/src/components/ExtraStatsDisplay.tsx

+14-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ import { InternalLink } from "./InternalLink";
88
const Container = styled.div`
99
display: flex;
1010
gap: 8px;
11-
align-items: center;
11+
justify-content: center;
12+
flex-wrap: wrap;
13+
`;
14+
15+
const TitleContainer = styled.div`
16+
display: flex;
17+
gap: 8px;
1218
`;
1319

1420
const SVGContainer = styled.div`
@@ -22,12 +28,12 @@ const SVGContainer = styled.div`
2228
}
2329
`;
2430

25-
const TextContainer = styled.div`
31+
const ContentContainer = styled.div`
2632
display: flex;
2733
align-items: center;
2834
gap: 8px;
2935
flex-wrap: wrap;
30-
justify-content: center;
36+
text-align: center;
3137
`;
3238

3339
const StyledInternalLink = styled(InternalLink)`
@@ -49,17 +55,19 @@ export interface IExtraStatsDisplay {
4955
const ExtraStatsDisplay: React.FC<IExtraStatsDisplay> = ({ title, courtId, text, content, icon: Icon, ...props }) => {
5056
return (
5157
<Container {...props}>
52-
<SVGContainer>{<Icon />}</SVGContainer>
53-
<TextContainer>
58+
<TitleContainer>
59+
<SVGContainer>{<Icon />}</SVGContainer>
5460
<label>{title}:</label>
61+
</TitleContainer>
62+
<ContentContainer>
5563
{content ? (
5664
content
5765
) : (
5866
<StyledInternalLink to={`/courts/${courtId?.toString()}`}>
5967
{!isUndefined(text) ? text : <StyledExtraStatTitleSkeleton />}
6068
</StyledInternalLink>
6169
)}
62-
</TextContainer>
70+
</ContentContainer>
6371
</Container>
6472
);
6573
};

Diff for: web/src/components/HowItWorks.tsx

+3-26
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,8 @@
11
import React from "react";
2-
import styled from "styled-components";
3-
4-
import { hoverShortTransitionTiming } from "styles/commonStyles";
52

63
import BookOpenIcon from "svgs/icons/book-open.svg";
74

8-
const Container = styled.div`
9-
${hoverShortTransitionTiming}
10-
display: flex;
11-
align-items: center;
12-
font-size: 14px;
13-
font-weight: 400;
14-
gap: 8px;
15-
cursor: pointer;
16-
color: ${({ theme }) => theme.primaryBlue};
17-
18-
svg path {
19-
fill: ${({ theme }) => theme.primaryBlue};
20-
}
21-
22-
&:hover {
23-
color: ${({ theme }) => theme.secondaryBlue};
24-
svg path {
25-
fill: ${({ theme }) => theme.secondaryBlue};
26-
}
27-
}
28-
`;
5+
import { BlueIconTextButtonContainer } from "./BlueIconTextButtonContainer";
296

307
interface IHowItWorks {
318
isMiniGuideOpen: boolean;
@@ -36,10 +13,10 @@ interface IHowItWorks {
3613
const HowItWorks: React.FC<IHowItWorks> = ({ isMiniGuideOpen, toggleMiniGuide, MiniGuideComponent }) => {
3714
return (
3815
<>
39-
<Container onClick={toggleMiniGuide}>
16+
<BlueIconTextButtonContainer onClick={toggleMiniGuide}>
4017
<BookOpenIcon />
4118
How it works
42-
</Container>
19+
</BlueIconTextButtonContainer>
4320
{isMiniGuideOpen && <MiniGuideComponent toggleMiniGuide={toggleMiniGuide} />}
4421
</>
4522
);

Diff for: web/src/components/JurorsLeaderboardButton.tsx

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from "react";
2+
3+
import RankingIcon from "svgs/icons/ranking.svg";
4+
5+
import { BlueIconTextButtonContainer } from "./BlueIconTextButtonContainer";
6+
import { InternalLink } from "./InternalLink";
7+
8+
const JurorsLeaderboardButton: React.FC = () => {
9+
return (
10+
<InternalLink to={"/jurors/1/desc/all"}>
11+
<BlueIconTextButtonContainer>
12+
<RankingIcon />
13+
Jurors Leaderboard
14+
</BlueIconTextButtonContainer>
15+
</InternalLink>
16+
);
17+
};
18+
19+
export default JurorsLeaderboardButton;

0 commit comments

Comments
 (0)