diff --git a/apps/judicial-system/backend/src/app/modules/case/filters/case.filter.ts b/apps/judicial-system/backend/src/app/modules/case/filters/case.filter.ts index 36a406f4badb..110e22c09bdf 100644 --- a/apps/judicial-system/backend/src/app/modules/case/filters/case.filter.ts +++ b/apps/judicial-system/backend/src/app/modules/case/filters/case.filter.ts @@ -289,19 +289,19 @@ const canPrisonAdminUserAccessCase = ( ) { return false } - } - // Check defendant verdict appeal deadline access - const canAppealVerdict = true - const verdictInfo = (theCase.defendants || []).map< - [boolean, Date | undefined] - >((defendant) => [canAppealVerdict, defendant.verdictViewDate]) + // Check defendant verdict appeal deadline access + const canAppealVerdict = true + const verdictInfo = (theCase.defendants || []).map< + [boolean, Date | undefined] + >((defendant) => [canAppealVerdict, defendant.verdictViewDate]) - const [_, indictmentVerdictAppealDeadlineExpired] = - getIndictmentVerdictAppealDeadlineStatus(verdictInfo) + const [_, indictmentVerdictAppealDeadlineExpired] = + getIndictmentVerdictAppealDeadlineStatus(verdictInfo) - if (!indictmentVerdictAppealDeadlineExpired) { - return false + if (!indictmentVerdictAppealDeadlineExpired) { + return false + } } return true diff --git a/libs/api/domains/signature-collection/src/lib/signatureCollection.resolver.ts b/libs/api/domains/signature-collection/src/lib/signatureCollection.resolver.ts index 058ef2387074..340f5c6170a9 100644 --- a/libs/api/domains/signature-collection/src/lib/signatureCollection.resolver.ts +++ b/libs/api/domains/signature-collection/src/lib/signatureCollection.resolver.ts @@ -31,6 +31,7 @@ import { SignatureCollectionSignedList, SignatureCollectionSignee, } from './models' +import { SignatureCollectionListSummary } from './models/areaSummaryReport.model' @UseGuards(IdsUserGuard, ScopesGuard, UserAccessGuard) @Resolver() @@ -207,4 +208,16 @@ export class SignatureCollectionResolver { signee.candidate?.id, ) } + + @Scopes(ApiScope.signatureCollection) + @IsOwner() + @AllowManager() + @Query(() => SignatureCollectionListSummary) + @Audit() + async signatureCollectionListOverview( + @CurrentUser() user: User, + @Args('input') input: SignatureCollectionListIdInput, + ): Promise { + return this.signatureCollectionService.listOverview(user, input.listId) + } } diff --git a/libs/api/domains/signature-collection/src/lib/signatureCollection.service.ts b/libs/api/domains/signature-collection/src/lib/signatureCollection.service.ts index b714b5f2d10e..7bafbcbc7207 100644 --- a/libs/api/domains/signature-collection/src/lib/signatureCollection.service.ts +++ b/libs/api/domains/signature-collection/src/lib/signatureCollection.service.ts @@ -18,6 +18,7 @@ import { SignatureCollectionAddListsInput } from './dto/addLists.input' import { SignatureCollectionUploadPaperSignatureInput } from './dto/uploadPaperSignature.input' import { SignatureCollectionCanSignFromPaperInput } from './dto/canSignFromPaper.input' import { SignatureCollectionCollector } from './models/collector.model' +import { SignatureCollectionListSummary } from './models/areaSummaryReport.model' @Injectable() export class SignatureCollectionService { @@ -187,4 +188,14 @@ export class SignatureCollectionService { candidateId, ) } + + async listOverview( + user: User, + listId: string, + ): Promise { + return await this.signatureCollectionClientService.getListOverview( + user, + listId, + ) + } } diff --git a/libs/application/template-api-modules/src/lib/modules/templates/european-health-insurance-card/european-health-insurance-card.module.ts b/libs/application/template-api-modules/src/lib/modules/templates/european-health-insurance-card/european-health-insurance-card.module.ts index 035139b05d16..a53e188627b1 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/european-health-insurance-card/european-health-insurance-card.module.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/european-health-insurance-card/european-health-insurance-card.module.ts @@ -1,10 +1,10 @@ import { Module } from '@nestjs/common' import { SharedTemplateAPIModule } from '../../shared' import { EuropeanHealthInsuranceCardService } from './european-health-insurance-card.service' -import { EhicClientModule } from '@island.is/clients/ehic-client-v1' +import { RightsPortalClientModule } from '@island.is/clients/icelandic-health-insurance/rights-portal' @Module({ - imports: [EhicClientModule, SharedTemplateAPIModule], + imports: [SharedTemplateAPIModule, RightsPortalClientModule], providers: [EuropeanHealthInsuranceCardService], exports: [EuropeanHealthInsuranceCardService], }) diff --git a/libs/application/template-api-modules/src/lib/modules/templates/european-health-insurance-card/european-health-insurance-card.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/european-health-insurance-card/european-health-insurance-card.service.ts index acd4a4fc0568..46c16ccfed72 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/european-health-insurance-card/european-health-insurance-card.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/european-health-insurance-card/european-health-insurance-card.service.ts @@ -1,5 +1,4 @@ import { Inject, Injectable } from '@nestjs/common' -import { EhicApi } from '@island.is/clients/ehic-client-v1' import { LOGGER_PROVIDER } from '@island.is/logging' import type { Logger } from '@island.is/logging' import { @@ -18,7 +17,7 @@ import { } from './types' import { TemplateApiModuleActionProps } from '../../../types' import { Auth, AuthMiddleware } from '@island.is/auth-nest-tools' - +import { EhicApi } from '@island.is/clients/icelandic-health-insurance/rights-portal' @Injectable() export class EuropeanHealthInsuranceCardService extends BaseTemplateApiService { constructor( @@ -29,6 +28,10 @@ export class EuropeanHealthInsuranceCardService extends BaseTemplateApiService { super(ApplicationTypes.EUROPEAN_HEALTH_INSURANCE_CARD) } + private ehicApiWithAuth(auth: Auth) { + return this.ehicApi.withMiddleware(new AuthMiddleware(auth)) + } + /** Returns unique values of an array */ onlyUnique(value: string, index: number, array: string[]) { return array.indexOf(value) === index @@ -149,11 +152,9 @@ export class EuropeanHealthInsuranceCardService extends BaseTemplateApiService { const nridArr = this.getApplicants(application) if (nridArr?.length > 0) { try { - const resp = await this.ehicApi - .withMiddleware(new AuthMiddleware(auth as Auth)) - .cardStatus({ - applicantnationalids: this.toCommaDelimitedList(nridArr), - }) + const resp = await this.ehicApiWithAuth(auth).getEhicCardStatus({ + applicantnationalids: this.toCommaDelimitedList(nridArr), + }) if (!resp) { this.logger.error( @@ -188,12 +189,10 @@ export class EuropeanHealthInsuranceCardService extends BaseTemplateApiService { for (let i = 0; i < applicants?.length; i++) { try { - const res = await this.ehicApi - .withMiddleware(new AuthMiddleware(auth as Auth)) - .requestCard({ - applicantnationalid: applicants[i], - cardtype: CardType.PLASTIC, - }) + const res = await this.ehicApiWithAuth(auth).requestEhicCard({ + applicantnationalid: applicants[i], + cardtype: CardType.PLASTIC, + }) cardResponses.push(res) } catch (error) { this.logger.error('EHIC.API error applyForPhysicalCard', error) @@ -214,12 +213,10 @@ export class EuropeanHealthInsuranceCardService extends BaseTemplateApiService { for (let i = 0; i < applicants?.length; i++) { try { - await this.ehicApi - .withMiddleware(new AuthMiddleware(auth as Auth)) - .requestCard({ - applicantnationalid: applicants[i], - cardtype: CardType.PDF, - }) + await this.ehicApiWithAuth(auth).requestEhicCard({ + applicantnationalid: applicants[i], + cardtype: CardType.PDF, + }) } catch (error) { this.logger.error('EHIC.API error applyForTemporaryCard', error) throw error @@ -233,12 +230,14 @@ export class EuropeanHealthInsuranceCardService extends BaseTemplateApiService { for (let i = 0; i < applicants?.length; i++) { try { - const res = await this.ehicApi - .withMiddleware(new AuthMiddleware(auth as Auth)) - .fetchTempPDFCard({ - applicantnationalid: applicants[i].nationalId ?? '', - cardnumber: applicants[i].cardNumber ?? '', - }) + const { nationalId, cardNumber } = applicants[i] + if (!nationalId || !cardNumber) { + throw new Error('National ID or card number is missing') + } + const res = await this.ehicApiWithAuth(auth).fetchTempEhicPDFCard({ + applicantnationalid: nationalId, + cardnumber: cardNumber, + }) pdfArray.push(res) } catch (error) { this.logger.error('EHIC.API error getTemporaryCard', error) diff --git a/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/OldAgePensionTemplate.ts b/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/OldAgePensionTemplate.ts index 6523157edaec..eb2343ca151d 100644 --- a/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/OldAgePensionTemplate.ts +++ b/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/OldAgePensionTemplate.ts @@ -162,8 +162,8 @@ const OldAgePensionTemplate: ApplicationTemplate< }, pendingAction: { title: coreSIAStatesMessages.tryggingastofnunSubmittedTitle, - content: coreSIAStatesMessages.tryggingastofnunSubmittedContent, - displayStatus: 'info', + content: statesMessages.oldAgePensionSubmittedContent, + displayStatus: 'warning', }, historyLogs: [ { diff --git a/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/messages.ts b/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/messages.ts index a25ebcb76d34..47a792a7f72c 100644 --- a/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/messages.ts +++ b/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/messages.ts @@ -516,4 +516,11 @@ export const statesMessages = defineMessages({ defaultMessage: 'Umsókn vegna ellilífeyris hefur verið samþykkt', description: 'The application for old-age pension has been approved', }, + oldAgePensionSubmittedContent: { + id: 'oap.application:oldAgePensionSubmittedContent#markdown', + defaultMessage: + 'Umsókn þín er í bið eftir yfirferð. Hægt er að breyta umsókn þar til hún er tekin til yfirferðar. Athugið að ef ekki er búið að skila inn tekjuáætlun þarf að gera það hér.', + description: + 'Your application is awaiting review. It is possible to edit the application until it is under review. Please note that if you have not submitted an income plan, you must do so here.', + }, }) diff --git a/libs/clients/signature-collection/src/clientConfig.json b/libs/clients/signature-collection/src/clientConfig.json index fe45f37d9a21..e6f3ad6b4575 100644 --- a/libs/clients/signature-collection/src/clientConfig.json +++ b/libs/clients/signature-collection/src/clientConfig.json @@ -1076,6 +1076,41 @@ } } }, + "/Medmaelalistar/{ID}/Info": { + "get": { + "tags": ["Medmaelalistar"], + "summary": "Skilar yfirliti fyrir ákveðinn meðmælalista", + "description": "Framboð geta sótt yfirlit fyrir sína eigin lista", + "parameters": [ + { + "name": "ID", + "in": "path", + "description": "ID meðmælalista", + "required": true, + "schema": { "type": "integer", "format": "int32" } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MedmaelalistiExtendedDTO" + } + } + } + }, + "204": { "description": "No Content" }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { "schema": { "type": "string" } } + } + } + } + } + }, "/Medmaelalistar/{ID}/Medmaeli": { "get": { "tags": ["Medmaelalistar"], diff --git a/libs/clients/signature-collection/src/lib/signature-collection.service.ts b/libs/clients/signature-collection/src/lib/signature-collection.service.ts index 8e74cf8d434c..a94a6dfebe91 100644 --- a/libs/clients/signature-collection/src/lib/signature-collection.service.ts +++ b/libs/clients/signature-collection/src/lib/signature-collection.service.ts @@ -23,6 +23,7 @@ import { mapCandidate } from './types/candidate.dto' import { Slug } from './types/slug.dto' import { Auth, AuthMiddleware, User } from '@island.is/auth-nest-tools' import { SignatureCollectionSharedClientService } from './signature-collection-shared.service' +import { ListSummary, mapListSummary } from './types/areaSummaryReport.dto' type Api = MedmaelalistarApi | MedmaelasofnunApi | MedmaeliApi | FrambodApi @Injectable() @@ -561,4 +562,15 @@ export class SignatureCollectionClientService { })) ?? [] ) } + + async getListOverview(auth: User, listId: string): Promise { + const summary = await this.getApiWithAuth( + this.listsApi, + auth, + ).medmaelalistarIDInfoGet({ + iD: parseInt(listId), + }) + + return mapListSummary(summary) + } } diff --git a/libs/nest/core/src/index.ts b/libs/nest/core/src/index.ts index 12b0afeebfad..e6b84b1639ef 100644 --- a/libs/nest/core/src/index.ts +++ b/libs/nest/core/src/index.ts @@ -1,3 +1,4 @@ export * from './lib/decorators/nationalId.decorator' +export * from './lib/decorators/ParsedUserAgent.decorator' export * from './lib/validators/isPersonNationalId.decorator' export * from './lib/validators/isNationalId.decorator' diff --git a/libs/nest/core/src/lib/decorators/ParsedUserAgent.decorator.spec.ts b/libs/nest/core/src/lib/decorators/ParsedUserAgent.decorator.spec.ts new file mode 100644 index 000000000000..0e8a07a28c64 --- /dev/null +++ b/libs/nest/core/src/lib/decorators/ParsedUserAgent.decorator.spec.ts @@ -0,0 +1,78 @@ +import { parseUserAgent } from './ParsedUserAgent.decorator' + +describe('parseUserAgent Function', () => { + it('should parse new iOS app user agent', () => { + // Arrange + const userAgentString = 'IslandIsApp (1.0.0) Build/321 (ios/9.0.0)' + + // Act + const result = parseUserAgent(userAgentString) + + // Assert + expect(result).toEqual({ + ua: userAgentString, + os: { name: 'iOS', version: '9.0.0' }, + app: { name: 'IslandIsApp', version: '1.0.0', build: 321 }, + }) + }) + + it('should parse new Android app user agent', () => { + // Arrange + const userAgentString = 'IslandIsApp (2.1.0) Build/123 (android/11.0.0)' + + // Act + const result = parseUserAgent(userAgentString) + + // Assert + expect(result).toEqual({ + ua: userAgentString, + os: { name: 'Android', version: '11.0.0' }, + app: { name: 'IslandIsApp', version: '2.1.0', build: 123 }, + }) + }) + + it('should parse old iOS app user agent', () => { + // Arrange + const userAgentString = 'IslandApp/144 CFNetwork/1498.700.2 Darwin/23.6.0' + + // Act + const result = parseUserAgent(userAgentString) + + // Assert + expect(result).toEqual({ + ua: userAgentString, + os: { name: 'iOS' }, + app: { name: 'IslandIsApp' }, + }) + }) + + it('should parse old Android app user agent', () => { + // Arrange + const userAgentString = 'okhttp/4.9.2' + + // Act + const result = parseUserAgent(userAgentString) + + // Assert + expect(result).toEqual({ + ua: userAgentString, + os: { name: 'Android' }, + app: { name: 'IslandIsApp' }, + }) + }) + + it('should return empty app and os for unknown user agent', () => { + // Arrange + const userAgentString = 'UnknownUserAgent/1.0' + + // Act + const result = parseUserAgent(userAgentString) + + // Assert + expect(result).toEqual({ + ua: userAgentString, + os: {}, + app: {}, + }) + }) +}) diff --git a/libs/nest/core/src/lib/decorators/ParsedUserAgent.decorator.ts b/libs/nest/core/src/lib/decorators/ParsedUserAgent.decorator.ts new file mode 100644 index 000000000000..13ea5c5b6702 --- /dev/null +++ b/libs/nest/core/src/lib/decorators/ParsedUserAgent.decorator.ts @@ -0,0 +1,92 @@ +import { getRequest } from '@island.is/auth-nest-tools' +import { createParamDecorator, ExecutionContext } from '@nestjs/common' + +// Old iOS app user agents: +// - IslandApp/144 CFNetwork/1498.700.2 Darwin/23.6.0 + +// Old Android app user agents. We associate it with IslandIsApp, assuming +// there are no other React Native android apps calling our API. +// - okhttp/4.9.2 + +// New app user agents +// - IslandIsApp (1.0.0}) Build/321 (ios/9.0.0) +// - IslandIsApp (1.0.0}) Build/321 (android/9.0.0) + +export interface UserAgent { + ua: string + os: { + name?: 'iOS' | 'Android' + version?: string + } + app: { + name?: 'IslandIsApp' + version?: string + build?: number + } +} + +/** + * Parses the user agent string and returns an object with the user agent, os and app information. + * + * Only supports parsing IslandIsApp user agents to start with but the interface is + * future compatible if we want to parse more user agents with ua-parser-js. + */ +export const parseUserAgent = (userAgentString: string): UserAgent => { + const userAgent: UserAgent = { + ua: userAgentString, + os: {}, + app: {}, + } + + // Match new app user agents + const newAppRegex = + /IslandIsApp \(([^)]+)\) Build\/(\d+) \((ios|android)\/([^)]+)\)/ + const newAppMatch = userAgentString.match(newAppRegex) + + if (newAppMatch) { + userAgent.app.name = 'IslandIsApp' + userAgent.app.version = newAppMatch[1] + userAgent.app.build = parseInt(newAppMatch[2], 10) + userAgent.os.name = newAppMatch[3] === 'ios' ? 'iOS' : 'Android' + userAgent.os.version = newAppMatch[4] + return userAgent + } + + // Match old iOS app user agents + const oldIosRegex = /IslandApp\/\d+ CFNetwork\/[^\s]+ Darwin\/[^\s]+/ + const oldIosMatch = userAgentString.match(oldIosRegex) + + if (oldIosMatch) { + userAgent.app.name = 'IslandIsApp' + userAgent.os.name = 'iOS' + return userAgent + } + + // Match old Android app user agents + const oldAndroidRegex = /okhttp\/[^\s]+/ + const oldAndroidMatch = userAgentString.match(oldAndroidRegex) + + if (oldAndroidMatch) { + userAgent.app.name = 'IslandIsApp' + userAgent.os.name = 'Android' + return userAgent + } + + // Default return, if no patterns matched + return userAgent +} + +/** + * Decorator that parses the user agent string from the request headers and returns an object with the user agent, os + * and app information. + * + * Only supports parsing IslandIsApp user agents for now. + */ +export const ParsedUserAgent = createParamDecorator( + (_: unknown, context: ExecutionContext): UserAgent => { + const request = getRequest(context) + const userAgentString = request.headers['user-agent'] || '' + + return parseUserAgent(userAgentString) + }, +) diff --git a/libs/portals/admin/signature-collection/src/lib/messages.ts b/libs/portals/admin/signature-collection/src/lib/messages.ts index 624895b9f682..f5ba0db59386 100644 --- a/libs/portals/admin/signature-collection/src/lib/messages.ts +++ b/libs/portals/admin/signature-collection/src/lib/messages.ts @@ -13,7 +13,7 @@ export const m = defineMessages({ description: '', }, signatureListsTitlePresidential: { - id: 'admin-portal.signature-collection-parliamentary:signatureLists', + id: 'admin-portal.signature-collection:signatureListsTitlePresidential', defaultMessage: 'Forsetakosningar', description: '', }, @@ -166,6 +166,23 @@ export const m = defineMessages({ defaultMessage: 'Forsetakosningar 2024', description: '', }, + parliamentaryCollectionTitle: { + id: 'admin-portal.signature-collection:parliamentaryCollectionTitle', + defaultMessage: 'Alþingiskosningar', + description: '', + }, + parliamentaryCollectionIntro: { + id: 'admin-portal.signature-collection:parliamentaryCollectionIntro', + defaultMessage: + 'Hér er yfirlit yfir kjördæmin sex. Ýttu á viðeigandi kjördæmi til að sjá meðmælendalista í því kjördæmi.', + description: '', + }, + parliamentaryConstituencyIntro: { + id: 'admin-portal.signature-collection:parliamentaryConstituencyIntro', + defaultMessage: + 'Hér er yfirlit yfir allar meðmælasafnanir sem stofnaðar hafa verið í', + description: '', + }, viewList: { id: 'admin-portal.signature-collection:viewList', defaultMessage: 'Skoða söfnun', @@ -713,41 +730,6 @@ export const m = defineMessages({ }, }) -export const parliamentaryMessages = defineMessages({ - signatureListsTitle: { - id: 'admin-portal.signature-collection-parliamentary:signatureLists', - defaultMessage: 'Alþingiskosningar', - description: '', - }, - signatureListsDescription: { - id: 'admin-portal.signature-collection-parliamentary:signatureListsDescription', - defaultMessage: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', - description: '', - }, - signatureListsIntro: { - id: 'admin-portal.signature-collection-parliamentary:signatureListsIntro', - defaultMessage: - 'Hér er yfirlit yfir kjördæmin sex. Ýttu á viðeigandi kjördæmi til að sjá meðmælendalista í því kjördæmi.', - description: '', - }, - compareListsButton: { - id: 'admin-portal.signature-collection-parliamentary:compareListsButton', - defaultMessage: 'Bera saman', - description: '', - }, - compareListsDescription: { - id: 'admin-portal.signature-collection-parliamentary:compareListsDescription', - defaultMessage: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', - description: '', - }, - singleConstituencyIntro: { - id: 'admin-portal.signature-collection-parliamentary:singleConstituencyIntro', - defaultMessage: - 'Hér er yfirlit yfir allar meðmælasafnanir sem stofnaðar hafa verið í', - description: '', - }, -}) - export const createCollectionErrorMessages = defineMessages({ age: { id: 'admin-portal.signature-collection:error.age', diff --git a/libs/portals/admin/signature-collection/src/lib/navigation.ts b/libs/portals/admin/signature-collection/src/lib/navigation.ts index c48d371f7453..419e13dc59d7 100644 --- a/libs/portals/admin/signature-collection/src/lib/navigation.ts +++ b/libs/portals/admin/signature-collection/src/lib/navigation.ts @@ -1,6 +1,6 @@ import { PortalNavigationItem } from '@island.is/portals/core' import { SignatureCollectionPaths } from './paths' -import { m, parliamentaryMessages } from './messages' +import { m } from './messages' export const signatureCollectionNavigation: PortalNavigationItem = { name: m.signatureListsTitle, @@ -11,7 +11,7 @@ export const signatureCollectionNavigation: PortalNavigationItem = { path: SignatureCollectionPaths.ParliamentaryRoot, children: [ { - name: parliamentaryMessages.signatureListsTitle, + name: m.parliamentaryCollectionTitle, path: SignatureCollectionPaths.ParliamentaryRoot, activeIfExact: true, }, diff --git a/libs/portals/admin/signature-collection/src/screens-parliamentary/Constituency/index.tsx b/libs/portals/admin/signature-collection/src/screens-parliamentary/Constituency/index.tsx index 7304c109ed0a..cc7ae4cd8152 100644 --- a/libs/portals/admin/signature-collection/src/screens-parliamentary/Constituency/index.tsx +++ b/libs/portals/admin/signature-collection/src/screens-parliamentary/Constituency/index.tsx @@ -1,7 +1,7 @@ import { IntroHeader, PortalNavigation } from '@island.is/portals/core' import { signatureCollectionNavigation } from '../../lib/navigation' import { useLocale } from '@island.is/localization' -import { m, parliamentaryMessages } from '../../lib/messages' +import { m } from '../../lib/messages' import { ActionCard, Box, @@ -90,9 +90,7 @@ export const Constituency = ({ - {constituencyLists?.length > 0 && ( + {allowedToProcess && constituencyLists?.length > 0 && ( )} @@ -142,97 +140,96 @@ export const Constituency = ({ maxProgress: list.area.min, withLabel: true, }} - cta={ - (allowedToProcess && !list.active) || !allowedToProcess - ? { - label: formatMessage(m.viewList), - variant: 'text', - onClick: () => { - navigate( - SignatureCollectionPaths.ParliamentaryConstituencyList.replace( - ':constituencyName', - constituencyName, - ).replace(':listId', list.id), - ) - }, - } - : undefined - } + cta={{ + label: formatMessage(m.viewList), + variant: 'text', + onClick: () => { + navigate( + SignatureCollectionPaths.ParliamentaryConstituencyList.replace( + ':constituencyName', + constituencyName, + ).replace(':listId', list.id), + ) + }, + }} tag={ !list.reviewed - ? { - label: 'Cancel collection', - renderTag: () => ( - - - - - - } - onConfirm={() => { - removeList({ - variables: { - input: { - listId: list.id, - }, - }, - }) - - if ( + ? allowedToProcess + ? { + label: 'Cancel collection', + renderTag: () => ( + + + + + + } + onConfirm={() => { + removeList({ variables: { input: { - candidateId: list.candidate.id, + listId: list.id, }, }, }) + + if ( + candidatesListCount[list.candidate.id] === + 1 + ) { + removeCandidate({ + variables: { + input: { + candidateId: list.candidate.id, + }, + }, + }) + } + }} + buttonTextConfirm={ + candidatesListCount[list.candidate.id] === 1 + ? formatMessage( + m.cancelCollectionAndCandidateModalConfirmButton, + ) + : formatMessage( + m.cancelCollectionModalConfirmButton, + ) } - }} - buttonTextConfirm={ - candidatesListCount[list.candidate.id] === 1 - ? formatMessage( - m.cancelCollectionAndCandidateModalConfirmButton, - ) - : formatMessage( - m.cancelCollectionModalConfirmButton, - ) - } - buttonPropsConfirm={{ - variant: 'primary', - colorScheme: 'destructive', - }} - buttonTextCancel={formatMessage( - m.cancelCollectionModalCancelButton, - )} - /> - ), - } + buttonPropsConfirm={{ + variant: 'primary', + colorScheme: 'destructive', + }} + buttonTextCancel={formatMessage( + m.cancelCollectionModalCancelButton, + )} + /> + ), + } + : undefined : { - label: m.confirmListReviewed.defaultMessage, + label: formatMessage(m.confirmListReviewed), variant: 'mint', outlined: false, } diff --git a/libs/portals/admin/signature-collection/src/screens-parliamentary/List/index.tsx b/libs/portals/admin/signature-collection/src/screens-parliamentary/List/index.tsx index b342542ddc29..48c8d6d1969e 100644 --- a/libs/portals/admin/signature-collection/src/screens-parliamentary/List/index.tsx +++ b/libs/portals/admin/signature-collection/src/screens-parliamentary/List/index.tsx @@ -8,7 +8,7 @@ import { import { useLocale } from '@island.is/localization' import { IntroHeader, PortalNavigation } from '@island.is/portals/core' import { signatureCollectionNavigation } from '../../lib/navigation' -import { m, parliamentaryMessages } from '../../lib/messages' +import { m } from '../../lib/messages' import { useLoaderData } from 'react-router-dom' import { ListStatus, SignatureCollectionList } from '@island.is/api/schema' import { PaperSignees } from './paperSignees' @@ -48,9 +48,7 @@ const List = ({ allowedToProcess }: { allowedToProcess: boolean }) => { { } type={listStatus === ListStatus.Reviewed ? 'success' : undefined} /> - - - - + + {(allowedToProcess && !list.active) || + (!allowedToProcess && ( + + ))} + {allowedToProcess && ( + + {!list.active && } + + + )} diff --git a/libs/portals/admin/signature-collection/src/screens-parliamentary/index.tsx b/libs/portals/admin/signature-collection/src/screens-parliamentary/index.tsx index 3a0b0b940abf..1c1e155ad4c3 100644 --- a/libs/portals/admin/signature-collection/src/screens-parliamentary/index.tsx +++ b/libs/portals/admin/signature-collection/src/screens-parliamentary/index.tsx @@ -13,7 +13,7 @@ import { import { useLocale } from '@island.is/localization' import { IntroHeader, PortalNavigation } from '@island.is/portals/core' import { signatureCollectionNavigation } from '../lib/navigation' -import { m, parliamentaryMessages } from '../lib/messages' +import { m } from '../lib/messages' import { useLoaderData, useNavigate } from 'react-router-dom' import { SignatureCollectionPaths } from '../lib/paths' import CompareLists from '../shared-components/compareLists' @@ -68,16 +68,14 @@ const ParliamentaryRoot = ({ - + {allowedToProcess && ( + + )} {loading && ( @@ -202,7 +202,7 @@ const ParliamentaryRoot = ({ /> ))} - + {allowedToProcess && } diff --git a/libs/portals/admin/signature-collection/src/screens-presidential/AllLists/index.tsx b/libs/portals/admin/signature-collection/src/screens-presidential/AllLists/index.tsx index eca58fdf7704..37dc264b12f2 100644 --- a/libs/portals/admin/signature-collection/src/screens-presidential/AllLists/index.tsx +++ b/libs/portals/admin/signature-collection/src/screens-presidential/AllLists/index.tsx @@ -265,7 +265,7 @@ const Lists = ({ allowedToProcess }: { allowedToProcess: boolean }) => { tag={ list.reviewed ? { - label: m.confirmListReviewed.defaultMessage, + label: formatMessage(m.confirmListReviewed), variant: 'mint', outlined: false, } diff --git a/libs/portals/admin/signature-collection/src/shared-components/completeReview/index.tsx b/libs/portals/admin/signature-collection/src/shared-components/completeReview/index.tsx index 96b5b1488381..5240b0db9dfc 100644 --- a/libs/portals/admin/signature-collection/src/shared-components/completeReview/index.tsx +++ b/libs/portals/admin/signature-collection/src/shared-components/completeReview/index.tsx @@ -6,7 +6,7 @@ import { useToggleListReviewMutation } from './toggleListReview.generated' import { useRevalidator } from 'react-router-dom' import { m } from '../../lib/messages' import { ListStatus } from '../../lib/utils' -import LockList from './lockList' +import ActionLockList from './lockList' const ActionReviewComplete = ({ listId, @@ -41,14 +41,15 @@ const ActionReviewComplete = ({ }) return ( - + - + diff --git a/libs/portals/admin/signature-collection/src/shared-components/completeReview/lockList/index.tsx b/libs/portals/admin/signature-collection/src/shared-components/completeReview/lockList/index.tsx index 5a95d7203aee..f8886457f401 100644 --- a/libs/portals/admin/signature-collection/src/shared-components/completeReview/lockList/index.tsx +++ b/libs/portals/admin/signature-collection/src/shared-components/completeReview/lockList/index.tsx @@ -4,7 +4,7 @@ import { useState } from 'react' import { Modal } from '@island.is/react/components' import { useRevalidator } from 'react-router-dom' import { m } from '../../../lib/messages' -import { ListStatus } from '../../../lib/utils' +import { ListStatus } from '@island.is/api/schema' import { useSignatureCollectionLockListMutation } from './lockList.generated' const ActionLockList = ({ @@ -44,6 +44,7 @@ const ActionLockList = ({ icon="lockClosed" colorScheme="destructive" onClick={() => setModalLockListIsOpen(true)} + disabled={listStatus !== ListStatus.Active} > {formatMessage(m.lockList)} diff --git a/libs/portals/admin/signature-collection/src/shared-components/createCollection/index.tsx b/libs/portals/admin/signature-collection/src/shared-components/createCollection/index.tsx index 73cb544d1093..12c03e5c9596 100644 --- a/libs/portals/admin/signature-collection/src/shared-components/createCollection/index.tsx +++ b/libs/portals/admin/signature-collection/src/shared-components/createCollection/index.tsx @@ -153,7 +153,6 @@ const CreateCollection = ({ collectionId }: { collectionId: string }) => { label={formatMessage(m.candidateName)} readOnly value={name} - placeholder={loadingCandidate ? 'Sæki nafn...' : ''} /> {!canCreate && ( @@ -170,7 +169,7 @@ const CreateCollection = ({ collectionId }: { collectionId: string }) => { onClick={() => { createNewCollection() }} - disabled={!canCreate} + disabled={!canCreate || !name} loading={loading} > {formatMessage(m.createCollection)} diff --git a/libs/portals/admin/signature-collection/src/shared-components/extendDeadline/index.tsx b/libs/portals/admin/signature-collection/src/shared-components/extendDeadline/index.tsx index c37ee13b4141..b49d827c5f7e 100644 --- a/libs/portals/admin/signature-collection/src/shared-components/extendDeadline/index.tsx +++ b/libs/portals/admin/signature-collection/src/shared-components/extendDeadline/index.tsx @@ -68,6 +68,7 @@ const ActionExtendDeadline = ({ icon="calendar" iconType="outline" variant="ghost" + disabled={!allowedToProcess} onClick={() => setModalChangeDateIsOpen(true)} >