From 3c4585e9b8b1b58dd6c41e8947d4acddd4865ce2 Mon Sep 17 00:00:00 2001 From: Ciabas Date: Fri, 16 May 2025 11:19:59 +0200 Subject: [PATCH 01/75] chore: update .gitignores to clarify tool version management file exclusion --- govtool/backend/.gitignore | 3 +++ govtool/frontend/.gitignore | 5 ++++- govtool/metadata-validation/.gitignore | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/govtool/backend/.gitignore b/govtool/backend/.gitignore index 148b93507..541110bca 100644 --- a/govtool/backend/.gitignore +++ b/govtool/backend/.gitignore @@ -1,3 +1,6 @@ # other .vscode dev-config.json + +# Tool version management file (e.g., asdf version manager) +.tool-versions diff --git a/govtool/frontend/.gitignore b/govtool/frontend/.gitignore index ba36087a4..e32feec72 100644 --- a/govtool/frontend/.gitignore +++ b/govtool/frontend/.gitignore @@ -6,4 +6,7 @@ /.lighthouseci /yarn-error.log .env -coverage \ No newline at end of file +coverage + +# Tool version management file (e.g., asdf version manager) +.tool-versions diff --git a/govtool/metadata-validation/.gitignore b/govtool/metadata-validation/.gitignore index 4b56acfbe..b0c0e90e0 100644 --- a/govtool/metadata-validation/.gitignore +++ b/govtool/metadata-validation/.gitignore @@ -54,3 +54,6 @@ pids # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Tool version management file (e.g., asdf version manager) +.tool-versions From c4eb4f47ebebb625d89507720b9d4d07c9b7b960 Mon Sep 17 00:00:00 2001 From: Niraj Date: Mon, 19 May 2025 12:01:42 +0545 Subject: [PATCH 02/75] feat: add updateWalletGivenName method to WalletManager for updating wallet names --- .../govtool-frontend/playwright/lib/walletManager.ts | 10 ++++++++++ .../govtool-frontend/playwright/tests/dRep.setup.ts | 8 +++----- .../playwright/tests/proposal-budget.dRep.setup.ts | 12 +++++++----- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/walletManager.ts b/tests/govtool-frontend/playwright/lib/walletManager.ts index 53192e886..23842a22d 100644 --- a/tests/govtool-frontend/playwright/lib/walletManager.ts +++ b/tests/govtool-frontend/playwright/lib/walletManager.ts @@ -65,5 +65,15 @@ class WalletManager { return await LockInterceptor.intercept("tempWallets", popCb); } + + async updateWalletGivenName(address: string, givenName: string) { + const wallets: StaticWallet[] = (await getFile("wallets.json")) ?? []; + wallets.map((wallet: StaticWallet) => { + if (wallet.address === address) { + wallet.givenName = givenName; + } + }); + await createFile("wallets.json", wallets); + } } export default WalletManager.getInstance(); diff --git a/tests/govtool-frontend/playwright/tests/dRep.setup.ts b/tests/govtool-frontend/playwright/tests/dRep.setup.ts index afb3c798c..584120038 100644 --- a/tests/govtool-frontend/playwright/tests/dRep.setup.ts +++ b/tests/govtool-frontend/playwright/tests/dRep.setup.ts @@ -45,11 +45,9 @@ setup("Register DRep of static wallets", async () => { const metadataPromises = dRepWallets.map(async (dRepWallet) => { const metadataResponse = await uploadMetadataAndGetJsonHash(); const givenName = metadataResponse.givenName; - const index = dRepWallets.indexOf(dRepWallet); - dRepWallets[index] = { - ...dRepWallet, - givenName, - }; + + await walletManager.updateWalletGivenName(dRepWallet.address, givenName); + return { ...metadataResponse, wallet: dRepWallet, diff --git a/tests/govtool-frontend/playwright/tests/proposal-budget.dRep.setup.ts b/tests/govtool-frontend/playwright/tests/proposal-budget.dRep.setup.ts index 0a91e509a..78191ad17 100644 --- a/tests/govtool-frontend/playwright/tests/proposal-budget.dRep.setup.ts +++ b/tests/govtool-frontend/playwright/tests/proposal-budget.dRep.setup.ts @@ -11,6 +11,7 @@ import { expect } from "@playwright/test"; import { test as setup } from "@fixtures/walletExtension"; import kuberService from "@services/kuberService"; +import walletManager from "lib/walletManager"; setup.beforeEach(async () => { await setAllureEpic("Setup"); @@ -28,11 +29,12 @@ setup("Register DRep of proposal budget static wallets", async () => { async (dRepWallet) => { const metadataResponse = await uploadMetadataAndGetJsonHash(); const givenName = metadataResponse.givenName; - const index = dRepWallets.indexOf(dRepWallet); - dRepWallets[index] = { - ...dRepWallet, - givenName, - }; + + await walletManager.updateWalletGivenName( + dRepWallet.address, + givenName + ); + return { ...metadataResponse, wallet: dRepWallet, From bb4556e5eb2ac3d7dde346fd1f4e216ed1f21553 Mon Sep 17 00:00:00 2001 From: Niraj Date: Mon, 19 May 2025 12:01:54 +0545 Subject: [PATCH 03/75] fix: update DRep comment visibility checks in proposal budget tests --- .../proposalBudget.dRep.pb.spec.ts | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts index 8e38001f0..cc71001f4 100644 --- a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts +++ b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts @@ -100,25 +100,17 @@ test.describe("Budget proposal dRep behaviour", () => { .locator('[data-testid^="comment-"][data-testid$="-content-card"]') .first(); - await expect( - dRepCommentedCard.getByText("DRep", { exact: true }) - ).toBeVisible(); - - const isDRepGivenNameVisible = await dRepCommentedCard - .getByTestId("given-name") - .isVisible(); - - expect( - isDRepGivenNameVisible, - !isDRepGivenNameVisible && "Missing given-name testId" - ).toBeTruthy(); + await expect(dRepCommentedCard.getByTestId("dRep-tag")).toBeVisible(); - await expect(dRepCommentedCard.getByTestId("given-name")).toHaveText( - dRep03Wallet.givenName + await expect(dRepCommentedCard.getByTestId("dRep-given-name")).toHaveText( + dRep03Wallet.givenName, + { timeout: 60_000 } ); - await expect(dRepCommentedCard.getByTestId("drep-id")).toHaveText( - dRep03Wallet.dRepId - ); + const dRepIdWithoutDotted = ( + await dRepCommentedCard.getByTestId("dRep-id").textContent() + ).replace(/\./g, ""); + + expect(dRep03Wallet.dRepId).toContain(dRepIdWithoutDotted); }); }); From 891e91835282ebdc2a6092b0788bc3e3c1e6ac13 Mon Sep 17 00:00:00 2001 From: Niraj Date: Mon, 19 May 2025 12:10:15 +0545 Subject: [PATCH 04/75] fix: costing rejection test by focusing to display error message --- .../playwright/lib/pages/budgetDiscussionSubmissionPage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts index b37520f54..bdb67e20c 100644 --- a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts @@ -391,10 +391,10 @@ export default class BudgetDiscussionSubmissionPage { await this.usaToAdaCnversionRateInput.fill( costing.usdToAdaConversionRate.toString() ); - await this.costBreakdownInput.fill(costing.costBreakdown); await this.preferredCurrencyInput.fill( costing.AmountInPreferredCurrency.toString() ); + await this.costBreakdownInput.fill(costing.costBreakdown); } async fillupCostingForm(costing: BudgetCostingProps) { From d011b9a11bbbeb5633603faf1bcfaeddda912dee Mon Sep 17 00:00:00 2001 From: Niraj Date: Mon, 19 May 2025 12:17:54 +0545 Subject: [PATCH 05/75] fix: trim whitespace in proposal title search assertion --- .../tests/8-proposal-discussion/proposalDiscussion.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts index e4303ae9b..cdecc19cc 100644 --- a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts +++ b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts @@ -119,7 +119,7 @@ test("8C. Should search the list of proposed governance actions.", async ({ const proposalTitle = await proposalCard .locator('[data-testid^="proposal-"][data-testid$="-title"]') .innerText(); - expect(proposalTitle).toContain(proposalName); + expect(proposalTitle.trim()).toContain(proposalName.trim()); } }, { From 6396e297181229b0b8a4aa30c3fa15b68911fc73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Mon, 19 May 2025 11:27:19 +0200 Subject: [PATCH 06/75] chore: add outcomes and pdf-ui version tags to sentry --- .../organisms/RegisterAsDRepSteps/WhatRetirementMeans.tsx | 6 +----- govtool/frontend/src/context/appContext.tsx | 3 --- govtool/frontend/src/context/governanceAction.tsx | 5 ----- govtool/frontend/src/main.tsx | 6 ++++++ 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/WhatRetirementMeans.tsx b/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/WhatRetirementMeans.tsx index 2f3421839..3ea078657 100644 --- a/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/WhatRetirementMeans.tsx +++ b/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/WhatRetirementMeans.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useState } from "react"; import * as Sentry from "@sentry/react"; import { Typography } from "@atoms"; @@ -35,10 +35,6 @@ export const WhatRetirementMeans = ({ closeModal(); }; - useEffect(() => { - Sentry.setTag("component_name", "WhatRetirementMeans"); - }, []); - const retireAsDrep = useCallback(async () => { try { setIsRetirementLoading(true); diff --git a/govtool/frontend/src/context/appContext.tsx b/govtool/frontend/src/context/appContext.tsx index dff1684f1..568ebb067 100644 --- a/govtool/frontend/src/context/appContext.tsx +++ b/govtool/frontend/src/context/appContext.tsx @@ -39,9 +39,6 @@ const AppContext = createContext(null); * @param children - The child components to render. */ const AppContextProvider = ({ children }: PropsWithChildren) => { - useEffect(() => { - Sentry.setTag("component_name", "AppContextProvider"); - }, []); const { fetchEpochParams, epochParams } = useGetEpochParams(); const { fetchNetworkInfo, networkInfo } = useGetNetworkInfo(); diff --git a/govtool/frontend/src/context/governanceAction.tsx b/govtool/frontend/src/context/governanceAction.tsx index ecb94c6c0..112513d45 100644 --- a/govtool/frontend/src/context/governanceAction.tsx +++ b/govtool/frontend/src/context/governanceAction.tsx @@ -4,7 +4,6 @@ import { createContext, useContext, useCallback, - useEffect, } from "react"; import { NodeObject } from "jsonld"; import { blake2bHex } from "blakejs"; @@ -43,10 +42,6 @@ const GovernanceActionProvider = ({ children }: PropsWithChildren) => { * @returns The JSON-LD representation of the governance action. */ - useEffect(() => { - Sentry.setTag("component_name", "GovernanceActionProvider"); - }, []); - const createGovernanceActionJsonLD = useCallback( async (govActionMetadata: GovActionMetadata) => { try { diff --git a/govtool/frontend/src/main.tsx b/govtool/frontend/src/main.tsx index f9b4a9a7f..469c54445 100644 --- a/govtool/frontend/src/main.tsx +++ b/govtool/frontend/src/main.tsx @@ -54,6 +54,12 @@ Sentry.init({ }, }); +Sentry.setTag("pdf_ui_version", pkg.dependencies["@intersect.mbo/pdf-ui"]); +Sentry.setTag( + "govtool_outcomes_pillar_ui_version", + pkg.dependencies["@intersect.mbo/govtool-outcomes-pillar-ui"], +); + ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( From 0b23e80bce62dc96b345a0b0a65e8dbda94335ca Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 20 May 2025 13:10:24 +0545 Subject: [PATCH 07/75] fix: increase timeout for visibility checks in DRep tests --- .../tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts | 6 ++++-- .../tests/3-drep-registration/dRepRegistration.dRep.spec.ts | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts index cc71001f4..db17b101a 100644 --- a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts +++ b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts @@ -35,7 +35,9 @@ test.describe("Budget proposal dRep behaviour", () => { await budgetDiscussionDetailsPage.voteOnPoll(choice); - await expect(budgetDiscussionDetailsPage.pollYesBtn).not.toBeVisible(); + await expect(budgetDiscussionDetailsPage.pollYesBtn).not.toBeVisible({ + timeout: 60_000, + }); await expect(budgetDiscussionDetailsPage.pollNoBtn).not.toBeVisible(); await expect( budgetDiscussionDetailsPage.currentPage.getByTestId( @@ -59,7 +61,7 @@ test.describe("Budget proposal dRep behaviour", () => { await budgetDiscussionDetailsPage.voteOnPoll(choice); await budgetDiscussionDetailsPage.changePollVote(); - await expect(budgetDiscussionDetailsPage.pollYesBtn).not.toBeVisible(); + await expect(budgetDiscussionDetailsPage.pollYesBtn).not.toBeVisible({timeout: 60_000}); await expect(budgetDiscussionDetailsPage.pollNoBtn).not.toBeVisible(); // vote must be changed diff --git a/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts index 91fb769dd..1e1bdcbfa 100644 --- a/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts +++ b/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts @@ -222,7 +222,7 @@ test.describe("Temporary DReps", () => { await dRepPage.getByTestId("continue-retirement-button").click(); await expect( dRepPage.getByTestId("retirement-transaction-submitted-modal") - ).toBeVisible({ timeout: 15_000 }); + ).toBeVisible({ timeout: 60_000 }); dRepPage.getByTestId("confirm-modal-button").click(); await waitForTxConfirmation(dRepPage); From d4d80d4a0f9db3912c1f488ccbc4312873711023 Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 20 May 2025 13:11:06 +0545 Subject: [PATCH 08/75] fix: handle unnecessary wait if title is already on response --- .../playwright/lib/pages/outcomesPage.ts | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts b/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts index 031dfa5e9..9ac9a9e06 100644 --- a/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts @@ -374,25 +374,30 @@ export default class OutComesPage { } async fetchOutcomeIdAndTitleFromNetwork( - governanceActionId: string, - governanceActionTitle: string - ) { + governanceActionId?: string, + governanceActionTitle?: string + ): Promise<{ governanceActionId: string; governanceActionTitle: string }> { let updatedGovernanceActionId = governanceActionId; let updatedGovernanceActionTitle = governanceActionTitle; + await this.page.route( "**/governance-actions?search=&filters=&sort=**", async (route) => { const response = await route.fetch(); const data: outcomeProposal[] = await response.json(); - if (!governanceActionId) { - if (data.length > 0) { - const randomIndexForId = Math.floor(Math.random() * data.length); - updatedGovernanceActionId = - data[randomIndexForId].tx_hash + - "#" + - data[randomIndexForId].index; + + if (!updatedGovernanceActionId && data.length > 0) { + const randomIndex = Math.floor(Math.random() * data.length); + updatedGovernanceActionId = `${data[randomIndex].tx_hash}#${data[randomIndex].index}`; + } + + if (!updatedGovernanceActionTitle) { + const itemWithTitle = data.find((item) => item.title != null); + if (itemWithTitle) { + updatedGovernanceActionTitle = itemWithTitle.title; } } + await route.fulfill({ status: 200, contentType: "application/json", @@ -410,31 +415,40 @@ export default class OutComesPage { await route.continue(); return; } + const data: outcomeMetadata = await response.json(); - if (!governanceActionTitle && data.data.title != null) { + if (!updatedGovernanceActionTitle && data.data.title) { updatedGovernanceActionTitle = data.data.title; } + await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(data), }); } catch (error) { + // Just return without handling the error return; } } ); - const responsePromise = this.page.waitForResponse( + const actionsResponsePromise = this.page.waitForResponse( "**/governance-actions?search=&filters=&sort=**" ); - const metadataResponsePromise = this.page.waitForResponse( - "**/governance-actions/metadata?**" - ); + await this.goto(); - await responsePromise; - await metadataResponsePromise; + await actionsResponsePromise; + + const needMetadataForTitle = !updatedGovernanceActionTitle; + const metadataResponsePromise = needMetadataForTitle + ? this.page.waitForResponse("**/governance-actions/metadata?**") + : Promise.resolve(null); + if (needMetadataForTitle) { + await metadataResponsePromise; + } + return { governanceActionId: updatedGovernanceActionId, governanceActionTitle: updatedGovernanceActionTitle, From f5ed3716bd7ee28d1abb9ecc2b5dbb593a3cbc43 Mon Sep 17 00:00:00 2001 From: Ciabas Date: Tue, 20 May 2025 15:02:27 +0200 Subject: [PATCH 09/75] feat: add support for CIP129 in governance actions --- CHANGELOG.md | 1 + .../organisms/DashboardGovernanceActionDetails.tsx | 4 ++-- .../frontend/src/pages/GovernanceActionDetails.tsx | 4 ++-- .../frontend/src/services/requests/getProposal.ts | 6 +++--- govtool/frontend/src/utils/getGovActionId.ts | 6 ++++-- .../src/utils/tests/getGovActionId.test.ts | 14 ++++++++++++++ 6 files changed, 26 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2515fbe34..2ba449a6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ changes. ## [Unreleased] ### Added +- Add CIP-129 support for gov_actions hashes in Live Voting (governance actions) [Issue 3619](https://github.com/IntersectMBO/govtool/issues/3619) ### Fixed diff --git a/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx b/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx index caa1ee1df..48eafadd2 100644 --- a/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx +++ b/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx @@ -99,8 +99,8 @@ export const DashboardGovernanceActionDetails = () => { useEffect(() => { const isProposalNotFound = - (error as AxiosError)?.response?.data === - `Proposal with id: ${fullProposalId} not found`; + error instanceof AxiosError && + error.response?.data.match(/Proposal with id: .* not found/); if (isProposalNotFound && fullProposalId) { navigate( OUTCOMES_PATHS.governanceActionOutcomes.replace(":id", fullProposalId), diff --git a/govtool/frontend/src/pages/GovernanceActionDetails.tsx b/govtool/frontend/src/pages/GovernanceActionDetails.tsx index c82e6a033..48bcceba7 100644 --- a/govtool/frontend/src/pages/GovernanceActionDetails.tsx +++ b/govtool/frontend/src/pages/GovernanceActionDetails.tsx @@ -94,8 +94,8 @@ export const GovernanceActionDetails = () => { useEffect(() => { const isProposalNotFound = - (error as AxiosError)?.response?.data === - `Proposal with id: ${fullProposalId} not found`; + error instanceof AxiosError && + error.response?.data.match(/Proposal with id: .* not found/); if (isProposalNotFound && fullProposalId) { navigate( OUTCOMES_PATHS.governanceActionOutcomes.replace(":id", fullProposalId), diff --git a/govtool/frontend/src/services/requests/getProposal.ts b/govtool/frontend/src/services/requests/getProposal.ts index 65744d6d0..a4aeda00b 100644 --- a/govtool/frontend/src/services/requests/getProposal.ts +++ b/govtool/frontend/src/services/requests/getProposal.ts @@ -7,10 +7,10 @@ export const getProposal = async ( proposalId: string, drepId?: string, ): Promise => { - const isCIP129Identifier = proposalId.includes("gov_action"); + const isCIP129Identifier = proposalId.startsWith("gov_action"); if (isCIP129Identifier) { - const { txID } = decodeCIP129Identifier(proposalId); - proposalId = txID; + const { txID, index } = decodeCIP129Identifier(proposalId); + proposalId = `${txID}#${parseInt(index, 16)}`; } const encodedHash = encodeURIComponent(proposalId); diff --git a/govtool/frontend/src/utils/getGovActionId.ts b/govtool/frontend/src/utils/getGovActionId.ts index 4b38e447a..e85d13e6b 100644 --- a/govtool/frontend/src/utils/getGovActionId.ts +++ b/govtool/frontend/src/utils/getGovActionId.ts @@ -9,8 +9,10 @@ export const getShortenedGovActionId = ( const firstPart = txHash.slice(0, 4); const lastPart = txHash.slice(-4); - return `${firstPart}...${lastPart}#${index}`; + return txHash.startsWith("gov_action") + ? `${firstPart}...${lastPart}` + : `${firstPart}...${lastPart}#${index}`; }; export const getFullGovActionId = (txHash: string, index: number | string) => - `${txHash}#${index}`; + (txHash.startsWith("gov_action") ? txHash : `${txHash}#${index}`); diff --git a/govtool/frontend/src/utils/tests/getGovActionId.test.ts b/govtool/frontend/src/utils/tests/getGovActionId.test.ts index c0e92949f..a7ce6fa4d 100644 --- a/govtool/frontend/src/utils/tests/getGovActionId.test.ts +++ b/govtool/frontend/src/utils/tests/getGovActionId.test.ts @@ -28,6 +28,13 @@ describe("getShortenedGovActionId", () => { const result = getShortenedGovActionId(txHash, index); expect(result).toBe("#1"); }); + + it("should handle a hash starting with 'gov_action' correctly", () => { + const txHash = "gov_action_1234567890abcdef"; + const index = 7; + const result = getShortenedGovActionId(txHash, index); + expect(result).toBe("gov_...cdef"); + }); }); describe("getFullGovActionId", () => { @@ -37,4 +44,11 @@ describe("getFullGovActionId", () => { const result = getFullGovActionId(txHash, index); expect(result).toBe("1234567890abcdef1234567890abcdef#10"); }); + + it("should return the full id without index if txHash starts with 'gov_action'", () => { + const txHash = "gov_action_1234567890abcdef"; + const index = 5; + const result = getFullGovActionId(txHash, index); + expect(result).toBe("gov_action_1234567890abcdef"); + }); }); From 1a0ff7e79a99dec2bf595b4bc79bb4bd8d2b4e58 Mon Sep 17 00:00:00 2001 From: Olindo Task Date: Wed, 21 May 2025 00:29:39 +0600 Subject: [PATCH 10/75] Added Sentiment Feedback Option to Feedback Modal --- .../frontend/src/context/usersnapContext.tsx | 36 +++++++++++++++++-- govtool/frontend/src/i18n/locales/en.json | 36 +++++++++++-------- .../tests/10-user-snap/userSnap.spec.ts | 25 ++++++++++++- 3 files changed, 80 insertions(+), 17 deletions(-) diff --git a/govtool/frontend/src/context/usersnapContext.tsx b/govtool/frontend/src/context/usersnapContext.tsx index 2b8643f0f..1134e47f6 100644 --- a/govtool/frontend/src/context/usersnapContext.tsx +++ b/govtool/frontend/src/context/usersnapContext.tsx @@ -77,7 +77,39 @@ export const UsersnapProvider = ({ if (API_KEY) { try { const api = await loadSpace(API_KEY); - api.init(initParams); + api.init({ + ...initParams, + customFields: { + sentiment_score: { + type: 'rating', + label: 'How would you rate your experience?', + required: true, + options: [1, 2, 3, 4, 5] + }, + additional_notes: { + type: 'textarea', + label: 'Additional Notes', + required: false + } + }, + feedbackTypes: [ + { + id: 'bug', + label: 'Report a Bug', + description: 'Something is not working as expected' + }, + { + id: 'idea', + label: 'Suggest a New Idea', + description: 'Share your ideas for improvement' + }, + { + id: 'sentiment', + label: 'Share Your Experience', + description: 'Rate your experience and provide feedback' + } + ] + }); setUsersnapApi(api); } catch (error) { console.error(error); @@ -98,4 +130,4 @@ export const UsersnapProvider = ({ export function useUsersnapApi() { return useContext(UsersnapContext); -} +} \ No newline at end of file diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index d057b97cb..c8042f9aa 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -109,8 +109,8 @@ "noDelegationDescription": "Find a DRep to vote on your behalf.", "noDelegationActionButton": "View DRep Directory", "dRepDelegationTitle": "Your Voting Power of ₳{{ada}}\nis Delegated to:", - "noConfidenceDelegationTitle": "You have delegated your Voting Power ₳{{ada}}\nto “No Confidence”", - "abstainDelegationTitle": "You have delegated your Voting Power ₳{{ada}}\nto “Abstain”", + "noConfidenceDelegationTitle": "You have delegated your Voting Power ₳{{ada}}\nto \"No Confidence\"", + "abstainDelegationTitle": "You have delegated your Voting Power ₳{{ada}}\nto \"Abstain\"", "abstainDescription": "You have selected to apply your Voting Power to Abstain on every vote.", "noDescription": "You have selected to apply your Voting Power to No Confidence on every vote.", "inProgress": { @@ -268,8 +268,8 @@ "abstainCardDefaultTitle": "Abstain from Every Vote", "automatedVotingOptions": "Automated Voting Options", "editBtn": "Edit DRep data", - "delegatedToAbstainTitle": "You have delegated ₳{{ada}} to “Abstain”", - "delegatedToNoConfidenceTitle": "You have delegated ₳{{ada}} to “No Confidence”", + "delegatedToAbstainTitle": "You have delegated ₳{{ada}} to \"Abstain\"", + "delegatedToNoConfidenceTitle": "You have delegated ₳{{ada}} to \"No Confidence\"", "delegatedToAbstainDescription": "You have selected to apply your Voting Power to Abstain on every vote.", "delegatedToNoConfidenceDescription": "You have selected to apply your Voting Power to No Confidence on every vote.", "delegationOptions": "Delegation Options", @@ -414,7 +414,7 @@ "chooseHowToVote": "Choose how you want to vote:", "contextAboutYourVote": "Context about your vote", "dataMissing": "Data Missing", - "dataMissingTooltipExplanation": "Please click “View Details” for more information.", + "dataMissingTooltipExplanation": "Please click \"View Details\" for more information.", "details": "Governance Details:", "expiresDateWithEpoch": "Expires: <0>{{date}} <1>(Epoch {{epoch}})", "expiryDate": "Expiry date:", @@ -641,7 +641,7 @@ }, "pendingValidation": { "title": "GovTool Is Checking Your Data", - "message": "GovTool will read the URL that you supplied and make a check to see if it’s identical with the information that you entered on the form." + "message": "GovTool will read the URL that you supplied and make a check to see if it's identical with the information that you entered on the form." } }, "dRepData": { @@ -679,7 +679,7 @@ "description": "Looks like you have already successfully completed your registration and you currently are a DRep.\n\nYou can view your details in the DRep Directory.", "viewDetails": "View your DRep details" }, - "becomeADRep": "Become a DRep", + "becomeADrep": "Become a DRep", "descriptionStepTwo": "By clicking register you create your DRep ID within your wallet and become a DRep.\n\nOnce the registration has completed your DRep ID will be shown on your dashboard. You will be able to share your DRep ID so that other ada holders can delegate their voting power to you.", "headingStepTwo": "Confirm DRep registration", "register": "Register", @@ -706,7 +706,7 @@ } }, "retirement": { - "notADRep": { + "notADrep": { "title": "You are not a DRep", "description": "Looks like you cannot retire, because currently you are not a DRep." }, @@ -754,7 +754,7 @@ }, "noConfidence": { "heading": "No confidence", - "paragraphOne": "If you don’t have trust in the current constitutional committee you signal ‘No-confidence’. By voting ‘No’ means you don’t want governance actions to be ratified." + "paragraphOne": "If you don't have trust in the current constitutional committee you signal 'No-confidence'. By voting 'No' means you don't want governance actions to be ratified." }, "todRep": { "heading": "Delegation to DRep", @@ -767,7 +767,7 @@ }, "expiryDate": { "heading": "Expiry Date", - "paragraphOne": "The date when the governance action will expiry if it doesn’t reach ratification thresholds.", + "paragraphOne": "The date when the governance action will expiry if it doesn't reach ratification thresholds.", "paragraphTwo": "IMPORTANT: If the governance action is ratified before the expiry date it will be considered ratified and it will not be available to vote on afterwards." }, "submissionDate": { @@ -781,7 +781,7 @@ } }, "wallet": { - "cantSeeWalletQuestion": "Can’t see your wallet? Check what wallets are currently compatible with GovTool ", + "cantSeeWalletQuestion": "Can't see your wallet? Check what wallets are currently compatible with GovTool ", "chooseWallet": "Choose the wallet you want to connect with:", "connect": "Connect", "connectWallet": "Connect Wallet", @@ -818,7 +818,7 @@ }, "intersectWebsite": { "title": "Intersect website", - "description": "Intersect is a member-based organization for the Cardano ecosystem — putting the community at the center of Cardano’s development", + "description": "Intersect is a member-based organization for the Cardano ecosystem — putting the community at the center of Cardano's development", "link": "Intersect website" } }, @@ -840,7 +840,15 @@ "cip129DrepId": "(CIP-129) DRep ID", "cip105DRepId": "Legacy DRep ID (CIP-105)", "email": "Email", - "feedback": "Feedback", + "feedback": { + "title": "Feedback", + "reportBug": "Report a Bug", + "suggestIdea": "Suggest a New Idea", + "sentimentFeedback": "Share Your Experience", + "sentimentScore": "How would you rate your experience?", + "additionalNotes": "Additional Notes", + "submit": "Submit Feedback" + }, "filter": "Filter", "goBack": "Go back", "goToMainnet": "Go to Mainnet", @@ -872,4 +880,4 @@ "viewDetails": "View details", "votingPower": "Voting power", "yourself": "Yourself" -} +} \ No newline at end of file diff --git a/tests/govtool-frontend/playwright/tests/10-user-snap/userSnap.spec.ts b/tests/govtool-frontend/playwright/tests/10-user-snap/userSnap.spec.ts index ab8e4c1be..0b748c171 100644 --- a/tests/govtool-frontend/playwright/tests/10-user-snap/userSnap.spec.ts +++ b/tests/govtool-frontend/playwright/tests/10-user-snap/userSnap.spec.ts @@ -187,4 +187,27 @@ test.describe("Submit Usersnap", () => { await expect(page.getByText("Thank you!")).toBeVisible(); }); -}); + + test("10F. Should submit sentiment feedback", async ({ page }) => { + // Intercept Usersnap submit API + await interceptUsersnap(page); + await interceptBucket(page); + + await page + .getByRole("button", { name: "Share Your Experience" }) + .click(); + + // Select a rating + await page.getByLabel("How would you rate your experience?").click(); + await page.getByRole("button", { name: "4" }).click(); + + // Add additional notes + await page + .getByPlaceholder("Additional Notes") + .fill(faker.lorem.paragraph(2)); + + await page.getByRole("button", { name: "Submit Feedback" }).click(); + + await expect(page.getByText("Thank you!")).toBeVisible(); + }); +}); \ No newline at end of file From 049f93010123a64e890b348515c38bd6a54da683 Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 21 May 2025 12:01:41 +0545 Subject: [PATCH 11/75] feat: add deployment environment script and integrate into backend workflow --- .github/scripts/set_deployment_environment.sh | 16 ++++++++++++++++ .github/workflows/test_backend.yml | 10 +++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 .github/scripts/set_deployment_environment.sh diff --git a/.github/scripts/set_deployment_environment.sh b/.github/scripts/set_deployment_environment.sh new file mode 100644 index 000000000..9cb31a912 --- /dev/null +++ b/.github/scripts/set_deployment_environment.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +DEPLOYMENT=${DEPLOYMENT:-"govtool.cardanoapi.io/api"} +GROUP_NAME="qa" + +if [[ "$DEPLOYMENT" == "be.preview.gov.tools" || "$DEPLOYMENT" == "z6b8d2f7a-zca4a4c45-gtw.z937eb260.rustrocks.fr" ]]; then + GROUP_NAME="preview" +elif [[ "$DEPLOYMENT" == "be.gov.tools" ]]; then + GROUP_NAME="mainnet" +else + GROUP_NAME="qa" +fi + +# Set environment variable for GitHub Actions +echo "GROUP_NAME=${GROUP_NAME}" >> $GITHUB_ENV +echo "Setting deployment environment to: ${GROUP_NAME}" diff --git a/.github/workflows/test_backend.yml b/.github/workflows/test_backend.yml index 74b9ca195..7b031ef74 100644 --- a/.github/workflows/test_backend.yml +++ b/.github/workflows/test_backend.yml @@ -59,6 +59,7 @@ jobs: - name: Set pending commit status id: set-pending-status + if: ${{ !github.event.schedule }} run: | echo "timestamp=$(date +%s)" >> $GITHUB_OUTPUT curl -X POST -H "Authorization: Bearer ${{ github.token }}" \ @@ -121,6 +122,12 @@ jobs: repository: ${{vars.GH_PAGES}} ssh-key: ${{ secrets.DEPLOY_KEY }} + - name: Set Deployment Environment + id: set-deployment-url + run: | + chmod +x .github/scripts/set_deployment_environment.sh + .github/scripts/set_deployment_environment.sh + - name: Remove oldest report to save space if: ${{success()}} run: | @@ -186,7 +193,7 @@ jobs: name: allure-results path: allure-results - name: Set Commit Status - if: always() + if: always() && !github.event.schedule run: | chmod +x .github/scripts/set_commit_status.sh .github/scripts/set_commit_status.sh @@ -198,6 +205,7 @@ jobs: env: BASE_URL: https://${{github.event.schedule && 'be.preview.gov.tools' || inputs.deployment || 'govtool.cardanoapi.io/api' }} + DEPLOYMENT: ${{ inputs.deployment || 'govtool.cardanoapi.io/api'}} REPORT_NAME: ${{ github.event.schedule && 'nightly-'}}govtool-backend GH_PAGES: ${{vars.GH_PAGES}} COMMIT_SHA: ${{ github.event.workflow_run.head_sha || github.sha }} From 7e7fc25143d59e02c373b2b42832d1ec3a174880 Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 21 May 2025 12:02:47 +0545 Subject: [PATCH 12/75] fix: update report scripts to include GROUP_NAME in paths --- .github/scripts/generate_latest_report_redirect.sh | 2 +- .github/scripts/generate_report_details.sh | 6 +++--- .github/scripts/register_report.sh | 4 ++-- .github/scripts/remove_oldest_report.sh | 4 ++-- .github/scripts/set_commit_status.sh | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/scripts/generate_latest_report_redirect.sh b/.github/scripts/generate_latest_report_redirect.sh index 688e61239..acf5187d7 100644 --- a/.github/scripts/generate_latest_report_redirect.sh +++ b/.github/scripts/generate_latest_report_redirect.sh @@ -11,7 +11,7 @@ cat < build/index.html - + Redirecting... diff --git a/.github/scripts/generate_report_details.sh b/.github/scripts/generate_report_details.sh index bf8131959..dff702fb2 100644 --- a/.github/scripts/generate_report_details.sh +++ b/.github/scripts/generate_report_details.sh @@ -1,12 +1,12 @@ #!/bin/bash -if [[ ! -d "gh-pages/$REPORT_NAME" ]]; then +if [[ ! -d "gh-pages/$GROUP_NAME/$REPORT_NAME" ]]; then latest_number=0 else - gh_pages_content=$(ls "gh-pages/$REPORT_NAME/") + gh_pages_content=$(ls "gh-pages/$GROUP_NAME/$REPORT_NAME/") latest_number=$(echo "$gh_pages_content" | grep -Eo '[0-9]+' | sort -nr | head -n 1) fi echo "report_number=$((latest_number+1))" >> $GITHUB_OUTPUT -echo "report_url=https://$(dirname "$GH_PAGES").github.io/$(basename "$GH_PAGES")/$REPORT_NAME" >> $GITHUB_OUTPUT +echo "report_url=https://$(dirname "$GH_PAGES").github.io/$(basename "$GH_PAGES")/$GROUP_NAME/$REPORT_NAME" >> $GITHUB_OUTPUT diff --git a/.github/scripts/register_report.sh b/.github/scripts/register_report.sh index 959368afb..e071e3e9b 100644 --- a/.github/scripts/register_report.sh +++ b/.github/scripts/register_report.sh @@ -6,10 +6,10 @@ PROJECT_FILE="projects.txt" mkdir -p "$PROJECT_DIR" cp -r gh-pages/* "$PROJECT_DIR" || true -if grep -q "$REPORT_NAME" "$PROJECT_DIR/$PROJECT_FILE"; then +if grep -q "$REPORT_NAME" "$PROJECT_DIR/$GROUP_NAME/$PROJECT_FILE"; then echo "Project already exists" echo "project_exists=true">> $GITHUB_OUTPUT else - echo "\n$REPORT_NAME" >> "$PROJECT_DIR/$PROJECT_FILE" + echo -e "\n$REPORT_NAME" >> "$PROJECT_DIR/$GROUP_NAME/$PROJECT_FILE" echo "project_exists=false">> $GITHUB_OUTPUT fi diff --git a/.github/scripts/remove_oldest_report.sh b/.github/scripts/remove_oldest_report.sh index e0a809604..208f0d9a9 100644 --- a/.github/scripts/remove_oldest_report.sh +++ b/.github/scripts/remove_oldest_report.sh @@ -1,7 +1,7 @@ #!/bin/bash -if [ -d "gh-pages/$REPORT_NAME" ]; then - cd gh-pages/$REPORT_NAME +if [ -d "gh-pages/$GROUP_NAME/$REPORT_NAME" ]; then + cd gh-pages/$GROUP_NAME/$REPORT_NAME # Count the number of numerical directories dir_count=$(find . -maxdepth 1 -type d -regex './[0-9]+' | wc -l) diff --git a/.github/scripts/set_commit_status.sh b/.github/scripts/set_commit_status.sh index f22c4e885..fec4e145b 100644 --- a/.github/scripts/set_commit_status.sh +++ b/.github/scripts/set_commit_status.sh @@ -48,9 +48,9 @@ fi # Determine target URL based on environment case "$GH_PAGES" in - "IntersectMBO/govtool-test-reports") TARGET_URL="https://intersectmbo.github.io/govtool-test-reports/${REPORT_NAME}/${REPORT_NUMBER}" ;; - "cardanoapi/govtool-test-reports") TARGET_URL="https://cardanoapi.github.io/govtool-test-reports/${REPORT_NAME}/${REPORT_NUMBER}" ;; - *) TARGET_URL="https://intersectmbo.github.io/govtool-test-reports/${REPORT_NAME}/${REPORT_NUMBER}" ;; + "IntersectMBO/govtool-test-reports") TARGET_URL="https://intersectmbo.github.io/govtool-test-reports/${GROUP_NAME}/${REPORT_NAME}/${REPORT_NUMBER}" ;; + "cardanoapi/govtool-test-reports") TARGET_URL="https://cardanoapi.github.io/govtool-test-reports/${GROUP_NAME}/${REPORT_NAME}/${REPORT_NUMBER}" ;; + *) TARGET_URL="https://intersectmbo.github.io/govtool-test-reports/${GROUP_NAME}/${REPORT_NAME}/${REPORT_NUMBER}" ;; esac # Determine test result message From c49541ed9c0a57e84d39928a8b6607ff436d602f Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 21 May 2025 12:16:08 +0545 Subject: [PATCH 13/75] chore: add set deployment env logic for integration test --- .github/scripts/set_deployment_environment.sh | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/scripts/set_deployment_environment.sh b/.github/scripts/set_deployment_environment.sh index 9cb31a912..63fac5c64 100644 --- a/.github/scripts/set_deployment_environment.sh +++ b/.github/scripts/set_deployment_environment.sh @@ -2,15 +2,31 @@ DEPLOYMENT=${DEPLOYMENT:-"govtool.cardanoapi.io/api"} GROUP_NAME="qa" +HOST_URL=$HOST_URL +BASE_URL=$BASE_URL -if [[ "$DEPLOYMENT" == "be.preview.gov.tools" || "$DEPLOYMENT" == "z6b8d2f7a-zca4a4c45-gtw.z937eb260.rustrocks.fr" ]]; then - GROUP_NAME="preview" -elif [[ "$DEPLOYMENT" == "be.gov.tools" ]]; then - GROUP_NAME="mainnet" +# Determine if running from frontend (HOST_URL is set) or backend (BASE_URL is set) +if [[ "$HOST_URL" != null && -n "$HOST_URL" ]]; then + if [[ "$DEPLOYMENT" == "preview.gov.tools" ]]; then + GROUP_NAME="preview" + elif [[ "$DEPLOYMENT" == "gov.tools" ]]; then + GROUP_NAME="mainnet" + else + GROUP_NAME="qa" + fi +elif [[ -n "$BASE_URL" ]]; then + if [[ "$DEPLOYMENT" == "be.preview.gov.tools" || "$DEPLOYMENT" == "z6b8d2f7a-zca4a4c45-gtw.z937eb260.rustrocks.fr" ]]; then + GROUP_NAME="preview" + elif [[ "$DEPLOYMENT" == "be.gov.tools" ]]; then + GROUP_NAME="mainnet" + else + GROUP_NAME="qa" + fi else + echo "Warning: Neither HOST_URL nor BASE_URL is properly set. Using default QA environment." GROUP_NAME="qa" fi # Set environment variable for GitHub Actions -echo "GROUP_NAME=${GROUP_NAME}" >> $GITHUB_ENV +echo "GROUP_NAME=${GROUP_NAME}" >>$GITHUB_ENV echo "Setting deployment environment to: ${GROUP_NAME}" From d16b35e408c74de3699c943d4c5d2051308e2477 Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 21 May 2025 12:19:04 +0545 Subject: [PATCH 14/75] feat: add deployment environment setup for integration test workflow --- .github/workflows/test_backend.yml | 1 + .github/workflows/test_integration_playwright.yml | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_backend.yml b/.github/workflows/test_backend.yml index 7b031ef74..8bf128f80 100644 --- a/.github/workflows/test_backend.yml +++ b/.github/workflows/test_backend.yml @@ -192,6 +192,7 @@ jobs: with: name: allure-results path: allure-results + - name: Set Commit Status if: always() && !github.event.schedule run: | diff --git a/.github/workflows/test_integration_playwright.yml b/.github/workflows/test_integration_playwright.yml index 841357529..835c67fbd 100644 --- a/.github/workflows/test_integration_playwright.yml +++ b/.github/workflows/test_integration_playwright.yml @@ -59,6 +59,7 @@ jobs: with: ref: ${{ env.COMMIT_SHA }} - name: Set pending commit status + if: ${{ !github.event.schedule }} id: set-pending-status run: | echo "timestamp=$(date +%s)" >> $GITHUB_OUTPUT @@ -161,6 +162,12 @@ jobs: repository: ${{vars.GH_PAGES}} ssh-key: ${{ secrets.DEPLOY_KEY }} + - name: Set Deployment Environment + id: set-deployment-url + run: | + chmod +x .github/scripts/set_deployment_environment.sh + .github/scripts/set_deployment_environment.sh + - name: Remove oldest report to save space if: ${{success()}} run: | @@ -226,8 +233,9 @@ jobs: with: name: allure-results path: allure-results + - name: Set Commit Status - if: always() + if: always() && !github.event.schedule run: | chmod +x .github/scripts/set_commit_status.sh .github/scripts/set_commit_status.sh From c6256a109932b0fc454fd29a93f8eee4fbfd0088 Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 21 May 2025 13:01:01 +0545 Subject: [PATCH 15/75] fix: add group name before reportName on every workflow steps --- .github/scripts/register_report.sh | 5 +++++ .github/scripts/set_deployment_environment.sh | 1 + .github/workflows/test_backend.yml | 8 ++++---- .github/workflows/test_integration_playwright.yml | 6 +++--- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/scripts/register_report.sh b/.github/scripts/register_report.sh index e071e3e9b..c3b78a16a 100644 --- a/.github/scripts/register_report.sh +++ b/.github/scripts/register_report.sh @@ -6,6 +6,11 @@ PROJECT_FILE="projects.txt" mkdir -p "$PROJECT_DIR" cp -r gh-pages/* "$PROJECT_DIR" || true +# Create group directory if it doesn't exist +mkdir -p "$PROJECT_DIR/$GROUP_NAME" +# Create project file if it doesn't exist +touch "$PROJECT_DIR/$GROUP_NAME/$PROJECT_FILE" + if grep -q "$REPORT_NAME" "$PROJECT_DIR/$GROUP_NAME/$PROJECT_FILE"; then echo "Project already exists" echo "project_exists=true">> $GITHUB_OUTPUT diff --git a/.github/scripts/set_deployment_environment.sh b/.github/scripts/set_deployment_environment.sh index 63fac5c64..7953c87e2 100644 --- a/.github/scripts/set_deployment_environment.sh +++ b/.github/scripts/set_deployment_environment.sh @@ -29,4 +29,5 @@ fi # Set environment variable for GitHub Actions echo "GROUP_NAME=${GROUP_NAME}" >>$GITHUB_ENV +echo "group_name=${GROUP_NAME}" >>$GITHUB_OUTPUT echo "Setting deployment environment to: ${GROUP_NAME}" diff --git a/.github/workflows/test_backend.yml b/.github/workflows/test_backend.yml index 8bf128f80..19d9ec0f0 100644 --- a/.github/workflows/test_backend.yml +++ b/.github/workflows/test_backend.yml @@ -33,7 +33,7 @@ on: workflow_run: workflows: ["Build and deploy GovTool test stack"] types: [completed] - branches: + branches: - test - infra/test-chores @@ -147,7 +147,7 @@ jobs: ssh-key: ${{ secrets.DEPLOY_KEY }} repository-name: ${{vars.GH_PAGES}} branch: gh-pages - folder: project + folder: project/${{steps.set-deployment-url.outputs.group_name}} - name: Generate report details id: report-details @@ -160,7 +160,7 @@ jobs: id: allure-report with: allure_results: allure-results - gh_pages: gh-pages/${{env.REPORT_NAME}} + gh_pages: gh-pages/${{steps.set-deployment-url.outputs.group_name}}/${{env.REPORT_NAME}} allure_report: allure-report allure_history: allure-history keep_reports: 2000 @@ -179,7 +179,7 @@ jobs: repository-name: ${{vars.GH_PAGES}} branch: gh-pages folder: build - target-folder: ${{ env.REPORT_NAME }} + target-folder: ${{steps.set-deployment-url.outputs.group_name}}/${{ env.REPORT_NAME }} publish-status: runs-on: ubuntu-latest diff --git a/.github/workflows/test_integration_playwright.yml b/.github/workflows/test_integration_playwright.yml index 835c67fbd..f431ad893 100644 --- a/.github/workflows/test_integration_playwright.yml +++ b/.github/workflows/test_integration_playwright.yml @@ -187,7 +187,7 @@ jobs: ssh-key: ${{ secrets.DEPLOY_KEY }} repository-name: ${{vars.GH_PAGES}} branch: gh-pages - folder: project + folder: project/${{steps.set-deployment-url.outputs.group_name}} - name: Generate report details id: report-details @@ -201,7 +201,7 @@ jobs: id: allure-report with: allure_results: allure-results - gh_pages: gh-pages/${{env.REPORT_NAME}} + gh_pages: gh-pages/${{steps.set-deployment-url.outputs.group_name}}/${{env.REPORT_NAME}} allure_report: allure-report allure_history: allure-history keep_reports: 2000 @@ -220,7 +220,7 @@ jobs: repository-name: ${{vars.GH_PAGES}} branch: gh-pages folder: build - target-folder: ${{ env.REPORT_NAME }} + target-folder: ${{steps.set-deployment-url.outputs.group_name}}/${{ env.REPORT_NAME }} publish-status: runs-on: ubuntu-latest From 415b1bdb449b976787d795c61a1e4ee6986a3264 Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 21 May 2025 13:09:02 +0545 Subject: [PATCH 16/75] chore: remove report registration step from backend and integration workflows --- .github/scripts/register_report.sh | 20 ------------------- .github/workflows/test_backend.yml | 15 -------------- .../workflows/test_integration_playwright.yml | 15 -------------- 3 files changed, 50 deletions(-) delete mode 100644 .github/scripts/register_report.sh diff --git a/.github/scripts/register_report.sh b/.github/scripts/register_report.sh deleted file mode 100644 index c3b78a16a..000000000 --- a/.github/scripts/register_report.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -PROJECT_DIR="project" -PROJECT_FILE="projects.txt" - -mkdir -p "$PROJECT_DIR" -cp -r gh-pages/* "$PROJECT_DIR" || true - -# Create group directory if it doesn't exist -mkdir -p "$PROJECT_DIR/$GROUP_NAME" -# Create project file if it doesn't exist -touch "$PROJECT_DIR/$GROUP_NAME/$PROJECT_FILE" - -if grep -q "$REPORT_NAME" "$PROJECT_DIR/$GROUP_NAME/$PROJECT_FILE"; then - echo "Project already exists" - echo "project_exists=true">> $GITHUB_OUTPUT -else - echo -e "\n$REPORT_NAME" >> "$PROJECT_DIR/$GROUP_NAME/$PROJECT_FILE" - echo "project_exists=false">> $GITHUB_OUTPUT -fi diff --git a/.github/workflows/test_backend.yml b/.github/workflows/test_backend.yml index 19d9ec0f0..4acbf9ced 100644 --- a/.github/workflows/test_backend.yml +++ b/.github/workflows/test_backend.yml @@ -134,21 +134,6 @@ jobs: chmod +x .github/scripts/remove_oldest_report.sh .github/scripts/remove_oldest_report.sh - - name: Register report - id: register-project - if: ${{success()}} - run: | - chmod +x .github/scripts/register_report.sh - .github/scripts/register_report.sh - - - if: steps.register-project.outputs.project_exists != 'true' - uses: JamesIves/github-pages-deploy-action@v4 - with: - ssh-key: ${{ secrets.DEPLOY_KEY }} - repository-name: ${{vars.GH_PAGES}} - branch: gh-pages - folder: project/${{steps.set-deployment-url.outputs.group_name}} - - name: Generate report details id: report-details run: | diff --git a/.github/workflows/test_integration_playwright.yml b/.github/workflows/test_integration_playwright.yml index f431ad893..0891bca70 100644 --- a/.github/workflows/test_integration_playwright.yml +++ b/.github/workflows/test_integration_playwright.yml @@ -174,21 +174,6 @@ jobs: chmod +x .github/scripts/remove_oldest_report.sh .github/scripts/remove_oldest_report.sh - - name: Register report - id: register-project - if: ${{success()}} - run: | - chmod +x .github/scripts/register_report.sh - .github/scripts/register_report.sh - - - if: steps.register-project.outputs.project_exists != 'true' - uses: JamesIves/github-pages-deploy-action@v4 - with: - ssh-key: ${{ secrets.DEPLOY_KEY }} - repository-name: ${{vars.GH_PAGES}} - branch: gh-pages - folder: project/${{steps.set-deployment-url.outputs.group_name}} - - name: Generate report details id: report-details run: | From 6e77b725efabd63f2ea2401ed5b02611e8a3c014 Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 21 May 2025 13:22:48 +0545 Subject: [PATCH 17/75] fix: correct environment variable name for faucet stake private key --- .github/workflows/test_integration_playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_integration_playwright.yml b/.github/workflows/test_integration_playwright.yml index 0891bca70..f2eaffda3 100644 --- a/.github/workflows/test_integration_playwright.yml +++ b/.github/workflows/test_integration_playwright.yml @@ -137,7 +137,7 @@ jobs: FAUCET_ADDRESS: ${{vars.FAUCET_ADDRESS}} CARDANOAPI_METADATA_URL: ${{vars.CARDANOAPI_METADATA_URL}} FAUCET_PAYMENT_PRIVATE: ${{secrets.FAUCET_PAYMENT_PRIVATE}} - FAUCET_STAKE_PKH: ${{secrets.FAUCET_STAKE_PKH}} + FAUCET_STAKE_PRIVATE: ${{secrets.FAUCET_STAKE_PRIVATE}} publish-report: runs-on: ubuntu-latest From bc96e674bc5d7f4022bf8559b7d4e4e557007755 Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 21 May 2025 15:53:50 +0545 Subject: [PATCH 18/75] chore: remove unnecessary condition for group name --- .github/scripts/set_deployment_environment.sh | 26 +++++-------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/.github/scripts/set_deployment_environment.sh b/.github/scripts/set_deployment_environment.sh index 7953c87e2..8c9495a57 100644 --- a/.github/scripts/set_deployment_environment.sh +++ b/.github/scripts/set_deployment_environment.sh @@ -2,28 +2,14 @@ DEPLOYMENT=${DEPLOYMENT:-"govtool.cardanoapi.io/api"} GROUP_NAME="qa" -HOST_URL=$HOST_URL -BASE_URL=$BASE_URL -# Determine if running from frontend (HOST_URL is set) or backend (BASE_URL is set) -if [[ "$HOST_URL" != null && -n "$HOST_URL" ]]; then - if [[ "$DEPLOYMENT" == "preview.gov.tools" ]]; then - GROUP_NAME="preview" - elif [[ "$DEPLOYMENT" == "gov.tools" ]]; then - GROUP_NAME="mainnet" - else - GROUP_NAME="qa" - fi -elif [[ -n "$BASE_URL" ]]; then - if [[ "$DEPLOYMENT" == "be.preview.gov.tools" || "$DEPLOYMENT" == "z6b8d2f7a-zca4a4c45-gtw.z937eb260.rustrocks.fr" ]]; then - GROUP_NAME="preview" - elif [[ "$DEPLOYMENT" == "be.gov.tools" ]]; then - GROUP_NAME="mainnet" - else - GROUP_NAME="qa" - fi +if [[ "$DEPLOYMENT" == "preview.gov.tools" || "$DEPLOYMENT" == "be.preview.gov.tools" || "$DEPLOYMENT" == "z6b8d2f7a-zca4a4c45-gtw.z937eb260.rustrocks.fr" ]]; then + GROUP_NAME="preview" +elif [[ "$DEPLOYMENT" == "gov.tools" || "$DEPLOYMENT" == "be.gov.tools" ]]; then + GROUP_NAME="mainnet" +elif [[ "$DEPLOYMENT" == "p80-z78acf3c2-zded6a792-gtw.z937eb260.rustrocks.fr" || "$DEPLOYMENT" == "z78acf3c2-z5575152b-gtw.z937eb260.rustrocks.fr" ]]; then + GROUP_NAME="dev" else - echo "Warning: Neither HOST_URL nor BASE_URL is properly set. Using default QA environment." GROUP_NAME="qa" fi From f57b314b2a36d8e5a283ba1422e7de49e33b2631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Tue, 20 May 2025 15:07:37 +0200 Subject: [PATCH 19/75] fix(#3192): fix missing proposals dashboard title --- CHANGELOG.md | 2 ++ govtool/frontend/src/pages/Dashboard.tsx | 37 +++++++++++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 145af887e..f04bce8c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ changes. ### Fixed +- Fix displaying proposals title in details page [Issue 3192](https://github.com/IntersectMBO/govtool/issues/3192) + ### Changed ### Removed diff --git a/govtool/frontend/src/pages/Dashboard.tsx b/govtool/frontend/src/pages/Dashboard.tsx index 684558337..d623ba1b1 100644 --- a/govtool/frontend/src/pages/Dashboard.tsx +++ b/govtool/frontend/src/pages/Dashboard.tsx @@ -4,10 +4,12 @@ import { Box } from "@mui/material"; import { Background, ScrollToManage } from "@atoms"; import { + BUDGET_DISCUSSION_PATHS, CONNECTED_NAV_ITEMS, DRAWER_WIDTH, OUTCOMES_PATHS, PATHS, + PDF_PATHS, } from "@consts"; import { useCardano } from "@context"; import { useScreenDimension, useTranslation } from "@hooks"; @@ -34,18 +36,37 @@ export const Dashboard = () => { return outcomesNavItem ?? ""; } + if (path.startsWith(BUDGET_DISCUSSION_PATHS.budgetDiscussion)) { + const budgetNavItem = findNavItem( + CONNECTED_NAV_ITEMS, + BUDGET_DISCUSSION_PATHS.budgetDiscussion, + ); + + return budgetNavItem ?? ""; + } + + if (path.startsWith(PDF_PATHS.proposalDiscussion)) { + const proposalDiscussionNavItem = findNavItem( + CONNECTED_NAV_ITEMS, + PDF_PATHS.proposalDiscussion, + ); + + return proposalDiscussionNavItem ?? ""; + } return findNavItem(CONNECTED_NAV_ITEMS, path) ?? ""; }; - const findNavItem = (items: NavItem[], targetPath: string): string | null => ( - items.reduce((result, item) => ( - result ?? ( - targetPath === item.navTo + const findNavItem = (items: NavItem[], targetPath: string): string | null => + items.reduce( + (result, item) => + result ?? + (targetPath === item.navTo ? item.label - : (item.childNavItems ? findNavItem(item.childNavItems, targetPath) : null) - ) - ), null) - ); + : item.childNavItems + ? findNavItem(item.childNavItems, targetPath) + : null), + null, + ); useEffect(() => { if (divRef.current && pathname !== PATHS.dashboardGovernanceActions) { From 856ef3d8369d8360b1f30e4efb9b36eb44bf5db9 Mon Sep 17 00:00:00 2001 From: Niraj Date: Thu, 22 May 2025 09:31:05 +0545 Subject: [PATCH 20/75] fix: add missing deployment url on integration test --- .github/workflows/test_integration_playwright.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_integration_playwright.yml b/.github/workflows/test_integration_playwright.yml index f2eaffda3..f48fc0099 100644 --- a/.github/workflows/test_integration_playwright.yml +++ b/.github/workflows/test_integration_playwright.yml @@ -231,6 +231,7 @@ jobs: GITHUB_TOKEN: ${{ github.token }} env: HOST_URL: https://${{ github.event.schedule && 'preview.gov.tools' || (inputs.deployment || 'govtool.cardanoapi.io') }} + DEPLOYMENT: ${{ github.event.schedule && 'preview.gov.tools' || inputs.deployment || 'govtool.cardanoapi.io'}} REPORT_NAME: ${{ github.event.schedule && 'nightly-'}}govtool-frontend GH_PAGES: ${{vars.GH_PAGES}} COMMIT_SHA: ${{ github.event.workflow_run.head_sha || github.sha }} From 3786d15a96d98064a57a9a5fae758dd566aefed4 Mon Sep 17 00:00:00 2001 From: Niraj Date: Thu, 22 May 2025 09:31:26 +0545 Subject: [PATCH 21/75] fix: deployment for schedule workflow --- .github/workflows/test_backend.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_backend.yml b/.github/workflows/test_backend.yml index 4acbf9ced..6ea254e21 100644 --- a/.github/workflows/test_backend.yml +++ b/.github/workflows/test_backend.yml @@ -191,7 +191,7 @@ jobs: env: BASE_URL: https://${{github.event.schedule && 'be.preview.gov.tools' || inputs.deployment || 'govtool.cardanoapi.io/api' }} - DEPLOYMENT: ${{ inputs.deployment || 'govtool.cardanoapi.io/api'}} + DEPLOYMENT: ${{ github.event.schedule && 'be.preview.gov.tools' || inputs.deployment || 'govtool.cardanoapi.io/api'}} REPORT_NAME: ${{ github.event.schedule && 'nightly-'}}govtool-backend GH_PAGES: ${{vars.GH_PAGES}} COMMIT_SHA: ${{ github.event.workflow_run.head_sha || github.sha }} From a39bd39586c89c18c3c80fcb6fcc0758f7fbf58b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 21 May 2025 22:34:02 +0200 Subject: [PATCH 22/75] feat: add support for Parameter Change and Hard Fork Initiation gov actions creation --- CHANGELOG.md | 1 + ...ted-governance-action-proposal-details.sql | 15 ++++ govtool/backend/src/VVA/API.hs | 29 +++++++ govtool/backend/src/VVA/API/Types.hs | 34 ++++++++ govtool/backend/src/VVA/Proposal.hs | 59 +++++++++++-- govtool/backend/src/VVA/Types.hs | 34 ++++++++ govtool/backend/vva-be.cabal | 1 + .../CreateGovernanceActionForm.tsx | 5 ++ .../src/consts/governanceAction/fields.ts | 82 +++++++++++++++++++ govtool/frontend/src/context/wallet.tsx | 5 +- .../forms/useCreateGovernanceActionForm.ts | 58 ++++++++++++- govtool/frontend/src/i18n/locales/en.json | 15 ++++ .../frontend/src/types/governanceAction.ts | 17 +++- 13 files changed, 338 insertions(+), 17 deletions(-) create mode 100644 govtool/backend/sql/get-previous-enacted-governance-action-proposal-details.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index f28ea4458..e3b03bc83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ changes. - Add CIP-129 support for gov_actions hashes in Live Voting (governance actions) [Issue 3619](https://github.com/IntersectMBO/govtool/issues/3619) - Add maintenance ending banner [Issue 3647](https://github.com/IntersectMBO/govtool/issues/3647) +- Add support for the Protocol Parameter Change and Hard Fork Initiation governance actions ### Fixed diff --git a/govtool/backend/sql/get-previous-enacted-governance-action-proposal-details.sql b/govtool/backend/sql/get-previous-enacted-governance-action-proposal-details.sql new file mode 100644 index 000000000..6aabbaa3d --- /dev/null +++ b/govtool/backend/sql/get-previous-enacted-governance-action-proposal-details.sql @@ -0,0 +1,15 @@ +SELECT + gap.id, + tx_id, + index, + description, + encode(hash, 'hex') AS hash +FROM + gov_action_proposal gap +JOIN + tx ON gap.tx_id = tx.id +WHERE + gap.type = ? AND gap.enacted_epoch IS NOT NULL +ORDER BY + gap.id DESC +LIMIT 1; \ No newline at end of file diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs index b95960f52..9488710a6 100644 --- a/govtool/backend/src/VVA/API.hs +++ b/govtool/backend/src/VVA/API.hs @@ -78,6 +78,7 @@ type VVAApi = :> QueryParam "search" Text :> Get '[JSON] ListProposalsResponse :<|> "proposal" :> "get" :> Capture "proposalId" GovActionId :> QueryParam "drepId" HexText :> Get '[JSON] GetProposalResponse + :<|> "proposal" :> "enacted-details" :> QueryParam "type" GovernanceActionType :> Get '[JSON] (Maybe EnactedProposalDetailsResponse) :<|> "epoch" :> "params" :> Get '[JSON] GetCurrentEpochParamsResponse :<|> "transaction" :> "status" :> Capture "transactionId" HexText :> Get '[JSON] GetTransactionStatusResponse :<|> "throw500" :> Get '[JSON] () @@ -95,6 +96,7 @@ server = drepList :<|> getStakeKeyVotingPower :<|> listProposals :<|> getProposal + :<|> getEnactedProposalDetails :<|> getCurrentEpochParams :<|> getTransactionStatus :<|> throw500 @@ -442,6 +444,33 @@ getProposal g@(GovActionId govActionTxHash govActionIndex) mDrepId' = do , getProposalResponseVote = voteResponse } +getEnactedProposalDetails :: App m => Maybe GovernanceActionType -> m (Maybe EnactedProposalDetailsResponse) +getEnactedProposalDetails maybeType = do + let proposalType = maybe "HardForkInitiation" governanceActionTypeToText maybeType + + mDetails <- Proposal.getPreviousEnactedProposal proposalType + + let response = enactedProposalDetailsToResponse <$> mDetails + + return response + where + governanceActionTypeToText :: GovernanceActionType -> Text + governanceActionTypeToText actionType = + case actionType of + HardForkInitiation -> "HardForkInitiation" + ParameterChange -> "ParameterChange" + _ -> "HardForkInitiation" + + enactedProposalDetailsToResponse :: Types.EnactedProposalDetails -> EnactedProposalDetailsResponse + enactedProposalDetailsToResponse Types.EnactedProposalDetails{..} = + EnactedProposalDetailsResponse + { enactedProposalDetailsResponseId = enactedProposalDetailsId + , enactedProposalDetailsResponseTxId = enactedProposalDetailsTxId + , enactedProposalDetailsResponseIndex = enactedProposalDetailsIndex + , enactedProposalDetailsResponseDescription = enactedProposalDetailsDescription + , enactedProposalDetailsResponseHash = HexText enactedProposalDetailsHash + } + getCurrentEpochParams :: App m => m GetCurrentEpochParamsResponse getCurrentEpochParams = do CacheEnv {currentEpochCache} <- asks vvaCache diff --git a/govtool/backend/src/VVA/API/Types.hs b/govtool/backend/src/VVA/API/Types.hs index d1c88adb0..6b517a9ce 100644 --- a/govtool/backend/src/VVA/API/Types.hs +++ b/govtool/backend/src/VVA/API/Types.hs @@ -455,6 +455,40 @@ instance ToSchema ProposalResponse where & example ?~ toJSON exampleProposalResponse +data EnactedProposalDetailsResponse + = EnactedProposalDetailsResponse + { enactedProposalDetailsResponseId :: Integer + , enactedProposalDetailsResponseTxId :: Integer + , enactedProposalDetailsResponseIndex :: Integer + , enactedProposalDetailsResponseDescription :: Maybe Value + , enactedProposalDetailsResponseHash :: HexText + } + deriving (Generic, Show) + +deriveJSON (jsonOptions "enactedProposalDetailsResponse") ''EnactedProposalDetailsResponse + +exampleEnactedProposalDetailsResponse :: Text +exampleEnactedProposalDetailsResponse = "{ \"id\": 123," + <> "\"txId\": 456," + <> "\"index\": 0," + <> "\"description\": {\"key\": \"value\"}," + <> "\"hash\": \"9af10e89979e51b8cdc827c963124a1ef4920d1253eef34a1d5cfe76438e3f11\"}" + +instance ToSchema EnactedProposalDetailsResponse where + declareNamedSchema proxy = do + NamedSchema name_ schema_ <- + genericDeclareNamedSchema + ( fromAesonOptions $ + jsonOptions "enactedProposalDetailsResponse" + ) + proxy + return $ + NamedSchema name_ $ + schema_ + & description ?~ "Enacted Proposal Details Response" + & example + ?~ toJSON exampleEnactedProposalDetailsResponse + exampleListProposalsResponse :: Text exampleListProposalsResponse = "{ \"page\": 0," diff --git a/govtool/backend/src/VVA/Proposal.hs b/govtool/backend/src/VVA/Proposal.hs index 89e72a8c8..6c31a8016 100644 --- a/govtool/backend/src/VVA/Proposal.hs +++ b/govtool/backend/src/VVA/Proposal.hs @@ -17,25 +17,34 @@ import Data.Aeson.Types (Parser, parseMaybe) import Data.ByteString (ByteString) import Data.FileEmbed (embedFile) import Data.Foldable (fold) -import Data.Has (Has) -import qualified Data.Map as Map -import Data.Maybe (fromMaybe) +import Data.Has (Has, getter) +import qualified Data.Map as Map +import Data.Maybe (fromMaybe, isJust) import Data.Monoid (Sum (..), getSum) import Data.Scientific import Data.String (fromString) import Data.Text (Text, pack, unpack) -import qualified Data.Text.Encoding as Text -import qualified Data.Text.IO as Text +import qualified Data.Text.Encoding as Text +import qualified Data.Text.IO as Text import Data.Time -import qualified Database.PostgreSQL.Simple as SQL -import qualified Database.PostgreSQL.Simple.Types as PG +import qualified Database.PostgreSQL.Simple as SQL +import qualified Database.PostgreSQL.Simple.Types as PG import Database.PostgreSQL.Simple.ToField (ToField(..)) import Database.PostgreSQL.Simple.ToRow (ToRow(..)) +import GHC.IO.Unsafe (unsafePerformIO) + import VVA.Config import VVA.Pool (ConnectionPool, withPool) -import VVA.Types (AppError (..), Proposal (..)) +import VVA.Types (AppError (..), Proposal (..), EnactedProposalDetails (..)) + +query1 :: (SQL.ToRow q, SQL.FromRow r) => SQL.Connection -> SQL.Query -> q -> IO (Maybe r) +query1 conn q params = do + results <- SQL.query conn q params + case results of + [x] -> return (Just x) + _ -> return Nothing sqlFrom :: ByteString -> SQL.Query sqlFrom bs = fromString $ unpack $ Text.decodeUtf8 bs @@ -84,4 +93,36 @@ getProposals mSearchTerms = withPool $ \conn -> do Left (e :: SomeException) -> do putStrLn $ "Error fetching proposals: " <> show e return [] - Right rows -> return rows \ No newline at end of file + Right rows -> return rows + +latestEnactedProposalSql :: SQL.Query +latestEnactedProposalSql = + let rawSql = sqlFrom $(embedFile "sql/get-previous-enacted-governance-action-proposal-details.sql") + in unsafePerformIO $ do + putStrLn $ "[DEBUG] SQL query content: " ++ show rawSql + return rawSql + +getPreviousEnactedProposal :: + (Has ConnectionPool r, Has VVAConfig r, MonadReader r m, MonadIO m, MonadFail m, MonadError AppError m) => + Text -> + m (Maybe EnactedProposalDetails) +getPreviousEnactedProposal proposalType = withPool $ \conn -> do + let query = latestEnactedProposalSql + let params = [proposalType] + + result <- liftIO $ try $ do + rows <- SQL.query conn query params :: IO [EnactedProposalDetails] + case rows of + [x] -> return (Just x) + _ -> return Nothing + + case result of + Left err -> do + throwError $ CriticalError $ "Database error: " <> pack (show (err :: SomeException)) + Right proposal -> do + case proposal of + Just details -> do + liftIO $ putStrLn $ "[DEBUG] Previous enacted proposal details: " ++ show details + Nothing -> + liftIO $ putStrLn "[DEBUG] No previous enacted proposal found" + return proposal \ No newline at end of file diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs index 35cdd37bf..e6e674925 100644 --- a/govtool/backend/src/VVA/Types.hs +++ b/govtool/backend/src/VVA/Types.hs @@ -211,6 +211,40 @@ instance ToJSON TransactionStatus where , "votingProcedure" .= votingProcedure ] +data EnactedProposalDetails = EnactedProposalDetails + { enactedProposalDetailsId :: Integer + , enactedProposalDetailsTxId :: Integer + , enactedProposalDetailsIndex :: Integer + , enactedProposalDetailsDescription :: Maybe Value + , enactedProposalDetailsHash :: Text + } + deriving (Show) + +instance FromRow EnactedProposalDetails where + fromRow = + EnactedProposalDetails + <$> field + <*> field + <*> (floor @Scientific <$> field) + <*> field + <*> field + +instance ToJSON EnactedProposalDetails where + toJSON EnactedProposalDetails + { enactedProposalDetailsId + , enactedProposalDetailsTxId + , enactedProposalDetailsIndex + , enactedProposalDetailsDescription + , enactedProposalDetailsHash + } = + object + [ "id" .= enactedProposalDetailsId + , "tx_id" .= enactedProposalDetailsTxId + , "index" .= enactedProposalDetailsIndex + , "description" .= enactedProposalDetailsDescription + , "hash" .= enactedProposalDetailsHash + ] + data CacheEnv = CacheEnv { proposalListCache :: Cache.Cache () [Proposal] diff --git a/govtool/backend/vva-be.cabal b/govtool/backend/vva-be.cabal index 1accd1af4..f3131a070 100644 --- a/govtool/backend/vva-be.cabal +++ b/govtool/backend/vva-be.cabal @@ -36,6 +36,7 @@ extra-source-files: sql/get-network-total-stake.sql sql/get-dreps-voting-power-list.sql sql/get-filtered-dreps-voting-power.sql + sql/get-previous-enacted-governance-action-proposal-details.sql executable vva-be main-is: Main.hs diff --git a/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/CreateGovernanceActionForm.tsx b/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/CreateGovernanceActionForm.tsx index 5f3e9b010..fbf3f0bd6 100644 --- a/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/CreateGovernanceActionForm.tsx +++ b/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/CreateGovernanceActionForm.tsx @@ -50,6 +50,8 @@ export const CreateGovernanceActionForm = ({ | GovernanceActionType.NewCommittee | GovernanceActionType.NewConstitution | GovernanceActionType.NoConfidence + | GovernanceActionType.HardForkInitiation + | GovernanceActionType.ParameterChange ], ).some( (field) => !watch(field as unknown as Parameters[0]), @@ -73,6 +75,8 @@ export const CreateGovernanceActionForm = ({ | GovernanceActionType.NewCommittee | GovernanceActionType.NewConstitution | GovernanceActionType.NoConfidence + | GovernanceActionType.HardForkInitiation + | GovernanceActionType.ParameterChange ], ).map(([key, field]) => { const fieldProps = { @@ -85,6 +89,7 @@ export const CreateGovernanceActionForm = ({ ? t(field.placeholderI18nKey) : undefined, rules: field.rules, + maxLength: field.maxLength, }; if (field.component === GovernanceActionField.Input) { diff --git a/govtool/frontend/src/consts/governanceAction/fields.ts b/govtool/frontend/src/consts/governanceAction/fields.ts index 0367b4799..2b8585390 100644 --- a/govtool/frontend/src/consts/governanceAction/fields.ts +++ b/govtool/frontend/src/consts/governanceAction/fields.ts @@ -262,6 +262,88 @@ export const GOVERNANCE_ACTION_FIELDS: GovernanceActionFields = { "createGovernanceAction.fields.declarations.scriptHash.placeholder", }, }, + [GovernanceActionType.HardForkInitiation]: { + ...sharedGovernanceActionFields, + prevGovernanceActionHash: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionHash.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionHash.placeholder", + }, + prevGovernanceActionIndex: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionIndex.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionIndex.placeholder", + rules: { + validate: numberValidation, + }, + }, + major: { + component: GovernanceActionField.Input, + labelI18nKey: "createGovernanceAction.fields.declarations.major.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.major.placeholder", + rules: { + required: { + value: true, + message: I18n.t("createGovernanceAction.fields.validations.required"), + }, + validate: numberValidation, + }, + }, + minor: { + component: GovernanceActionField.Input, + labelI18nKey: "createGovernanceAction.fields.declarations.minor.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.minor.placeholder", + rules: { + required: { + value: true, + message: I18n.t("createGovernanceAction.fields.validations.required"), + }, + validate: numberValidation, + }, + }, + }, + [GovernanceActionType.ParameterChange]: { + ...sharedGovernanceActionFields, + prevGovernanceActionHash: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionHash.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionHash.placeholder", + }, + prevGovernanceActionIndex: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionIndex.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionIndex.placeholder", + rules: { + validate: numberValidation, + }, + }, + protocolParameters: { + component: GovernanceActionField.TextArea, + maxLength: 5000, + labelI18nKey: + "createGovernanceAction.fields.declarations.protocolParameters.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.protocolParameters.placeholder", + rules: { + required: { + value: true, + message: I18n.t("createGovernanceAction.fields.validations.required"), + }, + }, + tipI18nKey: + "createGovernanceAction.fields.declarations.protocolParameters.tip", + }, + }, } as const; export const GOVERNANCE_ACTION_CONTEXT = { diff --git a/govtool/frontend/src/context/wallet.tsx b/govtool/frontend/src/context/wallet.tsx index a9a38f2a9..c7a6d1492 100644 --- a/govtool/frontend/src/context/wallet.tsx +++ b/govtool/frontend/src/context/wallet.tsx @@ -130,7 +130,7 @@ type TreasuryProps = { type ProtocolParameterChangeProps = { prevGovernanceActionHash: string; - prevGovernanceActionIndex: number; + prevGovernanceActionIndex: string; protocolParamsUpdate: Partial; } & VotingAnchor; @@ -166,7 +166,6 @@ export type QuorumThreshold = { numerator: string; denominator: string; }; - type ProtocolParamsUpdate = { adaPerUtxo: string; collateralPercentage: number; @@ -1343,7 +1342,7 @@ const CardanoProvider = (props: Props) => { if (prevGovernanceActionHash && prevGovernanceActionIndex) { const prevGovernanceActionId = GovernanceActionId.new( TransactionHash.from_hex(prevGovernanceActionHash), - prevGovernanceActionIndex, + Number(prevGovernanceActionIndex), ); protocolParamChangeAction = ParameterChangeAction.new_with_policy_hash_and_action_id( diff --git a/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts b/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts index f792c2bfa..c13eb5bb6 100644 --- a/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts +++ b/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts @@ -1,4 +1,10 @@ -import { Dispatch, SetStateAction, useCallback, useState } from "react"; +import { + Dispatch, + SetStateAction, + useCallback, + useEffect, + useState, +} from "react"; import { useNavigate } from "react-router-dom"; import { useFormContext } from "react-hook-form"; import { blake2bHex } from "blakejs"; @@ -60,6 +66,8 @@ export const useCreateGovernanceActionForm = ( buildNewConstitutionGovernanceAction, buildUpdateCommitteeGovernanceAction, buildSignSubmitConwayCertTx, + buildHardForkGovernanceAction, + buildProtocolParameterChangeGovernanceAction, } = useCardano(); // App Management @@ -85,6 +93,12 @@ export const useCreateGovernanceActionForm = ( } = useFormContext(); const govActionType = watch("governance_action_type"); + useEffect(() => { + if (govActionType === GovernanceActionType.ParameterChange) { + setValue("protocolParameters", JSON.stringify(protocolParams)); + } + }, [govActionType]); + // Navigation const backToForm = useCallback(() => { setStep?.(3); @@ -212,6 +226,48 @@ export const useCreateGovernanceActionForm = ( return buildTreasuryGovernanceAction(treasuryActionDetails); } + case GovernanceActionType.HardForkInitiation: { + if ( + data.major === undefined || + data.minor === undefined || + data.prevGovernanceActionHash === undefined || + data.prevGovernanceActionIndex === undefined + ) { + throw new Error( + t("errors.invalidHardForkInitiationGovernanceActionType"), + ); + } + const hardForkActionDetails = { + ...commonGovActionDetails, + prevGovernanceActionHash: data.prevGovernanceActionHash, + prevGovernanceActionIndex: data.prevGovernanceActionIndex, + major: data.major, + minor: data.minor, + }; + return buildHardForkGovernanceAction(hardForkActionDetails); + } + + case GovernanceActionType.ParameterChange: { + if ( + data.protocolParameters === undefined || + data.prevGovernanceActionHash === undefined || + data.prevGovernanceActionIndex === undefined + ) { + throw new Error( + t("errors.invalidParameterChangeGovernanceActionType"), + ); + } + const protocolParamsUpdate = JSON.parse(data.protocolParameters); + const parameterChangeActionDetails = { + ...commonGovActionDetails, + protocolParamsUpdate, + prevGovernanceActionHash: data.prevGovernanceActionHash, + prevGovernanceActionIndex: data.prevGovernanceActionIndex, + }; + return buildProtocolParameterChangeGovernanceAction( + parameterChangeActionDetails, + ); + } default: throw new Error(t("errors.invalidGovernanceActionType")); } diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index d057b97cb..9e259798d 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -205,6 +205,21 @@ "label": "New Constitution Script Hash", "placeholder": "New Constitution Script Hash", "tip": "Script hash of the new constitution" + }, + "major": { + "label": "Major", + "placeholder": "Major version", + "tip": "Major version of the new hard fork" + }, + "minor": { + "label": "Minor", + "placeholder": "Minor version", + "tip": "Minor version of the new hard fork" + }, + "protocolParameters": { + "label": "Protocol Parameters", + "placeholder": "Protocol parameters", + "tip": "Protocol parameters to be changed" } }, "validations": { diff --git a/govtool/frontend/src/types/governanceAction.ts b/govtool/frontend/src/types/governanceAction.ts index 77bad990a..bdc53934f 100644 --- a/govtool/frontend/src/types/governanceAction.ts +++ b/govtool/frontend/src/types/governanceAction.ts @@ -12,8 +12,8 @@ export enum GovernanceActionType { } export enum GovernanceActionField { - Input = "input", - TextArea = "textarea", + Input = "Input", + TextArea = "TextArea", } export type FieldSchema = { @@ -22,6 +22,7 @@ export type FieldSchema = { placeholderI18nKey: NestedKeys; tipI18nKey?: NestedKeys; rules?: Omit; + maxLength?: number; }; // Following properties are based on [CIP-108](https://github.com/Ryun1/CIPs/blob/governance-metadata-actions/CIP-0108/README.md) @@ -60,19 +61,27 @@ export type NewConstitutionActionFieldSchema = Partial<{ constitutionHash: FieldSchema; scriptHash: FieldSchema; }>; +export type ProtocolParameterActionFieldSchema = Partial<{ + prevGovernanceActionHash: FieldSchema; + prevGovernanceActionIndex: FieldSchema; + protocolParameters: FieldSchema; +}>; export type GovernanceActionFieldSchemas = | SharedGovernanceActionFieldSchema & TreasuryGovernanceActionFieldSchema & NewCommitteeActionFieldSchema & HardForkInitiationActionFieldSchema & - NewConstitutionActionFieldSchema; + NewConstitutionActionFieldSchema & + ProtocolParameterActionFieldSchema; export type GovernanceActionFields = Record< | GovernanceActionType.InfoAction | GovernanceActionType.TreasuryWithdrawals | GovernanceActionType.NoConfidence | GovernanceActionType.NewCommittee - | GovernanceActionType.NewConstitution, + | GovernanceActionType.NewConstitution + | GovernanceActionType.HardForkInitiation + | GovernanceActionType.ParameterChange, GovernanceActionFieldSchemas >; From 60721e24fb363fb53f1121aa4f7adc90cd2bb2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Fri, 16 May 2025 14:11:59 +0200 Subject: [PATCH 23/75] feat(#3622): home page redesign --- .../src/components/molecules/Card.tsx | 31 +-- .../src/components/molecules/HomeCard.tsx | 34 ++++ .../src/components/organisms/Hero.tsx | 109 ----------- .../organisms/Home/ConnectWalletTo.tsx | 142 ++++++++++++++ .../organisms/Home/HelpBuildGovTool.tsx | 60 ++++++ .../components/organisms/Home/OpenToAny.tsx | 116 +++++++++++ .../src/components/organisms/Home/Socials.tsx | 53 +++++ .../organisms/{ => Home}/UsefulLinks.tsx | 63 ++++-- .../src/components/organisms/Home/index.ts | 5 + .../src/components/organisms/HomeCards.tsx | 151 --------------- .../src/components/organisms/index.ts | 3 +- govtool/frontend/src/consts/index.ts | 10 + govtool/frontend/src/i18n/locales/en.json | 182 +++++++++++++++--- govtool/frontend/src/pages/DashboardHome.tsx | 6 +- govtool/frontend/src/pages/Home.tsx | 57 ++++-- 15 files changed, 693 insertions(+), 329 deletions(-) create mode 100644 govtool/frontend/src/components/molecules/HomeCard.tsx delete mode 100644 govtool/frontend/src/components/organisms/Hero.tsx create mode 100644 govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx create mode 100644 govtool/frontend/src/components/organisms/Home/HelpBuildGovTool.tsx create mode 100644 govtool/frontend/src/components/organisms/Home/OpenToAny.tsx create mode 100644 govtool/frontend/src/components/organisms/Home/Socials.tsx rename govtool/frontend/src/components/organisms/{ => Home}/UsefulLinks.tsx (64%) create mode 100644 govtool/frontend/src/components/organisms/Home/index.ts delete mode 100644 govtool/frontend/src/components/organisms/HomeCards.tsx diff --git a/govtool/frontend/src/components/molecules/Card.tsx b/govtool/frontend/src/components/molecules/Card.tsx index 6e18617b1..dd2912d68 100644 --- a/govtool/frontend/src/components/molecules/Card.tsx +++ b/govtool/frontend/src/components/molecules/Card.tsx @@ -1,19 +1,20 @@ -import { Chip, Paper, SxProps } from "@mui/material"; +import { Chip, Paper, SxProps, PaperProps } from "@mui/material"; import { Theme } from "@mui/material/styles"; import { PropsWithChildren } from "react"; import { errorRed, orange, primaryBlue, successGreen } from "@/consts"; -type CardProps = PropsWithChildren & { - border?: boolean; - elevation?: number; - dataTestId?: string; - label?: string; - labelDataTestId?: string; - sx?: SxProps; - variant?: "default" | "error" | "primary" | "success" | "warning"; - onCardClick?: () => void; -}; +type CardProps = Omit & + PropsWithChildren & { + border?: boolean; + elevation?: number; + dataTestId?: string; + label?: string; + labelDataTestId?: string; + sx?: SxProps; + variant?: "default" | "error" | "primary" | "success" | "warning"; + onCardClick?: () => void; + }; const COLORS = { default: { @@ -48,14 +49,22 @@ export const Card = ({ labelDataTestId = "card-label", sx, onCardClick, + ...props }: CardProps) => { const colors = COLORS[variant]; return ( { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + onCardClick?.(); + } + }} sx={{ backgroundColor: (theme) => colors.backgroundColor ?? `${theme.palette.neutralWhite}4D`, diff --git a/govtool/frontend/src/components/molecules/HomeCard.tsx b/govtool/frontend/src/components/molecules/HomeCard.tsx new file mode 100644 index 000000000..ef896e4eb --- /dev/null +++ b/govtool/frontend/src/components/molecules/HomeCard.tsx @@ -0,0 +1,34 @@ +import { Card } from "./Card"; +import { Typography } from "../atoms"; + +type Props = { + title: string; + description: string; + onCardClick?: () => void; +}; + +export const HomeCard = ({ title, description, onCardClick }: Props) => ( + + {title} + {description} + +); diff --git a/govtool/frontend/src/components/organisms/Hero.tsx b/govtool/frontend/src/components/organisms/Hero.tsx deleted file mode 100644 index a69726264..000000000 --- a/govtool/frontend/src/components/organisms/Hero.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import { useMemo } from "react"; -import { Trans } from "react-i18next"; -import { Box, Link } from "@mui/material"; -import { ArrowDownward } from "@mui/icons-material"; - -import { Button, Typography } from "@atoms"; -import { IMAGES } from "@consts"; -import { useScreenDimension, useTranslation } from "@hooks"; -import { openInNewTab } from "@utils"; - -export const Hero = () => { - const { isMobile, screenWidth } = useScreenDimension(); - const { t } = useTranslation(); - const IMAGE_SIZE = screenWidth < 640 ? 300 : screenWidth < 860 ? 400 : 600; - - const paddingHorizontal = useMemo(() => { - if (screenWidth < 640) return 3; - if (screenWidth < 1512) return 9.375; - if (screenWidth < 1728) return 14; - if (screenWidth < 1920) return 27.375; - if (screenWidth < 2560) return 39.375; - return 49.25; - }, [screenWidth]); - - const imageRightMargin = useMemo(() => { - if (screenWidth <= 860) return -(IMAGE_SIZE / 4); - if (screenWidth <= 1440) return -(IMAGE_SIZE / 15); - if (screenWidth <= 1728) return screenWidth / 20; - return screenWidth / 11; - }, [screenWidth]); - - const onClickVotingPower = () => - openInNewTab("https://docs.cardano.org/about-cardano/governance-overview"); - - return ( - - - - {t("hero.headline")} - - - , - ]} - /> - - - - - hero - - - ); -}; diff --git a/govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx b/govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx new file mode 100644 index 000000000..28dce86a2 --- /dev/null +++ b/govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx @@ -0,0 +1,142 @@ +import { Box } from "@mui/material"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; + +import I18n from "@/i18n"; +import { BUDGET_DISCUSSION_PATHS, PATHS, PDF_PATHS } from "@/consts"; +import { useCardano, useModal } from "@/context"; + +import { Typography, Button } from "../../atoms"; +import { HomeCard } from "../../molecules/HomeCard"; + +const isProposalDiscussionForumEnabled = JSON.parse( + import.meta.env.VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED || false, +); + +const CONNECT_WALLET_TO_CARDS = [ + ...(isProposalDiscussionForumEnabled + ? [ + { + title: I18n.t( + "home.connectWalletTo.cards.discussBudgetProposals.title", + ), + description: I18n.t( + "home.connectWalletTo.cards.discussBudgetProposals.description", + ), + path: BUDGET_DISCUSSION_PATHS.budgetDiscussion, + }, + { + title: I18n.t( + "home.connectWalletTo.cards.createBudgetProposal.title", + ), + description: I18n.t( + "home.connectWalletTo.cards.createBudgetProposal.description", + ), + path: BUDGET_DISCUSSION_PATHS.budgetDiscussion, + }, + { + title: I18n.t( + "home.connectWalletTo.cards.discussGovernanceActions.title", + ), + description: I18n.t( + "home.connectWalletTo.cards.discussGovernanceActions.description", + ), + path: PDF_PATHS.proposalDiscussion, + }, + { + title: I18n.t( + "home.connectWalletTo.cards.proposeGovernanceAction.title", + ), + description: I18n.t( + "home.connectWalletTo.cards.proposeGovernanceAction.description", + ), + path: PDF_PATHS.proposalDiscussionPropose, + }, + ] + : []), + { + title: I18n.t("home.connectWalletTo.cards.registerToVote.title"), + description: I18n.t( + "home.connectWalletTo.cards.registerToVote.description", + ), + path: PATHS.registerAsDirectVoter, + }, + { + title: I18n.t("home.connectWalletTo.cards.delegateVote.title"), + description: I18n.t("home.connectWalletTo.cards.delegateVote.description"), + path: PATHS.dRepDirectory, + }, + { + title: I18n.t("home.connectWalletTo.cards.becomeDRep.title"), + description: I18n.t("home.connectWalletTo.cards.becomeDRep.description"), + path: PATHS.registerAsdRep, + }, + { + title: I18n.t("home.connectWalletTo.cards.voteOnGovernanceActions.title"), + description: I18n.t( + "home.connectWalletTo.cards.voteOnGovernanceActions.description", + ), + path: PATHS.dashboardGovernanceActions, + }, +]; + +export const ConnectWalletTo = () => { + const { t } = useTranslation(); + const { openModal } = useModal(); + const { isEnabled, stakeKey } = useCardano(); + const navigate = useNavigate(); + + const handleCardClick = ({ path }: { path?: string }) => { + if (!path) return; + openModal({ + type: "chooseWallet", + state: { + pathToNavigate: path, + }, + }); + }; + + const onClickConnectButton = () => { + if (isEnabled && stakeKey) { + navigate(PATHS.dashboard); + } + openModal({ type: "chooseWallet" }); + }; + + return ( + + + + {t("home.connectWalletTo.section.title")} + + + + + {CONNECT_WALLET_TO_CARDS.map(({ title, description, path }) => ( + handleCardClick({ path }) : undefined} + /> + ))} + + + ); +}; diff --git a/govtool/frontend/src/components/organisms/Home/HelpBuildGovTool.tsx b/govtool/frontend/src/components/organisms/Home/HelpBuildGovTool.tsx new file mode 100644 index 000000000..2fb058c13 --- /dev/null +++ b/govtool/frontend/src/components/organisms/Home/HelpBuildGovTool.tsx @@ -0,0 +1,60 @@ +import { Box } from "@mui/material"; +import { useTranslation } from "react-i18next"; + +import I18n from "@/i18n"; +import { GOVTOOL_URLS } from "@/consts"; + +import { Typography } from "../../atoms"; +import { HomeCard } from "../../molecules/HomeCard"; +import { openInNewTab } from "@/utils"; + +const GOVTOOL_CARD_LINKS = [ + { + title: I18n.t("home.helpBuildGovTool.cards.githubRepo.title"), + description: I18n.t("home.helpBuildGovTool.cards.githubRepo.description"), + url: GOVTOOL_URLS.githubRepo, + }, + { + title: I18n.t("home.helpBuildGovTool.cards.documentation.title"), + description: I18n.t( + "home.helpBuildGovTool.cards.documentation.description", + ), + url: GOVTOOL_URLS.documentation, + }, +]; + +export const HelpBuildGovTool = ({ my = 4 }: { my?: number }) => { + const { t } = useTranslation(); + + const handleCardClick = ({ url }: { url?: string }) => { + if (!url) return; + openInNewTab(url); + }; + + return ( + + + {t("home.helpBuildGovTool.section.title")} + + + {GOVTOOL_CARD_LINKS.map(({ title, description, url }) => ( + handleCardClick({ url }) : undefined} + /> + ))} + + + ); +}; diff --git a/govtool/frontend/src/components/organisms/Home/OpenToAny.tsx b/govtool/frontend/src/components/organisms/Home/OpenToAny.tsx new file mode 100644 index 000000000..5d42a362c --- /dev/null +++ b/govtool/frontend/src/components/organisms/Home/OpenToAny.tsx @@ -0,0 +1,116 @@ +import { Box } from "@mui/material"; +import { useNavigate } from "react-router-dom"; +import { useTranslation } from "react-i18next"; + +import I18n from "@/i18n"; +import { + BUDGET_DISCUSSION_PATHS, + OUTCOMES_PATHS, + PATHS, + PDF_PATHS, +} from "@/consts"; +import { openInNewTab } from "@/utils"; + +import { Typography } from "../../atoms"; +import { HomeCard } from "../../molecules/HomeCard"; + +const isProposalDiscussionForumEnabled = JSON.parse( + import.meta.env.VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED || false, +); + +const isOutcomesEnabled = JSON.parse( + import.meta.env.VITE_IS_GOVERNANCE_OUTCOMES_PILLAR_ENABLED || false, +); + +const OPEN_TO_ANY_CARDS = [ + { + title: I18n.t("home.openToAny.cards.drepDirectory.title"), + description: I18n.t("home.openToAny.cards.drepDirectory.description"), + path: PATHS.dRepDirectory, + }, + ...(isProposalDiscussionForumEnabled + ? [ + { + title: I18n.t("home.openToAny.cards.budgetProposal.title"), + description: I18n.t( + "home.openToAny.cards.budgetProposal.description", + ), + path: BUDGET_DISCUSSION_PATHS.budgetDiscussion, + }, + { + title: I18n.t("home.openToAny.cards.proposalDiscussion.title"), + description: I18n.t( + "home.openToAny.cards.proposalDiscussion.description", + ), + path: PDF_PATHS.proposalDiscussion, + }, + ] + : []), + { + title: I18n.t("home.openToAny.cards.governanceActions.title"), + description: I18n.t("home.openToAny.cards.governanceActions.description"), + path: PATHS.governanceActions, + }, + ...(isOutcomesEnabled + ? [ + { + title: I18n.t("home.openToAny.cards.governanceOutcomes.title"), + description: I18n.t( + "home.openToAny.cards.governanceOutcomes.description", + ), + path: OUTCOMES_PATHS.governanceActionsOutcomes, + }, + ] + : []), + { + title: I18n.t("home.openToAny.cards.guides.title"), + description: I18n.t("home.openToAny.cards.guides.description"), + url: "https://docs.gov.tools/cardano-govtool/using-govtool", + }, +]; + +export const OpenToAny = () => { + const navigate = useNavigate(); + const { t } = useTranslation(); + + const handleCardClick = ({ path, url }: { path?: string; url?: string }) => { + if (path) { + navigate(path); + } else if (url) { + openInNewTab(url); + } + }; + + return ( + + + {t("home.openToAny.section.title")} + + + {OPEN_TO_ANY_CARDS.map(({ title, description, path, url }) => ( + handleCardClick({ path, url }) : undefined + } + /> + ))} + + + ); +}; diff --git a/govtool/frontend/src/components/organisms/Home/Socials.tsx b/govtool/frontend/src/components/organisms/Home/Socials.tsx new file mode 100644 index 000000000..2420e8e8c --- /dev/null +++ b/govtool/frontend/src/components/organisms/Home/Socials.tsx @@ -0,0 +1,53 @@ +import { Box } from "@mui/material"; +import { useTranslation } from "react-i18next"; + +import I18n from "@/i18n"; +import { SOCIAL_MEDIA_URLS } from "@/consts"; + +import { Typography } from "../../atoms"; +import { HomeCard } from "../../molecules/HomeCard"; +import { openInNewTab } from "@/utils"; + +const SOCIAL_CARDS = [ + { + title: I18n.t("home.joinDiscussion.cards.discord.title"), + description: I18n.t("home.joinDiscussion.cards.discord.description"), + url: SOCIAL_MEDIA_URLS.discord, + }, +]; + +export const Socials = ({ my = 4 }: { my?: number }) => { + const { t } = useTranslation(); + + const handleCardClick = ({ url }: { url?: string }) => { + if (!url) return; + openInNewTab(url); + }; + + return ( + + + {t("home.joinDiscussion.section.title")} + + + {SOCIAL_CARDS.map(({ title, description, url }) => ( + handleCardClick({ url }) : undefined} + /> + ))} + + + ); +}; diff --git a/govtool/frontend/src/components/organisms/UsefulLinks.tsx b/govtool/frontend/src/components/organisms/Home/UsefulLinks.tsx similarity index 64% rename from govtool/frontend/src/components/organisms/UsefulLinks.tsx rename to govtool/frontend/src/components/organisms/Home/UsefulLinks.tsx index 90bc1a740..62fbebe9f 100644 --- a/govtool/frontend/src/components/organisms/UsefulLinks.tsx +++ b/govtool/frontend/src/components/organisms/Home/UsefulLinks.tsx @@ -1,9 +1,10 @@ import { Box, Link } from "@mui/material"; import { useTranslation } from "@hooks"; -import { Typography } from "../atoms"; import { ICONS } from "@/consts"; -import { Card } from "../molecules"; + +import { Typography } from "../../atoms"; +import { Card } from "../../molecules"; const LINKS = { ccPortal: { @@ -12,6 +13,45 @@ const LINKS = { intersectWebsite: { url: "https://www.intersectmbo.org/", }, + tempo: { + url: "https://tempo.vote/", + }, + "1694io": { + url: "https://www.1694.io/", + }, + governanceSpace: { + url: "https://governancespace.com/", + }, + syncAi: { + url: "https://www.syncgovhub.com/app", + }, + ekklesia: { + url: "https://2025budget.intersectmbo.org/", + }, + adaStat: { + url: "https://adastat.net/", + }, + cexplorer: { + url: "https://cexplorer.io/", + }, + cardanoScan: { + url: "https://cardanoscan.io/", + }, + cardanoBudget: { + url: "https://cardanobudget.com/", + }, + budgetCardanoAfrica: { + url: "https://budget.cardano.africa/", + }, + reachYourPeople: { + url: "https://www.ryp.io/", + }, + "1694Tools": { + url: "https://1694-tools.vercel.app/", + }, + sanchonetGovernanceExplorer: { + url: "https://sancho.cardanoconnect.io/", + }, } as const; type Props = { @@ -23,19 +63,18 @@ export const UsefulLinks = ({ align = "left" }: Props) => { return (
- + {t("usefulLinks.title")} {Object.entries(LINKS).map(([key, { url }]) => ( { sx={{ flexBasis: 0, boxShadow: "2px 2px 20px 0px rgba(47, 98, 220, 0.20)", - maxWidth: 464, - minWidth: 264, minHeight: 196, boxSizing: "border-box", display: "flex", diff --git a/govtool/frontend/src/components/organisms/Home/index.ts b/govtool/frontend/src/components/organisms/Home/index.ts new file mode 100644 index 000000000..e514c04dc --- /dev/null +++ b/govtool/frontend/src/components/organisms/Home/index.ts @@ -0,0 +1,5 @@ +export * from "./ConnectWalletTo"; +export * from "./HelpBuildGovTool"; +export * from "./OpenToAny"; +export * from "./Socials"; +export * from "./UsefulLinks"; diff --git a/govtool/frontend/src/components/organisms/HomeCards.tsx b/govtool/frontend/src/components/organisms/HomeCards.tsx deleted file mode 100644 index d456cb2d3..000000000 --- a/govtool/frontend/src/components/organisms/HomeCards.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import { useCallback } from "react"; -import { useNavigate } from "react-router-dom"; -import { Box } from "@mui/material"; - -import { IMAGES, PATHS, PDF_PATHS } from "@consts"; -import { useFeatureFlag, useModal } from "@context"; -import { ActionCard } from "@molecules"; -import { useTranslation } from "@hooks"; -import { openInNewTab } from "@utils"; -import { LINKS } from "@/consts/links"; - -export const HomeCards = () => { - const { isProposalDiscussionForumEnabled } = useFeatureFlag(); - const navigate = useNavigate(); - const { openModal } = useModal(); - const { t } = useTranslation(); - - const openWalletModal = useCallback( - (pathToNavigate: string) => { - openModal({ - type: "chooseWallet", - state: { - pathToNavigate, - }, - }); - }, - [openModal], - ); - - const onClickLearnMoreAboutDelegation = () => openInNewTab(LINKS.DELEGATING); - - const onClickLearnMoreAboutDRepRegistration = () => - openInNewTab(LINKS.REGISTER_AS_A_DREP); - - const onClickLearnMoreAboutDirectVoterRegistration = () => - openInNewTab(LINKS.DIRECT_VOTING); - - const onClickLearnMoreAboutProposingGovAction = () => - openInNewTab(LINKS.PROPOSE_A_GOVERNANCE_ACTION); - - const navigateToGovActions = useCallback( - () => navigate(PATHS.governanceActions), - [navigate], - ); - - const navigateToDRepDirecotry = useCallback( - () => navigate(PATHS.dRepDirectory), - [navigate], - ); - - const navigateToProposalDiscussionPillar = useCallback( - () => navigate(PDF_PATHS.proposalDiscussion), - [navigate], - ); - - return ( - - {/* DELEGATE CARD */} - - {/* DELEGATE CARD END */} - {/* REGISTER AS DREP CARD */} - openWalletModal(PATHS.registerAsdRep)} - firstButtonLabel={t("home.cards.registerAsDRep.firstButtonLabel")} - imageHeight={80} - imageURL={IMAGES.govActionRegisterImage} - imageWidth={70} - secondButtonAction={onClickLearnMoreAboutDRepRegistration} - secondButtonLabel={t("learnMore")} - title={t("home.cards.registerAsDRep.title")} - /> - {/* REGISTER AS DREP CARD END */} - {/* REGISTER AS DIRECT VOTER CARD */} - openWalletModal(PATHS.registerAsDirectVoter)} - firstButtonLabel={t( - "home.cards.registerAsDirectVoter.firstButtonLabel", - )} - imageHeight={84} - imageURL={IMAGES.directVoterImage} - imageWidth={84} - secondButtonAction={onClickLearnMoreAboutDirectVoterRegistration} - secondButtonLabel={t("learnMore")} - title={t("home.cards.registerAsDirectVoter.title")} - /> - {/* REGISTER AS DIRECT VOTER CARD END */} - {/* GOV ACTIONS CARD */} - - {/* GOV ACTIONS CARD END */} - {/* PROPOSE GOV ACTION CARD */} - openWalletModal(PATHS.createGovernanceAction)} - firstButtonLabel={t( - "home.cards.proposeAGovernanceAction.firstButtonLabel", - )} - imageHeight={84} - imageURL={IMAGES.proposeGovActionImage} - imageWidth={84} - secondButtonAction={ - isProposalDiscussionForumEnabled - ? navigateToProposalDiscussionPillar - : onClickLearnMoreAboutProposingGovAction - } - secondButtonLabel={t( - isProposalDiscussionForumEnabled - ? "home.cards.proposeAGovernanceAction.secondButtonLabel" - : "learnMore", - )} - title={t("home.cards.proposeAGovernanceAction.title")} - /> - {/* PROPOSE GOV ACTION CARD END */} - - ); -}; diff --git a/govtool/frontend/src/components/organisms/index.ts b/govtool/frontend/src/components/organisms/index.ts index f1c136904..c3ade3106 100644 --- a/govtool/frontend/src/components/organisms/index.ts +++ b/govtool/frontend/src/components/organisms/index.ts @@ -18,8 +18,6 @@ export * from "./Footer"; export * from "./GovernanceActionDetailsCard"; export * from "./GovernanceActionDetailsCardData"; export * from "./GovernanceActionsToVote"; -export * from "./Hero"; -export * from "./HomeCards"; export * from "./Modal"; export * from "./RegisterAsDRepSteps"; export * from "./Slider"; @@ -29,3 +27,4 @@ export * from "./ValidatedGovernanceActionCard"; export * from "./ValidatedGovernanceVotedOnCard"; export * from "./VoteContext"; export * from "./WrongRouteInfo"; +export * from "./Home"; diff --git a/govtool/frontend/src/consts/index.ts b/govtool/frontend/src/consts/index.ts index f07ea2941..a11ef438c 100644 --- a/govtool/frontend/src/consts/index.ts +++ b/govtool/frontend/src/consts/index.ts @@ -92,3 +92,13 @@ export const PPU_GOVERNANCE_GROUP_PARAMS_KEYS = [ "committeeMinSize", "committeeMaxTermLength", ]; + +export const SOCIAL_MEDIA_URLS = { + discord: + "https://discord.com/channels/1136727663583698984/1212344688523214869", +}; + +export const GOVTOOL_URLS = { + githubRepo: "https://github.com/IntersectMBO/govtool", + documentation: "https://docs.gov.tools", +}; diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index 9e259798d..3740ee0da 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -556,36 +556,95 @@ }, "hero": { "connectWallet": "Participate now", - "description": "Cardano Governance lets Ada holders have a say in the network's future.\n\nYou can vote directly, find someone to represent you, or become a representative for others.\n\nYou can also propose changes in the network yourself, put these up for discussion and eventually, a vote.\n\n<0>Learn more about governance in the guide, or have a look around the app and see Cardano Governance in action.", - "headline": "Cardano \n Governance Tool" + "description": "An Open Source Governance Application for the Cardano Blockchain\n<0>Learn more about Cardano Governance" }, "home": { - "cards": { - "delegate": { - "description": "Find a DRep to vote on your behalf.", - "firstButtonLabel": "View DRep Directory", - "title": "Delegate your Voting Power" - }, - "governanceActions": { - "description": "See all the Governance Actions submitted on chain. ", - "firstButtonLabel": "View Governance Actions", - "title": "View Governance Actions" - }, - "proposeAGovernanceAction": { - "description": "Submit your proposal for a Governance Action.", - "secondButtonLabel": "View Proposals", - "firstButtonLabel": "Connect to Propose", - "title": "Propose a Governance Action" - }, - "registerAsDRep": { - "description": "Accept delegated voting power from other Ada holders, and combine it with your own voting power. Vote with the accumulated Power on Governance Actions.", - "firstButtonLabel": "Connect to Register", - "title": "Become a DRep" - }, - "registerAsDirectVoter": { - "description": "Vote on Governance Actions using your own voting power", - "firstButtonLabel": "Connect to Register", - "title": "Become a Direct Voter" + "openToAny": { + "section": { "title": "Open to any and all users:" }, + "cards": { + "drepDirectory": { + "description": "DReps are representatives that vote for others.", + "title": "Browse the DRep Directory" + }, + "budgetProposal": { + "description": "Budget proposal and comments are open to public inspection.", + "title": "View Budget Proposals" + }, + "proposalDiscussion": { + "description": "Any user can read the proposals and view comments on future Actions.", + "title": "See Proposed Governance Actions" + }, + "governanceActions": { + "description": "See how the voting is progressing on any Governance Action.", + "title": "View Live Voting" + }, + "governanceOutcomes": { + "description": "See the outcomes and final votes on any Governance Action.", + "title": "View Voting Outcomes" + }, + "guides": { + "description": "The roadmap to this tool, to get you started in Cardano Governance.", + "title": "Read our Guides" + } + } + }, + "connectWalletTo": { + "section": { "title": "Connect a Cardano Wallet to:" }, + "cards": { + "discussBudgetProposals": { + "description": "Read comments and participate in discussions for Budget requests.", + "title": "Discuss Budget Proposals" + }, + "createBudgetProposal": { + "description": "Create a proposal to fund your project from the Cardano treasury.", + "title": "Create a Budget Proposal" + }, + "discussGovernanceActions": { + "description": "Read comments and participate in discussions for Governance Actions.", + "title": "Discuss Governance Actions" + }, + "proposeGovernanceAction": { + "description": "Create a discussion for an Action, and submit it on-chain.", + "title": "Propose a Governace Action" + }, + "registerToVote": { + "description": "Register yourself to vote on all Governace Actions", + "title": "Register to Vote" + }, + "delegateVote": { + "description": "Delegate your voting power to a representative (they vote for you).", + "title": "Delegate your vote to a DRep" + }, + "becomeDRep": { + "description": "DReps are representatives that vote for others.", + "title": "Become a DRep" + }, + "voteOnGovernanceActions": { + "description": "Cast your vote on Governance Actions as yourself or as a DRep.", + "title": "Vote on Governace Actions" + } + } + }, + "joinDiscussion": { + "section": { "title": "Join the discussion on social media" }, + "cards": { + "discord": { + "title": "Discord", + "description": "Governance Tools working group" + } + } + }, + "helpBuildGovTool": { + "section": { "title": "Help build GovTool" }, + "cards": { + "githubRepo": { + "title": "GitHub Repo", + "description": "View the GovTool source code and contribute on GitHub." + }, + "documentation": { + "title": "Documentation", + "description": "GovTool documentation and guides." + } } } }, @@ -825,7 +884,7 @@ "notVoted": "Not voted" }, "usefulLinks": { - "title": "Useful links", + "title": "Links to other Cardano Governance resources:", "ccPortal": { "title": "Check the Constitutional Committee Portal", "description": "See Interim Cardano Constitution and Constitutional committee votes rationales", @@ -835,6 +894,71 @@ "title": "Intersect website", "description": "Intersect is a member-based organization for the Cardano ecosystem — putting the community at the center of Cardano’s development", "link": "Intersect website" + }, + "tempo": { + "title": "Tempo", + "description": "Tempo, a tool for DReps Community Engagement", + "link": "Tempo" + }, + "1694io": { + "title": "1694.io", + "description": "CIP-1694 explained plus DRep list, DRep campaign, proposal discussion", + "link": "1694.io" + }, + "governanceSpace": { + "title": "Governance Space", + "description": "Decentralized Governance for Everyone", + "link": "Governance Space" + }, + "syncAi": { + "title": "SyncAI Governance Hub", + "description": "One collaborative space to explore proposals, chat, vote, and track alignment", + "link": "SyncAI" + }, + "ekklesia": { + "title": "Ekklesia", + "description": "Where DReps indicate which proposals they support for funding consideration", + "link": "Ekklesia" + }, + "adaStat": { + "title": "AdaStat", + "description": "AdaStat Cardano Explorer will show you full details about Cardano (ADA) blockchain", + "link": "AdaStat" + }, + "cexplorer": { + "title": "CExplorer", + "description": "Independent tool for your better staking /decision-making", + "link": "CExplorer" + }, + "cardanoScan": { + "title": "Cardanoscan", + "description": "The Cardano (ADA) Explorer, explore blocks, transactions, metadata, certificates, pools, assets and more", + "link": "Cardanoscan" + }, + "cardanoBudget": { + "title": "Cardano Budget Proposals 2025", + "description": "A tool to track the Cardano treasury and its budget proposals", + "link": "Cardano Budget" + }, + "budgetCardanoAfrica": { + "title": "Budget Cardano Africa", + "description": "In-depth analysis of Cardano's budget proposals and insights", + "link": "Budget Cardano Africa" + }, + "reachYourPeople": { + "title": "Reach Your People", + "description": "RYP is a communication and announcement hub for Cardano and other blockchains", + "link": "Reach Your People" + }, + "1694Tools": { + "title": "1694.Tools", + "description": "Cardano proposal explorer", + "link": "1694.Tools" + }, + "sanchonetGovernanceExplorer": { + "title": "SanchoNet Governance Explorer", + "description": "This explorer allows you to view governance activities and other data from the Cardano SanchoNet testnet", + "link": "SanchoNet Governance Explorer" } }, "about": "About", diff --git a/govtool/frontend/src/pages/DashboardHome.tsx b/govtool/frontend/src/pages/DashboardHome.tsx index c2ef40f71..6430083f5 100644 --- a/govtool/frontend/src/pages/DashboardHome.tsx +++ b/govtool/frontend/src/pages/DashboardHome.tsx @@ -1,7 +1,7 @@ import { Box } from "@mui/material"; -import { DashboardCards } from "@organisms"; -import { UsefulLinks } from "@/components/organisms/UsefulLinks"; +import { DashboardCards, HelpBuildGovTool, Socials } from "@organisms"; +import { UsefulLinks } from "@/components/organisms/Home/UsefulLinks"; import { useScreenDimension } from "@/hooks"; export const DashboardHome = () => { @@ -20,6 +20,8 @@ export const DashboardHome = () => { > + + ); }; diff --git a/govtool/frontend/src/pages/Home.tsx b/govtool/frontend/src/pages/Home.tsx index 8af4eefdf..c89ac8ef3 100644 --- a/govtool/frontend/src/pages/Home.tsx +++ b/govtool/frontend/src/pages/Home.tsx @@ -1,17 +1,26 @@ import { useEffect } from "react"; import { useNavigate } from "react-router-dom"; -import { Box } from "@mui/material"; +import { Box, Link } from "@mui/material"; +import { Trans } from "react-i18next"; -import { Background } from "@atoms"; +import { Background, Typography } from "@atoms"; import { PATHS } from "@consts"; import { useCardano } from "@context"; -import { TopNav, Hero, Footer, HomeCards } from "@organisms"; +import { + TopNav, + Footer, + UsefulLinks, + OpenToAny, + ConnectWalletTo, + Socials, + HelpBuildGovTool, +} from "@organisms"; import { WALLET_LS_KEY, getItemFromLocalStorage } from "@utils"; -import { UsefulLinks } from "@/components/organisms/UsefulLinks"; import { useScreenDimension } from "@/hooks"; export const Home = () => { const { isEnabled } = useCardano(); + const navigate = useNavigate(); const { screenWidth } = useScreenDimension(); @@ -25,19 +34,43 @@ export const Home = () => { - - - + + , + ]} + /> + + + + + + {/* FIXME: Footer should be on top of the layout. Should not be rerendered across the pages */} From b9570d2f87ed010272ac319581eb04dcc49b5af7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 13:05:46 +0000 Subject: [PATCH 24/75] chore: update GovTool to v2.0.23 --- 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 e3b03bc83..a710eaa88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,17 @@ changes. ## [Unreleased] +### Added + +### Fixed + +### Changed + +### Removed + +## [v2.0.23](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.23) 2025-05-22 + + ### Added - Add CIP-129 support for gov_actions hashes in Live Voting (governance actions) [Issue 3619](https://github.com/IntersectMBO/govtool/issues/3619) diff --git a/govtool/backend/Dockerfile b/govtool/backend/Dockerfile index 0380c164d..88b71c171 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.22/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.23/x/vva-be/build/vva-be/vva-be /usr/local/bin diff --git a/govtool/backend/Dockerfile.qovery b/govtool/backend/Dockerfile.qovery index a5ea19d65..925a0a670 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.22/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.23/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 f3131a070..9b1345f50 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.22 +version: 2.0.23 -- A short (one-line) description of the package. -- synopsis: diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 0dc3da411..7b815177c 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "@govtool/frontend", - "version": "2.0.22", + "version": "2.0.23", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@govtool/frontend", - "version": "2.0.22", + "version": "2.0.23", "hasInstallScript": true, "dependencies": { "@emotion/react": "^11.11.1", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index 1db732b12..ed810a48f 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -1,7 +1,7 @@ { "name": "@govtool/frontend", "private": true, - "version": "2.0.22", + "version": "2.0.23", "type": "module", "scripts": { "build": "vite build", diff --git a/govtool/metadata-validation/package-lock.json b/govtool/metadata-validation/package-lock.json index d425f918b..59f24cd09 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.22", + "version": "2.0.23", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@govtool/metadata-validation", - "version": "2.0.22", + "version": "2.0.23", "license": "UNLICENSED", "dependencies": { "@nestjs/axios": "^3.0.2", diff --git a/govtool/metadata-validation/package.json b/govtool/metadata-validation/package.json index 26d09b2d6..865f15b43 100644 --- a/govtool/metadata-validation/package.json +++ b/govtool/metadata-validation/package.json @@ -1,6 +1,6 @@ { "name": "@govtool/metadata-validation", - "version": "2.0.22", + "version": "2.0.23", "description": "", "author": "", "private": true, diff --git a/govtool/metadata-validation/src/main.ts b/govtool/metadata-validation/src/main.ts index faf7322c7..5dd0961fb 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.22") + .setVersion("2.0.23") .build(); const document = SwaggerModule.createDocument(app, config); From 870100029667191706929f1069f7bd4b12c81f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Thu, 22 May 2025 16:02:43 +0200 Subject: [PATCH 25/75] feat: pass ada holder voting power request to PDF --- govtool/frontend/src/pages/ProposalDiscussion.tsx | 2 ++ .../src/services/requests/getAdaHolderVotingPower.ts | 2 +- govtool/frontend/src/types/@intersect.mbo.d.ts | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/govtool/frontend/src/pages/ProposalDiscussion.tsx b/govtool/frontend/src/pages/ProposalDiscussion.tsx index bbc0e8efe..d2f28667c 100644 --- a/govtool/frontend/src/pages/ProposalDiscussion.tsx +++ b/govtool/frontend/src/pages/ProposalDiscussion.tsx @@ -12,6 +12,7 @@ import { useValidateMutation } from "@/hooks/mutations"; import { useScreenDimension } from "@/hooks/useScreenDimension"; import { Footer, TopNav } from "@/components/organisms"; import { useGetDRepVotingPowerList, useGetVoterInfo } from "@/hooks"; +import { getAdaHolderVotingPower } from "@/services"; const ProposalDiscussion = React.lazy( () => import("@intersect.mbo/pdf-ui/cjs"), @@ -79,6 +80,7 @@ export const ProposalDiscussionPillar = () => { username={username} setUsername={setUsername} epochParams={epochParams} + getAdaHolderVotingPower={getAdaHolderVotingPower} {...snackbarContext} /> diff --git a/govtool/frontend/src/services/requests/getAdaHolderVotingPower.ts b/govtool/frontend/src/services/requests/getAdaHolderVotingPower.ts index 79f73d925..ec7a36755 100644 --- a/govtool/frontend/src/services/requests/getAdaHolderVotingPower.ts +++ b/govtool/frontend/src/services/requests/getAdaHolderVotingPower.ts @@ -4,7 +4,7 @@ export const getAdaHolderVotingPower = async ({ stakeKey, }: { stakeKey?: string; -}) => { +}): Promise => { const response = await API.get(`/ada-holder/get-voting-power/${stakeKey}`); return response.data; diff --git a/govtool/frontend/src/types/@intersect.mbo.d.ts b/govtool/frontend/src/types/@intersect.mbo.d.ts index 5db4fed7b..f980a30bb 100644 --- a/govtool/frontend/src/types/@intersect.mbo.d.ts +++ b/govtool/frontend/src/types/@intersect.mbo.d.ts @@ -32,6 +32,11 @@ declare module "@intersect.mbo/pdf-ui/cjs" { epochParams?: EpochParams; username: string; setUsername: (username: string) => void; + getAdaHolderVotingPower: ({ + stakeKey, + }: { + stakeKey?: string; + }) => Promise; }; type GovernanceActionsOutcomesProps = { From fc6ceb77c29ca4d2c21a43d12efb872ebf622355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Fri, 23 May 2025 09:51:56 +0200 Subject: [PATCH 26/75] feat: pass wallet name to wallet api --- govtool/frontend/src/context/wallet.tsx | 28 +++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/govtool/frontend/src/context/wallet.tsx b/govtool/frontend/src/context/wallet.tsx index c7a6d1492..cced1021c 100644 --- a/govtool/frontend/src/context/wallet.tsx +++ b/govtool/frontend/src/context/wallet.tsx @@ -225,6 +225,7 @@ interface CardanoContextType { setStakeKey: (key: string) => void; stakeKeys: string[]; walletApi?: CardanoApiWallet; + walletName?: string; registeredStakeKeysListState: string[]; buildSignSubmitConwayCertTx: ({ certBuilder, @@ -313,6 +314,7 @@ const CardanoProvider = (props: Props) => { changeAddress: undefined, usedAddress: undefined, }); + const [walletName, setWalletName] = useState(undefined); const { t } = useTranslation(); const epochParams = getItemFromLocalStorage(PROTOCOL_PARAMS_KEY); @@ -354,25 +356,25 @@ const CardanoProvider = (props: Props) => { const isStakeKeyRegistered = () => !!registeredStakeKeysListState.length; const enable = useCallback( - async (walletName: string) => { - setIsEnableLoading(walletName); + async (name: string) => { + setIsEnableLoading(name); await checkIsMaintenanceOn(); - // todo: use .getSupportedExtensions() to check if wallet supports CIP-95 - if (!isEnabled && walletName) { + // TODO: use .getSupportedExtensions() to check if wallet supports CIP-95 + if (!isEnabled && name) { try { // Check that this wallet supports CIP-95 connection - if (!window.cardano[walletName].supportedExtensions) { + if (!window.cardano[name].supportedExtensions) { throw new Error(t("errors.walletNoCIP30Support")); } else if ( - !window.cardano[walletName].supportedExtensions.some( + !window.cardano[name].supportedExtensions.some( (item) => item.cip === 95, ) ) { throw new Error(t("errors.walletNoCIP30Nor90Support")); } // Enable wallet connection - const enabledApi: CardanoApiWallet = await window.cardano[walletName] + const enabledApi: CardanoApiWallet = await window.cardano[name] .enable({ extensions: [{ cip: 95 }], }) @@ -381,7 +383,7 @@ const CardanoProvider = (props: Props) => { category: "wallet", message: "Wallet connected", level: "info", - data: window.cardano[walletName], + data: window.cardano[name], }); return enabledWalletApi; }) @@ -393,6 +395,7 @@ const CardanoProvider = (props: Props) => { setIsEnabled(true); setWalletApi(enabledApi); + setWalletName(name); // Check if wallet has enabled the CIP-95 extension const enabledExtensions = await enabledApi.getExtensions(); if (!enabledExtensions.some((item) => item.cip === 95)) { @@ -478,7 +481,7 @@ const CardanoProvider = (props: Props) => { const dRepIDs = await getPubDRepID(enabledApi); setPubDRepKey(dRepIDs?.dRepKey || ""); setDRepID(dRepIDs?.dRepID || ""); - setItemToLocalStorage(`${WALLET_LS_KEY}_name`, walletName); + setItemToLocalStorage(`${WALLET_LS_KEY}_name`, name); return { status: t("ok"), stakeKey: stakeKeySet }; } catch (e) { @@ -512,6 +515,7 @@ const CardanoProvider = (props: Props) => { setAddress(undefined); setStakeKey(undefined); setIsEnabled(false); + setWalletName(undefined); Sentry.addBreadcrumb({ category: "wallet", @@ -757,8 +761,8 @@ const CardanoProvider = (props: Props) => { // TODO: type error // eslint-disable-next-line @typescript-eslint/no-shadow, @typescript-eslint/no-explicit-any } catch (error: any) { - const walletName = getItemFromLocalStorage(`${WALLET_LS_KEY}_name`); - const isWalletConnected = await window.cardano[walletName].isEnabled(); + const name = getItemFromLocalStorage(`${WALLET_LS_KEY}_name`); + const isWalletConnected = await window.cardano[name].isEnabled(); if (!isWalletConnected) { disconnectWallet(); @@ -1489,6 +1493,7 @@ const CardanoProvider = (props: Props) => { stakeKey, stakeKeys, walletApi, + walletName, }), [ address, @@ -1523,6 +1528,7 @@ const CardanoProvider = (props: Props) => { stakeKey, stakeKeys, walletApi, + walletName, ], ); From c158a748b53a71c49cb94b807163309ef687096a Mon Sep 17 00:00:00 2001 From: Ciabas Date: Fri, 23 May 2025 09:59:01 +0200 Subject: [PATCH 27/75] fix: missing testIds on home page cards --- govtool/frontend/src/components/molecules/HomeCard.tsx | 1 + govtool/frontend/src/i18n/locales/en.json | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/govtool/frontend/src/components/molecules/HomeCard.tsx b/govtool/frontend/src/components/molecules/HomeCard.tsx index ef896e4eb..ef04545c9 100644 --- a/govtool/frontend/src/components/molecules/HomeCard.tsx +++ b/govtool/frontend/src/components/molecules/HomeCard.tsx @@ -27,6 +27,7 @@ export const HomeCard = ({ title, description, onCardClick }: Props) => ( component="button" role="button" aria-label={`${title}. ${description}`} + dataTestId={`home-card-${title.replace(/\s+/g, "-").toLowerCase()}`} > {title} {description} diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index 3740ee0da..23bb0f514 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -605,10 +605,10 @@ }, "proposeGovernanceAction": { "description": "Create a discussion for an Action, and submit it on-chain.", - "title": "Propose a Governace Action" + "title": "Propose a Governance Action" }, "registerToVote": { - "description": "Register yourself to vote on all Governace Actions", + "description": "Register yourself to vote on all Governance Actions", "title": "Register to Vote" }, "delegateVote": { @@ -621,7 +621,7 @@ }, "voteOnGovernanceActions": { "description": "Cast your vote on Governance Actions as yourself or as a DRep.", - "title": "Vote on Governace Actions" + "title": "Vote on Governance Actions" } } }, From 9a2f97165ddb115a99e6c47588678bd177cf53d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Fri, 23 May 2025 13:20:07 +0200 Subject: [PATCH 28/75] fix(#3622): apply new design system theme changes to home page --- .../frontend/src/components/atoms/Typography.tsx | 9 +++++++++ govtool/frontend/src/components/atoms/types.ts | 3 +++ .../src/components/molecules/HomeCard.tsx | 7 +++++-- .../organisms/Home/ConnectWalletTo.tsx | 6 +++--- .../organisms/Home/HelpBuildGovTool.tsx | 6 +++--- .../src/components/organisms/Home/OpenToAny.tsx | 6 +++--- .../src/components/organisms/Home/Socials.tsx | 6 +++--- .../components/organisms/Home/UsefulLinks.tsx | 16 ++++++++++------ govtool/frontend/src/pages/Home.tsx | 4 ++-- 9 files changed, 41 insertions(+), 22 deletions(-) diff --git a/govtool/frontend/src/components/atoms/Typography.tsx b/govtool/frontend/src/components/atoms/Typography.tsx index 34e1af742..c11a9f3fc 100644 --- a/govtool/frontend/src/components/atoms/Typography.tsx +++ b/govtool/frontend/src/components/atoms/Typography.tsx @@ -12,8 +12,11 @@ export const Typography = ({ headline3: 36, headline4: 32, headline5: 28, + title: 27, title1: 24, + titleH3: 23, title2: 22, + body: 21, body1: 16, body2: 14, caption: 12, @@ -25,8 +28,11 @@ export const Typography = ({ headline3: 400, headline4: 600, headline5: 500, + title: 500, title1: 400, + titleH3: 500, title2: 500, + body: 400, body1: 600, body2: 500, caption: 400, @@ -38,8 +44,11 @@ export const Typography = ({ headline3: "44px", headline4: "40px", headline5: "36px", + title: "32px", + titleH3: "32px", title1: "32px", title2: "28px", + body: "28px", body1: "24px", body2: "20px", caption: "16px", diff --git a/govtool/frontend/src/components/atoms/types.ts b/govtool/frontend/src/components/atoms/types.ts index 52bf82151..219d12d4e 100644 --- a/govtool/frontend/src/components/atoms/types.ts +++ b/govtool/frontend/src/components/atoms/types.ts @@ -32,8 +32,11 @@ export type TypographyProps = Pick< | "headline3" | "headline4" | "headline5" + | "title" + | "titleH3" | "title1" | "title2" + | "body" | "body1" | "body2" | "caption"; diff --git a/govtool/frontend/src/components/molecules/HomeCard.tsx b/govtool/frontend/src/components/molecules/HomeCard.tsx index ef04545c9..b5a644075 100644 --- a/govtool/frontend/src/components/molecules/HomeCard.tsx +++ b/govtool/frontend/src/components/molecules/HomeCard.tsx @@ -19,6 +19,7 @@ export const HomeCard = ({ title, description, onCardClick }: Props) => ( border: "none", cursor: onCardClick ? "pointer" : "default", outline: "none", + p: 3.75, "&:focus": { boxShadow: "0 0 0 3px rgba(47, 98, 220, 0.5)", }, @@ -29,7 +30,9 @@ export const HomeCard = ({ title, description, onCardClick }: Props) => ( aria-label={`${title}. ${description}`} dataTestId={`home-card-${title.replace(/\s+/g, "-").toLowerCase()}`} > - {title} - {description} + + {title} + + {description} ); diff --git a/govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx b/govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx index 28dce86a2..1bf5f362f 100644 --- a/govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx +++ b/govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx @@ -106,7 +106,7 @@ export const ConnectWalletTo = () => { return ( - + {t("home.connectWalletTo.section.title")} + + + hero + + + ); +}; diff --git a/govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx b/govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx deleted file mode 100644 index 1bf5f362f..000000000 --- a/govtool/frontend/src/components/organisms/Home/ConnectWalletTo.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import { Box } from "@mui/material"; -import { useTranslation } from "react-i18next"; -import { useNavigate } from "react-router-dom"; - -import I18n from "@/i18n"; -import { BUDGET_DISCUSSION_PATHS, PATHS, PDF_PATHS } from "@/consts"; -import { useCardano, useModal } from "@/context"; - -import { Typography, Button } from "../../atoms"; -import { HomeCard } from "../../molecules/HomeCard"; - -const isProposalDiscussionForumEnabled = JSON.parse( - import.meta.env.VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED || false, -); - -const CONNECT_WALLET_TO_CARDS = [ - ...(isProposalDiscussionForumEnabled - ? [ - { - title: I18n.t( - "home.connectWalletTo.cards.discussBudgetProposals.title", - ), - description: I18n.t( - "home.connectWalletTo.cards.discussBudgetProposals.description", - ), - path: BUDGET_DISCUSSION_PATHS.budgetDiscussion, - }, - { - title: I18n.t( - "home.connectWalletTo.cards.createBudgetProposal.title", - ), - description: I18n.t( - "home.connectWalletTo.cards.createBudgetProposal.description", - ), - path: BUDGET_DISCUSSION_PATHS.budgetDiscussion, - }, - { - title: I18n.t( - "home.connectWalletTo.cards.discussGovernanceActions.title", - ), - description: I18n.t( - "home.connectWalletTo.cards.discussGovernanceActions.description", - ), - path: PDF_PATHS.proposalDiscussion, - }, - { - title: I18n.t( - "home.connectWalletTo.cards.proposeGovernanceAction.title", - ), - description: I18n.t( - "home.connectWalletTo.cards.proposeGovernanceAction.description", - ), - path: PDF_PATHS.proposalDiscussionPropose, - }, - ] - : []), - { - title: I18n.t("home.connectWalletTo.cards.registerToVote.title"), - description: I18n.t( - "home.connectWalletTo.cards.registerToVote.description", - ), - path: PATHS.registerAsDirectVoter, - }, - { - title: I18n.t("home.connectWalletTo.cards.delegateVote.title"), - description: I18n.t("home.connectWalletTo.cards.delegateVote.description"), - path: PATHS.dRepDirectory, - }, - { - title: I18n.t("home.connectWalletTo.cards.becomeDRep.title"), - description: I18n.t("home.connectWalletTo.cards.becomeDRep.description"), - path: PATHS.registerAsdRep, - }, - { - title: I18n.t("home.connectWalletTo.cards.voteOnGovernanceActions.title"), - description: I18n.t( - "home.connectWalletTo.cards.voteOnGovernanceActions.description", - ), - path: PATHS.dashboardGovernanceActions, - }, -]; - -export const ConnectWalletTo = () => { - const { t } = useTranslation(); - const { openModal } = useModal(); - const { isEnabled, stakeKey } = useCardano(); - const navigate = useNavigate(); - - const handleCardClick = ({ path }: { path?: string }) => { - if (!path) return; - openModal({ - type: "chooseWallet", - state: { - pathToNavigate: path, - }, - }); - }; - - const onClickConnectButton = () => { - if (isEnabled && stakeKey) { - navigate(PATHS.dashboard); - } - openModal({ type: "chooseWallet" }); - }; - - return ( - - - - {t("home.connectWalletTo.section.title")} - - - - - {CONNECT_WALLET_TO_CARDS.map(({ title, description, path }) => ( - handleCardClick({ path }) : undefined} - /> - ))} - - - ); -}; diff --git a/govtool/frontend/src/components/organisms/Home/HelpBuildGovTool.tsx b/govtool/frontend/src/components/organisms/Home/HelpBuildGovTool.tsx deleted file mode 100644 index bd057d1d7..000000000 --- a/govtool/frontend/src/components/organisms/Home/HelpBuildGovTool.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { Box } from "@mui/material"; -import { useTranslation } from "react-i18next"; - -import I18n from "@/i18n"; -import { GOVTOOL_URLS } from "@/consts"; - -import { Typography } from "../../atoms"; -import { HomeCard } from "../../molecules/HomeCard"; -import { openInNewTab } from "@/utils"; - -const GOVTOOL_CARD_LINKS = [ - { - title: I18n.t("home.helpBuildGovTool.cards.githubRepo.title"), - description: I18n.t("home.helpBuildGovTool.cards.githubRepo.description"), - url: GOVTOOL_URLS.githubRepo, - }, - { - title: I18n.t("home.helpBuildGovTool.cards.documentation.title"), - description: I18n.t( - "home.helpBuildGovTool.cards.documentation.description", - ), - url: GOVTOOL_URLS.documentation, - }, -]; - -export const HelpBuildGovTool = ({ my = 4 }: { my?: number }) => { - const { t } = useTranslation(); - - const handleCardClick = ({ url }: { url?: string }) => { - if (!url) return; - openInNewTab(url); - }; - - return ( - - - {t("home.helpBuildGovTool.section.title")} - - - {GOVTOOL_CARD_LINKS.map(({ title, description, url }) => ( - handleCardClick({ url }) : undefined} - /> - ))} - - - ); -}; diff --git a/govtool/frontend/src/components/organisms/Home/OpenToAny.tsx b/govtool/frontend/src/components/organisms/Home/OpenToAny.tsx deleted file mode 100644 index d43961969..000000000 --- a/govtool/frontend/src/components/organisms/Home/OpenToAny.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import { Box } from "@mui/material"; -import { useNavigate } from "react-router-dom"; -import { useTranslation } from "react-i18next"; - -import I18n from "@/i18n"; -import { - BUDGET_DISCUSSION_PATHS, - OUTCOMES_PATHS, - PATHS, - PDF_PATHS, -} from "@/consts"; -import { openInNewTab } from "@/utils"; - -import { Typography } from "../../atoms"; -import { HomeCard } from "../../molecules/HomeCard"; - -const isProposalDiscussionForumEnabled = JSON.parse( - import.meta.env.VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED || false, -); - -const isOutcomesEnabled = JSON.parse( - import.meta.env.VITE_IS_GOVERNANCE_OUTCOMES_PILLAR_ENABLED || false, -); - -const OPEN_TO_ANY_CARDS = [ - { - title: I18n.t("home.openToAny.cards.drepDirectory.title"), - description: I18n.t("home.openToAny.cards.drepDirectory.description"), - path: PATHS.dRepDirectory, - }, - ...(isProposalDiscussionForumEnabled - ? [ - { - title: I18n.t("home.openToAny.cards.budgetProposal.title"), - description: I18n.t( - "home.openToAny.cards.budgetProposal.description", - ), - path: BUDGET_DISCUSSION_PATHS.budgetDiscussion, - }, - { - title: I18n.t("home.openToAny.cards.proposalDiscussion.title"), - description: I18n.t( - "home.openToAny.cards.proposalDiscussion.description", - ), - path: PDF_PATHS.proposalDiscussion, - }, - ] - : []), - { - title: I18n.t("home.openToAny.cards.governanceActions.title"), - description: I18n.t("home.openToAny.cards.governanceActions.description"), - path: PATHS.governanceActions, - }, - ...(isOutcomesEnabled - ? [ - { - title: I18n.t("home.openToAny.cards.governanceOutcomes.title"), - description: I18n.t( - "home.openToAny.cards.governanceOutcomes.description", - ), - path: OUTCOMES_PATHS.governanceActionsOutcomes, - }, - ] - : []), - { - title: I18n.t("home.openToAny.cards.guides.title"), - description: I18n.t("home.openToAny.cards.guides.description"), - url: "https://docs.gov.tools/cardano-govtool/using-govtool", - }, -]; - -export const OpenToAny = () => { - const navigate = useNavigate(); - const { t } = useTranslation(); - - const handleCardClick = ({ path, url }: { path?: string; url?: string }) => { - if (path) { - navigate(path); - } else if (url) { - openInNewTab(url); - } - }; - - return ( - - - {t("home.openToAny.section.title")} - - - {OPEN_TO_ANY_CARDS.map(({ title, description, path, url }) => ( - handleCardClick({ path, url }) : undefined - } - /> - ))} - - - ); -}; diff --git a/govtool/frontend/src/components/organisms/Home/Socials.tsx b/govtool/frontend/src/components/organisms/Home/Socials.tsx deleted file mode 100644 index 51132b219..000000000 --- a/govtool/frontend/src/components/organisms/Home/Socials.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Box } from "@mui/material"; -import { useTranslation } from "react-i18next"; - -import I18n from "@/i18n"; -import { SOCIAL_MEDIA_URLS } from "@/consts"; - -import { Typography } from "../../atoms"; -import { HomeCard } from "../../molecules/HomeCard"; -import { openInNewTab } from "@/utils"; - -const SOCIAL_CARDS = [ - { - title: I18n.t("home.joinDiscussion.cards.discord.title"), - description: I18n.t("home.joinDiscussion.cards.discord.description"), - url: SOCIAL_MEDIA_URLS.discord, - }, -]; - -export const Socials = ({ my = 4 }: { my?: number }) => { - const { t } = useTranslation(); - - const handleCardClick = ({ url }: { url?: string }) => { - if (!url) return; - openInNewTab(url); - }; - - return ( - - - {t("home.joinDiscussion.section.title")} - - - {SOCIAL_CARDS.map(({ title, description, url }) => ( - handleCardClick({ url }) : undefined} - /> - ))} - - - ); -}; diff --git a/govtool/frontend/src/components/organisms/Home/index.ts b/govtool/frontend/src/components/organisms/Home/index.ts deleted file mode 100644 index e514c04dc..000000000 --- a/govtool/frontend/src/components/organisms/Home/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./ConnectWalletTo"; -export * from "./HelpBuildGovTool"; -export * from "./OpenToAny"; -export * from "./Socials"; -export * from "./UsefulLinks"; diff --git a/govtool/frontend/src/components/organisms/HomeCards.tsx b/govtool/frontend/src/components/organisms/HomeCards.tsx new file mode 100644 index 000000000..d456cb2d3 --- /dev/null +++ b/govtool/frontend/src/components/organisms/HomeCards.tsx @@ -0,0 +1,151 @@ +import { useCallback } from "react"; +import { useNavigate } from "react-router-dom"; +import { Box } from "@mui/material"; + +import { IMAGES, PATHS, PDF_PATHS } from "@consts"; +import { useFeatureFlag, useModal } from "@context"; +import { ActionCard } from "@molecules"; +import { useTranslation } from "@hooks"; +import { openInNewTab } from "@utils"; +import { LINKS } from "@/consts/links"; + +export const HomeCards = () => { + const { isProposalDiscussionForumEnabled } = useFeatureFlag(); + const navigate = useNavigate(); + const { openModal } = useModal(); + const { t } = useTranslation(); + + const openWalletModal = useCallback( + (pathToNavigate: string) => { + openModal({ + type: "chooseWallet", + state: { + pathToNavigate, + }, + }); + }, + [openModal], + ); + + const onClickLearnMoreAboutDelegation = () => openInNewTab(LINKS.DELEGATING); + + const onClickLearnMoreAboutDRepRegistration = () => + openInNewTab(LINKS.REGISTER_AS_A_DREP); + + const onClickLearnMoreAboutDirectVoterRegistration = () => + openInNewTab(LINKS.DIRECT_VOTING); + + const onClickLearnMoreAboutProposingGovAction = () => + openInNewTab(LINKS.PROPOSE_A_GOVERNANCE_ACTION); + + const navigateToGovActions = useCallback( + () => navigate(PATHS.governanceActions), + [navigate], + ); + + const navigateToDRepDirecotry = useCallback( + () => navigate(PATHS.dRepDirectory), + [navigate], + ); + + const navigateToProposalDiscussionPillar = useCallback( + () => navigate(PDF_PATHS.proposalDiscussion), + [navigate], + ); + + return ( + + {/* DELEGATE CARD */} + + {/* DELEGATE CARD END */} + {/* REGISTER AS DREP CARD */} + openWalletModal(PATHS.registerAsdRep)} + firstButtonLabel={t("home.cards.registerAsDRep.firstButtonLabel")} + imageHeight={80} + imageURL={IMAGES.govActionRegisterImage} + imageWidth={70} + secondButtonAction={onClickLearnMoreAboutDRepRegistration} + secondButtonLabel={t("learnMore")} + title={t("home.cards.registerAsDRep.title")} + /> + {/* REGISTER AS DREP CARD END */} + {/* REGISTER AS DIRECT VOTER CARD */} + openWalletModal(PATHS.registerAsDirectVoter)} + firstButtonLabel={t( + "home.cards.registerAsDirectVoter.firstButtonLabel", + )} + imageHeight={84} + imageURL={IMAGES.directVoterImage} + imageWidth={84} + secondButtonAction={onClickLearnMoreAboutDirectVoterRegistration} + secondButtonLabel={t("learnMore")} + title={t("home.cards.registerAsDirectVoter.title")} + /> + {/* REGISTER AS DIRECT VOTER CARD END */} + {/* GOV ACTIONS CARD */} + + {/* GOV ACTIONS CARD END */} + {/* PROPOSE GOV ACTION CARD */} + openWalletModal(PATHS.createGovernanceAction)} + firstButtonLabel={t( + "home.cards.proposeAGovernanceAction.firstButtonLabel", + )} + imageHeight={84} + imageURL={IMAGES.proposeGovActionImage} + imageWidth={84} + secondButtonAction={ + isProposalDiscussionForumEnabled + ? navigateToProposalDiscussionPillar + : onClickLearnMoreAboutProposingGovAction + } + secondButtonLabel={t( + isProposalDiscussionForumEnabled + ? "home.cards.proposeAGovernanceAction.secondButtonLabel" + : "learnMore", + )} + title={t("home.cards.proposeAGovernanceAction.title")} + /> + {/* PROPOSE GOV ACTION CARD END */} + + ); +}; diff --git a/govtool/frontend/src/components/organisms/Home/UsefulLinks.tsx b/govtool/frontend/src/components/organisms/UsefulLinks.tsx similarity index 65% rename from govtool/frontend/src/components/organisms/Home/UsefulLinks.tsx rename to govtool/frontend/src/components/organisms/UsefulLinks.tsx index 502d3864f..12fa9152f 100644 --- a/govtool/frontend/src/components/organisms/Home/UsefulLinks.tsx +++ b/govtool/frontend/src/components/organisms/UsefulLinks.tsx @@ -1,10 +1,9 @@ import { Box, Link } from "@mui/material"; import { useTranslation } from "@hooks"; +import { Typography } from "../atoms"; import { ICONS } from "@/consts"; - -import { Typography } from "../../atoms"; -import { Card } from "../../molecules"; +import { Card } from "../molecules"; const LINKS = { ccPortal: { @@ -13,45 +12,6 @@ const LINKS = { intersectWebsite: { url: "https://www.intersectmbo.org/", }, - tempo: { - url: "https://tempo.vote/", - }, - "1694io": { - url: "https://www.1694.io/", - }, - governanceSpace: { - url: "https://governancespace.com/", - }, - syncAi: { - url: "https://www.syncgovhub.com/app", - }, - ekklesia: { - url: "https://2025budget.intersectmbo.org/", - }, - adaStat: { - url: "https://adastat.net/", - }, - cexplorer: { - url: "https://cexplorer.io/", - }, - cardanoScan: { - url: "https://cardanoscan.io/", - }, - cardanoBudget: { - url: "https://cardanobudget.com/", - }, - budgetCardanoAfrica: { - url: "https://budget.cardano.africa/", - }, - reachYourPeople: { - url: "https://www.ryp.io/", - }, - "1694Tools": { - url: "https://1694-tools.vercel.app/", - }, - sanchonetGovernanceExplorer: { - url: "https://sancho.cardanoconnect.io/", - }, } as const; type Props = { @@ -63,18 +23,19 @@ export const UsefulLinks = ({ align = "left" }: Props) => { return (
- + {t("usefulLinks.title")} {Object.entries(LINKS).map(([key, { url }]) => ( { sx={{ flexBasis: 0, boxShadow: "2px 2px 20px 0px rgba(47, 98, 220, 0.20)", + maxWidth: 464, + minWidth: 264, minHeight: 196, boxSizing: "border-box", display: "flex", diff --git a/govtool/frontend/src/components/organisms/index.ts b/govtool/frontend/src/components/organisms/index.ts index c3ade3106..f1c136904 100644 --- a/govtool/frontend/src/components/organisms/index.ts +++ b/govtool/frontend/src/components/organisms/index.ts @@ -18,6 +18,8 @@ export * from "./Footer"; export * from "./GovernanceActionDetailsCard"; export * from "./GovernanceActionDetailsCardData"; export * from "./GovernanceActionsToVote"; +export * from "./Hero"; +export * from "./HomeCards"; export * from "./Modal"; export * from "./RegisterAsDRepSteps"; export * from "./Slider"; @@ -27,4 +29,3 @@ export * from "./ValidatedGovernanceActionCard"; export * from "./ValidatedGovernanceVotedOnCard"; export * from "./VoteContext"; export * from "./WrongRouteInfo"; -export * from "./Home"; diff --git a/govtool/frontend/src/consts/index.ts b/govtool/frontend/src/consts/index.ts index a11ef438c..f07ea2941 100644 --- a/govtool/frontend/src/consts/index.ts +++ b/govtool/frontend/src/consts/index.ts @@ -92,13 +92,3 @@ export const PPU_GOVERNANCE_GROUP_PARAMS_KEYS = [ "committeeMinSize", "committeeMaxTermLength", ]; - -export const SOCIAL_MEDIA_URLS = { - discord: - "https://discord.com/channels/1136727663583698984/1212344688523214869", -}; - -export const GOVTOOL_URLS = { - githubRepo: "https://github.com/IntersectMBO/govtool", - documentation: "https://docs.gov.tools", -}; diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index 23bb0f514..9e259798d 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -556,95 +556,36 @@ }, "hero": { "connectWallet": "Participate now", - "description": "An Open Source Governance Application for the Cardano Blockchain\n<0>Learn more about Cardano Governance" + "description": "Cardano Governance lets Ada holders have a say in the network's future.\n\nYou can vote directly, find someone to represent you, or become a representative for others.\n\nYou can also propose changes in the network yourself, put these up for discussion and eventually, a vote.\n\n<0>Learn more about governance in the guide, or have a look around the app and see Cardano Governance in action.", + "headline": "Cardano \n Governance Tool" }, "home": { - "openToAny": { - "section": { "title": "Open to any and all users:" }, - "cards": { - "drepDirectory": { - "description": "DReps are representatives that vote for others.", - "title": "Browse the DRep Directory" - }, - "budgetProposal": { - "description": "Budget proposal and comments are open to public inspection.", - "title": "View Budget Proposals" - }, - "proposalDiscussion": { - "description": "Any user can read the proposals and view comments on future Actions.", - "title": "See Proposed Governance Actions" - }, - "governanceActions": { - "description": "See how the voting is progressing on any Governance Action.", - "title": "View Live Voting" - }, - "governanceOutcomes": { - "description": "See the outcomes and final votes on any Governance Action.", - "title": "View Voting Outcomes" - }, - "guides": { - "description": "The roadmap to this tool, to get you started in Cardano Governance.", - "title": "Read our Guides" - } - } - }, - "connectWalletTo": { - "section": { "title": "Connect a Cardano Wallet to:" }, - "cards": { - "discussBudgetProposals": { - "description": "Read comments and participate in discussions for Budget requests.", - "title": "Discuss Budget Proposals" - }, - "createBudgetProposal": { - "description": "Create a proposal to fund your project from the Cardano treasury.", - "title": "Create a Budget Proposal" - }, - "discussGovernanceActions": { - "description": "Read comments and participate in discussions for Governance Actions.", - "title": "Discuss Governance Actions" - }, - "proposeGovernanceAction": { - "description": "Create a discussion for an Action, and submit it on-chain.", - "title": "Propose a Governance Action" - }, - "registerToVote": { - "description": "Register yourself to vote on all Governance Actions", - "title": "Register to Vote" - }, - "delegateVote": { - "description": "Delegate your voting power to a representative (they vote for you).", - "title": "Delegate your vote to a DRep" - }, - "becomeDRep": { - "description": "DReps are representatives that vote for others.", - "title": "Become a DRep" - }, - "voteOnGovernanceActions": { - "description": "Cast your vote on Governance Actions as yourself or as a DRep.", - "title": "Vote on Governance Actions" - } - } - }, - "joinDiscussion": { - "section": { "title": "Join the discussion on social media" }, - "cards": { - "discord": { - "title": "Discord", - "description": "Governance Tools working group" - } - } - }, - "helpBuildGovTool": { - "section": { "title": "Help build GovTool" }, - "cards": { - "githubRepo": { - "title": "GitHub Repo", - "description": "View the GovTool source code and contribute on GitHub." - }, - "documentation": { - "title": "Documentation", - "description": "GovTool documentation and guides." - } + "cards": { + "delegate": { + "description": "Find a DRep to vote on your behalf.", + "firstButtonLabel": "View DRep Directory", + "title": "Delegate your Voting Power" + }, + "governanceActions": { + "description": "See all the Governance Actions submitted on chain. ", + "firstButtonLabel": "View Governance Actions", + "title": "View Governance Actions" + }, + "proposeAGovernanceAction": { + "description": "Submit your proposal for a Governance Action.", + "secondButtonLabel": "View Proposals", + "firstButtonLabel": "Connect to Propose", + "title": "Propose a Governance Action" + }, + "registerAsDRep": { + "description": "Accept delegated voting power from other Ada holders, and combine it with your own voting power. Vote with the accumulated Power on Governance Actions.", + "firstButtonLabel": "Connect to Register", + "title": "Become a DRep" + }, + "registerAsDirectVoter": { + "description": "Vote on Governance Actions using your own voting power", + "firstButtonLabel": "Connect to Register", + "title": "Become a Direct Voter" } } }, @@ -884,7 +825,7 @@ "notVoted": "Not voted" }, "usefulLinks": { - "title": "Links to other Cardano Governance resources:", + "title": "Useful links", "ccPortal": { "title": "Check the Constitutional Committee Portal", "description": "See Interim Cardano Constitution and Constitutional committee votes rationales", @@ -894,71 +835,6 @@ "title": "Intersect website", "description": "Intersect is a member-based organization for the Cardano ecosystem — putting the community at the center of Cardano’s development", "link": "Intersect website" - }, - "tempo": { - "title": "Tempo", - "description": "Tempo, a tool for DReps Community Engagement", - "link": "Tempo" - }, - "1694io": { - "title": "1694.io", - "description": "CIP-1694 explained plus DRep list, DRep campaign, proposal discussion", - "link": "1694.io" - }, - "governanceSpace": { - "title": "Governance Space", - "description": "Decentralized Governance for Everyone", - "link": "Governance Space" - }, - "syncAi": { - "title": "SyncAI Governance Hub", - "description": "One collaborative space to explore proposals, chat, vote, and track alignment", - "link": "SyncAI" - }, - "ekklesia": { - "title": "Ekklesia", - "description": "Where DReps indicate which proposals they support for funding consideration", - "link": "Ekklesia" - }, - "adaStat": { - "title": "AdaStat", - "description": "AdaStat Cardano Explorer will show you full details about Cardano (ADA) blockchain", - "link": "AdaStat" - }, - "cexplorer": { - "title": "CExplorer", - "description": "Independent tool for your better staking /decision-making", - "link": "CExplorer" - }, - "cardanoScan": { - "title": "Cardanoscan", - "description": "The Cardano (ADA) Explorer, explore blocks, transactions, metadata, certificates, pools, assets and more", - "link": "Cardanoscan" - }, - "cardanoBudget": { - "title": "Cardano Budget Proposals 2025", - "description": "A tool to track the Cardano treasury and its budget proposals", - "link": "Cardano Budget" - }, - "budgetCardanoAfrica": { - "title": "Budget Cardano Africa", - "description": "In-depth analysis of Cardano's budget proposals and insights", - "link": "Budget Cardano Africa" - }, - "reachYourPeople": { - "title": "Reach Your People", - "description": "RYP is a communication and announcement hub for Cardano and other blockchains", - "link": "Reach Your People" - }, - "1694Tools": { - "title": "1694.Tools", - "description": "Cardano proposal explorer", - "link": "1694.Tools" - }, - "sanchonetGovernanceExplorer": { - "title": "SanchoNet Governance Explorer", - "description": "This explorer allows you to view governance activities and other data from the Cardano SanchoNet testnet", - "link": "SanchoNet Governance Explorer" } }, "about": "About", diff --git a/govtool/frontend/src/pages/DashboardHome.tsx b/govtool/frontend/src/pages/DashboardHome.tsx index 6430083f5..c2ef40f71 100644 --- a/govtool/frontend/src/pages/DashboardHome.tsx +++ b/govtool/frontend/src/pages/DashboardHome.tsx @@ -1,7 +1,7 @@ import { Box } from "@mui/material"; -import { DashboardCards, HelpBuildGovTool, Socials } from "@organisms"; -import { UsefulLinks } from "@/components/organisms/Home/UsefulLinks"; +import { DashboardCards } from "@organisms"; +import { UsefulLinks } from "@/components/organisms/UsefulLinks"; import { useScreenDimension } from "@/hooks"; export const DashboardHome = () => { @@ -20,8 +20,6 @@ export const DashboardHome = () => { > - - ); }; diff --git a/govtool/frontend/src/pages/Home.tsx b/govtool/frontend/src/pages/Home.tsx index 078c44773..8af4eefdf 100644 --- a/govtool/frontend/src/pages/Home.tsx +++ b/govtool/frontend/src/pages/Home.tsx @@ -1,26 +1,17 @@ import { useEffect } from "react"; import { useNavigate } from "react-router-dom"; -import { Box, Link } from "@mui/material"; -import { Trans } from "react-i18next"; +import { Box } from "@mui/material"; -import { Background, Typography } from "@atoms"; +import { Background } from "@atoms"; import { PATHS } from "@consts"; import { useCardano } from "@context"; -import { - TopNav, - Footer, - UsefulLinks, - OpenToAny, - ConnectWalletTo, - Socials, - HelpBuildGovTool, -} from "@organisms"; +import { TopNav, Hero, Footer, HomeCards } from "@organisms"; import { WALLET_LS_KEY, getItemFromLocalStorage } from "@utils"; +import { UsefulLinks } from "@/components/organisms/UsefulLinks"; import { useScreenDimension } from "@/hooks"; export const Home = () => { const { isEnabled } = useCardano(); - const navigate = useNavigate(); const { screenWidth } = useScreenDimension(); @@ -34,44 +25,19 @@ export const Home = () => { + - - , - ]} - /> - - - - - - + + {/* FIXME: Footer should be on top of the layout. Should not be rerendered across the pages */} From 2b3e509e35a233afeea5593cb0dcdbe8761a59b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Mon, 26 May 2025 18:48:51 +0200 Subject: [PATCH 36/75] Revert "fix(#3622): apply new design system theme changes to home page" This reverts commit 9a2f97165ddb115a99e6c47588678bd177cf53d0. --- govtool/frontend/src/components/atoms/Typography.tsx | 9 --------- govtool/frontend/src/components/atoms/types.ts | 3 --- .../frontend/src/components/organisms/UsefulLinks.tsx | 10 +++------- 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/govtool/frontend/src/components/atoms/Typography.tsx b/govtool/frontend/src/components/atoms/Typography.tsx index c11a9f3fc..34e1af742 100644 --- a/govtool/frontend/src/components/atoms/Typography.tsx +++ b/govtool/frontend/src/components/atoms/Typography.tsx @@ -12,11 +12,8 @@ export const Typography = ({ headline3: 36, headline4: 32, headline5: 28, - title: 27, title1: 24, - titleH3: 23, title2: 22, - body: 21, body1: 16, body2: 14, caption: 12, @@ -28,11 +25,8 @@ export const Typography = ({ headline3: 400, headline4: 600, headline5: 500, - title: 500, title1: 400, - titleH3: 500, title2: 500, - body: 400, body1: 600, body2: 500, caption: 400, @@ -44,11 +38,8 @@ export const Typography = ({ headline3: "44px", headline4: "40px", headline5: "36px", - title: "32px", - titleH3: "32px", title1: "32px", title2: "28px", - body: "28px", body1: "24px", body2: "20px", caption: "16px", diff --git a/govtool/frontend/src/components/atoms/types.ts b/govtool/frontend/src/components/atoms/types.ts index 219d12d4e..52bf82151 100644 --- a/govtool/frontend/src/components/atoms/types.ts +++ b/govtool/frontend/src/components/atoms/types.ts @@ -32,11 +32,8 @@ export type TypographyProps = Pick< | "headline3" | "headline4" | "headline5" - | "title" - | "titleH3" | "title1" | "title2" - | "body" | "body1" | "body2" | "caption"; diff --git a/govtool/frontend/src/components/organisms/UsefulLinks.tsx b/govtool/frontend/src/components/organisms/UsefulLinks.tsx index 12fa9152f..c8648d6d8 100644 --- a/govtool/frontend/src/components/organisms/UsefulLinks.tsx +++ b/govtool/frontend/src/components/organisms/UsefulLinks.tsx @@ -53,10 +53,10 @@ export const UsefulLinks = ({ align = "left" }: Props) => { backgroundColor: "white", }} > - + {t(`usefulLinks.${key as keyof typeof LINKS}.title`)} - + {t(`usefulLinks.${key as keyof typeof LINKS}.description`)} { }, }} > - + {t(`usefulLinks.${key as keyof typeof LINKS}.link`)} Date: Mon, 26 May 2025 18:49:20 +0200 Subject: [PATCH 37/75] Revert "feat(#3622): add hover on home cards" This reverts commit a931f576d59d6695d37c73e2c89def5641cf450b. --- govtool/frontend/src/components/organisms/UsefulLinks.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/govtool/frontend/src/components/organisms/UsefulLinks.tsx b/govtool/frontend/src/components/organisms/UsefulLinks.tsx index c8648d6d8..90bc1a740 100644 --- a/govtool/frontend/src/components/organisms/UsefulLinks.tsx +++ b/govtool/frontend/src/components/organisms/UsefulLinks.tsx @@ -50,7 +50,6 @@ export const UsefulLinks = ({ align = "left" }: Props) => { display: "flex", flexDirection: "column", gap: 1, - backgroundColor: "white", }} > From 5313ce648372ecf60639910c6127640a6d5a5d69 Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 27 May 2025 09:54:30 +0545 Subject: [PATCH 38/75] fix: increase timeout to visibility checks for delegated DRep card and button --- .../delegationFunctionality.delegation.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/govtool-frontend/playwright/tests/2-delegation/delegationFunctionality.delegation.spec.ts b/tests/govtool-frontend/playwright/tests/2-delegation/delegationFunctionality.delegation.spec.ts index 573ffa93b..f2c04e9ba 100644 --- a/tests/govtool-frontend/playwright/tests/2-delegation/delegationFunctionality.delegation.spec.ts +++ b/tests/govtool-frontend/playwright/tests/2-delegation/delegationFunctionality.delegation.spec.ts @@ -63,9 +63,9 @@ test.describe("Delegate to others", () => { await dRepDirectoryPage.delegateToDRep(dRepId); // Verify dRepId in dRep directory - await expect( - page.getByTestId(`${dRepId}-delegate-button`) - ).not.toBeVisible(); + await expect(page.getByTestId(`${dRepId}-delegate-button`)).not.toBeVisible( + { timeout: 60_000 } + ); await expect(page.getByTestId(`${dRepId}-delegated-card`)).toBeVisible(); await expect( @@ -123,7 +123,7 @@ test.describe("Change delegation", () => { await dRepDirectoryPage.delegateToDRep(dRepIdSecond); await expect( page.getByTestId(`${dRepIdSecond}-delegated-card`) - ).toBeVisible(); + ).toBeVisible({ timeout: 60_000 }); await expect( page .getByTestId(`${dRepIdSecond}-delegated-card`) From 4eb8518965b48d175f1dd631592dc6428eaa541b Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 27 May 2025 10:03:38 +0545 Subject: [PATCH 39/75] fix: add group_name output to publish-report steps in backend and integration workflows --- .github/workflows/test_backend.yml | 2 ++ .github/workflows/test_integration_playwright.yml | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_backend.yml b/.github/workflows/test_backend.yml index 6ea254e21..a871cef71 100644 --- a/.github/workflows/test_backend.yml +++ b/.github/workflows/test_backend.yml @@ -105,6 +105,7 @@ jobs: needs: backend-tests outputs: report_number: ${{ steps.report-details.outputs.report_number }} + group_name: ${{ steps.set-deployment-url.outputs.group_name }} steps: - uses: actions/checkout@v4 - name: Download results @@ -188,6 +189,7 @@ jobs: TEST_STATUS: ${{ needs.backend-tests.outputs.status }} REPORT_NUMBER: ${{ needs.publish-report.outputs.report_number }} GITHUB_TOKEN: ${{ github.token }} + GROUP_NAME: ${{ needs.publish-report.outputs.group_name }} env: BASE_URL: https://${{github.event.schedule && 'be.preview.gov.tools' || inputs.deployment || 'govtool.cardanoapi.io/api' }} diff --git a/.github/workflows/test_integration_playwright.yml b/.github/workflows/test_integration_playwright.yml index f48fc0099..879b6bbab 100644 --- a/.github/workflows/test_integration_playwright.yml +++ b/.github/workflows/test_integration_playwright.yml @@ -145,6 +145,7 @@ jobs: needs: integration-tests outputs: report_number: ${{ steps.report-details.outputs.report_number }} + group_name: ${{ steps.set-deployment-url.outputs.group_name }} steps: - uses: actions/checkout@v4 - name: Download report @@ -218,7 +219,7 @@ jobs: with: name: allure-results path: allure-results - + - name: Set Commit Status if: always() && !github.event.schedule run: | @@ -229,6 +230,7 @@ jobs: TEST_STATUS: ${{ needs.integration-tests.outputs.status }} REPORT_NUMBER: ${{ needs.publish-report.outputs.report_number }} GITHUB_TOKEN: ${{ github.token }} + GROUP_NAME: ${{ needs.publish-report.outputs.group_name }} env: HOST_URL: https://${{ github.event.schedule && 'preview.gov.tools' || (inputs.deployment || 'govtool.cardanoapi.io') }} DEPLOYMENT: ${{ github.event.schedule && 'preview.gov.tools' || inputs.deployment || 'govtool.cardanoapi.io'}} From 87ba85afd53fb288d96bf7f2bfc616a79633c22c Mon Sep 17 00:00:00 2001 From: Olindo Task Date: Mon, 26 May 2025 23:12:47 -0700 Subject: [PATCH 40/75] Move label and description to config file --- .../frontend/src/context/usersnapContext.tsx | 20 ++++++++++--------- govtool/frontend/src/i18n/locales/en.json | 7 +++++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/govtool/frontend/src/context/usersnapContext.tsx b/govtool/frontend/src/context/usersnapContext.tsx index 1134e47f6..6e55a128a 100644 --- a/govtool/frontend/src/context/usersnapContext.tsx +++ b/govtool/frontend/src/context/usersnapContext.tsx @@ -6,6 +6,7 @@ import React, { useMemo, } from "react"; import { InitOptions, WidgetApi, loadSpace } from "@usersnap/browser"; +import { useTranslation } from "react-i18next"; type WidgetValues = { assignee?: string; @@ -65,6 +66,7 @@ export const UsersnapProvider = ({ children, }: UsersnapProviderProps) => { const [usersnapApi, setUsersnapApi] = useState(null); + const { t } = useTranslation(); const openFeedbackWindow = useCallback(() => { if (usersnapApi) { @@ -82,31 +84,31 @@ export const UsersnapProvider = ({ customFields: { sentiment_score: { type: 'rating', - label: 'How would you rate your experience?', + label: t("feedback.sentimentScore"), required: true, options: [1, 2, 3, 4, 5] }, additional_notes: { type: 'textarea', - label: 'Additional Notes', + label: t("feedback.additionalNotes"), required: false } }, feedbackTypes: [ { id: 'bug', - label: 'Report a Bug', - description: 'Something is not working as expected' + label: t("feedback.reportBug"), + description: t("feedback.reportBugDescription") }, { id: 'idea', - label: 'Suggest a New Idea', - description: 'Share your ideas for improvement' + label: t("feedback.suggestIdea"), + description: t("feedback.suggestIdeaDescription") }, { id: 'sentiment', - label: 'Share Your Experience', - description: 'Rate your experience and provide feedback' + label: t("feedback.sentimentFeedback"), + description: t("feedback.sentimentFeedbackDescription") } ] }); @@ -117,7 +119,7 @@ export const UsersnapProvider = ({ } }; initUsersnapSpace(); - }, [initParams, API_KEY]); + }, [initParams, API_KEY, t]); const value = useMemo(() => ({ openFeedbackWindow }), [openFeedbackWindow]); diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index c8042f9aa..51b96038c 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -844,10 +844,13 @@ "title": "Feedback", "reportBug": "Report a Bug", "suggestIdea": "Suggest a New Idea", - "sentimentFeedback": "Share Your Experience", + "sentimentFeedback": "Sentiment Feedback", "sentimentScore": "How would you rate your experience?", "additionalNotes": "Additional Notes", - "submit": "Submit Feedback" + "submit": "Submit Feedback", + "reportBugDescription": "Something is not working as expected", + "suggestIdeaDescription": "Share your ideas for improvement", + "sentimentFeedbackDescription": "Rate your experience and provide feedback" }, "filter": "Filter", "goBack": "Go back", From b5f778fb601ab3a3d78ae5b5260b64d15a232aa2 Mon Sep 17 00:00:00 2001 From: Ciabas Date: Mon, 26 May 2025 15:33:52 +0200 Subject: [PATCH 41/75] feat(#3672): add /account service for the usage of Proposal Discussion Forum pillar --- govtool/backend/sql/get-account-info.sql | 23 ++++++++++++ govtool/backend/src/VVA/API.hs | 14 ++++++++ govtool/backend/src/VVA/API/Types.hs | 23 ++++++++++++ govtool/backend/src/VVA/Account.hs | 35 +++++++++++++++++++ govtool/backend/src/VVA/Types.hs | 8 +++++ govtool/backend/vva-be.cabal | 2 ++ govtool/frontend/src/models/api.ts | 7 ++++ .../frontend/src/pages/ProposalDiscussion.tsx | 3 +- .../src/services/requests/getAccount.ts | 8 +++++ .../requests/getAdaHolderVotingPower.ts | 6 ++-- .../frontend/src/services/requests/index.ts | 1 + .../frontend/src/types/@intersect.mbo.d.ts | 7 +++- 12 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 govtool/backend/sql/get-account-info.sql create mode 100644 govtool/backend/src/VVA/Account.hs create mode 100644 govtool/frontend/src/services/requests/getAccount.ts diff --git a/govtool/backend/sql/get-account-info.sql b/govtool/backend/sql/get-account-info.sql new file mode 100644 index 000000000..d11fe68a4 --- /dev/null +++ b/govtool/backend/sql/get-account-info.sql @@ -0,0 +1,23 @@ +SELECT + sa.id, + sa.view, + CASE + WHEN sa.script_hash IS NOT NULL THEN true + ELSE false + END AS is_script_based, + CASE + WHEN ( + SELECT COALESCE(MAX(epoch_no), 0) + FROM stake_registration sr + WHERE sr.addr_id = sa.id + ) > ( + SELECT COALESCE(MAX(epoch_no), 0) + FROM stake_deregistration sd + WHERE sd.addr_id = sa.id + ) THEN true + ELSE false + END AS is_registered +FROM + stake_address sa +WHERE + sa.hash_raw = decode(?, 'hex'); diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs index 9488710a6..79eb491d6 100644 --- a/govtool/backend/src/VVA/API.hs +++ b/govtool/backend/src/VVA/API.hs @@ -40,6 +40,7 @@ import VVA.Config import qualified VVA.DRep as DRep import qualified VVA.Epoch as Epoch import VVA.Network as Network +import VVA.Account as Account import qualified VVA.Proposal as Proposal import qualified VVA.Transaction as Transaction import qualified VVA.Types as Types @@ -85,6 +86,7 @@ type VVAApi = :<|> "network" :> "metrics" :> Get '[JSON] GetNetworkMetricsResponse :<|> "network" :> "info" :> Get '[JSON] GetNetworkInfoResponse :<|> "network" :> "total-stake" :> Get '[JSON] GetNetworkTotalStakeResponse + :<|> "account" :> Capture "stakeKey" HexText :> Get '[JSON] GetAccountInfoResponse server :: App m => ServerT VVAApi m server = drepList @@ -103,6 +105,7 @@ server = drepList :<|> getNetworkMetrics :<|> getNetworkInfo :<|> getNetworkTotalStake + :<|> getAccountInfo mapDRepType :: Types.DRepType -> DRepType mapDRepType Types.DRep = NormalDRep @@ -527,3 +530,14 @@ getNetworkMetrics = do , getNetworkMetricsResponseQuorumNumerator = networkMetricsQuorumNumerator , getNetworkMetricsResponseQuorumDenominator = networkMetricsQuorumDenominator } + +getAccountInfo :: App m => HexText -> m GetAccountInfoResponse +getAccountInfo (unHexText -> stakeKey) = do + -- CacheEnv {accountInfoCache} <- asks vvaCache + Types.AccountInfo {..} <- Account.accountInfo stakeKey + return $ GetAccountInfoResponse + { getAccountInfoResponseId = accountInfoId + , getAccountInfoResponseView = accountInfoView + , getAccountInfoResponseIsRegistered = accountInfoIsRegistered + , getAccountInfoResponseIsScriptBased = accountInfoIsScriptBased + } diff --git a/govtool/backend/src/VVA/API/Types.hs b/govtool/backend/src/VVA/API/Types.hs index 6b517a9ce..5c0337191 100644 --- a/govtool/backend/src/VVA/API/Types.hs +++ b/govtool/backend/src/VVA/API/Types.hs @@ -1032,3 +1032,26 @@ instance ToSchema GetNetworkMetricsResponse where & description ?~ "GetNetworkMetricsResponse" & example ?~ toJSON exampleGetNetworkMetricsResponse + +data GetAccountInfoResponse + = GetAccountInfoResponse + { getAccountInfoResponseId :: Integer + , getAccountInfoResponseView :: Text + , getAccountInfoResponseIsRegistered :: Bool + , getAccountInfoResponseIsScriptBased :: Bool + } + deriving (Generic, Show) +deriveJSON (jsonOptions "getAccountInfoResponse") ''GetAccountInfoResponse +exampleGetAccountInfoResponse :: Text +exampleGetAccountInfoResponse = + "{\"stakeKey\": \"stake1u9\"," + <> " \"id\": \"1\"," + <> "\"view\": \"stake_test1uzapf83wydusjln97rqr7fen6vgrz5087yqdxm0akqdqkgstjz8g4\"," + <> "\"isRegistered\": false," + <> "\"isScriptBased\": false}" +instance ToSchema GetAccountInfoResponse where + declareNamedSchema _ = pure $ NamedSchema (Just "GetAccountInfoResponse") $ mempty + & type_ ?~ OpenApiObject + & description ?~ "GetAccountInfoResponse" + & example + ?~ toJSON exampleGetAccountInfoResponse diff --git a/govtool/backend/src/VVA/Account.hs b/govtool/backend/src/VVA/Account.hs new file mode 100644 index 000000000..10aa92e52 --- /dev/null +++ b/govtool/backend/src/VVA/Account.hs @@ -0,0 +1,35 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TemplateHaskell #-} + +module VVA.Account where + +import Control.Monad.Except (MonadError, throwError) +import Control.Monad.Reader (MonadIO, MonadReader, liftIO) +import Data.ByteString (ByteString) +import Data.FileEmbed (embedFile) +import Data.String (fromString) +import qualified Database.PostgreSQL.Simple as SQL +import VVA.Types (AppError(..), AccountInfo(..)) +import Data.Text (Text, unpack) +import qualified Data.Text.Encoding as Text +import qualified Data.Text.IO as Text +import Data.Has (Has) +import VVA.Pool (ConnectionPool, withPool) + +sqlFrom :: ByteString -> SQL.Query +sqlFrom = fromString . unpack . Text.decodeUtf8 + +accountInfoSql :: SQL.Query +accountInfoSql = sqlFrom $(embedFile "sql/get-account-info.sql") + +accountInfo :: + (Has ConnectionPool r, MonadReader r m, MonadIO m, MonadError AppError m) => + Text -> + m AccountInfo +accountInfo stakeKey = withPool $ \conn -> do + result <- liftIO $ SQL.query conn accountInfoSql (SQL.Only stakeKey) + case result of + [(id, view, is_registered, is_script_based)] -> + return $ AccountInfo id view is_registered is_script_based + _ -> throwError $ CriticalError "Could not query the account info." diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs index e6e674925..ffe165d93 100644 --- a/govtool/backend/src/VVA/Types.hs +++ b/govtool/backend/src/VVA/Types.hs @@ -302,3 +302,11 @@ data Delegation , delegationIsDRepScriptBased :: Bool , delegationTxHash :: Text } + +data AccountInfo + = AccountInfo + { accountInfoId :: Integer + , accountInfoView :: Text + , accountInfoIsRegistered :: Bool + , accountInfoIsScriptBased :: Bool + } diff --git a/govtool/backend/vva-be.cabal b/govtool/backend/vva-be.cabal index 9b1345f50..9ae62c3dd 100644 --- a/govtool/backend/vva-be.cabal +++ b/govtool/backend/vva-be.cabal @@ -37,6 +37,7 @@ extra-source-files: sql/get-dreps-voting-power-list.sql sql/get-filtered-dreps-voting-power.sql sql/get-previous-enacted-governance-action-proposal-details.sql + sql/get-account-info.sql executable vva-be main-is: Main.hs @@ -124,4 +125,5 @@ library , VVA.Pool , VVA.Types , VVA.Network + , VVA.Account ghc-options: -threaded diff --git a/govtool/frontend/src/models/api.ts b/govtool/frontend/src/models/api.ts index bc374ccad..4e1361498 100644 --- a/govtool/frontend/src/models/api.ts +++ b/govtool/frontend/src/models/api.ts @@ -261,3 +261,10 @@ type DRepVotingPower = { }; export type DRepVotingPowerListResponse = DRepVotingPower[]; + +export type Account = { + id: number, + view: string, + isRegistered: boolean, + isScriptBased: boolean +} diff --git a/govtool/frontend/src/pages/ProposalDiscussion.tsx b/govtool/frontend/src/pages/ProposalDiscussion.tsx index d2f28667c..196f73c15 100644 --- a/govtool/frontend/src/pages/ProposalDiscussion.tsx +++ b/govtool/frontend/src/pages/ProposalDiscussion.tsx @@ -12,7 +12,7 @@ import { useValidateMutation } from "@/hooks/mutations"; import { useScreenDimension } from "@/hooks/useScreenDimension"; import { Footer, TopNav } from "@/components/organisms"; import { useGetDRepVotingPowerList, useGetVoterInfo } from "@/hooks"; -import { getAdaHolderVotingPower } from "@/services"; +import { getAdaHolderVotingPower, getAccount } from "@/services"; const ProposalDiscussion = React.lazy( () => import("@intersect.mbo/pdf-ui/cjs"), @@ -81,6 +81,7 @@ export const ProposalDiscussionPillar = () => { setUsername={setUsername} epochParams={epochParams} getAdaHolderVotingPower={getAdaHolderVotingPower} + getAccount={getAccount} {...snackbarContext} /> diff --git a/govtool/frontend/src/services/requests/getAccount.ts b/govtool/frontend/src/services/requests/getAccount.ts new file mode 100644 index 000000000..f6badbebf --- /dev/null +++ b/govtool/frontend/src/services/requests/getAccount.ts @@ -0,0 +1,8 @@ +import { Account } from "@/models"; +import { API } from "../API"; + +export const getAccount = async ({ stakeKey }: { stakeKey?: string }) => { + const response = await API.get(`/account/${stakeKey || ""}`); + + return response.data; +}; diff --git a/govtool/frontend/src/services/requests/getAdaHolderVotingPower.ts b/govtool/frontend/src/services/requests/getAdaHolderVotingPower.ts index ec7a36755..c08b17b30 100644 --- a/govtool/frontend/src/services/requests/getAdaHolderVotingPower.ts +++ b/govtool/frontend/src/services/requests/getAdaHolderVotingPower.ts @@ -4,8 +4,10 @@ export const getAdaHolderVotingPower = async ({ stakeKey, }: { stakeKey?: string; -}): Promise => { - const response = await API.get(`/ada-holder/get-voting-power/${stakeKey}`); +}) => { + const response = await API.get( + `/ada-holder/get-voting-power/${stakeKey}`, + ); return response.data; }; diff --git a/govtool/frontend/src/services/requests/index.ts b/govtool/frontend/src/services/requests/index.ts index 0448747f2..598fe76d3 100644 --- a/govtool/frontend/src/services/requests/index.ts +++ b/govtool/frontend/src/services/requests/index.ts @@ -22,3 +22,4 @@ export * from "./postDRepRemoveVote"; export * from "./postDRepRetire"; export * from "./postDRepVote"; export * from "./getDRepVotingPowerList"; +export * from "./getAccount"; diff --git a/govtool/frontend/src/types/@intersect.mbo.d.ts b/govtool/frontend/src/types/@intersect.mbo.d.ts index f980a30bb..813a34eca 100644 --- a/govtool/frontend/src/types/@intersect.mbo.d.ts +++ b/govtool/frontend/src/types/@intersect.mbo.d.ts @@ -5,7 +5,7 @@ enum MetadataValidationStatus { INCORRECT_FORMAT = "INCORRECT_FORMAT", } declare module "@intersect.mbo/pdf-ui/cjs" { - import { EpochParams } from "@/models"; + import { EpochParams, Account } from "@/models"; type ProposalDiscussionProps = { pdfApiUrl: string; @@ -37,6 +37,11 @@ declare module "@intersect.mbo/pdf-ui/cjs" { }: { stakeKey?: string; }) => Promise; + getAccount: ({ + stakeKey, + }: { + stakeKey?: string; + }) => Promise; }; type GovernanceActionsOutcomesProps = { From 4c620b99016e438316e814fea85634c70289bbeb Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 28 May 2025 12:52:53 +0545 Subject: [PATCH 42/75] fix: update test IDs for budget discussion form components and related tests --- .../pages/budgetDiscussionSubmissionPage.ts | 87 +++++++++---------- .../proposalBudget.dRep.pb.spec.ts | 4 +- ...oposalBudgetSubmission.loggedin.pb.spec.ts | 8 +- 3 files changed, 46 insertions(+), 53 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts index bdb67e20c..5fb08c603 100644 --- a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts @@ -51,13 +51,8 @@ export default class BudgetDiscussionSubmissionPage { readonly verifyIdentityBtn = this.page.getByTestId("verify-identity-button"); readonly saveDraftBtn = this.page.getByTestId("draft-button"); readonly submitBtn = this.page.getByTestId("submit-button"); - readonly countryOfIncorporationBtn = this.page.getByTestId( - "country-of-incorporation" - ); - readonly agreeCheckbox = this.page.getByLabel( - "I agree to the information in" - ); //BUG missing test Ids + readonly agreeCheckbox = this.page.getByTestId("agree-checkbox"); readonly submitCheckbox = this.page.getByTestId("submit-checkbox"); // input @@ -65,18 +60,18 @@ export default class BudgetDiscussionSubmissionPage { readonly linkUrlInput = this.page.getByTestId("link-0-url-input"); // proposal-ownership - readonly companyNameInput = this.page.getByLabel("Company Name *"); //BUG missing test Ids - readonly companyDomainNameInput = this.page.getByLabel( - "Company Domain Name *" - ); //BUG missing test Ids - readonly groupNameInput = this.page.getByLabel("Group Name *"); //BUG missing test Ids - readonly groupTypeInput = this.page.getByLabel("Type of Group *"); //BUG missing test Ids - readonly keyInformationOfGroupInput = this.page.getByLabel( - "Key Information to Identify" - ); //BUG missing test Ids - readonly contactDetailsInput = this.page.getByLabel( - "Please provide your preferred" - ); //BUG missing test Ids + readonly companyNameInput = this.page.getByTestId("company-name-input"); + readonly companyDomainNameInput = this.page.getByTestId( + "company-domain-input" + ); + readonly groupNameInput = this.page.getByTestId("group-name-input"); + readonly groupTypeInput = this.page.getByTestId("group-type-input"); + readonly keyInformationOfGroupInput = this.page.getByTestId( + "group-identity-information-input" + ); + readonly contactDetailsInput = this.page.getByTestId( + "provide-preferred-input" + ); // problem-statements readonly problemStatementInput = this.page.getByTestId( @@ -93,51 +88,47 @@ export default class BudgetDiscussionSubmissionPage { ); // BUG missing test Ids // proposal-details - readonly proposalNameInput = this.page.getByLabel( - "What is your proposed name to" - ); //BUG missing testId + readonly proposalNameInput = this.page.getByTestId("proposal-name-input"); readonly proposalDescriptionInput = this.page.getByTestId( "proposal-description-input" ); readonly proposalKeyDependenciesInput = this.page.getByTestId( "key-dependencies-input" ); - readonly proposalMaintainAndSupportInput = this.page.getByLabel( - "How will this proposal be" - ); //BUG missing testId + readonly proposalMaintainAndSupportInput = this.page.getByTestId( + "proposal-maintain-and-support-input" + ); readonly milestonesInput = this.page.getByTestId( "key-proposal-deliverables-input" ); readonly teamSizeAndDurationInput = this.page.getByTestId( "resourcing-duration-estimates-input" ); - readonly previousExperienceInput = this.page.getByLabel( - "Please provide previous" - ); //BUG missing testId - readonly otherDescriptionInput = this.page.getByLabel( - "Please describe what you have" + readonly previousExperienceInput = this.page.getByTestId( + "proposal-previous-experience-input" + ); + readonly otherDescriptionInput = this.page.getByTestId( + "other-contract-description" ); // costing - readonly adaAmountInput = this.page.getByLabel("ADA Amount *"); //BUG missing test Ids - readonly usaToAdaCnversionRateInput = this.page.getByLabel( - "USD to ADA Conversion Rate *" - ); //BUG missing test Ids - readonly preferredCurrencyInput = this.page.getByLabel( - "Amount in preferred currency *" + readonly adaAmountInput = this.page.getByTestId("ada-amount-input"); + readonly usaToAdaCnversionRateInput = this.page.getByTestId( + "usd-ada-conversion-input" + ); + readonly preferredCurrencyInput = this.page.getByTestId( + "preferred-currency-amount-input" ); readonly costBreakdownInput = this.page.getByTestId("cost-breakdown-input"); readonly venderDetailsInput = this.page.getByLabel("Please provide further"); //BUG missing test Ids // select - readonly beneficiaryCountrySelect = this.page.getByTestId( - "beneficiary-country-of-residence" - ); - readonly beneficiaryNationalitySelect = this.page.getByTestId( - "beneficiary-nationality" - ); - - readonly companyTypeSelect = this.page.getByTestId("beneficiary-type"); + readonly proposalCommittee = this.page + .getByLabel("Is this proposal being") + .first(); // BUG incorrect position of testId + readonly countryOfIncorporationBtn = this.page + .getByLabel("Country of Incorporation *") + .first(); // BUG incorrect position of testId readonly publicChampionSelect = this.page.getByTestId( "proposal-public-champion" ); @@ -234,9 +225,9 @@ export default class BudgetDiscussionSubmissionPage { // costing readonly adaAmountContent = this.page.getByTestId("ada-amount-content"); - readonly adaToUsdConversionRateContent = this.page.getByTestId( + readonly usdToAdaConversionRateContent = this.page.getByTestId( "usd-to-ada-conversion-rate-content" - ); // BUG typo + ); readonly preferredCurrencyContent = this.page.getByTestId( "preferred-currency-content" ); @@ -271,7 +262,7 @@ export default class BudgetDiscussionSubmissionPage { proposalOwnership: BudgetProposalOwnershipProps, isNaviagted = true ) { - await this.companyTypeSelect.click(); + await this.proposalCommittee.click(); await this.page .getByRole("option", { name: proposalOwnership.companyType }) .click(); //BUG missing testId @@ -772,7 +763,7 @@ export default class BudgetDiscussionSubmissionPage { await expect(this.adaAmountContent).toHaveText( `₳ ${formatWithThousandSeparator(proposalInformations.costing.adaAmount)}` ); - await expect(this.adaToUsdConversionRateContent).toHaveText( + await expect(this.usdToAdaConversionRateContent).toHaveText( proposalInformations.costing.usdToAdaConversionRate.toString() ); @@ -836,7 +827,7 @@ export default class BudgetDiscussionSubmissionPage { proposalOwnership: BudgetProposalOwnershipProps, isValid: boolean = true ) { - const companyTypeSelectContent = await this.companyTypeSelect.textContent(); + const companyTypeSelectContent = await this.proposalCommittee.textContent(); if (isValid) { if (proposalOwnership.companyType === "Company") { diff --git a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts index db17b101a..4c511cf39 100644 --- a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts +++ b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.dRep.pb.spec.ts @@ -61,7 +61,9 @@ test.describe("Budget proposal dRep behaviour", () => { await budgetDiscussionDetailsPage.voteOnPoll(choice); await budgetDiscussionDetailsPage.changePollVote(); - await expect(budgetDiscussionDetailsPage.pollYesBtn).not.toBeVisible({timeout: 60_000}); + await expect(budgetDiscussionDetailsPage.pollYesBtn).not.toBeVisible({ + timeout: 60_000, + }); await expect(budgetDiscussionDetailsPage.pollNoBtn).not.toBeVisible(); // vote must be changed diff --git a/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts b/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts index ce5863062..d647175f9 100644 --- a/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts +++ b/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts @@ -62,7 +62,7 @@ test.describe("Budget proposal 01 wallet", () => { test("12D_1. Should verify all field of “proposal ownership” section", async () => { // default field await expect( - budgetProposalSubmissionPage.companyTypeSelect + budgetProposalSubmissionPage.proposalCommittee ).toBeVisible(); await expect( @@ -70,7 +70,7 @@ test.describe("Budget proposal 01 wallet", () => { ).toBeVisible(); // company type field - await budgetProposalSubmissionPage.companyTypeSelect.click(); + await budgetProposalSubmissionPage.proposalCommittee.click(); await budgetProposalSubmissionPage.currentPage .getByRole("option", { name: CompanyEnum.Company }) .click(); //BUG missing testId @@ -86,7 +86,7 @@ test.describe("Budget proposal 01 wallet", () => { ).toBeVisible(); // group type field - await budgetProposalSubmissionPage.companyTypeSelect.click(); + await budgetProposalSubmissionPage.proposalCommittee.click(); await budgetProposalSubmissionPage.currentPage .getByRole("option", { name: CompanyEnum.Group }) .click(); //BUG missing testId @@ -436,7 +436,7 @@ test("12C. Should save and view draft proposal", async ({ browser }) => { await budgetSubmissionPage.viewLastDraft(); - await expect(budgetSubmissionPage.companyTypeSelect).toHaveText( + await expect(budgetSubmissionPage.proposalCommittee).toHaveText( draftProposalOwnership.companyType ); From 4617a464fd84b9ec94bafecd664abd6a4f78b64e Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 28 May 2025 15:43:14 +0545 Subject: [PATCH 43/75] feat: extend proposed government action type to support extra responses --- .../govtool-frontend/playwright/lib/types.ts | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/govtool-frontend/playwright/lib/types.ts b/tests/govtool-frontend/playwright/lib/types.ts index b336993e8..5ac7273ca 100644 --- a/tests/govtool-frontend/playwright/lib/types.ts +++ b/tests/govtool-frontend/playwright/lib/types.ts @@ -196,13 +196,29 @@ export type ProposalCreateRequest = { has_guardrails?: boolean; is_draft: boolean; }; - export type ProposedGovAction = { id: number; attributes: { gov_action_type_name: string; + prop_comments_number: number; createdAt: string; updatedAt: string; + creator: { + data: { + id: number; + attributes: { + govtool_username: string; + }; + }; + }; + bd_proposal_detail: { + data: { + id: number; + attributes: { + proposal_name: string; + }; + }; + }; }; }; @@ -521,3 +537,13 @@ export enum BudgetProposalStageEnum { } export type VoterType = "DReps" | "SPOs" | "CC"; + +export type BudgetProposalFilterTypes = + | "Newest" + | "Oldest" + | "Most comments" + | "Least comments" + | "Name A-Z" + | "Name Z-A" + | "Proposer A-Z" + | "Proposer Z-A"; From 374b88077dc2bbf73aa80da6ccc422efdfe3f99b Mon Sep 17 00:00:00 2001 From: Niraj Date: Wed, 28 May 2025 15:43:48 +0545 Subject: [PATCH 44/75] feat: update budget propsoal filter logic to support updated filter --- .../playwright/lib/constants/index.ts | 14 ++++- .../lib/pages/budgetDiscussionPage.ts | 27 ++++++++-- .../11-proposal-budget/proposalBudget.spec.ts | 51 +++++++++++++++---- 3 files changed, 76 insertions(+), 16 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/constants/index.ts b/tests/govtool-frontend/playwright/lib/constants/index.ts index 407772241..11fe3a300 100644 --- a/tests/govtool-frontend/playwright/lib/constants/index.ts +++ b/tests/govtool-frontend/playwright/lib/constants/index.ts @@ -1,5 +1,5 @@ import { faker } from "@faker-js/faker"; -import { InvalidMetadataType } from "@types"; +import { BudgetProposalFilterTypes, InvalidMetadataType } from "@types"; export const SECURITY_RELEVANT_PARAMS_MAP: Record = { maxBlockBodySize: "max_block_size", @@ -61,3 +61,15 @@ export const InvalidMetadata: InvalidMetadataType[] = [ hash: "e71bf6171adda3754a87fff5c2d8d9e404eb3366428a5be13f7e76357a39004f", }, ]; + +export const budgetProposalfilterOptionNames: Array = + [ + "Newest", + "Oldest", + "Most comments", + "Least comments", + "Name A-Z", + "Name Z-A", + "Proposer A-Z", + "Proposer Z-A", + ]; diff --git a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionPage.ts b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionPage.ts index 3ca0fa9db..571d0688a 100644 --- a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionPage.ts @@ -1,6 +1,10 @@ import { functionWaitedAssert, waitedLoop } from "@helpers/waitedLoop"; import { expect, Locator, Page } from "@playwright/test"; -import { BudgetDiscussionEnum, ProposedGovAction } from "@types"; +import { + BudgetDiscussionEnum, + BudgetProposalFilterTypes, + ProposedGovAction, +} from "@types"; import environments from "lib/constants/environments"; import BudgetDiscussionDetailsPage from "./budgetDiscussionDetailsPage"; @@ -140,16 +144,29 @@ export default class BudgetDiscussionPage { } async sortAndValidate( - option: "asc" | "desc", + type: BudgetProposalFilterTypes, validationFn: (p1: ProposedGovAction, p2: ProposedGovAction) => boolean ) { + const sortMappings = { + "Proposer A-Z": "&sort[creator][govtool_username]=ASC", + "Proposer Z-A": "&sort[creator][govtool_username]=DESC", + "Name A-Z": "&sort[bd_proposal_detail][proposal_name]=ASC", + "Name Z-A": "&sort[bd_proposal_detail][proposal_name]=DESC", + "Most comments": "&sort[prop_comments_number]=DESC", + "Least comments": "&sort[prop_comments_number]=ASC", + Oldest: "&sort[createdAt]=ASC", + Newest: "&sort[createdAt]=DESC", + }; + + const urlParam = sortMappings[type]; + const populateParam = "&populate[0]=bd_costing"; + const responsePromise = this.page.waitForResponse((response) => - response - .url() - .includes(`&sort[createdAt]=${option}&populate[0]=bd_costing`) + response.url().includes(`${urlParam}${populateParam}`) ); await this.sortBtn.click(); + await this.page.getByTestId(`${type}-sort-option`).click(); const response = await responsePromise; let proposals: ProposedGovAction[] = (await response.json()).data; diff --git a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.spec.ts b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.spec.ts index 733ed6fd7..4cf3b5fb3 100644 --- a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.spec.ts +++ b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.spec.ts @@ -1,4 +1,5 @@ import environments from "@constants/environments"; +import { budgetProposalfilterOptionNames } from "@constants/index"; import { faker } from "@faker-js/faker"; import { test } from "@fixtures/walletExtension"; import { setAllureEpic } from "@helpers/allure"; @@ -8,7 +9,11 @@ import { functionWaitedAssert } from "@helpers/waitedLoop"; import BudgetDiscussionDetailsPage from "@pages/budgetDiscussionDetailsPage"; import BudgetDiscussionPage from "@pages/budgetDiscussionPage"; import { expect } from "@playwright/test"; -import { BudgetDiscussionEnum } from "@types"; +import { + BudgetDiscussionEnum, + BudgetProposalFilterTypes, + ProposedGovAction, +} from "@types"; const mockBudgetProposal = require("../../lib/_mock/budgetProposal.json"); const mockPoll = require("../../lib/_mock/budgetProposalPoll.json"); @@ -103,15 +108,41 @@ test.describe("Budget proposal list manipulation", () => { }); test("11B_3. Should sort budget proposals", async () => { - await budgetDiscussionPage.sortAndValidate( - "asc", - (p1, p2) => p1.attributes.createdAt <= p2.attributes.createdAt - ); - - await budgetDiscussionPage.sortAndValidate( - "desc", - (p1, p2) => p1.attributes.createdAt >= p2.attributes.createdAt - ); + const sortOptions = { + Oldest: (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.createdAt <= p2.attributes.createdAt, + Newest: (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.createdAt >= p2.attributes.createdAt, + "Most comments": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.prop_comments_number >= + p2.attributes.prop_comments_number, + "Least comments": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.prop_comments_number <= + p2.attributes.prop_comments_number, + "Name A-Z": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.bd_proposal_detail.data.attributes.proposal_name.localeCompare( + p2.attributes.bd_proposal_detail.data.attributes.proposal_name + ) <= 0, + "Name Z-A": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.bd_proposal_detail.data.attributes.proposal_name.localeCompare( + p2.attributes.bd_proposal_detail.data.attributes.proposal_name + ) >= 0, + "Proposer A-Z": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.creator.data.attributes.govtool_username.localeCompare( + p2.attributes.creator.data.attributes.govtool_username + ) <= 0, + "Proposer Z-A": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.creator.data.attributes.govtool_username.localeCompare( + p2.attributes.creator.data.attributes.govtool_username + ) >= 0, + }; + + for (const [option, validationFn] of Object.entries(sortOptions)) { + await budgetDiscussionPage.sortAndValidate( + option as BudgetProposalFilterTypes, + validationFn + ); + } }); }); }); From 4a1248e23314f76f9b834832e155d7dc8e405753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Tue, 27 May 2025 12:26:43 +0200 Subject: [PATCH 45/75] fix(#3681): preserve maintenance banner expanded state --- CHANGELOG.md | 4 +- .../src/components/organisms/Drawer.tsx | 5 +- .../MaintenanceEndingBanner.tsx | 17 +-- .../MaintenanceEndingBannerContext.tsx | 103 ++++++++++++++++++ .../MaintenanceEndingBanner/index.ts | 2 + .../src/components/organisms/TopBanners.tsx | 25 ++--- .../src/components/organisms/TopNav.tsx | 16 ++- .../src/components/organisms/index.ts | 1 + .../frontend/src/context/contextProviders.tsx | 33 +++--- govtool/frontend/src/pages/Dashboard.tsx | 7 +- 10 files changed, 169 insertions(+), 44 deletions(-) rename govtool/frontend/src/components/organisms/{ => MaintenanceEndingBanner}/MaintenanceEndingBanner.tsx (88%) create mode 100644 govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBannerContext.tsx create mode 100644 govtool/frontend/src/components/organisms/MaintenanceEndingBanner/index.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index a710eaa88..47a85717a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ changes. ### Added +- Preserve maintenance ending banner state on the wallet connection change [Issue 3681](https://github.com/IntersectMBO/govtool/issues/3681) + ### Fixed ### Changed @@ -20,8 +22,8 @@ changes. ## [v2.0.23](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.23) 2025-05-22 - ### Added + - Add CIP-129 support for gov_actions hashes in Live Voting (governance actions) [Issue 3619](https://github.com/IntersectMBO/govtool/issues/3619) - Add maintenance ending banner [Issue 3647](https://github.com/IntersectMBO/govtool/issues/3647) diff --git a/govtool/frontend/src/components/organisms/Drawer.tsx b/govtool/frontend/src/components/organisms/Drawer.tsx index 2ed7256af..5797acc7b 100644 --- a/govtool/frontend/src/components/organisms/Drawer.tsx +++ b/govtool/frontend/src/components/organisms/Drawer.tsx @@ -7,6 +7,7 @@ import { useFeatureFlag } from "@context"; import { useGetVoterInfo } from "@hooks"; import { WalletInfoCard, DRepInfoCard } from "@molecules"; import { openInNewTab } from "@utils"; +import { useMaintenanceEndingBannerContext } from "./MaintenanceEndingBanner"; export const Drawer = () => { const { @@ -14,6 +15,8 @@ export const Drawer = () => { isGovernanceOutcomesPillarEnabled, } = useFeatureFlag(); const { voter } = useGetVoterInfo(); + const { height: maintenanceEndingBannerHeight } = + useMaintenanceEndingBannerContext(); return ( { flexDirection: "column", height: "100vh", position: "sticky", - top: 0, + top: maintenanceEndingBannerHeight, width: `${DRAWER_WIDTH}px`, overflowY: "auto", diff --git a/govtool/frontend/src/components/organisms/MaintenanceEndingBanner.tsx b/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx similarity index 88% rename from govtool/frontend/src/components/organisms/MaintenanceEndingBanner.tsx rename to govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx index 37d207e72..9887799ad 100644 --- a/govtool/frontend/src/components/organisms/MaintenanceEndingBanner.tsx +++ b/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx @@ -1,19 +1,20 @@ import { Box, Typography, IconButton } from "@mui/material"; -import { useState } from "react"; import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; import { Trans, useTranslation } from "react-i18next"; +import { useMaintenanceEndingBannerContext } from "./MaintenanceEndingBannerContext"; + +const EXPANDED_HEIGHT = 135; +const COLLAPSED_HEIGHT = 50; export const MaintenanceEndingBanner = () => { - const [isExpanded, setIsExpanded] = useState(true); + const { ref, isExpanded, toggleExpanded } = + useMaintenanceEndingBannerContext(); const { t } = useTranslation(); - const handleToggle = () => { - setIsExpanded((prev) => !prev); - }; - return ( { { {/* Expandable Content */} ; + height: number; + y: number; + isExpanded: boolean; + toggleExpanded: () => void; +} + +const MaintenanceEndingBannerContext = + createContext({ + ref: createRef(), + height: 0, + y: 0, + isExpanded: true, + toggleExpanded: () => {}, + }); + +export const MaintenanceEndingBannerProvider = ({ + children, +}: React.PropsWithChildren) => { + const ref = useRef(null); + const [height, setHeight] = useState(0); + const [y, setY] = useState(0); + const [isExpanded, setIsExpanded] = useState(true); + + const toggleExpanded = () => { + setIsExpanded((prev) => !prev); + }; + + useLayoutEffect(() => { + let frameId: number | null = null; + + const updatePosition = () => { + if (ref.current) { + const rect = ref.current.getBoundingClientRect(); + + setY(rect.top); + setHeight(rect.height); + } + }; + + const throttledUpdate = () => { + // Context skipping update - frame already queued + if (frameId) return; + + frameId = requestAnimationFrame(() => { + updatePosition(); + frameId = null; + }); + }; + + updatePosition(); + + window.addEventListener("scroll", throttledUpdate, { passive: true }); + window.addEventListener("resize", throttledUpdate); + + return () => { + window.removeEventListener("scroll", throttledUpdate); + window.removeEventListener("resize", throttledUpdate); + + if (frameId) { + cancelAnimationFrame(frameId); + } + }; + }, []); + + const value = useMemo( + () => ({ + ref, + height, + y, + isExpanded, + toggleExpanded, + }), + [ref, height, y, isExpanded, toggleExpanded], + ); + + return ( + + {children} + + ); +}; + +export const useMaintenanceEndingBannerContext = () => { + const context = useContext(MaintenanceEndingBannerContext); + if (!context) { + throw new Error( + "useMaintenanceEndingBannerContext must be used within a MaintenanceEndingBannerProvider", + ); + } + return context; +}; diff --git a/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/index.ts b/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/index.ts new file mode 100644 index 000000000..e3253604a --- /dev/null +++ b/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/index.ts @@ -0,0 +1,2 @@ +export * from "./MaintenanceEndingBanner"; +export * from "./MaintenanceEndingBannerContext"; diff --git a/govtool/frontend/src/components/organisms/TopBanners.tsx b/govtool/frontend/src/components/organisms/TopBanners.tsx index f4cd741b8..df04c01db 100644 --- a/govtool/frontend/src/components/organisms/TopBanners.tsx +++ b/govtool/frontend/src/components/organisms/TopBanners.tsx @@ -1,13 +1,12 @@ import { Box, Link, Typography } from "@mui/material"; import { Trans, useTranslation } from "react-i18next"; -import { useAppContext, useCardano } from "@/context"; +import { useAppContext } from "@/context"; import { LINKS } from "@/consts/links"; import { MaintenanceEndingBanner } from "./MaintenanceEndingBanner"; export const TopBanners = () => { const { isMainnet, networkName, isInBootstrapPhase, isAppInitializing } = useAppContext(); - const { isEnabled } = useCardano(); const { t } = useTranslation(); if (isAppInitializing) { @@ -49,18 +48,16 @@ export const TopBanners = () => { {/* GOVTOOL MAINTENANCE ENDING SOON BANNER */} - {isEnabled && ( - - - - )} + + + {/* BOOTSTRAPPING BANNER */} diff --git a/govtool/frontend/src/components/organisms/TopNav.tsx b/govtool/frontend/src/components/organisms/TopNav.tsx index 5eb2654c5..2d8da5cf0 100644 --- a/govtool/frontend/src/components/organisms/TopNav.tsx +++ b/govtool/frontend/src/components/organisms/TopNav.tsx @@ -8,7 +8,7 @@ import { useCardano, useFeatureFlag, useModal } from "@context"; import { useScreenDimension, useTranslation } from "@hooks"; import { openInNewTab } from "@utils"; import { DrawerMobile } from "./DrawerMobile"; -import { MaintenanceEndingBanner } from "./MaintenanceEndingBanner"; +import { useMaintenanceEndingBannerContext } from "./MaintenanceEndingBanner"; const POSITION_TO_BLUR = 80; @@ -26,6 +26,9 @@ export const TopNav = ({ isConnectButton = true }) => { const navigate = useNavigate(); const { t } = useTranslation(); + const { height: maintenanceEndingBannerHeight } = + useMaintenanceEndingBannerContext(); + useEffect(() => { const onScroll = () => { if (!containerRef.current?.nextElementSibling) return; @@ -137,9 +140,14 @@ export const TopNav = ({ isConnectButton = true }) => { ); return ( - - - + ( - - - - - - - - {children} - - - - - - - + + + + + + + + + {children} + + + + + + + + ); diff --git a/govtool/frontend/src/pages/Dashboard.tsx b/govtool/frontend/src/pages/Dashboard.tsx index d623ba1b1..88648389d 100644 --- a/govtool/frontend/src/pages/Dashboard.tsx +++ b/govtool/frontend/src/pages/Dashboard.tsx @@ -88,7 +88,12 @@ export const Dashboard = () => { return ( - + {isMobile ? null : } Date: Tue, 27 May 2025 15:38:40 +0200 Subject: [PATCH 46/75] feat(#3681): add local storage for the value persistence --- .../MaintenanceEndingBannerContext.tsx | 25 +++++++++---- .../frontend/src/context/contextProviders.tsx | 37 ++++++++++--------- govtool/frontend/src/utils/localStorage.ts | 2 + 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBannerContext.tsx b/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBannerContext.tsx index 0644b2468..f57e25d8d 100644 --- a/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBannerContext.tsx +++ b/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBannerContext.tsx @@ -6,12 +6,17 @@ import { useRef, useState, useLayoutEffect, + useEffect, } from "react"; +import { + getItemFromLocalStorage, + MAINTENANCE_ENDING_BANNER_EXPANDED_KEY, + setItemToLocalStorage, +} from "@/utils"; interface MaintenanceEndingBannerContextType { ref: React.RefObject; height: number; - y: number; isExpanded: boolean; toggleExpanded: () => void; } @@ -20,7 +25,6 @@ const MaintenanceEndingBannerContext = createContext({ ref: createRef(), height: 0, - y: 0, isExpanded: true, toggleExpanded: () => {}, }); @@ -30,10 +34,19 @@ export const MaintenanceEndingBannerProvider = ({ }: React.PropsWithChildren) => { const ref = useRef(null); const [height, setHeight] = useState(0); - const [y, setY] = useState(0); - const [isExpanded, setIsExpanded] = useState(true); + const [isExpanded, setIsExpanded] = useState(true); + + useEffect(() => { + const storedValue = getItemFromLocalStorage( + MAINTENANCE_ENDING_BANNER_EXPANDED_KEY, + ); + if (storedValue !== null) { + setIsExpanded(JSON.parse(storedValue)); + } + }, []); const toggleExpanded = () => { + setItemToLocalStorage(MAINTENANCE_ENDING_BANNER_EXPANDED_KEY, !isExpanded); setIsExpanded((prev) => !prev); }; @@ -44,7 +57,6 @@ export const MaintenanceEndingBannerProvider = ({ if (ref.current) { const rect = ref.current.getBoundingClientRect(); - setY(rect.top); setHeight(rect.height); } }; @@ -78,11 +90,10 @@ export const MaintenanceEndingBannerProvider = ({ () => ({ ref, height, - y, isExpanded, toggleExpanded, }), - [ref, height, y, isExpanded, toggleExpanded], + [ref, height, isExpanded, toggleExpanded], ); return ( diff --git a/govtool/frontend/src/context/contextProviders.tsx b/govtool/frontend/src/context/contextProviders.tsx index 42d2703b5..f456018bb 100644 --- a/govtool/frontend/src/context/contextProviders.tsx +++ b/govtool/frontend/src/context/contextProviders.tsx @@ -7,6 +7,7 @@ import { FeatureFlagProvider } from "./featureFlag"; import { GovernanceActionProvider } from "./governanceAction"; import { AdaHandleProvider } from "./adaHandle"; import { ProposalDiscussionProvider } from "./proposalDiscussion"; + import { MaintenanceEndingBannerProvider } from "@/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBannerContext"; interface Props { @@ -15,23 +16,25 @@ interface Props { const ContextProviders = ({ children }: Props) => ( - - - - - - - - - {children} - - - - - - - - + + + + + + + + + + {children} + + + + + + + + + ); diff --git a/govtool/frontend/src/utils/localStorage.ts b/govtool/frontend/src/utils/localStorage.ts index 0bc866244..b1d6c9ae2 100644 --- a/govtool/frontend/src/utils/localStorage.ts +++ b/govtool/frontend/src/utils/localStorage.ts @@ -3,6 +3,8 @@ export const PROTOCOL_PARAMS_KEY = "protocol_params"; export const NETWORK_METRICS_KEY = "network_metrics"; export const NETWORK_INFO_KEY = "network_info"; export const NETWORK_TOTAL_STAKE_KEY = "network_total_stake"; +export const MAINTENANCE_ENDING_BANNER_EXPANDED_KEY = + "maintenance_ending_banner_expanded"; export const WALLET_LS_KEY = "wallet_data"; From 7260f0b238a8da529608b00d45e6c84d6af19393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 28 May 2025 13:43:41 +0200 Subject: [PATCH 47/75] fix(#3490): add missing DRep references --- CHANGELOG.md | 2 + govtool/backend/sql/list-dreps.sql | 54 ++++++++- govtool/backend/src/VVA/API.hs | 4 +- govtool/backend/src/VVA/API/Types.hs | 30 ++++- govtool/backend/src/VVA/DRep.hs | 112 ++++++++++++------ govtool/backend/src/VVA/Types.hs | 68 +++++++++-- .../components/organisms/DRepDetailsCard.tsx | 18 +-- .../EditDRepInfoSteps/EditDRepForm.tsx | 15 +-- govtool/frontend/src/models/api.ts | 9 +- .../src/stories/DRepDetailsCard.stories.ts | 12 +- .../GovernanceActionDetailsCard.stories.ts | 2 +- govtool/frontend/src/utils/tests/dRep.test.ts | 3 +- 12 files changed, 237 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47a85717a..53a5dc973 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ changes. ### Fixed +- Fix missing off chain references in DRep details [Issue 3490](https://github.com/IntersectMBO/govtool/issues/3490) + ### Changed ### Removed diff --git a/govtool/backend/sql/list-dreps.sql b/govtool/backend/sql/list-dreps.sql index 2c3b87aa5..3062c9f48 100644 --- a/govtool/backend/sql/list-dreps.sql +++ b/govtool/backend/sql/list-dreps.sql @@ -126,7 +126,35 @@ DRepData AS ( off_chain_vote_drep_data.motivations, off_chain_vote_drep_data.qualifications, off_chain_vote_drep_data.image_url, - off_chain_vote_drep_data.image_hash + off_chain_vote_drep_data.image_hash, + COALESCE( + ( + SELECT jsonb_agg(ref) + FROM jsonb_array_elements( + CASE + WHEN (ocvd.json::jsonb)->'body'->'references' IS NOT NULL + THEN (ocvd.json::jsonb)->'body'->'references' + ELSE '[]'::jsonb + END + ) AS ref + WHERE ref->>'@type' = 'Identity' + ), + '[]'::jsonb + ) AS identity_references, + COALESCE( + ( + SELECT jsonb_agg(ref) + FROM jsonb_array_elements( + CASE + WHEN (ocvd.json::jsonb)->'body'->'references' IS NOT NULL + THEN (ocvd.json::jsonb)->'body'->'references' + ELSE '[]'::jsonb + END + ) AS ref + WHERE ref->>'@type' = 'Link' + ), + '[]'::jsonb + ) AS link_references FROM drep_hash dh JOIN RankedDRepRegistration ON RankedDRepRegistration.drep_hash_id = dh.id @@ -212,7 +240,29 @@ DRepData AS ( off_chain_vote_drep_data.motivations, off_chain_vote_drep_data.qualifications, off_chain_vote_drep_data.image_url, - off_chain_vote_drep_data.image_hash + off_chain_vote_drep_data.image_hash, + ( + SELECT jsonb_agg(ref) + FROM jsonb_array_elements( + CASE + WHEN (ocvd.json::jsonb)->'body'->'references' IS NOT NULL + THEN (ocvd.json::jsonb)->'body'->'references' + ELSE '[]'::jsonb + END + ) AS ref + WHERE ref->>'@type' = 'Identity' + ), + ( + SELECT jsonb_agg(ref) + FROM jsonb_array_elements( + CASE + WHEN (ocvd.json::jsonb)->'body'->'references' IS NOT NULL + THEN (ocvd.json::jsonb)->'body'->'references' + ELSE '[]'::jsonb + END + ) AS ref + WHERE ref->>'@type' = 'Link' + ) ) SELECT * FROM DRepData WHERE diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs index 9488710a6..124356990 100644 --- a/govtool/backend/src/VVA/API.hs +++ b/govtool/backend/src/VVA/API.hs @@ -134,7 +134,9 @@ drepRegistrationToDrep Types.DRepRegistration {..} = dRepMotivations = dRepRegistrationMotivations, dRepQualifications = dRepRegistrationQualifications, dRepImageUrl = dRepRegistrationImageUrl, - dRepImageHash = HexText <$> dRepRegistrationImageHash + dRepImageHash = HexText <$> dRepRegistrationImageHash, + dRepIdentityReferences = DRepReferences <$> dRepRegistrationIdentityReferences, + dRepLinkReferences = DRepReferences <$> dRepRegistrationLinkReferences } delegationToResponse :: Types.Delegation -> DelegationResponse diff --git a/govtool/backend/src/VVA/API/Types.hs b/govtool/backend/src/VVA/API/Types.hs index 6b517a9ce..f478bd974 100644 --- a/govtool/backend/src/VVA/API/Types.hs +++ b/govtool/backend/src/VVA/API/Types.hs @@ -273,7 +273,7 @@ instance ToParamSchema GovernanceActionSortMode where newtype GovernanceActionDetails - = GovernanceActionDetails { getValue :: Value } + = GovernanceActionDetails { getGovernanceActionValue :: Value } deriving newtype (Show) instance FromJSON GovernanceActionDetails where @@ -593,6 +593,7 @@ instance ToSchema VoteResponse where & example ?~ toJSON exampleVoteResponse + data DRepInfoResponse = DRepInfoResponse { dRepInfoResponseIsScriptBased :: Bool @@ -612,7 +613,7 @@ data DRepInfoResponse , dRepInfoResponseGivenName :: Maybe Text , dRepInfoResponseObjectives :: Maybe Text , dRepInfoResponseMotivations :: Maybe Text - , dRepInfoResponseQualifications :: Maybe Text + , dRepInfoResponseQualifications :: Maybe Text , dRepInfoResponseImageUrl :: Maybe Text , dRepInfoResponseImageHash :: Maybe HexText } @@ -820,6 +821,27 @@ instance ToSchema DRepType where & description ?~ "DRep Type" & enum_ ?~ map toJSON [NormalDRep, SoleVoter] +newtype DRepReferences + = DRepReferences { getDRepReferencesValue :: Value } + deriving newtype (Show) + +instance FromJSON DRepReferences where + parseJSON v = return $ DRepReferences v + +instance ToJSON DRepReferences where + toJSON (DRepReferences d) = d + +instance ToSchema DRepReferences where + declareNamedSchema _ = pure $ NamedSchema (Just "DRepReferences") $ mempty + & type_ ?~ OpenApiObject + & description ?~ "A JSON value that can include nested objects and arrays" + & example ?~ toJSON + (Aeson.object + [ "some_key" .= ("some value" :: String) + , "nested_key" .= Aeson.object ["inner_key" .= (1 :: Int)] + , "array_key" .= [1, 2, 3 :: Int] + ]) + data DRep = DRep { dRepIsScriptBased :: Bool @@ -838,9 +860,11 @@ data DRep , dRepGivenName :: Maybe Text , dRepObjectives :: Maybe Text , dRepMotivations :: Maybe Text - , dRepQualifications :: Maybe Text + , dRepQualifications :: Maybe Text , dRepImageUrl :: Maybe Text , dRepImageHash :: Maybe HexText + , dRepIdentityReferences :: Maybe DRepReferences + , dRepLinkReferences :: Maybe DRepReferences } deriving (Generic, Show) diff --git a/govtool/backend/src/VVA/DRep.hs b/govtool/backend/src/VVA/DRep.hs index 49482b1e9..f8c9f8737 100644 --- a/govtool/backend/src/VVA/DRep.hs +++ b/govtool/backend/src/VVA/DRep.hs @@ -11,41 +11,74 @@ import Control.Monad.Reader import Crypto.Hash +import Data.Aeson (Value) import Data.ByteString (ByteString) -import qualified Data.ByteString.Base16 as Base16 -import qualified Data.ByteString.Char8 as C +import qualified Data.ByteString.Base16 as Base16 +import qualified Data.ByteString.Char8 as C import Data.FileEmbed (embedFile) import Data.Foldable (Foldable (sum)) import Data.Has (Has) -import qualified Data.Map as M +import qualified Data.Map as M import Data.Maybe (fromMaybe, isJust, isNothing) import Data.Scientific import Data.String (fromString) import Data.Text (Text, pack, unpack, intercalate) -import qualified Data.Text.Encoding as Text +import qualified Data.Text.Encoding as Text import Data.Time -import qualified Database.PostgreSQL.Simple as SQL +import qualified Database.PostgreSQL.Simple as SQL import Database.PostgreSQL.Simple.Types (In(..)) +import Database.PostgreSQL.Simple.FromRow import VVA.Config import VVA.Pool (ConnectionPool, withPool) -import qualified VVA.Proposal as Proposal +import qualified VVA.Proposal as Proposal import VVA.Types (AppError, DRepInfo (..), DRepRegistration (..), DRepStatus (..), DRepType (..), Proposal (..), Vote (..), DRepVotingPowerList (..)) +data DRepQueryResult = DRepQueryResult + { queryDrepHash :: Text + , queryDrepView :: Text + , queryIsScriptBased :: Bool + , queryUrl :: Maybe Text + , queryDataHash :: Maybe Text + , queryDeposit :: Scientific + , queryVotingPower :: Maybe Integer + , queryIsActive :: Bool + , queryTxHash :: Maybe Text + , queryDate :: LocalTime + , queryLatestDeposit :: Scientific + , queryLatestNonDeregisterVotingAnchorWasNotNull :: Bool + , queryMetadataError :: Maybe Text + , queryPaymentAddress :: Maybe Text + , queryGivenName :: Maybe Text + , queryObjectives :: Maybe Text + , queryMotivations :: Maybe Text + , queryQualifications :: Maybe Text + , queryImageUrl :: Maybe Text + , queryImageHash :: Maybe Text + , queryIdentityReferences :: Maybe Value + , queryLinkReferences :: Maybe Value + } deriving (Show) + +instance FromRow DRepQueryResult where + fromRow = DRepQueryResult + <$> field <*> field <*> field <*> field <*> field <*> field + <*> field <*> field <*> field <*> field <*> field <*> field + <*> field <*> field <*> field <*> field <*> field <*> field + <*> field <*> field <*> field <*> field + sqlFrom :: ByteString -> SQL.Query sqlFrom bs = fromString $ unpack $ Text.decodeUtf8 bs listDRepsSql :: SQL.Query listDRepsSql = sqlFrom $(embedFile "sql/list-dreps.sql") - listDReps :: (Has ConnectionPool r, Has VVAConfig r, MonadReader r m, MonadIO m) => Maybe Text -> m [DRepRegistration] listDReps mSearchQuery = withPool $ \conn -> do let searchParam = fromMaybe "" mSearchQuery - results <- liftIO $ SQL.query conn listDRepsSql + results <- liftIO (SQL.query conn listDRepsSql ( searchParam -- COALESCE(?, '') , searchParam -- LENGTH(?) , searchParam -- AND ? @@ -56,44 +89,45 @@ listDReps mSearchQuery = withPool $ \conn -> do , "%" <> searchParam <> "%" -- objectives , "%" <> searchParam <> "%" -- motivations , "%" <> searchParam <> "%" -- qualifications - ) + ) :: IO [DRepQueryResult]) timeZone <- liftIO getCurrentTimeZone return - [ DRepRegistration drepHash drepView isScriptBased url dataHash (floor @Scientific deposit) votingPower status drepType txHash (localTimeToUTC timeZone date) metadataError paymentAddress givenName objectives motivations qualifications imageUrl imageHash - | ( drepHash - , drepView - , isScriptBased - , url - , dataHash - , deposit - , votingPower - , isActive - , txHash - , date - , latestDeposit - , latestNonDeregisterVotingAnchorWasNotNull - , metadataError - , paymentAddress - , givenName - , objectives - , motivations - , qualifications - , imageUrl - , imageHash - ) <- results - , let status = case (isActive, deposit) of + [ DRepRegistration + (queryDrepHash result) + (queryDrepView result) + (queryIsScriptBased result) + (queryUrl result) + (queryDataHash result) + (floor @Scientific $ queryDeposit result) + (queryVotingPower result) + status + drepType + (queryTxHash result) + (localTimeToUTC timeZone $ queryDate result) + (queryMetadataError result) + (queryPaymentAddress result) + (queryGivenName result) + (queryObjectives result) + (queryMotivations result) + (queryQualifications result) + (queryImageUrl result) + (queryImageHash result) + (queryIdentityReferences result) + (queryLinkReferences result) + | result <- results + , let status = case (queryIsActive result, queryDeposit result) of (_, d) | d < 0 -> Retired (isActive, d) | d >= 0 && isActive -> Active | d >= 0 && not isActive -> Inactive - , let latestDeposit' = floor @Scientific latestDeposit :: Integer - , let drepType | latestDeposit' >= 0 && isNothing url = SoleVoter - | latestDeposit' >= 0 && isJust url = DRep - | latestDeposit' < 0 && not latestNonDeregisterVotingAnchorWasNotNull = SoleVoter - | latestDeposit' < 0 && latestNonDeregisterVotingAnchorWasNotNull = DRep - | Data.Maybe.isJust url = DRep + , let latestDeposit' = floor @Scientific (queryLatestDeposit result) :: Integer + , let drepType | latestDeposit' >= 0 && isNothing (queryUrl result) = SoleVoter + | latestDeposit' >= 0 && isJust (queryUrl result) = DRep + | latestDeposit' < 0 && not (queryLatestNonDeregisterVotingAnchorWasNotNull result) = SoleVoter + | latestDeposit' < 0 && queryLatestNonDeregisterVotingAnchorWasNotNull result = DRep + | Data.Maybe.isJust (queryUrl result) = DRep ] - + getVotingPowerSql :: SQL.Query getVotingPowerSql = sqlFrom $(embedFile "sql/get-voting-power.sql") diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs index e6e674925..154d0619f 100644 --- a/govtool/backend/src/VVA/Types.hs +++ b/govtool/backend/src/VVA/Types.hs @@ -5,26 +5,28 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE TypeApplications #-} +{-# LANGUAGE ScopedTypeVariables #-} module VVA.Types where import Control.Concurrent.QSem import Control.Exception -import Control.Monad.Except (MonadError) -import Control.Monad.Fail (MonadFail) -import Control.Monad.IO.Class (MonadIO) -import Control.Monad.Reader (MonadReader) +import Control.Monad.Except (MonadError) +import Control.Monad.Fail (MonadFail) +import Control.Monad.IO.Class (MonadIO) +import Control.Monad.Reader (MonadReader) -import Data.Aeson (Value, ToJSON (..), object, (.=)) -import qualified Data.Cache as Cache +import Data.Aeson (Value, ToJSON (..), object, (.=)) +import qualified Data.Cache as Cache import Data.Has -import Data.Pool (Pool) -import Data.Text (Text) -import Data.Time (UTCTime, LocalTime) +import Data.Pool (Pool) +import Data.Text (Text) +import Data.Time (UTCTime, LocalTime) import Data.Scientific -import Database.PostgreSQL.Simple (Connection) +import Database.PostgreSQL.Simple (Connection) import Database.PostgreSQL.Simple.FromRow +import Database.PostgreSQL.Simple.FromField (FromField(..), returnError, ResultError(ConversionFailed)) import VVA.Cache import VVA.Config @@ -107,8 +109,25 @@ data DRepVotingPowerList data DRepStatus = Active | Inactive | Retired deriving (Show, Eq, Ord) +instance FromField DRepStatus where + fromField f mdata = do + (value :: Text) <- fromField f mdata + case value of + "Active" -> return Active + "Inactive" -> return Inactive + "Retired" -> return Retired + _ -> returnError ConversionFailed f "Invalid DRepStatus" + data DRepType = DRep | SoleVoter deriving (Show, Eq) +instance FromField DRepType where + fromField f mdata = do + (value :: Text) <- fromField f mdata + case value of + "DRep" -> return DRep + "SoleVoter" -> return SoleVoter + _ -> returnError ConversionFailed f "Invalid DRepType" + data DRepRegistration = DRepRegistration { dRepRegistrationDRepHash :: Text @@ -127,12 +146,39 @@ data DRepRegistration , dRepRegistrationGivenName :: Maybe Text , dRepRegistrationObjectives :: Maybe Text , dRepRegistrationMotivations :: Maybe Text - , dRepRegistrationQualifications :: Maybe Text + , dRepRegistrationQualifications :: Maybe Text , dRepRegistrationImageUrl :: Maybe Text , dRepRegistrationImageHash :: Maybe Text + , dRepRegistrationIdentityReferences :: Maybe Value + , dRepRegistrationLinkReferences :: Maybe Value } deriving (Show) +instance FromRow DRepRegistration where + fromRow = + DRepRegistration + <$> field -- dRepRegistrationDRepHash + <*> field -- dRepRegistrationView + <*> field -- dRepRegistrationIsScriptBased + <*> field -- dRepRegistrationUrl + <*> field -- dRepRegistrationDataHash + <*> (floor @Scientific <$> field) -- dRepRegistrationDeposit + <*> field -- dRepRegistrationVotingPower + <*> field -- dRepRegistrationStatus + <*> field -- dRepRegistrationType + <*> field -- dRepRegistrationLatestTxHash + <*> field -- dRepRegistrationLatestRegistrationDate + <*> field -- dRepRegistrationMetadataError + <*> field -- dRepRegistrationPaymentAddress + <*> field -- dRepRegistrationGivenName + <*> field -- dRepRegistrationObjectives + <*> field -- dRepRegistrationMotivations + <*> field -- dRepRegistrationQualifications + <*> field -- dRepRegistrationImageUrl + <*> field -- dRepRegistrationImageHash + <*> field -- dRepRegistrationIdentityReferences + <*> field -- dRepRegistrationLinkReferences + data Proposal = Proposal { proposalId :: Integer diff --git a/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx b/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx index 82b560c44..8d692e788 100644 --- a/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx +++ b/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx @@ -41,7 +41,8 @@ export const DRepDetailsCard = ({ objectives, paymentAddress, qualifications, - references, + identityReferences, + linkReferences, status, url, view, @@ -75,21 +76,6 @@ export const DRepDetailsCard = ({ validate(); }, [url]); - const groupedReferences = references?.reduce>( - (acc, reference) => { - const type = reference["@type"]; - if (!acc[type]) { - acc[type] = []; - } - acc[type].push(reference); - return acc; - }, - {}, - ); - - const linkReferences = groupedReferences?.Link; - const identityReferences = groupedReferences?.Identity; - return ( { if (loadUserData) { const data: DRepData = state ?? yourselfDRep; - const groupedReferences = data?.references?.reduce< - Record - >((acc, reference) => { - const type = reference["@type"]; - if (!acc[type]) { - acc[type] = []; - } - acc[type].push(reference); - return acc; - }, {}); + reset({ ...data, objectives: data?.objectives ?? "", @@ -58,8 +49,8 @@ export const EditDRepForm = ({ qualifications: data?.qualifications ?? "", paymentAddress: data?.paymentAddress ?? "", image: data?.image ?? "", - linkReferences: groupedReferences?.Link ?? [getEmptyReference("Link")], - identityReferences: groupedReferences?.Identity ?? [ + linkReferences: data.linkReferences ?? [getEmptyReference("Link")], + identityReferences: data.identityReferences ?? [ getEmptyReference("Identity"), ], }); diff --git a/govtool/frontend/src/models/api.ts b/govtool/frontend/src/models/api.ts index bc374ccad..6ef89f3df 100644 --- a/govtool/frontend/src/models/api.ts +++ b/govtool/frontend/src/models/api.ts @@ -150,6 +150,12 @@ export enum DRepListSort { Status = "Status", } +type Reference = { + "@type": "Identity" | "Links"; + label: string; + uri: string; +}; + export type DrepDataDTO = { deposit: number; drepId: string; @@ -163,6 +169,8 @@ export type DrepDataDTO = { view: string; votingPower?: number; imageUrl: string | null; + identityReferences: Reference[]; + linkReferences: Reference[]; // either base64 for IPFS image or URL for regular image image: string | null; }; @@ -173,7 +181,6 @@ export type DRepData = DrepDataDTO & { objectives: string | null; motivations: string | null; qualifications: string | null; - references: Reference[]; doNotList: boolean; imageUrl: string | null; // either base64 for IPFS image or URL for regular image diff --git a/govtool/frontend/src/stories/DRepDetailsCard.stories.ts b/govtool/frontend/src/stories/DRepDetailsCard.stories.ts index 17754f8c9..71625f098 100644 --- a/govtool/frontend/src/stories/DRepDetailsCard.stories.ts +++ b/govtool/frontend/src/stories/DRepDetailsCard.stories.ts @@ -28,29 +28,31 @@ const meta = { "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras semper tortor ullamcorper volutpat vehicula. Duis varius orci a elit luctus, in fringilla nisl fringilla. Fusce pellentesque convallis dapibus. In hac habitasse platea dictumst. Nunc efficitur ipsum at ipsum blandit, ac eleifend purus pulvinar. Pellentesque orci quam, interdum eget massa id, sollicitudin lacinia turpis. Nullam lectus quam, congue commodo sollicitudin in, pretium sit amet metus. Integer pretium, odio eu dictum posuere.", qualifications: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc porta iaculis sodales. Praesent non nisi fermentum, porta sem in, porta arcu. In dignissim pulvinar est eu dignissim. Duis vitae vehicula dui. Praesent posuere egestas lacus, at pulvinar elit tempus ut. Etiam vulputate, lorem in accumsan.", - references: [ + linkReferences: [ { - "@type": "Link", + "@type": "Links", label: "Link Reference", uri: "https://example.com/", }, { - "@type": "Link", + "@type": "Links", label: "Another Link Reference", uri: "https://example.com/", }, + ], + identityReferences: [ { "@type": "Identity", label: "Identity Reference", uri: "https://example.com/", }, { - "@type": "GovernanceMetadata", + "@type": "Identity", label: "GovernanceMetadata Reference", uri: "https://example.com/", }, { - "@type": "Other", + "@type": "Identity", label: "Other Reference", uri: "https://example.com/", }, diff --git a/govtool/frontend/src/stories/GovernanceActionDetailsCard.stories.ts b/govtool/frontend/src/stories/GovernanceActionDetailsCard.stories.ts index 67e6001f7..7d1b14eab 100644 --- a/govtool/frontend/src/stories/GovernanceActionDetailsCard.stories.ts +++ b/govtool/frontend/src/stories/GovernanceActionDetailsCard.stories.ts @@ -59,7 +59,7 @@ const commonArgs = { metadataHash: "exampleMetadataHash", references: [ { - "@type": "Reference", + "@type": "Links", uri: "https://exampleurl.com", label: "Example label", }, diff --git a/govtool/frontend/src/utils/tests/dRep.test.ts b/govtool/frontend/src/utils/tests/dRep.test.ts index 00a06a4f2..f35f7cbd0 100644 --- a/govtool/frontend/src/utils/tests/dRep.test.ts +++ b/govtool/frontend/src/utils/tests/dRep.test.ts @@ -14,7 +14,8 @@ const EXAMPLE_DREP: DRepData = { status: DRepStatus.Active, type: "DRep" as TDRepType, givenName: "name", - references: [], + identityReferences: [], + linkReferences: [], latestRegistrationDate: "2024-07-10", paymentAddress: null, objectives: null, From 8a7678fcec670dd4b032285fe1104d3196d50df8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 13:35:11 +0000 Subject: [PATCH 48/75] chore: update @intersect.mbo/pdf-ui to 0.7.0-beta-31 --- govtool/frontend/package-lock.json | 8 ++++---- govtool/frontend/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index c38a3bf93..e67501fbd 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -15,7 +15,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.2", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "0.7.0-beta-30", + "@intersect.mbo/pdf-ui": "0.7.0-beta-31", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -3424,9 +3424,9 @@ "license": "ISC" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "0.7.0-beta-30", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-30.tgz", - "integrity": "sha512-lCEwD8XeuJuwhwrWDkSnFrVocd+OIaPeP4KF1giZNpBiLPXN+kJ6uQrT9ALoFw/1y7IRzzX571+Cyz8iHGguMw==", + "version": "0.7.0-beta-31", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-31.tgz", + "integrity": "sha512-fzPbL3kBB4k7IthkDzSWKrntcTC6261kGcIqilCReRYxHJvTnXJpcoKTGkJ7Q7C8Gd+IWI2/nYqYHBkb5O914w==", "dependencies": { "@emurgo/cardano-serialization-lib-asmjs": "^12.0.0-beta.2", "@fontsource/poppins": "^5.0.14", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index 21be7bb42..f45cf9865 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -29,7 +29,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.2", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "0.7.0-beta-30", + "@intersect.mbo/pdf-ui": "0.7.0-beta-31", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", From 875ba3507a7cbfe05ec82e54a42adb81b602725d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 21:03:49 +0000 Subject: [PATCH 49/75] chore: update @intersect.mbo/govtool-outcomes-pillar-ui to v1.4.3 --- govtool/frontend/package-lock.json | 8 ++++---- govtool/frontend/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index e67501fbd..de3686a93 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -13,7 +13,7 @@ "@emotion/styled": "^11.11.0", "@emurgo/cardano-serialization-lib-asmjs": "^14.1.1", "@hookform/resolvers": "^3.3.1", - "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.2", + "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.3", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", "@intersect.mbo/pdf-ui": "0.7.0-beta-31", "@mui/icons-material": "^5.14.3", @@ -3390,9 +3390,9 @@ } }, "node_modules/@intersect.mbo/govtool-outcomes-pillar-ui": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@intersect.mbo/govtool-outcomes-pillar-ui/-/govtool-outcomes-pillar-ui-1.4.2.tgz", - "integrity": "sha512-NpoRLzNFvmuojsOX6ZknWVjmTu2gnTCf8fzP2yjcnOQA+2YPR94NMIszYT8mHfYuRd4M0+Cvt0ssl37CqQdf+w==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@intersect.mbo/govtool-outcomes-pillar-ui/-/govtool-outcomes-pillar-ui-1.4.3.tgz", + "integrity": "sha512-WPdTV30joLgaLGSiezvHLrzAJSOlUAgtQ4Ln4thhXKpjGQlBrLroGGn1uG5pKEaWxTtz5KVjdbFpMkSXB26bdA==", "license": "ISC", "dependencies": { "@fontsource/poppins": "^5.0.14", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index f45cf9865..3282611c1 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -27,7 +27,7 @@ "@emotion/styled": "^11.11.0", "@emurgo/cardano-serialization-lib-asmjs": "^14.1.1", "@hookform/resolvers": "^3.3.1", - "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.2", + "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.3", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", "@intersect.mbo/pdf-ui": "0.7.0-beta-31", "@mui/icons-material": "^5.14.3", From 9e58b5949e4493bafe10be91a1ab89e1d57e8503 Mon Sep 17 00:00:00 2001 From: Ciabas Date: Thu, 29 May 2025 09:40:50 +0200 Subject: [PATCH 50/75] cache --- govtool/backend/app/Main.hs | 2 ++ govtool/backend/src/VVA/API.hs | 2 +- govtool/backend/src/VVA/API/Types.hs | 2 +- govtool/backend/src/VVA/Types.hs | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/govtool/backend/app/Main.hs b/govtool/backend/app/Main.hs index c2d3ca711..d82821424 100644 --- a/govtool/backend/app/Main.hs +++ b/govtool/backend/app/Main.hs @@ -125,6 +125,7 @@ startApp vvaConfig sentryService = do networkInfoCache <- newCache networkTotalStakeCache <- newCache dRepVotingPowerListCache <- newCache + accountInfoCache <- newCache return $ CacheEnv { proposalListCache , getProposalCache @@ -139,6 +140,7 @@ startApp vvaConfig sentryService = do , networkInfoCache , networkTotalStakeCache , dRepVotingPowerListCache + , accountInfoCache } let connectionString = encodeUtf8 (dbSyncConnectionString $ getter vvaConfig) diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs index 79eb491d6..f8eaaa224 100644 --- a/govtool/backend/src/VVA/API.hs +++ b/govtool/backend/src/VVA/API.hs @@ -533,7 +533,7 @@ getNetworkMetrics = do getAccountInfo :: App m => HexText -> m GetAccountInfoResponse getAccountInfo (unHexText -> stakeKey) = do - -- CacheEnv {accountInfoCache} <- asks vvaCache + CacheEnv {accountInfoCache} <- asks vvaCache Types.AccountInfo {..} <- Account.accountInfo stakeKey return $ GetAccountInfoResponse { getAccountInfoResponseId = accountInfoId diff --git a/govtool/backend/src/VVA/API/Types.hs b/govtool/backend/src/VVA/API/Types.hs index 5c0337191..dac0a9e0d 100644 --- a/govtool/backend/src/VVA/API/Types.hs +++ b/govtool/backend/src/VVA/API/Types.hs @@ -1046,7 +1046,7 @@ exampleGetAccountInfoResponse :: Text exampleGetAccountInfoResponse = "{\"stakeKey\": \"stake1u9\"," <> " \"id\": \"1\"," - <> "\"view\": \"stake_test1uzapf83wydusjln97rqr7fen6vgrz5087yqdxm0akqdqkgstjz8g4\"," + <> "\"view\": \"stake_test1uzapf83wydusjln97rqr7fen6vgrz5087yqdxm0akqdqkgstj2345\"," <> "\"isRegistered\": false," <> "\"isScriptBased\": false}" instance ToSchema GetAccountInfoResponse where diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs index ffe165d93..2d461d6dc 100644 --- a/govtool/backend/src/VVA/Types.hs +++ b/govtool/backend/src/VVA/Types.hs @@ -260,6 +260,7 @@ data CacheEnv , networkInfoCache :: Cache.Cache () NetworkInfo , networkTotalStakeCache :: Cache.Cache () NetworkTotalStake , dRepVotingPowerListCache :: Cache.Cache Text [DRepVotingPowerList] + , accountInfoCache :: Cache.Cache Text AccountInfo } data NetworkInfo From 592019c035a791ae97da871d0f452d9458cae325 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 29 May 2025 12:36:37 +0000 Subject: [PATCH 51/75] chore: update @intersect.mbo/pdf-ui to 0.7.0-beta-32 --- govtool/frontend/package-lock.json | 8 ++++---- govtool/frontend/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index de3686a93..9496c4e92 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -15,7 +15,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.3", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "0.7.0-beta-31", + "@intersect.mbo/pdf-ui": "0.7.0-beta-32", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -3424,9 +3424,9 @@ "license": "ISC" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "0.7.0-beta-31", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-31.tgz", - "integrity": "sha512-fzPbL3kBB4k7IthkDzSWKrntcTC6261kGcIqilCReRYxHJvTnXJpcoKTGkJ7Q7C8Gd+IWI2/nYqYHBkb5O914w==", + "version": "0.7.0-beta-32", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-32.tgz", + "integrity": "sha512-9n4r39UTasny4ON6qXYELMhSMLQGcsZDiU+wu2Ri6CW0S1hReFy/w3I+CKPIWtqVkqVN81DJ2HjNf1Ox98fjOg==", "dependencies": { "@emurgo/cardano-serialization-lib-asmjs": "^12.0.0-beta.2", "@fontsource/poppins": "^5.0.14", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index 3282611c1..dac3cb215 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -29,7 +29,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.3", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "0.7.0-beta-31", + "@intersect.mbo/pdf-ui": "0.7.0-beta-32", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", From 752cd26fffb67d0bc5298df1d14e87082f2e689d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Thu, 29 May 2025 16:54:22 +0200 Subject: [PATCH 52/75] Revert "Added Sentiment Feedback Option to Feedback Modal" This reverts commit 1a0ff7e79a99dec2bf595b4bc79bb4bd8d2b4e58. --- .../frontend/src/context/usersnapContext.tsx | 36 +---------------- govtool/frontend/src/i18n/locales/en.json | 39 +++++++------------ .../tests/10-user-snap/userSnap.spec.ts | 25 +----------- 3 files changed, 17 insertions(+), 83 deletions(-) diff --git a/govtool/frontend/src/context/usersnapContext.tsx b/govtool/frontend/src/context/usersnapContext.tsx index 6e55a128a..0100e443b 100644 --- a/govtool/frontend/src/context/usersnapContext.tsx +++ b/govtool/frontend/src/context/usersnapContext.tsx @@ -79,39 +79,7 @@ export const UsersnapProvider = ({ if (API_KEY) { try { const api = await loadSpace(API_KEY); - api.init({ - ...initParams, - customFields: { - sentiment_score: { - type: 'rating', - label: t("feedback.sentimentScore"), - required: true, - options: [1, 2, 3, 4, 5] - }, - additional_notes: { - type: 'textarea', - label: t("feedback.additionalNotes"), - required: false - } - }, - feedbackTypes: [ - { - id: 'bug', - label: t("feedback.reportBug"), - description: t("feedback.reportBugDescription") - }, - { - id: 'idea', - label: t("feedback.suggestIdea"), - description: t("feedback.suggestIdeaDescription") - }, - { - id: 'sentiment', - label: t("feedback.sentimentFeedback"), - description: t("feedback.sentimentFeedbackDescription") - } - ] - }); + api.init(initParams); setUsersnapApi(api); } catch (error) { console.error(error); @@ -132,4 +100,4 @@ export const UsersnapProvider = ({ export function useUsersnapApi() { return useContext(UsersnapContext); -} \ No newline at end of file +} diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index f9538f9a4..9e259798d 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -109,8 +109,8 @@ "noDelegationDescription": "Find a DRep to vote on your behalf.", "noDelegationActionButton": "View DRep Directory", "dRepDelegationTitle": "Your Voting Power of ₳{{ada}}\nis Delegated to:", - "noConfidenceDelegationTitle": "You have delegated your Voting Power ₳{{ada}}\nto \"No Confidence\"", - "abstainDelegationTitle": "You have delegated your Voting Power ₳{{ada}}\nto \"Abstain\"", + "noConfidenceDelegationTitle": "You have delegated your Voting Power ₳{{ada}}\nto “No Confidence”", + "abstainDelegationTitle": "You have delegated your Voting Power ₳{{ada}}\nto “Abstain”", "abstainDescription": "You have selected to apply your Voting Power to Abstain on every vote.", "noDescription": "You have selected to apply your Voting Power to No Confidence on every vote.", "inProgress": { @@ -283,8 +283,8 @@ "abstainCardDefaultTitle": "Abstain from Every Vote", "automatedVotingOptions": "Automated Voting Options", "editBtn": "Edit DRep data", - "delegatedToAbstainTitle": "You have delegated ₳{{ada}} to \"Abstain\"", - "delegatedToNoConfidenceTitle": "You have delegated ₳{{ada}} to \"No Confidence\"", + "delegatedToAbstainTitle": "You have delegated ₳{{ada}} to “Abstain”", + "delegatedToNoConfidenceTitle": "You have delegated ₳{{ada}} to “No Confidence”", "delegatedToAbstainDescription": "You have selected to apply your Voting Power to Abstain on every vote.", "delegatedToNoConfidenceDescription": "You have selected to apply your Voting Power to No Confidence on every vote.", "delegationOptions": "Delegation Options", @@ -429,7 +429,7 @@ "chooseHowToVote": "Choose how you want to vote:", "contextAboutYourVote": "Context about your vote", "dataMissing": "Data Missing", - "dataMissingTooltipExplanation": "Please click \"View Details\" for more information.", + "dataMissingTooltipExplanation": "Please click “View Details” for more information.", "details": "Governance Details:", "expiresDateWithEpoch": "Expires: <0>{{date}} <1>(Epoch {{epoch}})", "expiryDate": "Expiry date:", @@ -656,7 +656,7 @@ }, "pendingValidation": { "title": "GovTool Is Checking Your Data", - "message": "GovTool will read the URL that you supplied and make a check to see if it's identical with the information that you entered on the form." + "message": "GovTool will read the URL that you supplied and make a check to see if it’s identical with the information that you entered on the form." } }, "dRepData": { @@ -694,7 +694,7 @@ "description": "Looks like you have already successfully completed your registration and you currently are a DRep.\n\nYou can view your details in the DRep Directory.", "viewDetails": "View your DRep details" }, - "becomeADrep": "Become a DRep", + "becomeADRep": "Become a DRep", "descriptionStepTwo": "By clicking register you create your DRep ID within your wallet and become a DRep.\n\nOnce the registration has completed your DRep ID will be shown on your dashboard. You will be able to share your DRep ID so that other ada holders can delegate their voting power to you.", "headingStepTwo": "Confirm DRep registration", "register": "Register", @@ -721,7 +721,7 @@ } }, "retirement": { - "notADrep": { + "notADRep": { "title": "You are not a DRep", "description": "Looks like you cannot retire, because currently you are not a DRep." }, @@ -769,7 +769,7 @@ }, "noConfidence": { "heading": "No confidence", - "paragraphOne": "If you don't have trust in the current constitutional committee you signal 'No-confidence'. By voting 'No' means you don't want governance actions to be ratified." + "paragraphOne": "If you don’t have trust in the current constitutional committee you signal ‘No-confidence’. By voting ‘No’ means you don’t want governance actions to be ratified." }, "todRep": { "heading": "Delegation to DRep", @@ -782,7 +782,7 @@ }, "expiryDate": { "heading": "Expiry Date", - "paragraphOne": "The date when the governance action will expiry if it doesn't reach ratification thresholds.", + "paragraphOne": "The date when the governance action will expiry if it doesn’t reach ratification thresholds.", "paragraphTwo": "IMPORTANT: If the governance action is ratified before the expiry date it will be considered ratified and it will not be available to vote on afterwards." }, "submissionDate": { @@ -796,7 +796,7 @@ } }, "wallet": { - "cantSeeWalletQuestion": "Can't see your wallet? Check what wallets are currently compatible with GovTool ", + "cantSeeWalletQuestion": "Can’t see your wallet? Check what wallets are currently compatible with GovTool ", "chooseWallet": "Choose the wallet you want to connect with:", "connect": "Connect", "connectWallet": "Connect Wallet", @@ -833,7 +833,7 @@ }, "intersectWebsite": { "title": "Intersect website", - "description": "Intersect is a member-based organization for the Cardano ecosystem — putting the community at the center of Cardano's development", + "description": "Intersect is a member-based organization for the Cardano ecosystem — putting the community at the center of Cardano’s development", "link": "Intersect website" } }, @@ -855,18 +855,7 @@ "cip129DrepId": "(CIP-129) DRep ID", "cip105DRepId": "Legacy DRep ID (CIP-105)", "email": "Email", - "feedback": { - "title": "Feedback", - "reportBug": "Report a Bug", - "suggestIdea": "Suggest a New Idea", - "sentimentFeedback": "Sentiment Feedback", - "sentimentScore": "How would you rate your experience?", - "additionalNotes": "Additional Notes", - "submit": "Submit Feedback", - "reportBugDescription": "Something is not working as expected", - "suggestIdeaDescription": "Share your ideas for improvement", - "sentimentFeedbackDescription": "Rate your experience and provide feedback" - }, + "feedback": "Feedback", "filter": "Filter", "goBack": "Go back", "goToMainnet": "Go to Mainnet", @@ -898,4 +887,4 @@ "viewDetails": "View details", "votingPower": "Voting power", "yourself": "Yourself" -} \ No newline at end of file +} diff --git a/tests/govtool-frontend/playwright/tests/10-user-snap/userSnap.spec.ts b/tests/govtool-frontend/playwright/tests/10-user-snap/userSnap.spec.ts index 0b748c171..ab8e4c1be 100644 --- a/tests/govtool-frontend/playwright/tests/10-user-snap/userSnap.spec.ts +++ b/tests/govtool-frontend/playwright/tests/10-user-snap/userSnap.spec.ts @@ -187,27 +187,4 @@ test.describe("Submit Usersnap", () => { await expect(page.getByText("Thank you!")).toBeVisible(); }); - - test("10F. Should submit sentiment feedback", async ({ page }) => { - // Intercept Usersnap submit API - await interceptUsersnap(page); - await interceptBucket(page); - - await page - .getByRole("button", { name: "Share Your Experience" }) - .click(); - - // Select a rating - await page.getByLabel("How would you rate your experience?").click(); - await page.getByRole("button", { name: "4" }).click(); - - // Add additional notes - await page - .getByPlaceholder("Additional Notes") - .fill(faker.lorem.paragraph(2)); - - await page.getByRole("button", { name: "Submit Feedback" }).click(); - - await expect(page.getByText("Thank you!")).toBeVisible(); - }); -}); \ No newline at end of file +}); From 7f83827ed2ce575d29a2c46f2217f9fe5789614e Mon Sep 17 00:00:00 2001 From: Niraj Date: Thu, 29 May 2025 23:08:47 +0545 Subject: [PATCH 53/75] fix: add remaining missing test ids of budget submission form --- .../pages/budgetDiscussionSubmissionPage.ts | 30 ++++++++----------- .../playwright/lib/pages/outcomesPage.ts | 1 - ...oposalBudgetSubmission.loggedin.pb.spec.ts | 8 ++--- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts index 5fb08c603..96cc46d98 100644 --- a/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/budgetDiscussionSubmissionPage.ts @@ -83,9 +83,9 @@ export default class BudgetDiscussionSubmissionPage { readonly suplimentaryEndorsementInput = this.page.getByTestId( "supplementary-endorsement-input" ); - readonly productRoadmapDescriptionInput = this.page.getByLabel( - "Please explain how your" - ); // BUG missing test Ids + readonly productRoadmapDescriptionInput = this.page.getByTestId( + "proposal-roadmap-description-input" + ); // proposal-details readonly proposalNameInput = this.page.getByTestId("proposal-name-input"); @@ -123,12 +123,10 @@ export default class BudgetDiscussionSubmissionPage { readonly venderDetailsInput = this.page.getByLabel("Please provide further"); //BUG missing test Ids // select - readonly proposalCommittee = this.page - .getByLabel("Is this proposal being") - .first(); // BUG incorrect position of testId - readonly countryOfIncorporationBtn = this.page - .getByLabel("Country of Incorporation *") - .first(); // BUG incorrect position of testId + readonly proposalCommittee = this.page.getByTestId("proposal-committee"); + readonly countryOfIncorporationBtn = this.page.getByTestId( + "country-of-incorporation" + ); readonly publicChampionSelect = this.page.getByTestId( "proposal-public-champion" ); @@ -264,8 +262,8 @@ export default class BudgetDiscussionSubmissionPage { ) { await this.proposalCommittee.click(); await this.page - .getByRole("option", { name: proposalOwnership.companyType }) - .click(); //BUG missing testId + .getByTestId(`${proposalOwnership.companyType.toLowerCase()}-submission`) + .click(); await this.contactDetailsInput.fill(proposalOwnership.contactDetails); @@ -787,13 +785,9 @@ export default class BudgetDiscussionSubmissionPage { // further information for (let i = 0; i < proposalInformations.furtherInformation.length; i++) { - //BUG missing testId - await expect( - this.currentPage.getByRole("link", { - name: proposalInformations.furtherInformation[i].prop_link_text, - exact: true, - }) - ).toBeVisible(); + await expect(this.currentPage.getByTestId(`link-${i}-label`)).toHaveText( + proposalInformations.furtherInformation[i].prop_link_text + ); } // administration and auditing diff --git a/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts b/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts index 9ac9a9e06..bed26b0aa 100644 --- a/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts @@ -437,7 +437,6 @@ export default class OutComesPage { "**/governance-actions?search=&filters=&sort=**" ); - await this.goto(); await actionsResponsePromise; diff --git a/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts b/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts index d647175f9..c092f05d5 100644 --- a/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts +++ b/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts @@ -72,8 +72,8 @@ test.describe("Budget proposal 01 wallet", () => { // company type field await budgetProposalSubmissionPage.proposalCommittee.click(); await budgetProposalSubmissionPage.currentPage - .getByRole("option", { name: CompanyEnum.Company }) - .click(); //BUG missing testId + .getByTestId("company-submission") + .click(); await expect( budgetProposalSubmissionPage.companyNameInput @@ -88,8 +88,8 @@ test.describe("Budget proposal 01 wallet", () => { // group type field await budgetProposalSubmissionPage.proposalCommittee.click(); await budgetProposalSubmissionPage.currentPage - .getByRole("option", { name: CompanyEnum.Group }) - .click(); //BUG missing testId + .getByTestId("group-submission") + .click(); await expect(budgetProposalSubmissionPage.groupNameInput).toBeVisible(); await expect(budgetProposalSubmissionPage.groupTypeInput).toBeVisible(); await expect( From ea68d940d940b0d9df9702905013072f69d05206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Thu, 29 May 2025 12:12:40 +0200 Subject: [PATCH 54/75] fix: overlapping banners over app content --- govtool/frontend/src/App.tsx | 5 ++--- .../components/organisms/DashboardTopNav.tsx | 11 ++++++++--- .../src/components/organisms/Drawer.tsx | 5 ++--- .../MaintenanceEndingBanner.tsx | 3 +++ .../src/components/organisms/TopBanners.tsx | 19 ++++++------------- 5 files changed, 21 insertions(+), 22 deletions(-) diff --git a/govtool/frontend/src/App.tsx b/govtool/frontend/src/App.tsx index 3ef7a5c0a..c4903b4d8 100644 --- a/govtool/frontend/src/App.tsx +++ b/govtool/frontend/src/App.tsx @@ -93,9 +93,8 @@ export default () => { }, [checkTheWalletIsActive]); return ( - <> + - } /> } /> @@ -226,6 +225,6 @@ export default () => { {modals[modal.type].component!} )} - + ); }; diff --git a/govtool/frontend/src/components/organisms/DashboardTopNav.tsx b/govtool/frontend/src/components/organisms/DashboardTopNav.tsx index 45d51d8d3..ef0d91dd7 100644 --- a/govtool/frontend/src/components/organisms/DashboardTopNav.tsx +++ b/govtool/frontend/src/components/organisms/DashboardTopNav.tsx @@ -8,7 +8,10 @@ import { useGetVoterInfo, useScreenDimension, } from "@hooks"; -import { DashboardDrawerMobile } from "@organisms"; +import { + DashboardDrawerMobile, + useMaintenanceEndingBannerContext, +} from "@organisms"; import { useCardano } from "@context"; type DashboardTopNavProps = { @@ -28,6 +31,8 @@ export const DashboardTopNav = ({ const { isEnableLoading } = useCardano(); const { voter } = useGetVoterInfo(); const { dRepVotingPower } = useGetDRepVotingPowerQuery(voter); + const { height: maintenanceEndingBannerHeight } = + useMaintenanceEndingBannerContext(); const openDrawer = () => { setIsDrawerOpen(true); @@ -53,7 +58,7 @@ export const DashboardTopNav = ({ alignItems: "center", backdropFilter: "blur(10px)", backgroundColor: - windowScroll > POSITION_TO_BLUR + windowScroll > POSITION_TO_BLUR + maintenanceEndingBannerHeight ? "rgba(256, 256, 256, 0.7)" : isMobile ? "#FBFBFF59" @@ -65,7 +70,7 @@ export const DashboardTopNav = ({ minHeight: isMobile ? 36 : 48, px: isMobile ? 2 : 5, py: 3, - top: 0, + top: maintenanceEndingBannerHeight || 0, width: "fill-available", zIndex: 100, }} diff --git a/govtool/frontend/src/components/organisms/Drawer.tsx b/govtool/frontend/src/components/organisms/Drawer.tsx index 5797acc7b..d54c729a0 100644 --- a/govtool/frontend/src/components/organisms/Drawer.tsx +++ b/govtool/frontend/src/components/organisms/Drawer.tsx @@ -26,11 +26,10 @@ export const Drawer = () => { flexDirection: "column", height: "100vh", position: "sticky", - top: maintenanceEndingBannerHeight, width: `${DRAWER_WIDTH}px`, - + top: maintenanceEndingBannerHeight || 0, overflowY: "auto", - maxHeight: "100vh", + maxHeight: `calc(100vh - ${maintenanceEndingBannerHeight || 0}px)`, }} > { width: "100%", overflow: "hidden", transition: "all 0.3s ease-in-out", + position: "sticky", + top: 0, + zIndex: 1200, }} > {/* Banner Header */} diff --git a/govtool/frontend/src/components/organisms/TopBanners.tsx b/govtool/frontend/src/components/organisms/TopBanners.tsx index df04c01db..ad4a878f8 100644 --- a/govtool/frontend/src/components/organisms/TopBanners.tsx +++ b/govtool/frontend/src/components/organisms/TopBanners.tsx @@ -1,10 +1,11 @@ +import { PropsWithChildren } from "react"; import { Box, Link, Typography } from "@mui/material"; import { Trans, useTranslation } from "react-i18next"; import { useAppContext } from "@/context"; import { LINKS } from "@/consts/links"; import { MaintenanceEndingBanner } from "./MaintenanceEndingBanner"; -export const TopBanners = () => { +export const TopBanners = ({ children }: PropsWithChildren) => { const { isMainnet, networkName, isInBootstrapPhase, isAppInitializing } = useAppContext(); const { t } = useTranslation(); @@ -14,7 +15,7 @@ export const TopBanners = () => { } return ( - <> + {/* NETWORK BANNER */} {!isMainnet && ( @@ -48,16 +49,7 @@ export const TopBanners = () => { {/* GOVTOOL MAINTENANCE ENDING SOON BANNER */} - - - + {/* BOOTSTRAPPING BANNER */} @@ -89,6 +81,7 @@ export const TopBanners = () => { )} - + {children} + ); }; From 1fa8aba1bb5c26619a0ae0e910da159f392acadf Mon Sep 17 00:00:00 2001 From: Ciabas Date: Fri, 30 May 2025 09:52:24 +0200 Subject: [PATCH 55/75] fix: update the content of the red banner displayed on GovTool --- .../MaintenanceEndingBanner.tsx | 15 +++++++++++++-- govtool/frontend/src/i18n/locales/en.json | 9 +++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx b/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx index 7921a66a4..669a98820 100644 --- a/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx +++ b/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx @@ -1,4 +1,4 @@ -import { Box, Typography, IconButton } from "@mui/material"; +import { Box, Typography, IconButton, Link } from "@mui/material"; import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; import { Trans, useTranslation } from "react-i18next"; @@ -101,7 +101,18 @@ export const MaintenanceEndingBanner = () => { /> - {t("system.maintenanceEnding.description3")} + {t("system.maintenanceEnding.description3")}{" "} + + {t("system.maintenanceEnding.linkText")} + diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index 9e259798d..b25cf774d 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -755,10 +755,11 @@ "title": "This tool is connected to {{networkName}}", "bootstrappingWarning": "Govtool is in the Bootstrapping phase. Some features are not available. Learn more", "maintenanceEnding": { - "title": "⚠️ GovTool Maintenance Ending Soon", - "description1": "GovTool has not been included in the 2025 Cardano budget.", - "description2": "Unless alternative support is secured, <0>maintenance will end in June 2025.", - "description3": "We remain committed to transparency and will keep you updated." + "title": "⚠️ Funding for GovTool is at risk", + "description1": "GovTool was not included in the current Cardano budget.", + "description2": "Without new support, active development and <0>maintenance will end in June 2025.", + "description3": "Learn what this means and what’s next:", + "linkText": "The future of GovTool" } }, "tooltips": { From f609a67dea46e9cccc94eea52c5a6d02b3485390 Mon Sep 17 00:00:00 2001 From: Niraj Date: Fri, 30 May 2025 20:05:42 +0545 Subject: [PATCH 56/75] chore: split out generate-address from crypto --- .../playwright/lib/helpers/crypto.ts | 24 +++++++------- .../playwright/lib/helpers/shellyWallet.ts | 32 +++++++++++++++++++ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/helpers/crypto.ts b/tests/govtool-frontend/playwright/lib/helpers/crypto.ts index 62442ac9f..13bcd9512 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/crypto.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/crypto.ts @@ -2,7 +2,12 @@ import environments from "../constants/environments"; import { ed25519 as ed } from "@noble/curves/ed25519"; import { bech32 } from "bech32"; import * as blake from "blakejs"; -import { rewardAddressBech32, rewardAddressRawBytes } from "./shellyWallet"; +import { + addressBech32, + addressRawBytes, + rewardAddressBech32, + rewardAddressRawBytes, +} from "./shellyWallet"; const KEY_HASH_LENGTH = 28; const ADDR_LENGTH = KEY_HASH_LENGTH * 2 + 1; @@ -103,20 +108,15 @@ export class ShelleyWallet { } addressBech32(networkId: number): string { - const prefix = networkId == 0 ? "addr_test" : "addr"; - return bech32.encode( - prefix, - bech32.toWords(Buffer.from(this.addressRawBytes(networkId))), - 200 - ); + const stakePkh = Buffer.from(this.stakeKey.pkh).toString("hex"); + const paymentPkh = Buffer.from(this.paymentKey.pkh).toString("hex"); + return addressBech32(networkId, paymentPkh, stakePkh); } addressRawBytes(networkId) { - const concatenatedArray1 = new Uint8Array(ADDR_LENGTH); - concatenatedArray1[0] = networkId; - concatenatedArray1.set(this.paymentKey.pkh, 1); - concatenatedArray1.set(this.stakeKey.pkh, KEY_HASH_LENGTH + 1); - return concatenatedArray1; + const stakePkh = Buffer.from(this.stakeKey.pkh).toString("hex"); + const paymentPkh = Buffer.from(this.paymentKey.pkh).toString("hex"); + return addressRawBytes(networkId, paymentPkh, stakePkh); } rewardAddressRawBytes(network: number) { diff --git a/tests/govtool-frontend/playwright/lib/helpers/shellyWallet.ts b/tests/govtool-frontend/playwright/lib/helpers/shellyWallet.ts index aa8001906..8c2e57082 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/shellyWallet.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/shellyWallet.ts @@ -2,7 +2,9 @@ import { bech32 } from "bech32"; import { blake2bHex } from "blakejs"; import convertBufferToHex from "./convertBufferToHex"; import { ShelleyWallet } from "./crypto"; + const KEY_HASH_LENGTH = 28; +const ADDR_LENGTH = KEY_HASH_LENGTH * 2 + 1; export default function extractDRepFromWallet(wallet: ShelleyWallet) { const dRepPubKey = convertBufferToHex(wallet.dRepKey.public); @@ -36,6 +38,36 @@ export function rewardAddressBech32( ); } +export function addressBech32( + networkId: number, + paymentPkh: string, + stakePkh: string +): string { + const prefix = networkId == 0 ? "addr_test" : "addr"; + return bech32.encode( + prefix, + bech32.toWords( + Buffer.from(addressRawBytes(networkId, paymentPkh, stakePkh)) + ), + 200 + ); +} + +export function addressRawBytes( + networkId: number, + paymentPkh: string, + stakePkh: string +) { + const concatenatedArray1 = new Uint8Array(ADDR_LENGTH); + concatenatedArray1[0] = networkId; + concatenatedArray1.set(Uint8Array.from(Buffer.from(paymentPkh, "hex")), 1); + concatenatedArray1.set( + Uint8Array.from(Buffer.from(stakePkh, "hex")), + KEY_HASH_LENGTH + 1 + ); + return concatenatedArray1; +} + export async function generateWallets(num: number) { return await Promise.all( Array.from({ length: num }, () => From e0f016197e5d9c093d3aee172e6fac58259bce78 Mon Sep 17 00:00:00 2001 From: Niraj Date: Fri, 30 May 2025 20:08:05 +0545 Subject: [PATCH 57/75] chore: update stake and address on propsal wallet setup --- .../playwright/tests/proposal.setup.ts | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/tests/govtool-frontend/playwright/tests/proposal.setup.ts b/tests/govtool-frontend/playwright/tests/proposal.setup.ts index 5087fd136..36ec41f0e 100644 --- a/tests/govtool-frontend/playwright/tests/proposal.setup.ts +++ b/tests/govtool-frontend/playwright/tests/proposal.setup.ts @@ -1,13 +1,14 @@ import environments from "@constants/environments"; import { setAllureEpic, setAllureStory } from "@helpers/allure"; import { skipIfBalanceIsInsufficient, skipIfMainnet } from "@helpers/cardano"; -import { generateWallets } from "@helpers/shellyWallet"; +import { addressBech32, generateWallets } from "@helpers/shellyWallet"; import { pollTransaction } from "@helpers/transaction"; import { test as setup } from "@fixtures/walletExtension"; import kuberService from "@services/kuberService"; import walletManager from "lib/walletManager"; import { functionWaitedAssert } from "@helpers/waitedLoop"; import { getWalletConfigForFaucet } from "@helpers/index"; +import { createKeyFromPrivateKeyHex } from "@helpers/crypto"; const PROPOSAL_WALLETS_COUNT = environments.isScheduled ? 1 : 5; @@ -33,20 +34,38 @@ setup.beforeEach(async () => { }); setup("Setup temporary proposal wallets", async () => { - setup.setTimeout(2 * environments.txTimeOut); + setup.setTimeout(environments.txTimeOut); const proposalWallets = await generateWallets(PROPOSAL_WALLETS_COUNT); - - // initialize wallets - const initializeRes = await kuberService.initializeWallets( - [...proposalWallets], - getWalletConfigForFaucet().address, - getWalletConfigForFaucet().payment.private + const stakeKeys = await createKeyFromPrivateKeyHex( + environments.faucet.stake.private || "" ); - await pollTransaction(initializeRes.txId, initializeRes.lockInfo); + const { pkh: stakePkh, public: stakePublic } = stakeKeys.json(); + + const enrichedProposalWallets = proposalWallets.map((wallet) => { + const stake = { + pkh: stakePkh, + private: environments.faucet.stake.private, + public: stakePublic, + }; + + const walletAddress = addressBech32( + environments.networkId, + wallet.payment.pkh, + stakePkh + ); + + return { + ...wallet, + address: walletAddress, + stake, + }; + }); + + proposalWallets.splice(0, proposalWallets.length, ...enrichedProposalWallets); const amountOutputs = proposalWallets.map((wallet) => { - return { address: wallet.address, value: govActionDeposit }; + return { address: wallet.address, value: govActionDeposit + 22000000 }; }); const transferRes = await kuberService.multipleTransferADA( amountOutputs, From fc139c5931b33ec813da5154df86363929bbe2e0 Mon Sep 17 00:00:00 2001 From: Niraj Date: Fri, 30 May 2025 20:08:30 +0545 Subject: [PATCH 58/75] refactor: remove redundant stake key creation in proposal submission tests --- .../proposalSubmission.ga.spec.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts index dcc0fbaa3..a6a266581 100644 --- a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts +++ b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts @@ -38,14 +38,6 @@ Object.values(ProposalType).forEach((proposalType, index) => { const wallet = await walletManager.popWallet("proposalSubmission"); - const stakeKeys = await createKeyFromPrivateKeyHex( - environments.faucet.stake.private || "" - ); - const { pkh: stakePkh, public: stakePublic } = stakeKeys.json(); - wallet.stake.pkh = stakePkh; - wallet.stake.private = getWalletConfigForFaucet().stake.private; - wallet.stake.public = stakePublic; - await logWalletDetails(wallet.address); const tempUserAuth = await createTempUserAuth(page, wallet); @@ -73,7 +65,10 @@ Object.values(ProposalType).forEach((proposalType, index) => { await proposalSubmissionPage.proposalCreateBtn.click(); await proposalDiscussionPage.continueBtn.click(); - const rewardAddress = rewardAddressBech32(environments.networkId, stakePkh); + const rewardAddress = rewardAddressBech32( + environments.networkId, + wallet.stake.pkh + ); await proposalSubmissionPage.createProposal(rewardAddress, proposalType); From 7a9f768b227c10808d5e0593a33e48550a87fce2 Mon Sep 17 00:00:00 2001 From: Niraj Date: Fri, 30 May 2025 20:09:55 +0545 Subject: [PATCH 59/75] fix: Check if the input field is set; otherwise, skip the process on auth. --- .../playwright/lib/helpers/auth.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/helpers/auth.ts b/tests/govtool-frontend/playwright/lib/helpers/auth.ts index 980cfa4f6..44ef71661 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/auth.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/auth.ts @@ -2,7 +2,7 @@ import { importWallet } from "@fixtures/importWallet"; import { valid as mockValid } from "@mock/index"; import LoginPage from "@pages/loginPage"; import ProposalDiscussionPage from "@pages/proposalDiscussionPage"; -import { BrowserContext, Page } from "@playwright/test"; +import { BrowserContext, expect, Page } from "@playwright/test"; import { ProposalType, StaticWallet } from "@types"; import { ShelleyWallet } from "./crypto"; import convertBufferToHex from "./convertBufferToHex"; @@ -57,9 +57,16 @@ export async function createAuthWithUserName({ const proposalDiscussionPage = new ProposalDiscussionPage(page); await proposalDiscussionPage.goto(); - await proposalDiscussionPage.verifyIdentityBtn.click({ timeout: 15_000 }); - - await proposalDiscussionPage.setUsername(mockValid.username()); + await proposalDiscussionPage.verifyIdentityBtn.click({ timeout: 60_000 }); + try { + await expect(page.getByTestId("username-input")).toBeVisible({ + timeout: 10_000, + }); + await proposalDiscussionPage.setUsername(mockValid.username()); + } catch (error) { + // Ignore error if username is already set + console.log("Username is already set"); + } await context.storageState({ path: auth }); } From 8e464f327d9b5b51da77a82f0b21d38219a4888c Mon Sep 17 00:00:00 2001 From: Niraj Date: Fri, 30 May 2025 20:33:21 +0545 Subject: [PATCH 60/75] chore: update @cardanoapi/cardano-test-wallet to version 3.3.2 --- tests/govtool-frontend/playwright/package-lock.json | 8 ++++---- tests/govtool-frontend/playwright/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/govtool-frontend/playwright/package-lock.json b/tests/govtool-frontend/playwright/package-lock.json index 9f2a897ee..edbd65f52 100644 --- a/tests/govtool-frontend/playwright/package-lock.json +++ b/tests/govtool-frontend/playwright/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@cardanoapi/cardano-test-wallet": "^3.3.1", + "@cardanoapi/cardano-test-wallet": "^3.3.2", "@faker-js/faker": "^8.4.1", "@noble/curves": "^1.3.0", "@noble/ed25519": "^2.0.0", @@ -43,9 +43,9 @@ } }, "node_modules/@cardanoapi/cardano-test-wallet": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-3.3.1.tgz", - "integrity": "sha512-AOIDoEkVRYanW4O0pflfcJ2K4Pb3cUHf93cz8pJANU3qIZRQXW+ubGVM60s1WodTcJEmUccpxxXZJuuGRBGXCw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-3.3.2.tgz", + "integrity": "sha512-N80hAiw/9SkEQJyx8lYB0FqfnzCcWI+wzjPHgULzjz9C9b92irE0zvV6X1/GgN96OYLV+V1VCzgkJ7A1aGnCvQ==", "license": "MIT" }, "node_modules/@cbor-extract/cbor-extract-darwin-arm64": { diff --git a/tests/govtool-frontend/playwright/package.json b/tests/govtool-frontend/playwright/package.json index b0127afe7..91e185062 100644 --- a/tests/govtool-frontend/playwright/package.json +++ b/tests/govtool-frontend/playwright/package.json @@ -48,7 +48,7 @@ "generate-faucet-wallet": "ts-node ./generate_faucet_wallet.ts" }, "dependencies": { - "@cardanoapi/cardano-test-wallet": "^3.3.1", + "@cardanoapi/cardano-test-wallet": "^3.3.2", "@faker-js/faker": "^8.4.1", "@noble/curves": "^1.3.0", "@noble/ed25519": "^2.0.0", From a40a8a91b18b23eac48687ba2c0703a460fa0faf Mon Sep 17 00:00:00 2001 From: Niraj Date: Mon, 2 Jun 2025 16:28:16 +0545 Subject: [PATCH 61/75] feat: enhance sorting functionality for proposed governance actions --- .../lib/pages/proposalDiscussionPage.ts | 29 +++++++++-- .../govtool-frontend/playwright/lib/types.ts | 21 ++++++++ .../proposalDiscussion.spec.ts | 50 +++++++++++++++---- 3 files changed, 85 insertions(+), 15 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts b/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts index 07da72fda..c2c301c39 100644 --- a/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts @@ -1,5 +1,10 @@ import { expect, Locator, Page } from "@playwright/test"; -import { ProposalCreateRequest, ProposalType, ProposedGovAction } from "@types"; +import { + ProposalCreateRequest, + ProposalDiscussionFilterTypes, + ProposalType, + ProposedGovAction, +} from "@types"; import environments from "lib/constants/environments"; import ProposalDiscussionDetailsPage from "./proposalDiscussionDetailsPage"; import { functionWaitedAssert, waitedLoop } from "@helpers/waitedLoop"; @@ -147,16 +152,30 @@ export default class ProposalDiscussionPage { } async sortAndValidate( - option: "asc" | "desc", + type: ProposalDiscussionFilterTypes, validationFn: (p1: ProposedGovAction, p2: ProposedGovAction) => boolean ) { + const sortMappings = { + "Name A-Z": "&sort[prop_name]=ASC", + "Name Z-A": "&sort[prop_name]=DESC", + "Most comments": "&sort[proposal][prop_comments_number]=DESC", + "Least comments": "&sort[proposal][prop_comments_number]=ASC", + "Most likes": "&sort[proposal][prop_likes]=DESC", + "Least likes": "&sort[proposal][prop_likes]=ASC", + "Most dislikes": "&sort[proposal][prop_dislikes]=DESC", + "Least dislikes": "&sort[proposal][prop_dislikes]=ASC", + Oldest: "&sort[createdAt]=ASC", + Newest: "&sort[createdAt]=DESC", + }; + + const urlParam = sortMappings[type]; + const populateParam = "&populate[0]=proposal_links"; const responsePromise = this.page.waitForResponse((response) => - response - .url() - .includes(`&sort[createdAt]=${option}&populate[0]=proposal_links`) + response.url().includes(`${urlParam}${populateParam}`) ); await this.sortBtn.click(); + await this.page.getByTestId(`${type}-sort-option`).click(); const response = await responsePromise; let proposals: ProposedGovAction[] = (await response.json()).data; diff --git a/tests/govtool-frontend/playwright/lib/types.ts b/tests/govtool-frontend/playwright/lib/types.ts index 5ac7273ca..2ffdac42c 100644 --- a/tests/govtool-frontend/playwright/lib/types.ts +++ b/tests/govtool-frontend/playwright/lib/types.ts @@ -201,8 +201,17 @@ export type ProposedGovAction = { attributes: { gov_action_type_name: string; prop_comments_number: number; + prop_likes: number; + prop_dislikes: number; createdAt: string; updatedAt: string; + content: { + id: string; + attributes: { + proposal_id: string; + prop_name: string; + }; + }; creator: { data: { id: number; @@ -547,3 +556,15 @@ export type BudgetProposalFilterTypes = | "Name Z-A" | "Proposer A-Z" | "Proposer Z-A"; + +export type ProposalDiscussionFilterTypes = + | "Newest" + | "Oldest" + | "Most likes" + | "Least likes" + | "Most dislikes" + | "Least dislikes" + | "Most comments" + | "Least comments" + | "Name A-Z" + | "Name Z-A"; diff --git a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts index cdecc19cc..a895ecfa5 100644 --- a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts +++ b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts @@ -13,7 +13,11 @@ import { functionWaitedAssert } from "@helpers/waitedLoop"; import ProposalDiscussionDetailsPage from "@pages/proposalDiscussionDetailsPage"; import ProposalDiscussionPage from "@pages/proposalDiscussionPage"; import { expect } from "@playwright/test"; -import { ProposalType } from "@types"; +import { + ProposalDiscussionFilterTypes, + ProposalType, + ProposedGovAction, +} from "@types"; const mockProposal = require("../../lib/_mock/proposal.json"); const mockPoll = require("../../lib/_mock/proposalPoll.json"); @@ -65,15 +69,41 @@ test.describe("Filter and sort proposals", () => { }); test("8B_2. Should sort the list of proposed governance actions.", async () => { - await proposalDiscussionPage.sortAndValidate( - "asc", - (p1, p2) => p1.attributes.createdAt <= p2.attributes.createdAt - ); - - await proposalDiscussionPage.sortAndValidate( - "desc", - (p1, p2) => p1.attributes.createdAt >= p2.attributes.createdAt - ); + const sortOptions = { + Oldest: (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.createdAt <= p2.attributes.createdAt, + Newest: (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.createdAt >= p2.attributes.createdAt, + "Most likes": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.prop_likes >= p2.attributes.prop_likes, + "Least likes": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.prop_likes <= p2.attributes.prop_likes, + "Most dislikes": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.prop_dislikes >= p2.attributes.prop_dislikes, + "Least dislikes": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.prop_dislikes <= p2.attributes.prop_dislikes, + "Most comments": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.prop_comments_number >= + p2.attributes.prop_comments_number, + "Least comments": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.prop_comments_number <= + p2.attributes.prop_comments_number, + "Name A-Z": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.content.attributes.prop_name.localeCompare( + p2.attributes.content.attributes.prop_name + ) <= 0, + "Name Z-A": (p1: ProposedGovAction, p2: ProposedGovAction) => + p1.attributes.content.attributes.prop_name.localeCompare( + p2.attributes.content.attributes.prop_name + ) >= 0, + }; + + for (const [sortOption, sortFunction] of Object.entries(sortOptions)) { + await proposalDiscussionPage.sortAndValidate( + sortOption as ProposalDiscussionFilterTypes, + sortFunction + ); + } }); }); From af7a9b110b6ef821b23c1c3877af4ec7cae61ef4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 13:51:33 +0000 Subject: [PATCH 62/75] chore: update @intersect.mbo/pdf-ui to 0.7.0-beta-33 --- govtool/frontend/package-lock.json | 8 ++++---- govtool/frontend/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 9496c4e92..8fb6e4f8b 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -15,7 +15,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.3", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "0.7.0-beta-32", + "@intersect.mbo/pdf-ui": "0.7.0-beta-33", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -3424,9 +3424,9 @@ "license": "ISC" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "0.7.0-beta-32", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-32.tgz", - "integrity": "sha512-9n4r39UTasny4ON6qXYELMhSMLQGcsZDiU+wu2Ri6CW0S1hReFy/w3I+CKPIWtqVkqVN81DJ2HjNf1Ox98fjOg==", + "version": "0.7.0-beta-33", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-33.tgz", + "integrity": "sha512-Jddj4txjkLm7ecrmhPHP2/I7n2lzfgT8mYAMQAPd/PvUQ/9QvXoWTvg7rF0xeh4VmgAiLONv1LKfRE2VJZcz8A==", "dependencies": { "@emurgo/cardano-serialization-lib-asmjs": "^12.0.0-beta.2", "@fontsource/poppins": "^5.0.14", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index dac3cb215..c31b492ae 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -29,7 +29,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.3", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "0.7.0-beta-32", + "@intersect.mbo/pdf-ui": "0.7.0-beta-33", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", From aa41aa19ecd3f6a85b9e2fc37d0d3972df39c114 Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 3 Jun 2025 09:37:37 +0545 Subject: [PATCH 63/75] fix: update response URL filter for vote count in proposal visibility tests --- .../4-proposal-visibility/proposalVisibility.dRep.spec.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts index fd75c0b1d..7e6623005 100644 --- a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts +++ b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts @@ -147,7 +147,11 @@ test.describe("Check vote count", () => { : GovernanceActionType; const responsesPromise = Object.keys(voteWhiteListOption).map((filterKey) => page.waitForResponse((response) => - response.url().includes(`&type[]=${voteWhiteListOption[filterKey]}`) + response + .url() + .includes( + `proposal/list?page=0&pageSize=7&type[]=${voteWhiteListOption[filterKey]}` + ) ) ); From e5ba568984a4df8d29d520aa74b9660c0c5e32ac Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 3 Jun 2025 12:31:11 +0545 Subject: [PATCH 64/75] fix: handle visibility of progress bar during outcome searches --- .../playwright/lib/pages/outcomesPage.ts | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts b/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts index bed26b0aa..e86db03e7 100644 --- a/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts @@ -456,10 +456,15 @@ export default class OutComesPage { async searchOutcomesById(governanceActionId: string) { await this.searchInput.fill(governanceActionId); - await expect( - this.page.getByRole("progressbar").getByRole("img") - ).toBeVisible(); + try { + await expect( + this.page.getByRole("progressbar").getByRole("img") + ).toBeVisible(); + } catch (error) { + // Handle the case where the progress bar is not visible + console.warn("Progress bar not visible, proceeding with search."); + } await functionWaitedAssert( async () => { const idSearchOutcomeCards = await this.getAllOutcomes(); @@ -480,9 +485,14 @@ export default class OutComesPage { async searchOutcomesByTitle(governanceActionTitle: string) { await this.searchInput.fill(governanceActionTitle); - await expect( - this.page.getByRole("progressbar").getByRole("img") - ).toBeVisible(); + try { + await expect( + this.page.getByRole("progressbar").getByRole("img") + ).toBeVisible(); + } catch (error) { + // Handle the case where the progress bar is not visible + console.warn("Progress bar not visible, proceeding with search."); + } await functionWaitedAssert( async () => { From 6c9751c24397c7b7934d124509bb09e054de3758 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 08:05:37 +0000 Subject: [PATCH 65/75] chore: update @intersect.mbo/pdf-ui to 0.7.0-beta-34 --- govtool/frontend/package-lock.json | 8 ++++---- govtool/frontend/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 8fb6e4f8b..47d4b3fae 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -15,7 +15,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.3", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "0.7.0-beta-33", + "@intersect.mbo/pdf-ui": "0.7.0-beta-34", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -3424,9 +3424,9 @@ "license": "ISC" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "0.7.0-beta-33", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-33.tgz", - "integrity": "sha512-Jddj4txjkLm7ecrmhPHP2/I7n2lzfgT8mYAMQAPd/PvUQ/9QvXoWTvg7rF0xeh4VmgAiLONv1LKfRE2VJZcz8A==", + "version": "0.7.0-beta-34", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-34.tgz", + "integrity": "sha512-PC5/wiqj2QH/57edzqor2tOZLNbCtijof8IUCFIKwfaeQ7wkKkEVHEIY1iKs0eK9DYAIEnHWCS3rnpjm9vY9Vg==", "dependencies": { "@emurgo/cardano-serialization-lib-asmjs": "^12.0.0-beta.2", "@fontsource/poppins": "^5.0.14", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index c31b492ae..bdad215a5 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -29,7 +29,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.3", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "0.7.0-beta-33", + "@intersect.mbo/pdf-ui": "0.7.0-beta-34", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", From 15c62a72ad2597814a240607f0437fa605f2d190 Mon Sep 17 00:00:00 2001 From: Ciabas Date: Tue, 3 Jun 2025 09:44:55 +0200 Subject: [PATCH 66/75] fix(#3714): type error on linkReferences when editing dRep page --- CHANGELOG.md | 1 + .../components/organisms/EditDRepInfoSteps/EditDRepForm.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53a5dc973..ad0011279 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ changes. ### Fixed - Fix missing off chain references in DRep details [Issue 3490](https://github.com/IntersectMBO/govtool/issues/3490) +- Fix blank screen and type error on linkReferences when navigating to edit dRep page that has no links [Issue 3714](https://github.com/IntersectMBO/govtool/issues/3714) ### Changed diff --git a/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepForm.tsx b/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepForm.tsx index d758c7398..1efc085e7 100644 --- a/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepForm.tsx +++ b/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepForm.tsx @@ -49,8 +49,8 @@ export const EditDRepForm = ({ qualifications: data?.qualifications ?? "", paymentAddress: data?.paymentAddress ?? "", image: data?.image ?? "", - linkReferences: data.linkReferences ?? [getEmptyReference("Link")], - identityReferences: data.identityReferences ?? [ + linkReferences: data?.linkReferences ?? [getEmptyReference("Link")], + identityReferences: data?.identityReferences ?? [ getEmptyReference("Identity"), ], }); From 04aa7d6a80ea8b60409b5a6f5b833aec9e83b6ac Mon Sep 17 00:00:00 2001 From: Niraj Date: Thu, 29 May 2025 15:32:11 +0545 Subject: [PATCH 67/75] fix: correct abstain votes reference in outcome details test --- .../govtool-frontend/playwright/lib/pages/outcomeDetailsPage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/govtool-frontend/playwright/lib/pages/outcomeDetailsPage.ts b/tests/govtool-frontend/playwright/lib/pages/outcomeDetailsPage.ts index dd94a1c6b..1f3737422 100644 --- a/tests/govtool-frontend/playwright/lib/pages/outcomeDetailsPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/outcomeDetailsPage.ts @@ -267,7 +267,7 @@ export default class OutcomeDetailsPage { { message: `CC "Abstain" vote count checked for ${currentPageUrl}`, } - ).toHaveText(`Abstain Votes${proposalToCheck.pool_abstain_votes}`); //BUG missing testIds + ).toHaveText(`Abstain Votes${proposalToCheck.cc_abstain_votes}`); //BUG missing testIds const noPercentage = 100 - parseFloat(yesPercentage.replace("%", "")); await expect(govActionDetailsPage.ccCommitteeNoVotes, { From 958a19e55e3ee956a56463f4852360fec8ddabd7 Mon Sep 17 00:00:00 2001 From: Niraj Date: Thu, 29 May 2025 21:48:44 +0545 Subject: [PATCH 68/75] fix: outcome no proposal test failing issue --- .../lib/pages/outcomeDetailsPage.ts | 4 ++++ .../playwright/lib/pages/outcomesPage.ts | 22 +++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/pages/outcomeDetailsPage.ts b/tests/govtool-frontend/playwright/lib/pages/outcomeDetailsPage.ts index 1f3737422..cbf39d9ca 100644 --- a/tests/govtool-frontend/playwright/lib/pages/outcomeDetailsPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/outcomeDetailsPage.ts @@ -106,6 +106,10 @@ export default class OutcomeDetailsPage { isLoggedIn ); + if (!govActionDetailsPage) { + return; + } + const outcomeResponse = await outcomeResponsePromise; const proposalToCheck = (await outcomeResponse.json())[0]; diff --git a/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts b/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts index e86db03e7..915cb2c67 100644 --- a/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/outcomesPage.ts @@ -177,8 +177,7 @@ export default class OutComesPage { await this.page.getByTestId(this.getSortTestId(sortOption)).click(); const response = await responsePromise; - const data = await response.json(); - let outcomeProposalList: outcomeProposal[] = data.length != 0 ? data : null; + const outcomeProposalList: outcomeProposal[] = await response.json(); // API validation if (outcomeProposalList.length <= 1) return; @@ -555,17 +554,26 @@ export default class OutComesPage { { timeout: 60_000 } ); - const metricsResponsePromise = page.waitForResponse( - (response) => response.url().includes(`/misc/network/metrics?epoch`), - { timeout: 60_000 } - ); - const outcomePage = new OutComesPage(page); await outcomePage.goto({ filter: filterKey }); const outcomeListResponse = await outcomeListResponsePromise; const proposals = await outcomeListResponse.json(); + if (proposals.length === 0) { + expect(true, "No proposals found!").toBeTruthy(); + return { + govActionDetailsPage: null, + outcomeResponsePromise: null, + metricsResponsePromise: null, + }; + } + + const metricsResponsePromise = page.waitForResponse( + (response) => response.url().includes(`/misc/network/metrics?epoch`), + { timeout: 60_000 } + ); + expect( proposals.length, proposals.length == 0 && "No proposals found!" From 527d34d1ac964514259712441607e56db53439c7 Mon Sep 17 00:00:00 2001 From: Niraj Date: Thu, 29 May 2025 21:50:57 +0545 Subject: [PATCH 69/75] chore: decouple dRep auth setup from dRep setup dependency --- tests/govtool-frontend/playwright/playwright.config.ts | 3 +-- tests/govtool-frontend/playwright/tests/dRep.auth.setup.ts | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/govtool-frontend/playwright/playwright.config.ts b/tests/govtool-frontend/playwright/playwright.config.ts index 4e8757478..be00da55a 100644 --- a/tests/govtool-frontend/playwright/playwright.config.ts +++ b/tests/govtool-frontend/playwright/playwright.config.ts @@ -61,7 +61,6 @@ export default defineConfig({ { name: "dRep auth setup", testMatch: "**/dRep.auth.setup.ts", - dependencies: environments.ci ? ["dRep setup"] : [], }, { name: "proposal discussion auth setup", @@ -143,7 +142,7 @@ export default defineConfig({ use: { ...devices["Desktop Chrome"] }, testMatch: "**/*.dRep.spec.ts", dependencies: environments.ci - ? ["dRep auth setup"] + ? ["dRep auth setup" , "dRep setup"] : [], teardown: environments.ci && "cleanup artifacts", }, diff --git a/tests/govtool-frontend/playwright/tests/dRep.auth.setup.ts b/tests/govtool-frontend/playwright/tests/dRep.auth.setup.ts index f1593d593..a5e22ad69 100644 --- a/tests/govtool-frontend/playwright/tests/dRep.auth.setup.ts +++ b/tests/govtool-frontend/playwright/tests/dRep.auth.setup.ts @@ -3,12 +3,10 @@ import { dRep01Wallet, dRep02Wallet } from "@constants/staticWallets"; import { test as setup } from "@fixtures/walletExtension"; import { setAllureEpic, setAllureStory } from "@helpers/allure"; import { createAuth } from "@helpers/auth"; -import { skipIfMainnet } from "@helpers/cardano"; setup.beforeEach(async () => { await setAllureEpic("Setup"); await setAllureStory("Authentication"); - await skipIfMainnet(); }); const drepAuthConfigs = [ From 1c2e7f0281d433139b4366003491c0f0893e6a35 Mon Sep 17 00:00:00 2001 From: Niraj Date: Thu, 29 May 2025 21:51:49 +0545 Subject: [PATCH 70/75] feat: skip propsoal/ draft creation test for mainnet --- .../playwright/lib/helpers/cardano.ts | 2 +- .../proposalBudget.loggedin.pb.spec.ts | 5 + ...oposalBudgetSubmission.loggedin.pb.spec.ts | 6 + .../3-drep-registration/editDRep.dRep.spec.ts | 2 - .../proposalSubmission.ga.spec.ts | 1 + .../proposalSubmission.loggedin.pd.spec.ts | 46 +- .../proposalDiscussion.loggedin.pd.spec.ts | 3 +- .../proposal-submission.ga.auth.setup.ts | 2 + tests/test-metadata-api/package-lock.json | 1119 +++++++++++++++++ 9 files changed, 1169 insertions(+), 17 deletions(-) create mode 100644 tests/test-metadata-api/package-lock.json diff --git a/tests/govtool-frontend/playwright/lib/helpers/cardano.ts b/tests/govtool-frontend/playwright/lib/helpers/cardano.ts index e4ff03501..582d2608a 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/cardano.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/cardano.ts @@ -50,7 +50,7 @@ export async function skipIfNotInfoAndBootstrapping(type: ProposalType) { export async function skipIfMainnet() { if (environments.networkId === 1) { await allure.description( - "Ada spendable features are not available on mainnet." + "Test skipped on mainnet to prevent affecting the production environment or using real ADA." ); test.skip(); } diff --git a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.loggedin.pb.spec.ts b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.loggedin.pb.spec.ts index d8747f469..ed705d51a 100644 --- a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.loggedin.pb.spec.ts +++ b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.loggedin.pb.spec.ts @@ -3,6 +3,7 @@ import { budgetProposal01Wallet } from "@constants/staticWallets"; import { faker } from "@faker-js/faker"; import { test } from "@fixtures/walletExtension"; import { setAllureEpic } from "@helpers/allure"; +import { skipIfMainnet } from "@helpers/cardano"; import BudgetDiscussionDetailsPage from "@pages/budgetDiscussionDetailsPage"; import BudgetDiscussionPage from "@pages/budgetDiscussionPage"; import { expect } from "@playwright/test"; @@ -50,6 +51,8 @@ test.describe("Budget proposal logged in state", () => { }); test("11I. Should comments on any proposal", async ({}) => { + await skipIfMainnet(); + const comment = faker.lorem.words(5); await budgetDiscussionDetailsPage.addComment(comment); await expect( @@ -60,6 +63,8 @@ test.describe("Budget proposal logged in state", () => { }); test("11J. Should reply to any comments", async ({}) => { + await skipIfMainnet(); + const randComment = faker.lorem.words(5); const randReply = faker.lorem.words(5); diff --git a/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts b/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts index c092f05d5..24f836706 100644 --- a/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts +++ b/tests/govtool-frontend/playwright/tests/12-proposal-budget-submission/proposalBudgetSubmission.loggedin.pb.spec.ts @@ -15,6 +15,7 @@ import { import { faker } from "@faker-js/faker"; import { test } from "@fixtures/budgetProposal"; import { setAllureEpic } from "@helpers/allure"; +import { skipIfMainnet } from "@helpers/cardano"; import { createNewPageWithWallet } from "@helpers/page"; import BudgetDiscussionDetailsPage from "@pages/budgetDiscussionDetailsPage"; import BudgetDiscussionPage from "@pages/budgetDiscussionPage"; @@ -421,6 +422,7 @@ test.describe("Budget proposal 01 wallet", () => { }); test("12C. Should save and view draft proposal", async ({ browser }) => { + await skipIfMainnet(); const page = await createNewPageWithWallet(browser, { storageState: budgetProposal02AuthFile, wallet: budgetProposal02Wallet, @@ -469,6 +471,8 @@ test("12C. Should save and view draft proposal", async ({ browser }) => { }); test("12H. Should submit a valid budget proposal", async ({ browser }) => { + await skipIfMainnet(); + const page = await createNewPageWithWallet(browser, { storageState: budgetProposal03AuthFile, wallet: budgetProposal03Wallet, @@ -489,6 +493,7 @@ test("12H. Should submit a valid budget proposal", async ({ browser }) => { test("12I. Should submit a valid draft budget proposal", async ({ browser, }) => { + await skipIfMainnet(); test.slow(); const page = await createNewPageWithWallet(browser, { storageState: budgetProposal04AuthFile, @@ -517,6 +522,7 @@ test("12I. Should submit a valid draft budget proposal", async ({ test("12J. Should verify created proposal appears in my proposals list", async ({ browser, }) => { + await skipIfMainnet(); test.slow(); const page = await createNewPageWithWallet(browser, { storageState: budgetProposal05AuthFile, diff --git a/tests/govtool-frontend/playwright/tests/3-drep-registration/editDRep.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/3-drep-registration/editDRep.dRep.spec.ts index 782df6ada..383a43a89 100644 --- a/tests/govtool-frontend/playwright/tests/3-drep-registration/editDRep.dRep.spec.ts +++ b/tests/govtool-frontend/playwright/tests/3-drep-registration/editDRep.dRep.spec.ts @@ -2,7 +2,6 @@ import { dRep02Wallet } from "@constants/staticWallets"; import { faker } from "@faker-js/faker"; import { test } from "@fixtures/walletExtension"; import { setAllureEpic } from "@helpers/allure"; -import { ShelleyWallet } from "@helpers/crypto"; import { invalid as mockInvalid, valid as mockValid } from "@mock/index"; import { skipIfMainnet, @@ -10,7 +9,6 @@ import { } from "@helpers/cardano"; import EditDRepPage from "@pages/editDRepPage"; import { expect } from "@playwright/test"; -import environments from "@constants/environments"; import { dRep02AuthFile } from "@constants/auth"; import { generateInvalidDRepInfo, generateValidDRepInfo } from "@helpers/dRep"; diff --git a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts index a6a266581..7cd57efc1 100644 --- a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts +++ b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts @@ -124,6 +124,7 @@ test.describe("Proposed as a governance action", async () => { }); test.afterEach(async () => { + await skipIfMainnet(); // cleanup await proposalDiscussionDetailPage.goto(proposalId); diff --git a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts index d7126799a..2cf95f381 100644 --- a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts +++ b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts @@ -18,10 +18,11 @@ import { getDraftProposalWalletAndState } from "@helpers/auth"; import { skipIfNotInfoAndBootstrapping, isBootStrapingPhase, + skipIfMainnet, } from "@helpers/cardano"; import { ShelleyWallet } from "@helpers/crypto"; import { createNewPageWithWallet } from "@helpers/page"; -import { invalid, valid as mockValid } from "@mock/index"; +import { rewardAddressBech32 } from "@helpers/shellyWallet"; import ProposalDiscussionDetailsPage from "@pages/proposalDiscussionDetailsPage"; import ProposalSubmissionPage from "@pages/proposalSubmissionPage"; import { expect } from "@playwright/test"; @@ -132,6 +133,7 @@ test.describe("Proposal created logged state", () => { page, wallet, }) => { + await skipIfMainnet(); await skipIfNotInfoAndBootstrapping(type); const proposalSubmissionPage = new ProposalSubmissionPage(page); @@ -308,28 +310,43 @@ test.describe("Proposal created logged state", () => { test("7O. Should display insufficient balance modal when submitting proposal with insufficient funds", async ({ page, - proposalId, }) => { + await skipIfMainnet(); + const proposalCreationPage = new ProposalSubmissionPage(page); + await proposalCreationPage.goto(); + + const receiverAddress = rewardAddressBech32( + environments.networkId, + proposal01Wallet.stake.pkh + ); + + await proposalCreationPage.createProposal(receiverAddress); + const proposalDiscussionDetailsPage = new ProposalDiscussionDetailsPage( page ); - await proposalDiscussionDetailsPage.goto(proposalId); - await proposalDiscussionDetailsPage.verifyIdentityBtn.click(); - await proposalDiscussionDetailsPage.submitAsGABtn.click(); - - const proposalSubmissionPage = new ProposalSubmissionPage(page); - await expect( - proposalSubmissionPage.currentPage.getByText( - "Insufficient wallet balance", - { exact: true } - ) - ).toBeVisible(); // BUG missing test id + try { + await proposalDiscussionDetailsPage.submitAsGABtn.click(); + await expect( + proposalCreationPage.currentPage.getByText( + "Insufficient wallet balance", + { exact: true } + ) + ).toBeVisible(); // BUG missing test id + + await proposalCreationPage.currentPage + .getByRole("button", { name: "Close" }) + .click(); // BUG missing test id + } finally { + await proposalDiscussionDetailsPage.deleteProposal(); + } }); }); test.describe("Proposal Draft", () => { test("7C. Should list unfinished Draft ", async ({ browser }) => { + await skipIfMainnet(); const page = await createNewPageWithWallet(browser, { storageState: proposal03AuthFile, wallet: proposal03Wallet, @@ -346,6 +363,7 @@ test.describe("Proposal Draft", () => { }); test("7L. Should save proposal as a draft", async ({ browser }) => { + await skipIfMainnet(); const page = await createNewPageWithWallet(browser, { storageState: proposal04AuthFile, wallet: proposal04Wallet, @@ -422,6 +440,7 @@ test.describe("Proposal Draft", () => { test(`7M_${index + 1}. Should edit a ${proposalType.toLowerCase()} proposal draft`, async ({ browser, }) => { + await skipIfMainnet(); test.slow(); const { storageState, wallet } = getDraftProposalWalletAndState(proposalType); @@ -496,6 +515,7 @@ test.describe("Proposal Draft", () => { }); test("7N. Should submit a draft proposal", async ({ browser }) => { + await skipIfMainnet(); const page = await createNewPageWithWallet(browser, { storageState: proposal06AuthFile, wallet: proposal06Wallet, diff --git a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.pd.spec.ts b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.pd.spec.ts index 98f4c4e36..40c725509 100644 --- a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.pd.spec.ts +++ b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.pd.spec.ts @@ -9,15 +9,16 @@ import { createNewPageWithWallet } from "@helpers/page"; import ProposalDiscussionDetailsPage from "@pages/proposalDiscussionDetailsPage"; import { Page, expect } from "@playwright/test"; import { setAllureEpic } from "@helpers/allure"; -import ProposalSubmissionPage from "@pages/proposalSubmissionPage"; import { proposal01AuthFile, proposal02AuthFile, user01AuthFile, } from "@constants/auth"; +import { skipIfMainnet } from "@helpers/cardano"; test.beforeEach(async () => { await setAllureEpic("8. Proposal Discussion Forum"); + await skipIfMainnet(); }); test.describe("Proposal created logged in state", () => { diff --git a/tests/govtool-frontend/playwright/tests/proposal-submission.ga.auth.setup.ts b/tests/govtool-frontend/playwright/tests/proposal-submission.ga.auth.setup.ts index 171a2c20f..e88d7690e 100644 --- a/tests/govtool-frontend/playwright/tests/proposal-submission.ga.auth.setup.ts +++ b/tests/govtool-frontend/playwright/tests/proposal-submission.ga.auth.setup.ts @@ -3,10 +3,12 @@ import { test as setup } from "@fixtures/walletExtension"; import { createAuthWithUserName } from "@helpers/auth"; import walletManager from "lib/walletManager"; import { proposalSubmissionAuthFile } from "@constants/auth"; +import { skipIfMainnet } from "@helpers/cardano"; setup.beforeEach(async () => { await setAllureEpic("Setup"); await setAllureStory("Authentication"); + await skipIfMainnet(); }); setup( diff --git a/tests/test-metadata-api/package-lock.json b/tests/test-metadata-api/package-lock.json new file mode 100644 index 000000000..cedd224bd --- /dev/null +++ b/tests/test-metadata-api/package-lock.json @@ -0,0 +1,1119 @@ +{ + "name": "test-metadata-api", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "test-metadata-api", + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "express": "^4.19.2", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.0", + "uuid": "^9.0.1" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "license": "MIT" + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^9.0.6", + "@apidevtools/openapi-schemas": "^2.0.4", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "z-schema": "^5.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "license": "MIT" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT", + "peer": true + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/swagger-jsdoc": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", + "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", + "license": "MIT", + "dependencies": { + "commander": "6.2.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "lodash.mergewith": "^4.6.2", + "swagger-parser": "^10.0.3", + "yaml": "2.0.0-1" + }, + "bin": { + "swagger-jsdoc": "bin/swagger-jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", + "license": "MIT", + "dependencies": { + "@apidevtools/swagger-parser": "10.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.17.14", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", + "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==", + "license": "Apache-2.0" + }, + "node_modules/swagger-ui-express": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", + "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", + "license": "MIT", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.0.0-1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", + "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/z-schema": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.6.tgz", + "integrity": "sha512-+XR1GhnWklYdfr8YaZv/iu+vY+ux7V5DS5zH1DQf6bO5ufrt/5cgNhVO5qyhsjFXvsqQb/f08DWE9b6uPscyAg==", + "license": "MIT", + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^10.0.0" + } + }, + "node_modules/z-schema/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + } + } +} From f2c682c15018038048fe2bb51424a4789ce437b8 Mon Sep 17 00:00:00 2001 From: Niraj Date: Fri, 30 May 2025 07:54:00 +0545 Subject: [PATCH 71/75] fix: add missing testId of insufficient wallet balance dialog --- .../proposalSubmission.loggedin.pd.spec.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts index 2cf95f381..63ef2d23e 100644 --- a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts +++ b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts @@ -329,15 +329,14 @@ test.describe("Proposal created logged state", () => { try { await proposalDiscussionDetailsPage.submitAsGABtn.click(); await expect( - proposalCreationPage.currentPage.getByText( - "Insufficient wallet balance", - { exact: true } + proposalCreationPage.currentPage.getByTestId( + "insufficient-wallet-balance-title" ) - ).toBeVisible(); // BUG missing test id + ).toHaveText(/Insufficient wallet balance/); await proposalCreationPage.currentPage - .getByRole("button", { name: "Close" }) - .click(); // BUG missing test id + .getByTestId("insufficient-wallet-balance-dialog-button") + .click(); } finally { await proposalDiscussionDetailsPage.deleteProposal(); } From 00de1294cae590dfe319637f7f4755102eaa2bc5 Mon Sep 17 00:00:00 2001 From: Niraj Date: Fri, 30 May 2025 10:06:01 +0545 Subject: [PATCH 72/75] cleanup: remove unnecessary package-lock file --- tests/test-metadata-api/package-lock.json | 1119 --------------------- 1 file changed, 1119 deletions(-) delete mode 100644 tests/test-metadata-api/package-lock.json diff --git a/tests/test-metadata-api/package-lock.json b/tests/test-metadata-api/package-lock.json deleted file mode 100644 index cedd224bd..000000000 --- a/tests/test-metadata-api/package-lock.json +++ /dev/null @@ -1,1119 +0,0 @@ -{ - "name": "test-metadata-api", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "test-metadata-api", - "version": "0.0.1", - "license": "MIT", - "dependencies": { - "express": "^4.19.2", - "swagger-jsdoc": "^6.2.8", - "swagger-ui-express": "^5.0.0", - "uuid": "^9.0.1" - } - }, - "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", - "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", - "license": "MIT", - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - } - }, - "node_modules/@apidevtools/openapi-schemas": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", - "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/@apidevtools/swagger-methods": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", - "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", - "license": "MIT" - }, - "node_modules/@apidevtools/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", - "license": "MIT", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^9.0.6", - "@apidevtools/openapi-schemas": "^2.0.4", - "@apidevtools/swagger-methods": "^3.0.2", - "@jsdevtools/ono": "^7.1.3", - "call-me-maybe": "^1.0.1", - "z-schema": "^5.0.1" - }, - "peerDependencies": { - "openapi-types": ">=7" - } - }, - "node_modules/@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "license": "MIT" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "license": "MIT" - }, - "node_modules/commander": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", - "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "license": "ISC" - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "license": "MIT" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "license": "MIT" - }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "license": "MIT" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/openapi-types": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", - "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", - "license": "MIT", - "peer": true - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", - "license": "MIT" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/swagger-jsdoc": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", - "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", - "license": "MIT", - "dependencies": { - "commander": "6.2.0", - "doctrine": "3.0.0", - "glob": "7.1.6", - "lodash.mergewith": "^4.6.2", - "swagger-parser": "^10.0.3", - "yaml": "2.0.0-1" - }, - "bin": { - "swagger-jsdoc": "bin/swagger-jsdoc.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", - "license": "MIT", - "dependencies": { - "@apidevtools/swagger-parser": "10.0.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/swagger-ui-dist": { - "version": "5.17.14", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", - "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==", - "license": "Apache-2.0" - }, - "node_modules/swagger-ui-express": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", - "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", - "license": "MIT", - "dependencies": { - "swagger-ui-dist": ">=5.0.0" - }, - "engines": { - "node": ">= v0.10.32" - }, - "peerDependencies": { - "express": ">=4.0.0 || >=5.0.0-beta" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/yaml": { - "version": "2.0.0-1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", - "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, - "node_modules/z-schema": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.6.tgz", - "integrity": "sha512-+XR1GhnWklYdfr8YaZv/iu+vY+ux7V5DS5zH1DQf6bO5ufrt/5cgNhVO5qyhsjFXvsqQb/f08DWE9b6uPscyAg==", - "license": "MIT", - "dependencies": { - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.7.0" - }, - "bin": { - "z-schema": "bin/z-schema" - }, - "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "commander": "^10.0.0" - } - }, - "node_modules/z-schema/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - } - } -} From 991814fb7e1246e9a05846c597a1cf5fa225a800 Mon Sep 17 00:00:00 2001 From: Niraj Date: Fri, 30 May 2025 11:40:50 +0545 Subject: [PATCH 73/75] fix: add faucet address on merge utxo inputs --- tests/govtool-frontend/playwright/lib/services/kuberService.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/govtool-frontend/playwright/lib/services/kuberService.ts b/tests/govtool-frontend/playwright/lib/services/kuberService.ts index 07956b80d..d97e5e514 100644 --- a/tests/govtool-frontend/playwright/lib/services/kuberService.ts +++ b/tests/govtool-frontend/playwright/lib/services/kuberService.ts @@ -177,6 +177,7 @@ const kuberService = { })); const inputs = wallets.map((wallet) => wallet.address); + inputs.push(getWalletConfigForFaucet().address); return kuber.signAndSubmitTx({ inputs, selections, From 80aedef098d239e41f9db984a881b6cdb95e342e Mon Sep 17 00:00:00 2001 From: Ciabas Date: Tue, 3 Jun 2025 14:05:46 +0200 Subject: [PATCH 74/75] fix(#3709): edit dRep form adds two link input fields instead of one --- CHANGELOG.md | 1 + .../EditDRepInfoSteps/EditDRepForm.tsx | 31 ++++++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad0011279..6c28d95c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ changes. - Fix missing off chain references in DRep details [Issue 3490](https://github.com/IntersectMBO/govtool/issues/3490) - Fix blank screen and type error on linkReferences when navigating to edit dRep page that has no links [Issue 3714](https://github.com/IntersectMBO/govtool/issues/3714) +- Fix adding two link input fields when editing the dRep form when no links are present initially [Issue 3709](https://github.com/IntersectMBO/govtool/issues/3709) ### Changed diff --git a/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepForm.tsx b/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepForm.tsx index 1efc085e7..268e8936d 100644 --- a/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepForm.tsx +++ b/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepForm.tsx @@ -4,6 +4,7 @@ import { Box } from "@mui/material"; import { useCardano } from "@context"; import { + defaultEditDRepInfoValues, useEditDRepInfoForm, useGetDRepDetailsQuery, useTranslation, @@ -44,15 +45,21 @@ export const EditDRepForm = ({ reset({ ...data, - objectives: data?.objectives ?? "", - motivations: data?.motivations ?? "", - qualifications: data?.qualifications ?? "", - paymentAddress: data?.paymentAddress ?? "", - image: data?.image ?? "", - linkReferences: data?.linkReferences ?? [getEmptyReference("Link")], - identityReferences: data?.identityReferences ?? [ - getEmptyReference("Identity"), - ], + objectives: data?.objectives ?? defaultEditDRepInfoValues.objectives, + motivations: data?.motivations ?? defaultEditDRepInfoValues.motivations, + qualifications: + data?.qualifications ?? defaultEditDRepInfoValues.qualifications, + paymentAddress: + data?.paymentAddress ?? defaultEditDRepInfoValues.paymentAddress, + image: data?.image ?? defaultEditDRepInfoValues.image, + linkReferences: + Array.isArray(data?.linkReferences) && data.linkReferences.length > 0 + ? data.linkReferences + : defaultEditDRepInfoValues.linkReferences, + identityReferences: + Array.isArray(data?.identityReferences) && data.identityReferences.length > 0 + ? data.identityReferences + : defaultEditDRepInfoValues.identityReferences, }); } }, [yourselfDRep, loadUserData]); @@ -74,9 +81,3 @@ export const EditDRepForm = ({ ); }; - -const getEmptyReference = (type: "Link" | "Identity") => ({ - "@type": type, - uri: "", - label: "", -}); From 8abcc81dfb96095d0a776cafc34a70ee616833ff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 13:41:28 +0000 Subject: [PATCH 75/75] chore: update @intersect.mbo/pdf-ui to 0.7.0-beta-35 --- govtool/frontend/package-lock.json | 8 ++++---- govtool/frontend/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 47d4b3fae..2492bd6d6 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -15,7 +15,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.3", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "0.7.0-beta-34", + "@intersect.mbo/pdf-ui": "0.7.0-beta-35", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -3424,9 +3424,9 @@ "license": "ISC" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "0.7.0-beta-34", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-34.tgz", - "integrity": "sha512-PC5/wiqj2QH/57edzqor2tOZLNbCtijof8IUCFIKwfaeQ7wkKkEVHEIY1iKs0eK9DYAIEnHWCS3rnpjm9vY9Vg==", + "version": "0.7.0-beta-35", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.7.0-beta-35.tgz", + "integrity": "sha512-S0HAl4pwJm+AqzGxEEHxQ59VsU6Tbvnn5w7F6jG0jd7zUHSCKJAt3PhJQ6VliA5FoOI4z43a2xm7J/9PK+Q9IA==", "dependencies": { "@emurgo/cardano-serialization-lib-asmjs": "^12.0.0-beta.2", "@fontsource/poppins": "^5.0.14", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index bdad215a5..56e71b22e 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -29,7 +29,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "v1.4.3", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "0.7.0-beta-34", + "@intersect.mbo/pdf-ui": "0.7.0-beta-35", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4",