diff --git a/.github/workflows/build-and-deploy-test-stack.yml b/.github/workflows/build-and-deploy-test-stack.yml index a4d3c07a2..01802be3c 100644 --- a/.github/workflows/build-and-deploy-test-stack.yml +++ b/.github/workflows/build-and-deploy-test-stack.yml @@ -29,6 +29,7 @@ jobs: key: ${{ secrets.TEST_STACK_SSH_KEY }} command_timeout: 100m ## Haskell container build takes a lot of time. script: | + set -euo pipefail REPO_URL="https://github.com/${{ github.repository }}" DEST_DIR="$HOME/Documents/govtool" @@ -59,9 +60,8 @@ jobs: # Execute the build-and-deploy.sh script cd $DEST_DIR/tests/test-infrastructure ./build-and-deploy.sh update-images - docker system prune - (docker image ls -q | xargs docker image rm --force ) || echo "Images cleaned-up" - envs: GOVTOOL_TAG, GRAFANA_ADMIN_PASSWORD, GRAFANA_SLACK_RECIPIENT, GRAFANA_SLACK_OAUTH_TOKEN, SENTRY_DSN_BACKEND, GTM_ID, NPMRC_TOKEN, SENTRY_DSN_FRONTEND, PIPELINE_URL, USERSNAP_SPACE_API_KEY, APP_ENV, PDF_API_URL + yes | docker system prune -f || echo "Ignoring system prune eror" + envs: GOVTOOL_TAG, GRAFANA_ADMIN_PASSWORD, GRAFANA_SLACK_RECIPIENT, GRAFANA_SLACK_OAUTH_TOKEN, SENTRY_DSN_BACKEND, GTM_ID, NPMRC_TOKEN, SENTRY_DSN_FRONTEND, PIPELINE_URL, USERSNAP_SPACE_API_KEY, APP_ENV, PDF_API_URL, KUBER_API_KEY env: GOVTOOL_TAG: ${{ github.sha }} GRAFANA_ADMIN_PASSWORD: ${{ secrets.GRAFANA_ADMIN_PASSWORD }} @@ -75,4 +75,4 @@ jobs: USERSNAP_SPACE_API_KEY: ${{ secrets.USERSNAP_SPACE_API_KEY }} APP_ENV: test PDF_API_URL: ${{ secrets.PDF_API_URL }} - KUBER_API_KEY: ${{secrets.KUBER_API_KEY}} + KUBER_API_KEY: ${{ secrets.KUBER_API_KEY }} diff --git a/.github/workflows/merge.yaml b/.github/workflows/merge.yaml index d89b4ee3f..a21f26b48 100644 --- a/.github/workflows/merge.yaml +++ b/.github/workflows/merge.yaml @@ -162,3 +162,11 @@ jobs: docker load -i '/tmp/image-${{ matrix.name }}-${{ env.ENVIRONMENT }}.tar' rm -rf '/tmp/image-${{ matrix.name }}-${{ env.ENVIRONMENT }}.tar' docker push ${{ steps.image_lowercase.outputs.lowercase }}:${{ env.TAG }} + + - name: Add tag as a PR comment + uses: ubie-oss/comment-to-merged-pr-action@v0.3.3 + id: comment-to-merged-pr + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + message: |- + This PR is in the tag: ${{ env.TAG }} , for ${{ matrix.name }} service diff --git a/CHANGELOG.md b/CHANGELOG.md index 9981d01ad..065341b36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,51 @@ changes. - -## [sancho-v1.0.18](https://github.com/IntersectMBO/govtool/releases/tag/sancho-v1.0.18) 2024-09-12 +## [v1.0.20](https://github.com/IntersectMBO/govtool/releases/tag/v1.0.20) 2024-10-03 + +### Added + +- Add useful external links to home page and dashboard [Issue 1995](https://github.com/IntersectMBO/govtool/issues/1995) + +### Fixed + +- Add missing testIds for submitted votes [Issue 1875](https://github.com/IntersectMBO/govtool/issues/1875) +- Provide workaround for iOS for downloading metadata on iOS [Issue 1989](https://github.com/IntersectMBO/govtool/issues/1989) +- Fix infinite loading in DRep Directory [Issue 2090](https://github.com/IntersectMBO/govtool/issues/2090) + +### Changed + +- Change constitutional committee vote totals to be constitutional for yes and unconstitutional for no [Issue 2062](https://github.com/IntersectMBO/govtool/issues/2062) +- Bump @intersect.mbo/pdf-ui to v0.4.0 +- Include @language property in generated jsonld files [Issue 1856](https://github.com/IntersectMBO/govtool/issues/1856) + +### Removed + +- + +## [v1.0.19](https://github.com/IntersectMBO/govtool/releases/tag/v1.0.19) 2024-09-19 + +### Added + +- + +### Fixed + +- Fix private policy link and get support link +- Fixed poor UTxO management when building transactions [Issue 2059](https://github.com/IntersectMBO/govtool/issues/2059) + +### Changed + +- Bump cardano-db-sync 13.5.0.2 [Issue 1945](https://github.com/IntersectMBO/govtool/issues/1945) +- Add Mainnet link to network banner [Issue 2002](https://github.com/IntersectMBO/govtool/issues/2002) +- Bump CSL version to 12.1.0 +- Add random sorting as default sorting for DRep list [Issue 2013](https://github.com/IntersectMBO/govtool/issues/2013) + +### Removed + +- + +## [v1.0.18](https://github.com/IntersectMBO/govtool/releases/tag/v1.0.18) 2024-09-12 ### Added @@ -39,6 +83,7 @@ changes. - Hide Delegate button in DRep list and details if user has already delegated to this DRep [Issue 1982](https://github.com/IntersectMBO/govtool/issues/1982) - Fix condition for disabling voting on different GA types [Issue 2008](https://github.com/IntersectMBO/govtool/issues/2008) - Fix incorrect copy (ex. github) to (e.g. github) [Issue 1748](https://github.com/IntersectMBO/govtool/issues/1748) +- Fix broken translation in DRep Details [Issue 2036](https://github.com/IntersectMBO/govtool/issues/2036) ### Changed diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 9b8e3fafa..66689da9c 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -35,7 +35,7 @@ Frontend is a React application using Vite as a built tool to enhance developmen Direct voter uses following CSL services: - TransactionBuilder - to build the transaction - CertificatesBuilder - to build the delegation certificate - - DrepRegistration - to build the DRep registration certificate + - DRepRegistration - to build the DRep registration certificate - **DRep** - DRep is a Decentralized Representative which has a metadata and can delegate ADA to other DReps. DRep registration and delegation are separate processes. DReps are visible in the DRep directory. @@ -46,9 +46,9 @@ Frontend is a React application using Vite as a built tool to enhance developmen DRep uses following CSL services: - TransactionBuilder - to build the transaction - CertificatesBuilder - to build the DRep registration certificate - - DrepRegistration - to build the DRep registration certificate - - DrepDeregistration - to build the DRep deregistration certificate - - DrepUpdate - to build the DRep update certificate + - DRepRegistration - to build the DRep registration certificate + - DRepDeregistration - to build the DRep deregistration certificate + - DRepUpdate - to build the DRep update certificate **Note** diff --git a/gov-action-loader/frontend/src/views/SpecificLoad.vue b/gov-action-loader/frontend/src/views/SpecificLoad.vue index 05fd0507f..b9cc8744a 100644 --- a/gov-action-loader/frontend/src/views/SpecificLoad.vue +++ b/gov-action-loader/frontend/src/views/SpecificLoad.vue @@ -72,15 +72,17 @@ import config from '../config' - +
+ + +
+ -
- + -
+ @@ -915,6 +917,12 @@ export default { ...(this.DRepDeposit != null ? { DRepDeposit: parseInt(this.DRepDeposit) } : {}), ...(this.DRepActivity != null ? { DRepActivity: parseInt(this.DRepActivity) } : {}), } + proposal_data['script'] = + { + type: "PlutusScriptV3", + description: "", + cborHex: this.guardrailScript + } break } diff --git a/govtool/backend/Dockerfile b/govtool/backend/Dockerfile index c6c0d2827..ba636d0c5 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-1.0.18/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-1.0.20/x/vva-be/build/vva-be/vva-be /usr/local/bin diff --git a/govtool/backend/Dockerfile.base b/govtool/backend/Dockerfile.base index 6dd3c75a3..fcdf388ab 100644 --- a/govtool/backend/Dockerfile.base +++ b/govtool/backend/Dockerfile.base @@ -3,16 +3,60 @@ # process by ensuring it only needs to compile against these dependencies. This # is a common practice in Haskell projects, as it can significantly reduce the # time it takes to build the project. +# +# The reason why we do not use the official haskell image is that the official +# image does not include the necessary dependencies for the project, which are +# unobtainable from the official image. -FROM haskell:9.2.7-buster +FROM ubuntu:24.04 + +# Set the working directory WORKDIR /src +# Set noninteractive mode +ENV DEBIAN_FRONTEND=noninteractive + +# Update package list and install dependencies RUN apt-get update && \ - apt-get install -y wget lsb-release && \ - sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \ + apt-get install -y \ + software-properties-common \ + wget \ + gnupg \ + curl \ + build-essential \ + libncurses-dev \ + libgmp-dev \ + liblzma-dev \ + pkg-config \ + zlib1g-dev \ + xz-utils + +# Install PostgreSQL 14 +RUN sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \ apt-get update && \ apt-get install -y postgresql-14 libpq-dev +# Download and install GHC 9.2.7 +RUN wget https://downloads.haskell.org/~ghc/9.2.7/ghc-9.2.7-x86_64-deb10-linux.tar.xz && \ + tar -xf ghc-9.2.7-x86_64-deb10-linux.tar.xz && \ + cd ghc-9.2.7 && \ + ./configure && \ + make install && \ + cd .. && \ + rm -rf ghc-9.2.7 ghc-9.2.7-x86_64-deb10-linux.tar.xz + +# Install Cabal +RUN wget https://downloads.haskell.org/~cabal/cabal-install-3.6.2.0/cabal-install-3.6.2.0-x86_64-linux-deb10.tar.xz && \ + tar -xf cabal-install-3.6.2.0-x86_64-linux-deb10.tar.xz && \ + mv cabal /usr/local/bin/ && \ + rm cabal-install-3.6.2.0-x86_64-linux-deb10.tar.xz + +# Copy the project files into the container COPY . . -RUN cabal update && cabal configure && cabal install --only-dependencies && rm -rf /src/* + +# Install the project dependencies +RUN cabal update && \ + cabal configure && \ + cabal install --only-dependencies && \ + rm -rf /src/* diff --git a/govtool/backend/Dockerfile.qovery b/govtool/backend/Dockerfile.qovery index 94d4c4fa4..2bc1dddc1 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-1.0.18/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-1.0.20/x/vva-be/build/vva-be/vva-be /usr/local/bin # Expose the necessary port EXPOSE 9876 diff --git a/govtool/backend/sql/list-dreps.sql b/govtool/backend/sql/list-dreps.sql index 917f0641f..2ae88d72b 100644 --- a/govtool/backend/sql/list-dreps.sql +++ b/govtool/backend/sql/list-dreps.sql @@ -30,6 +30,7 @@ SELECT newestRegister.time AS last_register_time, COALESCE(latestDeposit.deposit, 0), non_deregister_voting_anchor.url IS NOT NULL AS has_non_deregister_voting_anchor, + off_chain_vote_fetch_error.fetch_error, off_chain_vote_drep_data.payment_address, off_chain_vote_drep_data.given_name, off_chain_vote_drep_data.objectives, @@ -96,6 +97,7 @@ FROM AND DRepDistr.rn = 1 LEFT JOIN voting_anchor va ON va.id = dr_voting_anchor.voting_anchor_id LEFT JOIN voting_anchor non_deregister_voting_anchor on non_deregister_voting_anchor.id = dr_non_deregister_voting_anchor.voting_anchor_id + LEFT JOIN off_chain_vote_fetch_error ON off_chain_vote_fetch_error.voting_anchor_id = va.id LEFT JOIN off_chain_vote_data ON off_chain_vote_data.voting_anchor_id = va.id LEFT JOIN off_chain_vote_drep_data on off_chain_vote_drep_data.off_chain_vote_data_id = off_chain_vote_data.id CROSS JOIN DRepActivity @@ -138,6 +140,7 @@ GROUP BY newestRegister.time, latestDeposit.deposit, non_deregister_voting_anchor.url, + off_chain_vote_fetch_error.fetch_error, off_chain_vote_drep_data.payment_address, off_chain_vote_drep_data.given_name, off_chain_vote_drep_data.objectives, diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs index 64f6236dd..36c6551bc 100644 --- a/govtool/backend/src/VVA/API.hs +++ b/govtool/backend/src/VVA/API.hs @@ -29,6 +29,7 @@ import Numeric.Natural (Natural) import Servant.API import Servant.Server +import System.Random (randomRIO) import Text.Read (readMaybe) @@ -115,6 +116,7 @@ drepRegistrationToDrep Types.DRepRegistration {..} = dRepType = mapDRepType dRepRegistrationType, dRepLatestTxHash = HexText <$> dRepRegistrationLatestTxHash, dRepLatestRegistrationDate = dRepRegistrationLatestRegistrationDate, + dRepMetadataError = dRepRegistrationMetadataError, dRepPaymentAddress = dRepRegistrationPaymentAddress, dRepGivenName = dRepRegistrationGivenName, dRepObjectives = dRepRegistrationObjectives, @@ -151,8 +153,11 @@ drepList mSearchQuery statuses mSortMode mPage mPageSize = do _ -> filter $ \Types.DRepRegistration {..} -> mapDRepStatus dRepRegistrationStatus `elem` statuses + randomizedOrderList <- mapM (\_ -> randomRIO (0, 1 :: Double)) dreps + let sortDReps = case mSortMode of Nothing -> id + Just Random -> fmap snd . sortOn fst . Prelude.zip randomizedOrderList Just VotingPower -> sortOn $ \Types.DRepRegistration {..} -> Down dRepRegistrationVotingPower Just RegistrationDate -> sortOn $ \Types.DRepRegistration {..} -> diff --git a/govtool/backend/src/VVA/API/Types.hs b/govtool/backend/src/VVA/API/Types.hs index 308c17669..68b23fc94 100644 --- a/govtool/backend/src/VVA/API/Types.hs +++ b/govtool/backend/src/VVA/API/Types.hs @@ -202,7 +202,7 @@ instance ToParamSchema GovernanceActionType where & enum_ ?~ map toJSON (enumFromTo minBound maxBound :: [GovernanceActionType]) -data DRepSortMode = VotingPower | RegistrationDate | Status deriving (Bounded, Enum, Eq, Generic, Read, Show) +data DRepSortMode = Random | VotingPower | RegistrationDate | Status deriving (Bounded, Enum, Eq, Generic, Read, Show) instance FromJSON DRepSortMode where parseJSON (Aeson.String dRepSortMode) = pure $ fromJust $ readMaybe (Text.unpack dRepSortMode) @@ -768,6 +768,7 @@ data DRep , dRepType :: DRepType , dRepLatestTxHash :: Maybe HexText , dRepLatestRegistrationDate :: UTCTime + , dRepMetadataError :: Maybe Text , dRepPaymentAddress :: Maybe Text , dRepGivenName :: Maybe Text , dRepObjectives :: Maybe Text diff --git a/govtool/backend/src/VVA/DRep.hs b/govtool/backend/src/VVA/DRep.hs index fd262bc94..315e9b50a 100644 --- a/govtool/backend/src/VVA/DRep.hs +++ b/govtool/backend/src/VVA/DRep.hs @@ -61,7 +61,7 @@ listDReps = withPool $ \conn -> do results <- liftIO $ SQL.query_ conn listDRepsSql timeZone <- liftIO getCurrentTimeZone return - [ DRepRegistration drepHash drepView url dataHash (floor @Scientific deposit) votingPower status drepType txHash (localTimeToUTC timeZone date) paymentAddress givenName objectives motivations qualifications imageUrl imageHash + [ DRepRegistration drepHash drepView url dataHash (floor @Scientific deposit) votingPower status drepType txHash (localTimeToUTC timeZone date) metadataError paymentAddress givenName objectives motivations qualifications imageUrl imageHash | ( drepHash , drepView , url @@ -73,6 +73,7 @@ listDReps = withPool $ \conn -> do , date , latestDeposit , latestNonDeregisterVotingAnchorWasNotNull + , metadataError , paymentAddress , givenName , objectives diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs index d3965ff34..669102b84 100644 --- a/govtool/backend/src/VVA/Types.hs +++ b/govtool/backend/src/VVA/Types.hs @@ -109,6 +109,7 @@ data DRepRegistration , dRepRegistrationType :: DRepType , dRepRegistrationLatestTxHash :: Maybe Text , dRepRegistrationLatestRegistrationDate :: UTCTime + , dRepRegistrationMetadataError :: Maybe Text , dRepRegistrationPaymentAddress :: Maybe Text , dRepRegistrationGivenName :: Maybe Text , dRepRegistrationObjectives :: Maybe Text diff --git a/govtool/backend/vva-be.cabal b/govtool/backend/vva-be.cabal index b269c0e52..a5a3a4b43 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: 1.0.18 +version: 1.0.20 -- A short (one-line) description of the package. -- synopsis: @@ -103,6 +103,7 @@ library , http-client-tls , vector , async + , random exposed-modules: VVA.Config , VVA.CommandLine diff --git a/govtool/frontend/Dockerfile.qovey b/govtool/frontend/Dockerfile.qovey new file mode 100644 index 000000000..33e83cbe9 --- /dev/null +++ b/govtool/frontend/Dockerfile.qovey @@ -0,0 +1,31 @@ +FROM node:18-alpine as builder + +ARG VITE_APP_ENV='beta' +ARG VITE_BASE_URL +ARG VITE_METADATA_API_URL +ARG VITE_GTM_ID +ARG VITE_NETWORK_FLAG=0 +ARG VITE_SENTRY_DSN +ARG NPMRC_TOKEN +ARG VITE_USERSNAP_SPACE_API_KEY +ARG VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED='true' +ARG VITE_PDF_API_URL + +ENV NODE_OPTIONS=--max_old_space_size=8192 + +WORKDIR /src + +# Set npm configuration settings using environment variables +RUN npm config set @intersect.mbo:registry "https://registry.npmjs.org/" --location=global +RUN npm config set //registry.npmjs.org/:_authToken ${NPMRC_TOKEN} --location=global + +COPY package.json package-lock.json ./ +RUN npm install +COPY . . +RUN npm run build + +FROM nginx:stable-alpine +EXPOSE 80 +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=builder /src/maintenance-page/index.html /usr/share/nginx/html/maintenance.html +COPY --from=builder /src/dist /usr/share/nginx/html diff --git a/govtool/frontend/junit-report.xml b/govtool/frontend/junit-report.xml index 2f3434f92..1396b87e1 100644 --- a/govtool/frontend/junit-report.xml +++ b/govtool/frontend/junit-report.xml @@ -1,230 +1,256 @@ - - - + + + - - - + - + - + + + - + - + - + - + - - + + - + - + - - - + + + - + + + - + - + - + - - - + - - + + - + - + - + - - + + - + - + - - + + - + + + - + - + - + - + - + - + - + - + + + - + - + - + + + - + - + + + - + - - - - + + - + - - + + - - - - - - + + - + - + - + - + + + - + - - + + - + - + - + - + + + - + - - + + - + - + - + + + - - + + - + - + - + - + - - + + - + + + - - + + - + + + - + - + - - + + - + - + + + + +Error: Failed to get PubDRepKey + at [90m/Users/asiadyczka/Desktop/govtool/govtool/frontend/[39msrc/utils/tests/getDRepID.test.ts:46:40 + at [90mfile:///Users/asiadyczka/Desktop/govtool/govtool/frontend/[39mnode_modules/[4m@vitest[24m/runner/dist/index.js:135:14 + at [90mfile:///Users/asiadyczka/Desktop/govtool/govtool/frontend/[39mnode_modules/[4m@vitest[24m/runner/dist/index.js:60:26 + at runTest [90m(file:///Users/asiadyczka/Desktop/govtool/govtool/frontend/[39mnode_modules/[4m@vitest[24m/runner/dist/index.js:781:17[90m)[39m +[90m at processTicksAndRejections (node:internal/process/task_queues:95:5)[39m + at runSuite [90m(file:///Users/asiadyczka/Desktop/govtool/govtool/frontend/[39mnode_modules/[4m@vitest[24m/runner/dist/index.js:909:15[90m)[39m + at runSuite [90m(file:///Users/asiadyczka/Desktop/govtool/govtool/frontend/[39mnode_modules/[4m@vitest[24m/runner/dist/index.js:909:15[90m)[39m + at runFiles [90m(file:///Users/asiadyczka/Desktop/govtool/govtool/frontend/[39mnode_modules/[4m@vitest[24m/runner/dist/index.js:958:5[90m)[39m + at startTests [90m(file:///Users/asiadyczka/Desktop/govtool/govtool/frontend/[39mnode_modules/[4m@vitest[24m/runner/dist/index.js:967:3[90m)[39m + at [90mfile:///Users/asiadyczka/Desktop/govtool/govtool/frontend/[39mnode_modules/[4mvitest[24m/dist/chunks/runtime-runBaseTests.oAvMKtQC.js:116:7 + + - - + + - + - + - - - + - + - + + + - + - - - + + + - - + + - + - - - + - + - + @@ -234,88 +260,112 @@ - - + + - + - - - + - + - - + + - + - - - + - + - + - - - + - + - + - + - - - + - + + + + + + + + + + + - - + + - + - + + + + + - - + + - + - + - + + + + + - - + + - + - + - + + + - + + + + + - - + + - + - + - + - + + + + + + + + + diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 43293d7e5..baaa3e532 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -1,20 +1,20 @@ { "name": "@govtool/frontend", - "version": "1.0.18", + "version": "1.0.20", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@govtool/frontend", - "version": "1.0.18", + "version": "1.0.20", "hasInstallScript": true, "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@emurgo/cardano-serialization-lib-asmjs": "12.0.0-beta.2", + "@emurgo/cardano-serialization-lib-asmjs": "^12.1.0", "@hookform/resolvers": "^3.3.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "^0.3.9", + "@intersect.mbo/pdf-ui": "^0.4.0", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -2901,10 +2901,9 @@ "license": "MIT" }, "node_modules/@emurgo/cardano-serialization-lib-asmjs": { - "version": "12.0.0-beta.2", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-asmjs/-/cardano-serialization-lib-asmjs-12.0.0-beta.2.tgz", - "integrity": "sha512-WVM/TDBb2/Pvq/PxKkoMFz/iuxXfFDuBbD1dem+olg4kqut7x2Fu5SM/iNmKvZF3DbiuA7fQVTabj14i7C9g+w==", - "license": "MIT" + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-asmjs/-/cardano-serialization-lib-asmjs-12.1.0.tgz", + "integrity": "sha512-LVClEWmZmTvaXTBUpSOdyAYr10PlnfEycG1Z5m96aHWN08mdQH/x2LyZxuCjWVSusrG3ZwFnsOYZCHLel7tu4g==" }, "node_modules/@esbuild/aix-ppc64": { "version": "0.19.12", @@ -3551,9 +3550,9 @@ "license": "ISC" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.3.9.tgz", - "integrity": "sha512-KL2bd3Q7EuG0iYCdw19k8uABfr0NYmEaFkgwiXxNOAubGmUeZW/uognbfSl5hWdJIbJ3XZ68GCIW1JhrskgCHg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.4.0.tgz", + "integrity": "sha512-0Wc0fze9zFy7wCGVaDMdWf5eI9flwLHnUDlGQYKEFi7y5DM2uH2rT1OSFw7h2uAnfjZJ0w3pivI1TjPi3HkAIg==", "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 7a3b7cc66..5f7c2705c 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -1,7 +1,7 @@ { "name": "@govtool/frontend", "private": true, - "version": "1.0.18", + "version": "1.0.20", "type": "module", "scripts": { "build": "vite build", @@ -25,10 +25,10 @@ "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@emurgo/cardano-serialization-lib-asmjs": "12.0.0-beta.2", + "@emurgo/cardano-serialization-lib-asmjs": "^12.1.0", "@hookform/resolvers": "^3.3.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "^0.3.9", + "@intersect.mbo/pdf-ui": "^0.4.0", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -109,5 +109,5 @@ "typescript": "^5.0.2" }, "readme": "ERROR: No README data found!", - "_id": "govtool@1.0.18" + "_id": "govtool@1.0.20" } diff --git a/govtool/frontend/src/App.tsx b/govtool/frontend/src/App.tsx index 9b667cb04..553d5295f 100644 --- a/govtool/frontend/src/App.tsx +++ b/govtool/frontend/src/App.tsx @@ -6,7 +6,6 @@ import { PATHS, PDF_PATHS } from "@consts"; import { useCardano, useFeatureFlag, useModal } from "@context"; import { useWalletConnectionListener } from "@hooks"; import { - DashboardCards, DashboardGovernanceActions, DashboardGovernanceActionDetails, } from "@organisms"; @@ -39,6 +38,7 @@ import { } from "@utils"; import { PublicRoute } from "./pages/PublicRoute"; import { TopBanners } from "./components/organisms/TopBanners"; +import { DashboardHome } from "./pages/DashboardHome"; export default () => { const { isProposalDiscussionForumEnabled } = useFeatureFlag(); @@ -104,7 +104,7 @@ export default () => { /> )} }> - } /> + } /> {isProposalDiscussionForumEnabled && ( { it('renders the VotePill component with "yes" vote correctly', () => { const { getByText } = render(); - const voteText = getByText("yes"); + const voteText = getByText("Yes"); expect(voteText).toBeInTheDocument(); expect(voteText.parentNode).toHaveStyle({ borderColor: "#C0E4BA", @@ -15,7 +15,7 @@ describe("VotePill", () => { it('renders the VotePill component with "no" vote correctly', () => { const { getByText } = render(); - const voteText = getByText("no"); + const voteText = getByText("No"); expect(voteText).toBeInTheDocument(); expect(voteText.parentNode).toHaveStyle({ borderColor: "#EDACAC", @@ -25,7 +25,7 @@ describe("VotePill", () => { it('renders the VotePill component with "abstain" vote correctly', () => { const { getByText } = render(); - const voteText = getByText("abstain"); + const voteText = getByText("Abstain"); expect(voteText).toBeInTheDocument(); expect(voteText.parentNode).toHaveStyle({ borderColor: "#99ADDE", diff --git a/govtool/frontend/src/components/atoms/VotePill.tsx b/govtool/frontend/src/components/atoms/VotePill.tsx index de29ac900..53ad58ece 100644 --- a/govtool/frontend/src/components/atoms/VotePill.tsx +++ b/govtool/frontend/src/components/atoms/VotePill.tsx @@ -1,3 +1,4 @@ +import { useTranslation } from "react-i18next"; import { Box, Typography } from "@mui/material"; import { Vote } from "@models"; @@ -6,12 +7,15 @@ export const VotePill = ({ vote, width, maxWidth, + isCC, }: { vote: Vote; width?: number; maxWidth?: number; + isCC?: boolean; }) => { - const VOTE = vote.toLowerCase(); + const { t } = useTranslation(); + const VOTE = vote.toLowerCase() as "yes" | "no" | "abstain"; return ( - {vote} + {t( + `votes.${ + isCC + ? VOTE === "yes" + ? "constitutional" + : vote === "no" + ? "unconstitutional" + : VOTE + : VOTE + }`, + )} ); diff --git a/govtool/frontend/src/components/molecules/DataActionsBar.tsx b/govtool/frontend/src/components/molecules/DataActionsBar.tsx index f66274ced..c2839ae78 100644 --- a/govtool/frontend/src/components/molecules/DataActionsBar.tsx +++ b/govtool/frontend/src/components/molecules/DataActionsBar.tsx @@ -25,7 +25,6 @@ type DataActionsBarProps = { setFiltersOpen?: Dispatch>; setSearchText: Dispatch>; setSortOpen: Dispatch>; - sortingActive: boolean; sortOpen: boolean; sortOptions?: { key: string; @@ -50,7 +49,6 @@ export const DataActionsBar: FC = ({ ...props }) => { setFiltersOpen, setSearchText, setSortOpen, - sortingActive, sortOpen, sortOptions = [], } = props; @@ -94,8 +92,8 @@ export const DataActionsBar: FC = ({ ...props }) => { filtersOpen={filtersOpen} isFiltering={isFiltering} setFiltersOpen={setFiltersOpen} + chosenSorting={chosenSorting} setSortOpen={setSortOpen} - sortingActive={sortingActive} sortOpen={sortOpen} > {filtersOpen && ( diff --git a/govtool/frontend/src/components/molecules/OrderActionsChip.tsx b/govtool/frontend/src/components/molecules/OrderActionsChip.tsx index 006133653..63a233d1e 100644 --- a/govtool/frontend/src/components/molecules/OrderActionsChip.tsx +++ b/govtool/frontend/src/components/molecules/OrderActionsChip.tsx @@ -10,9 +10,9 @@ type Props = { filtersOpen?: boolean; setFiltersOpen?: Dispatch>; chosenFiltersLength?: number; + chosenSorting: string; sortOpen: boolean; setSortOpen: Dispatch>; - sortingActive: boolean; children?: React.ReactNode; isFiltering?: boolean; }; @@ -29,9 +29,9 @@ export const OrderActionsChip = (props: Props) => { filtersOpen, setFiltersOpen = () => {}, chosenFiltersLength = 0, + chosenSorting, sortOpen, setSortOpen, - sortingActive, isFiltering = true, children, } = props; @@ -163,31 +163,12 @@ export const OrderActionsChip = (props: Props) => { sx={{ color: sortOpen ? "white" : "primaryBlue", fontWeight: 500, + whiteSpace: "nowrap", }} > - {t("sort")} + {chosenSorting ? `${t("sortBy")}: ${chosenSorting}` : t("sort")} )} - {!sortOpen && sortingActive && ( - - sorting active - - )} {children} diff --git a/govtool/frontend/src/components/molecules/VoteActionForm.tsx b/govtool/frontend/src/components/molecules/VoteActionForm.tsx index 79e13120b..e7fd496f0 100644 --- a/govtool/frontend/src/components/molecules/VoteActionForm.tsx +++ b/govtool/frontend/src/components/molecules/VoteActionForm.tsx @@ -170,7 +170,7 @@ export const VoteActionForm = ({ name="vote" register={registerInput} setValue={setValue} - title={t("yes")} + title={t("votes.yes")} value="yes" disabled={isInProgress} /> @@ -180,7 +180,7 @@ export const VoteActionForm = ({ name="vote" register={registerInput} setValue={setValue} - title={t("no")} + title={t("votes.no")} value="no" disabled={isInProgress} /> @@ -190,7 +190,7 @@ export const VoteActionForm = ({ name="vote" register={registerInput} setValue={setValue} - title={t("abstain")} + title={t("votes.abstain")} value="abstain" disabled={isInProgress} /> diff --git a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx index 8edd31219..14aa7d0c0 100644 --- a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx +++ b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx @@ -1,7 +1,7 @@ -import { Box, Typography } from "@mui/material"; +import { Box } from "@mui/material"; import { IMAGES } from "@consts"; -import { VotePill } from "@atoms"; +import { Typography, VotePill } from "@atoms"; import { useTranslation } from "@hooks"; import { correctAdaFormat } from "@utils"; import { SubmittedVotesData } from "@models"; @@ -10,27 +10,6 @@ type Props = { votes: SubmittedVotesData; }; -const Vote = ({ - vote, - value, -}: { - vote: "yes" | "no" | "abstain"; - value: string | number; -}) => ( - - - - {value} - - -); - export const VotesSubmitted = ({ votes: { dRepYesVotes, @@ -83,67 +62,95 @@ export const VotesSubmitted = ({ sx={{ display: "flex", flexDirection: "column", - gap: "12px", + gap: 4.5, }} > - - {t("govActions.dReps")} - - - + + - - - - {t("govActions.sPos")} - - - - - - - {t("govActions.ccCommittee")} - - - - - - ); }; + +type VoterType = "ccCommittee" | "dReps" | "sPos"; + +type VotesGroupProps = { + type: VoterType; + yesVotes: number; + noVotes: number; + abstainVotes: number; +}; + +const VotesGroup = ({ + type, + yesVotes, + noVotes, + abstainVotes, +}: VotesGroupProps) => { + const { t } = useTranslation(); + return ( + + + {t(`govActions.${type}`)} + + + + + + ); +}; + +type VoteProps = { + type: VoterType; + vote: VoteType; + value: number; +}; +const Vote = ({ type, vote, value }: VoteProps) => ( + + + + {type === "dReps" ? `₳ ${correctAdaFormat(value)}` : value} + + +); diff --git a/govtool/frontend/src/components/organisms/DRepCard.tsx b/govtool/frontend/src/components/organisms/DRepCard.tsx index 95e611c2e..d63d0b859 100644 --- a/govtool/frontend/src/components/organisms/DRepCard.tsx +++ b/govtool/frontend/src/components/organisms/DRepCard.tsx @@ -118,6 +118,7 @@ export const DRepCard = ({ sx={{ gap: 1, width: "250px", + maxWidth: "100%", "&:hover": { opacity: 0.6, transition: "opacity 0.3s", diff --git a/govtool/frontend/src/components/organisms/DRepDetailsCardHeader.tsx b/govtool/frontend/src/components/organisms/DRepDetailsCardHeader.tsx index 84f33b987..b66da0c83 100644 --- a/govtool/frontend/src/components/organisms/DRepDetailsCardHeader.tsx +++ b/govtool/frontend/src/components/organisms/DRepDetailsCardHeader.tsx @@ -1,4 +1,5 @@ import { useNavigate } from "react-router-dom"; +import { Trans } from "react-i18next"; import { Box, Chip } from "@mui/material"; import { Button } from "@atoms"; @@ -58,13 +59,18 @@ export const DRepDetailsCardHeader = ({ } sx={{ boxShadow: (theme) => theme.shadows[2], diff --git a/govtool/frontend/src/components/organisms/DashboardCards.tsx b/govtool/frontend/src/components/organisms/DashboardCards.tsx index 869faf2a7..210004259 100644 --- a/govtool/frontend/src/components/organisms/DashboardCards.tsx +++ b/govtool/frontend/src/components/organisms/DashboardCards.tsx @@ -32,7 +32,7 @@ export const DashboardCards = () => { alignItems: "center", display: "flex", flex: 1, - height: "100vh", + minHeight: "calc(100vh - 175px)", justifyContent: "center", }} > @@ -42,49 +42,45 @@ export const DashboardCards = () => { } return ( - - = 1728 - ? "repeat(3, minmax(300px, 570px))" - : "repeat(2, minmax(300px, 530px))", - justifyContent: screenWidth < 1024 ? "center" : "flex-start", - px: screenWidth < 640 ? 2 : 5, - py: 3, - rowGap: 3, - }} - > - + = 1728 + ? "repeat(3, minmax(300px, 570px))" + : "repeat(2, minmax(300px, 530px))", + justifyContent: screenWidth < 1024 ? "center" : "flex-start", + rowGap: 3, + }} + > + - + - + - + - - + ); }; diff --git a/govtool/frontend/src/components/organisms/DrawerMobile.tsx b/govtool/frontend/src/components/organisms/DrawerMobile.tsx index 59be2af86..824799c27 100644 --- a/govtool/frontend/src/components/organisms/DrawerMobile.tsx +++ b/govtool/frontend/src/components/organisms/DrawerMobile.tsx @@ -22,7 +22,7 @@ export const DrawerMobile = ({ const { t } = useTranslation(); const onClickHelp = () => - openInNewTab("https://docs.gov.tools/support/get-help-in-discord"); + openInNewTab("https://docs.gov.tools/support/"); return ( { const { openFeedbackWindow } = useUsersnapApi(); const onClickHelp = () => - openInNewTab("https://docs.gov.tools/support/get-help-in-discord"); + openInNewTab("https://docs.gov.tools/support"); const onClickPrivacyPolicy = () => - openInNewTab("https://docs.gov.tools/legal/privacy-policy"); + openInNewTab("https://docs.intersectmbo.org/legal/policies-and-conditions/privacy-policy"); const onClickTermOfService = () => openInNewTab("https://docs.intersectmbo.org/legal/policies-and-conditions/terms-of-use"); diff --git a/govtool/frontend/src/components/organisms/HomeCards.tsx b/govtool/frontend/src/components/organisms/HomeCards.tsx index 76dd9167f..59c97b252 100644 --- a/govtool/frontend/src/components/organisms/HomeCards.tsx +++ b/govtool/frontend/src/components/organisms/HomeCards.tsx @@ -5,14 +5,13 @@ import { Box } from "@mui/material"; import { IMAGES, PATHS, PDF_PATHS } from "@consts"; import { useFeatureFlag, useModal } from "@context"; import { ActionCard } from "@molecules"; -import { useScreenDimension, useTranslation } from "@hooks"; +import { useTranslation } from "@hooks"; import { openInNewTab } from "@utils"; export const HomeCards = () => { const { isProposalDiscussionForumEnabled } = useFeatureFlag(); const navigate = useNavigate(); const { openModal } = useModal(); - const { screenWidth } = useScreenDimension(); const { t } = useTranslation(); const openWalletModal = useCallback( @@ -66,23 +65,8 @@ export const HomeCards = () => { {/* DELEGATE CARD */} diff --git a/govtool/frontend/src/components/organisms/TopBanners.tsx b/govtool/frontend/src/components/organisms/TopBanners.tsx index c63f68bf5..332a2c440 100644 --- a/govtool/frontend/src/components/organisms/TopBanners.tsx +++ b/govtool/frontend/src/components/organisms/TopBanners.tsx @@ -1,9 +1,15 @@ import { Box, Link, Typography } from "@mui/material"; -import { Trans } from "react-i18next"; +import { Trans, useTranslation } from "react-i18next"; import { useAppContext } from "@/context"; export const TopBanners = () => { - const { isMainnet, networkName, isInBootstrapPhase } = useAppContext(); + const { isMainnet, networkName, isInBootstrapPhase, isAppInitializing } = + useAppContext(); + const { t } = useTranslation(); + + if (isAppInitializing) { + return null; + } return ( @@ -14,13 +20,26 @@ export const TopBanners = () => { backgroundColor: "#BBE3F0", px: 2, py: 0.5, - textAlign: "center", + display: "flex", + justifyContent: "center", + gap: 1, }} data-testid="system-network-name" > - {networkName} + {`${t("network")}: ${networkName}`} + + + | + + {t("goToMainnet")} + )} diff --git a/govtool/frontend/src/components/organisms/UsefulLinks.tsx b/govtool/frontend/src/components/organisms/UsefulLinks.tsx new file mode 100644 index 000000000..90bc1a740 --- /dev/null +++ b/govtool/frontend/src/components/organisms/UsefulLinks.tsx @@ -0,0 +1,91 @@ +import { Box, Link } from "@mui/material"; + +import { useTranslation } from "@hooks"; +import { Typography } from "../atoms"; +import { ICONS } from "@/consts"; +import { Card } from "../molecules"; + +const LINKS = { + ccPortal: { + url: "https://constitution.gov.tools", + }, + intersectWebsite: { + url: "https://www.intersectmbo.org/", + }, +} as const; + +type Props = { + align?: "left" | "center"; +}; + +export const UsefulLinks = ({ align = "left" }: Props) => { + const { t } = useTranslation(); + + return ( +
+ + {t("usefulLinks.title")} + + + {Object.entries(LINKS).map(([key, { url }]) => ( + + + {t(`usefulLinks.${key as keyof typeof LINKS}.title`)} + + + {t(`usefulLinks.${key as keyof typeof LINKS}.description`)} + + + + {t(`usefulLinks.${key as keyof typeof LINKS}.link`)} + + link + + + ))} + +
+ ); +}; diff --git a/govtool/frontend/src/consts/dRepActions/jsonContext.ts b/govtool/frontend/src/consts/dRepActions/jsonContext.ts index 5b7886211..a077f153e 100644 --- a/govtool/frontend/src/consts/dRepActions/jsonContext.ts +++ b/govtool/frontend/src/consts/dRepActions/jsonContext.ts @@ -2,6 +2,7 @@ export const CIP_119 = "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0119/README.md#"; export const DREP_CONTEXT = { + "@language": "en-us", CIP100: "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0100/README.md#", CIP119: CIP_119, diff --git a/govtool/frontend/src/consts/dRepDirectory/sorting.ts b/govtool/frontend/src/consts/dRepDirectory/sorting.ts index 9604e9c61..0e6c4d016 100644 --- a/govtool/frontend/src/consts/dRepDirectory/sorting.ts +++ b/govtool/frontend/src/consts/dRepDirectory/sorting.ts @@ -1,4 +1,8 @@ export const DREP_DIRECTORY_SORTING = [ + { + key: "Random", + label: "Random", + }, { key: "RegistrationDate", label: "Registration date", diff --git a/govtool/frontend/src/context/dataActionsBar.tsx b/govtool/frontend/src/context/dataActionsBar.tsx index eab02a6f6..5bb3acf32 100644 --- a/govtool/frontend/src/context/dataActionsBar.tsx +++ b/govtool/frontend/src/context/dataActionsBar.tsx @@ -27,7 +27,6 @@ interface DataActionsBarContextType { setFiltersOpen: Dispatch>; setSearchText: Dispatch>; setSortOpen: Dispatch>; - sortingActive: boolean; sortOpen: boolean; } @@ -102,7 +101,6 @@ const DataActionsBarProvider: FC = ({ children }) => { setFiltersOpen, setSearchText, setSortOpen, - sortingActive: Boolean(chosenSorting), sortOpen, }), [ diff --git a/govtool/frontend/src/context/wallet.tsx b/govtool/frontend/src/context/wallet.tsx index 61349b695..5916471af 100644 --- a/govtool/frontend/src/context/wallet.tsx +++ b/govtool/frontend/src/context/wallet.tsx @@ -12,9 +12,9 @@ import { CertificatesBuilder, Credential, DRep, - DrepDeregistration, - DrepRegistration, - DrepUpdate, + DRepDeregistration, + DRepRegistration, + DRepUpdate, Ed25519KeyHash, GovernanceActionId, LinearFee, @@ -24,11 +24,9 @@ import { TransactionBuilder, TransactionBuilderConfigBuilder, TransactionHash, - TransactionOutput, TransactionUnspentOutput, TransactionUnspentOutputs, TransactionWitnessSet, - Value, VoteDelegation, Voter, VotingBuilder, @@ -45,7 +43,7 @@ import { ProtocolParamUpdate, ParameterChangeAction, Costmdls, - DrepVotingThresholds, + DRepVotingThresholds, ExUnitPrices, UnitInterval, ExUnits, @@ -116,7 +114,7 @@ type ProtocolParamsUpdate = { costModels: Costmdls; drepDeposit: string; drepInactivityPeriod: number; - drepVotingThresholds: DrepVotingThresholds; + drepVotingThresholds: DRepVotingThresholds; executionCosts: ExUnitPrices; expansionRate: UnitInterval; governanceActionDeposit: string; @@ -508,7 +506,6 @@ const CardanoProvider = (props: Props) => { resourceId, type, votingBuilder, - voter, }: BuildSignSubmitConwayCertTxArgs) => { await checkIsMaintenanceOn(); const isPendingTx = isPendingTransaction(); @@ -545,31 +542,10 @@ const CardanoProvider = (props: Props) => { !walletApi ) throw new Error(t("errors.checkIsWalletConnected")); - const shelleyOutputAddress = Address.from_bech32( - walletState.usedAddress, - ); const shelleyChangeAddress = Address.from_bech32( walletState.changeAddress, ); - // Add output of 1 ada to the address of our wallet - let outputValue = BigNum.from_str("1000000"); - - if ( - (type === "retireAsDrep" || - type === "retireAsDirectVoter" || - (type === "delegate" && voter?.isRegisteredAsSoleVoter)) && - voter?.deposit - ) { - outputValue = outputValue.checked_add( - BigNum.from_str(voter?.deposit?.toString()), - ); - } - - txBuilder.add_output( - TransactionOutput.new(shelleyOutputAddress, Value.new(outputValue)), - ); - const utxos = await getUtxos(walletApi); if (!utxos) { @@ -577,9 +553,8 @@ const CardanoProvider = (props: Props) => { } // Find the available UTXOs in the wallet and use them as Inputs for the transaction const txUnspentOutputs = await getTxUnspentOutputs(utxos); - - // Use UTxO selection strategy 3 const changeConfig = ChangeConfig.new(shelleyChangeAddress); + // Use UTxO selection strategy 3 try { txBuilder.add_inputs_from_and_change( txUnspentOutputs, @@ -669,7 +644,7 @@ const CardanoProvider = (props: Props) => { stakeCred = Credential.from_keyhash(stakeKeyHash); } else { stakeCred = Credential.from_keyhash(stakeKeyHash); - const stakeKeyRegCert = StakeRegistration.new_with_coin( + const stakeKeyRegCert = StakeRegistration.new_with_explicit_deposit( stakeCred, BigNum.from_str(`${epochParams.key_deposit}`), ); @@ -717,14 +692,14 @@ const CardanoProvider = (props: Props) => { if (cip95MetadataURL && cip95MetadataHash) { const anchor = generateAnchor(cip95MetadataURL, cip95MetadataHash); // Create cert object using one Ada as the deposit - dRepRegCert = DrepRegistration.new_with_anchor( + dRepRegCert = DRepRegistration.new_with_anchor( dRepCred, BigNum.from_str(`${epochParams?.drep_deposit}`), anchor, ); } else { console.error(t("errors.notUsingAnchor")); - dRepRegCert = DrepRegistration.new( + dRepRegCert = DRepRegistration.new( dRepCred, BigNum.from_str(`${epochParams?.drep_deposit}`), ); @@ -753,9 +728,9 @@ const CardanoProvider = (props: Props) => { if (cip95MetadataURL && cip95MetadataHash) { const anchor = generateAnchor(cip95MetadataURL, cip95MetadataHash); // Create cert object using one Ada as the deposit - dRepUpdateCert = DrepUpdate.new_with_anchor(dRepCred, anchor); + dRepUpdateCert = DRepUpdate.new_with_anchor(dRepCred, anchor); } else { - dRepUpdateCert = DrepUpdate.new(dRepCred); + dRepUpdateCert = DRepUpdate.new(dRepCred); } return Certificate.new_drep_update(dRepUpdateCert); } catch (e) { @@ -773,7 +748,7 @@ const CardanoProvider = (props: Props) => { const dRepKeyHash = Ed25519KeyHash.from_hex(dRepID); const dRepCred = Credential.from_keyhash(dRepKeyHash); - const dRepRetirementCert = DrepDeregistration.new( + const dRepRetirementCert = DRepDeregistration.new( dRepCred, BigNum.from_str(voterDeposit), ); @@ -799,7 +774,9 @@ const CardanoProvider = (props: Props) => { // Get wallet's DRep key const dRepKeyHash = Ed25519KeyHash.from_hex(dRepID); // Vote things - const voter = Voter.new_drep(Credential.from_keyhash(dRepKeyHash)); + const voter = Voter.new_drep_credential( + Credential.from_keyhash(dRepKeyHash), + ); const govActionId = GovernanceActionId.new( // placeholder TransactionHash.from_hex(txHash), diff --git a/govtool/frontend/src/hooks/queries/useGetDRepListQuery.ts b/govtool/frontend/src/hooks/queries/useGetDRepListQuery.ts index 3eb2a956f..562eb4930 100644 --- a/govtool/frontend/src/hooks/queries/useGetDRepListQuery.ts +++ b/govtool/frontend/src/hooks/queries/useGetDRepListQuery.ts @@ -33,11 +33,11 @@ export const useGetDRepListInfiniteQuery = ( pendingTransaction.registerAsDrep || pendingTransaction.retireAsDirectVoter || pendingTransaction.retireAsDrep - )?.transactionHash, - filters, - searchPhrase, - sorting, - status, + )?.transactionHash ?? 'noPendingTransaction', + filters.length ? filters : "", + searchPhrase ?? "", + sorting ?? "", + status?.length ? status : "", ], async ({ pageParam = 0 }) => getDRepList({ diff --git a/govtool/frontend/src/i18n/locales/en.ts b/govtool/frontend/src/i18n/locales/en.ts index 8fb7cc171..ad5aa48a5 100644 --- a/govtool/frontend/src/i18n/locales/en.ts +++ b/govtool/frontend/src/i18n/locales/en.ts @@ -268,8 +268,8 @@ export const en = { meAsDRep: "This DRep ID is connected to your wallet", myDelegation: "You have delegated ₳ {{ada}} to:", myDelegationToYourself: - "You have delegated ₳ {{ada}} to yourself:", - myDRep: "You have delegated ₳{{ada}} to this DRep.", + "You have delegated ₳ {{ada}} to yourself", + myDRep: "You have delegated ₳ {{ada}} to this DRep", listTitle: "Find a DRep", noConfidenceDefaultDescription: "Select this to signal no confidence in the current constitutional committee by voting NO on every proposal and voting YES to no confidence proposals", @@ -823,8 +823,27 @@ export const en = { notVerifiable: "Data Not Verifiable", incorrectFormat: "Data Formatted Incorrectly", }, + votes: { + abstain: "Abstain", + constitutional: "Constitutional", + no: "No", + unconstitutional: "Unconstitutional", + yes: "Yes", + }, + usefulLinks: { + title: "Useful links", + ccPortal: { + title: "Check the Constitutional Committee Portal", + description: "See Interim Cardano Constitution and Constitutional committee votes rationales", + link: "CC Portal", + }, + 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", + link: "Intersect website", + }, + }, about: "About", - abstain: "Abstain", addLink: "+ Add link", back: "Back", backToDashboard: "Back to dashboard", @@ -843,6 +862,7 @@ export const en = { feedback: "Feedback", filter: "Filter", goBack: "Go back", + goToMainnet: "Go to Mainnet", here: "here", info: "Info", inProgress: "In Progress", @@ -852,7 +872,7 @@ export const en = { moreInformation: "More information", myDRepId: "My DRep ID:", nextStep: "Next step", - no: "No", + network: "Network", ok: "Ok", optional: "Optional", register: "Register", @@ -870,7 +890,6 @@ export const en = { thisLink: "this link", viewDetails: "View details", votingPower: "Voting power", - yes: "Yes", yourself: "Yourself", }, }; diff --git a/govtool/frontend/src/models/api.ts b/govtool/frontend/src/models/api.ts index 4988fed43..541c4e77c 100644 --- a/govtool/frontend/src/models/api.ts +++ b/govtool/frontend/src/models/api.ts @@ -102,6 +102,7 @@ export enum DRepStatus { } export enum DRepListSort { + Random = "Random", VotingPower = "VotingPower", RegistrationDate = "RegistrationDate", Status = "Status", diff --git a/govtool/frontend/src/pages/DRepDirectoryContent.tsx b/govtool/frontend/src/pages/DRepDirectoryContent.tsx index ee75f09b7..c86b90744 100644 --- a/govtool/frontend/src/pages/DRepDirectoryContent.tsx +++ b/govtool/frontend/src/pages/DRepDirectoryContent.tsx @@ -1,4 +1,4 @@ -import { FC } from "react"; +import { FC, useEffect } from "react"; import { Trans, useTranslation } from "react-i18next"; import { Box, CircularProgress } from "@mui/material"; @@ -44,7 +44,12 @@ export const DRepDirectoryContent: FC = ({ const { dRepID: myDRepId, pendingTransaction, stakeKey } = useCardano(); const { t } = useTranslation(); const { debouncedSearchText, ...dataActionsBarProps } = useDataActionsBar(); - const { chosenFilters, chosenSorting } = dataActionsBarProps; + const { chosenFilters, chosenSorting, setChosenSorting } = + dataActionsBarProps; + + useEffect(() => { + if (!chosenSorting) setChosenSorting(DRepListSort.Random); + }, [chosenSorting, setChosenSorting]); const { delegate, isDelegating } = useDelegateTodRep(); @@ -62,9 +67,12 @@ export const DRepDirectoryContent: FC = ({ ); const myDrep = myDRepList?.[0]; - const { dRepData: yourselfDRepList } = useGetDRepListInfiniteQuery({ - searchPhrase: myDRepId, - }); + const { dRepData: yourselfDRepList } = useGetDRepListInfiniteQuery( + { + searchPhrase: myDRepId, + }, + { enabled: !!myDRepId }, + ); const yourselfDRep = !!isConnected && @@ -84,6 +92,7 @@ export const DRepDirectoryContent: FC = ({ status: chosenFilters as DRepStatus[], }, { + enabled: !!chosenSorting, keepPreviousData: true, }, ); diff --git a/govtool/frontend/src/pages/DashboardHome.tsx b/govtool/frontend/src/pages/DashboardHome.tsx new file mode 100644 index 000000000..c2ef40f71 --- /dev/null +++ b/govtool/frontend/src/pages/DashboardHome.tsx @@ -0,0 +1,25 @@ +import { Box } from "@mui/material"; + +import { DashboardCards } from "@organisms"; +import { UsefulLinks } from "@/components/organisms/UsefulLinks"; +import { useScreenDimension } from "@/hooks"; + +export const DashboardHome = () => { + const { screenWidth } = useScreenDimension(); + + return ( + + + + + ); +}; diff --git a/govtool/frontend/src/pages/Home.tsx b/govtool/frontend/src/pages/Home.tsx index b78921194..8af4eefdf 100644 --- a/govtool/frontend/src/pages/Home.tsx +++ b/govtool/frontend/src/pages/Home.tsx @@ -7,10 +7,13 @@ import { PATHS } from "@consts"; import { useCardano } from "@context"; 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(); useEffect(() => { if (isEnabled && getItemFromLocalStorage(`${WALLET_LS_KEY}_stake_key`)) { @@ -23,7 +26,19 @@ export const Home = () => { - + + + + {/* FIXME: Footer should be on top of the layout. Should not be rerendered across the pages */}