Skip to content

Commit 906260b

Browse files
committed
feat(web): show-policy-once-uploaded-in-resolver
1 parent 1699758 commit 906260b

File tree

9 files changed

+132
-95
lines changed

9 files changed

+132
-95
lines changed

web/src/app.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import Loader from "components/Loader";
2626
import Layout from "layout/index";
2727

2828
import ErrorFallback from "./components/ErrorFallback";
29+
import AttachmentDisplay from "./pages/AttachmentDisplay";
2930
import { SentryRoutes } from "./utils/sentry";
3031

3132
const App: React.FC = () => {
@@ -104,6 +105,14 @@ const App: React.FC = () => {
104105
</Suspense>
105106
}
106107
/>
108+
<Route
109+
path="attachment/*"
110+
element={
111+
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
112+
<AttachmentDisplay />
113+
</Suspense>
114+
}
115+
/>
107116
<Route path="*" element={<h1>Page not found</h1>} />
108117
</Route>
109118
</SentryRoutes>

web/src/components/DisputePreview/Policies.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,13 @@ export const Policies: React.FC<IPolicies> = ({ disputePolicyURI, courtId, attac
7171
<Container>
7272
<StyledP>Policy documents:</StyledP>
7373
{!isUndefined(attachment) && !isUndefined(attachment.uri) ? (
74-
<StyledInternalLink to={`attachment/?url=${getIpfsUrl(attachment.uri)}`}>
74+
<StyledInternalLink to={`/attachment/?title=${"Case Policy"}&&url=${getIpfsUrl(attachment.uri)}`}>
7575
<StyledPaperclipIcon />
7676
{attachment.label ?? "Attachment"}
7777
</StyledInternalLink>
7878
) : null}
7979
{isUndefined(disputePolicyURI) ? null : (
80-
<StyledInternalLink to={`policy/attachment/?url=${getIpfsUrl(disputePolicyURI)}`}>
80+
<StyledInternalLink to={`/attachment/?title=${"Dispute Policy"}&&url=${getIpfsUrl(disputePolicyURI)}`}>
8181
<StyledPolicyIcon />
8282
Dispute Policy
8383
</StyledInternalLink>

web/src/components/EvidenceCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ const EvidenceCard: React.FC<IEvidenceCard> = ({
258258
</BottomLeftContent>
259259
{fileURI && fileURI !== "-" ? (
260260
<FileLinkContainer>
261-
<StyledInternalLink to={`attachment/?url=${getIpfsUrl(fileURI)}`}>
261+
<StyledInternalLink to={`/attachment/?title=${"Evidence File"}&&url=${getIpfsUrl(fileURI)}`}>
262262
<AttachmentIcon />
263263
<AttachedFileText />
264264
</StyledInternalLink>

web/src/context/NewDisputeContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export const NewDisputeProvider: React.FC<{ children: React.ReactNode }> = ({ ch
112112

113113
useEffect(() => {
114114
// Cleanup function to clear local storage when user leaves the route
115-
if (location.pathname.includes("/resolver")) return;
115+
if (location.pathname.includes("/resolver") || location.pathname.includes("/attachment")) return;
116116

117117
resetDisputeData();
118118
// eslint-disable-next-line react-hooks/exhaustive-deps

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

Lines changed: 2 additions & 13 deletions
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, useLocation, useParams } from "react-router-dom";
4+
import { useNavigate } from "react-router-dom";
55

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

@@ -64,24 +64,13 @@ const StyledButton = styled(Button)`
6464
}
6565
`;
6666

67-
const Header: React.FC = () => {
67+
const Header: React.FC<{ title: string }> = ({ title }) => {
6868
const navigate = useNavigate();
69-
const { id } = useParams();
70-
const location = useLocation();
7169

7270
const handleReturn = () => {
7371
navigate(-1);
7472
};
7573

76-
let title = "";
77-
if (location.pathname.includes("policy")) {
78-
title = `Policy - Case #${id}`;
79-
} else if (location.pathname.includes("evidence")) {
80-
title = "Attached File";
81-
} else if (location.pathname.includes("attachment")) {
82-
title = `Attachment - Case #${id}`;
83-
}
84-
8574
return (
8675
<Container>
8776
<TitleContainer>
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import React, { lazy, Suspense } from "react";
2+
import styled from "styled-components";
3+
4+
import { useSearchParams } from "react-router-dom";
5+
6+
import NewTabIcon from "svgs/icons/new-tab.svg";
7+
8+
import { MAX_WIDTH_LANDSCAPE } from "styles/landscapeStyle";
9+
10+
import { ExternalLink } from "components/ExternalLink";
11+
import Loader from "components/Loader";
12+
13+
import Header from "./Header";
14+
15+
const FileViewer = lazy(() => import("components/FileViewer"));
16+
17+
const Container = styled.div`
18+
width: 100%;
19+
background-color: ${({ theme }) => theme.lightBackground};
20+
padding: calc(24px + (136 - 24) * (min(max(100vw, 375px), 1250px) - 375px) / 875);
21+
padding-top: calc(32px + (80 - 32) * (min(max(100vw, 375px), 1250px) - 375px) / 875);
22+
padding-bottom: calc(76px + (96 - 76) * (min(max(100vw, 375px), 1250px) - 375px) / 875);
23+
max-width: ${MAX_WIDTH_LANDSCAPE};
24+
margin: 0 auto;
25+
`;
26+
27+
const AttachmentContainer = styled.div`
28+
width: 100%;
29+
display: flex;
30+
flex-direction: column;
31+
gap: 8px;
32+
`;
33+
34+
const LoaderContainer = styled.div`
35+
width: 100%;
36+
display: flex;
37+
justify-content: center;
38+
`;
39+
40+
const StyledExternalLink = styled(ExternalLink)`
41+
display: flex;
42+
align-items: center;
43+
align-self: flex-end;
44+
gap: 8px;
45+
`;
46+
47+
const StyledNewTabIcon = styled(NewTabIcon)`
48+
path {
49+
fill: ${({ theme }) => theme.primaryBlue};
50+
}
51+
`;
52+
53+
const AttachmentDisplay: React.FC = () => {
54+
const [searchParams] = useSearchParams();
55+
56+
const url = searchParams.get("url");
57+
const title = searchParams.get("title") ?? "Attachment";
58+
return (
59+
<Container>
60+
<AttachmentContainer>
61+
<Header {...{ title }} />
62+
{url ? (
63+
<>
64+
<StyledExternalLink to={url} rel="noreferrer" target="_blank">
65+
Open in new tab <StyledNewTabIcon />
66+
</StyledExternalLink>
67+
<Suspense
68+
fallback={
69+
<LoaderContainer>
70+
<Loader width={"48px"} height={"48px"} />
71+
</LoaderContainer>
72+
}
73+
>
74+
<FileViewer url={url} />
75+
</Suspense>
76+
</>
77+
) : null}
78+
</AttachmentContainer>
79+
</Container>
80+
);
81+
};
82+
83+
export default AttachmentDisplay;

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

Lines changed: 0 additions & 70 deletions
This file was deleted.

web/src/pages/Cases/index.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import React from "react";
22
import styled, { css } from "styled-components";
33

4+
import { Routes, Route } from "react-router-dom";
5+
46
import { MAX_WIDTH_LANDSCAPE, landscapeStyle } from "styles/landscapeStyle";
57
import { responsiveSize } from "styles/responsiveSize";
68

7-
import { Routes, Route } from "react-router-dom";
8-
9-
import AttachmentDisplay from "./AttachmentDisplay";
109
import CaseDetails from "./CaseDetails";
1110
import CasesFetcher from "./CasesFetcher";
1211

@@ -28,9 +27,6 @@ const Cases: React.FC = () => (
2827
<Container>
2928
<Routes>
3029
<Route path="/display/:page/:order/:filter" element={<CasesFetcher />} />
31-
<Route path="/:id/evidence/attachment/*" element={<AttachmentDisplay />} />
32-
<Route path="/:id/overview/policy/attachment/*" element={<AttachmentDisplay />} />
33-
<Route path="/:id/overview/attachment/*" element={<AttachmentDisplay />} />
3430
<Route path="/:id/*" element={<CaseDetails />} />
3531
</Routes>
3632
</Container>

web/src/pages/Resolver/Policy/index.tsx

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@ import styled, { css } from "styled-components";
44
import { useAtlasProvider, Roles } from "@kleros/kleros-app";
55
import { FileUploader } from "@kleros/ui-components-library";
66

7+
import PolicyIcon from "svgs/icons/policy.svg";
8+
79
import { useNewDisputeContext } from "context/NewDisputeContext";
810
import useIsDesktop from "hooks/useIsDesktop";
11+
import { getIpfsUrl } from "utils/getIpfsUrl";
912
import { errorToast, infoToast, successToast } from "utils/wrapWithToast";
1013

11-
import { getFileUploaderMsg } from "src/utils";
14+
import { getFileUploaderMsg, isUndefined } from "src/utils";
1215

16+
import { hoverShortTransitionTiming } from "styles/commonStyles";
1317
import { landscapeStyle } from "styles/landscapeStyle";
1418
import { responsiveSize } from "styles/responsiveSize";
1519

20+
import { InternalLink } from "components/InternalLink";
1621
import Header from "pages/Resolver/Header";
1722

1823
import NavigationButtons from "../NavigationButtons";
@@ -54,6 +59,25 @@ const StyledFileUploader = styled(FileUploader)`
5459
}
5560
`;
5661

62+
const StyledPolicyIcon = styled(PolicyIcon)`
63+
width: 16px;
64+
fill: ${({ theme }) => theme.primaryBlue};
65+
`;
66+
67+
const StyledInternalLink = styled(InternalLink)`
68+
${hoverShortTransitionTiming}
69+
display: flex;
70+
gap: 4px;
71+
align-self: flex-start;
72+
margin-bottom: 32px;
73+
margin-top: 32px;
74+
&:hover {
75+
svg {
76+
fill: ${({ theme }) => theme.secondaryBlue};
77+
}
78+
}
79+
`;
80+
5781
const Policy: React.FC = () => {
5882
const { disputeData, setDisputeData, setIsPolicyUploading } = useNewDisputeContext();
5983
const { uploadFile, roleRestrictions } = useAtlasProvider();
@@ -83,12 +107,18 @@ const Policy: React.FC = () => {
83107
criteria, a contract stating the rights and duties of the parties, or any set of pre-defined rules that are
84108
relevant to jurors' decision-making.
85109
</StyledLabel>
110+
86111
<StyledFileUploader
87112
callback={handleFileUpload}
88113
variant={isDesktop ? "info" : undefined}
89114
msg={`You can attach additional information here. Important: the above description must reference the relevant parts of the file content.\n${getFileUploaderMsg(Roles.Policy, roleRestrictions)}`}
90115
/>
91-
116+
{!isUndefined(disputeData.policyURI) ? (
117+
<StyledInternalLink to={`/attachment/?title=${"Policy File"}&&url=${getIpfsUrl(disputeData.policyURI)}`}>
118+
<StyledPolicyIcon />
119+
Inspect the uploaded policy
120+
</StyledInternalLink>
121+
) : null}
92122
<NavigationButtons prevRoute="/resolver/notable-persons" nextRoute="/resolver/preview" />
93123
</Container>
94124
);

0 commit comments

Comments
 (0)