Skip to content

Commit 7a33b9d

Browse files
committed
Update "govtool-pins-metadata" flow to match design
1 parent 01af374 commit 7a33b9d

File tree

5 files changed

+140
-23
lines changed

5 files changed

+140
-23
lines changed

govtool/frontend/src/components/organisms/VoteContext/VoteContextChoice.tsx

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { Dispatch, SetStateAction } from "react";
2-
import { Box, Button } from "@mui/material";
2+
import { Box, Button, Link } from "@mui/material";
33

44
import { Spacer, Typography } from "@atoms";
55
import { useScreenDimension, useTranslation } from "@hooks";
66
import { VoteContextWrapper } from "@organisms";
77
import { NodeObject } from "jsonld";
8+
import { openInNewTab } from "@utils";
9+
import { LINKS } from "@/consts/links";
810

911
type VoteContextChoiceProps = {
1012
setStep: Dispatch<SetStateAction<number>>;
@@ -26,6 +28,8 @@ export const VoteContextChoice = ({
2628
const { t } = useTranslation();
2729
const { isMobile } = useScreenDimension();
2830

31+
const openLink = () => openInNewTab(LINKS.STORING_INFORMATION_OFFLINE);
32+
2933
const handleStoreItMyself = () => {
3034
setStoreDataYourself(true);
3135
setStep(3);
@@ -42,23 +46,57 @@ export const VoteContextChoice = ({
4246
return (
4347
<VoteContextWrapper onCancel={onCancel} showContinueButton={false}>
4448
<Typography sx={{ textAlign: "center" }} variant="headline4">
45-
{t("createGovernanceAction.storeDataTitle")}
49+
{t("createGovernanceAction.storeAndMaintainDataTitle")}
50+
</Typography>
51+
<Link
52+
onClick={openLink}
53+
sx={{
54+
cursor: "pointer",
55+
fontSize: 16,
56+
fontWeight: 500,
57+
fontFamily: "Poppins",
58+
my: 4,
59+
textAlign: "center",
60+
textDecoration: "none",
61+
}}
62+
>
63+
{t("createGovernanceAction.learnMoreAboutStoringInformation")}
64+
</Link>
65+
<Typography fontWeight={400} sx={{ textAlign: "center" }} variant="body1">
66+
{t("createGovernanceAction.govToolProvidesOptions")}
67+
</Typography>
68+
<Box sx={{ my: 4 }}>
69+
<ul>
70+
<li>
71+
<Typography variant="body1">
72+
{t("createGovernanceAction.govToolCanPinToIPFS")}
73+
</Typography>
74+
</li>
75+
<li>
76+
<Typography variant="body1">
77+
{t("createGovernanceAction.storeYourselfInRepo")}
78+
</Typography>
79+
</li>
80+
</ul>
81+
</Box>
82+
<Typography sx={{ textAlign: "center" }} variant="body1">
83+
{t("createGovernanceAction.chooseDataStorageOption")}
4684
</Typography>
4785
<Spacer y={isMobile ? 4 : 6} />
48-
<Box sx={{ display: "flex", gap: 2 }}>
86+
<Box sx={{ display: "flex", gap: 2, width: "100%", justifyContent: "center" }}>
4987
<Button
5088
variant="outlined"
51-
onClick={handleStoreItMyself}
52-
sx={{ width: "100%" }}
89+
onClick={handleLetGovToolStore}
90+
sx={{ width: "250px", whiteSpace: "nowrap" }}
5391
>
54-
{t("createGovernanceAction.storeDataYourself")}
92+
{t("createGovernanceAction.govToolPinsDataToIPFS")}
5593
</Button>
5694
<Button
5795
variant="contained"
58-
onClick={handleLetGovToolStore}
59-
sx={{ width: "100%" }}
96+
onClick={handleStoreItMyself}
97+
sx={{ width: "250px", whiteSpace: "nowrap" }}
6098
>
61-
{t("createGovernanceAction.letGovToolStore")}
99+
{t("createGovernanceAction.downloadAndStoreYourself")}
62100
</Button>
63101
</Box>
64102
<Spacer y={isMobile ? 4 : 12.5} />

govtool/frontend/src/components/organisms/VoteContext/VoteContextGovTool.tsx

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
import { useEffect, Dispatch, SetStateAction, useState } from "react";
22
import { Box, Button, CircularProgress, Link, Typography } from "@mui/material";
3+
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
34
import { useMutation } from "react-query";
45

56
import { Spacer } from "@atoms";
67
import { useTranslation } from "@hooks";
78
import { VoteContextWrapper } from "@organisms";
89
import { postIpfs } from "@services";
9-
import { downloadTextFile } from "@utils";
10+
import { downloadTextFile, openInNewTab } from "@utils";
1011
import { NodeObject } from "jsonld";
1112
import { UseFormSetValue } from "react-hook-form";
1213
import { VoteContextFormValues } from "@hooks";
14+
import { LINKS } from "@/consts/links";
15+
import { ICONS } from "@/consts/icons";
16+
import { useSnackbar } from "@context";
17+
import { copyToClipboard } from "@utils";
1318

1419
interface PostIpfsResponse {
15-
ipfsHash: string;
20+
ipfsCid: string;
1621
}
1722

1823
type VoteContextGovToolProps = {
@@ -34,24 +39,29 @@ export const VoteContextGovTool = ({
3439
metadataHash,
3540
setValue,
3641
}: VoteContextGovToolProps) => {
37-
const [apiResponse, setApiResponse] = useState<string | null>(null);
42+
const [apiResponse, setApiResponse] = useState<PostIpfsResponse | null>(null);
43+
const [uploadInitiated, setUploadInitiated] = useState(false); // New state to track upload
3844
const { t } = useTranslation();
45+
const { addSuccessAlert } = useSnackbar();
46+
47+
const openLink = () => openInNewTab(LINKS.STORING_INFORMATION_OFFLINE);
3948

4049
const { mutate, isLoading } = useMutation<PostIpfsResponse, Error, { content: string }>({
4150
mutationFn: postIpfs,
4251
onSuccess: (data) => {
43-
const ipfsUrl = `ipfs://${data.ipfsHash}`;
52+
const ipfsUrl = `ipfs://${data.ipfsCid}`;
4453
setValue("storingURL", ipfsUrl);
4554
setSavedHash(metadataHash); // Set savedHash to metadataHash
46-
setApiResponse(JSON.stringify(data, null, 2));
55+
setApiResponse(data);
4756
},
4857
});
4958

5059
useEffect(() => {
51-
if (jsonldContent) {
60+
if (jsonldContent && !uploadInitiated) {
5261
mutate({ content: JSON.stringify(jsonldContent, null, 2) });
62+
setUploadInitiated(true); // Set flag after initiating upload
5363
}
54-
}, [jsonldContent, mutate]);
64+
}, [jsonldContent, mutate, uploadInitiated]);
5565

5666
const handleDownload = () => {
5767
if (jsonldContent) {
@@ -66,7 +76,33 @@ export const VoteContextGovTool = ({
6676
onCancel={onCancel}
6777
>
6878
<Typography sx={{ textAlign: "center" }} variant="h4">
69-
{t("createGovernanceAction.letGovToolStore")}
79+
{t("createGovernanceAction.rationalePinnedToIPFS")}
80+
</Typography>
81+
<Link
82+
onClick={openLink}
83+
sx={{
84+
cursor: "pointer",
85+
fontSize: 16,
86+
fontWeight: 500,
87+
fontFamily: "Poppins",
88+
my: 4,
89+
textAlign: "center",
90+
textDecoration: "none",
91+
}}
92+
>
93+
{t("createGovernanceAction.readFullGuide")}
94+
<OpenInNewIcon
95+
sx={{
96+
color: "primary",
97+
height: 17,
98+
width: 17,
99+
ml: 0.5,
100+
verticalAlign: "middle",
101+
}}
102+
/>
103+
</Link>
104+
<Typography sx={{ textAlign: "center" }} variant="h5">
105+
{t("createGovernanceAction.recommendations")}
70106
</Typography>
71107
<Spacer y={4} />
72108
{isLoading ? (
@@ -75,13 +111,38 @@ export const VoteContextGovTool = ({
75111
</Box>
76112
) : apiResponse ? (
77113
<>
78-
<Typography sx={{ whiteSpace: "pre-wrap", textAlign: "left" }}>
79-
{apiResponse}
114+
<Typography fontWeight={400} sx={{ textAlign: "center" }} variant="body1">
115+
{t("createGovernanceAction.downloadAndStoreMetadataFile")}
116+
</Typography>
117+
<Button
118+
data-testid="metadata-download-button"
119+
onClick={handleDownload}
120+
size="large"
121+
startIcon={<img alt="download" src={ICONS.download} />}
122+
sx={{ width: "fit-content", alignSelf: "center", my: 4 }}
123+
variant="outlined"
124+
>
125+
{t("govActions.voteContextFileName")}
126+
</Button>
127+
<Typography sx={{ textAlign: "center" }} variant="body1">
128+
{t("createGovernanceAction.rePinYourFile")}
80129
</Typography>
81-
<Spacer y={2} />
82-
<Link onClick={handleDownload} sx={{ cursor: "pointer" }}>
83-
{t("createGovernanceAction.downloadJsonLd")}
84-
</Link>
130+
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 1 }}>
131+
<Typography sx={{ textAlign: "center" }} variant="body1">
132+
{apiResponse.ipfsCid ? `ipfs://${apiResponse.ipfsCid}` : "[URI]"}
133+
</Typography>
134+
{apiResponse.ipfsCid && (
135+
<Link
136+
onClick={() => {
137+
copyToClipboard(`ipfs://${apiResponse.ipfsCid}`);
138+
addSuccessAlert(t("alerts.copiedToClipboard"));
139+
}}
140+
sx={{ cursor: "pointer", display: "flex", alignItems: "center" }}
141+
>
142+
<img alt="copy" src={ICONS.copyBlueIcon} style={{ width: 16, height: 16 }} />
143+
</Link>
144+
)}
145+
</Box>
85146
</>
86147
) : (
87148
<Typography sx={{ textAlign: "center" }} variant="body1">

govtool/frontend/src/i18n/locales/en.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,20 @@
246246
"storingInformationURLPlaceholder": "URL",
247247
"supportingLinks": "Supporting links",
248248
"title": "Create a Governance Action",
249+
"storeAndMaintainDataTitle": "Store and Maintain the Data Yourself",
250+
"learnMoreAboutStoringInformation": "Learn more about storing information",
251+
"govToolProvidesOptions": "GovTool currently provides two options for storing your rationale:",
252+
"govToolCanPinToIPFS": "GovTool can pin it to IPFS",
253+
"storeYourselfInRepo": "Store it yourself in a repository such as GitHub",
254+
"chooseDataStorageOption": "Choose a data storage option:",
255+
"govToolPinsDataToIPFS": "GovTool pins data to IPFS",
256+
"downloadAndStoreYourself": "Download and store yourself",
257+
"uploadingToIPFS": "Uploading to IPFS...",
258+
"rationalePinnedToIPFS": "Your rationale will be pinned to IPFS",
259+
"readFullGuide": "Read full guide",
260+
"recommendations": "Recommendations",
261+
"downloadAndStoreMetadataFile": "Download and store your metadata file\n(if you needed in the future you can re-pin it on IPFS)",
262+
"rePinYourFile": "Re-pin your file",
249263
"modals": {
250264
"submitTransactionSuccess": {
251265
"message": "Your Governance Action may take a little time to submit to the chain.",
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const copyToClipboard = (text: string) => {
2+
navigator.clipboard.writeText(text);
3+
};

govtool/frontend/src/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ export * from "./getBase64ImageDetails";
3939
export * from "./parseBoolean";
4040
export * from "./validateSignature";
4141
export * from "./cip8verification";
42+
export * from "./clipboard";

0 commit comments

Comments
 (0)