From a6ca482fe8b8a58d58440106ba80ffbc10ed8502 Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 18 Mar 2025 13:45:56 +0545 Subject: [PATCH 1/8] chore: change convertDRepToCIP129 to convertDRep and use for both conversion --- .../playwright/lib/helpers/dRep.ts | 18 +++++++++++++----- .../playwright/lib/pages/dRepDirectoryPage.ts | 14 +++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/helpers/dRep.ts b/tests/govtool-frontend/playwright/lib/helpers/dRep.ts index bbe9f56ff..40d9e694d 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/dRep.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/dRep.ts @@ -88,10 +88,14 @@ export function tohex(drepId: string) { ).toString("hex"); } -export function convertDRepToCIP129(drepId: string, script = false): string { +export function convertDRep( + drepId: string, + script = false +): { cip129: string; cip105: string } { const hexPattern = /^[0-9a-fA-F]+$/; let cip129DRep: string; let cip129DrepHex: string; + let cip105DRep: string; const prefix = script ? "23" : "22"; const addPrefix = (hex: string) => { if (hex.length === 56) { @@ -102,8 +106,8 @@ export function convertDRepToCIP129(drepId: string, script = false): string { throw new Error("Invalid DRep hex length"); } }; - const drepIdFromHex = (hex: string) => { - return fromHex("drep", hex); + const drepIdFromHex = (prefix: string, hex: string) => { + return fromHex(prefix, hex); }; if (hexPattern.test(drepId)) { cip129DrepHex = addPrefix(drepId); @@ -115,6 +119,10 @@ export function convertDRepToCIP129(drepId: string, script = false): string { throw new Error("Invalid DRep Bech32 format"); } } - cip129DRep = drepIdFromHex(cip129DrepHex); - return cip129DRep; + cip105DRep = drepIdFromHex( + cip129DrepHex.slice(0, 2) == "22" ? "drep" : "drep_script", + cip129DrepHex.slice(-56) + ); + cip129DRep = drepIdFromHex("drep", cip129DrepHex); + return { cip129: cip129DRep, cip105: cip105DRep }; } diff --git a/tests/govtool-frontend/playwright/lib/pages/dRepDirectoryPage.ts b/tests/govtool-frontend/playwright/lib/pages/dRepDirectoryPage.ts index 83dae3ba1..384863fb7 100644 --- a/tests/govtool-frontend/playwright/lib/pages/dRepDirectoryPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/dRepDirectoryPage.ts @@ -1,4 +1,4 @@ -import { convertDRepToCIP129 } from "@helpers/dRep"; +import { convertDRep } from "@helpers/dRep"; import { functionWaitedAssert, waitedLoop } from "@helpers/waitedLoop"; import { Locator, Page, expect } from "@playwright/test"; import { IDRep } from "@types"; @@ -156,8 +156,12 @@ export default class DRepDirectoryPage { const cip105DRepListFE = await this.getAllListedCIP105DRepIds(); const cip129DRepListFE = await this.getAllListedCIP129DRepIds(); - const cip129DRepListApi = dRepList.map((dRep) => - convertDRepToCIP129(dRep.drepId, dRep.isScriptBased) + const cip129DRepListApi = dRepList.map( + (dRep) => convertDRep(dRep.drepId, dRep.isScriptBased).cip129 + ); + + const cip105DRepListApi = dRepList.map( + (dRep) => convertDRep(dRep.drepId, dRep.isScriptBased).cip105 ); for (let i = 0; i <= cip105DRepListFE.length - 1; i++) { @@ -165,8 +169,8 @@ export default class DRepDirectoryPage { message: `Cip129 dRep Id from Api:${cip129DRepListApi[i]} is not equal to ${await cip129DRepListFE[i].textContent()} on sort ${option}`, }).toHaveText(cip129DRepListApi[i]); await expect(cip105DRepListFE[i], { - message: `Cip105 dRep Id from Api:${dRepList[i].view} is not equal to ${await cip105DRepListFE[i].textContent()} on sort ${option}`, - }).toHaveText(`(CIP-105) ${dRepList[i].view}`); + message: `Cip105 dRep Id from Api:${cip105DRepListApi} is not equal to ${await cip105DRepListFE[i].textContent()} on sort ${option}`, + }).toHaveText(`(CIP-105) ${cip105DRepListApi[i]}`); } }, { name: `frontend sort validation of ${option}` } From 3817a4afd6f149988ae500784ce2a4d321985760 Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 18 Mar 2025 13:49:11 +0545 Subject: [PATCH 2/8] test: add mock data and tests for converting script DRep to CIP-129/CIP-105 --- .../playwright/lib/_mock/scriptDRep.json | 28 +++++++++++++++++ .../tests/2-delegation/delegation.spec.ts | 31 ++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/govtool-frontend/playwright/lib/_mock/scriptDRep.json diff --git a/tests/govtool-frontend/playwright/lib/_mock/scriptDRep.json b/tests/govtool-frontend/playwright/lib/_mock/scriptDRep.json new file mode 100644 index 000000000..b07dacdd4 --- /dev/null +++ b/tests/govtool-frontend/playwright/lib/_mock/scriptDRep.json @@ -0,0 +1,28 @@ +{ + "page": 0, + "pageSize": 10, + "total": 1, + "elements": [ + { + "isScriptBased": true, + "drepId": "429b12461640cefd3a4a192f7c531d8f6c6d33610b727f481eb22d39", + "view": "drep1g2d3y3skgr806wj2ryhhc5ca3akx6vmppde87jq7kgknjmv589e", + "url": null, + "metadataHash": null, + "deposit": 500000000, + "votingPower": 83414740266257, + "status": "Active", + "type": "SoleVoter", + "latestTxHash": "8de2a5f9074679de947549ea36c3980496503ffc40f0cbce5ce1ee3df66306e9", + "latestRegistrationDate": "2024-11-20T01:59:20Z", + "metadataError": null, + "paymentAddress": null, + "givenName": null, + "objectives": null, + "motivations": null, + "qualifications": null, + "imageUrl": null, + "imageHash": null + } + ] +} diff --git a/tests/govtool-frontend/playwright/tests/2-delegation/delegation.spec.ts b/tests/govtool-frontend/playwright/tests/2-delegation/delegation.spec.ts index 9f83b7178..a12b44a48 100644 --- a/tests/govtool-frontend/playwright/tests/2-delegation/delegation.spec.ts +++ b/tests/govtool-frontend/playwright/tests/2-delegation/delegation.spec.ts @@ -1,7 +1,7 @@ import environments from "@constants/environments"; import { setAllureEpic } from "@helpers/allure"; import { skipIfNotHardFork } from "@helpers/cardano"; -import { fetchFirstActiveDRepDetails } from "@helpers/dRep"; +import { convertDRep, fetchFirstActiveDRepDetails } from "@helpers/dRep"; import { functionWaitedAssert } from "@helpers/waitedLoop"; import DRepDetailsPage from "@pages/dRepDetailsPage"; import DRepDirectoryPage from "@pages/dRepDirectoryPage"; @@ -27,6 +27,8 @@ const statusRank: Record = { Retired: 3, }; +const scripDRepId = require("../../lib/_mock/scriptDRep.json"); + test("2K_2. Should sort DReps", async ({ page }) => { test.slow(); @@ -223,3 +225,30 @@ test.describe("DRep dependent tests", () => { expect(copiedTextDRepDirectory).toEqual(dRepId); }); }); + +test("2Y. Should correctly convert CIP-129/CIP-105 script dRep", async ({ page }) => { + const dRepId = scripDRepId.elements[0]["drepId"]; + await page.route("**/drep/list?page=0&pageSize=10&**", async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/json", + body: JSON.stringify(scripDRepId), + }); + }); + + const responsePromise = page.waitForResponse( + "**/drep/list?page=0&pageSize=10&**" + ); + + const { cip129, cip105 } = convertDRep(dRepId, true); + + await page.goto(`/drep_directory/${dRepId}`); + await responsePromise; + + await expect( + page.getByTestId("cip-129-drep-id-info-item-description") + ).toHaveText(cip129, { timeout: 60_000 }); + await expect( + page.getByTestId("cip-105-drep-id-info-item-description") + ).toHaveText(cip105); +}); From 6ac3128a4eda9494a999047e7d9df1048f06e22b Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 18 Mar 2025 15:01:55 +0545 Subject: [PATCH 3/8] chore: check conversion for both script/ non-script drep --- .../govtool-frontend/playwright/lib/types.ts | 7 +++ .../tests/2-delegation/delegation.spec.ts | 55 +++++++++++-------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/types.ts b/tests/govtool-frontend/playwright/lib/types.ts index 4639885e7..84cc17c38 100644 --- a/tests/govtool-frontend/playwright/lib/types.ts +++ b/tests/govtool-frontend/playwright/lib/types.ts @@ -118,6 +118,13 @@ export enum FullGovernanceDRepVoteActionsType { export type DRepStatus = "Active" | "Inactive" | "Retired"; +export interface PaginatedDRepResponse { + page: number; + pageSize: number; + total: number; + elements: IDRep[]; +} + export type IDRep = { isScriptBased: boolean; drepId: string; diff --git a/tests/govtool-frontend/playwright/tests/2-delegation/delegation.spec.ts b/tests/govtool-frontend/playwright/tests/2-delegation/delegation.spec.ts index a12b44a48..1bab08af8 100644 --- a/tests/govtool-frontend/playwright/tests/2-delegation/delegation.spec.ts +++ b/tests/govtool-frontend/playwright/tests/2-delegation/delegation.spec.ts @@ -7,7 +7,7 @@ import DRepDetailsPage from "@pages/dRepDetailsPage"; import DRepDirectoryPage from "@pages/dRepDirectoryPage"; import { expect, Locator } from "@playwright/test"; import { test } from "@fixtures/walletExtension"; -import { DRepStatus, IDRep } from "@types"; +import { DRepStatus, IDRep, PaginatedDRepResponse } from "@types"; test.beforeEach(async () => { await setAllureEpic("2. Delegation"); @@ -27,7 +27,7 @@ const statusRank: Record = { Retired: 3, }; -const scripDRepId = require("../../lib/_mock/scriptDRep.json"); +const scripDRepId: PaginatedDRepResponse = require("../../lib/_mock/scriptDRep.json"); test("2K_2. Should sort DReps", async ({ page }) => { test.slow(); @@ -226,29 +226,40 @@ test.describe("DRep dependent tests", () => { }); }); -test("2Y. Should correctly convert CIP-129/CIP-105 script dRep", async ({ page }) => { - const dRepId = scripDRepId.elements[0]["drepId"]; - await page.route("**/drep/list?page=0&pageSize=10&**", async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/json", - body: JSON.stringify(scripDRepId), +Object.values(["script drep", "drep"]).forEach((type, index) => { + test(`2Y_${index + 1}. Should correctly convert CIP-129/CIP-105 ${type}`, async ({ + page, + }) => { + const dRepId = scripDRepId.elements[0]["drepId"]; + const dRepResponse = { + ...scripDRepId, + elements: [{ ...scripDRepId.elements[0], isScriptBased: false }], + }; + await page.route("**/drep/list?page=0&pageSize=10&**", async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/json", + body: JSON.stringify(type === "drep" ? dRepResponse : scripDRepId), + }); }); - }); - const responsePromise = page.waitForResponse( - "**/drep/list?page=0&pageSize=10&**" - ); + const responsePromise = page.waitForResponse( + "**/drep/list?page=0&pageSize=10&**" + ); - const { cip129, cip105 } = convertDRep(dRepId, true); + const { cip129, cip105 } = convertDRep( + dRepId, + type === "drep" ? false : true + ); - await page.goto(`/drep_directory/${dRepId}`); - await responsePromise; + await page.goto(`/drep_directory/${dRepId}`); + await responsePromise; - await expect( - page.getByTestId("cip-129-drep-id-info-item-description") - ).toHaveText(cip129, { timeout: 60_000 }); - await expect( - page.getByTestId("cip-105-drep-id-info-item-description") - ).toHaveText(cip105); + await expect( + page.getByTestId("cip-129-drep-id-info-item-description") + ).toHaveText(cip129, { timeout: 60_000 }); + await expect( + page.getByTestId("cip-105-drep-id-info-item-description") + ).toHaveText(cip105); + }); }); From c62cf0d7cfc9e6f39c0d515a646c5c6e480336b5 Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 19 Mar 2025 10:44:59 +0545 Subject: [PATCH 4/8] fix: vote assertion check issue on revote with updated context --- .../5-proposal-functionality/proposalFunctionality.dRep.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts index fb0bf4c96..0ad6f67b4 100644 --- a/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts +++ b/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts @@ -264,7 +264,7 @@ test.describe("Perform voting", () => { window.scrollTo(0, 500) ); await expect( - govActionDetailsPage.currentPage.getByTestId("my-vote").getByText("No"), + govActionDetailsPage.currentPage.getByTestId("my-vote").getByText("Yes"), { message: !isYesVoteVisible && From 472834cbaf964e3b23f1bc6c97987fdc29407dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 19 Mar 2025 13:37:07 +0100 Subject: [PATCH 5/8] fix: filtering drep votes --- govtool/backend/src/VVA/API.hs | 16 +++++++++------- govtool/backend/src/VVA/DRep.hs | 6 ++---- govtool/backend/src/VVA/Types.hs | 17 +++++++++-------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs index 5bfbd304d..7b9d0fe4c 100644 --- a/govtool/backend/src/VVA/API.hs +++ b/govtool/backend/src/VVA/API.hs @@ -283,18 +283,20 @@ getVotes (unHexText -> dRepId) selectedTypes sortMode mSearch = do CacheEnv {dRepGetVotesCache} <- asks vvaCache (votes, proposals) <- cacheRequest dRepGetVotesCache dRepId $ DRep.getVotes dRepId [] - let voteMap = Map.fromList $ map (\vote@Types.Vote {..} -> (voteProposalId, vote)) votes - - processedProposals <- filter (isProposalSearchedFor mSearch) <$> mapSortAndFilterProposals selectedTypes sortMode proposals - + let voteMapByTxHash = Map.fromList $ + map (\vote -> (pack $ Prelude.takeWhile (/= '#') (unpack $ Types.voteGovActionId vote), vote)) votes + + processedProposals <- filter (isProposalSearchedFor mSearch) <$> + mapSortAndFilterProposals selectedTypes sortMode proposals + return $ [ VoteResponse { voteResponseVote = voteToResponse vote , voteResponseProposal = proposalResponse } - | proposalResponse@ProposalResponse{proposalResponseId} <- processedProposals - , let proposalIdInt = read (unpack proposalResponseId) :: Int - , Just vote <- [Map.lookup (toInteger proposalIdInt) voteMap] + | proposalResponse <- processedProposals + , let txHash = unHexText (proposalResponseTxHash proposalResponse) + , Just vote <- [Map.lookup txHash voteMapByTxHash] ] drepInfo :: App m => HexText -> m DRepInfoResponse diff --git a/govtool/backend/src/VVA/DRep.hs b/govtool/backend/src/VVA/DRep.hs index 187cdc73d..16f6d70d0 100644 --- a/govtool/backend/src/VVA/DRep.hs +++ b/govtool/backend/src/VVA/DRep.hs @@ -115,16 +115,14 @@ getVotes :: m ([Vote], [Proposal]) getVotes drepId selectedProposals = withPool $ \conn -> do results <- liftIO $ SQL.query conn getVotesSql (SQL.Only drepId) - + if null results then return ([], []) else do let proposalsToSelect = if null selectedProposals then [ govActionId | (_, govActionId, _, _, _, _, _, _, _) <- results] else selectedProposals - allProposals <- mapM (Proposal.getProposals . Just . (:[])) proposalsToSelect - let proposals = concat allProposals let proposalMap = M.fromList $ map (\x -> (proposalId x, x)) proposals @@ -132,7 +130,7 @@ getVotes drepId selectedProposals = withPool $ \conn -> do timeZone <- liftIO getCurrentTimeZone let votes = - [ Vote proposalId' drepId' vote' url' docHash' epochNo' (localTimeToUTC timeZone date') voteTxHash' + [ Vote proposalId' govActionId' drepId' vote' url' docHash' epochNo' (localTimeToUTC timeZone date') voteTxHash' | (proposalId', govActionId', drepId', vote', url', docHash', epochNo', date', voteTxHash') <- results , govActionId' `elem` proposalsToSelect ] diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs index 5d1f3ca5f..5af17aa16 100644 --- a/govtool/backend/src/VVA/Types.hs +++ b/govtool/backend/src/VVA/Types.hs @@ -61,14 +61,15 @@ instance Exception AppError data Vote = Vote - { voteProposalId :: Integer - , voteDrepId :: Text - , voteVote :: Text - , voteUrl :: Maybe Text - , voteDocHash :: Maybe Text - , voteEpochNo :: Integer - , voteDate :: UTCTime - , voteTxHash :: Text + { voteProposalId :: Integer + , voteGovActionId :: Text + , voteDrepId :: Text + , voteVote :: Text + , voteUrl :: Maybe Text + , voteDocHash :: Maybe Text + , voteEpochNo :: Integer + , voteDate :: UTCTime + , voteTxHash :: Text } data DRepInfo From f510e4b18616a915b9fe36baf603a98a6cb4a41a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 19 Mar 2025 15:06:46 +0100 Subject: [PATCH 6/8] fix(#3242): fix redirection after vote --- CHANGELOG.md | 3 +- .../organisms/DashboardGovernanceActions.tsx | 32 +++++++++++++++-- .../DashboardGovernanceActionsVotedOn.tsx | 34 ++++++++----------- .../src/hooks/queries/useGetDRepVotesQuery.ts | 2 ++ .../src/hooks/queries/useGetProposalsQuery.ts | 13 +++---- govtool/frontend/src/types/global.d.ts | 3 +- 6 files changed, 54 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5c444349..6853205ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,13 +14,14 @@ changes. ### Fixed +- Fix post-vote navigation to governance action list [Issue 3242](https://github.com/IntersectMBO/govtool/issues/3242) + ### Changed ### Removed ## [v2.0.17](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.17) 2025-03-18 - ### Added ### Fixed diff --git a/govtool/frontend/src/components/organisms/DashboardGovernanceActions.tsx b/govtool/frontend/src/components/organisms/DashboardGovernanceActions.tsx index 6c246b929..b1b4f80e1 100644 --- a/govtool/frontend/src/components/organisms/DashboardGovernanceActions.tsx +++ b/govtool/frontend/src/components/organisms/DashboardGovernanceActions.tsx @@ -10,6 +10,7 @@ import { } from "@consts"; import { useCardano, useDataActionsBar, useFeatureFlag } from "@context"; import { + useGetDRepVotesQuery, useGetProposalsQuery, useGetVoterInfo, useScreenDimension, @@ -89,6 +90,31 @@ export const DashboardGovernanceActions = () => { searchPhrase: debouncedSearchText, enabled: !isAdjusting, }); + const { data: votes, areDRepVotesLoading } = useGetDRepVotesQuery( + queryFilters, + chosenSorting, + debouncedSearchText, + ); + + // TODO: Black magic - that filtering should be done on the backend + const filteredProposals = proposals + ?.map((proposalCategory) => { + const filteredActions = proposalCategory.actions.filter((action) => { + const hasVote = votes?.some((voteCategory) => + voteCategory.actions.some( + (voteAction) => voteAction.proposal.txHash === action.txHash, + ), + ); + + return !hasVote; + }); + + return { + ...proposalCategory, + actions: filteredActions, + }; + }) + .filter((category) => category.actions.length > 0); const { state } = useLocation(); const [content, setContent] = useState( @@ -189,14 +215,14 @@ export const DashboardGovernanceActions = () => { onDashboard searchPhrase={debouncedSearchText} sorting={chosenSorting} - proposals={proposals} + proposals={filteredProposals} /> diff --git a/govtool/frontend/src/components/organisms/DashboardGovernanceActionsVotedOn.tsx b/govtool/frontend/src/components/organisms/DashboardGovernanceActionsVotedOn.tsx index 5d4dcf134..552f63061 100644 --- a/govtool/frontend/src/components/organisms/DashboardGovernanceActionsVotedOn.tsx +++ b/govtool/frontend/src/components/organisms/DashboardGovernanceActionsVotedOn.tsx @@ -2,38 +2,34 @@ import { useMemo } from "react"; import { Box, Typography, CircularProgress } from "@mui/material"; import { useCardano } from "@context"; -import { - useGetDRepVotesQuery, - useScreenDimension, - useTranslation, -} from "@hooks"; +import { useScreenDimension, useTranslation } from "@hooks"; import { GovernanceVotedOnCard } from "@molecules"; import { Slider } from "@organisms"; import { getFullGovActionId, getProposalTypeLabel } from "@utils"; +import { VotedProposal } from "@/models"; type DashboardGovernanceActionsVotedOnProps = { - filters: string[]; searchPhrase?: string; - sorting: string; + votes: { + title: string; + actions: VotedProposal[]; + }[]; + areDRepVotesLoading: boolean; }; export const DashboardGovernanceActionsVotedOn = ({ - filters, searchPhrase, - sorting, + votes, + areDRepVotesLoading, }: DashboardGovernanceActionsVotedOnProps) => { - const { data, areDRepVotesLoading } = useGetDRepVotesQuery( - filters, - sorting, - searchPhrase, - ); const { isMobile } = useScreenDimension(); const { pendingTransaction } = useCardano(); const { t } = useTranslation(); + // TODO: Filtering here is some kind of craziness. It should be done on the backend. const filteredData = useMemo(() => { - if (data.length && searchPhrase) { - return data + if (votes.length && searchPhrase) { + return votes .map((entry) => ({ ...entry, actions: entry.actions.filter((action) => @@ -44,8 +40,8 @@ export const DashboardGovernanceActionsVotedOn = ({ })) .filter((entry) => entry.actions?.length > 0); } - return data; - }, [data, searchPhrase, pendingTransaction.vote]); + return votes; + }, [votes, searchPhrase, pendingTransaction.vote]); return areDRepVotesLoading ? ( @@ -53,7 +49,7 @@ export const DashboardGovernanceActionsVotedOn = ({ ) : ( <> - {!data.length ? ( + {!votes.length ? ( {t("govActions.youHaventVotedYet")} diff --git a/govtool/frontend/src/hooks/queries/useGetDRepVotesQuery.ts b/govtool/frontend/src/hooks/queries/useGetDRepVotesQuery.ts index bec791c61..0878191bc 100644 --- a/govtool/frontend/src/hooks/queries/useGetDRepVotesQuery.ts +++ b/govtool/frontend/src/hooks/queries/useGetDRepVotesQuery.ts @@ -30,6 +30,8 @@ export const useGetDRepVotesQuery = ( }, }), enabled: !!dRepID, + refetchOnWindowFocus: true, + keepPreviousData: true, }); const groupedByType = data?.reduce((groups, item) => { diff --git a/govtool/frontend/src/hooks/queries/useGetProposalsQuery.ts b/govtool/frontend/src/hooks/queries/useGetProposalsQuery.ts index 6843f76af..0ebbe8677 100644 --- a/govtool/frontend/src/hooks/queries/useGetProposalsQuery.ts +++ b/govtool/frontend/src/hooks/queries/useGetProposalsQuery.ts @@ -12,7 +12,7 @@ export const useGetProposalsQuery = ({ sorting, enabled, }: GetProposalsArguments) => { - const { dRepID, pendingTransaction } = useCardano(); + const { dRepID } = useCardano(); const { voter } = useGetVoterInfo(); const fetchProposals = async (): Promise => { @@ -34,17 +34,12 @@ export const useGetProposalsQuery = ({ }; const { data, isLoading } = useQuery( - [ - QUERY_KEYS.useGetProposalsKey, - filters, - searchPhrase, - sorting, - dRepID, - pendingTransaction.vote?.transactionHash, - ], + [QUERY_KEYS.useGetProposalsKey, filters, searchPhrase, sorting, dRepID], fetchProposals, { enabled, + refetchOnWindowFocus: true, + keepPreviousData: true, }, ); diff --git a/govtool/frontend/src/types/global.d.ts b/govtool/frontend/src/types/global.d.ts index 7f990a3d3..8e8ebaea5 100644 --- a/govtool/frontend/src/types/global.d.ts +++ b/govtool/frontend/src/types/global.d.ts @@ -14,6 +14,7 @@ declare global { type ActionTypeFromAPI = { id: string; + txHash: string; type: string; details: string; expiryDate: string; @@ -36,7 +37,7 @@ declare global { type ToVoteDataType = { title: string; - actions: ActionTypeToDsiplay[]; + actions: ProposalData[]; }[]; type NestedKeys = T extends Record From d20d0c5ddf2fdf0e8e1489227c6318d1184f6159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Thu, 20 Mar 2025 14:59:33 +0100 Subject: [PATCH 7/8] feat(#3230): redirect to outcomes from voting pillar --- CHANGELOG.md | 2 ++ .../DashboardGovernanceActionDetails.tsx | 17 +++++++++++++++-- .../src/hooks/queries/useGetProposalQuery.ts | 3 ++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6853205ed..4acdcebcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ changes. ### Added +- Add redirection to outcomes when proposal is not found [Issue 3230](https://github.com/IntersectMBO/govtool/issues/3230) + ### Fixed - Fix post-vote navigation to governance action list [Issue 3242](https://github.com/IntersectMBO/govtool/issues/3242) diff --git a/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx b/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx index d7dd7be60..d5ffa61c2 100644 --- a/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx +++ b/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx @@ -1,3 +1,4 @@ +import { useEffect } from "react"; import { useNavigate, useLocation, @@ -5,8 +6,9 @@ import { generatePath, } from "react-router-dom"; import { Box, CircularProgress, Link, Typography } from "@mui/material"; +import { AxiosError } from "axios"; -import { ICONS, PATHS } from "@consts"; +import { ICONS, OUTCOMES_PATHS, PATHS } from "@consts"; import { useCardano } from "@context"; import { useGetProposalQuery, @@ -42,13 +44,24 @@ export const DashboardGovernanceActionDetails = () => { const shortenedGovActionId = txHash && getShortenedGovActionId(txHash, +index); - const { data, isLoading } = useGetProposalQuery( + const { data, isLoading, error } = useGetProposalQuery( fullProposalId ?? "", !state?.proposal || !state?.vote, ); const proposal = (data ?? state)?.proposal; const vote = (data ?? state)?.vote; + useEffect(() => { + const isProposalNotFound = + (error as AxiosError)?.response?.data === + `Proposal with id: ${fullProposalId} not found`; + if (isProposalNotFound && fullProposalId) { + navigate( + OUTCOMES_PATHS.governanceActionOutcomes.replace(":id", fullProposalId), + ); + } + }, [error]); + return ( { const { dRepID } = useCardano(); - const { data, isLoading, refetch, isRefetching } = useQuery( + const { data, isLoading, refetch, isRefetching, error } = useQuery( [QUERY_KEYS.useGetProposalKey, dRepID, proposalId], () => getProposal(proposalId, dRepID), { @@ -21,5 +21,6 @@ export const useGetProposalQuery = (proposalId: string, enabled?: boolean) => { isLoading, refetch, isFetching: isRefetching, + error, }; }; From 662847213e6958eb6de08d1eb1d14c912c1cd2e3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:37:10 +0000 Subject: [PATCH 8/8] chore: update GovTool to v2.0.18 --- CHANGELOG.md | 11 +++++++++++ govtool/backend/Dockerfile | 2 +- govtool/backend/Dockerfile.qovery | 2 +- govtool/backend/vva-be.cabal | 2 +- govtool/frontend/package-lock.json | 4 ++-- govtool/frontend/package.json | 2 +- govtool/metadata-validation/package-lock.json | 4 ++-- govtool/metadata-validation/package.json | 2 +- govtool/metadata-validation/src/main.ts | 2 +- 9 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4acdcebcd..61f6b9e84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,17 @@ changes. ## [Unreleased] +### Added + +### Fixed + +### Changed + +### Removed + +## [v2.0.18](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.18) 2025-03-20 + + ### Added - Add redirection to outcomes when proposal is not found [Issue 3230](https://github.com/IntersectMBO/govtool/issues/3230) diff --git a/govtool/backend/Dockerfile b/govtool/backend/Dockerfile index 768cfd7cf..cd0b1ac6c 100644 --- a/govtool/backend/Dockerfile +++ b/govtool/backend/Dockerfile @@ -4,4 +4,4 @@ FROM $BASE_IMAGE_REPO:$BASE_IMAGE_TAG WORKDIR /src COPY . . RUN cabal build -RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.17/x/vva-be/build/vva-be/vva-be /usr/local/bin +RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.18/x/vva-be/build/vva-be/vva-be /usr/local/bin diff --git a/govtool/backend/Dockerfile.qovery b/govtool/backend/Dockerfile.qovery index 53a840711..b698475e0 100644 --- a/govtool/backend/Dockerfile.qovery +++ b/govtool/backend/Dockerfile.qovery @@ -4,7 +4,7 @@ FROM $BASE_IMAGE_REPO:$BASE_IMAGE_TAG WORKDIR /src COPY . . RUN cabal build -RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.17/x/vva-be/build/vva-be/vva-be /usr/local/bin +RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.18/x/vva-be/build/vva-be/vva-be /usr/local/bin # Expose the necessary port EXPOSE 9876 diff --git a/govtool/backend/vva-be.cabal b/govtool/backend/vva-be.cabal index 704f1d705..fe757d486 100644 --- a/govtool/backend/vva-be.cabal +++ b/govtool/backend/vva-be.cabal @@ -1,6 +1,6 @@ cabal-version: 3.6 name: vva-be -version: 2.0.17 +version: 2.0.18 -- A short (one-line) description of the package. -- synopsis: diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 9eb541707..62274e080 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "@govtool/frontend", - "version": "2.0.17", + "version": "2.0.18", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@govtool/frontend", - "version": "2.0.17", + "version": "2.0.18", "hasInstallScript": true, "dependencies": { "@emotion/react": "^11.11.1", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index ca68f3066..4f9ba9651 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -1,7 +1,7 @@ { "name": "@govtool/frontend", "private": true, - "version": "2.0.17", + "version": "2.0.18", "type": "module", "scripts": { "build": "vite build", diff --git a/govtool/metadata-validation/package-lock.json b/govtool/metadata-validation/package-lock.json index c13718059..38b4d2ba5 100644 --- a/govtool/metadata-validation/package-lock.json +++ b/govtool/metadata-validation/package-lock.json @@ -1,12 +1,12 @@ { "name": "@govtool/metadata-validation", - "version": "2.0.17", + "version": "2.0.18", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@govtool/metadata-validation", - "version": "2.0.17", + "version": "2.0.18", "license": "UNLICENSED", "dependencies": { "@nestjs/axios": "^3.0.2", diff --git a/govtool/metadata-validation/package.json b/govtool/metadata-validation/package.json index 693b2c7ca..ac5a8ec96 100644 --- a/govtool/metadata-validation/package.json +++ b/govtool/metadata-validation/package.json @@ -1,6 +1,6 @@ { "name": "@govtool/metadata-validation", - "version": "2.0.17", + "version": "2.0.18", "description": "", "author": "", "private": true, diff --git a/govtool/metadata-validation/src/main.ts b/govtool/metadata-validation/src/main.ts index d6656ba7e..5d1d15d80 100644 --- a/govtool/metadata-validation/src/main.ts +++ b/govtool/metadata-validation/src/main.ts @@ -13,7 +13,7 @@ async function bootstrap() { const config = new DocumentBuilder() .setTitle('Metadata Validation Tool') .setDescription('The Metadata Validation Tool API description') - .setVersion("2.0.17") + .setVersion("2.0.18") .build(); const document = SwaggerModule.createDocument(app, config);