From 239a6d9fe682b1ec95aae45c9ae8cbe555d996cf Mon Sep 17 00:00:00 2001 From: Sudip Bhattarai Date: Thu, 13 Jun 2024 17:18:02 +0545 Subject: [PATCH 01/15] Update proposal format for test --- tests/govtool-backend/models/TestData.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/govtool-backend/models/TestData.py b/tests/govtool-backend/models/TestData.py index a48179698..cf24c5532 100644 --- a/tests/govtool-backend/models/TestData.py +++ b/tests/govtool-backend/models/TestData.py @@ -26,7 +26,7 @@ class Proposal(TypedDict): url: str metadataHash: str title: Optional[str] - about: Optional[str] + abstract: Optional[str] motivation: Optional[str] rationale: Optional[str] metadata: Optional[dict] @@ -34,6 +34,8 @@ class Proposal(TypedDict): yesVotes: int noVotes: int abstainVotes: int + metadataStatus: str + metadataValid: bool class Drep(TypedDict): From e0df013518e2f544f37bf5c9b86709d9f6061287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Fri, 14 Jun 2024 15:12:16 +0200 Subject: [PATCH 02/15] fix(#1282): fix validation for missing references --- CHANGELOG.md | 1 + .../src/app.controller.spec.ts | 50 ----- .../src/app.service.test.ts | 164 ++++++++++++++++ .../src/schemas/cipStandardSchema.test.ts | 185 ++++++++++++++++++ .../src/schemas/cipStandardSchema.ts | 78 ++++---- 5 files changed, 393 insertions(+), 85 deletions(-) delete mode 100644 govtool/metadata-validation/src/app.controller.spec.ts create mode 100644 govtool/metadata-validation/src/app.service.test.ts create mode 100644 govtool/metadata-validation/src/schemas/cipStandardSchema.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 46887e708..c58d8708b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -95,6 +95,7 @@ changes. - Remove wrongly appended `Yourself` filter on DRep Directory [Issue 1028](https://github.com/IntersectMBO/govtool/issues/1028) - Fix validation of uris in metadata [Issue 1011](https://github.com/IntersectMBO/govtool/issues/1011) - Fix wrong link to the GA Details once it is in progress [Issue 1252](https://github.com/IntersectMBO/govtool/issues/1252) +- Fix validation of the GAs with missing references [Issue 1282](https://github.com/IntersectMBO/govtool/issues/1282) ### Changed diff --git a/govtool/metadata-validation/src/app.controller.spec.ts b/govtool/metadata-validation/src/app.controller.spec.ts deleted file mode 100644 index f74ccb63d..000000000 --- a/govtool/metadata-validation/src/app.controller.spec.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { HttpModule } from '@nestjs/axios'; - -import { MetadataValidationStatus } from '@enums'; - -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -// TODO: Mock HttpService -describe('AppController', () => { - let appController: AppController; - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - imports: [ - HttpModule.register({ - timeout: 5000, - maxRedirects: 5, - }), - ], - controllers: [AppController], - providers: [AppService], - }).compile(); - - appController = app.get(AppController); - }); - - it('should throw invalid URL', async () => { - const result = await appController.validateMetadata({ - hash: 'hash', - url: 'url', - }); - expect(result).toEqual({ - status: MetadataValidationStatus.URL_NOT_FOUND, - valid: false, - }); - }); - - it('should throw invalid JSONLD', async () => { - const result = await appController.validateMetadata({ - hash: 'hash', - url: 'http://www.schema.org', - }); - - expect(result).toEqual({ - status: MetadataValidationStatus.INVALID_JSONLD, - valid: false, - }); - }); -}); diff --git a/govtool/metadata-validation/src/app.service.test.ts b/govtool/metadata-validation/src/app.service.test.ts new file mode 100644 index 000000000..0e3d8f946 --- /dev/null +++ b/govtool/metadata-validation/src/app.service.test.ts @@ -0,0 +1,164 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { HttpService } from '@nestjs/axios'; +import { of, throwError } from 'rxjs'; +import * as blake from 'blakejs'; + +import { AppService } from './app.service'; +import { ValidateMetadataDTO } from '@dto'; +import { MetadataValidationStatus } from '@enums'; +import { MetadataStandard } from '@types'; +import { canonizeJSON, validateMetadataStandard, parseMetadata } from '@utils'; +import { AxiosResponse, AxiosRequestHeaders } from 'axios'; + +jest.mock('@utils'); + +describe('AppService', () => { + let service: AppService; + let httpService: HttpService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + AppService, + { + provide: HttpService, + useValue: { + get: jest.fn(), + }, + }, + ], + }).compile(); + + service = module.get(AppService); + httpService = module.get(HttpService); + }); + + it('should validate metadata correctly', async () => { + const url = 'http://example.com'; + const hash = 'correctHash'; + const standard = MetadataStandard.CIP108; + const validateMetadataDTO: ValidateMetadataDTO = { hash, url, standard }; + const data = { + body: 'testBody', + headers: {}, + }; + const canonizedMetadata = 'canonizedMetadata'; + const parsedMetadata = { parsed: 'metadata' }; + const response: AxiosResponse = { + data, + status: 200, + statusText: 'OK', + headers: {}, + config: { + headers: {} as AxiosRequestHeaders, + url, + }, + }; + jest.spyOn(httpService, 'get').mockReturnValueOnce(of(response)); + (validateMetadataStandard as jest.Mock).mockResolvedValueOnce(undefined); + (parseMetadata as jest.Mock).mockReturnValueOnce(parsedMetadata); + (canonizeJSON as jest.Mock).mockResolvedValueOnce(canonizedMetadata); + jest.spyOn(blake, 'blake2bHex').mockReturnValueOnce(hash); + + const result = await service.validateMetadata(validateMetadataDTO); + + expect(result).toEqual({ + status: undefined, + valid: true, + metadata: parsedMetadata, + }); + expect(validateMetadataStandard).toHaveBeenCalledWith(data, standard); + expect(parseMetadata).toHaveBeenCalledWith(data.body, standard); + expect(canonizeJSON).toHaveBeenCalledWith(data); + }); + + it('should handle URL_NOT_FOUND error', async () => { + const url = 'http://example.com'; + const hash = 'correctHash'; + const validateMetadataDTO: ValidateMetadataDTO = { hash, url }; + + jest + .spyOn(httpService, 'get') + .mockReturnValueOnce( + throwError(() => MetadataValidationStatus.URL_NOT_FOUND), + ); + + const result = await service.validateMetadata(validateMetadataDTO); + + expect(result).toEqual({ + status: MetadataValidationStatus.URL_NOT_FOUND, + valid: false, + metadata: undefined, + }); + }); + + it('should handle INVALID_HASH error', async () => { + const url = 'http://example.com'; + const hash = 'incorrectHash'; + const standard = MetadataStandard.CIP108; + const validateMetadataDTO: ValidateMetadataDTO = { hash, url, standard }; + const data = { + body: 'testBody', + }; + const canonizedMetadata = 'canonizedMetadata'; + const parsedMetadata = { parsed: 'metadata' }; + + const response: AxiosResponse = { + data, + status: 200, + statusText: 'OK', + headers: {}, + config: { + headers: {} as AxiosRequestHeaders, + url, + }, + }; + jest.spyOn(httpService, 'get').mockReturnValueOnce(of(response)); + (validateMetadataStandard as jest.Mock).mockResolvedValueOnce(undefined); + (parseMetadata as jest.Mock).mockReturnValueOnce(parsedMetadata); + (canonizeJSON as jest.Mock).mockResolvedValueOnce(canonizedMetadata); + jest.spyOn(blake, 'blake2bHex').mockReturnValueOnce('differentHash'); + + const result = await service.validateMetadata(validateMetadataDTO); + + expect(result).toEqual({ + status: MetadataValidationStatus.INVALID_HASH, + valid: false, + metadata: parsedMetadata, + }); + }); + + it('should handle INVALID_JSONLD error', async () => { + const url = 'http://example.com'; + const hash = 'correctHash'; + const standard = MetadataStandard.CIP108; + const validateMetadataDTO: ValidateMetadataDTO = { hash, url, standard }; + const data = { + body: 'testBody', + }; + const parsedMetadata = { parsed: 'metadata' }; + + const response: AxiosResponse = { + data, + status: 200, + statusText: 'OK', + headers: {}, + config: { + headers: {} as AxiosRequestHeaders, + url, + }, + }; + jest.spyOn(httpService, 'get').mockReturnValueOnce(of(response)); + (validateMetadataStandard as jest.Mock).mockResolvedValueOnce(undefined); + (parseMetadata as jest.Mock).mockReturnValueOnce(parsedMetadata); + (canonizeJSON as jest.Mock).mockRejectedValueOnce(new Error()); + + const result = await service.validateMetadata(validateMetadataDTO); + + expect(result).toEqual({ + status: MetadataValidationStatus.INVALID_JSONLD, + valid: false, + metadata: parsedMetadata, + }); + }); +}); diff --git a/govtool/metadata-validation/src/schemas/cipStandardSchema.test.ts b/govtool/metadata-validation/src/schemas/cipStandardSchema.test.ts new file mode 100644 index 000000000..fab4dbfdd --- /dev/null +++ b/govtool/metadata-validation/src/schemas/cipStandardSchema.test.ts @@ -0,0 +1,185 @@ +import { MetadataStandard } from '@types'; + +import { cipStandardSchema } from './cipStandardSchema'; + +const validCIP108Data = { + '@context': { + '@language': 'en', + CIP100: + 'https://github.com/cardano-foundation/CIPs/blob/master/CIP-0100/README.md#', + CIP108: + 'https://github.com/cardano-foundation/CIPs/blob/master/CIP-0108/README.md#', + hashAlgorithm: 'CIP100:hashAlgorithm', + body: {}, + authors: {}, + }, + authors: [], + hashAlgorithm: { + '@value': 'blake2b-256', + }, + body: { + title: { '@value': 'Sample Title' }, + abstract: { '@value': 'Sample Abstract' }, + motivation: { '@value': 'Sample Motivation' }, + rationale: { '@value': 'Sample Rationale' }, + references: [ + { + '@type': 'ReferenceType', + label: { '@value': 'Sample Label' }, + uri: { '@value': 'https://sampleuri.com' }, + referenceHash: { + hashDigest: 'sampleHashDigest', + hashAlgorithm: 'sampleHashAlgorithm', + }, + }, + ], + }, +}; + +const validCIPQQQData = { + '@context': { + '@language': 'en', + CIP100: + 'https://github.com/cardano-foundation/CIPs/blob/master/CIP-0100/README.md#', + CIPQQQ: + 'https://github.com/cardano-foundation/CIPs/blob/master/CIP-QQQ/README.md#', + hashAlgorithm: 'CIP100:hashAlgorithm', + body: {}, + authors: {}, + }, + authors: [], + hashAlgorithm: { + '@value': 'blake2b-256', + }, + body: { + bio: { '@value': 'Sample Bio' }, + dRepName: { '@value': 'Sample Name' }, + email: { '@value': 'sample@example.com' }, + references: [ + { + '@type': 'ReferenceType', + label: { '@value': 'Sample Label' }, + uri: { '@value': 'https://sampleuri.com' }, + referenceHash: { + hashDigest: 'sampleHashDigest', + hashAlgorithm: 'sampleHashAlgorithm', + }, + }, + ], + }, +}; + +describe('cipStandardSchema', () => { + it('should validate CIP108 data correctly', () => { + const { error } = + cipStandardSchema[MetadataStandard.CIP108].validate(validCIP108Data); + expect(error).toBeUndefined(); + }); + + it('should invalidate CIP108 data with missing required fields', () => { + const invalidData = { + ...validCIP108Data, + body: { ...validCIP108Data.body, title: {} }, + }; + const { error } = + cipStandardSchema[MetadataStandard.CIP108].validate(invalidData); + expect(error).toBeDefined(); + }); + + it('should invalidate CIP108 data with wrong hashAlgorithm', () => { + const invalidData = { + ...validCIP108Data, + hashAlgorithm: { + '@value': 'wrongHashAlgorithm', + }, + }; + const { error } = + cipStandardSchema[MetadataStandard.CIP108].validate(invalidData); + expect(error).toBeDefined(); + }); + + it('should invalidate CIP108 with too long title', () => { + const invalidData = { + ...validCIP108Data, + body: { + ...validCIP108Data.body, + title: { + '@value': 'a'.repeat(81), + }, + }, + }; + const { error } = + cipStandardSchema[MetadataStandard.CIP108].validate(invalidData); + expect(error).toBeDefined(); + }); + + it('should invalidate CIP108 data with wrong references', () => { + const invalidData = { + ...validCIP108Data, + body: { + ...validCIP108Data.body, + references: [ + { + '@type': 'ReferenceType', + label: { '@value': 'Sample Label' }, + // Missing uri + referenceHash: { + hashDigest: 'sampleHashDigest', + hashAlgorithm: 'sampleHashAlgorithm', + }, + }, + ], + }, + }; + const { error } = + cipStandardSchema[MetadataStandard.CIP108].validate(invalidData); + expect(error).toBeDefined(); + }); + + it('should validate CIP108 with empty references', () => { + const { error } = cipStandardSchema[MetadataStandard.CIP108].validate({ + ...validCIP108Data, + body: { ...validCIP108Data.body, references: [] }, + }); + expect(error).toBeUndefined(); + }); + + it('should validate CIPQQQ data correctly', () => { + const { error } = + cipStandardSchema[MetadataStandard.CIPQQQ].validate(validCIPQQQData); + expect(error).toBeUndefined(); + }); + + it('should invalidate CIPQQQ data with missing required fields', () => { + const invalidData = { + ...validCIPQQQData, + body: { ...validCIPQQQData.body, bio: undefined }, + }; + const { error } = + cipStandardSchema[MetadataStandard.CIPQQQ].validate(invalidData); + expect(error).toBeDefined(); + }); + + it('should invalidate CIPQQQ data with wrong references', () => { + const invalidData = { + ...validCIPQQQData, + body: { + ...validCIPQQQData.body, + references: [ + { + '@type': 'ReferenceType', + label: { '@value': 'Sample Label' }, + // Missing uri + referenceHash: { + hashDigest: 'sampleHashDigest', + hashAlgorithm: 'sampleHashAlgorithm', + }, + }, + ], + }, + }; + const { error } = + cipStandardSchema[MetadataStandard.CIPQQQ].validate(invalidData); + expect(error).toBeDefined(); + }); +}); diff --git a/govtool/metadata-validation/src/schemas/cipStandardSchema.ts b/govtool/metadata-validation/src/schemas/cipStandardSchema.ts index 3f074d75a..03781bf4b 100644 --- a/govtool/metadata-validation/src/schemas/cipStandardSchema.ts +++ b/govtool/metadata-validation/src/schemas/cipStandardSchema.ts @@ -29,25 +29,31 @@ export const cipStandardSchema: StandardSpecification = { '@value': Joi.string().valid('blake2b-256').required(), }), body: Joi.object({ - title: Joi.object({ '@value': Joi.string().max(80).required() }), - abstract: Joi.object({ '@value': Joi.string().max(2500).required() }), - motivation: Joi.object({ '@value': Joi.string().required() }), - rationale: Joi.object({ '@value': Joi.string().required() }), - references: Joi.array().items( - Joi.object({ - '@type': Joi.string(), - label: Joi.object({ - '@value': Joi.string().required(), + title: Joi.object({ + '@value': Joi.string().max(80).required(), + }).required(), + abstract: Joi.object({ + '@value': Joi.string().max(2500).required(), + }).required(), + motivation: Joi.object({ '@value': Joi.string().required() }).required(), + rationale: Joi.object({ '@value': Joi.string().required() }).required(), + references: Joi.array() + .items( + Joi.object({ + '@type': Joi.string().required(), + label: Joi.object({ + '@value': Joi.string().required(), + }).required(), + uri: Joi.object({ + '@value': Joi.string().required(), + }).required(), + referenceHash: Joi.object({ + hashDigest: Joi.string().required(), + hashAlgorithm: Joi.string().required(), + }), }), - uri: Joi.object({ - '@value': Joi.string().required(), - }), - referenceHash: Joi.object({ - hashDigest: Joi.string().required(), - hashAlgorithm: Joi.string().required(), - }), - }), - ), + ) + .required(), }), }), [MetadataStandard.CIPQQQ]: Joi.object({ @@ -64,24 +70,26 @@ export const cipStandardSchema: StandardSpecification = { '@value': Joi.string().valid('blake2b-256').required(), }), body: Joi.object({ - bio: Joi.object({ '@value': Joi.string().allow('') }), - dRepName: Joi.object({ '@value': Joi.string().allow('') }), - email: Joi.object({ '@value': Joi.string().allow('') }), - references: Joi.array().items( - Joi.object({ - '@type': Joi.string(), - label: Joi.object({ - '@value': Joi.string().allow('').required(), - }), - uri: Joi.object({ - '@value': Joi.string().required(), - }), - referenceHash: Joi.object({ - hashDigest: Joi.string().required(), - hashAlgorithm: Joi.string().required(), + bio: Joi.object({ '@value': Joi.string().allow('') }).required(), + dRepName: Joi.object({ '@value': Joi.string().allow('') }).required(), + email: Joi.object({ '@value': Joi.string().allow('') }).required(), + references: Joi.array() + .items( + Joi.object({ + '@type': Joi.string(), + label: Joi.object({ + '@value': Joi.string().allow('').required(), + }).required(), + uri: Joi.object({ + '@value': Joi.string().required(), + }).required(), + referenceHash: Joi.object({ + hashDigest: Joi.string().required(), + hashAlgorithm: Joi.string().required(), + }), }), - }), - ), + ) + .required(), }), }), }; From 16d6734bed302fe68854c04763167bd979bfeb85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Sworze=C5=84?= Date: Mon, 17 Jun 2024 11:31:26 +0200 Subject: [PATCH 03/15] use optional chaining --- .../WhatGovernanceActionIsAbout.tsx | 2 +- govtool/frontend/src/components/organisms/DashboardCards.tsx | 2 +- govtool/frontend/src/context/wallet.tsx | 4 ++-- .../frontend/src/hooks/forms/useCreateGovernanceActionForm.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/WhatGovernanceActionIsAbout.tsx b/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/WhatGovernanceActionIsAbout.tsx index 69aca4cf9..3f1f789b6 100644 --- a/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/WhatGovernanceActionIsAbout.tsx +++ b/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/WhatGovernanceActionIsAbout.tsx @@ -50,7 +50,7 @@ export const WhatGovernanceActionIsAbout = ({ diff --git a/govtool/frontend/src/components/organisms/DashboardCards.tsx b/govtool/frontend/src/components/organisms/DashboardCards.tsx index 2cd241fe3..bccf72fdb 100644 --- a/govtool/frontend/src/components/organisms/DashboardCards.tsx +++ b/govtool/frontend/src/components/organisms/DashboardCards.tsx @@ -86,7 +86,7 @@ export const DashboardCards = () => { diff --git a/govtool/frontend/src/context/wallet.tsx b/govtool/frontend/src/context/wallet.tsx index 70989957d..1ea70f80c 100644 --- a/govtool/frontend/src/context/wallet.tsx +++ b/govtool/frontend/src/context/wallet.tsx @@ -789,7 +789,7 @@ const CardanoProvider = (props: Props) => { infoGovAct, anchor, rewardAddr, - BigNum.from_str(epochParams.gov_action_deposit.toString()), + BigNum.from_str(epochParams?.gov_action_deposit.toString()), ); govActionBuilder.add(votingProposal); @@ -830,7 +830,7 @@ const CardanoProvider = (props: Props) => { treasuryGovAct, anchor, rewardAddr, - BigNum.from_str(epochParams.gov_action_deposit.toString()), + BigNum.from_str(epochParams?.gov_action_deposit.toString()), ); govActionBuilder.add(votingProposal); diff --git a/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts b/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts index 7556c9f22..7406665b0 100644 --- a/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts +++ b/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts @@ -240,7 +240,7 @@ export const useCreateGovernanceActionForm = ( openWalletErrorModal({ error: isInsufficientBalance ? t("errors.insufficientBalanceDescription", { - ada: correctAdaFormat(protocolParams.gov_action_deposit), + ada: correctAdaFormat(protocolParams?.gov_action_deposit), }) : error, title: isInsufficientBalance From 8690cd19a3ea57aaac35c6853aad8888c28e6b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Fri, 14 Jun 2024 16:15:13 +0200 Subject: [PATCH 04/15] chore: remove unsafe-inline for font-src csp directive --- scripts/govtool/config/templates/docker-compose.yml.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/govtool/config/templates/docker-compose.yml.tpl b/scripts/govtool/config/templates/docker-compose.yml.tpl index 0a8a6bb78..5882aef20 100644 --- a/scripts/govtool/config/templates/docker-compose.yml.tpl +++ b/scripts/govtool/config/templates/docker-compose.yml.tpl @@ -273,7 +273,7 @@ services: logging: *logging labels: - "traefik.enable=true" - - "traefik.http.middlewares.frontend-csp.headers.contentSecurityPolicy=default-src 'self'; img-src *.usersnap.com https://www.googletagmanager.com 'self' data:; script-src *.usersnap.com 'self' 'unsafe-inline' https://www.googletagmanager.com https://browser.sentry-cdn.com; style-src *.usersnap.com *.googleapis.com 'self' 'unsafe-inline' https://fonts.googleapis.com; connect-src *.usersnap.com https://s3.eu-central-1.amazonaws.com/upload.usersnap.com 'self' o4506155985141760.ingest.sentry.io *.google-analytics.com *.api.pdf.gov.tools; font-src *.usersnap.com *.gstatic.com 'self' 'unsafe-inline' https://fonts.gstatic.com; worker-src blob:" + - "traefik.http.middlewares.frontend-csp.headers.contentSecurityPolicy=default-src 'self'; img-src *.usersnap.com https://www.googletagmanager.com 'self' data:; script-src *.usersnap.com 'self' https://www.googletagmanager.com https://browser.sentry-cdn.com; style-src *.usersnap.com *.googleapis.com 'self' 'unsafe-inline' https://fonts.googleapis.com; connect-src *.usersnap.com https://s3.eu-central-1.amazonaws.com/upload.usersnap.com 'self' o4506155985141760.ingest.sentry.io *.google-analytics.com *.api.pdf.gov.tools; font-src *.usersnap.com *.gstatic.com 'self' https://fonts.gstatic.com data:; worker-src blob:" - "traefik.http.routers.to-frontend.rule=Host(``)" - "traefik.http.routers.to-frontend.entrypoints=websecure" - "traefik.http.routers.to-frontend.tls.certresolver=myresolver" From d8aedbf22ac30664f47b884ad828538baeb81205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Mon, 17 Jun 2024 15:02:24 +0200 Subject: [PATCH 05/15] fix(#1244): fix direction on the governance actions --- CHANGELOG.md | 1 + .../src/components/molecules/GovernanceActionCardElement.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c58d8708b..6a53afcc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -96,6 +96,7 @@ changes. - Fix validation of uris in metadata [Issue 1011](https://github.com/IntersectMBO/govtool/issues/1011) - Fix wrong link to the GA Details once it is in progress [Issue 1252](https://github.com/IntersectMBO/govtool/issues/1252) - Fix validation of the GAs with missing references [Issue 1282](https://github.com/IntersectMBO/govtool/issues/1282) +- Fix displaying the GA Markdowns [Issue 1244](https://github.com/IntersectMBO/govtool/issues/1244) ### Changed diff --git a/govtool/frontend/src/components/molecules/GovernanceActionCardElement.tsx b/govtool/frontend/src/components/molecules/GovernanceActionCardElement.tsx index 2caa9a254..f0a0a995b 100644 --- a/govtool/frontend/src/components/molecules/GovernanceActionCardElement.tsx +++ b/govtool/frontend/src/components/molecules/GovernanceActionCardElement.tsx @@ -108,6 +108,7 @@ export const GovernanceActionCardElement = ({ display: "flex", alignItems: "center", overflow: "hidden", + flexDirection: "column", }} > {isMarkdown ? ( From cb078c8883a417ef8dd48aaf6c37c7039067aa34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Mon, 17 Jun 2024 12:27:12 +0200 Subject: [PATCH 06/15] chore: bump pdf-ui package to v0.1.8; remove propose a governance action button from wrapper --- govtool/frontend/package-lock.json | 8 +-- govtool/frontend/package.json | 2 +- .../components/organisms/DashboardTopNav.tsx | 34 ++--------- .../src/components/organisms/Drawer.tsx | 4 +- govtool/frontend/src/consts/index.ts | 2 + govtool/frontend/src/consts/paths.ts | 1 - govtool/frontend/src/pages/Dashboard.tsx | 8 ++- govtool/frontend/yarn.lock | 58 +++++++++---------- 8 files changed, 47 insertions(+), 70 deletions(-) diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 5198c10d2..7466fc6e2 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -14,7 +14,7 @@ "@emurgo/cardano-serialization-lib-asmjs": "12.0.0-alpha.29", "@hookform/resolvers": "^3.3.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "^0.1.3", + "@intersect.mbo/pdf-ui": "^0.1.8", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -3346,9 +3346,9 @@ "integrity": "sha512-Y+5vYGlF3Smg/QscQT/4ZwsKTNm2C0GCs2czzYWrE4O4RV2YAAg9MZkQ52u8uZp3cEW0h9vr+f9W9ihhwsNHGQ==" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.1.3.tgz", - "integrity": "sha512-XCcmKw7sAxqU7JpllfxyLzGjfZBUIhm1aqjLpupm/35Ntr6UpxfBm9bgGmxcDtRHW9kSHMTWQoadiGro2kBx+A==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.1.8.tgz", + "integrity": "sha512-KMprTN0YbYcRAYWF8zmZIQzokdQUh3Q0Fly7zcDstfF8MZB64X5ZphoT1SP7GLSXryLadLVkqK/MuGFrr6LAcQ==", "dependencies": { "@fontsource/poppins": "^5.0.14", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index e9c9da593..d7d2bbba7 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -28,7 +28,7 @@ "@emurgo/cardano-serialization-lib-asmjs": "12.0.0-alpha.29", "@hookform/resolvers": "^3.3.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "^0.1.3", + "@intersect.mbo/pdf-ui": "^0.1.8", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", diff --git a/govtool/frontend/src/components/organisms/DashboardTopNav.tsx b/govtool/frontend/src/components/organisms/DashboardTopNav.tsx index fad5f1955..369483e7a 100644 --- a/govtool/frontend/src/components/organisms/DashboardTopNav.tsx +++ b/govtool/frontend/src/components/organisms/DashboardTopNav.tsx @@ -1,10 +1,9 @@ import { useEffect, useState } from "react"; -import { Box, Button, IconButton } from "@mui/material"; -import { IconPlusCircle } from "@intersect.mbo/intersectmbo.org-icons-set"; +import { Box, IconButton } from "@mui/material"; import { VotingPowerChips, Typography } from "@atoms"; -import { ICONS, PATHS, PDF_PATHS } from "@consts"; -import { useScreenDimension, useTranslation } from "@hooks"; +import { ICONS } from "@consts"; +import { useScreenDimension } from "@hooks"; import { DashboardDrawerMobile } from "@organisms"; type DashboardTopNavProps = { @@ -18,14 +17,6 @@ export const DashboardTopNav = ({ title, isVotingPowerHidden, }: DashboardTopNavProps) => { - const { t } = useTranslation(); - const isProposalDiscussion = Object.values(PDF_PATHS).some( - (pdfPath) => - window.location.pathname.includes(pdfPath) && - window.location.pathname.includes( - PATHS.connectedProposalPillar.replace("/*", ""), - ), - ); const [windowScroll, setWindowScroll] = useState(0); const { isMobile } = useScreenDimension(); const [isDrawerOpen, setIsDrawerOpen] = useState(false); @@ -34,12 +25,6 @@ export const DashboardTopNav = ({ setIsDrawerOpen(true); }; - const goToProposalDiscussionCreateGovernanceAction = () => { - window.location.href = `${PATHS.connectedProposalPillar.replace("/*", "")}${ - PDF_PATHS.proposalDiscussionCreateGovernanceAction - }`; - }; - useEffect(() => { const onScroll = () => { setWindowScroll(window.scrollY); @@ -91,9 +76,7 @@ export const DashboardTopNav = ({ ) : null} - {!isVotingPowerHidden && !isProposalDiscussion && ( - - )} + {!isVotingPowerHidden && } {isMobile && ( )} - {isProposalDiscussion && ( - - )} {isMobile && ( { height: "100vh", position: "sticky", top: 0, - width: "268px", + width: `${DRAWER_WIDTH}px`, }} > { const getPageTitle = (path: string) => { if (path === PATHS.dashboard) return t("dashboard.title"); return ( - Object.values(CONNECTED_NAV_ITEMS).find(({ navTo }) => pathname.startsWith(navTo)) - ?.label ?? "" + Object.values(CONNECTED_NAV_ITEMS).find(({ navTo }) => + pathname.startsWith(navTo), + )?.label ?? "" ); }; @@ -53,6 +54,7 @@ export const Dashboard = () => { flex: 1, flexDirection: "column", minHeight: "100vh", + width: `calc(100vw - ${DRAWER_WIDTH}px)`, overflow: "clip", position: "relative", }} diff --git a/govtool/frontend/yarn.lock b/govtool/frontend/yarn.lock index 9c213c428..2f72f8efc 100644 --- a/govtool/frontend/yarn.lock +++ b/govtool/frontend/yarn.lock @@ -1466,20 +1466,20 @@ resolved "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-asmjs/-/cardano-serialization-lib-asmjs-12.0.0-alpha.29.tgz" integrity sha512-E9+jGLo8QciXbkb7dDYEbZL6YlEJfNRwzYkyR4kkuvzAsy0uKe93dtAY1tdj6ECp+NyeH5xqyKU6aUT8rxwm7A== -"@esbuild/darwin-arm64@0.18.20": +"@esbuild/linux-x64@0.18.20": version "0.18.20" - resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz" - integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA== + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz" + integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== -"@esbuild/darwin-arm64@0.19.12": +"@esbuild/linux-x64@0.19.12": version "0.19.12" - resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz" - integrity sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g== + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz" + integrity sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg== -"@esbuild/darwin-arm64@0.20.2": +"@esbuild/linux-x64@0.20.2": version "0.20.2" - resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz" - integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz" + integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" @@ -1596,10 +1596,10 @@ resolved "https://registry.npmjs.org/@intersect.mbo/intersectmbo.org-icons-set/-/intersectmbo.org-icons-set-1.0.8.tgz" integrity sha512-Y+5vYGlF3Smg/QscQT/4ZwsKTNm2C0GCs2czzYWrE4O4RV2YAAg9MZkQ52u8uZp3cEW0h9vr+f9W9ihhwsNHGQ== -"@intersect.mbo/pdf-ui@^0.1.3": - version "0.1.3" - resolved "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.1.3.tgz" - integrity sha512-XCcmKw7sAxqU7JpllfxyLzGjfZBUIhm1aqjLpupm/35Ntr6UpxfBm9bgGmxcDtRHW9kSHMTWQoadiGro2kBx+A== +"@intersect.mbo/pdf-ui@^0.1.8": + version "0.1.8" + resolved "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.1.8.tgz" + integrity sha512-KMprTN0YbYcRAYWF8zmZIQzokdQUh3Q0Fly7zcDstfF8MZB64X5ZphoT1SP7GLSXryLadLVkqK/MuGFrr6LAcQ== dependencies: "@fontsource/poppins" "^5.0.14" "@intersect.mbo/intersectmbo.org-icons-set" "^1.0.8" @@ -2630,10 +2630,15 @@ estree-walker "^2.0.2" picomatch "^2.3.1" -"@rollup/rollup-darwin-arm64@4.18.0": +"@rollup/rollup-linux-x64-gnu@4.18.0": + version "4.18.0" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz" + integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w== + +"@rollup/rollup-linux-x64-musl@4.18.0": version "4.18.0" - resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz" - integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w== + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz" + integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg== "@rushstack/eslint-patch@^1.1.0": version "1.10.3" @@ -3675,10 +3680,15 @@ "@svgr/plugin-svgo" "^5.5.0" loader-utils "^2.0.0" -"@swc/core-darwin-arm64@1.5.25": +"@swc/core-linux-x64-gnu@1.5.25": version "1.5.25" - resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.25.tgz" - integrity sha512-YbD0SBgVJS2DM0vwJTU5m7+wOyCjHPBDMf3nCBJQzFZzOLzK11eRW7SzU2jhJHr9HI9sKcNFfN4lIC2Sj+4inA== + resolved "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.25.tgz" + integrity sha512-LwbJEgNT3lXbvz4WFzVNXNvs8DvxpoXjMZk9K9Hig8tmZQJKHC2qZTGomcyK5EFzfj2HBuBXZnAEW8ZT9PcEaA== + +"@swc/core-linux-x64-musl@1.5.25": + version "1.5.25" + resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.25.tgz" + integrity sha512-rsepMTgml0EkswWkBpg3Wrjj5eqjwTzZN5omAn1klzXSZnClTrfeHvBuoIJYVr1yx+jmBkqySgME2p7+magUAw== "@swc/core@*", "@swc/core@^1.3.18": version "1.5.25" @@ -8406,16 +8416,6 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -fsevents@2.3.2: - version "2.3.2" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" From 7f12996850788d4a70ea9f75dabbc9a6f5ad07f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Sworze=C5=84?= Date: Mon, 17 Jun 2024 13:43:27 +0200 Subject: [PATCH 07/15] fix text area story --- .../frontend/src/stories/TextArea.stories.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/govtool/frontend/src/stories/TextArea.stories.tsx b/govtool/frontend/src/stories/TextArea.stories.tsx index 30614dfac..75e78954b 100644 --- a/govtool/frontend/src/stories/TextArea.stories.tsx +++ b/govtool/frontend/src/stories/TextArea.stories.tsx @@ -3,7 +3,7 @@ import type { Meta, StoryFn } from "@storybook/react"; import { Field } from "@molecules"; import { userEvent, within } from "@storybook/testing-library"; -import { ComponentProps } from "react"; +import { ComponentProps, useState } from "react"; const meta: Meta = { title: "Example/TextArea", @@ -16,9 +16,17 @@ const meta: Meta = { export default meta; -const Template: StoryFn> = (args) => ( - -); +const Template: StoryFn> = (args) => { + const [val, setVal] = useState(""); + + return ( + setVal(e.target.value)} + /> + ); +}; async function assertTextbox(canvas: ReturnType) { const text = "test"; From 8efd006182bd97daf098e914530c1570d02a38d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Sworze=C5=84?= Date: Mon, 17 Jun 2024 13:46:53 +0200 Subject: [PATCH 08/15] fix dashboard card story --- ...Card.stories.ts => DashboardCard.stories.tsx} | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) rename govtool/frontend/src/stories/{DashboardCard.stories.ts => DashboardCard.stories.tsx} (87%) diff --git a/govtool/frontend/src/stories/DashboardCard.stories.ts b/govtool/frontend/src/stories/DashboardCard.stories.tsx similarity index 87% rename from govtool/frontend/src/stories/DashboardCard.stories.ts rename to govtool/frontend/src/stories/DashboardCard.stories.tsx index 455707271..a175d414d 100644 --- a/govtool/frontend/src/stories/DashboardCard.stories.ts +++ b/govtool/frontend/src/stories/DashboardCard.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { DashboardActionCard } from "@molecules"; +import { CopyableInfo, DashboardActionCard } from "@molecules"; import { expect } from "@storybook/jest"; import { within } from "@storybook/testing-library"; import { IMAGES } from "@/consts"; @@ -43,10 +43,22 @@ export const DashboardCardComponent: Story = { export const WithDRepIdDashboardCardComponent: Story = { args: { - buttons: [{ children: "first button" }, { children: "second button" }], + buttons: [ + { children: "first button", variant: "contained" }, + { children: "second button" }, + ], description: "Lorem ipsum dolor sit amet, consectetur adipisicing elit.", imageURL: IMAGES.govActionDelegateImage, + state: "active", title: "Action card", + children: ( + + ), }, play: async ({ canvasElement }) => { const dRepId = ""; From 25903ebab67dade87c38943a41b0d2e5abfb3d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Sworze=C5=84?= Date: Mon, 17 Jun 2024 13:47:07 +0200 Subject: [PATCH 09/15] fix voting power chips story --- .../src/components/atoms/VotingPowerChips.tsx | 29 ++++++++++--------- .../components/organisms/DashboardTopNav.tsx | 22 ++++++++++++-- .../src/stories/VotingPowerChips.stories.ts | 1 + 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/govtool/frontend/src/components/atoms/VotingPowerChips.tsx b/govtool/frontend/src/components/atoms/VotingPowerChips.tsx index aa7a3655a..159859c90 100644 --- a/govtool/frontend/src/components/atoms/VotingPowerChips.tsx +++ b/govtool/frontend/src/components/atoms/VotingPowerChips.tsx @@ -2,24 +2,25 @@ import { Box, CircularProgress } from "@mui/material"; import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; import { Typography, Tooltip } from "@atoms"; -import { useCardano } from "@context"; -import { - useGetDRepVotingPowerQuery, - useGetVoterInfo, - useScreenDimension, - useTranslation, -} from "@hooks"; +import { useScreenDimension, useTranslation } from "@hooks"; import { correctAdaFormat } from "@utils"; -export const VotingPowerChips = () => { - const { isEnableLoading } = useCardano(); - const { voter } = useGetVoterInfo(); - const { dRepVotingPower } = useGetDRepVotingPowerQuery(voter); +type VotingPowerChipsProps = { + votingPower?: number; + isLoading?: boolean; + isShown?: boolean; +}; + +export const VotingPowerChips = ({ + isLoading, + isShown, + votingPower, +}: VotingPowerChipsProps) => { const { isMobile, screenWidth } = useScreenDimension(); const { t } = useTranslation(); return ( - (voter?.isRegisteredAsDRep || voter?.isRegisteredAsSoleVoter) && ( + isShown && ( { {t("votingPower")}: )} - {dRepVotingPower === undefined || isEnableLoading || !voter ? ( + {isLoading ? ( ) : ( { fontWeight={600} sx={{ whiteSpace: "nowrap" }} > - ₳ {correctAdaFormat(dRepVotingPower) ?? 0} + ₳ {correctAdaFormat(votingPower) ?? 0} )} diff --git a/govtool/frontend/src/components/organisms/DashboardTopNav.tsx b/govtool/frontend/src/components/organisms/DashboardTopNav.tsx index 369483e7a..7f5e94ffc 100644 --- a/govtool/frontend/src/components/organisms/DashboardTopNav.tsx +++ b/govtool/frontend/src/components/organisms/DashboardTopNav.tsx @@ -3,8 +3,13 @@ import { Box, IconButton } from "@mui/material"; import { VotingPowerChips, Typography } from "@atoms"; import { ICONS } from "@consts"; -import { useScreenDimension } from "@hooks"; +import { + useGetDRepVotingPowerQuery, + useGetVoterInfo, + useScreenDimension, +} from "@hooks"; import { DashboardDrawerMobile } from "@organisms"; +import { useCardano } from "@context"; type DashboardTopNavProps = { title: string; @@ -20,6 +25,9 @@ export const DashboardTopNav = ({ const [windowScroll, setWindowScroll] = useState(0); const { isMobile } = useScreenDimension(); const [isDrawerOpen, setIsDrawerOpen] = useState(false); + const { isEnableLoading } = useCardano(); + const { voter } = useGetVoterInfo(); + const { dRepVotingPower } = useGetDRepVotingPowerQuery(voter); const openDrawer = () => { setIsDrawerOpen(true); @@ -76,7 +84,17 @@ export const DashboardTopNav = ({ ) : null} - {!isVotingPowerHidden && } + {!isVotingPowerHidden && ( + + )} {isMobile && ( ; From 788bbde322c87356ad1e2599520ebe0d5a213bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Sworze=C5=84?= Date: Mon, 17 Jun 2024 13:55:32 +0200 Subject: [PATCH 10/15] fix test --- .../atoms/VotingPowerChips.test.tsx | 55 +++++++------------ 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx b/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx index af80779fc..114b29364 100644 --- a/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx +++ b/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx @@ -6,23 +6,23 @@ import * as Utils from "@utils"; import { VotingPowerChips } from "@atoms"; describe("VotingPowerChips", () => { - const mockUseCardano = vi.spyOn(Context, "useCardano"); - const mockUseGetDRepVotingPowerQuery = vi.spyOn( - Hooks, - "useGetDRepVotingPowerQuery", - ); + // const mockUseCardano = vi.spyOn(Context, "useCardano"); + // const mockUseGetDRepVotingPowerQuery = vi.spyOn( + // Hooks, + // "useGetDRepVotingPowerQuery", + // ); const mockUseScreenDimension = vi.spyOn(Hooks, "useScreenDimension"); const mockCorrectAdaFormat = vi.spyOn(Utils, "correctAdaFormat"); const mockUseTranslation = vi.spyOn(Hooks, "useTranslation"); - const mockUseGetVoterInfo = vi.spyOn(Hooks, "useGetVoterInfo"); + // const mockUseGetVoterInfo = vi.spyOn(Hooks, "useGetVoterInfo"); it("renders loading spinner when data is loading", () => { - mockUseCardano.mockReturnValue({ - isEnableLoading: 'demos', - } as ReturnType); - mockUseGetDRepVotingPowerQuery.mockReturnValue( - {} as ReturnType, - ); + // mockUseCardano.mockReturnValue({ + // isEnableLoading: "demos", + // } as ReturnType); + // mockUseGetDRepVotingPowerQuery.mockReturnValue( + // {} as ReturnType, + // ); mockUseScreenDimension.mockReturnValue({ isMobile: false, screenWidth: 1024, @@ -30,21 +30,15 @@ describe("VotingPowerChips", () => { mockUseTranslation.mockReturnValue({ t: (key: string) => key, } as ReturnType); - mockUseGetVoterInfo.mockReturnValue( - { voter: { isRegisteredAsDRep: true } } as ReturnType, - ); + // mockUseGetVoterInfo.mockReturnValue({ + // voter: { isRegisteredAsDRep: true }, + // } as ReturnType); - render(); + render(); expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); it("displays formatted ADA amount when data is available and not loading", () => { - mockUseCardano.mockReturnValue({ - isEnableLoading: null, - } as ReturnType); - mockUseGetDRepVotingPowerQuery.mockReturnValue({ - dRepVotingPower: 1000, - } as ReturnType); mockUseScreenDimension.mockReturnValue({ isMobile: false, screenWidth: 1024, @@ -52,22 +46,13 @@ describe("VotingPowerChips", () => { mockUseTranslation.mockReturnValue({ t: (key: string) => key, } as ReturnType); - mockUseGetVoterInfo.mockReturnValue({ - voter: { isRegisteredAsDRep: true }, - } as ReturnType); mockCorrectAdaFormat.mockReturnValue(1000); - render(); + render(); expect(screen.getByText(/₳ 1000/)).toBeInTheDocument(); }); it("displays the tooltip correctly for non-mobile DRep registered users", async () => { - mockUseCardano.mockReturnValue({ - isEnableLoading: null, - } as ReturnType); - mockUseGetDRepVotingPowerQuery.mockReturnValue({ - dRepVotingPower: 1000, - } as ReturnType); mockUseScreenDimension.mockReturnValue({ isMobile: false, screenWidth: 800, @@ -75,12 +60,10 @@ describe("VotingPowerChips", () => { mockUseTranslation.mockReturnValue({ t: (key: string) => key, } as ReturnType); - mockUseGetVoterInfo.mockReturnValue({ - voter: { isRegisteredAsDRep: true }, - } as ReturnType); + mockCorrectAdaFormat.mockReturnValue(1000); - render(); + render(); const icon = screen.getByTestId("InfoOutlinedIcon"); fireEvent.mouseOver(icon); From 98fb67b416f4cbb499d63b0302be94cf18cbf7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Sworze=C5=84?= Date: Mon, 17 Jun 2024 14:22:27 +0200 Subject: [PATCH 11/15] delete unnecessary code --- govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx b/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx index 114b29364..fa38253e3 100644 --- a/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx +++ b/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx @@ -1,7 +1,6 @@ import { render, screen, fireEvent } from "@testing-library/react"; import { describe, it, expect, vi } from "vitest"; import * as Hooks from "@hooks"; -import * as Context from "@context"; import * as Utils from "@utils"; import { VotingPowerChips } from "@atoms"; From 954f7f6e62f8d67e6851a93f3d77d9aa811ad3eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Sworze=C5=84?= Date: Tue, 18 Jun 2024 09:27:23 +0200 Subject: [PATCH 12/15] remove coments --- .../components/atoms/VotingPowerChips.test.tsx | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx b/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx index fa38253e3..8ec10f9fd 100644 --- a/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx +++ b/govtool/frontend/src/components/atoms/VotingPowerChips.test.tsx @@ -5,23 +5,11 @@ import * as Utils from "@utils"; import { VotingPowerChips } from "@atoms"; describe("VotingPowerChips", () => { - // const mockUseCardano = vi.spyOn(Context, "useCardano"); - // const mockUseGetDRepVotingPowerQuery = vi.spyOn( - // Hooks, - // "useGetDRepVotingPowerQuery", - // ); const mockUseScreenDimension = vi.spyOn(Hooks, "useScreenDimension"); const mockCorrectAdaFormat = vi.spyOn(Utils, "correctAdaFormat"); const mockUseTranslation = vi.spyOn(Hooks, "useTranslation"); - // const mockUseGetVoterInfo = vi.spyOn(Hooks, "useGetVoterInfo"); it("renders loading spinner when data is loading", () => { - // mockUseCardano.mockReturnValue({ - // isEnableLoading: "demos", - // } as ReturnType); - // mockUseGetDRepVotingPowerQuery.mockReturnValue( - // {} as ReturnType, - // ); mockUseScreenDimension.mockReturnValue({ isMobile: false, screenWidth: 1024, @@ -29,9 +17,6 @@ describe("VotingPowerChips", () => { mockUseTranslation.mockReturnValue({ t: (key: string) => key, } as ReturnType); - // mockUseGetVoterInfo.mockReturnValue({ - // voter: { isRegisteredAsDRep: true }, - // } as ReturnType); render(); expect(screen.getByRole("progressbar")).toBeInTheDocument(); From 821dd307557580efc2e72d00b12119be5f26171b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Mon, 17 Jun 2024 15:31:30 +0200 Subject: [PATCH 13/15] fix: dashboard action card drepId storybook test fix images on loading test --- .../frontend/src/components/molecules/CopyableInfo.tsx | 2 +- govtool/frontend/src/stories/DashboardCard.stories.tsx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/govtool/frontend/src/components/molecules/CopyableInfo.tsx b/govtool/frontend/src/components/molecules/CopyableInfo.tsx index 792aabc72..ac0875ebc 100644 --- a/govtool/frontend/src/components/molecules/CopyableInfo.tsx +++ b/govtool/frontend/src/components/molecules/CopyableInfo.tsx @@ -20,7 +20,7 @@ export const CopyableInfo = ({ }: CopyableInfoProps) => ( ; async function assertCardInfo(canvas: ReturnType) { expect(canvas.getByText("Action card")).toBeVisible(); expect(canvas.queryByText(/lorem/i)).toBeInTheDocument(); - expect(canvas.queryByRole("img")).toBeInTheDocument(); + expect(canvas.queryAllByRole("img")).not.toHaveLength(0); } export const DashboardCardComponent: Story = { @@ -61,11 +61,13 @@ export const WithDRepIdDashboardCardComponent: Story = { ), }, play: async ({ canvasElement }) => { - const dRepId = ""; + const dRepId = "drep133vmtzlem9asdkl4jfs3f9mrg5jg34tymf4uzwj2nx0fgwyg9ds"; const canvas = within(canvasElement); await assertCardInfo(canvas); - await expect(canvas.getByTestId("drep-id-info")).toHaveTextContent(dRepId); + await expect( + canvas.getByTestId("dRep-id-display-card-dashboard"), + ).toHaveTextContent(dRepId); }, }; From 566b057838dc6da2962b019f2b77947006de4d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Tue, 18 Jun 2024 09:53:33 +0200 Subject: [PATCH 14/15] fix(#1244): Fix styling of the markdowns on the slider cards --- .../src/components/molecules/GovernanceActionCard.tsx | 1 + .../src/components/molecules/GovernanceActionCardElement.tsx | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/govtool/frontend/src/components/molecules/GovernanceActionCard.tsx b/govtool/frontend/src/components/molecules/GovernanceActionCard.tsx index b80fb194d..3dda9eda9 100644 --- a/govtool/frontend/src/components/molecules/GovernanceActionCard.tsx +++ b/govtool/frontend/src/components/molecules/GovernanceActionCard.tsx @@ -94,6 +94,7 @@ export const GovernanceActionCard: FC = ({ ...props }) => { textVariant="twoLines" dataTestId="governance-action-abstract" isSliderCard + isMarkdown /> {isMarkdown ? ( From beb84ebdfa3da3042107ae81f1c7c4a6e8ddc3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Tue, 18 Jun 2024 12:29:41 +0200 Subject: [PATCH 15/15] fix(#1313): fix blank screen on GAs voting when wallet is not initially connected --- CHANGELOG.md | 1 + govtool/frontend/src/components/molecules/WalletOption.tsx | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a53afcc5..fcbeb3afc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,6 +97,7 @@ changes. - Fix wrong link to the GA Details once it is in progress [Issue 1252](https://github.com/IntersectMBO/govtool/issues/1252) - Fix validation of the GAs with missing references [Issue 1282](https://github.com/IntersectMBO/govtool/issues/1282) - Fix displaying the GA Markdowns [Issue 1244](https://github.com/IntersectMBO/govtool/issues/1244) +- Fix app crash on voting on the GA without the connected wallet before [Issue 1313](https://github.com/IntersectMBO/govtool/issues/1313) ### Changed diff --git a/govtool/frontend/src/components/molecules/WalletOption.tsx b/govtool/frontend/src/components/molecules/WalletOption.tsx index 16a8ca4ff..f33b599aa 100644 --- a/govtool/frontend/src/components/molecules/WalletOption.tsx +++ b/govtool/frontend/src/components/molecules/WalletOption.tsx @@ -23,7 +23,7 @@ export const WalletOptionButton: FC = ({ cip95Available, pathToNavigate, }) => { - const { pathname, hash } = useLocation(); + const { pathname, hash, state } = useLocation(); const { enable, isEnableLoading } = useCardano(); const { palette: { lightBlue }, @@ -38,6 +38,7 @@ export const WalletOptionButton: FC = ({ pathToNavigate ?? pathname === "/" ? "/dashboard" : `connected${pathname}${hash}`, + { state }, ); return; }