Skip to content

Commit f314504

Browse files
authored
Merge pull request #1754 from kleros/feat(web)/ux-ui-impros-in-evidence-cards-and-case-overview
feat: UX & UI impros in various places (evidence cards, voting cards, case overview, top jurors)
2 parents 884674e + fd6a186 commit f314504

File tree

18 files changed

+157
-38
lines changed

18 files changed

+157
-38
lines changed

subgraph/core/schema.graphql

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ interface Evidence {
5656
sender: User!
5757
senderAddress: String!
5858
timestamp: BigInt!
59+
transactionHash: Bytes!
5960
name: String
6061
description: String
6162
fileURI: String
@@ -318,6 +319,7 @@ type ClassicEvidence implements Evidence @entity(immutable: true) {
318319
sender: User!
319320
senderAddress: String!
320321
timestamp: BigInt!
322+
transactionHash: Bytes!
321323
name: String
322324
description: String
323325
fileURI: String

subgraph/core/src/EvidenceModule.ts

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export function handleEvidenceEvent(event: EvidenceEvent): void {
1717
evidence.evidenceIndex = evidenceIndex.plus(ONE).toString();
1818
const userId = event.params._party.toHexString();
1919
evidence.timestamp = event.block.timestamp;
20+
evidence.transactionHash = event.transaction.hash;
2021
evidence.evidence = event.params._evidence;
2122
evidence.evidenceGroup = evidenceGroupID.toString();
2223
evidence.sender = userId;

subgraph/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@kleros/kleros-v2-subgraph",
3-
"version": "0.9.0",
3+
"version": "0.9.1",
44
"license": "MIT",
55
"scripts": {
66
"update:core:arbitrum-sepolia-devnet": "./scripts/update.sh arbitrumSepoliaDevnet arbitrum-sepolia core/subgraph.yaml",

web/src/assets/svgs/icons/calendar.svg

+1-1
Loading

web/src/assets/svgs/icons/law-balance.svg

+1-1
Loading

web/src/components/DisputePreview/Policies.tsx

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from "react";
22
import styled, { css } from "styled-components";
33

4+
import { Link } from "react-router-dom";
5+
46
import PaperclipIcon from "svgs/icons/paperclip.svg";
57
import PolicyIcon from "svgs/icons/policy.svg";
68

@@ -59,6 +61,12 @@ const LinkContainer = styled.div`
5961
display: flex;
6062
gap: ${responsiveSize(16, 24)};
6163
flex-wrap: wrap;
64+
align-items: center;
65+
`;
66+
67+
const StyledLink = styled(Link)`
68+
display: flex;
69+
gap: 4px;
6270
`;
6371

6472
type Attachment = {
@@ -83,10 +91,10 @@ export const Policies: React.FC<IPolicies> = ({ disputePolicyURI, courtId, attac
8391
</StyledA>
8492
) : null}
8593
{isUndefined(disputePolicyURI) ? null : (
86-
<StyledA href={getIpfsUrl(disputePolicyURI)} target="_blank" rel="noreferrer">
94+
<StyledLink to={`policy/attachment/?url=${getIpfsUrl(disputePolicyURI)}`}>
8795
<StyledPolicyIcon />
8896
Dispute Policy
89-
</StyledA>
97+
</StyledLink>
9098
)}
9199
{isUndefined(courtId) ? null : (
92100
<StyledA href={`#/courts/${courtId}/purpose?section=description`}>

web/src/components/DisputeView/DisputeInfo/DisputeInfoCard.tsx

+9-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { getCourtsPath } from "pages/Courts/CourtDetails";
1212

1313
import CardLabel from "../CardLabels";
1414

15-
import { FieldItem, IDisputeInfo } from ".";
15+
import { FieldItem, IDisputeInfo } from "./index";
1616

1717
const Container = styled.div`
1818
display: flex;
@@ -59,6 +59,7 @@ const StyledField = styled(Field)`
5959
margin-left: 8px;
6060
overflow: hidden;
6161
text-overflow: ellipsis;
62+
text-wrap: auto;
6263
}
6364
}
6465
`;
@@ -86,7 +87,13 @@ const DisputeInfoCard: React.FC<IDisputeInfoCard> = ({
8687
<Container>
8788
{court && courtId && isOverview && (
8889
<CourtBranchFieldContainer>
89-
<StyledField icon={LawBalanceIcon} name="Court Branch" value={courtBranchValue} {...{ isOverview }} />
90+
<StyledField
91+
link={`/courts/${courtId}`}
92+
icon={LawBalanceIcon}
93+
name="Court Branch"
94+
value={courtBranchValue}
95+
{...{ isOverview }}
96+
/>
9097
</CourtBranchFieldContainer>
9198
)}
9299
<RestOfFieldsContainer {...{ isOverview }}>

web/src/components/EvidenceCard.tsx

+42-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from "react";
1+
import React, { useMemo } from "react";
22
import styled, { css } from "styled-components";
33

44
import Identicon from "react-identicons";
@@ -9,6 +9,7 @@ import { Card } from "@kleros/ui-components-library";
99

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

12+
import { DEFAULT_CHAIN, getChain } from "consts/chains";
1213
import { formatDate } from "utils/date";
1314
import { getIpfsUrl } from "utils/getIpfsUrl";
1415
import { shortenAddress } from "utils/shortenAddress";
@@ -116,6 +117,19 @@ const StyledLink = styled(Link)`
116117
)}
117118
`;
118119

120+
const StyledA = styled.a`
121+
:hover {
122+
text-decoration: underline;
123+
p {
124+
color: ${({ theme }) => theme.primaryBlue};
125+
}
126+
label {
127+
cursor: pointer;
128+
color: ${({ theme }) => theme.primaryBlue};
129+
}
130+
}
131+
`;
132+
119133
const AttachedFileText: React.FC = () => (
120134
<>
121135
<DesktopText>View attached file</DesktopText>
@@ -126,9 +140,27 @@ const AttachedFileText: React.FC = () => (
126140
interface IEvidenceCard extends Pick<Evidence, "evidence" | "timestamp" | "name" | "description" | "fileURI"> {
127141
sender: string;
128142
index: number;
143+
transactionHash: string;
129144
}
130145

131-
const EvidenceCard: React.FC<IEvidenceCard> = ({ evidence, sender, index, timestamp, name, description, fileURI }) => {
146+
const EvidenceCard: React.FC<IEvidenceCard> = ({
147+
evidence,
148+
sender,
149+
index,
150+
timestamp,
151+
transactionHash,
152+
name,
153+
description,
154+
fileURI,
155+
}) => {
156+
const addressExplorerLink = useMemo(() => {
157+
return `${getChain(DEFAULT_CHAIN)?.blockExplorers?.default.url}/address/${sender}`;
158+
}, [sender]);
159+
160+
const transactionExplorerLink = useMemo(() => {
161+
return `${getChain(DEFAULT_CHAIN)?.blockExplorers?.default.url}/tx/${transactionHash}`;
162+
}, [transactionHash]);
163+
132164
return (
133165
<StyledCard>
134166
<TextContainer>
@@ -145,15 +177,19 @@ const EvidenceCard: React.FC<IEvidenceCard> = ({ evidence, sender, index, timest
145177
<BottomShade>
146178
<AccountContainer>
147179
<Identicon size="24" string={sender} />
148-
<p>{shortenAddress(sender)}</p>
180+
<StyledA href={addressExplorerLink} rel="noopener noreferrer" target="_blank">
181+
<p>{shortenAddress(sender)}</p>
182+
</StyledA>
149183
</AccountContainer>
150-
<Timestamp>{formatDate(Number(timestamp), true)}</Timestamp>
151-
{fileURI && (
184+
<StyledA href={transactionExplorerLink} rel="noopener noreferrer" target="_blank">
185+
<Timestamp>{formatDate(Number(timestamp), true)}</Timestamp>
186+
</StyledA>
187+
{fileURI && fileURI !== "-" ? (
152188
<StyledLink to={`attachment/?url=${getIpfsUrl(fileURI)}`}>
153189
<AttachmentIcon />
154190
<AttachedFileText />
155191
</StyledLink>
156-
)}
192+
) : null}
157193
</BottomShade>
158194
</StyledCard>
159195
);

web/src/components/Field.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React from "react";
22
import styled, { css } from "styled-components";
3+
import { landscapeStyle } from "styles/landscapeStyle";
34

45
import { Link } from "react-router-dom";
56

6-
import { landscapeStyle } from "styles/landscapeStyle";
7+
import { useScrollTop } from "hooks/useScrollTop";
78

89
const FieldContainer = styled.div<FieldContainerProps>`
910
display: flex;
@@ -61,6 +62,8 @@ const LinkContainer = styled.div``;
6162

6263
const StyledLink = styled(Link)`
6364
color: ${({ theme }) => theme.primaryBlue};
65+
text-wrap: auto;
66+
justify-content: end;
6467
`;
6568

6669
type FieldContainerProps = {
@@ -93,6 +96,8 @@ const Field: React.FC<IField> = ({
9396
isJurorBalance,
9497
className,
9598
}) => {
99+
const scrollTop = useScrollTop();
100+
96101
return (
97102
<FieldContainer isList={displayAsList} {...{ isOverview, isJurorBalance, width, className }}>
98103
<Icon />
@@ -103,6 +108,7 @@ const Field: React.FC<IField> = ({
103108
to={link}
104109
onClick={(event) => {
105110
event.stopPropagation();
111+
scrollTop();
106112
}}
107113
>
108114
{value}

web/src/hooks/queries/useEvidences.ts

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const evidenceFragment = graphql(`
1515
id
1616
}
1717
timestamp
18+
transactionHash
1819
name
1920
description
2021
fileURI

web/src/hooks/useScrollTop.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { useContext } from "react";
2+
import { OverlayScrollContext } from "context/OverlayScrollContext";
3+
4+
export const useScrollTop = () => {
5+
const osInstanceRef = useContext(OverlayScrollContext);
6+
7+
const scrollTop = () => {
8+
osInstanceRef?.current?.osInstance().elements().viewport.scroll({ top: 0 });
9+
};
10+
11+
return scrollTop;
12+
};

web/src/layout/Header/navbar/DappList.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ const ITEMS = [
125125
url: "https://klerosscout.eth.limo",
126126
},
127127
{
128-
text: "POH V1",
128+
text: "POH V2",
129129
Icon: POH,
130-
url: "https://app.proofofhumanity.id",
130+
url: "https://v2.proofofhumanity.id",
131131
},
132132
{
133133
text: "Governor",

web/src/pages/Cases/AttachmentDisplay/Header.tsx

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
22
import styled from "styled-components";
33

4-
import { useNavigate, useParams } from "react-router-dom";
4+
import { useNavigate, useLocation, useParams } from "react-router-dom";
55

66
import { Button } from "@kleros/ui-components-library";
77

@@ -57,16 +57,23 @@ const StyledButton = styled(Button)`
5757
`;
5858

5959
const Header: React.FC = () => {
60-
const { id } = useParams();
6160
const navigate = useNavigate();
61+
const { id } = useParams();
62+
const location = useLocation();
63+
64+
const handleReturn = () => {
65+
navigate(-1);
66+
};
67+
68+
const title = location.pathname.includes("policy") ? `Policy File - Case #${id}` : "Attachment File";
6269

6370
return (
6471
<Container>
6572
<TitleContainer>
6673
<StyledPaperClip />
67-
<Title>Attachment File</Title>{" "}
74+
<Title>{title}</Title>
6875
</TitleContainer>
69-
<StyledButton text="Return" Icon={Arrow} onClick={() => navigate(`/cases/${id}/evidence`)} />
76+
<StyledButton text="Return" Icon={Arrow} onClick={handleReturn} />
7077
</Container>
7178
);
7279
};

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const StyledNewTabIcon = styled(NewTabIcon)`
3737
}
3838
`;
3939

40-
const EvidenceAttachmentDisplay: React.FC = () => {
40+
const AttachmentDisplay: React.FC = () => {
4141
const [searchParams] = useSearchParams();
4242

4343
const url = searchParams.get("url");
@@ -64,4 +64,4 @@ const EvidenceAttachmentDisplay: React.FC = () => {
6464
);
6565
};
6666

67-
export default EvidenceAttachmentDisplay;
67+
export default AttachmentDisplay;

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

+12-10
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,16 @@ const Evidence: React.FC = () => {
9595
<EvidenceSearch {...{ search, setSearch, evidenceGroup: disputeData?.dispute?.externalDisputeId }} />
9696
<ScrollButton small Icon={DownArrow} text="Scroll to latest" onClick={scrollToLatest} />
9797
{evidences?.realEvidences ? (
98-
evidences?.realEvidences.map(({ evidence, sender, timestamp, name, description, fileURI, evidenceIndex }) => (
99-
<EvidenceCard
100-
key={timestamp}
101-
index={parseInt(evidenceIndex)}
102-
sender={sender?.id}
103-
{...{ evidence, timestamp, name, description, fileURI }}
104-
/>
105-
))
98+
evidences?.realEvidences.map(
99+
({ evidence, sender, timestamp, transactionHash, name, description, fileURI, evidenceIndex }) => (
100+
<EvidenceCard
101+
key={timestamp}
102+
index={parseInt(evidenceIndex)}
103+
sender={sender?.id}
104+
{...{ evidence, timestamp, transactionHash, name, description, fileURI }}
105+
/>
106+
)
107+
)
106108
) : (
107109
<SkeletonEvidenceCard />
108110
)}
@@ -111,12 +113,12 @@ const Evidence: React.FC = () => {
111113
<Divider />
112114
{showSpam ? (
113115
evidences?.spamEvidences.map(
114-
({ evidence, sender, timestamp, name, description, fileURI, evidenceIndex }) => (
116+
({ evidence, sender, timestamp, transactionHash, name, description, fileURI, evidenceIndex }) => (
115117
<EvidenceCard
116118
key={timestamp}
117119
index={parseInt(evidenceIndex)}
118120
sender={sender?.id}
119-
{...{ evidence, timestamp, name, description, fileURI }}
121+
{...{ evidence, timestamp, transactionHash, name, description, fileURI }}
120122
/>
121123
)
122124
)

0 commit comments

Comments
 (0)