diff --git a/.github/workflows/merge.yaml b/.github/workflows/merge.yaml
index e0591e18..f37b64fa 100644
--- a/.github/workflows/merge.yaml
+++ b/.github/workflows/merge.yaml
@@ -134,7 +134,7 @@ jobs:
NEXT_PUBLIC_USERSNAP_SPACE_API_KEY=${{ secrets.QA_NEXT_PUBLIC_USERSNAP_SPACE_API_KEY }}
NEXT_PUBLIC_USERSNAP_PROJECT_API_KEY=${{ secrets.QA_NEXT_PUBLIC_USERSNAP_PROJECT_API_KEY }}
NEXT_PUBLIC_HIDDEN_USERSNAP_PROJECT_IDS=${{ secrets.QA_NEXT_PUBLIC_HIDDEN_USERSNAP_PROJECT_IDS }}
- NEXT_PUBLIC_IS_MAINNET=${{ secrets.QA_NEXT_PUBLIC_IS_MAINNET }}
+ NEXT_PUBLIC_IS_MAINNET=${{ secrets.QA_NEXT_PUBLIC_IS_MAINNET }}g
- name: Scan Docker image with Dockle
id: dockle
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index 8856e2dc..55a52173 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -117,7 +117,7 @@ jobs:
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
outputs: type=docker,dest=/tmp/image-${{ matrix.name }}-${{ github.sha }}-pr.tar
- build-args: |
+ build-args: |
NEXT_PUBLIC_API_URL=${{ secrets.QA_NEXT_PUBLIC_API_URL }}
NEXT_PUBLIC_USERSNAP_SPACE_API_KEY=${{ secrets.QA_NEXT_PUBLIC_USERSNAP_SPACE_API_KEY }}
NEXT_PUBLIC_USERSNAP_PROJECT_API_KEY=${{ secrets.QA_NEXT_PUBLIC_USERSNAP_PROJECT_API_KEY }}
diff --git a/backend/src/users/api/request/update-user.request.ts b/backend/src/users/api/request/update-user.request.ts
index 77d72556..a9cc6b81 100644
--- a/backend/src/users/api/request/update-user.request.ts
+++ b/backend/src/users/api/request/update-user.request.ts
@@ -15,7 +15,7 @@ export class UpdateUserRequest {
})
@MinLength(2, { message: `Minimum character length is 2` })
@MaxLength(30, { message: `Maximum character length is 30` })
- @Matches(/^[a-zA-Z0-9_.\s]+$/, {
+ @Matches(/^[a-zA-Z0-9_|.\s]+$/, {
message: `Name can't contain special characters & symbols`,
})
@IsString()
diff --git a/frontend/messages/de.json b/frontend/messages/de.json
index e68e972d..b068c1a6 100644
--- a/frontend/messages/de.json
+++ b/frontend/messages/de.json
@@ -30,6 +30,7 @@
"govAction": "Governance Action",
"govActionCategoryShort": "GA Category",
"voted": "Voted",
+ "time": "Time",
"rationale": "Rationale",
"actionTitle": "Show more",
"notAvailable": "Not Available",
@@ -225,29 +226,15 @@
"previewRationale": {
"headline": "Rationale",
"description": "Please update rationale for your vote on specific governance action.",
- "noRationaleUrl": "A rationale has not been provided for this vote",
"rationaleLink": "Rationale link",
+ "rationale": "Rationale",
+ "notAvailable": "Not Available",
+ "governanceActionStatus": "Governance Action Status",
"governanceActionCategory": "Governance Action Category",
"governanceActionId": "Governance Action ID",
"voted": "Voted",
- "submissionDate": "Submission date",
- "expiryDate": "Expiry date",
- "voteSubmissionDate": "Vote submission date",
- "tooltips": {
- "expiryDate": {
- "heading": "Expiry Date",
- "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": {
- "heading": "Submission Date",
- "paragraphOne": "The date when the governance action was submitted on-chain.",
- "vote": {
- "heading": "Vote Submission Date",
- "paragraphOne": "The date when the vote was submitted on-chain."
- }
- }
- },
+ "submissionDate": "GA submitted on:",
+ "expiryDate": "GA expiration date:",
"alerts": {
"error": "Error fetching rationale data"
}
diff --git a/frontend/messages/en.json b/frontend/messages/en.json
index 053776d0..b4a9f141 100644
--- a/frontend/messages/en.json
+++ b/frontend/messages/en.json
@@ -30,6 +30,7 @@
"govAction": "Governance Action",
"govActionCategoryShort": "GA Category",
"voted": "Voted",
+ "time": "Time",
"rationale": "Rationale",
"actionTitle": "Show more",
"notAvailable": "Not Available",
@@ -225,29 +226,15 @@
"previewRationale": {
"headline": "Rationale",
"description": "Please update rationale for your vote on specific governance action.",
- "noRationaleUrl": "A rationale has not been provided for this vote",
"rationaleLink": "Rationale link",
+ "rationale": "Rationale",
+ "notAvailable": "Not Available",
+ "governanceActionStatus": "Governance Action Status",
"governanceActionCategory": "Governance Action Category",
"governanceActionId": "Governance Action ID",
"voted": "Voted",
- "submissionDate": "Submission date",
- "expiryDate": "Expiry date",
- "voteSubmissionDate": "Vote submission date",
- "tooltips": {
- "expiryDate": {
- "heading": "Expiry Date",
- "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": {
- "heading": "Submission Date",
- "paragraphOne": "The date when the governance action was submitted on-chain.",
- "vote": {
- "heading": "Vote Submission Date",
- "paragraphOne": "The date when the vote was submitted on-chain."
- }
- }
- },
+ "submissionDate": "GA submitted on:",
+ "expiryDate": "GA expiration date:",
"alerts": {
"error": "Error fetching rationale data"
}
diff --git a/frontend/src/app/[locale]/loading.tsx b/frontend/src/app/[locale]/loading.tsx
new file mode 100644
index 00000000..a58d77b5
--- /dev/null
+++ b/frontend/src/app/[locale]/loading.tsx
@@ -0,0 +1,16 @@
+import { Box, CircularProgress } from "@mui/material";
+
+export default function CenteredLoading() {
+ return (
+
+
+
+ );
+}
diff --git a/frontend/src/components/atoms/modal/ModalWrapper.tsx b/frontend/src/components/atoms/modal/ModalWrapper.tsx
index eb39bd05..36f882f1 100644
--- a/frontend/src/components/atoms/modal/ModalWrapper.tsx
+++ b/frontend/src/components/atoms/modal/ModalWrapper.tsx
@@ -1,11 +1,11 @@
"use client";
-import { SxProps, styled } from "@mui/material/styles";
+import { styled, SxProps } from "@mui/material/styles";
-import { customPalette, ICONS } from "@consts";
-import { callAll } from "@utils";
import { useModal } from "@/context";
import { useScreenDimension } from "@/lib/hooks";
+import { customPalette, ICONS } from "@consts";
+import { callAll } from "@utils";
type ModalVariant = "modal" | "popup" | "wide";
interface Props {
@@ -27,7 +27,7 @@ export const ModalWrapper = ({
icon,
scrollable,
hideCloseButton = true,
- onClose,
+ onClose
}: Props) => {
const { closeModal } = useModal();
const { isMobile } = useScreenDimension();
@@ -79,6 +79,7 @@ export const BaseWrapper = styled("div")<{
transform: translate(-50%, -50%);
overflow-y: ${({ scrollable }) => scrollable && "scroll"};
overflow-x: hidden;
+ scrollbar-width: ${({ scrollable }) => (scrollable ? "auto" : "none")};
@media (max-width: ${700}px) {
overflow: scroll;
}
diff --git a/frontend/src/components/organisms/Constitution/Constitution.tsx b/frontend/src/components/organisms/Constitution/Constitution.tsx
index d7ad6454..601a8151 100644
--- a/frontend/src/components/organisms/Constitution/Constitution.tsx
+++ b/frontend/src/components/organisms/Constitution/Constitution.tsx
@@ -16,6 +16,7 @@ import {
Heading1,
Heading2,
Heading3,
+ Heading5,
ListItem,
NavDrawerDesktop,
Paragraph,
@@ -66,6 +67,7 @@ export function Constitution({ constitution, metadata }: ConstitutionProps) {
h1: Heading1,
h2: Heading2,
h3: Heading3,
+ h5: Heading5,
p: Paragraph,
li: ListItem,
code: Code,
diff --git a/frontend/src/components/organisms/Constitution/ConstitutionSidebar.tsx b/frontend/src/components/organisms/Constitution/ConstitutionSidebar.tsx
index 1a4608da..dae59467 100644
--- a/frontend/src/components/organisms/Constitution/ConstitutionSidebar.tsx
+++ b/frontend/src/components/organisms/Constitution/ConstitutionSidebar.tsx
@@ -28,7 +28,7 @@ export const ConstitutionSidebar = ({ tableOfContents, metadata }) => {
justifyContent="left"
padding={2}
pt={{ xxs: 0, md: 2 }}
- px={{ xxs: 2, md: 3 }}
+ px={{ xxs: 1, md: 2 }}
flexWrap="nowrap"
>
{/*
@@ -45,7 +45,7 @@ export const ConstitutionSidebar = ({ tableOfContents, metadata }) => {
container
direction="column"
width={{ xxs: "100%", lg: "340px" }}
- px={{ xxs: 1, md: 1 }}
+ px={{ xxs: 0, md: 0 }}
>
{/* {tab === "revisions" ? (
diff --git a/frontend/src/components/organisms/Constitution/MDXComponents.tsx b/frontend/src/components/organisms/Constitution/MDXComponents.tsx
index 5291e7e7..e7304e57 100644
--- a/frontend/src/components/organisms/Constitution/MDXComponents.tsx
+++ b/frontend/src/components/organisms/Constitution/MDXComponents.tsx
@@ -79,6 +79,21 @@ export const Heading3 = ({ children, id }) => (
>
);
+export const Heading5 = ({ children }) => (
+
+ {children}
+
+);
export const Paragraph = ({ children, id }) => (
<>
@@ -105,7 +120,8 @@ export const ListItem = ({ children, id }) => (
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
- justifyContent: "center"
+ justifyContent: "center",
+ wordBreak: "break-all"
}}
>
{children}
@@ -131,6 +147,7 @@ export const Code = ({ children }) => (
export const TABLE_OF_CONTENTS_WRAPPER_STYLE_PROPS = {
backgroundColor: customPalette.neutralWhite,
borderRadius: "16px",
+ padding: "12px",
"& ol.toc-level": {
margin: 0
},
diff --git a/frontend/src/components/organisms/Constitution/TOCAccordion.tsx b/frontend/src/components/organisms/Constitution/TOCAccordion.tsx
index 6d0336b6..9af16484 100644
--- a/frontend/src/components/organisms/Constitution/TOCAccordion.tsx
+++ b/frontend/src/components/organisms/Constitution/TOCAccordion.tsx
@@ -1,5 +1,4 @@
"use client";
-import { customPalette } from "@/constants";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import {
Accordion,
@@ -35,7 +34,6 @@ export const TocAccordion = ({ children }) => {
elevation={0}
sx={{
boxShadow: "none",
- padding: 0,
"&:before": {
display: "none"
},
@@ -48,12 +46,7 @@ export const TocAccordion = ({ children }) => {
sx={{
borderRadius: "30px",
minHeight: "56px",
- "&:hover": {
- backgroundColor: customPalette.accordionBg
- },
- "&.Mui-expanded": {
- backgroundColor: customPalette.accordionBg
- },
+ padding: 0,
"& a": {
"&:active": {
pointerEvents: "none" // disables the href activation on click but keep tooltip showing
@@ -100,11 +93,9 @@ export const TocAccordion = ({ children }) => {
alignItems: "center",
justifyContent: "left",
listStyleType: "none",
- padding: "0 16px",
+ padding: 0,
width: "100%",
- "&:hover": {
- backgroundColor: customPalette.accordionBg
- },
+
"& li": {
display: "flex",
alignItems: "center"
@@ -117,7 +108,7 @@ export const TocAccordion = ({ children }) => {
void;
- disabled: boolean;
}
/**
* TOCLink Component
@@ -19,7 +18,7 @@ interface Props {
* @param {Function} props.callback - A callback function to be executed after the link is clicked.
*/
-const TOCLink = ({ href, children, callback, disabled }: Props) => {
+const TOCLink = ({ href, children, callback }: Props) => {
const [isActive, setIsActive] = useState(false);
const [isTruncated, setIsTruncated] = useState(false);
const linkRef = useRef(null);
@@ -68,7 +67,13 @@ const TOCLink = ({ href, children, callback, disabled }: Props) => {
}, [children]);
return (
-
+
{
style={{
color: customPalette.textBlack,
textDecoration: "none",
- maxWidth: "260px",
+ maxWidth: "292px",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
- display: "inline-block"
+ display: "inline-block",
+ backgroundColor: isActive ? customPalette.accordionBg : undefined,
+ borderRadius: "30px",
+ padding: "0 16px",
+ boxSizing: "border-box"
}}
>
{children}
diff --git a/frontend/src/components/organisms/Constitution/TOCNested.tsx b/frontend/src/components/organisms/Constitution/TOCNested.tsx
index 1f671c24..a6afbbfa 100644
--- a/frontend/src/components/organisms/Constitution/TOCNested.tsx
+++ b/frontend/src/components/organisms/Constitution/TOCNested.tsx
@@ -1,4 +1,3 @@
-import { customPalette } from "@/constants";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import { Accordion, AccordionDetails, AccordionSummary } from "@mui/material";
@@ -23,12 +22,8 @@ export const TocNested = ({ headings }) => {
sx={{
borderRadius: "30px",
minHeight: "56px",
- "&:hover": {
- backgroundColor: customPalette.accordionBg
- },
- "&.Mui-expanded": {
- backgroundColor: customPalette.accordionBg
- },
+ padding: 0,
+
"& a": {
"&:active": {
pointerEvents: "none" // disables the href activation on click but keep tooltip showing
diff --git a/frontend/src/components/organisms/Footer/Footer.tsx b/frontend/src/components/organisms/Footer/Footer.tsx
index 6ca6885f..cf22f562 100644
--- a/frontend/src/components/organisms/Footer/Footer.tsx
+++ b/frontend/src/components/organisms/Footer/Footer.tsx
@@ -66,14 +66,29 @@ export const Footer = ({
variant="caption"
data-testid="footer-privacy-policy-hyperlink"
>
- {t("privacyPolicy")}
+
+ {t("privacyPolicy")}
+
+
- {t("termsOfService")}
+
+ {t("termsOfService")}
+
{!userSession && showSignIn && (
diff --git a/frontend/src/components/organisms/LatestUpdates.tsx b/frontend/src/components/organisms/LatestUpdates.tsx
index 0e8e9396..5d4e97d4 100644
--- a/frontend/src/components/organisms/LatestUpdates.tsx
+++ b/frontend/src/components/organisms/LatestUpdates.tsx
@@ -47,7 +47,9 @@ export const LatestUpdates = ({
end_time: action.gov_action_proposal_end_time,
vote: action.value,
reasoning_title: action.reasoning_title,
- rationale_url: action.rationale_url
+ rationale_url: action.rationale_url,
+ status: action.gov_action_proposal_status,
+ title: action.gov_action_proposal_title
}
}
});
diff --git a/frontend/src/components/organisms/Modals/GovActionModal.tsx b/frontend/src/components/organisms/Modals/GovActionModal.tsx
index f6ae2723..7efe73f6 100644
--- a/frontend/src/components/organisms/Modals/GovActionModal.tsx
+++ b/frontend/src/components/organisms/Modals/GovActionModal.tsx
@@ -1,178 +1,178 @@
-"use client";
-
-import { useSnackbar } from "@/context/snackbar";
-import { getGovernanceMetadata } from "@/lib/api";
-import {
- Button,
- ModalHeader,
- ModalWrapper,
- OutlinedLightButton,
- Typography
-} from "@atoms";
-import { customPalette, IMAGES } from "@consts";
-import { useModal } from "@context";
-import { useScreenDimension } from "@hooks";
-import { CopyCard, Loading } from "@molecules";
-import { Box } from "@mui/material";
-import { GovActionModalState } from "@organisms";
-import {
- formatDisplayDate,
- getProposalTypeLabel,
- getShortenedGovActionId,
- isResponseErrorI
-} from "@utils";
-import { useTranslations } from "next-intl";
-import { useEffect, useState } from "react";
-import { GovActionMetadata } from "../types";
-
-export const GovActionModal = () => {
- const t = useTranslations("Modals");
- const { closeModal, state } = useModal();
- const [govAction, setGovAction] = useState();
- const { addErrorAlert } = useSnackbar();
- const { isMobile } = useScreenDimension();
-
- const onClick = () => {
- closeModal();
- };
-
- useEffect(() => {
- async function fetchGAMetadata(id) {
- const meta = await getGovernanceMetadata(id);
- if (isResponseErrorI(meta)) {
- addErrorAlert(meta.error);
- closeModal();
- } else {
- setGovAction(meta);
- }
- }
-
- if (state.id) {
- fetchGAMetadata(state.id);
- }
- }, [state.id]);
-
- return (
-
- {govAction ? (
- <>
-
-
-
-
-
- {govAction.title}
-
-
-
-
- {govAction?.abstract}
-
-
-
-
-
-
- {t("govActionModal.govActionCategory")}
-
-
- {getProposalTypeLabel(govAction.type)}
-
-
-
-
- {t("govActionModal.gaStatus")}
-
-
-
- {govAction.status}
-
-
-
-
-
-
- {t("govActionModal.submitTime")}
-
-
- {formatDisplayDate(govAction.submit_time)}
-
-
- {govAction.end_time && (
-
-
- {t("govActionModal.endTime")}
-
-
- {formatDisplayDate(govAction.end_time)}
-
-
- )}
-
-
-
- >
- ) : (
-
- )}
-
- );
-};
+"use client";
+
+import { useSnackbar } from "@/context/snackbar";
+import { getGovernanceMetadata } from "@/lib/api";
+import {
+ Button,
+ ModalHeader,
+ ModalWrapper,
+ OutlinedLightButton,
+ Typography
+} from "@atoms";
+import { customPalette, IMAGES } from "@consts";
+import { useModal } from "@context";
+import { useScreenDimension } from "@hooks";
+import { CopyCard, Loading } from "@molecules";
+import { Box } from "@mui/material";
+import { GovActionModalState } from "@organisms";
+import {
+ formatDisplayDate,
+ getProposalTypeLabel,
+ getShortenedGovActionId,
+ isResponseErrorI
+} from "@utils";
+import { useTranslations } from "next-intl";
+import { useEffect, useState } from "react";
+import { GovActionMetadata } from "../types";
+
+export const GovActionModal = () => {
+ const t = useTranslations("Modals");
+ const { closeModal, state } = useModal();
+ const [govAction, setGovAction] = useState();
+ const { addErrorAlert } = useSnackbar();
+ const { isMobile } = useScreenDimension();
+
+ const onClick = () => {
+ closeModal();
+ };
+
+ useEffect(() => {
+ async function fetchGAMetadata(id) {
+ const meta = await getGovernanceMetadata(id);
+ if (isResponseErrorI(meta)) {
+ addErrorAlert(meta.error);
+ closeModal();
+ } else {
+ setGovAction(meta);
+ }
+ }
+
+ if (state.id) {
+ fetchGAMetadata(state.id);
+ }
+ }, [state.id]);
+
+ return (
+
+ {govAction ? (
+ <>
+
+
+
+
+
+ {govAction.title}
+
+
+
+
+ {govAction?.abstract}
+
+
+
+
+
+
+ {t("govActionModal.govActionCategory")}
+
+
+ {getProposalTypeLabel(govAction.type)}
+
+
+
+
+ {t("govActionModal.gaStatus")}
+
+
+
+ {govAction.status}
+
+
+
+
+
+
+ {t("govActionModal.submitTime")}
+
+
+ {formatDisplayDate(govAction.submit_time)}
+
+
+ {govAction.end_time && (
+
+
+ {t("govActionModal.endTime")}
+
+
+ {formatDisplayDate(govAction.end_time)}
+
+
+ )}
+
+
+
+ >
+ ) : (
+
+ )}
+
+ );
+};
diff --git a/frontend/src/components/organisms/Modals/PreviewReasoningModal.tsx b/frontend/src/components/organisms/Modals/PreviewReasoningModal.tsx
index 592ad93f..8edb512d 100644
--- a/frontend/src/components/organisms/Modals/PreviewReasoningModal.tsx
+++ b/frontend/src/components/organisms/Modals/PreviewReasoningModal.tsx
@@ -1,116 +1,61 @@
"use client";
import { CopyPill } from "@/components/molecules";
-import { Reasoning } from "@/components/molecules/Reasoning";
import { useSnackbar } from "@/context/snackbar";
-import { ReasoningResponseI } from "@/lib/requests";
+import { getGovernanceMetadata } from "@/lib/api";
import {
Button,
ModalHeader,
ModalWrapper,
OutlinedLightButton,
- Tooltip,
Typography,
VotePill
} from "@atoms";
-import { customPalette, IMAGES } from "@consts";
+import { IMAGES } from "@consts";
import { useModal } from "@context";
import { useScreenDimension } from "@hooks";
-import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
import { Box } from "@mui/material";
import {
formatDisplayDate,
getProposalTypeLabel,
- getShortenedGovActionId
+ getShortenedGovActionId,
+ isResponseErrorI
} from "@utils";
import { useTranslations } from "next-intl";
import { useEffect, useState } from "react";
-import { OpenPreviewReasoningModal } from "../types";
+import { GovActionMetadata, OpenPreviewReasoningModal } from "../types";
-interface Reasoning extends Omit {
- comment: string;
-}
export const PreviewReasoningModal = () => {
const t = useTranslations("Modals");
const {
closeModal,
state: { govAction, onActionClick, actionTitle }
} = useModal();
- const [reasoning, setReasoning] = useState(null);
const onClose = () => {
closeModal();
};
const { isMobile } = useScreenDimension();
const { addErrorAlert } = useSnackbar();
+ const [govMetadata, setGovMetadata] = useState();
useEffect(() => {
- // async function fetchData(id: string) {
- // const response = await getReasoningData(id);
- // if (isResponseErrorI(response)) {
- // if (response.statusCode !== 404 && response.statusCode !== 401) {
- // addErrorAlert(response.error);
- // closeModal();
- // }
- // } else {
- // const contents = JSON.parse(response.contents);
- // setReasoning({ ...response, comment: contents.body.comment });
- // }
- // }
- // if (govAction.reasoning_title && govAction.reasoning_comment) {
- // setReasoning({
- // comment: govAction.reasoning_comment,
- // title: govAction.reasoning_title,
- // });
- // } else if (govAction?.id) {
- // fetchData(govAction.id);
- // }
- }, [govAction?.id]);
+ async function fetchGAMetadata(id) {
+ const meta = await getGovernanceMetadata(id);
+ if (isResponseErrorI(meta)) {
+ addErrorAlert(meta.error);
+ closeModal();
+ } else {
+ setGovMetadata(meta);
+ }
+ }
+
+ if (govAction.id) {
+ fetchGAMetadata(govAction.id);
+ }
+ }, [govAction.id]);
+
+ if (!govMetadata) return null;
- const DisplayDate = ({
- bgColor = "#D6E2FF80",
- title,
- date,
- tooltipHeading,
- tooltipParagraph,
- dataTestId
- }) => {
- return (
-
-
- {title}
-
-
- {formatDisplayDate(date)}
-
-
-
-
-
- );
- };
return (
@@ -122,62 +67,30 @@ export const PreviewReasoningModal = () => {
src={IMAGES.pastelAddMember}
/>
-
- {t("previewRationale.headline")}
+
+ {govAction.title}
- {!govAction.rationale_url && (
-
- {t("previewRationale.noRationaleUrl")}
-
- )}
- {/* {reasoning && (
-
+
-
-
- )} */}
- {govAction.rationale_url && (
-
-
- {t("previewRationale.rationaleLink")}
-
-
-
- )}
+ {govMetadata.abstract}
+
+
{t("previewRationale.governanceActionId")}
@@ -202,6 +115,19 @@ export const PreviewReasoningModal = () => {
{getProposalTypeLabel(govAction.type)}
+
+
+ {t("previewRationale.governanceActionStatus")}
+
+
+
+ {govAction.status}
+
+
+
{govAction.vote && (
@@ -216,44 +142,73 @@ export const PreviewReasoningModal = () => {
)}
-
- {govAction.submit_time && (
-
- )}
- {govAction.vote_submit_time && (
-
+
+ {t("previewRationale.rationale")}
+
+ {govAction.rationale_url ? (
+
+ ) : (
+
+ {t("previewRationale.notAvailable")}
+
)}
- dataTestId="vote-submit-date-row"
- />
+
+
+
+ {govMetadata.submit_time && (
+
+
+ {t("previewRationale.submissionDate")}
+
+
+ {formatDisplayDate(govAction.submit_time)}
+
+
)}
- {govAction.end_time && (
-
+ {govMetadata?.end_time && (
+
+
+ {t("previewRationale.expiryDate")}
+
+
+ {formatDisplayDate(govAction.end_time)}
+
+
)}
-
{
const { state, closeModal } = useModal();
@@ -35,7 +35,7 @@ export const SignUpModal = () => {
handleSubmit,
formState: { errors },
control,
- setValue,
+ setValue
} = useForm();
useEffect(() => {
@@ -99,8 +99,16 @@ export const SignUpModal = () => {
label={t("signUp.fields.displayName.label")}
errors={errors}
control={control}
- {...register("name", { required: "Display name is required" })}
+ {...register("name", {
+ pattern: {
+ value: PATTERNS.username,
+ message:
+ "Display name can only contain letters, numbers, spaces, underscores, pipes, and periods"
+ },
+ required: "Display name is required"
+ })}
/>
+
{
{t("signUp.fields.hotCredential.label")}
{
{...register("hotAddress", {
pattern: {
value: PATTERNS.hotAddress,
- message: "Entered value does not match the expected format",
- },
+ message: "Entered value does not match the expected format"
+ }
})}
/>
{
fileSize: (file) =>
!file ||
file.size / (1024 * 1024) < PROFILE_PICTURE_MAX_FILE_SIZE ||
- "The file size should be less than 5MB",
- },
+ "The file size should be less than 5MB"
+ }
})}
>
{t("signUp.fields.upload")}
{state.showCloseButton ? (
diff --git a/frontend/src/components/organisms/MyActions.tsx b/frontend/src/components/organisms/MyActions.tsx
index 3fea4807..d957e4b2 100644
--- a/frontend/src/components/organisms/MyActions.tsx
+++ b/frontend/src/components/organisms/MyActions.tsx
@@ -55,13 +55,15 @@ export const MyActions = ({
type: action.gov_action_proposal_type,
submit_time: null, //todo, update BE response
end_time: action.gov_action_proposal_end_time,
- vote_submit_time: action.vote_submit_time,
- vote: action.value
+ vote: action.value,
+ reasoning_title: action.reasoning_title,
+ rationale_url: action.rationale_url,
+ status: action.gov_action_proposal_status,
+ title: action.gov_action_proposal_title
}
}
});
};
-
const params: Record = {
search: searchText || null,
govActionType:
diff --git a/frontend/src/components/organisms/TopNavigation/DrawerMobile.tsx b/frontend/src/components/organisms/TopNavigation/DrawerMobile.tsx
index a2dfcfce..9dc54c89 100644
--- a/frontend/src/components/organisms/TopNavigation/DrawerMobile.tsx
+++ b/frontend/src/components/organisms/TopNavigation/DrawerMobile.tsx
@@ -1,5 +1,4 @@
"use client";
-import React from "react";
import { Box, Grid, IconButton, SwipeableDrawer } from "@mui/material";
@@ -10,7 +9,7 @@ export const DrawerMobile = ({
setIsDrawerOpen,
children,
sx = {},
- rowGap = 4,
+ rowGap = 4
}) => {
return (
setIsDrawerOpen(true)}
open={isDrawerOpen}
PaperProps={{
- sx: { width: "100%", ...sx },
+ sx: { width: "100%", ...sx }
}}
>
setIsDrawerOpen(false)}>
diff --git a/frontend/src/components/organisms/VotesTable/VotesTableRow.tsx b/frontend/src/components/organisms/VotesTable/VotesTableRow.tsx
index cdbe3723..3d154229 100644
--- a/frontend/src/components/organisms/VotesTable/VotesTableRow.tsx
+++ b/frontend/src/components/organisms/VotesTable/VotesTableRow.tsx
@@ -2,14 +2,11 @@
import { VotesTableI } from "@/lib/requests";
import { Button, OutlinedLightButton, Typography, VotePill } from "@atoms";
-import { customPalette, ICONS } from "@consts";
-import { useModal } from "@context";
+import { customPalette } from "@consts";
import { Card, TableDivider, UserAvatar, UserBasicInfo } from "@molecules";
import { Box, Grid } from "@mui/material";
-import { getProposalTypeLabel, truncateText } from "@utils";
+import { formatDisplayDate, getProposalTypeLabel, truncateText } from "@utils";
import { useTranslations } from "next-intl";
-import Image from "next/image";
-import { GovActionModalState } from "../types";
interface Props {
votes: VotesTableI;
@@ -25,25 +22,16 @@ export const VotesTableRow = ({
onActionClick
}: Props) => {
const t = useTranslations("LatestUpdates");
- const { openModal } = useModal();
const {
user_name,
user_address,
user_photo_url,
value,
rationale_url,
- gov_action_proposal_id,
gov_action_proposal_title,
- gov_action_proposal_type
+ gov_action_proposal_type,
+ vote_submit_time
} = votes;
- const openGAModal = () => {
- openModal({
- type: "govActionModal",
- state: {
- id: gov_action_proposal_id
- }
- });
- };
return (
{t("govAction")}
-
- }
- >
+
{gov_action_proposal_title
? truncateText(gov_action_proposal_title, 40)
: t("notAvailable")}
-
+
@@ -181,12 +156,39 @@ export const VotesTableRow = ({
>
{t("voted")}
-
+
+
+
+
+
+
+ {t("time")}
+
+
+
+ {formatDisplayDate(vote_submit_time)}
+
+
+
+
@@ -201,7 +203,7 @@ export const VotesTableRow = ({
>
diff --git a/frontend/src/components/organisms/types.ts b/frontend/src/components/organisms/types.ts
index b4ab0e0a..53a6beeb 100644
--- a/frontend/src/components/organisms/types.ts
+++ b/frontend/src/components/organisms/types.ts
@@ -95,10 +95,7 @@ export interface GovActionMetadata {
}
export interface OpenPreviewReasoningModal {
- govAction: Pick<
- GovernanceActionTableI,
- "id" | "type" | "submit_time" | "end_time" | "tx_hash"
- > & {
+ govAction: Partial & {
vote?: Vote;
vote_submit_time?: string;
reasoning_title?: string;
diff --git a/frontend/src/constants/forms.ts b/frontend/src/constants/forms.ts
index 57d9c30b..6869c80d 100644
--- a/frontend/src/constants/forms.ts
+++ b/frontend/src/constants/forms.ts
@@ -8,29 +8,29 @@ import { isAdminRole, isSuperAdminRole } from "@/lib/utils/roles";
export const permissionsList: PermissionsListObject[] = [
{
label: "Manage constitutional members",
- value: "manage_cc_members",
+ value: "manage_cc_members"
},
{
label: "Upload Constitution version",
- value: "add_constitution_version",
- },
+ value: "add_constitution_version"
+ }
];
//Roles that admin can append when creating new members through Admin Dashboard in application
export const adminAddMemberRoleList: RoleListObject[] = [
{
label: "Constitutional member",
- value: "user",
- },
+ value: "user"
+ }
];
//Roles that super admin can append when creating new members through Admin Dashboard in application
export const superAdminAddMemberRoleList: RoleListObject[] = [
{
label: "Admin",
- value: "admin",
+ value: "admin"
},
- ...adminAddMemberRoleList,
+ ...adminAddMemberRoleList
];
//All roles available in application
@@ -38,12 +38,12 @@ export const rolesList: RoleListObject[] = [
...superAdminAddMemberRoleList,
{
label: "Super admin",
- value: "super_admin",
+ value: "super_admin"
},
{
label: "Alumni",
- value: "alumni",
- },
+ value: "alumni"
+ }
];
export const getRoleDropdownList = (userRole) => {
@@ -57,5 +57,6 @@ export const getRoleDropdownList = (userRole) => {
export const PROFILE_PICTURE_MAX_FILE_SIZE = 5;
export const PATTERNS = {
- hotAddress: /^[a-fA-F0-9]{56}$/,
+ username: /^[a-zA-Z0-9_|.\s]+$/,
+ hotAddress: /^[a-fA-F0-9]{56}$/
};
diff --git a/frontend/src/context/modal.tsx b/frontend/src/context/modal.tsx
index 9dc72377..9b29b39d 100644
--- a/frontend/src/context/modal.tsx
+++ b/frontend/src/context/modal.tsx
@@ -43,8 +43,8 @@ export type ModalType =
| "addReasoningModal"
| "reasoningLinkModal"
| "previewReasoningModal"
- | "govActionModal"
- | "switchUserStatus";
+ | "switchUserStatus"
+ | "govActionModal";
const modals: Record = {
none: {
diff --git a/ipfs-service/src/bullmq/bullmq.module.ts b/ipfs-service/src/bullmq/bullmq.module.ts
index a616bf14..3de0a31d 100644
--- a/ipfs-service/src/bullmq/bullmq.module.ts
+++ b/ipfs-service/src/bullmq/bullmq.module.ts
@@ -14,6 +14,11 @@ import { ExpressAdapter } from "@bull-board/express";
host: configService.getOrThrow("REDIS_HOST"),
port: configService.getOrThrow("REDIS_PORT"),
password: configService.getOrThrow("REDIS_PASSWORD"),
+ connectTimeout: 20000,
+ reconnectOnError: (err) => {
+ const targetErrors = ['READONLY', 'ETIMEDOUT', 'ECONNRESET'];
+ return targetErrors.some(targetError => err.message.includes(targetError));
+ },
...(configService.get('REDIS_TLS') === 'false' ? {} : { tls: {} }),
},
}),