From 420bd1b29688820b5e2412c8d3a4e86fa7578bf9 Mon Sep 17 00:00:00 2001 From: Adam Tomaszczyk Date: Sun, 26 Oct 2025 18:53:01 +0100 Subject: [PATCH 1/6] Refactor live voting proposal/votes filtering - frontend --- .../DashboardGovernanceActionsVotedOn.tsx | 42 +++------------ .../organisms/GovernanceActionsToVote.tsx | 53 +++---------------- .../src/hooks/queries/useGetDRepVotesQuery.ts | 1 + 3 files changed, 14 insertions(+), 82 deletions(-) diff --git a/govtool/frontend/src/components/organisms/DashboardGovernanceActionsVotedOn.tsx b/govtool/frontend/src/components/organisms/DashboardGovernanceActionsVotedOn.tsx index 3c145d98d..be82ad668 100644 --- a/govtool/frontend/src/components/organisms/DashboardGovernanceActionsVotedOn.tsx +++ b/govtool/frontend/src/components/organisms/DashboardGovernanceActionsVotedOn.tsx @@ -8,7 +8,6 @@ import { useTranslation, } from "@hooks"; import { ValidatedGovernanceVotedOnCard } from "@organisms"; -import { getFullGovActionId } from "@utils"; type DashboardGovernanceActionsVotedOnProps = { searchPhrase?: string; @@ -25,41 +24,14 @@ export const DashboardGovernanceActionsVotedOn = ({ const { data: votes, - areDRepVotesLoading, - isFetching, + areDRepVotesLoading } = useGetDRepVotesQuery(chosenFilters, chosenSorting, searchPhrase); - // TODO: Filtering here is some kind of craziness. It should be done on the backend. - const filteredData = useMemo(() => { - if (!votes?.length) return []; - if (!searchPhrase) return votes.flatMap((entry) => entry.actions); + const proposals = useMemo(() => + votes.flatMap((entry) => entry.actions), + [votes, searchPhrase, pendingTransaction.vote]); - const lowerSearch = searchPhrase.toLowerCase(); - - return votes.flatMap((entry) => - entry.actions.filter((action) => { - const hash = getFullGovActionId( - action.proposal.txHash, - action.proposal.index, - ).toLowerCase(); - - const title = action.proposal.title?.toLowerCase() || ""; - const motivation = action.proposal.motivation?.toLowerCase() || ""; - const rationale = action.proposal.rationale?.toLowerCase() || ""; - const abstract = action.proposal.abstract?.toLowerCase() || ""; - - return ( - hash.includes(lowerSearch) || - title.includes(lowerSearch) || - motivation.includes(lowerSearch) || - rationale.includes(lowerSearch) || - abstract.includes(lowerSearch) - ); - }), - ); - }, [votes, searchPhrase, pendingTransaction.vote]); - - return areDRepVotesLoading || isFetching ? ( + return areDRepVotesLoading ? ( @@ -69,7 +41,7 @@ export const DashboardGovernanceActionsVotedOn = ({ {t("govActions.youHaventVotedYet")} - ) : !filteredData?.length ? ( + ) : !proposals?.length ? ( {t("govActions.noResultsForTheSearch")} @@ -81,7 +53,7 @@ export const DashboardGovernanceActionsVotedOn = ({ screenWidth < 420 ? "290px" : isMobile ? "324px" : "350px" }, 1fr))`} > - {filteredData.map((item) => ( + {proposals.map((item) => ( removeDuplicatedProposals(proposals), - [proposals, voter?.isRegisteredAsDRep, isProposalsFetchingNextPage], + [proposals, isProposalsFetchingNextPage], ); - // TODO: Filtering here is some kind of craziness. It should be done on the backend. - const filteredProposals = useMemo(() => { - const list = mappedData ?? []; - if (!votes?.length) return list; - - const proposalsFromVotes = votes - .flatMap((v) => v?.actions ?? []) - .map((a) => a?.proposal) - .filter(Boolean); - - const votedKeys = new Set( - proposalsFromVotes - .map((p) => ({ - id: p?.id ?? p?.id, - tx: p?.txHash ?? p?.txHash, - })) - .filter(({ id, tx }) => Boolean(id && tx)) - .map(({ id, tx }) => `${id}:${tx}`), - ); - - if (votedKeys.size === 0) return list; - - return list.filter((p) => { - const id = p?.id ?? p?.id; - const tx = p?.txHash ?? p?.txHash; - if (!id || !tx) return true; - return !votedKeys.has(`${id}:${tx}`); - }); - }, [mappedData, voter?.isRegisteredAsDRep, isProposalsFetchingNextPage]); - return ( <> - {!filteredProposals || + {!mappedProposals || isEnableLoading || - isProposalsLoading || - areDRepVotesLoading || - isFetchingVotes ? ( + isProposalsLoading ? ( - ) : !filteredProposals?.length ? ( + ) : !mappedProposals?.length ? ( {t("govActions.noResultsForTheSearch")} @@ -125,7 +84,7 @@ export const GovernanceActionsToVote = ({ screenWidth < 420 ? "290px" : isMobile ? "324px" : "350px" }, 1fr))`} > - {filteredProposals.map((item) => ( + {mappedProposals.map((item) => ( { From ffb086340e229d862e506c5cebaa166d27050476 Mon Sep 17 00:00:00 2001 From: Miro Date: Mon, 27 Oct 2025 12:11:24 +0100 Subject: [PATCH 2/6] Refactor live voting proposal/votes filtering - backend --- govtool/backend/src/VVA/API.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs index 7c4b3f519..c0a594f7a 100644 --- a/govtool/backend/src/VVA/API.hs +++ b/govtool/backend/src/VVA/API.hs @@ -434,7 +434,8 @@ listProposals selectedTypes sortMode mPage mPageSize mDrepRaw mSearchQuery = do proposalsToRemove <- case mDrepRaw of Nothing -> return [] Just drepId -> - map (voteParamsProposalId . voteResponseVote) + map (\VoteResponse { voteResponseProposal = ProposalResponse { proposalResponseTxHash, proposalResponseIndex } } -> + (proposalResponseTxHash, proposalResponseIndex)) <$> getVotes drepId [] Nothing Nothing CacheEnv {proposalListCache} <- asks vvaCache @@ -444,8 +445,8 @@ listProposals selectedTypes sortMode mPage mPageSize mDrepRaw mSearchQuery = do mappedSortedAndFilteredProposals <- mapSortAndFilterProposals selectedTypes sortMode proposals let filteredProposals = filter - ( \p@ProposalResponse {proposalResponseId} -> - proposalResponseId `notElem` proposalsToRemove + (\p@ProposalResponse { proposalResponseTxHash, proposalResponseIndex } -> + (proposalResponseTxHash, proposalResponseIndex) `notElem` proposalsToRemove && isProposalSearchedFor mSearchQuery p ) mappedSortedAndFilteredProposals From 3ff7344d6a783ec328816a964969c08de0505700 Mon Sep 17 00:00:00 2001 From: Aaron Boyle Date: Tue, 18 Nov 2025 10:41:59 +0000 Subject: [PATCH 3/6] updates CODEOWNERS --- CODEOWNERS | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 92b6221ef..0d19d3436 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,22 +1,22 @@ # GovTool Project Codeowners # These owners will be the default owners for everything in the repository. -* @Ryun1 @MSzalowski +* @Ryun1 @aaboyle878 # Frontend assets templates -govtool/frontend/* @MSzalowski -*.tsx @MSzalowski -*.ts @MSzalowski -*.css @MSzalowski +govtool/frontend/* +*.tsx +*.ts +*.css # Backend -govtool/backend/* @MSzalowski @jankun4 +govtool/backend/* # DevOps -.github/workflows/* @placek @adgud -config/govtool/* @placek @adgud -infra/terraform/* @placek @adgud +.github/workflows/* +config/govtool/* +infra/terraform/* # Testing -tests/* @spannercode @mesudip @kneerose -gov-action-loader/* @spannercode @mesudip @kneerose +tests/* +gov-action-loader/* From 277b7870c0850b9df63a58865fec0a174b43023f Mon Sep 17 00:00:00 2001 From: Aaron Boyle Date: Tue, 18 Nov 2025 10:47:26 +0000 Subject: [PATCH 4/6] removes pre-prod from build --- .github/workflows/build-from-main.yml | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/.github/workflows/build-from-main.yml b/.github/workflows/build-from-main.yml index 48d283cdb..f8952ceae 100644 --- a/.github/workflows/build-from-main.yml +++ b/.github/workflows/build-from-main.yml @@ -40,27 +40,6 @@ jobs: dockerfile: ./govtool/metadata-validation/Dockerfile image: ghcr.io/${{ github.repository }}-metadata-validation qovery_container_name: govtool-metadata-validation - - branch: main - network: pre-prod-govtool - workdir: ./govtool/backend - name: govtool-backend - dockerfile: ./govtool/backend/Dockerfile.qovery - image: ghcr.io/${{ github.repository }}-backend - qovery_container_name: govtool-backend - - branch: main - network: pre-prod-govtool - workdir: ./govtool/frontend - name: govtool-frontend - dockerfile: ./govtool/frontend/Dockerfile.qovery - image: ghcr.io/${{ github.repository }}-frontend - qovery_container_name: govtool-frontend - - branch: main - network: pre-prod-govtool - workdir: ./govtool/metadata-validation - name: govtool-metadata-validation - dockerfile: ./govtool/metadata-validation/Dockerfile - image: ghcr.io/${{ github.repository }}-metadata-validation - qovery_container_name: govtool-metadata-validation - branch: main network: prod-govtool workdir: ./govtool/backend From 070392cb3042640e05271af00b825718d8690c3b Mon Sep 17 00:00:00 2001 From: Aaron Boyle Date: Tue, 18 Nov 2025 10:54:07 +0000 Subject: [PATCH 5/6] removes auto trigger and comments out build and deployment --- .github/workflows/build-from-test.yml | 149 +++++++++++++------------- 1 file changed, 73 insertions(+), 76 deletions(-) diff --git a/.github/workflows/build-from-test.yml b/.github/workflows/build-from-test.yml index 701f19494..c7f5d4446 100644 --- a/.github/workflows/build-from-test.yml +++ b/.github/workflows/build-from-test.yml @@ -1,9 +1,6 @@ name: Check and Build QA on: - push: - branches: - - test workflow_dispatch: permissions: @@ -131,80 +128,80 @@ jobs: CLEAN_NETWORK=$(echo "${{ matrix.network }}" | sed 's/-govtool$//') echo "CLEAN_NETWORK=$CLEAN_NETWORK" >> $GITHUB_ENV - - name: Build Docker image - uses: docker/build-push-action@v5 - with: - context: ${{ matrix.workdir }} - file: ${{ matrix.dockerfile }} - tags: > - ${{ steps.image_lowercase.outputs.lowercase }}-${{ env.CLEAN_NETWORK }}:${{ env.COMMIT_TAG }}, - ${{ steps.image_lowercase.outputs.lowercase }}-${{ env.CLEAN_NETWORK }}:${{ env.STATIC_TAG }} - load: false - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache - outputs: type=docker,dest=/tmp/image-${{ matrix.name }}-${{ env.ENVIRONMENT }}.tar - build-args: | - VITE_APP_ENV=${{ secrets.VITE_APP_ENV }} - VITE_BASE_URL=${{ secrets.VITE_BASE_URL }} - VITE_METADATA_API_URL=${{ secrets.VITE_METADATA_API_URL }} - VITE_NETWORK_FLAG=${{ secrets.VITE_NETWORK_FLAG }} - VITE_SENTRY_DSN=${{ secrets.VITE_SENTRY_DSN }} - VITE_USERSNAP_SPACE_API_KEY=${{ secrets.VITE_USERSNAP_SPACE_API_KEY }} - VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED=${{ secrets.VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED }} - VITE_IS_GOVERNANCE_OUTCOMES_PILLAR_ENABLED=${{ secrets.VITE_IS_GOVERNANCE_OUTCOMES_PILLAR_ENABLED }} - VITE_OUTCOMES_API_URL=${{secrets.VITE_OUTCOMES_API_URL}} - VITE_PDF_API_URL=${{ secrets.VITE_PDF_API_URL }} - VITE_IPFS_GATEWAY=${{ secrets.IPFS_GATEWAY }} - VITE_IPFS_PROJECT_ID=${{ secrets.IPFS_PROJECT_ID }} - IPFS_GATEWAY=${{ secrets.IPFS_GATEWAY }} - IPFS_PROJECT_ID=${{ secrets.IPFS_PROJECT_ID }} - - - name: Login to GHCR - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Scan Docker image with Dockle - id: dockle - run: | - wget -q https://github.com/goodwithtech/dockle/releases/download/v0.4.14/dockle_0.4.14_Linux-64bit.tar.gz - tar zxf dockle_0.4.14_Linux-64bit.tar.gz - sudo mv dockle /usr/local/bin - - dockle --exit-code 1 --exit-level fatal --format json -ak GHC_RELEASE_KEY -ak CABAL_INSTALL_RELEASE_KEY -ak STACK_RELEASE_KEY -ak KEY_SHA512 --input '/tmp/image-${{ matrix.name }}-${{ env.ENVIRONMENT }}.tar' --output ${{ matrix.workdir }}/dockle_scan_output.json - echo " dockle exited w/ $?" - cat ${{ matrix.workdir }}/dockle_scan_output.json - - echo "outcome=success" >> $GITHUB_OUTPUT - - - name: Debug TAG Before Docker Push - run: | - echo "Lowercase Image: ${{ steps.image_lowercase.outputs.lowercase }}" - echo "Network: ${{ matrix.network }}" - echo "COMMIT_TAG: ${{ env.COMMIT_TAG }}" - echo "STATIC_TAG: ${{ env.STATIC_TAG }}" - echo "Final Docker Tag: ${{ steps.image_lowercase.outputs.lowercase }}-${{ matrix.network}}:${{ env.TAG }}" + # - name: Build Docker image + # uses: docker/build-push-action@v5 + # with: + # context: ${{ matrix.workdir }} + # file: ${{ matrix.dockerfile }} + # tags: > + # ${{ steps.image_lowercase.outputs.lowercase }}-${{ env.CLEAN_NETWORK }}:${{ env.COMMIT_TAG }}, + # ${{ steps.image_lowercase.outputs.lowercase }}-${{ env.CLEAN_NETWORK }}:${{ env.STATIC_TAG }} + # load: false + # cache-from: type=local,src=/tmp/.buildx-cache + # cache-to: type=local,dest=/tmp/.buildx-cache + # outputs: type=docker,dest=/tmp/image-${{ matrix.name }}-${{ env.ENVIRONMENT }}.tar + # build-args: | + # VITE_APP_ENV=${{ secrets.VITE_APP_ENV }} + # VITE_BASE_URL=${{ secrets.VITE_BASE_URL }} + # VITE_METADATA_API_URL=${{ secrets.VITE_METADATA_API_URL }} + # VITE_NETWORK_FLAG=${{ secrets.VITE_NETWORK_FLAG }} + # VITE_SENTRY_DSN=${{ secrets.VITE_SENTRY_DSN }} + # VITE_USERSNAP_SPACE_API_KEY=${{ secrets.VITE_USERSNAP_SPACE_API_KEY }} + # VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED=${{ secrets.VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED }} + # VITE_IS_GOVERNANCE_OUTCOMES_PILLAR_ENABLED=${{ secrets.VITE_IS_GOVERNANCE_OUTCOMES_PILLAR_ENABLED }} + # VITE_OUTCOMES_API_URL=${{secrets.VITE_OUTCOMES_API_URL}} + # VITE_PDF_API_URL=${{ secrets.VITE_PDF_API_URL }} + # VITE_IPFS_GATEWAY=${{ secrets.IPFS_GATEWAY }} + # VITE_IPFS_PROJECT_ID=${{ secrets.IPFS_PROJECT_ID }} + # IPFS_GATEWAY=${{ secrets.IPFS_GATEWAY }} + # IPFS_PROJECT_ID=${{ secrets.IPFS_PROJECT_ID }} + + # - name: Login to GHCR + # uses: docker/login-action@v2 + # with: + # registry: ghcr.io + # username: ${{ github.actor }} + # password: ${{ secrets.GITHUB_TOKEN }} + + # - name: Scan Docker image with Dockle + # id: dockle + # run: | + # wget -q https://github.com/goodwithtech/dockle/releases/download/v0.4.14/dockle_0.4.14_Linux-64bit.tar.gz + # tar zxf dockle_0.4.14_Linux-64bit.tar.gz + # sudo mv dockle /usr/local/bin + + # dockle --exit-code 1 --exit-level fatal --format json -ak GHC_RELEASE_KEY -ak CABAL_INSTALL_RELEASE_KEY -ak STACK_RELEASE_KEY -ak KEY_SHA512 --input '/tmp/image-${{ matrix.name }}-${{ env.ENVIRONMENT }}.tar' --output ${{ matrix.workdir }}/dockle_scan_output.json + # echo " dockle exited w/ $?" + # cat ${{ matrix.workdir }}/dockle_scan_output.json + + # echo "outcome=success" >> $GITHUB_OUTPUT + + # - name: Debug TAG Before Docker Push + # run: | + # echo "Lowercase Image: ${{ steps.image_lowercase.outputs.lowercase }}" + # echo "Network: ${{ matrix.network }}" + # echo "COMMIT_TAG: ${{ env.COMMIT_TAG }}" + # echo "STATIC_TAG: ${{ env.STATIC_TAG }}" + # echo "Final Docker Tag: ${{ steps.image_lowercase.outputs.lowercase }}-${{ matrix.network}}:${{ env.TAG }}" - - name: Push Docker image to GHCR - run: | - 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.CLEAN_NETWORK}}:${{ env.COMMIT_TAG }} - - - name: Sleep for 20 Seconds - run: sleep 20 - - - name: Notify Qovery of new image tag - run: | - curl -i -X POST https://api.qovery.com/organization/${{ secrets.QOVERY_ORG_ID }}/container/deploy \ - -H "Authorization: Token ${{ secrets.QOVERY_API_TOKEN }}" \ - -H "Content-Type: application/json" \ - -d '{ - "image_name": "intersectmbo/${{ matrix.name }}-${{ env.CLEAN_NETWORK }}", - "tag": "${{ env.COMMIT_TAG }}" - }' + # - name: Push Docker image to GHCR + # run: | + # 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.CLEAN_NETWORK}}:${{ env.COMMIT_TAG }} + + # - name: Sleep for 20 Seconds + # run: sleep 20 + + # - name: Notify Qovery of new image tag + # run: | + # curl -i -X POST https://api.qovery.com/organization/${{ secrets.QOVERY_ORG_ID }}/container/deploy \ + # -H "Authorization: Token ${{ secrets.QOVERY_API_TOKEN }}" \ + # -H "Content-Type: application/json" \ + # -d '{ + # "image_name": "intersectmbo/${{ matrix.name }}-${{ env.CLEAN_NETWORK }}", + # "tag": "${{ env.COMMIT_TAG }}" + # }' - name: Add tag as a PR comment uses: ubie-oss/comment-to-merged-pr-action@v0.3.3 From 661f27b06d265501f7b7662521c90ae9f51fc091 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Wed, 22 Apr 2026 15:20:09 +0100 Subject: [PATCH 6/6] increase abstract limit --- govtool/metadata-validation/src/utils/validateCIP108body.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/govtool/metadata-validation/src/utils/validateCIP108body.ts b/govtool/metadata-validation/src/utils/validateCIP108body.ts index abd8bc70b..6ef8e0447 100644 --- a/govtool/metadata-validation/src/utils/validateCIP108body.ts +++ b/govtool/metadata-validation/src/utils/validateCIP108body.ts @@ -17,7 +17,7 @@ export const validateCIP108body = (body: Record) => { if (!title || !abstract || !motivation || !rationale) { throw MetadataValidationStatus.INCORRECT_FORMAT; } - if (String(title).length > 80 || String(abstract).length > 2500) { + if (String(title).length > 80 || String(abstract).length > 3000) { throw MetadataValidationStatus.INCORRECT_FORMAT; }