diff --git a/CHANGELOG.md b/CHANGELOG.md
index 69e2f4722..82cddf042 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,9 @@ changes.
### Added
+- Add Proposal discussion context that manages username [Issue 3341](https://github.com/IntersectMBO/govtool/issues/3341)
+- Add epochParams and ada holder balance to Proposal Discussion Pillar [Issue 2243](https://github.com/IntersectMBO/govtool/issues/2243)
+
### Fixed
- Fix scroll on a drawer on smaller resolution
diff --git a/govtool/frontend/src/context/contextProviders.tsx b/govtool/frontend/src/context/contextProviders.tsx
index d38fa0acc..b17e122be 100644
--- a/govtool/frontend/src/context/contextProviders.tsx
+++ b/govtool/frontend/src/context/contextProviders.tsx
@@ -6,6 +6,7 @@ import { DataActionsBarProvider } from "./dataActionsBar";
import { FeatureFlagProvider } from "./featureFlag";
import { GovernanceActionProvider } from "./governanceAction";
import { AdaHandleProvider } from "./adaHandle";
+import { ProposalDiscussionProvider } from "./proposalDiscussion";
interface Props {
children: React.ReactNode;
@@ -14,17 +15,19 @@ interface Props {
const ContextProviders = ({ children }: Props) => (
-
-
-
-
-
- {children}
-
-
-
-
-
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
);
diff --git a/govtool/frontend/src/context/index.ts b/govtool/frontend/src/context/index.ts
index 8bf7be85f..0ece5a1b5 100644
--- a/govtool/frontend/src/context/index.ts
+++ b/govtool/frontend/src/context/index.ts
@@ -8,3 +8,4 @@ export * from "./usersnapContext";
export * from "./wallet";
export * from "./featureFlag";
export * from "./governanceAction";
+export * from "./proposalDiscussion";
diff --git a/govtool/frontend/src/context/proposalDiscussion.tsx b/govtool/frontend/src/context/proposalDiscussion.tsx
new file mode 100644
index 000000000..6e1ee3b1f
--- /dev/null
+++ b/govtool/frontend/src/context/proposalDiscussion.tsx
@@ -0,0 +1,54 @@
+import {
+ PropsWithChildren,
+ useMemo,
+ createContext,
+ useContext,
+ useState,
+} from "react";
+
+type ProposalDiscussionContextType = {
+ username: string;
+ setUsername: (username: string) => void;
+} | null;
+
+const ProposalDiscussionContext =
+ createContext(null);
+
+/**
+ * Provides proposal discussion context to its children components.
+ *
+ * @param children - The child components to render.
+ */
+const ProposalDiscussionProvider = ({ children }: PropsWithChildren) => {
+ const [username, setUsername] = useState("");
+
+ const value = useMemo(
+ () => ({
+ username,
+ setUsername,
+ }),
+ [username],
+ );
+
+ return (
+
+ {children}
+
+ );
+};
+
+/**
+ * Custom hook to use the ProposalDiscussionContext.
+ * @returns The context value.
+ */
+const useProposalDiscussion = () => {
+ const context = useContext(ProposalDiscussionContext);
+ if (!context) {
+ throw new Error(
+ "useProposalDiscussion must be used within a ProposalDiscussionProvider",
+ );
+ }
+ return context;
+};
+
+export { ProposalDiscussionProvider, useProposalDiscussion };
diff --git a/govtool/frontend/src/pages/GovernanceActionOutComes.tsx b/govtool/frontend/src/pages/GovernanceActionOutComes.tsx
index 79db53f63..100250c23 100644
--- a/govtool/frontend/src/pages/GovernanceActionOutComes.tsx
+++ b/govtool/frontend/src/pages/GovernanceActionOutComes.tsx
@@ -2,7 +2,7 @@ import { Box, CircularProgress } from "@mui/material";
import React, { Suspense } from "react";
import { Footer, TopNav } from "@/components/organisms";
import { useCardano } from "@/context";
-import { useScreenDimension } from "@/hooks";
+import { useScreenDimension, useTranslation } from "@/hooks";
import { Background } from "@/components/atoms";
const GovernanceActionsOutcomes = React.lazy(
@@ -12,6 +12,8 @@ const GovernanceActionsOutcomes = React.lazy(
export const GovernanceActionOutComesPillar = () => {
const { pagePadding } = useScreenDimension();
const { walletApi, ...context } = useCardano();
+ const { i18n } = useTranslation();
+
return (
{
apiUrl={import.meta.env.VITE_OUTCOMES_API_URL}
ipfsGateway={import.meta.env.VITE_IPFS_GATEWAY}
walletAPI={{ ...context, ...walletApi }}
+ i18n={i18n}
/>
diff --git a/govtool/frontend/src/pages/ProposalDiscussion.tsx b/govtool/frontend/src/pages/ProposalDiscussion.tsx
index 25d3c67bf..b69836df9 100644
--- a/govtool/frontend/src/pages/ProposalDiscussion.tsx
+++ b/govtool/frontend/src/pages/ProposalDiscussion.tsx
@@ -1,23 +1,35 @@
import React, { ComponentProps, Suspense } from "react";
import { Box, CircularProgress } from "@mui/material";
import "@intersect.mbo/pdf-ui/style";
-import { useCardano, useGovernanceActions } from "@/context";
+import {
+ useAppContext,
+ useCardano,
+ useGovernanceActions,
+ useProposalDiscussion,
+} from "@/context";
import { useValidateMutation } from "@/hooks/mutations";
import { useScreenDimension } from "@/hooks/useScreenDimension";
import { Footer, TopNav } from "@/components/organisms";
-import { useGetDRepVotingPowerList, useGetVoterInfo } from "@/hooks";
+import {
+ useGetAdaHolderVotingPowerQuery,
+ useGetDRepVotingPowerList,
+ useGetVoterInfo,
+} from "@/hooks";
const ProposalDiscussion = React.lazy(
() => import("@intersect.mbo/pdf-ui/cjs"),
);
export const ProposalDiscussionPillar = () => {
+ const { epochParams } = useAppContext();
const { pagePadding } = useScreenDimension();
const { validateMetadata } = useValidateMutation();
const { walletApi, ...context } = useCardano();
const { voter } = useGetVoterInfo();
const { createGovernanceActionJsonLD, createHash } = useGovernanceActions();
const { fetchDRepVotingPowerList } = useGetDRepVotingPowerList();
+ const { username, setUsername } = useProposalDiscussion();
+ const { votingPower } = useGetAdaHolderVotingPowerQuery(context.stakeKey);
return (
{
>["validateMetadata"]
}
fetchDRepVotingPowerList={fetchDRepVotingPowerList}
+ username={username}
+ setUsername={setUsername}
+ epochParams={epochParams}
+ votingPower={votingPower}
/>
diff --git a/govtool/frontend/src/types/@intersect.mbo.d.ts b/govtool/frontend/src/types/@intersect.mbo.d.ts
index 39af24c64..140fcd55b 100644
--- a/govtool/frontend/src/types/@intersect.mbo.d.ts
+++ b/govtool/frontend/src/types/@intersect.mbo.d.ts
@@ -4,39 +4,46 @@ enum MetadataValidationStatus {
INVALID_HASH = "INVALID_HASH",
INCORRECT_FORMAT = "INCORRECT_FORMAT",
}
+declare module "@intersect.mbo/pdf-ui/cjs" {
+ import { EpochParams } from "@/models";
-type ProposalDiscussionProps = {
- pdfApiUrl: string;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- walletAPI: any;
- pathname: string;
- locale?: string;
- validateMetadata: ({
- url,
- hash,
- standard,
- }: {
- url: string;
- hash: string;
- standard: "CIP108";
- }) => Promise<
+ type ProposalDiscussionProps = {
+ pdfApiUrl: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- | { status?: MetadataValidationStatus; metadata?: any; valid: boolean }
- | undefined
- >;
- fetchDRepVotingPowerList: (
- identifiers: string[],
- ) => Promise;
-};
+ walletAPI: any;
+ pathname: string;
+ locale?: string;
+ validateMetadata: ({
+ url,
+ hash,
+ standard,
+ }: {
+ url: string;
+ hash: string;
+ standard: "CIP108";
+ }) => Promise<
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ | { status?: MetadataValidationStatus; metadata?: any; valid: boolean }
+ | undefined
+ >;
+ fetchDRepVotingPowerList: (
+ identifiers: string[],
+ ) => Promise;
+ epochParams?: EpochParams;
+ votingPower: number;
+ username: string;
+ setUsername: (username: string) => void;
+ };
-type GovernanceActionsOutcomesProps = {
- apiUrl?: string;
- ipfsGateway?: string;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- walletAPI?: any;
-};
+ type GovernanceActionsOutcomesProps = {
+ apiUrl?: string;
+ ipfsGateway?: string;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ walletAPI?: any;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ i18n?: any;
+ };
-declare module "@intersect.mbo/pdf-ui/cjs" {
export default function ProposalDiscussion(
props: ProposalDiscussionProps,
): JSX.Element;
diff --git a/tests/govtool-frontend/playwright/lib/services/kuberService.ts b/tests/govtool-frontend/playwright/lib/services/kuberService.ts
index d4bbd06c5..5192debc4 100644
--- a/tests/govtool-frontend/playwright/lib/services/kuberService.ts
+++ b/tests/govtool-frontend/playwright/lib/services/kuberService.ts
@@ -211,7 +211,10 @@ const kuberService = {
},
multipleDRepRegistration: (metadataAndWallets: WalletAndAnchorType[]) => {
- const kuber = new Kuber(faucetWallet.address, faucetWallet.payment.private);
+ const kuber = new Kuber(
+ proposalFaucetWallet.address,
+ proposalFaucetWallet.payment.private
+ );
const req = {
certificates: metadataAndWallets.map((metadataAndWallet) =>
Kuber.generateCert(
diff --git a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.loggedin.spec.ts
index e73882eac..e76bb8738 100644
--- a/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.loggedin.spec.ts
+++ b/tests/govtool-frontend/playwright/tests/11-proposal-budget/proposalBudget.loggedin.spec.ts
@@ -49,7 +49,7 @@ test.describe("Budget proposal logged in state", () => {
});
test("11I. Should comments on any proposal", async ({}) => {
- const comment = faker.lorem.paragraph(2);
+ const comment = faker.lorem.paragraph(1);
await budgetDiscussionDetailsPage.addComment(comment);
await expect(
budgetDiscussionDetailsPage.currentPage
@@ -59,7 +59,7 @@ test.describe("Budget proposal logged in state", () => {
});
test("11J. Should reply to any comments", async ({}) => {
- const randComment = faker.lorem.paragraph(2);
+ const randComment = faker.lorem.paragraph(1);
const randReply = faker.lorem.words(5);
await budgetDiscussionDetailsPage.addComment(randComment);
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 9e7fc2ce2..22a041e45 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
@@ -187,7 +187,7 @@ test("11E. Should view comments with count indications on a budget proposal", as
page,
}) => {
let responsePromise = page.waitForResponse((response) =>
- response.url().includes(`/api/comments`)
+ response.url().includes(`/api/bds/`)
);
const budgetDiscussionPage = new BudgetDiscussionPage(page);
@@ -197,13 +197,23 @@ test("11E. Should view comments with count indications on a budget proposal", as
await budgetDiscussionPage.viewFirstProposal();
const response = await responsePromise;
- const comments: CommentResponse[] = (await response.json()).data;
+ const proposalResponse = await response.json();
- await responsePromise;
+ const actualTotalComments =
+ await budgetDiscussionDetailsPage.totalComments.textContent();
+ const expectedTotalComments =
+ proposalResponse.data.attributes.prop_comments_number.toString();
+ const isEqual = actualTotalComments === expectedTotalComments;
- await expect(budgetDiscussionDetailsPage.totalComments).toHaveText(
- comments.length.toString()
- );
+ const currentPageUrl = budgetDiscussionDetailsPage.currentPage.url();
+
+ const proposalId = extractProposalIdFromUrl(currentPageUrl);
+
+ await expect(
+ budgetDiscussionDetailsPage.totalComments,
+ !isEqual &&
+ `Total comments do not match in ${environments.frontendUrl}/budget_discussion/${proposalId}`
+ ).toHaveText(expectedTotalComments);
});
test.describe("Restricted access to interact budget proposal", () => {