diff --git a/CHANGELOG.md b/CHANGELOG.md index d2c4a786e..ba69e3a67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ 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) +- Fix images in Governance Action Details are displayed at full width and height without cropping or clipping [Issue 3837](https://github.com/IntersectMBO/govtool/issues/3837) +- Fix missing page titles on subpages: DRep details and Gov Actions details [Issue 3142](https://github.com/IntersectMBO/govtool/issues/3142) ### Changed - Adjust top menu (navbar) layout when wallet is not connected [Issue-3682](https://github.com/IntersectMBO/govtool/issues/3682) diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 24ffb835c..612ed8faa 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.5.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "1.0.3-beta", + "@intersect.mbo/pdf-ui": "1.0.9-beta", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@noble/ed25519": "^2.3.0", @@ -3426,9 +3426,9 @@ "license": "ISC" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "1.0.3-beta", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-1.0.3-beta.tgz", - "integrity": "sha512-zsG3wD3C2k7x3rWPTmrUan22rIuly2ltLMx3lOYN7MIFFnQCeJ1+qXYwnZhvLsgVtzZbAi+gGnDqYggZLgVkoQ==", + "version": "1.0.9-beta", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-1.0.9-beta.tgz", + "integrity": "sha512-rFWt8PrRt6ecbW0mN2p3HQVUGtJyYEmJSaaMYcN/XgwGfehmJ5CblP9S7/W5ZoDiQrFTaH3bBLl9Bu31mbcJpA==", "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 ea8747291..5afca7323 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.5.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "1.0.3-beta", + "@intersect.mbo/pdf-ui": "1.0.9-beta", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@noble/ed25519": "^2.3.0", diff --git a/govtool/frontend/src/components/molecules/GovernanceActionCardElement.tsx b/govtool/frontend/src/components/molecules/GovernanceActionCardElement.tsx index d2c4bf83e..55fc43d39 100644 --- a/govtool/frontend/src/components/molecules/GovernanceActionCardElement.tsx +++ b/govtool/frontend/src/components/molecules/GovernanceActionCardElement.tsx @@ -133,6 +133,21 @@ export const GovernanceActionCardElement = ({ p: ({ children: markdownChildren }: PropsWithChildren) => renderMarkdownText({ children: markdownChildren }), br: () =>
, + img: ({ + src, + alt, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + node, // node is passed by react-markdown but we should not use it + ...rest + }: React.ImgHTMLAttributes & { node?: unknown }) => ( + {alt + ), }; const renderMarkdown = (markdownText: string | number) => { diff --git a/govtool/frontend/src/components/molecules/VoteActionForm.tsx b/govtool/frontend/src/components/molecules/VoteActionForm.tsx index ca72961a5..9bc79a797 100644 --- a/govtool/frontend/src/components/molecules/VoteActionForm.tsx +++ b/govtool/frontend/src/components/molecules/VoteActionForm.tsx @@ -144,7 +144,10 @@ export const VoteActionForm = ({ sx={{ lineHeight: "18px", alignSelf: "start" }} > {t("govActions.castVoteDeadline", { - date: expiryDate, + date: formatDisplayDate( + expiryDate ?? "", + "yyyy-MM-dd HH:mm:ss", + ), epoch: expiryEpochNo, })} diff --git a/govtool/frontend/src/components/molecules/tableMarkdown.css b/govtool/frontend/src/components/molecules/tableMarkdown.css index 6a76a446c..acc270f75 100644 --- a/govtool/frontend/src/components/molecules/tableMarkdown.css +++ b/govtool/frontend/src/components/molecules/tableMarkdown.css @@ -1,28 +1,26 @@ -.markdown { - & table { - display: block; - overflow-x: auto; - margin: 32px 0; - border-spacing: 0; - border-collapse: collapse; - max-width: 100%; +.markdown table { + display: block; + overflow-x: auto; + margin: 32px 0; + border-spacing: 0; + border-collapse: collapse; + max-width: 100%; +} - & thead { - background-color: #d6e2ff80; - } +.markdown thead { + background-color: #d6e2ff80; +} - & th, - & td { - padding: 6px 13px; - border: 1px solid #d6e2ff; - } +.markdown th, +.markdown td { + padding: 6px 13px; + border: 1px solid #d6e2ff; +} - & td > :last-child { - margin-bottom: 0; - } +.markdown td > :last-child { + margin-bottom: 0; +} - & tr:nth-child(2n) { - background-color: #d6e2ff80; - } - } +.markdown tr:nth-child(2n) { + background-color: #d6e2ff80; } diff --git a/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx b/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx index 223839887..557839f93 100644 --- a/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx +++ b/govtool/frontend/src/components/organisms/MaintenanceEndingBanner/MaintenanceEndingBanner.tsx @@ -61,7 +61,7 @@ export const MaintenanceEndingBanner = () => { {/* Expandable Content */} { color="common.white" mb={0.5} > - {t("system.maintenanceEnding.description1")} - - , ]} /> - - {t("system.maintenanceEnding.description3")}{" "} - - {t("system.maintenanceEnding.linkText")} - - diff --git a/govtool/frontend/src/consts/navItems.tsx b/govtool/frontend/src/consts/navItems.tsx index 6274f7a33..e291728d1 100644 --- a/govtool/frontend/src/consts/navItems.tsx +++ b/govtool/frontend/src/consts/navItems.tsx @@ -45,7 +45,7 @@ export const NAV_ITEMS: Array = [ }, { dataTestId: "governance-actions", - label: i18n.t("govActions.title"), + label: i18n.t("govActions.categoryTitle"), childNavItems: [ { dataTestId: "proposed-governance-actions-link", @@ -56,7 +56,7 @@ export const NAV_ITEMS: Array = [ { dataTestId: "governance-actions-link", navTo: PATHS.governanceActions, - label: i18n.t("govActions.navTitle"), + label: i18n.t("govActions.title"), newTabLink: null, }, { @@ -108,7 +108,7 @@ export const CONNECTED_NAV_ITEMS = [ }, { dataTestId: "governance-actions-link", - label: i18n.t("govActions.title"), + label: i18n.t("govActions.categoryTitle"), navTo: PATHS.dashboardGovernanceActions, activeIcon: ICONS.governanceActionsActiveIcon, icon: ICONS.governanceActionsIcon, @@ -139,7 +139,7 @@ export const CONNECTED_NAV_ITEMS = [ { dataTestId: "governance-actions-live-voting-link", label: i18n.t("govActions.liveVoting.title"), - navTo: OUTCOMES_PATHS.governanceActionsLiveVoting, + navTo: PATHS.dashboardGovernanceActions, activeIcon: ICONS.governanceActionsActiveIcon, icon: ICONS.governanceActionsIcon, newTabLink: null, diff --git a/govtool/frontend/src/consts/paths.ts b/govtool/frontend/src/consts/paths.ts index 94e16e0a4..0fbd60ef0 100644 --- a/govtool/frontend/src/consts/paths.ts +++ b/govtool/frontend/src/consts/paths.ts @@ -49,5 +49,4 @@ export const USER_PATHS = { export const OUTCOMES_PATHS = { governanceActionsOutcomes: "/outcomes", governanceActionOutcomes: "/outcomes/governance_actions/:id", - governanceActionsLiveVoting: "/connected/governance_actions", }; diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index 111029fca..4ecbc2ea9 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -432,7 +432,7 @@ }, "backToGovActions": "Back to Governance Actions", "castVote": "<0>You voted {{vote}} on this proposal\non {{date}} (Epoch {{epoch}})", - "castVoteDeadline": "You can change your vote up to {{date}} (Epoch {{epoch}})", + "castVoteDeadline": "You can change your vote up to {{date}} UTC (Epoch {{epoch}})", "changeVote": "Change vote", "changeYourVote": "Change your vote", "chooseHowToVote": "Choose how you want to vote:", @@ -489,8 +489,8 @@ "submittedDateWithEpoch": "Submitted: <0>{{date}} <1>(Epoch {{epoch}})", "supportingLinks": "Supporting links", "threshold": "Ratification Threshold", - "title": "Governance Actions", - "navTitle": "Live Voting", + "categoryTitle": "Governance Actions", + "title": "Live Voting", "toVote": "To vote", "viewDetails": "View Details", "viewDetailsAndVote": "View Details and Vote", @@ -764,11 +764,8 @@ "title": "This tool is connected to {{networkName}}", "bootstrappingWarning": "Govtool is in the Bootstrapping phase. Some features are not available. Learn more", "maintenanceEnding": { - "title": "⚠️ GovTool needs your support", - "description1": "GovTool wasn’t included in the current Cardano budget.", - "description2": "A 100k ada maintenance grant will sustain essential infrastructure and bug fixes through 2025 — but future development depends on renewed community backing.", - "description3": "Find out what this means and how you can help:", - "linkText": "The future of GovTool" + "title": "🔥 GovTool needs your support - Info Action is submitted", + "description1": "This Info Action outlines the revised GovTool plan and <0>your vote is essential to continue active development and maintenance for the next 12 months, keeping community owned open governance tooling on Cardano." } }, "tooltips": { diff --git a/govtool/frontend/src/pages/Dashboard.tsx b/govtool/frontend/src/pages/Dashboard.tsx index 88648389d..d34cbd877 100644 --- a/govtool/frontend/src/pages/Dashboard.tsx +++ b/govtool/frontend/src/pages/Dashboard.tsx @@ -53,6 +53,11 @@ export const Dashboard = () => { return proposalDiscussionNavItem ?? ""; } + + if (path.startsWith(PATHS.dashboardGovernanceActions)) { + return t("govActions.title"); + } + return findNavItem(CONNECTED_NAV_ITEMS, path) ?? ""; }; @@ -60,7 +65,7 @@ export const Dashboard = () => { items.reduce( (result, item) => result ?? - (targetPath === item.navTo + (targetPath === item.navTo || targetPath.startsWith(`${item.navTo}/`) ? item.label : item.childNavItems ? findNavItem(item.childNavItems, targetPath) diff --git a/tests/govtool-frontend/playwright/lib/helpers/file.ts b/tests/govtool-frontend/playwright/lib/helpers/file.ts index d8145b0a4..d7a787edb 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/file.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/file.ts @@ -1,4 +1,5 @@ -import { readFile, rm, writeFile } from "fs"; +import { faker } from "@faker-js/faker"; +import { readFile, rename, rm, writeFile } from "fs"; const path = require("path"); const mockFolderPath = path.resolve(__dirname, "../_mock"); @@ -20,6 +21,27 @@ export async function createFile(fileName: string, data?: any) { ); } +export async function renameFile(currentPath: string, newPath: string) { + await new Promise((resolve, reject) => + rename(currentPath, newPath, (err) => { + if (err) { + reject(err); + } else { + resolve(); + } + }) + ); +} + +export async function atomicWriteFile(fileName: string, data: any) { + const actualFilePath = `${mockFolderPath}/${fileName}`; + const tempFileName = `${faker.person.firstName()}-${faker.string.uuid()}.json`; + const tmpPath = `${mockFolderPath}/${tempFileName}`; + + await createFile(tempFileName, data); + await renameFile(tmpPath, actualFilePath); +} + export async function getFile(fileName: string): Promise { const data: string = await new Promise((resolve, reject) => readFile(`${mockFolderPath}/${fileName}`, "utf8", (err, data) => { diff --git a/tests/govtool-frontend/playwright/lib/walletManager.ts b/tests/govtool-frontend/playwright/lib/walletManager.ts index 23842a22d..6ec178828 100644 --- a/tests/govtool-frontend/playwright/lib/walletManager.ts +++ b/tests/govtool-frontend/playwright/lib/walletManager.ts @@ -1,6 +1,6 @@ import { StaticWallet } from "@types"; import { LockInterceptor } from "./lockInterceptor"; -import { createFile, getFile } from "@helpers/file"; +import { atomicWriteFile, createFile, getFile } from "@helpers/file"; const path = require("path"); const baseFilePath = path.resolve(__dirname, "./_mock"); @@ -73,7 +73,7 @@ class WalletManager { wallet.givenName = givenName; } }); - await createFile("wallets.json", wallets); + await atomicWriteFile("wallets.json", wallets); } } export default WalletManager.getInstance();