diff --git a/CHANGELOG.md b/CHANGELOG.md index b80f9c5f8..101a6893a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,15 @@ As a minor extension, we also keep a semantic version for the `UNRELEASED` changes. ## [Unreleased] +- Add possibility to vote on behalf of myself - Sole Voter [Issue 119](https://github.com/IntersectMBO/govtool/issues/119) - Create DRep registration page about roles [Issue 205](https://github.com/IntersectMBO/govtool/issues/205) - Create Checkbox component. Improve Field and ControlledField [Issue 177](https://github.com/IntersectMBO/govtool/pull/177) - Vitest unit tests added for utils functions [Issue 81](https://github.com/IntersectMBO/govtool/issues/81) - i18next library added to FE [Issue 80](https://github.com/IntersectMBO/govtool/issues/80) +### Added +- Added `isRegisteredAsSoleVoter` and `wasRegisteredAsSoleVoter` fields to the drep/info response [Issue 212](https://github.com/IntersectMBO/govtool/issues/212) + ### Fixed - Fix make button disble when wallet tries connect [Issue 265](https://github.com/IntersectMBO/govtool/issues/265) - Fix drep voting power calculation [Issue 231](https://github.com/IntersectMBO/govtool/issues/231) @@ -27,6 +31,7 @@ changes. - Fixed get drep voting power incorrectly executed endpoint [Issue 280](https://github.com/IntersectMBO/govtool/issues/280) ### Changed +- `isRegistered` and `wasRegistered` fields in the drep/info endpoint changed to `isRegisteredAsDRep` and `wasRegisteredAsDRep` respectively [Issue 212](https://github.com/IntersectMBO/govtool/issues/212) - Update Cardano-Serialization-Lib to 12.0.0-alpha.16 [Issue 156](https://github.com/IntersectMBO/govtool/issues/156) - Changed and improved working conventions docs, PR template and codeowners file, addressing [Issue 88](https://github.com/IntersectMBO/govtool/issues/88). - Changed Node version from 8.7.1-pre to 8.8.0-pre and DbSync version from sancho-2-3-0 to sancho-4-0-0-fix-config, addressing also [Issue 181](https://github.com/IntersectMBO/govtool/issues/181). diff --git a/govtool/backend/sql/get-drep-info.sql b/govtool/backend/sql/get-drep-info.sql index 341dbabbc..65611fe76 100644 --- a/govtool/backend/sql/get-drep-info.sql +++ b/govtool/backend/sql/get-drep-info.sql @@ -1,6 +1,6 @@ WITH DRepId AS ( SELECT decode(?, 'hex') as raw -), IsRegistered AS ( +), IsRegisteredAsDRep AS ( SELECT (deposit>0) as value, deposit as deposit FROM drep_registration @@ -9,9 +9,10 @@ WITH DRepId AS ( CROSS JOIN DRepId WHERE drep_hash.raw = DRepId.raw and deposit is not null + and drep_registration.voting_anchor_id is not null ORDER BY drep_registration.tx_id DESC LIMIT 1 -), WasRegistered AS ( +), WasRegisteredAsDRep AS ( select (EXISTS ( SELECT * FROM drep_registration @@ -20,9 +21,42 @@ WITH DRepId AS ( CROSS JOIN DRepId WHERE drep_hash.raw = DRepId.raw and drep_registration.deposit > 0 + and drep_registration.voting_anchor_id is not null + )) as value +), IsRegisteredAsSoleVoter AS ( + SELECT (deposit>0) as value, + deposit as deposit + FROM drep_registration + JOIN drep_hash + ON drep_hash.id = drep_registration.drep_hash_id + CROSS JOIN DRepId + WHERE drep_hash.raw = DRepId.raw + and deposit is not null + and drep_registration.voting_anchor_id is null + ORDER BY drep_registration.tx_id DESC + LIMIT 1 +), WasRegisteredAsSoleVoter AS ( + select (EXISTS ( + SELECT * + FROM drep_registration + JOIN drep_hash + ON drep_hash.id = drep_registration.drep_hash_id + CROSS JOIN DRepId + WHERE drep_hash.raw = DRepId.raw + and drep_registration.deposit > 0 + and drep_registration.voting_anchor_id is null )) as value ) -SELECT IsRegistered.value, WasRegistered.value, IsRegistered.deposit -FROM WasRegistered -LEFT JOIN IsRegistered +SELECT + IsRegisteredAsDrep.value, + WasRegisteredAsDRep.value, + IsRegisteredAsSoleVoter.value, + WasRegisteredAsSoleVoter.value, + coalesce(IsRegisteredAsDRep.deposit, IsRegisteredAsSoleVoter.deposit) +FROM WasRegisteredAsDRep +LEFT JOIN IsRegisteredAsDRep +ON 1=1 +LEFT JOIN WasRegisteredAsSoleVoter +ON 1=1 +LEFT JOIN IsRegisteredAsSoleVoter ON 1=1 \ No newline at end of file diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs index ed0b5f193..30557f6c6 100644 --- a/govtool/backend/src/VVA/API.hs +++ b/govtool/backend/src/VVA/API.hs @@ -153,8 +153,10 @@ drepInfo (unHexText -> dRepId) = do CacheEnv {dRepInfoCache} <- asks vvaCache Types.DRepInfo {..} <- cacheRequest dRepInfoCache dRepId $ DRep.getDRepInfo dRepId return $ DRepInfoResponse - { dRepInfoResponseIsRegistered = dRepInfoIsRegistered - , dRepInfoResponseWasRegistered = dRepInfoWasRegistered + { dRepInfoResponseIsRegisteredAsDRep = dRepInfoIsRegisteredAsDRep + , dRepInfoResponseWasRegisteredAsDRep = dRepInfoWasRegisteredAsDRep + , dRepInfoResponseIsRegisteredAsSoleVoter = dRepInfoIsRegisteredAsSoleVoter + , dRepInfoResponseWasRegisteredAsSoleVoter = dRepInfoWasRegisteredAsSoleVoter , dRepInfoResponseDeposit = dRepInfoDeposit } diff --git a/govtool/backend/src/VVA/API/Types.hs b/govtool/backend/src/VVA/API/Types.hs index 208e2b4f4..459e72563 100644 --- a/govtool/backend/src/VVA/API/Types.hs +++ b/govtool/backend/src/VVA/API/Types.hs @@ -375,8 +375,10 @@ instance ToSchema VoteResponse where ?~ toJSON exampleVoteResponse data DRepInfoResponse = DRepInfoResponse - { dRepInfoResponseIsRegistered :: Bool - , dRepInfoResponseWasRegistered :: Bool + { dRepInfoResponseIsRegisteredAsDRep :: Bool + , dRepInfoResponseWasRegisteredAsDRep :: Bool + , dRepInfoResponseIsRegisteredAsSoleVoter :: Bool + , dRepInfoResponseWasRegisteredAsSoleVoter :: Bool , dRepInfoResponseDeposit :: Maybe Integer } deriving (Generic, Show) @@ -384,8 +386,10 @@ deriveJSON (jsonOptions "dRepInfoResponse") ''DRepInfoResponse exampleDRepInfoResponse :: Text exampleDRepInfoResponse = - "{\"isRegistered\": false," - <> "\"wasRegistered\": true," + "{\"isRegisteredAsDRep\": false," + <> "\"wasRegisteredAsDRep\": true," + <> "\"wasRegisteredAsSoleVoter\": true," + <> "\"wasRegisteredAsSoleVoter\": true," <> "\"deposit\": 2000000}" instance ToSchema DRepInfoResponse where diff --git a/govtool/backend/src/VVA/DRep.hs b/govtool/backend/src/VVA/DRep.hs index 0661f0f82..4a29872ea 100644 --- a/govtool/backend/src/VVA/DRep.hs +++ b/govtool/backend/src/VVA/DRep.hs @@ -99,10 +99,12 @@ getDRepInfo getDRepInfo drepId = withPool $ \conn -> do result <- liftIO $ SQL.query conn getDRepInfoSql (SQL.Only drepId) case result of - [(isRegistered, wasRegistered, deposit)] -> + [(isRegisteredAsDRep, wasRegisteredAsDRep, isRegisteredAsSoleVoter, wasRegisteredAsSoleVoter, deposit)] -> return $ DRepInfo - { dRepInfoIsRegistered = fromMaybe False isRegistered - , dRepInfoWasRegistered = fromMaybe False wasRegistered + { dRepInfoIsRegisteredAsDRep = fromMaybe False isRegisteredAsDRep + , dRepInfoWasRegisteredAsDRep = fromMaybe False wasRegisteredAsDRep + , dRepInfoIsRegisteredAsSoleVoter = fromMaybe False isRegisteredAsSoleVoter + , dRepInfoWasRegisteredAsSoleVoter = fromMaybe False wasRegisteredAsSoleVoter , dRepInfoDeposit = deposit } - [] -> return $ DRepInfo False False Nothing \ No newline at end of file + [] -> return $ DRepInfo False False False False Nothing \ No newline at end of file diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs index dc4438d18..4d5d2e0db 100644 --- a/govtool/backend/src/VVA/Types.hs +++ b/govtool/backend/src/VVA/Types.hs @@ -59,8 +59,10 @@ data Vote = Vote } data DRepInfo = DRepInfo - { dRepInfoIsRegistered :: Bool - , dRepInfoWasRegistered :: Bool + { dRepInfoIsRegisteredAsDRep :: Bool + , dRepInfoWasRegisteredAsDRep :: Bool + , dRepInfoIsRegisteredAsSoleVoter :: Bool + , dRepInfoWasRegisteredAsSoleVoter :: Bool , dRepInfoDeposit :: Maybe Integer } diff --git a/govtool/frontend/public/icons/ArrowLeftThin.svg b/govtool/frontend/public/icons/ArrowLeftThin.svg new file mode 100644 index 000000000..38c648693 --- /dev/null +++ b/govtool/frontend/public/icons/ArrowLeftThin.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/govtool/frontend/public/images/GovActionsSoleVoter.png b/govtool/frontend/public/images/GovActionsSoleVoter.png new file mode 100644 index 000000000..69048a4c3 Binary files /dev/null and b/govtool/frontend/public/images/GovActionsSoleVoter.png differ diff --git a/govtool/frontend/src/App.tsx b/govtool/frontend/src/App.tsx index 91dab6356..a282b9e74 100644 --- a/govtool/frontend/src/App.tsx +++ b/govtool/frontend/src/App.tsx @@ -21,6 +21,7 @@ import { UpdatedRepMetadata, GovernanceActionsCategory, DashboardGovernanceActionsCategory, + RetireAsSoleVoter, } from "@pages"; import { callAll, @@ -30,9 +31,10 @@ import { } from "@utils"; import { SetupInterceptors } from "./services"; import { useGetDRepInfo, useWalletConnectionListener } from "./hooks"; +import { RegisterAsSoleVoter } from "./pages/RegisterAsSoleVoter"; export default function App() { - const { enable, setDRep, setIsDrepLoading } = useCardano(); + const { enable, setVoter, setIsDrepLoading } = useCardano(); const navigate = useNavigate(); const { data } = useGetDRepInfo(); const { modal, openModal, modals } = useModal(); @@ -45,11 +47,11 @@ export default function App() { useEffect(() => { setIsDrepLoading(true); - setDRep(data); + setVoter(data); const timer = setTimeout(() => setIsDrepLoading(false), 1000); return () => clearTimeout(timer); - }, [data?.isRegistered]); + }, [data?.isRegisteredAsDRep, data?.isRegisteredAsSoleVoter]); const checkTheWalletIsActive = useCallback(() => { const hrefCondition = @@ -115,6 +117,11 @@ export default function App() { } /> } /> + } + /> + } /> } /> } /> } /> diff --git a/govtool/frontend/src/components/atoms/VotingPowerChips.tsx b/govtool/frontend/src/components/atoms/VotingPowerChips.tsx index 897ec0ce8..ad707be93 100644 --- a/govtool/frontend/src/components/atoms/VotingPowerChips.tsx +++ b/govtool/frontend/src/components/atoms/VotingPowerChips.tsx @@ -13,7 +13,7 @@ import { correctAdaFormat } from "@utils"; import { Tooltip } from "@atoms"; export const VotingPowerChips = () => { - const { dRep, stakeKey, isDrepLoading } = useCardano(); + const { voter, stakeKey, isDrepLoading } = useCardano(); const { dRepVotingPower, isDRepVotingPowerLoading } = useGetDRepVotingPowerQuery(); const { votingPower, powerIsLoading } = @@ -33,7 +33,7 @@ export const VotingPowerChips = () => { alignItems="center" maxHeight={isMobile ? undefined : 48} > - {dRep?.isRegistered && ( + {voter?.isRegisteredAsDRep && ( { {t("votingPower")} )} - {(dRep?.isRegistered && isDRepVotingPowerLoading) || - (!dRep?.isRegistered && powerIsLoading) || + {(voter?.isRegisteredAsDRep && isDRepVotingPowerLoading) || + (!voter?.isRegisteredAsDRep && powerIsLoading) || isDrepLoading ? ( ) : ( @@ -67,7 +67,7 @@ export const VotingPowerChips = () => { sx={{ whiteSpace: "nowrap" }} > ₳{" "} - {dRep?.isRegistered + {voter?.isRegisteredAsDRep ? correctAdaFormat(dRepVotingPower) ?? 0 : correctAdaFormat(votingPower) ?? 0} diff --git a/govtool/frontend/src/components/molecules/ActionCard.tsx b/govtool/frontend/src/components/molecules/ActionCard.tsx index 63fc9eb03..3418c6471 100644 --- a/govtool/frontend/src/components/molecules/ActionCard.tsx +++ b/govtool/frontend/src/components/molecules/ActionCard.tsx @@ -94,7 +94,6 @@ export const ActionCard: FC = ({ ...props }) => { + ); + }, [isMobile]); + + const renderActionButton = useMemo(() => { + return ( + + {actionButtonText ?? t("continue")} + + ); + }, [isLoading, isMobile]); + + return ( + + {renderBackButton} + + {renderActionButton} + + ); +}; diff --git a/govtool/frontend/src/components/molecules/CenteredBoxPageWrapper.tsx b/govtool/frontend/src/components/molecules/CenteredBoxPageWrapper.tsx new file mode 100644 index 000000000..dc9cbe0da --- /dev/null +++ b/govtool/frontend/src/components/molecules/CenteredBoxPageWrapper.tsx @@ -0,0 +1,108 @@ +import { FC, PropsWithChildren } from "react"; +import { Box, Link } from "@mui/material"; + +import { Background, Typography } from "@atoms"; +import { ICONS } from "@consts"; +import { DashboardTopNav } from "@organisms"; +import { useScreenDimension } from "@hooks"; +import { useNavigate } from "react-router-dom"; +import { theme } from "@/theme"; + +interface Props { + pageTitle: string; + backButtonText: string; + backButtonPath: string; + isVotingPowerHidden?: boolean; +} +export const CenteredBoxPageWrapper: FC> = ({ + pageTitle, + backButtonText, + backButtonPath, + isVotingPowerHidden, + children, +}) => { + const { isMobile, screenWidth, pagePadding } = useScreenDimension(); + const navigate = useNavigate(); + const { + palette: { boxShadow2 }, + } = theme; + + return ( + + + + + {isMobile && ( + + + {pageTitle} + + + )} + navigate(backButtonPath)} + > + arrow + + {backButtonText} + + + + + + {children} + + + + + + + ); +}; diff --git a/govtool/frontend/src/components/molecules/DashboardActionCard.tsx b/govtool/frontend/src/components/molecules/DashboardActionCard.tsx index 3d3e9fc26..d394c12a4 100644 --- a/govtool/frontend/src/components/molecules/DashboardActionCard.tsx +++ b/govtool/frontend/src/components/molecules/DashboardActionCard.tsx @@ -2,7 +2,7 @@ import { Box, ButtonProps, Skeleton } from "@mui/material"; import { FC, ReactNode } from "react"; import { CopyButton, LoadingButton, Typography } from "@atoms"; -import { useScreenDimension } from "@hooks"; +import { useScreenDimension, useTranslation } from "@hooks"; import { theme } from "@/theme"; type DashboardActionCardProps = { @@ -18,9 +18,7 @@ type DashboardActionCardProps = { firstButtonIsLoading?: boolean; firstButtonLabel?: string; firstButtonVariant?: ButtonProps["variant"]; - imageHeight?: number; imageURL?: string; - imageWidth?: number; inProgress?: boolean; isLoading?: boolean; secondButtonAction?: () => void; @@ -33,6 +31,7 @@ type DashboardActionCardProps = { export const DashboardActionCard: FC = ({ ...props }) => { + const { t } = useTranslation(); const { cardId, cardTitle, @@ -62,17 +61,15 @@ export const DashboardActionCard: FC = ({ return ( {inProgress && !isLoading && ( = ({ }} > - In progress + {t("inProgress").toLocaleUpperCase()} )} @@ -116,7 +113,7 @@ export const DashboardActionCard: FC = ({ ) : null} {inProgress && !isLoading ? ( - in progress + In Progress ) : null} {description ? ( diff --git a/govtool/frontend/src/components/molecules/VoteActionForm.tsx b/govtool/frontend/src/components/molecules/VoteActionForm.tsx index 3c1645bd2..920021f24 100644 --- a/govtool/frontend/src/components/molecules/VoteActionForm.tsx +++ b/govtool/frontend/src/components/molecules/VoteActionForm.tsx @@ -25,7 +25,7 @@ export const VoteActionForm = ({ const [isContext, setIsContext] = useState(false); const { isMobile, screenWidth } = useScreenDimension(); const { openModal } = useModal(); - const { dRep } = useCardano(); + const { voter } = useCardano(); const { t } = useTranslation(); const { @@ -142,7 +142,7 @@ export const VoteActionForm = ({ /> - {dRep?.isRegistered && ( + {(voter?.isRegisteredAsDRep || voter?.isRegisteredAsSoleVoter) && (