diff --git a/apps/api/src/app/app.module.ts b/apps/api/src/app/app.module.ts index 7431d688223a..0cae9d7fa483 100644 --- a/apps/api/src/app/app.module.ts +++ b/apps/api/src/app/app.module.ts @@ -154,6 +154,7 @@ import { IdsClientConfig, XRoadConfig, } from '@island.is/nest/config' +import { CodeOwnerInterceptor } from '@island.is/nest/core' import { DataLoaderInterceptor } from '@island.is/nest/dataloader' import { FeatureFlagConfig } from '@island.is/nest/feature-flags' import { ProblemModule } from '@island.is/nest/problem' @@ -175,6 +176,7 @@ import { FormSystemModule } from '@island.is/api/domains/form-system' import { HealthDirectorateModule } from '@island.is/api/domains/health-directorate' import { VehiclesMileageClientConfig } from '@island.is/clients/vehicles-mileage' + import { getConfig } from './environments' import { GraphqlOptionsFactory } from './graphql-options.factory' import { GraphQLConfig } from './graphql.config' @@ -212,6 +214,10 @@ const environment = getConfig provide: APP_INTERCEPTOR, useClass: DataLoaderInterceptor, }, + { + provide: APP_INTERCEPTOR, + useClass: CodeOwnerInterceptor, + }, ], imports: [ GraphQLModule.forRootAsync({ diff --git a/apps/application-system/api/infra/application-system-api.ts b/apps/application-system/api/infra/application-system-api.ts index e4c51330e256..9cb0aa3406ea 100644 --- a/apps/application-system/api/infra/application-system-api.ts +++ b/apps/application-system/api/infra/application-system-api.ts @@ -1,4 +1,9 @@ -import { ref, service, ServiceBuilder } from '../../../../infra/src/dsl/dsl' +import { + CodeOwners, + ref, + service, + ServiceBuilder, +} from '../../../../infra/src/dsl/dsl' import { Base, ChargeFjsV2, @@ -44,79 +49,83 @@ export const GRAPHQL_API_URL_ENV_VAR_NAME = 'GRAPHQL_API_URL' // This property i const namespace = 'application-system' const serviceAccount = 'application-system-api' -export const workerSetup = - (): ServiceBuilder<'application-system-api-worker'> => - service('application-system-api-worker') - .namespace(namespace) - .image('application-system-api') - .db() - .serviceAccount('application-system-api-worker') - .redis() - .env({ - IDENTITY_SERVER_CLIENT_ID: '@island.is/clients/application-system', - IDENTITY_SERVER_ISSUER_URL: { - dev: 'https://identity-server.dev01.devland.is', - staging: 'https://identity-server.staging01.devland.is', - prod: 'https://innskra.island.is', - }, - XROAD_CHARGE_FJS_V2_PATH: { - dev: 'IS-DEV/GOV/10021/FJS-Public/chargeFJS_v2', - staging: 'IS-TEST/GOV/10021/FJS-Public/chargeFJS_v2', - prod: 'IS/GOV/5402697509/FJS-Public/chargeFJS_v2', - }, - APPLICATION_ATTACHMENT_BUCKET: { - dev: 'island-is-dev-storage-application-system', - staging: 'island-is-staging-storage-application-system', - prod: 'island-is-prod-storage-application-system', - }, - FILE_SERVICE_PRESIGN_BUCKET: { - dev: 'island-is-dev-fs-presign-bucket', - staging: 'island-is-staging-fs-presign-bucket', - prod: 'island-is-prod-fs-presign-bucket', - }, - FILE_STORAGE_UPLOAD_BUCKET: { - dev: 'island-is-dev-upload-api', - staging: 'island-is-staging-upload-api', - prod: 'island-is-prod-upload-api', - }, - CLIENT_LOCATION_ORIGIN: { - dev: 'https://beta.dev01.devland.is/umsoknir', - staging: 'https://beta.staging01.devland.is/umsoknir', - prod: 'https://island.is/umsoknir', - local: 'http://localhost:4200/umsoknir', - }, - }) - .xroad(Base, Client, Payment, Inna, EHIC, WorkMachines) - .secrets({ - IDENTITY_SERVER_CLIENT_SECRET: - '/k8s/application-system/api/IDENTITY_SERVER_CLIENT_SECRET', - SYSLUMENN_HOST: '/k8s/application-system-api/SYSLUMENN_HOST', - SYSLUMENN_USERNAME: '/k8s/application-system/api/SYSLUMENN_USERNAME', - SYSLUMENN_PASSWORD: '/k8s/application-system/api/SYSLUMENN_PASSWORD', - DRIVING_LICENSE_BOOK_XROAD_PATH: - '/k8s/application-system-api/DRIVING_LICENSE_BOOK_XROAD_PATH', - DRIVING_LICENSE_BOOK_USERNAME: - '/k8s/application-system-api/DRIVING_LICENSE_BOOK_USERNAME', - DRIVING_LICENSE_BOOK_PASSWORD: - '/k8s/application-system-api/DRIVING_LICENSE_BOOK_PASSWORD', - DOKOBIT_ACCESS_TOKEN: - '/k8s/application-system/api/DOKOBIT_ACCESS_TOKEN', - DOKOBIT_URL: '/k8s/application-system-api/DOKOBIT_URL', - ARK_BASE_URL: '/k8s/application-system-api/ARK_BASE_URL', - DOMSYSLA_PASSWORD: '/k8s/application-system-api/DOMSYSLA_PASSWORD', - DOMSYSLA_USERNAME: '/k8s/application-system-api/DOMSYSLA_USERNAME', - }) - .args('main.js', '--job', 'worker') - .command('node') - .extraAttributes({ - dev: { schedule: '*/30 * * * *' }, - staging: { schedule: '*/30 * * * *' }, - prod: { schedule: '*/30 * * * *' }, - }) - .resources({ - limits: { cpu: '400m', memory: '768Mi' }, - requests: { cpu: '150m', memory: '384Mi' }, - }) +export const workerSetup = (services: { + userNotificationService: ServiceBuilder<'services-user-notification'> +}): ServiceBuilder<'application-system-api-worker'> => + service('application-system-api-worker') + .namespace(namespace) + .image('application-system-api') + .db() + .serviceAccount('application-system-api-worker') + .redis() + .codeOwner(CodeOwners.NordaApplications) + .env({ + IDENTITY_SERVER_CLIENT_ID: '@island.is/clients/application-system', + IDENTITY_SERVER_ISSUER_URL: { + dev: 'https://identity-server.dev01.devland.is', + staging: 'https://identity-server.staging01.devland.is', + prod: 'https://innskra.island.is', + }, + XROAD_CHARGE_FJS_V2_PATH: { + dev: 'IS-DEV/GOV/10021/FJS-Public/chargeFJS_v2', + staging: 'IS-TEST/GOV/10021/FJS-Public/chargeFJS_v2', + prod: 'IS/GOV/5402697509/FJS-Public/chargeFJS_v2', + }, + APPLICATION_ATTACHMENT_BUCKET: { + dev: 'island-is-dev-storage-application-system', + staging: 'island-is-staging-storage-application-system', + prod: 'island-is-prod-storage-application-system', + }, + FILE_SERVICE_PRESIGN_BUCKET: { + dev: 'island-is-dev-fs-presign-bucket', + staging: 'island-is-staging-fs-presign-bucket', + prod: 'island-is-prod-fs-presign-bucket', + }, + FILE_STORAGE_UPLOAD_BUCKET: { + dev: 'island-is-dev-upload-api', + staging: 'island-is-staging-upload-api', + prod: 'island-is-prod-upload-api', + }, + CLIENT_LOCATION_ORIGIN: { + dev: 'https://beta.dev01.devland.is/umsoknir', + staging: 'https://beta.staging01.devland.is/umsoknir', + prod: 'https://island.is/umsoknir', + local: 'http://localhost:4200/umsoknir', + }, + USER_NOTIFICATION_API_URL: ref( + (h) => `http://${h.svc(services.userNotificationService)}`, + ), + }) + .xroad(Base, Client, Payment, Inna, EHIC, WorkMachines) + .secrets({ + IDENTITY_SERVER_CLIENT_SECRET: + '/k8s/application-system/api/IDENTITY_SERVER_CLIENT_SECRET', + SYSLUMENN_HOST: '/k8s/application-system-api/SYSLUMENN_HOST', + SYSLUMENN_USERNAME: '/k8s/application-system/api/SYSLUMENN_USERNAME', + SYSLUMENN_PASSWORD: '/k8s/application-system/api/SYSLUMENN_PASSWORD', + DRIVING_LICENSE_BOOK_XROAD_PATH: + '/k8s/application-system-api/DRIVING_LICENSE_BOOK_XROAD_PATH', + DRIVING_LICENSE_BOOK_USERNAME: + '/k8s/application-system-api/DRIVING_LICENSE_BOOK_USERNAME', + DRIVING_LICENSE_BOOK_PASSWORD: + '/k8s/application-system-api/DRIVING_LICENSE_BOOK_PASSWORD', + DOKOBIT_ACCESS_TOKEN: '/k8s/application-system/api/DOKOBIT_ACCESS_TOKEN', + DOKOBIT_URL: '/k8s/application-system-api/DOKOBIT_URL', + ARK_BASE_URL: '/k8s/application-system-api/ARK_BASE_URL', + DOMSYSLA_PASSWORD: '/k8s/application-system-api/DOMSYSLA_PASSWORD', + DOMSYSLA_USERNAME: '/k8s/application-system-api/DOMSYSLA_USERNAME', + }) + .args('main.js', '--job', 'worker') + .command('node') + .extraAttributes({ + dev: { schedule: '*/30 * * * *' }, + staging: { schedule: '*/30 * * * *' }, + prod: { schedule: '*/30 * * * *' }, + }) + .resources({ + limits: { cpu: '400m', memory: '768Mi' }, + requests: { cpu: '150m', memory: '384Mi' }, + }) export const serviceSetup = (services: { documentsService: ServiceBuilder<'services-documents'> @@ -131,6 +140,7 @@ export const serviceSetup = (services: { .serviceAccount(serviceAccount) .command('node') .redis() + .codeOwner(CodeOwners.NordaApplications) .args('main.js') .env({ EMAIL_REGION: 'eu-west-1', diff --git a/apps/auth-admin-web/infra/auth-admin-web.ts b/apps/auth-admin-web/infra/auth-admin-web.ts index 44299b219a8d..476fde40c532 100644 --- a/apps/auth-admin-web/infra/auth-admin-web.ts +++ b/apps/auth-admin-web/infra/auth-admin-web.ts @@ -1,4 +1,4 @@ -import { service, ServiceBuilder } from '../../../infra/src/dsl/dsl' +import { CodeOwners, service, ServiceBuilder } from '../../../infra/src/dsl/dsl' const extraAnnotations = { 'nginx.ingress.kubernetes.io/proxy-buffer-size': '16k', @@ -12,6 +12,7 @@ export const serviceSetup = (): ServiceBuilder<'auth-admin-web'> => service('auth-admin-web') .namespace('identity-server-admin') .image('auth-admin-web') + .codeOwner(CodeOwners.Aranja) .env({ NEXT_PUBLIC_BACKEND_URL: '/backend', IDENTITYSERVER_DOMAIN: { diff --git a/apps/consultation-portal/infra/samradsgatt.ts b/apps/consultation-portal/infra/samradsgatt.ts index e7ed848cbab4..ffbe032843df 100644 --- a/apps/consultation-portal/infra/samradsgatt.ts +++ b/apps/consultation-portal/infra/samradsgatt.ts @@ -1,4 +1,9 @@ -import { ref, service, ServiceBuilder } from '../../../infra/src/dsl/dsl' +import { + CodeOwners, + ref, + service, + ServiceBuilder, +} from '../../../infra/src/dsl/dsl' export const serviceSetup = (services: { api: ServiceBuilder<'api'> @@ -7,6 +12,7 @@ export const serviceSetup = (services: { consultationService .image('consultation-portal') .namespace('consultation-portal') + .codeOwner(CodeOwners.Advania) .liveness('/liveness') .readiness('/liveness') .replicaCount({ @@ -28,6 +34,7 @@ export const serviceSetup = (services: { prod: 'innskra.island.is', }, NEXTAUTH_URL: { + local: 'http://localhost:4200/samradsgatt/api/auth', dev: 'https://beta.dev01.devland.is/samradsgatt/api/auth', staging: 'https://beta.staging01.devland.is/samradsgatt/api/auth', prod: 'https://island.is/samradsgatt/api/auth', diff --git a/apps/consultation-portal/proxy.config.json b/apps/consultation-portal/proxy.config.json deleted file mode 100644 index 1ec1f59e0a1a..000000000000 --- a/apps/consultation-portal/proxy.config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "/api/graphql": { - "target": "http://localhost:4444", - "secure": false - } -} diff --git a/apps/consultation-portal/proxy.config.ts b/apps/consultation-portal/proxy.config.ts new file mode 100644 index 000000000000..f11a5ea0c142 --- /dev/null +++ b/apps/consultation-portal/proxy.config.ts @@ -0,0 +1,8 @@ +const proxyConfig = { + '/api/graphql': { + target: process.env.API_URL ?? 'http://localhost:4444', + secure: false, + }, +} + +export default proxyConfig diff --git a/apps/consultation-portal/server.ts b/apps/consultation-portal/server.ts index c9dfb9850f13..29a716307e84 100644 --- a/apps/consultation-portal/server.ts +++ b/apps/consultation-portal/server.ts @@ -1,5 +1,6 @@ import { bootstrap } from '@island.is/infra-next-server' -import proxyConfig from './proxy.config.json' +import proxyConfig from './proxy.config' + bootstrap({ name: 'consultation-portal', appDir: 'apps/consultation-portal', diff --git a/apps/judicial-system/api/src/app/modules/case-list/models/caseList.model.ts b/apps/judicial-system/api/src/app/modules/case-list/models/caseList.model.ts index 3b2982563026..6372ac2e17d2 100644 --- a/apps/judicial-system/api/src/app/modules/case-list/models/caseList.model.ts +++ b/apps/judicial-system/api/src/app/modules/case-list/models/caseList.model.ts @@ -77,6 +77,9 @@ export class CaseListEntry { @Field(() => String, { nullable: true }) readonly prosecutorPostponedAppealDate?: string + @Field(() => Institution, { nullable: true }) + readonly court?: Institution + @Field(() => User, { nullable: true }) readonly creatingProsecutor?: User diff --git a/apps/judicial-system/api/src/app/modules/file/file.controller.ts b/apps/judicial-system/api/src/app/modules/file/file.controller.ts index a729124f5f6e..283b548d0efa 100644 --- a/apps/judicial-system/api/src/app/modules/file/file.controller.ts +++ b/apps/judicial-system/api/src/app/modules/file/file.controller.ts @@ -196,7 +196,7 @@ export class FileController { } for defendant ${defendantId} of case ${id} as a pdf document`, ) - const subpoenaIdInjection = subpoenaId ? `/${subpoenaId}` : '' + const subpoenaIdInjection = subpoenaId ? `/${subpoenaId}/pdf` : '' const queryInjection = arraignmentDate ? `?arraignmentDate=${arraignmentDate}&location=${location}&subpoenaType=${subpoenaType}` : '' diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index 6454603536c8..c89bbc8c0e0c 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -409,6 +409,7 @@ export const include: Includeable[] = [ ] export const caseListInclude: Includeable[] = [ + { model: Institution, as: 'court' }, { model: Institution, as: 'prosecutorsOffice' }, { model: Defendant, @@ -775,12 +776,16 @@ export class CaseService { CaseFileCategory.CRIMINAL_RECORD, CaseFileCategory.COST_BREAKDOWN, CaseFileCategory.CASE_FILE, + CaseFileCategory.PROSECUTOR_CASE_FILE, + CaseFileCategory.DEFENDANT_CASE_FILE, ] : [ CaseFileCategory.INDICTMENT, CaseFileCategory.CRIMINAL_RECORD, CaseFileCategory.COST_BREAKDOWN, CaseFileCategory.CASE_FILE, + CaseFileCategory.PROSECUTOR_CASE_FILE, + CaseFileCategory.DEFENDANT_CASE_FILE, ] const deliverCaseFileToCourtMessages = @@ -927,12 +932,10 @@ export class CaseService { (caseFile) => caseFile.state === CaseFileState.STORED_IN_RVG && caseFile.key && - caseFile.category === CaseFileCategory.RULING && - theCase.indictmentRulingDecision && - [ - CaseIndictmentRulingDecision.RULING, - CaseIndictmentRulingDecision.DISMISSAL, - ].includes(theCase.indictmentRulingDecision), + caseFile.category && + [CaseFileCategory.COURT_RECORD, CaseFileCategory.RULING].includes( + caseFile.category, + ), ) .map((caseFile) => ({ type: MessageType.DELIVERY_TO_COURT_CASE_FILE, diff --git a/apps/judicial-system/backend/src/app/modules/case/interceptors/caseList.interceptor.ts b/apps/judicial-system/backend/src/app/modules/case/interceptors/caseList.interceptor.ts index dbc56797bcb1..bee2da1a9852 100644 --- a/apps/judicial-system/backend/src/app/modules/case/interceptors/caseList.interceptor.ts +++ b/apps/judicial-system/backend/src/app/modules/case/interceptors/caseList.interceptor.ts @@ -23,7 +23,6 @@ export class CaseListInterceptor implements NestInterceptor { // WARNING: Be careful when adding to this list. No sensitive information should be returned. // If you need to add sensitive information, then you should consider adding a new endpoint // for defenders and other user roles that are not allowed to see sensitive information. - return { id: theCase.id, created: theCase.created, @@ -65,6 +64,7 @@ export class CaseListInterceptor implements NestInterceptor { indictmentRulingDecision: theCase.indictmentRulingDecision, courtSessionType: theCase.courtSessionType, eventLogs: theCase.eventLogs, + court: theCase.court, } }), ), diff --git a/apps/judicial-system/backend/src/app/modules/file/file.service.ts b/apps/judicial-system/backend/src/app/modules/file/file.service.ts index 397f488a5c0c..fbf3b50a9d5e 100644 --- a/apps/judicial-system/backend/src/app/modules/file/file.service.ts +++ b/apps/judicial-system/backend/src/app/modules/file/file.service.ts @@ -148,12 +148,12 @@ export class FileService { courtDocumentFolder = CourtDocumentFolder.INDICTMENT_DOCUMENTS break case CaseFileCategory.COURT_RECORD: - courtDocumentFolder = CourtDocumentFolder.COURT_DOCUMENTS - break case CaseFileCategory.RULING: courtDocumentFolder = CourtDocumentFolder.COURT_DOCUMENTS break case CaseFileCategory.CASE_FILE: + case CaseFileCategory.PROSECUTOR_CASE_FILE: + case CaseFileCategory.DEFENDANT_CASE_FILE: case undefined: case null: courtDocumentFolder = CourtDocumentFolder.CASE_DOCUMENTS @@ -388,6 +388,25 @@ export class FileService { }, ]) } + + if ( + isIndictmentCase(theCase.type) && + file.category && + [ + CaseFileCategory.PROSECUTOR_CASE_FILE, + CaseFileCategory.DEFENDANT_CASE_FILE, + ].includes(file.category) + ) { + await this.messageService.sendMessagesToQueue([ + { + type: MessageType.DELIVERY_TO_COURT_CASE_FILE, + user, + caseId: theCase.id, + elementId: file.id, + }, + ]) + } + return file } diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts index 8242d7867970..ed673bbf76b5 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts @@ -105,7 +105,7 @@ export class SubpoenaController { districtCourtRegistrarRule, districtCourtAssistantRule, ) - @Get(['', ':subpoenaId']) + @Get(['', ':subpoenaId/pdf']) @UseGuards(SubpoenaExistsOptionalGuard) @Header('Content-Type', 'application/pdf') @ApiOkResponse({ diff --git a/apps/judicial-system/web/messages/Core/tables.ts b/apps/judicial-system/web/messages/Core/tables.ts index 66879b64ce6a..b2b2500d65bb 100644 --- a/apps/judicial-system/web/messages/Core/tables.ts +++ b/apps/judicial-system/web/messages/Core/tables.ts @@ -134,4 +134,15 @@ export const tables = defineMessages({ defaultMessage: 'Sent', description: 'Notaður sem titill fyrir sent dálk í lista yfir mál.', }, + fineTag: { + id: 'judicial.system.core:tables.fine_tag', + defaultMessage: 'Viðurlagaákvörðun', + description: + 'Notaðir sem texti í tagg þegar mál endar sem viðurlagaákvörðun', + }, + rulingTag: { + id: 'judicial.system.core:tables.ruling_tag', + defaultMessage: 'Dómur', + description: 'Notaðir sem texti í tagg þegar mál endar sem dómur', + }, }) diff --git a/apps/judicial-system/web/src/components/Table/Table.tsx b/apps/judicial-system/web/src/components/Table/Table.tsx index 45b6398dfe04..8e572422391c 100644 --- a/apps/judicial-system/web/src/components/Table/Table.tsx +++ b/apps/judicial-system/web/src/components/Table/Table.tsx @@ -6,7 +6,10 @@ import { AnimatePresence, motion } from 'framer-motion' import { Box, Text } from '@island.is/island-ui/core' import { theme } from '@island.is/island-ui/theme' -import { formatDate } from '@island.is/judicial-system/formatters' +import { + districtCourtAbbreviation, + formatDate, +} from '@island.is/judicial-system/formatters' import { CaseType, isCompletedCase, @@ -168,25 +171,30 @@ const Table: FC = (props) => { return null } + const getColumnValue = ( + entry: CaseListEntry, + column: keyof CaseListEntry, + ) => { + const courtAbbreviation = districtCourtAbbreviation(entry.court?.name) + + switch (column) { + case 'defendants': + return entry.defendants?.[0]?.name ?? '' + case 'courtCaseNumber': + return courtAbbreviation + ? `${courtAbbreviation}: ${entry.courtCaseNumber}` + : entry.courtCaseNumber ?? '' + default: + return entry[column]?.toString() ?? '' + } + } + useMemo(() => { if (sortConfig) { data.sort((a: CaseListEntry, b: CaseListEntry) => { - const getColumnValue = (entry: CaseListEntry) => { - if ( - sortConfig.column === 'defendants' && - entry.defendants && - entry.defendants.length > 0 && - entry.defendants[0].name - ) { - return entry.defendants[0].name - } - - return entry[sortConfig.column]?.toString() - } - const compareResult = compareLocaleIS( - getColumnValue(a), - getColumnValue(b), + getColumnValue(a, sortConfig.column), + getColumnValue(b, sortConfig.column), ) return sortConfig.direction === 'ascending' diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Advocates/SelectDefender.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Advocates/SelectDefender.tsx index 70711fe486d7..56033fefc230 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Advocates/SelectDefender.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Advocates/SelectDefender.tsx @@ -43,16 +43,16 @@ const SelectDefender: FC = ({ defendant }) => { caseId, defendantId: defendant.id, defenderNationalId: defendantWaivesRightToCounsel - ? '' - : defendant.defenderNationalId, + ? null + : defendant.defenderNationalId || null, defenderName: defendantWaivesRightToCounsel - ? '' + ? null : defendant.defenderName, defenderEmail: defendantWaivesRightToCounsel - ? '' + ? null : defendant.defenderEmail, defenderPhoneNumber: defendantWaivesRightToCounsel - ? '' + ? null : defendant.defenderPhoneNumber, defenderChoice: defendantWaivesRightToCounsel === true diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Summary/Summary.strings.ts b/apps/judicial-system/web/src/routes/Court/Indictments/Summary/Summary.strings.ts index 0d0db14b68a4..e5c50b59327c 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Summary/Summary.strings.ts +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Summary/Summary.strings.ts @@ -28,14 +28,28 @@ export const strings = defineMessages({ description: 'Notaður sem titill á Staðfesta takka á Samantektarskjá ákæru.', }, - completedCaseModalTitle: { - id: 'judicial.system.core:indictments.summary.completed_case_modal_title', - defaultMessage: 'Máli hefur verið lokið', - description: 'Notaður sem titill á staðfestingarglugga um að mál sé lokið.', - }, - completedCaseModalBody: { - id: 'judicial.system.core:indictments.summary.completed_case_modal_body_v2', - defaultMessage: 'Gögn hafa verið send ákæranda og verjanda.', - description: 'Notaður sem texti í staðfestingarglugga um að mál sé lokið.', + completeCaseModalTitle: { + id: 'judicial.system.core:indictments.summary.complete_case_modal_title', + defaultMessage: 'Viltu ljúka máli?', + description: + 'Notaður sem titill á staðfestingarglugga um að hvort eigi að ljúka máli.', + }, + completeCaseModalBody: { + id: 'judicial.system.core:indictments.summary.complete_case_modal_body', + defaultMessage: 'Niðurstaða málsins verður send ákæranda og verjanda.', + description: + 'Notaður sem texti í staðfestingarglugga um hvort eigi að ljúka máli.', + }, + completeCaseModalPrimaryButton: { + id: 'judicial.system.core:indictments.summary.complete_case_modal_primary_button', + defaultMessage: 'Já, ljúka máli', + description: + 'Notaður sem texti á aðalhnapp í staðfestingarglugga um hvort eigi að ljúka máli.', + }, + completeCaseModalSecondaryButton: { + id: 'judicial.system.core:indictments.summary.complete_case_modal_secondary_button', + defaultMessage: 'Hætta við', + description: + 'Notaður sem texti á aukahnapp í staðfestingarglugga um hvort eigi að ljúka máli.', }, }) diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Summary/Summary.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Summary/Summary.tsx index d1186e033ce4..51d109336b5e 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Summary/Summary.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Summary/Summary.tsx @@ -52,7 +52,7 @@ const Summary: FC = () => { return router.push(`${destination}/${workingCase.id}`) } - const handleNextButtonClick = async () => { + const handleModalPrimaryButtonClick = async () => { const transitionSuccess = await transitionCase( workingCase.id, CaseTransition.COMPLETE, @@ -63,7 +63,7 @@ const Summary: FC = () => { return } - setModalVisible('CONFIRM_INDICTMENT') + router.push(`${constants.INDICTMENTS_COMPLETED_ROUTE}/${workingCase.id}`) } const [courtRecordFiles, rulingFiles] = (workingCase.caseFiles || []).reduce( @@ -158,20 +158,24 @@ const Summary: FC = () => { previousUrl={`${constants.INDICTMENTS_CONCLUSION_ROUTE}/${workingCase.id}`} nextButtonIcon="checkmark" nextButtonText={formatMessage(strings.nextButtonText)} - onNextButtonClick={async () => await handleNextButtonClick()} - nextIsDisabled={isTransitioningCase} + onNextButtonClick={() => setModalVisible('CONFIRM_INDICTMENT')} /> {modalVisible === 'CONFIRM_INDICTMENT' && ( - router.push( - `${constants.INDICTMENTS_COMPLETED_ROUTE}/${workingCase.id}`, - ) + title={formatMessage(strings.completeCaseModalTitle)} + text={formatMessage(strings.completeCaseModalBody)} + primaryButtonText={formatMessage( + strings.completeCaseModalPrimaryButton, + )} + onPrimaryButtonClick={async () => + await handleModalPrimaryButtonClick() } + secondaryButtonText={formatMessage( + strings.completeCaseModalSecondaryButton, + )} + onSecondaryButtonClick={() => setModalVisible(undefined)} + isPrimaryButtonLoading={isTransitioningCase} /> )} diff --git a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/Defendant.tsx b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/Defendant.tsx index 2bae92a4bbd9..5f5e15f5b14a 100644 --- a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/Defendant.tsx +++ b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/Defendant.tsx @@ -370,7 +370,6 @@ const Defendant = () => { router.push(`${destination}/${createdCase.id}`) } else { toast.error(formatMessage(errors.createCase)) - return } } else { router.push(`${destination}/${workingCase.id}`) @@ -416,14 +415,7 @@ const Defendant = () => { const handleCreateDefendantClick = async () => { if (workingCase.id) { - const defendantId = await createDefendant({ - caseId: workingCase.id, - gender: undefined, - name: '', - address: '', - nationalId: null, - citizenship: '', - }) + const defendantId = await createDefendant({ caseId: workingCase.id }) createEmptyDefendant(defendantId) } else { @@ -438,14 +430,7 @@ const Defendant = () => { ...prevWorkingCase, defendants: prevWorkingCase.defendants && [ ...prevWorkingCase.defendants, - { - id: defendantId || uuid(), - gender: undefined, - name: '', - nationalId: null, - address: '', - citizenship: '', - } as TDefendant, + { id: defendantId || uuid() }, ], })) } diff --git a/apps/judicial-system/web/src/routes/Prosecutor/InvestigationCase/Defendant/Defendant.tsx b/apps/judicial-system/web/src/routes/Prosecutor/InvestigationCase/Defendant/Defendant.tsx index 2be75ba20374..119bca8574ae 100644 --- a/apps/judicial-system/web/src/routes/Prosecutor/InvestigationCase/Defendant/Defendant.tsx +++ b/apps/judicial-system/web/src/routes/Prosecutor/InvestigationCase/Defendant/Defendant.tsx @@ -192,14 +192,7 @@ const Defendant = () => { const handleCreateDefendantClick = async () => { if (workingCase.id) { - const defendantId = await createDefendant({ - caseId: workingCase.id, - gender: undefined, - name: '', - address: '', - nationalId: '', - citizenship: '', - }) + const defendantId = await createDefendant({ caseId: workingCase.id }) createEmptyDefendant(defendantId) } else { @@ -214,14 +207,7 @@ const Defendant = () => { ...prevWorkingCase, defendants: prevWorkingCase.defendants && [ ...prevWorkingCase.defendants, - { - id: defendantId || uuid(), - gender: undefined, - name: '', - nationalId: '', - address: '', - citizenship: '', - } as TDefendant, + { id: defendantId || uuid() }, ], })) } diff --git a/apps/judicial-system/web/src/routes/PublicProsecutor/Tables/CasesAwaitingReview.tsx b/apps/judicial-system/web/src/routes/PublicProsecutor/Tables/CasesAwaitingReview.tsx index 5f1cc2d3dac2..ec030bbaa80b 100644 --- a/apps/judicial-system/web/src/routes/PublicProsecutor/Tables/CasesAwaitingReview.tsx +++ b/apps/judicial-system/web/src/routes/PublicProsecutor/Tables/CasesAwaitingReview.tsx @@ -2,7 +2,7 @@ import { FC } from 'react' import { useIntl } from 'react-intl' import { AnimatePresence } from 'framer-motion' -import { Text } from '@island.is/island-ui/core' +import { Tag, Text } from '@island.is/island-ui/core' import { capitalize, formatDate } from '@island.is/judicial-system/formatters' import { core, tables } from '@island.is/judicial-system-web/messages' import { SectionHeading } from '@island.is/judicial-system-web/src/components' @@ -18,7 +18,10 @@ import TableInfoContainer from '@island.is/judicial-system-web/src/components/Ta import TagCaseState, { mapIndictmentCaseStateToTagVariant, } from '@island.is/judicial-system-web/src/components/TagCaseState/TagCaseState' -import { CaseListEntry } from '@island.is/judicial-system-web/src/graphql/schema' +import { + CaseIndictmentRulingDecision, + CaseListEntry, +} from '@island.is/judicial-system-web/src/graphql/schema' import { strings } from './CasesAwaitingReview.strings' @@ -48,6 +51,7 @@ const CasesForReview: FC = ({ loading, cases }) => { ), sortable: { isSortable: true, key: 'defendants' }, }, + { title: formatMessage(tables.type) }, { title: formatMessage(tables.state) }, { title: formatMessage(tables.deadline), @@ -58,9 +62,9 @@ const CasesForReview: FC = ({ loading, cases }) => { }, ]} data={cases} - generateContextMenuItems={(row) => { - return [openCaseInNewTabMenuItem(row.id)] - }} + generateContextMenuItems={(row) => [ + openCaseInNewTabMenuItem(row.id), + ]} columns={[ { cell: (row) => ( @@ -74,6 +78,18 @@ const CasesForReview: FC = ({ loading, cases }) => { { cell: (row) => , }, + { + cell: (row) => ( + + {formatMessage( + row.indictmentRulingDecision === + CaseIndictmentRulingDecision.FINE + ? tables.fineTag + : tables.rulingTag, + )} + + ), + }, { cell: (row) => ( = ({ loading, cases }) => { thead={[ { title: formatMessage(tables.caseNumber), + sortable: { + isSortable: true, + key: 'courtCaseNumber', + }, }, { title: capitalize( @@ -51,6 +62,7 @@ const CasesForReview: FC = ({ loading, cases }) => { key: 'defendants', }, }, + { title: formatMessage(tables.type) }, { title: formatMessage(tables.state) }, { title: formatMessage(tables.prosecutorName) }, { @@ -62,22 +74,42 @@ const CasesForReview: FC = ({ loading, cases }) => { }, ]} data={cases} - generateContextMenuItems={(row) => { - return [openCaseInNewTabMenuItem(row.id)] - }} + generateContextMenuItems={(row) => [ + openCaseInNewTabMenuItem(row.id), + ]} columns={[ { - cell: (row) => ( - - ), + cell: (row) => { + const courtAbbreviation = districtCourtAbbreviation( + row.court?.name, + ) + + return ( + + ) + }, }, { cell: (row) => , }, + { + cell: (row) => ( + + {formatMessage( + row.indictmentRulingDecision === + CaseIndictmentRulingDecision.FINE + ? tables.fineTag + : tables.rulingTag, + )} + + ), + }, { cell: (row) => ( = ({ loading, cases }) => { thead={[ { title: formatMessage(tables.caseNumber), + sortable: { + isSortable: true, + key: 'courtCaseNumber', + }, }, { title: capitalize( @@ -96,27 +103,48 @@ const CasesReviewed: FC = ({ loading, cases }) => { ), sortable: { isSortable: true, key: 'defendants' }, }, + { title: formatMessage(tables.type) }, { title: formatMessage(tables.reviewDecision) }, { title: formatMessage(tables.verdictViewState) }, { title: formatMessage(tables.prosecutorName) }, ]} data={cases} - generateContextMenuItems={(row) => { - return [openCaseInNewTabMenuItem(row.id)] - }} + generateContextMenuItems={(row) => [ + openCaseInNewTabMenuItem(row.id), + ]} columns={[ { - cell: (row) => ( - - ), + cell: (row) => { + const courtAbbreviation = districtCourtAbbreviation( + row.court?.name, + ) + + return ( + + ) + }, }, { cell: (row) => , }, + { + cell: (row) => ( + + {formatMessage( + row.indictmentRulingDecision === + CaseIndictmentRulingDecision.FINE + ? tables.fineTag + : tables.rulingTag, + )} + + ), + }, { cell: (row) => ( diff --git a/apps/judicial-system/web/src/routes/Shared/Cases/MobileCase.tsx b/apps/judicial-system/web/src/routes/Shared/Cases/MobileCase.tsx index 391d004d76d4..a14415196497 100644 --- a/apps/judicial-system/web/src/routes/Shared/Cases/MobileCase.tsx +++ b/apps/judicial-system/web/src/routes/Shared/Cases/MobileCase.tsx @@ -7,6 +7,7 @@ import { AnimatePresence } from 'framer-motion' import { Box, FocusableBox, Text } from '@island.is/island-ui/core' import { displayFirstPlusRemaining, + districtCourtAbbreviation, formatDOB, } from '@island.is/judicial-system/formatters' import { tables } from '@island.is/judicial-system-web/messages' @@ -69,6 +70,7 @@ const MobileCase: FC> = ({ isLoading = false, }) => { const { formatMessage } = useIntl() + const courtAbbreviation = districtCourtAbbreviation(theCase.court?.name) return ( > = ({ {displayFirstPlusRemaining(theCase.policeCaseNumbers)} - {theCase.courtCaseNumber && {theCase.courtCaseNumber}} + + {theCase.courtCaseNumber && ( + {`${courtAbbreviation ? `${courtAbbreviation}: ` : ''}${ + theCase.courtCaseNumber + }`} + )}
{theCase.defendants && theCase.defendants.length > 0 && ( <> diff --git a/apps/judicial-system/web/src/routes/Shared/Cases/cases.graphql b/apps/judicial-system/web/src/routes/Shared/Cases/cases.graphql index d35f7fb9af54..4001b83c6fcb 100644 --- a/apps/judicial-system/web/src/routes/Shared/Cases/cases.graphql +++ b/apps/judicial-system/web/src/routes/Shared/Cases/cases.graphql @@ -34,6 +34,10 @@ query Cases { initialRulingDate rulingDate rulingSignatureDate + court { + id + name + } judge { id created diff --git a/apps/native/app/src/graphql/client.ts b/apps/native/app/src/graphql/client.ts index 2e4e29eb5d34..fe5e2ea8205b 100644 --- a/apps/native/app/src/graphql/client.ts +++ b/apps/native/app/src/graphql/client.ts @@ -164,6 +164,9 @@ const cache = new InMemoryCache({ getUserProfile: { merge: true, }, + nationalRegistryPerson: { + merge: false, + }, }, }, DocumentV2: { diff --git a/apps/native/app/src/graphql/fragments/vehicle.fragment.graphql b/apps/native/app/src/graphql/fragments/vehicle.fragment.graphql index 244ad841d50a..0ab686f97ab0 100644 --- a/apps/native/app/src/graphql/fragments/vehicle.fragment.graphql +++ b/apps/native/app/src/graphql/fragments/vehicle.fragment.graphql @@ -1,39 +1,10 @@ -fragment VehicleFragment on VehiclesVehicle { - isCurrent +fragment VehicleFragment on VehicleListed { permno regno - vin - type - color - firstRegDate + make + colorName modelYear - productYear - registrationType - role - operatorStartDate - operatorEndDate - outOfUse - otherOwners - termination - buyerPersidno - ownerPersidno - vehicleStatus - useGroup - vehGroup - plateStatus - nextInspection { - nextInspectionDate - nextInspectionDateIfPassedInspectionToday - } - operatorNumber - primaryOperator - ownerSsid - ownerName - lastInspectionResult - lastInspectionDate - lastInspectionType - nextInspectionDate - nextAvailableMileageReadDate requiresMileageRegistration canRegisterMileage + nextMainInspection } diff --git a/apps/native/app/src/graphql/queries/national-registry.graphql b/apps/native/app/src/graphql/queries/national-registry.graphql index 84777c6e116c..764939d31273 100644 --- a/apps/native/app/src/graphql/queries/national-registry.graphql +++ b/apps/native/app/src/graphql/queries/national-registry.graphql @@ -1,5 +1,5 @@ query NationalRegistryUser { - nationalRegistryUser { + nationalRegistryPerson { nationalId fullName gender @@ -23,37 +23,83 @@ query NationalRegistryUser { } } -query NationalRegistryChildren { - nationalRegistryUser { +query NationalRegistryPerson { + nationalRegistryPerson { nationalId - fullName + name { + fullName + } spouse { - name nationalId + fullName + } + childCustody { + nationalId + fullName + } + biologicalChildren { + nationalId + fullName } } - nationalRegistryChildren { +} + +query NationalRegistryBioChild($childNationalId: String) { + nationalRegistryPerson { nationalId fullName - displayName - genderDisplay - birthplace - custody1 - custodyText1 - nameCustody1 - custody2 - custodyText2 - nameCustody2 - parent1 - nameParent1 - parent2 - nameParent2 - homeAddress - religion - nationality - religion - homeAddress - nationality - legalResidence + biologicalChildren(childNationalId: $childNationalId) { + details { + nationalId + fullName + baseId + housing { + address { + streetAddress + } + } + } + } + } +} + +query NationalRegistryChildCustody($childNationalId: String) { + nationalRegistryPerson { + nationalId + fullName + childCustody(childNationalId: $childNationalId) { + details { + nationalId + fullName + baseId + gender + religion + housing { + address { + streetAddress + postalCode + city + } + } + birthplace { + location + } + citizenship { + code + name + } + } + } + } +} + +query NationalRegistrySpouse { + nationalRegistryPerson { + nationalId + spouse { + maritalStatus + nationalId + fullName + } } } diff --git a/apps/native/app/src/graphql/queries/vehicles.graphql b/apps/native/app/src/graphql/queries/vehicles.graphql index da2ad3c69212..a88bb380e3b7 100644 --- a/apps/native/app/src/graphql/queries/vehicles.graphql +++ b/apps/native/app/src/graphql/queries/vehicles.graphql @@ -1,5 +1,5 @@ -query ListVehicles($input: GetVehiclesForUserInput!) { - vehiclesList(input: $input) { +query ListVehiclesV2($input: GetVehiclesListV2Input!) { + vehiclesListV2(input: $input) { vehicleList { ...VehicleFragment } diff --git a/apps/native/app/src/screens/family/family-details.tsx b/apps/native/app/src/screens/family/family-details.tsx index 154a056f051e..e4cf541c22cd 100644 --- a/apps/native/app/src/screens/family/family-details.tsx +++ b/apps/native/app/src/screens/family/family-details.tsx @@ -6,10 +6,40 @@ import { Navigation, NavigationFunctionComponent, } from 'react-native-navigation' -import { useNationalRegistryChildrenQuery } from '../../graphql/types/schema' +import { + NationalRegistryBioChildQuery, + NationalRegistryChildCustodyQuery, + NationalRegistrySpouseQuery, + useNationalRegistryBioChildQuery, + useNationalRegistryChildCustodyQuery, + useNationalRegistrySpouseQuery, +} from '../../graphql/types/schema' import { createNavigationOptionHooks } from '../../hooks/create-navigation-option-hooks' import { formatNationalId } from '../../lib/format-national-id' import { testIDs } from '../../utils/test-ids' +import { useTheme } from 'styled-components' + +type ChildCustodyDetails = NonNullable< + NonNullable< + NonNullable< + NonNullable + >['childCustody'] + >[number] +>['details'] + +type BioChildDetails = NonNullable< + NonNullable< + NonNullable< + NonNullable + >['biologicalChildren'] + >[number] +>['details'] + +type SpouseDetails = NonNullable< + NonNullable +>['spouse'] + +type Person = ChildCustodyDetails | BioChildDetails | SpouseDetails const { getNavigationOptions, useNavigationOptions } = createNavigationOptionHooks(() => ({ @@ -20,25 +50,39 @@ const { getNavigationOptions, useNavigationOptions } = export const FamilyDetailScreen: NavigationFunctionComponent<{ id: string - type: string + type: 'bioChild' | 'custodyChild' | 'spouse' }> = ({ componentId, id, type }) => { useNavigationOptions(componentId) const intl = useIntl() + const theme = useTheme() - const { data, loading, error } = useNationalRegistryChildrenQuery({ - fetchPolicy: 'cache-first', + const bioChildRes = useNationalRegistryBioChildQuery({ + variables: { childNationalId: id }, + skip: type !== 'bioChild', }) - const { nationalRegistryUser, nationalRegistryChildren = [] } = data || {} - const listOfPeople = [ - { ...(nationalRegistryUser?.spouse ?? {}), type: 'spouse' }, - ...(nationalRegistryChildren ?? []).map((item: any) => ({ - ...item, - type: 'child', - })), - ].filter((item) => item.nationalId) + const custodyChildRes = useNationalRegistryChildCustodyQuery({ + variables: { childNationalId: id }, + skip: type !== 'custodyChild', + }) + + const spouseRes = useNationalRegistrySpouseQuery({ + skip: type !== 'spouse', + }) - const person = listOfPeople?.find((x) => x.nationalId === id) || null + const person: Person = + bioChildRes.data?.nationalRegistryPerson?.biologicalChildren?.find( + (child) => child.details?.nationalId === id, + )?.details || + custodyChildRes?.data?.nationalRegistryPerson?.childCustody?.find( + (child) => child.details?.nationalId === id, + )?.details || + spouseRes.data?.nationalRegistryPerson?.spouse || + null + + const loading = + bioChildRes.loading || custodyChildRes.loading || spouseRes.loading + const error = bioChildRes.error || custodyChildRes.error || spouseRes.error if (!person) return null @@ -53,7 +97,11 @@ export const FamilyDetailScreen: NavigationFunctionComponent<{ {intl.formatMessage({ id: 'familyDetail.description' })} @@ -64,13 +112,12 @@ export const FamilyDetailScreen: NavigationFunctionComponent<{ label={intl.formatMessage({ id: 'familyDetail.natreg.displayName', })} - value={person?.name || person?.displayName} + value={person?.fullName} loading={loading} error={!!error} size="big" /> - - {person?.nationality ? ( + {'citizenship' in person && person?.citizenship ? ( ) : null} - {person?.legalResidence ? ( + {'housing' in person && + person?.housing && + 'address' in person.housing && + person.housing.address ? ( @@ -118,20 +178,23 @@ export const FamilyDetailScreen: NavigationFunctionComponent<{ ) : null} - {person?.genderDisplay ? ( + {'gender' in person && person.gender ? ( ) : null} - {person?.birthplace ? ( + {'birthplace' in person && person?.birthplace ? ( diff --git a/apps/native/app/src/screens/family/family-overview.tsx b/apps/native/app/src/screens/family/family-overview.tsx index 91dd32bf52fb..f2bb50879b2a 100644 --- a/apps/native/app/src/screens/family/family-overview.tsx +++ b/apps/native/app/src/screens/family/family-overview.tsx @@ -1,4 +1,4 @@ -import { EmptyList, FamilyMemberCard, Skeleton, TopLine } from '@ui' +import { EmptyList, FamilyMemberCard, Problem, Skeleton, TopLine } from '@ui' import React, { useCallback, useRef, useState } from 'react' import { useIntl } from 'react-intl' import { @@ -14,13 +14,29 @@ import { NavigationFunctionComponent } from 'react-native-navigation' import { useTheme } from 'styled-components/native' import illustrationSrc from '../../assets/illustrations/hero_spring.png' import { BottomTabsIndicator } from '../../components/bottom-tabs-indicator/bottom-tabs-indicator' -import { useNationalRegistryChildrenQuery } from '../../graphql/types/schema' +import { + NationalRegistryChildCustody, + NationalRegistrySpouse, + useNationalRegistryPersonQuery, +} from '../../graphql/types/schema' import { createNavigationOptionHooks } from '../../hooks/create-navigation-option-hooks' import { useConnectivityIndicator } from '../../hooks/use-connectivity-indicator' import { navigateTo } from '../../lib/deep-linking' import { formatNationalId } from '../../lib/format-national-id' import { testIDs } from '../../utils/test-ids' +type ChildItem = NationalRegistryChildCustody & { + type: 'custodyChild' | 'bioChild' +} + +type SpouseItem = NationalRegistrySpouse & { type: 'spouse' } + +type FamilyListItem = + | ChildItem + | SpouseItem + | { type: 'skeleton'; id: string } + | { type: 'empty'; id: string } + const { useNavigationOptions, getNavigationOptions } = createNavigationOptionHooks((theme, intl) => ({ topBar: { @@ -30,32 +46,34 @@ const { useNavigationOptions, getNavigationOptions } = }, })) -const FamilyMember = React.memo(({ item }: { item: any }) => { - const theme = useTheme() - - return ( - - { - navigateTo(`/family/${item.type}/${item.nationalId}`, { - id: item?.nationalId, - }) - }} - > - - - - - - ) -}) +const FamilyMember = React.memo( + ({ item }: { item: ChildItem | SpouseItem }) => { + const theme = useTheme() + + return ( + + { + navigateTo(`/family/${item.type}/${item.nationalId}`, { + id: item?.nationalId, + }) + }} + > + + + + + + ) + }, +) export const FamilyOverviewScreen: NavigationFunctionComponent = ({ componentId, @@ -68,7 +86,7 @@ export const FamilyOverviewScreen: NavigationFunctionComponent = ({ const theme = useTheme() const scrollY = useRef(new Animated.Value(0)).current const loadingTimeout = useRef() - const familyRes = useNationalRegistryChildrenQuery() + const familyRes = useNationalRegistryPersonQuery() useConnectivityIndicator({ componentId, @@ -76,14 +94,23 @@ export const FamilyOverviewScreen: NavigationFunctionComponent = ({ refetching, }) - const { nationalRegistryUser, nationalRegistryChildren = [] } = - familyRes?.data || {} + const { biologicalChildren, spouse, childCustody } = + familyRes.data?.nationalRegistryPerson || {} + + // Filter out bio children with custody so we don't show them twice + const bioChildren = biologicalChildren?.filter( + (child) => !childCustody?.some((c) => c.nationalId === child.nationalId), + ) const listOfPeople = [ - { ...(nationalRegistryUser?.spouse ?? {}), type: 'spouse' }, - ...(nationalRegistryChildren ?? []).map((item: any) => ({ + { ...(spouse ?? {}), type: 'spouse' }, + ...(childCustody ?? []).map((item: NationalRegistryChildCustody) => ({ ...item, - type: 'child', + type: 'custodyChild', + })), + ...(bioChildren ?? []).map((item: NationalRegistryChildCustody) => ({ + ...item, + type: 'bioChild', })), ].filter((item) => item.nationalId) @@ -110,10 +137,10 @@ export const FamilyOverviewScreen: NavigationFunctionComponent = ({ } }, []) - const renderItem = ({ item }: { item: any }) => { + const renderItem = ({ item }: { item: FamilyListItem }) => { if (item.type === 'skeleton') { return ( - + @@ -137,7 +164,7 @@ export const FamilyOverviewScreen: NavigationFunctionComponent = ({ if (item.type === 'empty') { return ( - + - - } - scrollEventThrottle={16} - scrollToOverflowEnabled={true} - onScroll={Animated.event( - [{ nativeEvent: { contentOffset: { y: scrollY } } }], - { - useNativeDriver: true, - }, - )} - data={isSkeleton ? skeletonItems : isEmpty ? emptyItems : listOfPeople} - keyExtractor={keyExtractor} - renderItem={renderItem} - /> + {(familyRes.data || familyRes.loading) && ( + + } + scrollEventThrottle={16} + scrollToOverflowEnabled={true} + onScroll={Animated.event( + [{ nativeEvent: { contentOffset: { y: scrollY } } }], + { + useNativeDriver: true, + }, + )} + data={ + isSkeleton ? skeletonItems : isEmpty ? emptyItems : listOfPeople + } + keyExtractor={keyExtractor} + renderItem={renderItem} + /> + )} + {familyRes.error && !familyRes.data && } diff --git a/apps/native/app/src/screens/home/home.tsx b/apps/native/app/src/screens/home/home.tsx index 057b658de585..f228c0843a88 100644 --- a/apps/native/app/src/screens/home/home.tsx +++ b/apps/native/app/src/screens/home/home.tsx @@ -55,7 +55,7 @@ import { } from './licenses-module' import { OnboardingModule } from './onboarding-module' import { - useListVehiclesQuery, + useListVehiclesV2Query, validateVehiclesInitialData, VehiclesModule, } from './vehicles-module' @@ -174,13 +174,11 @@ export const MainHomeScreen: NavigationFunctionComponent = ({ skip: !airDiscountWidgetEnabled, }) - const vehiclesRes = useListVehiclesQuery({ + const vehiclesRes = useListVehiclesV2Query({ variables: { input: { page: 1, pageSize: 15, - showDeregeristered: false, - showHistory: false, }, }, skip: !vehiclesWidgetEnabled, diff --git a/apps/native/app/src/screens/home/vehicles-module.tsx b/apps/native/app/src/screens/home/vehicles-module.tsx index 02975f50a8e2..34c5c709c86d 100644 --- a/apps/native/app/src/screens/home/vehicles-module.tsx +++ b/apps/native/app/src/screens/home/vehicles-module.tsx @@ -17,8 +17,8 @@ import illustrationSrc from '../../assets/illustrations/le-moving-s4.png' import { navigateTo } from '../../lib/deep-linking' import { VehicleItem } from '../vehicles/components/vehicle-item' import { - ListVehiclesQuery, - useListVehiclesQuery, + ListVehiclesV2Query, + useListVehiclesV2Query, } from '../../graphql/types/schema' import { screenWidth } from '../../utils/dimensions' @@ -30,7 +30,7 @@ const validateVehiclesInitialData = ({ data, loading, }: { - data: ListVehiclesQuery | undefined + data: ListVehiclesV2Query | undefined loading: boolean }) => { if (loading) { @@ -38,7 +38,7 @@ const validateVehiclesInitialData = ({ } // Only show widget initially if there are vehicles that require mileage registration if ( - data?.vehiclesList?.vehicleList?.some( + data?.vehiclesListV2?.vehicleList?.some( (vehicle) => vehicle.requiresMileageRegistration, ) ) { @@ -49,7 +49,7 @@ const validateVehiclesInitialData = ({ } interface VehiclesModuleProps { - data: ListVehiclesQuery | undefined + data: ListVehiclesV2Query | undefined loading: boolean error?: ApolloError | undefined } @@ -59,7 +59,7 @@ const VehiclesModule = React.memo( const theme = useTheme() const intl = useIntl() - const vehicles = data?.vehiclesList?.vehicleList + const vehicles = data?.vehiclesListV2?.vehicleList // Reorder vehicles so vehicles that require mileage registration are shown first const reorderedVehicles = useMemo( @@ -170,4 +170,4 @@ const VehiclesModule = React.memo( }, ) -export { VehiclesModule, validateVehiclesInitialData, useListVehiclesQuery } +export { VehiclesModule, validateVehiclesInitialData, useListVehiclesV2Query } diff --git a/apps/native/app/src/screens/more/personal-info.tsx b/apps/native/app/src/screens/more/personal-info.tsx index f0b7eec2784e..87417710ad0c 100644 --- a/apps/native/app/src/screens/more/personal-info.tsx +++ b/apps/native/app/src/screens/more/personal-info.tsx @@ -27,7 +27,7 @@ export const PersonalInfoScreen: NavigationFunctionComponent = ({ const intl = useIntl() const { dismiss, dismissed } = usePreferencesStore() const natRegRes = useNationalRegistryUserQuery() - const natRegData = natRegRes?.data?.nationalRegistryUser + const natRegData = natRegRes?.data?.nationalRegistryPerson const errorNatReg = !!natRegRes.error && !natRegData const loadingNatReg = natRegRes.loading && !natRegData diff --git a/apps/native/app/src/screens/vehicles/components/vehicle-item.tsx b/apps/native/app/src/screens/vehicles/components/vehicle-item.tsx index 100dc377366b..afe6b8c607a5 100644 --- a/apps/native/app/src/screens/vehicles/components/vehicle-item.tsx +++ b/apps/native/app/src/screens/vehicles/components/vehicle-item.tsx @@ -3,7 +3,7 @@ import React from 'react' import { FormattedDate, FormattedMessage } from 'react-intl' import { SafeAreaView, TouchableHighlight, View, ViewStyle } from 'react-native' import styled, { useTheme } from 'styled-components/native' -import { ListVehiclesQuery } from '../../../graphql/types/schema' +import { ListVehiclesV2Query } from '../../../graphql/types/schema' import { navigateTo } from '../../../lib/deep-linking' function differenceInMonths(a: Date, b: Date) { @@ -11,7 +11,7 @@ function differenceInMonths(a: Date, b: Date) { } type VehicleListItem = NonNullable< - NonNullable['vehicleList'] + NonNullable['vehicleList'] >[0] const Cell = styled(TouchableHighlight)` @@ -31,8 +31,8 @@ export const VehicleItem = React.memo( style?: ViewStyle }) => { const theme = useTheme() - const nextInspection = item?.nextInspection?.nextInspectionDate - ? new Date(item?.nextInspection.nextInspectionDate) + const nextInspection = item?.nextMainInspection + ? new Date(item?.nextMainInspection) : null const isInspectionDeadline = @@ -51,14 +51,14 @@ export const VehicleItem = React.memo( onPress={() => { navigateTo(`/vehicle/`, { id: item.permno, - title: item.type, + title: item.make, }) }} > ['vehicleList'] + NonNullable['vehicleList'] >[0] type ListItem = @@ -61,8 +61,6 @@ const Empty = () => ( const input = { page: 1, pageSize: 10, - showDeregeristered: false, - showHistory: false, } export const VehiclesScreen: NavigationFunctionComponent = ({ @@ -77,7 +75,7 @@ export const VehiclesScreen: NavigationFunctionComponent = ({ const scrollY = useRef(new Animated.Value(0)).current const loadingTimeout = useRef>() - const res = useListVehiclesQuery({ + const res = useListVehiclesV2Query({ variables: { input, }, @@ -135,7 +133,9 @@ export const VehiclesScreen: NavigationFunctionComponent = ({ // Extract key of data const keyExtractor = useCallback( (item: ListItem, index: number) => - item.__typename === 'Skeleton' ? String(item.id) : `${item.vin}${index}`, + item.__typename === 'Skeleton' + ? String(item.id) + : `${item.permno}${index}`, [], ) @@ -147,7 +147,7 @@ export const VehiclesScreen: NavigationFunctionComponent = ({ __typename: 'Skeleton', })) } - return res?.data?.vehiclesList?.vehicleList || [] + return res?.data?.vehiclesListV2?.vehicleList || [] }, [res.data, res.loading]) return ( @@ -184,8 +184,8 @@ export const VehiclesScreen: NavigationFunctionComponent = ({ if (res.loading) { return } - const pageNumber = res.data?.vehiclesList?.paging?.pageNumber ?? 1 - const totalPages = res.data?.vehiclesList?.paging?.totalPages ?? 1 + const pageNumber = res.data?.vehiclesListV2?.paging?.pageNumber ?? 1 + const totalPages = res.data?.vehiclesListV2?.paging?.totalPages ?? 1 if (pageNumber >= totalPages) { return } @@ -200,11 +200,11 @@ export const VehiclesScreen: NavigationFunctionComponent = ({ }, updateQuery(prev, { fetchMoreResult }) { return { - vehiclesList: { - ...fetchMoreResult.vehiclesList, + vehiclesListV2: { + ...fetchMoreResult.vehiclesListV2, vehicleList: [ - ...(prev.vehiclesList?.vehicleList ?? []), - ...(fetchMoreResult.vehiclesList?.vehicleList ?? []), + ...(prev.vehiclesListV2?.vehicleList ?? []), + ...(fetchMoreResult.vehiclesListV2?.vehicleList ?? []), ], }, } diff --git a/apps/native/app/src/ui/lib/avatar/avatar.tsx b/apps/native/app/src/ui/lib/avatar/avatar.tsx index 0debd370fd8a..d3a77094e7a7 100644 --- a/apps/native/app/src/ui/lib/avatar/avatar.tsx +++ b/apps/native/app/src/ui/lib/avatar/avatar.tsx @@ -38,13 +38,15 @@ interface AvatarProps { export function Avatar({ name, isSmall }: AvatarProps) { function getFirstLetters(str: string) { - const firstLetters = str - .split(' ') - .slice(0, 2) - .map((word) => word[0]) - .join('') + const names = str.split(' ') - return firstLetters + let initials = names[0].substring(0, 1).toUpperCase() + + if (names.length > 1) { + initials += names[names.length - 1].substring(0, 1).toUpperCase() + } + + return initials } return ( diff --git a/apps/native/app/src/ui/utils/theme.ts b/apps/native/app/src/ui/utils/theme.ts index ce97652ea88a..baec29a5de00 100644 --- a/apps/native/app/src/ui/utils/theme.ts +++ b/apps/native/app/src/ui/utils/theme.ts @@ -82,7 +82,7 @@ export const theme = { standard: '4px', large: '8px', extraLarge: '16px', - circle: '100px', + full: '100px', }, width: { standard: 1, diff --git a/apps/services/auth/admin-api/infra/auth-admin-api.ts b/apps/services/auth/admin-api/infra/auth-admin-api.ts index cf773f0dbd94..e93b1e2e1759 100644 --- a/apps/services/auth/admin-api/infra/auth-admin-api.ts +++ b/apps/services/auth/admin-api/infra/auth-admin-api.ts @@ -1,4 +1,5 @@ import { + CodeOwners, json, ref, service, @@ -27,6 +28,7 @@ export const serviceSetup = (): ServiceBuilder<'services-auth-admin-api'> => { return service('services-auth-admin-api') .namespace('identity-server-admin') .image('services-auth-admin-api') + .codeOwner(CodeOwners.Aranja) .db({ name: 'servicesauth', }) diff --git a/apps/services/auth/admin-api/project.json b/apps/services/auth/admin-api/project.json index 2866faa0019a..e5d91fd92127 100644 --- a/apps/services/auth/admin-api/project.json +++ b/apps/services/auth/admin-api/project.json @@ -57,6 +57,17 @@ }, "docker-express": { "executor": "Intentionally left blank, only so this target is valid when using `nx show projects --with-target docker-express`" + }, + "dev": { + "executor": "nx:run-commands", + "options": { + "commands": [ + { + "command": "yarn start --project services-auth-admin-api" + } + ], + "parallel": true + } } } } diff --git a/apps/services/auth/admin-api/src/app/v2/delegations/test/delegation-admin.spec.ts b/apps/services/auth/admin-api/src/app/v2/delegations/test/delegation-admin.spec.ts index 6d0637535db9..f4c0faeccff7 100644 --- a/apps/services/auth/admin-api/src/app/v2/delegations/test/delegation-admin.spec.ts +++ b/apps/services/auth/admin-api/src/app/v2/delegations/test/delegation-admin.spec.ts @@ -24,7 +24,7 @@ import { AuthDelegationType } from '@island.is/shared/types' import { getModelToken } from '@nestjs/sequelize' import { faker } from '@island.is/shared/mocking' import { TicketStatus, ZendeskService } from '@island.is/clients/zendesk' -import { NationalRegistryClientService } from '@island.is/clients/national-registry-v2' +import { NationalRegistryV3ClientService } from '@island.is/clients/national-registry-v3' import { ErrorCodes } from '@island.is/shared/utils' const currentUser = createCurrentUser({ @@ -36,7 +36,7 @@ describe('DelegationAdmin - With authentication', () => { let server: request.SuperTest let factory: FixtureFactory let zendeskService: ZendeskService - let nationalRegistryApi: NationalRegistryClientService + let nationalRegistryApi: NationalRegistryV3ClientService let delegationIndexServiceApi: DelegationsIndexService beforeEach(async () => { @@ -51,7 +51,7 @@ describe('DelegationAdmin - With authentication', () => { factory = new FixtureFactory(app) zendeskService = app.get(ZendeskService) - nationalRegistryApi = app.get(NationalRegistryClientService) + nationalRegistryApi = app.get(NationalRegistryV3ClientService) delegationIndexServiceApi = app.get(DelegationsIndexService) jest @@ -212,7 +212,7 @@ describe('DelegationAdmin - With authentication', () => { const mockNationalRegistryService = () => { nationalRegistryApiSpy = jest - .spyOn(nationalRegistryApi, 'getIndividual') + .spyOn(nationalRegistryApi, 'getAllDataIndividual') .mockImplementation(async (id) => { const user = createNationalRegistryUser({ nationalId: id, diff --git a/apps/services/auth/delegation-api/infra/delegation-api.ts b/apps/services/auth/delegation-api/infra/delegation-api.ts index 1dc2615d28d6..e1e98dcd9448 100644 --- a/apps/services/auth/delegation-api/infra/delegation-api.ts +++ b/apps/services/auth/delegation-api/infra/delegation-api.ts @@ -1,4 +1,5 @@ import { + CodeOwners, json, ref, service, @@ -29,6 +30,7 @@ export const serviceSetup = (services: { return service('services-auth-delegation-api') .namespace('identity-server-delegation') .image('services-auth-delegation-api') + .codeOwner(CodeOwners.Aranja) .db({ name: 'servicesauth', }) diff --git a/apps/services/auth/delegation-api/project.json b/apps/services/auth/delegation-api/project.json index 366532998b91..66890516fc3c 100644 --- a/apps/services/auth/delegation-api/project.json +++ b/apps/services/auth/delegation-api/project.json @@ -28,6 +28,17 @@ "buildTarget": "services-auth-delegation-api:build" } }, + "dev": { + "executor": "nx:run-commands", + "options": { + "commands": [ + { + "command": "yarn start services-auth-delegation-api" + } + ], + "parallel": true + } + }, "lint": { "executor": "@nx/eslint:lint" }, diff --git a/apps/services/auth/ids-api/infra/identity-server.ts b/apps/services/auth/ids-api/infra/identity-server.ts index 0e953612dc11..60fe5358f7b4 100644 --- a/apps/services/auth/ids-api/infra/identity-server.ts +++ b/apps/services/auth/ids-api/infra/identity-server.ts @@ -196,5 +196,6 @@ export const serviceSetup = (services: { 'nginx-ingress-external', 'user-notification', 'portals-admin', + 'datadog', ) } diff --git a/apps/services/auth/ids-api/infra/ids-api.ts b/apps/services/auth/ids-api/infra/ids-api.ts index 4282d5f39f9e..1afda547b717 100644 --- a/apps/services/auth/ids-api/infra/ids-api.ts +++ b/apps/services/auth/ids-api/infra/ids-api.ts @@ -1,4 +1,9 @@ -import { json, service, ServiceBuilder } from '../../../../../infra/src/dsl/dsl' +import { + CodeOwners, + json, + service, + ServiceBuilder, +} from '../../../../../infra/src/dsl/dsl' import { Base, Client, @@ -27,6 +32,7 @@ export const serviceSetup = (): ServiceBuilder<'services-auth-ids-api'> => { return service('services-auth-ids-api') .namespace(namespace) .image(imageName) + .codeOwner(CodeOwners.Aranja) .env({ IDENTITY_SERVER_CLIENT_ID: '@island.is/clients/auth-api', IDENTITY_SERVER_ISSUER_URL: { @@ -131,7 +137,7 @@ export const serviceSetup = (): ServiceBuilder<'services-auth-ids-api'> => { min: 2, max: 15, }) - .grantNamespaces('nginx-ingress-external', 'user-notification') + .grantNamespaces('nginx-ingress-external', 'user-notification', 'datadog') } const cleanupId = 'services-auth-ids-api-cleanup' diff --git a/apps/services/auth/ids-api/project.json b/apps/services/auth/ids-api/project.json index cfefdd77acda..b64e70508680 100644 --- a/apps/services/auth/ids-api/project.json +++ b/apps/services/auth/ids-api/project.json @@ -175,6 +175,17 @@ ], "parallel": true } + }, + "dev": { + "executor": "nx:run-commands", + "options": { + "commands": [ + { + "command": "yarn start services-auth-ids-api" + } + ], + "parallel": true + } } } } diff --git a/apps/services/auth/ids-api/src/app/delegations/delegations-personal-representative.controller.spec.ts b/apps/services/auth/ids-api/src/app/delegations/delegations-personal-representative.controller.spec.ts index 5c07ba95334d..bcf7ed73dab1 100644 --- a/apps/services/auth/ids-api/src/app/delegations/delegations-personal-representative.controller.spec.ts +++ b/apps/services/auth/ids-api/src/app/delegations/delegations-personal-representative.controller.spec.ts @@ -36,16 +36,13 @@ import { } from '@island.is/shared/types' import { createCurrentUser, + createNationalId, createNationalRegistryUser, } from '@island.is/testing/fixtures' import { TestApp } from '@island.is/testing/nest' import { defaultScopes, setupWithAuth } from '../../../test/setup' -import { - getFakeName, - getFakeNationalId, - NameIdTuple, -} from '../../../test/stubs/genericStubs' +import { getFakeName, NameIdTuple } from '../../../test/stubs/genericStubs' import { delegationTypes, getPersonalRepresentativeRelationship, @@ -55,6 +52,10 @@ import { personalRepresentativeType, } from '../../../test/stubs/personalRepresentativeStubs' +const getFakeNationalId = () => createNationalId('person') + +const setupHookTimeout = 10000 + describe('Personal Representative DelegationsController', () => { describe.each([false, true])( 'national registry v3 featureflag: %s', @@ -73,6 +74,7 @@ describe('Personal Representative DelegationsController', () => { let prTypeModel: typeof PersonalRepresentativeType let prDelegationTypeModel: typeof PersonalRepresentativeDelegationTypeModel let delegationTypeModel: typeof DelegationTypeModel + let nationalRegistryV3FeatureService: NationalRegistryV3FeatureService let nationalRegistryApi: NationalRegistryClientService let nationalRegistryV3Api: NationalRegistryV3ClientService let delegationProviderModel: typeof DelegationProviderModel @@ -152,17 +154,14 @@ describe('Personal Representative DelegationsController', () => { getModelToken(DelegationProviderModel), ) clientModel = app.get(getModelToken(Client)) + nationalRegistryV3FeatureService = app.get( + NationalRegistryV3FeatureService, + ) nationalRegistryApi = app.get(NationalRegistryClientService) nationalRegistryV3Api = app.get(NationalRegistryV3ClientService) delegationIndexService = app.get(DelegationsIndexService) - const nationalRegistryV3FeatureService = app.get( - NationalRegistryV3FeatureService, - ) - jest - .spyOn(nationalRegistryV3FeatureService, 'getValue') - .mockImplementation(async () => featureFlag) factory = new FixtureFactory(app) - }) + }, setupHookTimeout) const createDelegationTypeAndProvider = async (rightCode: string[]) => { const newDelegationProvider = await delegationProviderModel.create({ @@ -403,6 +402,10 @@ describe('Personal Representative DelegationsController', () => { ), ] + jest + .spyOn(nationalRegistryV3FeatureService, 'getValue') + .mockImplementation(async () => featureFlag) + nationalRegistryApiSpy = jest .spyOn(nationalRegistryApi, 'getIndividual') .mockImplementation(async (id) => { @@ -461,7 +464,7 @@ describe('Personal Representative DelegationsController', () => { }) afterAll(async () => { - jest.clearAllMocks() + jest.resetAllMocks() await prRightsModel.destroy({ where: {}, cascade: true, diff --git a/apps/services/auth/ids-api/src/app/delegations/test/delegations.controller.spec.ts b/apps/services/auth/ids-api/src/app/delegations/test/delegations.controller.spec.ts index f2dee16513d6..faee06788837 100644 --- a/apps/services/auth/ids-api/src/app/delegations/test/delegations.controller.spec.ts +++ b/apps/services/auth/ids-api/src/app/delegations/test/delegations.controller.spec.ts @@ -1,7 +1,7 @@ import { getModelToken } from '@nestjs/sequelize' -import addDays from 'date-fns/addDays' import request from 'supertest' import { uuid } from 'uuidv4' +import addDays from 'date-fns/addDays' import { ApiScope, @@ -27,12 +27,16 @@ import { } from '@island.is/shared/types' import { createCurrentUser, + createNationalId, createNationalRegistryUser, } from '@island.is/testing/fixtures' import { TestApp } from '@island.is/testing/nest' import { defaultScopes, setupWithAuth } from '../../../../test/setup' -import { getFakeNationalId } from '../../../../test/stubs/genericStubs' +import { + getFakeCompanyNationalId, + getFakeNationalId, +} from '../../../../test/stubs/genericStubs' describe('DelegationsController', () => { describe.each([false, true])( @@ -57,6 +61,8 @@ describe('DelegationsController', () => { clientId: '@island.is/webapp', }) + const representeeNationalId = createNationalId('person') + const scopeValid1 = 'scope/valid1' const scopeValid2 = 'scope/valid2' const scopeValid1and2 = 'scope/valid1and2' @@ -76,7 +82,7 @@ describe('DelegationsController', () => { scopeName: s, })) - const userNationalId = getFakeNationalId() + const userNationalId = createNationalId('person') const user = createCurrentUser({ nationalId: userNationalId, @@ -85,6 +91,8 @@ describe('DelegationsController', () => { }) const domain = createDomain() + let nationalRegistryApiSpy: jest.SpyInstance + let nationalRegistryV3ApiSpy: jest.SpyInstance beforeAll(async () => { app = await setupWithAuth({ @@ -117,36 +125,214 @@ describe('DelegationsController', () => { >(getModelToken(DelegationDelegationType)) nationalRegistryApi = app.get(NationalRegistryClientService) nationalRegistryV3Api = app.get(NationalRegistryV3ClientService) + factory = new FixtureFactory(app) + + client.supportedDelegationTypes = [ + AuthDelegationType.GeneralMandate, + AuthDelegationType.LegalGuardian, + AuthDelegationType.ProcurationHolder, + ] + await factory.createClient(client) + + nationalRegistryApiSpy = jest + .spyOn(nationalRegistryApi, 'getIndividual') + .mockImplementation(async (id) => { + const user = createNationalRegistryUser({ + nationalId: representeeNationalId, + }) + + return user ?? null + }) + + nationalRegistryV3ApiSpy = jest + .spyOn(nationalRegistryV3Api, 'getAllDataIndividual') + .mockImplementation(async () => { + const user = createNationalRegistryUser({ + nationalId: representeeNationalId, + }) + + return { kennitala: user.nationalId, nafn: user.name } + }) + const nationalRegistryV3FeatureService = app.get( NationalRegistryV3FeatureService, ) jest .spyOn(nationalRegistryV3FeatureService, 'getValue') .mockImplementation(async () => featureFlag) - factory = new FixtureFactory(app) }) afterAll(async () => { await app.cleanUp() + nationalRegistryV3ApiSpy.mockClear() + nationalRegistryApiSpy.mockClear() }) - describe('GET with general mandate delegation type', () => { - const representeeNationalId = getFakeNationalId() - let nationalRegistryApiSpy: jest.SpyInstance - let nationalRegistryV3ApiSpy: jest.SpyInstance + describe('GET with general mandate delegation type for company', () => { + const companyNationalId = getFakeCompanyNationalId() + const scopeNames = [ 'api-scope/generalMandate1', 'api-scope/generalMandate2', 'api-scope/generalMandate3', + 'api-scope/procuration1', + 'api-scope/procuration2', ] beforeAll(async () => { - client.supportedDelegationTypes = [ - AuthDelegationType.GeneralMandate, - AuthDelegationType.LegalGuardian, + const delegations = await delegationModel.create({ + id: uuid(), + fromDisplayName: 'Company', + fromNationalId: companyNationalId, + toNationalId: userNationalId, + toName: 'Person', + }) + + await delegationDelegationTypeModel.create({ + delegationId: delegations.id, + delegationTypeId: AuthDelegationType.GeneralMandate, + }) + + await apiScopeModel.bulkCreate( + scopeNames.map((name) => ({ + name, + domainName: domain.name, + enabled: true, + description: `${name}: description`, + displayName: `${name}: display name`, + })), + ) + + await apiScopeDelegationTypeModel.bulkCreate([ + { + apiScopeName: scopeNames[0], + delegationType: AuthDelegationType.GeneralMandate, + }, + { + apiScopeName: scopeNames[1], + delegationType: AuthDelegationType.GeneralMandate, + }, + { + apiScopeName: scopeNames[3], + delegationType: AuthDelegationType.ProcurationHolder, + }, + { + apiScopeName: scopeNames[4], + delegationType: AuthDelegationType.ProcurationHolder, + }, + ]) + }) + + afterAll(async () => { + await apiScopeDelegationTypeModel.destroy({ + where: {}, + cascade: true, + truncate: true, + force: true, + }) + await apiScopeModel.destroy({ + where: {}, + cascade: true, + truncate: true, + force: true, + }) + await delegationDelegationTypeModel.destroy({ + where: {}, + cascade: true, + truncate: true, + force: true, + }) + await delegationModel.destroy({ + where: {}, + cascade: true, + truncate: true, + force: true, + }) + }) + + it('should return mergedDelegationDTO with the generalMandate', async () => { + const response = await server.get('/v2/delegations') + + expect(response.status).toEqual(200) + expect(response.body).toHaveLength(1) + }) + + it('should return all general mandate scopes and other preset scopes', async () => { + const response = await server.get('/delegations/scopes').query({ + fromNationalId: companyNationalId, + delegationType: [ + AuthDelegationType.GeneralMandate, + AuthDelegationType.ProcurationHolder, + ], + }) + + const expected = [ + scopeNames[0], + scopeNames[1], + scopeNames[3], + scopeNames[4], + ] + + expect(response.status).toEqual(200) + expect(response.body).toEqual(expect.arrayContaining(expected)) + expect(response.body).toHaveLength(expected.length) + }) + + it('should return all general mandate scopes and all procuration scopes', async () => { + const response = await server.get('/delegations/scopes').query({ + fromNationalId: companyNationalId, + delegationType: [AuthDelegationType.GeneralMandate], + }) + + const expected = [ + scopeNames[0], + scopeNames[1], + scopeNames[3], + scopeNames[4], ] - await factory.createClient(client) + expect(response.status).toEqual(200) + expect(response.body).toEqual(expect.arrayContaining(expected)) + expect(response.body).toHaveLength(expected.length) + }) + + it('should return all general mandate scopes, and not procuration scopes since from nationalId is person', async () => { + // Assert + const delegation = await delegationModel.create({ + id: uuid(), + fromDisplayName: 'FromPersonPerson', + fromNationalId: representeeNationalId, + toNationalId: userNationalId, + toName: 'Person', + }) + + await delegationDelegationTypeModel.create({ + delegationId: delegation.id, + delegationTypeId: AuthDelegationType.GeneralMandate, + }) + + // Act + const response = await server.get('/delegations/scopes').query({ + fromNationalId: representeeNationalId, + delegationType: [AuthDelegationType.GeneralMandate], + }) + + const expected = [scopeNames[0], scopeNames[1]] + + expect(response.status).toEqual(200) + expect(response.body).toEqual(expect.arrayContaining(expected)) + expect(response.body).toHaveLength(expected.length) + }) + }) + + describe('GET with general mandate delegation type', () => { + const scopeNames = [ + 'api-scope/generalMandate1', + 'api-scope/generalMandate2', + 'api-scope/generalMandate3', + ] + + beforeAll(async () => { const delegations = await delegationModel.create({ id: uuid(), fromDisplayName: 'Test', @@ -187,32 +373,39 @@ describe('DelegationsController', () => { delegationType: AuthDelegationType.GeneralMandate, }, ]) - - nationalRegistryApiSpy = jest - .spyOn(nationalRegistryApi, 'getIndividual') - .mockImplementation(async (id) => { - const user = createNationalRegistryUser({ - nationalId: representeeNationalId, - }) - - return user ?? null - }) - - nationalRegistryV3ApiSpy = jest - .spyOn(nationalRegistryV3Api, 'getAllDataIndividual') - .mockImplementation(async () => { - const user = createNationalRegistryUser({ - nationalId: representeeNationalId, - }) - - return { kennitala: user.nationalId, nafn: user.name } - }) }) afterAll(async () => { - await app.cleanUp() - nationalRegistryApiSpy.mockClear() - nationalRegistryV3ApiSpy.mockClear() + await apiScopeDelegationTypeModel.destroy({ + where: {}, + cascade: true, + truncate: true, + force: true, + }) + await apiScopeModel.destroy({ + where: {}, + cascade: true, + truncate: true, + force: true, + }) + await delegationProviderModel.destroy({ + where: {}, + cascade: true, + truncate: true, + force: true, + }) + await delegationDelegationTypeModel.destroy({ + where: {}, + cascade: true, + truncate: true, + force: true, + }) + await delegationModel.destroy({ + where: {}, + cascade: true, + truncate: true, + force: true, + }) }) it('should return mergedDelegationDTO with the generalMandate', async () => { diff --git a/apps/services/auth/ids-api/src/app/user-profile/user-profile.service.ts b/apps/services/auth/ids-api/src/app/user-profile/user-profile.service.ts index 9e310e1513c9..626b782bb437 100644 --- a/apps/services/auth/ids-api/src/app/user-profile/user-profile.service.ts +++ b/apps/services/auth/ids-api/src/app/user-profile/user-profile.service.ts @@ -130,7 +130,7 @@ export class UserProfileService { } return { - name: individual.fulltNafn?.fulltNafn ?? individual.nafn ?? undefined, + name: individual.nafn ?? undefined, givenName: individual.fulltNafn?.eiginNafn ?? undefined, familyName: individual.fulltNafn?.kenniNafn ?? undefined, middleName: individual.fulltNafn?.milliNafn ?? undefined, diff --git a/apps/services/auth/ids-api/test/stubs/genericStubs.ts b/apps/services/auth/ids-api/test/stubs/genericStubs.ts index 91956b00fcc5..177ad31ae023 100644 --- a/apps/services/auth/ids-api/test/stubs/genericStubs.ts +++ b/apps/services/auth/ids-api/test/stubs/genericStubs.ts @@ -6,6 +6,8 @@ export type NameIdTuple = [name: string, id: string] export const getFakeNationalId = () => faker.helpers.replaceSymbolWithNumber('##########') +export const getFakeCompanyNationalId = () => createNationalId('company') + export const getFakeName = () => faker.fake('{{name.firstName}} {{name.lastName}}') @@ -18,4 +20,5 @@ export default { getFakeNationalId, getFakeName, getFakePerson, + getFakeCompanyNationalId, } diff --git a/apps/services/auth/public-api/infra/auth-public-api.ts b/apps/services/auth/public-api/infra/auth-public-api.ts index 609588c46271..d8ca744663b9 100644 --- a/apps/services/auth/public-api/infra/auth-public-api.ts +++ b/apps/services/auth/public-api/infra/auth-public-api.ts @@ -1,4 +1,9 @@ -import { json, service, ServiceBuilder } from '../../../../../infra/src/dsl/dsl' +import { + CodeOwners, + json, + service, + ServiceBuilder, +} from '../../../../../infra/src/dsl/dsl' import { Base, Client, @@ -23,6 +28,7 @@ export const serviceSetup = (): ServiceBuilder<'services-auth-public-api'> => { .namespace('identity-server-admin') .image('services-auth-public-api') .db({ name: 'servicesauth' }) + .codeOwner(CodeOwners.Aranja) .env({ IDENTITY_SERVER_CLIENT_ID: '@island.is/clients/auth-api', IDENTITY_SERVER_ISSUER_URL: { diff --git a/apps/services/bff/infra/admin-portal.infra.ts b/apps/services/bff/infra/admin-portal.infra.ts index e7227d3f379a..46e246a554ce 100644 --- a/apps/services/bff/infra/admin-portal.infra.ts +++ b/apps/services/bff/infra/admin-portal.infra.ts @@ -1,5 +1,10 @@ /* eslint-disable @nx/enforce-module-boundaries */ -import { ServiceBuilder, json, service } from '../../../../infra/src/dsl/dsl' +import { + ServiceBuilder, + json, + service, + CodeOwners, +} from '../../../../infra/src/dsl/dsl' import { BffInfraServices } from '../../../../infra/src/dsl/types/input-types' const bffName = 'services-bff' @@ -13,6 +18,7 @@ export const serviceSetup = ( service(serviceName) .namespace(clientName) .image(bffName) + .codeOwner(CodeOwners.Core) .redis() .serviceAccount(bffName) .env({ diff --git a/apps/services/endorsements/api/infra/endorsement-system-api.ts b/apps/services/endorsements/api/infra/endorsement-system-api.ts index 865c1d945b8f..60ffa938b194 100644 --- a/apps/services/endorsements/api/infra/endorsement-system-api.ts +++ b/apps/services/endorsements/api/infra/endorsement-system-api.ts @@ -1,4 +1,8 @@ -import { service, ServiceBuilder } from '../../../../../infra/src/dsl/dsl' +import { + CodeOwners, + service, + ServiceBuilder, +} from '../../../../../infra/src/dsl/dsl' import { Base, Client, @@ -12,6 +16,7 @@ export const serviceSetup = .image('services-endorsements-api') .namespace('endorsement-system') .serviceAccount('endorsement-system-api') + .codeOwner(CodeOwners.Juni) .command('node') .args('--tls-min-v1.0', '--no-experimental-fetch', 'main.js') .db({ name: 'services-endorsements-api' }) diff --git a/apps/services/form-system/infra/form-system.ts b/apps/services/form-system/infra/form-system.ts index 41bacb92c560..9dda94f1db68 100644 --- a/apps/services/form-system/infra/form-system.ts +++ b/apps/services/form-system/infra/form-system.ts @@ -1,9 +1,14 @@ -import { service, ServiceBuilder } from '../../../../infra/src/dsl/dsl' +import { + CodeOwners, + service, + ServiceBuilder, +} from '../../../../infra/src/dsl/dsl' export const serviceSetup = (): ServiceBuilder<'services-form-system'> => service('services-form-system') .image('services-form-system') .namespace('services-form-system') + .codeOwner(CodeOwners.Advania) .env({ IDENTITY_SERVER_ISSUER_URL: { dev: 'https://identity-server.dev01.devland.is', diff --git a/apps/services/license-api/infra/license-api.ts b/apps/services/license-api/infra/license-api.ts index 1b5d32886203..7cca417cc585 100644 --- a/apps/services/license-api/infra/license-api.ts +++ b/apps/services/license-api/infra/license-api.ts @@ -1,16 +1,22 @@ -import { json, service, ServiceBuilder } from '../../../../infra/src/dsl/dsl' +import { + CodeOwners, + json, + service, + ServiceBuilder, +} from '../../../../infra/src/dsl/dsl' import { Base, Client, Disability, - Firearm, DrivingLicense, + Firearm, Hunting, } from '../../../../infra/src/dsl/xroad' export const serviceSetup = (): ServiceBuilder<'license-api'> => service('license-api') .namespace('license-api') + .codeOwner(CodeOwners.Hugsmidjan) .resources({ limits: { cpu: '400m', memory: '512Mi' }, requests: { cpu: '50m', memory: '256Mi' }, diff --git a/apps/services/regulations-admin-backend/infra/regulations-admin-backend.ts b/apps/services/regulations-admin-backend/infra/regulations-admin-backend.ts index 1af574773a05..1b5d7066b614 100644 --- a/apps/services/regulations-admin-backend/infra/regulations-admin-backend.ts +++ b/apps/services/regulations-admin-backend/infra/regulations-admin-backend.ts @@ -1,4 +1,8 @@ -import { service, ServiceBuilder } from '../../../../infra/src/dsl/dsl' +import { + CodeOwners, + service, + ServiceBuilder, +} from '../../../../infra/src/dsl/dsl' import { Base, Client, @@ -9,6 +13,7 @@ export const serviceSetup = (): ServiceBuilder<'regulations-admin-backend'> => service('regulations-admin-backend') .image('regulations-admin-backend') .namespace('regulations-admin') + .codeOwner(CodeOwners.Hugsmidjan) .env({ IDENTITY_SERVER_ISSUER_URL: { dev: 'https://identity-server.dev01.devland.is', diff --git a/apps/services/search-indexer/infra/search-indexer-service.ts b/apps/services/search-indexer/infra/search-indexer-service.ts index 521c9afa4475..a9e3cbd6ea97 100644 --- a/apps/services/search-indexer/infra/search-indexer-service.ts +++ b/apps/services/search-indexer/infra/search-indexer-service.ts @@ -1,4 +1,9 @@ -import { ref, service, ServiceBuilder } from '../../../../infra/src/dsl/dsl' +import { + CodeOwners, + ref, + service, + ServiceBuilder, +} from '../../../../infra/src/dsl/dsl' const envs = { APPLICATION_URL: 'http://search-indexer-service', @@ -33,6 +38,7 @@ export const serviceSetup = (): ServiceBuilder<'search-indexer-service'> => .image('services-search-indexer') .namespace('search-indexer') .serviceAccount('search-indexer') + .codeOwner(CodeOwners.Stefna) .secrets({ CONTENTFUL_ACCESS_TOKEN: '/k8s/search-indexer/CONTENTFUL_ACCESS_TOKEN', API_CMS_SYNC_TOKEN: '/k8s/search-indexer/API_CMS_SYNC_TOKEN', diff --git a/apps/services/sessions/infra/sessions.ts b/apps/services/sessions/infra/sessions.ts index bb771f1b2383..a5c0683246fa 100644 --- a/apps/services/sessions/infra/sessions.ts +++ b/apps/services/sessions/infra/sessions.ts @@ -1,4 +1,8 @@ -import { service, ServiceBuilder } from '../../../../infra/src/dsl/dsl' +import { + CodeOwners, + service, + ServiceBuilder, +} from '../../../../infra/src/dsl/dsl' const namespace = 'services-sessions' const imageName = 'services-sessions' @@ -7,6 +11,7 @@ export const serviceSetup = (): ServiceBuilder<'services-sessions'> => service('services-sessions') .namespace(namespace) .image(imageName) + .codeOwner(CodeOwners.Aranja) .redis() .db({ readOnly: true, @@ -54,6 +59,7 @@ export const workerSetup = (): ServiceBuilder<'services-sessions-worker'> => service('services-sessions-worker') .image(imageName) .namespace(namespace) + .codeOwner(CodeOwners.Aranja) .redis() .serviceAccount('sessions-worker') .command('node') @@ -92,6 +98,7 @@ export const cleanupSetup = (): ServiceBuilder => service(cleanupId) .namespace(namespace) .image(imageName) + .codeOwner(CodeOwners.Aranja) .command('node') .args('main.js', '--job=cleanup') .resources({ diff --git a/apps/services/university-gateway/infra/university-gateway.ts b/apps/services/university-gateway/infra/university-gateway.ts index f56f1cf8f8ae..15357d06e5c3 100644 --- a/apps/services/university-gateway/infra/university-gateway.ts +++ b/apps/services/university-gateway/infra/university-gateway.ts @@ -1,4 +1,8 @@ -import { service, ServiceBuilder } from '../../../../infra/src/dsl/dsl' +import { + CodeOwners, + service, + ServiceBuilder, +} from '../../../../infra/src/dsl/dsl' import { Base, Client, @@ -21,6 +25,7 @@ export const serviceSetup = (): ServiceBuilder => { .serviceAccount(serviceName) .namespace(namespace) .image(imageName) + .codeOwner(CodeOwners.Origo) .command('node') .redis() .args('main.js') @@ -79,6 +84,7 @@ export const workerSetup = (): ServiceBuilder => { .serviceAccount(serviceWorkerName) .namespace(namespace) .image(imageName) + .codeOwner(CodeOwners.Origo) .command('node') .redis() .args('main.js', '--job', 'worker') diff --git a/apps/services/user-notification/infra/user-notification.ts b/apps/services/user-notification/infra/user-notification.ts index d71a994b67c6..96c8788bf22a 100644 --- a/apps/services/user-notification/infra/user-notification.ts +++ b/apps/services/user-notification/infra/user-notification.ts @@ -5,6 +5,7 @@ import { RskCompanyInfo, } from '../../../../infra/src/dsl/xroad' import { + CodeOwners, json, ref, service, @@ -56,6 +57,7 @@ export const userNotificationServiceSetup = (services: { .image(imageName) .namespace(serviceName) .serviceAccount(serviceName) + .codeOwner(CodeOwners.Juni) .db() .command('node') .args('--no-experimental-fetch', 'main.js') @@ -121,6 +123,7 @@ export const userNotificationWorkerSetup = (services: { .image(imageName) .namespace(serviceName) .serviceAccount(serviceWorkerName) + .codeOwner(CodeOwners.Juni) .command('node') .args('--no-experimental-fetch', 'main.js', '--job=worker') .db() @@ -169,6 +172,7 @@ export const userNotificationCleanUpWorkerSetup = (): ServiceBuilder< .image(imageName) .namespace(serviceName) .serviceAccount(serviceCleanupWorkerName) + .codeOwner(CodeOwners.Juni) .command('node') .args('--no-experimental-fetch', 'main.js', '--job=cleanup') .db({ name: 'user-notification' }) diff --git a/apps/services/user-notification/src/app/modules/notifications/me-notifications.controller.ts b/apps/services/user-notification/src/app/modules/notifications/me-notifications.controller.ts index da5d5c7e63a9..26deb3a189a6 100644 --- a/apps/services/user-notification/src/app/modules/notifications/me-notifications.controller.ts +++ b/apps/services/user-notification/src/app/modules/notifications/me-notifications.controller.ts @@ -52,7 +52,7 @@ export class MeNotificationsController { @CurrentUser() user: User, @Query() query: ExtendedPaginationDto, ): Promise { - return this.notificationService.findMany(user, query) + return this.notificationService.findManyWithTemplate(user.nationalId, query) } @Get('/unread-count') diff --git a/apps/services/user-notification/src/app/modules/notifications/notifications.controller.ts b/apps/services/user-notification/src/app/modules/notifications/notifications.controller.ts index a1425841a8b8..c8f578ce6397 100644 --- a/apps/services/user-notification/src/app/modules/notifications/notifications.controller.ts +++ b/apps/services/user-notification/src/app/modules/notifications/notifications.controller.ts @@ -3,10 +3,13 @@ import { Body, Controller, Get, + Headers, + HttpStatus, Inject, Param, Post, Query, + UseGuards, Version, } from '@nestjs/common' import { ApiTags } from '@nestjs/swagger' @@ -19,6 +22,12 @@ import { CreateHnippNotificationDto } from './dto/createHnippNotification.dto' import { HnippTemplate } from './dto/hnippTemplate.response' import { NotificationsService } from './notifications.service' import type { Locale } from '@island.is/shared/types' +import { + ExtendedPaginationDto, + PaginatedNotificationDto, +} from './dto/notification.dto' +import { IdsUserGuard, Scopes, ScopesGuard } from '@island.is/auth-nest-tools' +import { AdminPortalScope } from '@island.is/auth/scopes' @Controller('notifications') @ApiTags('notifications') @@ -85,6 +94,20 @@ export class NotificationsController { return await this.notificationsService.getTemplate(templateId, locale) } + @UseGuards(IdsUserGuard, ScopesGuard) + @Scopes(AdminPortalScope.serviceDesk) + @Get('/') + @Documentation({ + summary: 'Returns a paginated list of notifications for a national id', + response: { status: HttpStatus.OK, type: PaginatedNotificationDto }, + }) + findMany( + @Headers('X-Query-National-Id') nationalId: string, + @Query() query: ExtendedPaginationDto, + ): Promise { + return this.notificationsService.findMany(nationalId, query) + } + @Documentation({ summary: 'Creates a new notification and adds to queue', includeNoContentResponse: true, diff --git a/apps/services/user-notification/src/app/modules/notifications/notifications.service.ts b/apps/services/user-notification/src/app/modules/notifications/notifications.service.ts index 8d8e937ff0f7..4116120d2744 100644 --- a/apps/services/user-notification/src/app/modules/notifications/notifications.service.ts +++ b/apps/services/user-notification/src/app/modules/notifications/notifications.service.ts @@ -260,8 +260,24 @@ export class NotificationsService { ) } - async findMany( - user: User, + findMany( + nationalId: string, + query: ExtendedPaginationDto, + ): Promise { + return paginate({ + Model: this.notificationModel, + limit: query.limit || 10, + after: query.after || '', + before: query.before, + primaryKeyField: 'id', + orderOption: [['id', 'DESC']], + where: { recipient: nationalId }, + attributes: ['id', 'messageId', 'senderId', 'created', 'updated'], + }) + } + + async findManyWithTemplate( + nationalId: string, query: ExtendedPaginationDto, ): Promise { const locale = mapToLocale(query.locale as Locale) @@ -273,7 +289,7 @@ export class NotificationsService { before: query.before, primaryKeyField: 'id', orderOption: [['id', 'DESC']], - where: { recipient: user.nationalId }, + where: { recipient: nationalId }, }) const formattedNotifications = await Promise.all( diff --git a/apps/services/user-notification/src/app/modules/notifications/tests/notifications.service.spec.ts b/apps/services/user-notification/src/app/modules/notifications/tests/notifications.service.spec.ts index 8820d8ddd2cb..8456f9a5333e 100644 --- a/apps/services/user-notification/src/app/modules/notifications/tests/notifications.service.spec.ts +++ b/apps/services/user-notification/src/app/modules/notifications/tests/notifications.service.spec.ts @@ -159,7 +159,9 @@ describe('NotificationsService', () => { .spyOn(service, 'findMany') .mockImplementation(async () => mockedResponse) - expect(await service.findMany(user, query)).toBe(mockedResponse) + expect(await service.findMany(user.nationalId, query)).toBe( + mockedResponse, + ) }) }) diff --git a/apps/services/user-profile/infra/service-portal-api.ts b/apps/services/user-profile/infra/service-portal-api.ts index e8d9d75f88cb..3e070897e824 100644 --- a/apps/services/user-profile/infra/service-portal-api.ts +++ b/apps/services/user-profile/infra/service-portal-api.ts @@ -1,4 +1,9 @@ -import { json, service, ServiceBuilder } from '../../../../infra/src/dsl/dsl' +import { + CodeOwners, + json, + service, + ServiceBuilder, +} from '../../../../infra/src/dsl/dsl' import { EnvironmentVariables, Secrets, @@ -63,6 +68,7 @@ export const serviceSetup = (): ServiceBuilder => .namespace(namespace) .image(imageId) .serviceAccount(serviceId) + .codeOwner(CodeOwners.Aranja) .env(envVariables) .secrets(secrets) .xroad(Base, Client, NationalRegistryB2C) diff --git a/apps/web/components/GenericList/GenericList.tsx b/apps/web/components/GenericList/GenericList.tsx index d717d1616388..bbc7592e5172 100644 --- a/apps/web/components/GenericList/GenericList.tsx +++ b/apps/web/components/GenericList/GenericList.tsx @@ -311,6 +311,7 @@ export const GenericList = ({ key={value} active={true} onClick={() => { + setPage(null) setParameters((prevParameters) => { const updatedParameters = { ...prevParameters, @@ -465,6 +466,7 @@ export const GenericList = ({ if (!category) { return } + setPage(null) setParameters((prevParameters) => ({ ...prevParameters, [category]: ( diff --git a/apps/web/components/OfficialJournalOfIceland/OJOIAdvertCard.tsx b/apps/web/components/OfficialJournalOfIceland/OJOIAdvertCard.tsx index fe375bbe25fa..089ebaf2630a 100644 --- a/apps/web/components/OfficialJournalOfIceland/OJOIAdvertCard.tsx +++ b/apps/web/components/OfficialJournalOfIceland/OJOIAdvertCard.tsx @@ -66,7 +66,7 @@ export const OJOIAdvertCard = ({ marginTop={2} rowGap={1} > - {categories && categories.length && ( + {categories && categories.length > 0 && ( {categories.map((cat) => { return ( diff --git a/apps/web/components/Organization/Wrapper/OrganizationWrapper.tsx b/apps/web/components/Organization/Wrapper/OrganizationWrapper.tsx index d42d13d63913..44e38cb37d59 100644 --- a/apps/web/components/Organization/Wrapper/OrganizationWrapper.tsx +++ b/apps/web/components/Organization/Wrapper/OrganizationWrapper.tsx @@ -128,7 +128,7 @@ interface NavigationData { interface WrapperProps { pageTitle: string pageDescription?: string - pageFeaturedImage?: Image + pageFeaturedImage?: Image | null organizationPage: OrganizationPage breadcrumbItems?: BreadCrumbItem[] mainContent?: ReactNode diff --git a/apps/web/components/Webreader/Webreader.tsx b/apps/web/components/Webreader/Webreader.tsx index 1c9793b7abd9..107d8079cbde 100644 --- a/apps/web/components/Webreader/Webreader.tsx +++ b/apps/web/components/Webreader/Webreader.tsx @@ -109,7 +109,7 @@ const Webreader: FC> = ({ : 'Listen to this page using ReadSpeaker' return ( - +
{ + return String(round(score, 1)).replace('.', ',') +} + interface Question { question: string answerOptions: { @@ -41,6 +46,7 @@ interface Step { interface CheckboxState { steps: { title: string + maxScorePossible: number questions: { selectedAnswerIndex: number answerScore: number @@ -119,89 +125,107 @@ interface WHODASResultsProps { steps: (Pick & { scoreForStep: number })[] } bracket: 1 | 2 + totalScore: number } -const WHODASResults = ({ results, bracket }: WHODASResultsProps) => { +const WHODASResults = ({ + results, + bracket, + totalScore, +}: WHODASResultsProps) => { const { format } = useDateUtils() const date = format(new Date(), 'do MMMM yyyy') const { formatMessage } = useIntl() return ( - - - - {formatMessage(m.results.mainHeading)} - - - - {date} - - - {formatMessage(m.results.scoreHeading)} - - + + + + + {formatMessage(m.results.mainHeading)} + + + + {date} + + + {formatMessage(m.results.scoreHeading)} + + + + {formatScore(totalScore)} {formatMessage(m.results.outOf100)} + + + + + + {formatMessage(m.results.interpretationHeading)} + {formatMessage( bracket === 1 - ? m.results.firstBracketScoreText - : m.results.secondBracketScoreText, + ? m.results.firstBracketInterpretationText + : m.results.secondBracketInterpretationText, )} - - - - - {formatMessage(m.results.interpretationHeading)} - - - {formatMessage( - bracket === 1 - ? m.results.firstBracketInterpretationText - : m.results.secondBracketInterpretationText, - )} - - - - - - {formatMessage(m.results.adviceHeading)} - - - {formatMessage( - bracket === 1 - ? m.results.firstBracketAdviceText - : m.results.secondBracketAdviceText, - )} - - + - {bracket !== 1 && ( - {formatMessage(m.results.breakdownHeading)} + {formatMessage(m.results.adviceHeading)} - - {results.steps.map((step) => ( - - - {step.title} - {step.scoreForStep} - - - ))} - + + {formatMessage( + bracket === 1 + ? m.results.firstBracketAdviceText + : m.results.secondBracketAdviceText, + )} + - )} + + {bracket > 1 && ( + + + + + {formatMessage(m.results.breakdownHeading)} + + + {results.steps.map((step) => ( + + + {step.title} + + {formatScore(step.scoreForStep)}{' '} + {formatMessage(m.results.outOf100)} + + + + ))} + + + + + {formatMessage(m.results.resultDisclaimer)} + + + )} + ) } @@ -225,6 +249,14 @@ export const WHODASCalculator = ({ slice }: WHODASCalculatorProps) => { steps: steps.map(({ title, description, questions }) => ({ title, description, + maxScorePossible: questions.reduce( + (prev, acc) => + prev + + (acc.answerOptions.length > 0 + ? acc.answerOptions[acc.answerOptions.length - 1].score + : 0), + 0, + ), questions: questions.map(() => ({ selectedAnswerIndex: 0, answerScore: 0, @@ -245,74 +277,99 @@ export const WHODASCalculator = ({ slice }: WHODASCalculatorProps) => { if (showResults) { let totalScore = 0 + let totalMaxScorePossible = 0 const results: WHODASResultsProps['results'] = { steps: [], } for (const stateStep of state.steps) { + totalMaxScorePossible += stateStep.maxScorePossible let score = 0 for (const question of stateStep.questions) { score += question.answerScore } - results.steps.push({ ...stateStep, scoreForStep: score }) totalScore += score + if (stateStep.maxScorePossible > 0) { + score = (score * 100) / stateStep.maxScorePossible + } + results.steps.push({ ...stateStep, scoreForStep: score }) + } + if (totalMaxScorePossible > 0) { + totalScore = (totalScore * 100) / totalMaxScorePossible } return ( - + + + {formatMessage(m.results.topDescription)} + + + + + ) } return ( - - - - - - {formatMessage(m.form.progress, { - stepIndex: stepIndex + 1, - stepCount: steps.length, - })} - - + + + {formatMessage(m.form.topDescription)} + + + + + + + {formatMessage(m.form.progress, { + stepIndex: stepIndex + 1, + stepCount: steps.length, + })} + + + + - - - - - {stepIndex > 0 && ( + + + {stepIndex > 0 && ( + + )} - )} - - + + ) } diff --git a/apps/web/infra/web.ts b/apps/web/infra/web.ts index a85284278d41..5e1bf92540dd 100644 --- a/apps/web/infra/web.ts +++ b/apps/web/infra/web.ts @@ -1,4 +1,9 @@ -import { ref, service, ServiceBuilder } from '../../../infra/src/dsl/dsl' +import { + CodeOwners, + ref, + service, + ServiceBuilder, +} from '../../../infra/src/dsl/dsl' export const serviceSetup = (services: { api: ServiceBuilder<'api'> @@ -6,6 +11,7 @@ export const serviceSetup = (services: { const web = service('web') web .namespace('islandis') + .codeOwner(CodeOwners.Stefna) .env({ API_URL: ref((h) => `http://${h.svc(services.api)}`), TRACKING_DOMAIN: { diff --git a/apps/web/pages/s/[...slugs]/index.tsx b/apps/web/pages/s/[...slugs]/index.tsx index 9eca5605ac4c..e5bee55e773d 100644 --- a/apps/web/pages/s/[...slugs]/index.tsx +++ b/apps/web/pages/s/[...slugs]/index.tsx @@ -25,6 +25,9 @@ import OrganizationNewsArticle, { import OrganizationNewsList, { type OrganizationNewsListProps, } from '@island.is/web/screens/Organization/OrganizationNews/OrganizationNewsList' +import OrganizationParentSubpage, { + type OrganizationParentSubpageProps, +} from '@island.is/web/screens/Organization/ParentSubpage' import PublishedMaterial, { type PublishedMaterialProps, } from '@island.is/web/screens/Organization/PublishedMaterial/PublishedMaterial' @@ -54,6 +57,7 @@ enum PageType { STANDALONE_PARENT_SUBPAGE = 'standalone-parent-subpage', STANDALONE_LEVEL1_SITEMAP = 'standalone-level1-sitemap', STANDALONE_LEVEL2_SITEMAP = 'standalone-level2-sitemap', + PARENT_SUBPAGE = 'parent-subpage', SUBPAGE = 'subpage', ALL_NEWS = 'news', PUBLISHED_MATERIAL = 'published-material', @@ -76,6 +80,9 @@ const pageMap: Record> = { [PageType.STANDALONE_LEVEL2_SITEMAP]: (props) => ( ), + [PageType.PARENT_SUBPAGE]: (props) => ( + + ), [PageType.SUBPAGE]: (props) => , [PageType.ALL_NEWS]: (props) => , [PageType.PUBLISHED_MATERIAL]: (props) => , @@ -112,6 +119,13 @@ interface Props { type: PageType.STANDALONE_LEVEL2_SITEMAP props: StandaloneLevel2SitemapProps } + | { + type: PageType.PARENT_SUBPAGE + props: { + layoutProps: LayoutProps + componentProps: OrganizationParentSubpageProps + } + } | { type: PageType.SUBPAGE props: { @@ -282,10 +296,18 @@ Component.getProps = async (context) => { } try { + if (isStandaloneTheme) { + return { + page: { + type: PageType.STANDALONE_PARENT_SUBPAGE, + props: await StandaloneParentSubpage.getProps(modifiedContext), + }, + } + } return { page: { - type: PageType.STANDALONE_PARENT_SUBPAGE, - props: await StandaloneParentSubpage.getProps(modifiedContext), + type: PageType.PARENT_SUBPAGE, + props: await OrganizationParentSubpage.getProps(modifiedContext), }, } } catch (error) { @@ -360,10 +382,18 @@ Component.getProps = async (context) => { } try { + if (isStandaloneTheme) { + return { + page: { + type: PageType.STANDALONE_PARENT_SUBPAGE, + props: await StandaloneParentSubpage.getProps(modifiedContext), + }, + } + } return { page: { - type: PageType.STANDALONE_PARENT_SUBPAGE, - props: await StandaloneParentSubpage.getProps(modifiedContext), + type: PageType.PARENT_SUBPAGE, + props: await OrganizationParentSubpage.getProps(modifiedContext), }, } } catch (error) { diff --git a/apps/web/screens/OfficialJournalOfIceland/OJOISearch.tsx b/apps/web/screens/OfficialJournalOfIceland/OJOISearch.tsx index 86a586ccc44d..a3c4371e88d3 100644 --- a/apps/web/screens/OfficialJournalOfIceland/OJOISearch.tsx +++ b/apps/web/screens/OfficialJournalOfIceland/OJOISearch.tsx @@ -105,12 +105,8 @@ const OJOISearchPage: CustomScreen = ({ category: [defaultSearchParams.malaflokkur], involvedParty: [defaultSearchParams.stofnun], type: [defaultSearchParams.tegund], - dateFrom: defaultSearchParams.dagsFra - ? new Date(defaultSearchParams.dagsFra) - : undefined, - dateTo: defaultSearchParams.dagsTil - ? new Date(defaultSearchParams.dagsTil) - : undefined, + dateFrom: defaultSearchParams.dagsFra, + dateTo: defaultSearchParams.dagsTil, search: defaultSearchParams.q, page: defaultSearchParams.sida, pageSize: defaultSearchParams.staerd, @@ -176,12 +172,8 @@ const OJOISearchPage: CustomScreen = ({ category: [searchValues.malaflokkur], involvedParty: [searchValues.stofnun], type: [searchValues.tegund], - dateFrom: searchValues.dagsFra - ? new Date(searchValues.dagsFra) - : undefined, - dateTo: searchValues.dagsTil - ? new Date(searchValues.dagsTil) - : undefined, + dateFrom: searchValues.dagsFra, + dateTo: searchValues.dagsTil, search: searchValues.q, page: searchValues.sida, pageSize: searchValues.staerd, @@ -596,12 +588,8 @@ OJOISearch.getProps = async ({ apolloClient, locale, query }) => { variables: { input: { category: [defaultParams.malaflokkur], - dateFrom: defaultParams.dagsFra - ? new Date(defaultParams.dagsFra) - : undefined, - dateTo: defaultParams.dagsTil - ? new Date(defaultParams.dagsTil) - : undefined, + dateFrom: defaultParams.dagsFra, + dateTo: defaultParams.dagsTil, department: [defaultParams.deild], involvedParty: [defaultParams.stofnun], page: defaultParams.sida, diff --git a/apps/web/screens/OfficialJournalOfIceland/hooks/useAdverts.ts b/apps/web/screens/OfficialJournalOfIceland/hooks/useAdverts.ts index 0d4c3092886b..235c26397441 100644 --- a/apps/web/screens/OfficialJournalOfIceland/hooks/useAdverts.ts +++ b/apps/web/screens/OfficialJournalOfIceland/hooks/useAdverts.ts @@ -20,8 +20,8 @@ export type UseAdvertsVariables = { type?: Array category?: Array involvedParty?: Array - dateFrom?: Date - dateTo?: Date + dateFrom?: string + dateTo?: string } export type UseAdvertsInput = { diff --git a/apps/web/screens/Organization/ParentSubpage.tsx b/apps/web/screens/Organization/ParentSubpage.tsx new file mode 100644 index 000000000000..3ae364be44fb --- /dev/null +++ b/apps/web/screens/Organization/ParentSubpage.tsx @@ -0,0 +1,123 @@ +import { useRouter } from 'next/router' + +import { + Box, + GridColumn, + GridContainer, + GridRow, + Stack, + TableOfContents, + Text, +} from '@island.is/island-ui/core' +import { OrganizationWrapper } from '@island.is/web/components' +import { Query } from '@island.is/web/graphql/schema' +import { useLinkResolver, useNamespace } from '@island.is/web/hooks' +import useContentfulId from '@island.is/web/hooks/useContentfulId' +import { useI18n } from '@island.is/web/i18n' +import { withMainLayout } from '@island.is/web/layouts/main' +import type { Screen, ScreenContext } from '@island.is/web/types' + +import { + getProps, + StandaloneParentSubpageProps, +} from './Standalone/ParentSubpage' +import { getSubpageNavList, SubPageContent } from './SubPage' + +type OrganizationParentSubpageScreenContext = ScreenContext & { + organizationPage?: Query['getOrganizationPage'] +} + +export type OrganizationParentSubpageProps = StandaloneParentSubpageProps + +const OrganizationParentSubpage: Screen< + OrganizationParentSubpageProps, + OrganizationParentSubpageScreenContext +> = ({ + organizationPage, + parentSubpage, + selectedHeadingId, + subpage, + tableOfContentHeadings, + namespace, +}) => { + const router = useRouter() + const { activeLocale } = useI18n() + const { linkResolver } = useLinkResolver() + const n = useNamespace(namespace) + useContentfulId(organizationPage.id, parentSubpage.id, subpage.id) + + return ( + + + + + + + {parentSubpage.childLinks.length > 1 && ( + + + {parentSubpage.title} + + { + const href = tableOfContentHeadings.find( + (heading) => heading.headingId === headingId, + )?.href + if (href) { + router.push(href) + } + }} + tableOfContentsTitle={ + namespace?.['OrganizationTableOfContentsTitle'] ?? + activeLocale === 'is' + ? 'Efnisyfirlit' + : 'Table of contents' + } + selectedHeadingId={selectedHeadingId} + /> + + )} + + + + + 1 ? 'h2' : 'h1' + } + /> + + + ) +} + +OrganizationParentSubpage.getProps = getProps + +export default withMainLayout(OrganizationParentSubpage) diff --git a/apps/web/screens/Organization/Standalone/ParentSubpage.tsx b/apps/web/screens/Organization/Standalone/ParentSubpage.tsx index 9f30ee2920a4..7191f959e12a 100644 --- a/apps/web/screens/Organization/Standalone/ParentSubpage.tsx +++ b/apps/web/screens/Organization/Standalone/ParentSubpage.tsx @@ -138,7 +138,7 @@ const StandaloneParentSubpage: Screen< ) } -StandaloneParentSubpage.getProps = async ({ +export const getProps: typeof StandaloneParentSubpage['getProps'] = async ({ apolloClient, locale, query, @@ -262,4 +262,6 @@ StandaloneParentSubpage.getProps = async ({ } } +StandaloneParentSubpage.getProps = getProps + export default StandaloneParentSubpage diff --git a/apps/web/screens/Organization/SubPage.tsx b/apps/web/screens/Organization/SubPage.tsx index 6d81780073b2..dd2850892088 100644 --- a/apps/web/screens/Organization/SubPage.tsx +++ b/apps/web/screens/Organization/SubPage.tsx @@ -1,4 +1,4 @@ -import { useRouter } from 'next/router' +import { NextRouter, useRouter } from 'next/router' import { ParsedUrlQuery } from 'querystring' import { SliceType } from '@island.is/island-ui/contentful' @@ -27,6 +27,7 @@ import { import { SLICE_SPACING } from '@island.is/web/constants' import { ContentLanguage, + OrganizationPage, Query, QueryGetNamespaceArgs, QueryGetOrganizationPageArgs, @@ -214,6 +215,27 @@ export const SubPageContent = ({ ) } +export const getSubpageNavList = ( + organizationPage: OrganizationPage | null | undefined, + router: NextRouter, +): NavigationItem[] => { + const pathname = new URL(router.asPath, 'https://island.is').pathname + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore make web strict + return organizationPage?.menuLinks.map(({ primaryLink, childrenLinks }) => ({ + title: primaryLink?.text, + href: primaryLink?.url, + active: + primaryLink?.url === pathname || + childrenLinks.some((link) => link.url === pathname), + items: childrenLinks.map(({ text, url }) => ({ + title: text, + href: url, + active: url === pathname, + })), + })) +} + type SubPageScreenContext = ScreenContext & { organizationPage?: Query['getOrganizationPage'] } @@ -239,24 +261,6 @@ const SubPage: Screen = ({ useContentfulId(...contentfulIds) - const pathname = new URL(router.asPath, 'https://island.is').pathname - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore make web strict - const navList: NavigationItem[] = organizationPage?.menuLinks.map( - ({ primaryLink, childrenLinks }) => ({ - title: primaryLink?.text, - href: primaryLink?.url, - active: - primaryLink?.url === pathname || - childrenLinks.some((link) => link.url === pathname), - items: childrenLinks.map(({ text, url }) => ({ - title: text, - href: url, - active: url === pathname, - })), - }), - ) - return ( = ({ } navigationData={{ title: n('navigationTitle', 'Efnisyfirlit'), - items: navList, + items: getSubpageNavList(organizationPage, router), }} > {customContent ? ( diff --git a/charts/identity-server/values.dev.yaml b/charts/identity-server/values.dev.yaml index 5ab8aa121f50..a5d5ce51e239 100644 --- a/charts/identity-server/values.dev.yaml +++ b/charts/identity-server/values.dev.yaml @@ -9,6 +9,7 @@ auth-admin-web: enabled: true env: BASE_URL: 'https://identity-server.dev01.devland.is/admin' + CODE_OWNER: 'aranja' IDENTITYSERVER_DOMAIN: 'identity-server.dev01.devland.is' LOG_LEVEL: 'info' NEXTAUTH_URL: 'https://identity-server.dev01.devland.is/admin/api/auth' @@ -128,6 +129,7 @@ identity-server: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: @@ -217,6 +219,7 @@ namespaces: services-auth-admin-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' @@ -314,6 +317,7 @@ services-auth-admin-api: services-auth-delegation-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' @@ -410,6 +414,7 @@ services-auth-delegation-api: services-auth-ids-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' DB_EXTENSIONS: 'uuid-ossp' @@ -453,6 +458,7 @@ services-auth-ids-api: grantNamespaces: - 'nginx-ingress-external' - 'user-notification' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: @@ -561,6 +567,7 @@ services-auth-ids-api-cleanup: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: @@ -758,6 +765,7 @@ services-auth-personal-representative-public: services-auth-public-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/identity-server/values.prod.yaml b/charts/identity-server/values.prod.yaml index 7521a7863cfd..2f51a29e6326 100644 --- a/charts/identity-server/values.prod.yaml +++ b/charts/identity-server/values.prod.yaml @@ -9,6 +9,7 @@ auth-admin-web: enabled: true env: BASE_URL: 'https://innskra.island.is/admin' + CODE_OWNER: 'aranja' IDENTITYSERVER_DOMAIN: 'innskra.island.is' LOG_LEVEL: 'info' NEXTAUTH_URL: 'https://innskra.island.is/admin/api/auth' @@ -126,6 +127,7 @@ identity-server: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: @@ -214,6 +216,7 @@ namespaces: services-auth-admin-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.dnugi2.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-ids.internal' @@ -311,6 +314,7 @@ services-auth-admin-api: services-auth-delegation-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.dnugi2.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-ids.internal' @@ -407,6 +411,7 @@ services-auth-delegation-api: services-auth-ids-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.dnugi2.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' DB_EXTENSIONS: 'uuid-ossp' @@ -450,6 +455,7 @@ services-auth-ids-api: grantNamespaces: - 'nginx-ingress-external' - 'user-notification' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: @@ -558,6 +564,7 @@ services-auth-ids-api-cleanup: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: @@ -755,6 +762,7 @@ services-auth-personal-representative-public: services-auth-public-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.dnugi2.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-ids.internal' diff --git a/charts/identity-server/values.staging.yaml b/charts/identity-server/values.staging.yaml index 5c982fb923f9..00cbc00e4a90 100644 --- a/charts/identity-server/values.staging.yaml +++ b/charts/identity-server/values.staging.yaml @@ -9,6 +9,7 @@ auth-admin-web: enabled: true env: BASE_URL: 'https://identity-server.staging01.devland.is/admin' + CODE_OWNER: 'aranja' IDENTITYSERVER_DOMAIN: 'identity-server.staging01.devland.is' LOG_LEVEL: 'info' NEXTAUTH_URL: 'https://identity-server.staging01.devland.is/admin/api/auth' @@ -128,6 +129,7 @@ identity-server: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: @@ -217,6 +219,7 @@ namespaces: services-auth-admin-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' @@ -314,6 +317,7 @@ services-auth-admin-api: services-auth-delegation-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' @@ -410,6 +414,7 @@ services-auth-delegation-api: services-auth-ids-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' DB_EXTENSIONS: 'uuid-ossp' @@ -453,6 +458,7 @@ services-auth-ids-api: grantNamespaces: - 'nginx-ingress-external' - 'user-notification' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: @@ -561,6 +567,7 @@ services-auth-ids-api-cleanup: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: @@ -758,6 +765,7 @@ services-auth-personal-representative-public: services-auth-public-api: enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/islandis/values.dev.yaml b/charts/islandis/values.dev.yaml index 47abcaf93395..0dd1634ad8ad 100644 --- a/charts/islandis/values.dev.yaml +++ b/charts/islandis/values.dev.yaml @@ -586,6 +586,7 @@ application-system-api: APPLICATION_ATTACHMENT_BUCKET: 'island-is-dev-storage-application-system' AUTH_PUBLIC_API_URL: 'https://identity-server.dev01.devland.is/api' CLIENT_LOCATION_ORIGIN: 'https://beta.dev01.devland.is/umsoknir' + CODE_OWNER: 'norda-applications' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' CONTENTFUL_HOST: 'preview.contentful.com' @@ -837,6 +838,7 @@ application-system-api-worker: env: APPLICATION_ATTACHMENT_BUCKET: 'island-is-dev-storage-application-system' CLIENT_LOCATION_ORIGIN: 'https://beta.dev01.devland.is/umsoknir' + CODE_OWNER: 'norda-applications' DB_HOST: 'postgres-applications.internal' DB_NAME: 'application_system_api' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' @@ -850,6 +852,7 @@ application-system-api-worker: NODE_OPTIONS: '--max-old-space-size=691 -r dd-trace/init' REDIS_URL_NODE_01: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: '' + USER_NOTIFICATION_API_URL: 'http://web-user-notification.user-notification.svc.cluster.local' XROAD_BASE_PATH: 'http://securityserver.dev01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.dev01.devland.is/r1/IS-DEV' XROAD_CHARGE_FJS_V2_PATH: 'IS-DEV/GOV/10021/FJS-Public/chargeFJS_v2' @@ -999,6 +1002,7 @@ consultation-portal: API_URL: 'http://web-api.islandis.svc.cluster.local' BACKEND_DL_URL: 'https://samradapi-test.devland.is/api/Documents/' BASEPATH: '/consultation-portal' + CODE_OWNER: 'Advania' ENVIRONMENT: 'dev' IDENTITY_SERVER_ISSUER_DOMAIN: 'identity-server.dev01.devland.is' LOG_LEVEL: 'info' @@ -1297,6 +1301,7 @@ endorsement-system-api: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_endorsements_api' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' @@ -1687,6 +1692,7 @@ island-ui-storybook: license-api: enabled: true env: + CODE_OWNER: 'hugsmidjan' HUNTING_LICENSE_PASS_TEMPLATE_ID: '1da72d52-a93a-4d0f-8463-1933a2bd210b' IDENTITY_SERVER_ISSUER_URL: 'https://identity-server.dev01.devland.is' LICENSE_SERVICE_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' @@ -1873,6 +1879,7 @@ portals-admin: regulations-admin-backend: enabled: true env: + CODE_OWNER: 'hugsmidjan' DB_HOST: 'postgres-applications.internal' DB_NAME: 'regulations_admin_backend' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' @@ -1969,6 +1976,7 @@ search-indexer-service: env: AIR_DISCOUNT_SCHEME_FRONTEND_HOSTNAME: 'loftbru.dev01.devland.is' APPLICATION_URL: 'http://search-indexer-service' + CODE_OWNER: 'stefna' CONTENTFUL_ENTRY_FETCH_CHUNK_SIZE: '40' CONTENTFUL_ENVIRONMENT: 'master' CONTENTFUL_HOST: 'preview.contentful.com' @@ -2170,6 +2178,7 @@ service-portal-api: env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'service_portal_api' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' @@ -2306,6 +2315,7 @@ services-bff-portals-admin: BFF_NAME: 'stjornbord' BFF_PAR_SUPPORT_ENABLED: 'true' BFF_PROXY_API_ENDPOINT: 'http://web-api.islandis.svc.cluster.local/api/graphql' + CODE_OWNER: 'core' IDENTITY_SERVER_CLIENT_ID: '@admin.island.is/bff-stjornbord' IDENTITY_SERVER_CLIENT_SCOPES: '["@admin.island.is/delegations","@admin.island.is/ads","@admin.island.is/regulations","@admin.island.is/regulations:manage","@admin.island.is/icelandic-names-registry","@admin.island.is/application-system:admin","@admin.island.is/application-system:institution","@admin.island.is/document-provider","@admin.island.is/auth","@admin.island.is/auth:admin","@admin.island.is/petitions","@admin.island.is/service-desk","@admin.island.is/ads:explicit","@admin.island.is/signature-collection:manage","@admin.island.is/signature-collection:process","@admin.island.is/form-system","@admin.island.is/form-system:admin","@admin.island.is/delegation-system","@admin.island.is/delegation-system:admin"]' IDENTITY_SERVER_ISSUER_URL: 'https://identity-server.dev01.devland.is' @@ -2544,6 +2554,7 @@ services-documents: services-sessions: enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' @@ -2616,6 +2627,7 @@ services-sessions-cleanup: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' @@ -2677,6 +2689,7 @@ services-sessions-worker: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_EXTENSIONS: 'uuid-ossp' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' @@ -2771,6 +2784,7 @@ services-university-gateway: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' @@ -2900,6 +2914,7 @@ services-university-gateway-worker: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' @@ -3149,6 +3164,7 @@ user-notification: env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' @@ -3253,6 +3269,7 @@ user-notification-cleanup-worker: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'user_notification' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' @@ -3348,6 +3365,7 @@ user-notification-worker: env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' CONTENTFUL_HOST: 'preview.contentful.com' @@ -3461,6 +3479,7 @@ web: enabled: true env: API_URL: 'http://web-api' + CODE_OWNER: 'stefna' DISABLE_API_CATALOGUE: 'false' DISABLE_ORGANIZATION_CHATBOT: 'false' DISABLE_SYSLUMENN_PAGE: 'false' diff --git a/charts/islandis/values.prod.yaml b/charts/islandis/values.prod.yaml index cfe7870b0fc5..04619e6f6b0a 100644 --- a/charts/islandis/values.prod.yaml +++ b/charts/islandis/values.prod.yaml @@ -574,6 +574,7 @@ application-system-api: APPLICATION_ATTACHMENT_BUCKET: 'island-is-prod-storage-application-system' AUTH_PUBLIC_API_URL: 'https://innskra.island.is/api' CLIENT_LOCATION_ORIGIN: 'https://island.is/umsoknir' + CODE_OWNER: 'norda-applications' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.whakos.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' CONTENTFUL_HOST: 'cdn.contentful.com' @@ -825,6 +826,7 @@ application-system-api-worker: env: APPLICATION_ATTACHMENT_BUCKET: 'island-is-prod-storage-application-system' CLIENT_LOCATION_ORIGIN: 'https://island.is/umsoknir' + CODE_OWNER: 'norda-applications' DB_HOST: 'postgres-applications.internal' DB_NAME: 'application_system_api' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -838,6 +840,7 @@ application-system-api-worker: NODE_OPTIONS: '--max-old-space-size=691 -r dd-trace/init' REDIS_URL_NODE_01: '["clustercfg.general-redis-cluster-group.whakos.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: 'driving-license-use-v1-endpoint-for-v2-comms' + USER_NOTIFICATION_API_URL: 'http://web-user-notification.user-notification.svc.cluster.local' XROAD_BASE_PATH: 'http://securityserver.island.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.island.is/r1/IS' XROAD_CHARGE_FJS_V2_PATH: 'IS/GOV/5402697509/FJS-Public/chargeFJS_v2' @@ -990,6 +993,7 @@ consultation-portal: API_URL: 'http://web-api.islandis.svc.cluster.local' BACKEND_DL_URL: 'https://samradapi.island.is/api/Documents/' BASEPATH: '/consultation-portal' + CODE_OWNER: 'Advania' ENVIRONMENT: 'prod' IDENTITY_SERVER_ISSUER_DOMAIN: 'innskra.island.is' LOG_LEVEL: 'info' @@ -1290,6 +1294,7 @@ endorsement-system-api: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_endorsements_api' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -1553,6 +1558,7 @@ island-ui-storybook: license-api: enabled: true env: + CODE_OWNER: 'hugsmidjan' HUNTING_LICENSE_PASS_TEMPLATE_ID: 'd4ecf781-3764-4063-a4e1-9c3e17cebfba' IDENTITY_SERVER_ISSUER_URL: 'https://innskra.island.is' LICENSE_SERVICE_REDIS_NODES: '["clustercfg.general-redis-cluster-group.whakos.euw1.cache.amazonaws.com:6379"]' @@ -1740,6 +1746,7 @@ portals-admin: regulations-admin-backend: enabled: true env: + CODE_OWNER: 'hugsmidjan' DB_HOST: 'postgres-applications.internal' DB_NAME: 'regulations_admin_backend' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -1836,6 +1843,7 @@ search-indexer-service: env: AIR_DISCOUNT_SCHEME_FRONTEND_HOSTNAME: 'loftbru.island.is' APPLICATION_URL: 'http://search-indexer-service' + CODE_OWNER: 'stefna' CONTENTFUL_ENTRY_FETCH_CHUNK_SIZE: '40' CONTENTFUL_ENVIRONMENT: 'master' CONTENTFUL_HOST: 'cdn.contentful.com' @@ -2039,6 +2047,7 @@ service-portal-api: env: AUTH_DELEGATION_API_URL: 'https://auth-delegation-api.internal.innskra.island.is' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'service_portal_api' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -2175,6 +2184,7 @@ services-bff-portals-admin: BFF_NAME: 'stjornbord' BFF_PAR_SUPPORT_ENABLED: 'true' BFF_PROXY_API_ENDPOINT: 'http://web-api.islandis.svc.cluster.local/api/graphql' + CODE_OWNER: 'core' IDENTITY_SERVER_CLIENT_ID: '@admin.island.is/bff-stjornbord' IDENTITY_SERVER_CLIENT_SCOPES: '["@admin.island.is/delegations","@admin.island.is/ads","@admin.island.is/regulations","@admin.island.is/regulations:manage","@admin.island.is/icelandic-names-registry","@admin.island.is/application-system:admin","@admin.island.is/application-system:institution","@admin.island.is/document-provider","@admin.island.is/auth","@admin.island.is/auth:admin","@admin.island.is/petitions","@admin.island.is/service-desk","@admin.island.is/ads:explicit","@admin.island.is/signature-collection:manage","@admin.island.is/signature-collection:process","@admin.island.is/form-system","@admin.island.is/form-system:admin","@admin.island.is/delegation-system","@admin.island.is/delegation-system:admin"]' IDENTITY_SERVER_ISSUER_URL: 'https://innskra.island.is' @@ -2417,6 +2427,7 @@ services-documents: services-sessions: enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -2489,6 +2500,7 @@ services-sessions-cleanup: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -2550,6 +2562,7 @@ services-sessions-worker: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_EXTENSIONS: 'uuid-ossp' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' @@ -2644,6 +2657,7 @@ services-university-gateway: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -2773,6 +2787,7 @@ services-university-gateway-worker: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -3028,6 +3043,7 @@ user-notification: env: AUTH_DELEGATION_API_URL: 'https://auth-delegation-api.internal.innskra.island.is' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.whakos.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' @@ -3132,6 +3148,7 @@ user-notification-cleanup-worker: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'user_notification' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -3227,6 +3244,7 @@ user-notification-worker: env: AUTH_DELEGATION_API_URL: 'https://auth-delegation-api.internal.innskra.island.is' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.whakos.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' CONTENTFUL_HOST: 'cdn.contentful.com' @@ -3340,6 +3358,7 @@ web: enabled: true env: API_URL: 'http://web-api' + CODE_OWNER: 'stefna' DISABLE_API_CATALOGUE: 'false' DISABLE_ORGANIZATION_CHATBOT: 'false' DISABLE_SYSLUMENN_PAGE: 'false' diff --git a/charts/islandis/values.staging.yaml b/charts/islandis/values.staging.yaml index bb265c51b251..a2192f932e41 100644 --- a/charts/islandis/values.staging.yaml +++ b/charts/islandis/values.staging.yaml @@ -583,6 +583,7 @@ application-system-api: APPLICATION_ATTACHMENT_BUCKET: 'island-is-staging-storage-application-system' AUTH_PUBLIC_API_URL: 'https://identity-server.staging01.devland.is/api' CLIENT_LOCATION_ORIGIN: 'https://beta.staging01.devland.is/umsoknir' + CODE_OWNER: 'norda-applications' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' CONTENTFUL_HOST: 'cdn.contentful.com' @@ -834,6 +835,7 @@ application-system-api-worker: env: APPLICATION_ATTACHMENT_BUCKET: 'island-is-staging-storage-application-system' CLIENT_LOCATION_ORIGIN: 'https://beta.staging01.devland.is/umsoknir' + CODE_OWNER: 'norda-applications' DB_HOST: 'postgres-applications.internal' DB_NAME: 'application_system_api' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -847,6 +849,7 @@ application-system-api-worker: NODE_OPTIONS: '--max-old-space-size=691 -r dd-trace/init' REDIS_URL_NODE_01: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: '' + USER_NOTIFICATION_API_URL: 'http://web-user-notification.user-notification.svc.cluster.local' XROAD_BASE_PATH: 'http://securityserver.staging01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.staging01.devland.is/r1/IS-TEST' XROAD_CHARGE_FJS_V2_PATH: 'IS-TEST/GOV/10021/FJS-Public/chargeFJS_v2' @@ -996,6 +999,7 @@ consultation-portal: API_URL: 'http://web-api.islandis.svc.cluster.local' BACKEND_DL_URL: 'https://samradapi-test.devland.is/api/Documents/' BASEPATH: '/consultation-portal' + CODE_OWNER: 'Advania' ENVIRONMENT: 'staging' IDENTITY_SERVER_ISSUER_DOMAIN: 'identity-server.staging01.devland.is' LOG_LEVEL: 'info' @@ -1166,6 +1170,7 @@ endorsement-system-api: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_endorsements_api' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -1429,6 +1434,7 @@ island-ui-storybook: license-api: enabled: true env: + CODE_OWNER: 'hugsmidjan' HUNTING_LICENSE_PASS_TEMPLATE_ID: '1da72d52-a93a-4d0f-8463-1933a2bd210b' IDENTITY_SERVER_ISSUER_URL: 'https://identity-server.staging01.devland.is' LICENSE_SERVICE_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' @@ -1611,6 +1617,7 @@ portals-admin: regulations-admin-backend: enabled: true env: + CODE_OWNER: 'hugsmidjan' DB_HOST: 'postgres-applications.internal' DB_NAME: 'regulations_admin_backend' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -1707,6 +1714,7 @@ search-indexer-service: env: AIR_DISCOUNT_SCHEME_FRONTEND_HOSTNAME: 'loftbru.staging01.devland.is' APPLICATION_URL: 'http://search-indexer-service' + CODE_OWNER: 'stefna' CONTENTFUL_ENTRY_FETCH_CHUNK_SIZE: '40' CONTENTFUL_ENVIRONMENT: 'master' CONTENTFUL_HOST: 'cdn.contentful.com' @@ -1908,6 +1916,7 @@ service-portal-api: env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'service_portal_api' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -2044,6 +2053,7 @@ services-bff-portals-admin: BFF_NAME: 'stjornbord' BFF_PAR_SUPPORT_ENABLED: 'true' BFF_PROXY_API_ENDPOINT: 'http://web-api.islandis.svc.cluster.local/api/graphql' + CODE_OWNER: 'core' IDENTITY_SERVER_CLIENT_ID: '@admin.island.is/bff-stjornbord' IDENTITY_SERVER_CLIENT_SCOPES: '["@admin.island.is/delegations","@admin.island.is/ads","@admin.island.is/regulations","@admin.island.is/regulations:manage","@admin.island.is/icelandic-names-registry","@admin.island.is/application-system:admin","@admin.island.is/application-system:institution","@admin.island.is/document-provider","@admin.island.is/auth","@admin.island.is/auth:admin","@admin.island.is/petitions","@admin.island.is/service-desk","@admin.island.is/ads:explicit","@admin.island.is/signature-collection:manage","@admin.island.is/signature-collection:process","@admin.island.is/form-system","@admin.island.is/form-system:admin","@admin.island.is/delegation-system","@admin.island.is/delegation-system:admin"]' IDENTITY_SERVER_ISSUER_URL: 'https://identity-server.staging01.devland.is' @@ -2282,6 +2292,7 @@ services-documents: services-sessions: enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -2354,6 +2365,7 @@ services-sessions-cleanup: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -2415,6 +2427,7 @@ services-sessions-worker: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_EXTENSIONS: 'uuid-ossp' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' @@ -2509,6 +2522,7 @@ services-university-gateway: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -2638,6 +2652,7 @@ services-university-gateway-worker: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -2887,6 +2902,7 @@ user-notification: env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' @@ -2991,6 +3007,7 @@ user-notification-cleanup-worker: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'user_notification' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -3086,6 +3103,7 @@ user-notification-worker: env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' CONTENTFUL_HOST: 'cdn.contentful.com' @@ -3200,6 +3218,7 @@ web: enabled: true env: API_URL: 'http://web-api' + CODE_OWNER: 'stefna' DISABLE_API_CATALOGUE: 'false' DISABLE_ORGANIZATION_CHATBOT: 'false' DISABLE_SYSLUMENN_PAGE: 'false' diff --git a/charts/services/application-system-api-worker/values.dev.yaml b/charts/services/application-system-api-worker/values.dev.yaml index ff4bd2d0ebb0..91699959fa25 100644 --- a/charts/services/application-system-api-worker/values.dev.yaml +++ b/charts/services/application-system-api-worker/values.dev.yaml @@ -27,6 +27,7 @@ enabled: true env: APPLICATION_ATTACHMENT_BUCKET: 'island-is-dev-storage-application-system' CLIENT_LOCATION_ORIGIN: 'https://beta.dev01.devland.is/umsoknir' + CODE_OWNER: 'norda-applications' DB_HOST: 'postgres-applications.internal' DB_NAME: 'application_system_api' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' @@ -40,6 +41,7 @@ env: NODE_OPTIONS: '--max-old-space-size=691 -r dd-trace/init' REDIS_URL_NODE_01: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: '' + USER_NOTIFICATION_API_URL: 'http://web-user-notification.user-notification.svc.cluster.local' XROAD_BASE_PATH: 'http://securityserver.dev01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.dev01.devland.is/r1/IS-DEV' XROAD_CHARGE_FJS_V2_PATH: 'IS-DEV/GOV/10021/FJS-Public/chargeFJS_v2' diff --git a/charts/services/application-system-api-worker/values.prod.yaml b/charts/services/application-system-api-worker/values.prod.yaml index c03336214cd1..e484a5d20bb8 100644 --- a/charts/services/application-system-api-worker/values.prod.yaml +++ b/charts/services/application-system-api-worker/values.prod.yaml @@ -27,6 +27,7 @@ enabled: true env: APPLICATION_ATTACHMENT_BUCKET: 'island-is-prod-storage-application-system' CLIENT_LOCATION_ORIGIN: 'https://island.is/umsoknir' + CODE_OWNER: 'norda-applications' DB_HOST: 'postgres-applications.internal' DB_NAME: 'application_system_api' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -40,6 +41,7 @@ env: NODE_OPTIONS: '--max-old-space-size=691 -r dd-trace/init' REDIS_URL_NODE_01: '["clustercfg.general-redis-cluster-group.whakos.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: 'driving-license-use-v1-endpoint-for-v2-comms' + USER_NOTIFICATION_API_URL: 'http://web-user-notification.user-notification.svc.cluster.local' XROAD_BASE_PATH: 'http://securityserver.island.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.island.is/r1/IS' XROAD_CHARGE_FJS_V2_PATH: 'IS/GOV/5402697509/FJS-Public/chargeFJS_v2' diff --git a/charts/services/application-system-api-worker/values.staging.yaml b/charts/services/application-system-api-worker/values.staging.yaml index c45d550e4db3..a654300a66ef 100644 --- a/charts/services/application-system-api-worker/values.staging.yaml +++ b/charts/services/application-system-api-worker/values.staging.yaml @@ -27,6 +27,7 @@ enabled: true env: APPLICATION_ATTACHMENT_BUCKET: 'island-is-staging-storage-application-system' CLIENT_LOCATION_ORIGIN: 'https://beta.staging01.devland.is/umsoknir' + CODE_OWNER: 'norda-applications' DB_HOST: 'postgres-applications.internal' DB_NAME: 'application_system_api' DB_REPLICAS_HOST: 'postgres-applications.internal' @@ -40,6 +41,7 @@ env: NODE_OPTIONS: '--max-old-space-size=691 -r dd-trace/init' REDIS_URL_NODE_01: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: '' + USER_NOTIFICATION_API_URL: 'http://web-user-notification.user-notification.svc.cluster.local' XROAD_BASE_PATH: 'http://securityserver.staging01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.staging01.devland.is/r1/IS-TEST' XROAD_CHARGE_FJS_V2_PATH: 'IS-TEST/GOV/10021/FJS-Public/chargeFJS_v2' diff --git a/charts/services/application-system-api/values.dev.yaml b/charts/services/application-system-api/values.dev.yaml index 9cabf0c60fd2..4ebec0038f8a 100644 --- a/charts/services/application-system-api/values.dev.yaml +++ b/charts/services/application-system-api/values.dev.yaml @@ -26,6 +26,7 @@ env: APPLICATION_ATTACHMENT_BUCKET: 'island-is-dev-storage-application-system' AUTH_PUBLIC_API_URL: 'https://identity-server.dev01.devland.is/api' CLIENT_LOCATION_ORIGIN: 'https://beta.dev01.devland.is/umsoknir' + CODE_OWNER: 'norda-applications' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' CONTENTFUL_HOST: 'preview.contentful.com' diff --git a/charts/services/application-system-api/values.prod.yaml b/charts/services/application-system-api/values.prod.yaml index bb8e6388c85d..e31f1971a9bc 100644 --- a/charts/services/application-system-api/values.prod.yaml +++ b/charts/services/application-system-api/values.prod.yaml @@ -26,6 +26,7 @@ env: APPLICATION_ATTACHMENT_BUCKET: 'island-is-prod-storage-application-system' AUTH_PUBLIC_API_URL: 'https://innskra.island.is/api' CLIENT_LOCATION_ORIGIN: 'https://island.is/umsoknir' + CODE_OWNER: 'norda-applications' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.whakos.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' CONTENTFUL_HOST: 'cdn.contentful.com' diff --git a/charts/services/application-system-api/values.staging.yaml b/charts/services/application-system-api/values.staging.yaml index 4be6d8efdc8e..c47d9cd07c30 100644 --- a/charts/services/application-system-api/values.staging.yaml +++ b/charts/services/application-system-api/values.staging.yaml @@ -26,6 +26,7 @@ env: APPLICATION_ATTACHMENT_BUCKET: 'island-is-staging-storage-application-system' AUTH_PUBLIC_API_URL: 'https://identity-server.staging01.devland.is/api' CLIENT_LOCATION_ORIGIN: 'https://beta.staging01.devland.is/umsoknir' + CODE_OWNER: 'norda-applications' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' CONTENTFUL_HOST: 'cdn.contentful.com' diff --git a/charts/services/auth-admin-web/values.dev.yaml b/charts/services/auth-admin-web/values.dev.yaml index 5c3eb4b36803..990c8a57b7ae 100644 --- a/charts/services/auth-admin-web/values.dev.yaml +++ b/charts/services/auth-admin-web/values.dev.yaml @@ -20,6 +20,7 @@ name: 'auth-admin-web' enabled: true env: BASE_URL: 'https://identity-server.dev01.devland.is/admin' + CODE_OWNER: 'aranja' IDENTITYSERVER_DOMAIN: 'identity-server.dev01.devland.is' LOG_LEVEL: 'info' NEXTAUTH_URL: 'https://identity-server.dev01.devland.is/admin/api/auth' diff --git a/charts/services/auth-admin-web/values.prod.yaml b/charts/services/auth-admin-web/values.prod.yaml index 556bdfda6dc3..7adf118589d6 100644 --- a/charts/services/auth-admin-web/values.prod.yaml +++ b/charts/services/auth-admin-web/values.prod.yaml @@ -20,6 +20,7 @@ name: 'auth-admin-web' enabled: true env: BASE_URL: 'https://innskra.island.is/admin' + CODE_OWNER: 'aranja' IDENTITYSERVER_DOMAIN: 'innskra.island.is' LOG_LEVEL: 'info' NEXTAUTH_URL: 'https://innskra.island.is/admin/api/auth' diff --git a/charts/services/auth-admin-web/values.staging.yaml b/charts/services/auth-admin-web/values.staging.yaml index 203226a74c77..846c0af6c998 100644 --- a/charts/services/auth-admin-web/values.staging.yaml +++ b/charts/services/auth-admin-web/values.staging.yaml @@ -20,6 +20,7 @@ name: 'auth-admin-web' enabled: true env: BASE_URL: 'https://identity-server.staging01.devland.is/admin' + CODE_OWNER: 'aranja' IDENTITYSERVER_DOMAIN: 'identity-server.staging01.devland.is' LOG_LEVEL: 'info' NEXTAUTH_URL: 'https://identity-server.staging01.devland.is/admin/api/auth' diff --git a/charts/services/consultation-portal/values.dev.yaml b/charts/services/consultation-portal/values.dev.yaml index 4a88058fbef2..3e06661dab79 100644 --- a/charts/services/consultation-portal/values.dev.yaml +++ b/charts/services/consultation-portal/values.dev.yaml @@ -22,6 +22,7 @@ env: API_URL: 'http://web-api.islandis.svc.cluster.local' BACKEND_DL_URL: 'https://samradapi-test.devland.is/api/Documents/' BASEPATH: '/consultation-portal' + CODE_OWNER: 'Advania' ENVIRONMENT: 'dev' IDENTITY_SERVER_ISSUER_DOMAIN: 'identity-server.dev01.devland.is' LOG_LEVEL: 'info' diff --git a/charts/services/consultation-portal/values.prod.yaml b/charts/services/consultation-portal/values.prod.yaml index 1079e249d7ea..018ba338011c 100644 --- a/charts/services/consultation-portal/values.prod.yaml +++ b/charts/services/consultation-portal/values.prod.yaml @@ -22,6 +22,7 @@ env: API_URL: 'http://web-api.islandis.svc.cluster.local' BACKEND_DL_URL: 'https://samradapi.island.is/api/Documents/' BASEPATH: '/consultation-portal' + CODE_OWNER: 'Advania' ENVIRONMENT: 'prod' IDENTITY_SERVER_ISSUER_DOMAIN: 'innskra.island.is' LOG_LEVEL: 'info' diff --git a/charts/services/consultation-portal/values.staging.yaml b/charts/services/consultation-portal/values.staging.yaml index ab669a620d94..e3547fb54d2e 100644 --- a/charts/services/consultation-portal/values.staging.yaml +++ b/charts/services/consultation-portal/values.staging.yaml @@ -22,6 +22,7 @@ env: API_URL: 'http://web-api.islandis.svc.cluster.local' BACKEND_DL_URL: 'https://samradapi-test.devland.is/api/Documents/' BASEPATH: '/consultation-portal' + CODE_OWNER: 'Advania' ENVIRONMENT: 'staging' IDENTITY_SERVER_ISSUER_DOMAIN: 'identity-server.staging01.devland.is' LOG_LEVEL: 'info' diff --git a/charts/services/endorsement-system-api/values.dev.yaml b/charts/services/endorsement-system-api/values.dev.yaml index df8da5be9bc2..b9bff23c05fe 100644 --- a/charts/services/endorsement-system-api/values.dev.yaml +++ b/charts/services/endorsement-system-api/values.dev.yaml @@ -25,6 +25,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_endorsements_api' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' diff --git a/charts/services/endorsement-system-api/values.prod.yaml b/charts/services/endorsement-system-api/values.prod.yaml index da5c42fcc716..3bc849455a0c 100644 --- a/charts/services/endorsement-system-api/values.prod.yaml +++ b/charts/services/endorsement-system-api/values.prod.yaml @@ -25,6 +25,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_endorsements_api' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/endorsement-system-api/values.staging.yaml b/charts/services/endorsement-system-api/values.staging.yaml index f4b5b1cc659f..4cc0f489f38b 100644 --- a/charts/services/endorsement-system-api/values.staging.yaml +++ b/charts/services/endorsement-system-api/values.staging.yaml @@ -25,6 +25,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_endorsements_api' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/identity-server/values.dev.yaml b/charts/services/identity-server/values.dev.yaml index ea8cd4ed5200..50d9763ee45a 100644 --- a/charts/services/identity-server/values.dev.yaml +++ b/charts/services/identity-server/values.dev.yaml @@ -59,6 +59,7 @@ grantNamespaces: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: diff --git a/charts/services/identity-server/values.prod.yaml b/charts/services/identity-server/values.prod.yaml index d086237e7757..7daf65fea874 100644 --- a/charts/services/identity-server/values.prod.yaml +++ b/charts/services/identity-server/values.prod.yaml @@ -59,6 +59,7 @@ grantNamespaces: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: diff --git a/charts/services/identity-server/values.staging.yaml b/charts/services/identity-server/values.staging.yaml index aa4536101391..ebe78fbb22a2 100644 --- a/charts/services/identity-server/values.staging.yaml +++ b/charts/services/identity-server/values.staging.yaml @@ -59,6 +59,7 @@ grantNamespaces: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: diff --git a/charts/services/license-api/values.dev.yaml b/charts/services/license-api/values.dev.yaml index 525b0341c608..a4d52b20c15b 100644 --- a/charts/services/license-api/values.dev.yaml +++ b/charts/services/license-api/values.dev.yaml @@ -19,6 +19,7 @@ global: name: 'license-api' enabled: true env: + CODE_OWNER: 'hugsmidjan' HUNTING_LICENSE_PASS_TEMPLATE_ID: '1da72d52-a93a-4d0f-8463-1933a2bd210b' IDENTITY_SERVER_ISSUER_URL: 'https://identity-server.dev01.devland.is' LICENSE_SERVICE_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' diff --git a/charts/services/license-api/values.prod.yaml b/charts/services/license-api/values.prod.yaml index 2f003504d184..aee4de56111c 100644 --- a/charts/services/license-api/values.prod.yaml +++ b/charts/services/license-api/values.prod.yaml @@ -19,6 +19,7 @@ global: name: 'license-api' enabled: true env: + CODE_OWNER: 'hugsmidjan' HUNTING_LICENSE_PASS_TEMPLATE_ID: 'd4ecf781-3764-4063-a4e1-9c3e17cebfba' IDENTITY_SERVER_ISSUER_URL: 'https://innskra.island.is' LICENSE_SERVICE_REDIS_NODES: '["clustercfg.general-redis-cluster-group.whakos.euw1.cache.amazonaws.com:6379"]' diff --git a/charts/services/license-api/values.staging.yaml b/charts/services/license-api/values.staging.yaml index d85276d6d82b..6e7db7b9814d 100644 --- a/charts/services/license-api/values.staging.yaml +++ b/charts/services/license-api/values.staging.yaml @@ -19,6 +19,7 @@ global: name: 'license-api' enabled: true env: + CODE_OWNER: 'hugsmidjan' HUNTING_LICENSE_PASS_TEMPLATE_ID: '1da72d52-a93a-4d0f-8463-1933a2bd210b' IDENTITY_SERVER_ISSUER_URL: 'https://identity-server.staging01.devland.is' LICENSE_SERVICE_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' diff --git a/charts/services/regulations-admin-backend/values.dev.yaml b/charts/services/regulations-admin-backend/values.dev.yaml index d0fb60d1bca9..922313bd4eb7 100644 --- a/charts/services/regulations-admin-backend/values.dev.yaml +++ b/charts/services/regulations-admin-backend/values.dev.yaml @@ -19,6 +19,7 @@ global: name: 'regulations-admin-backend' enabled: true env: + CODE_OWNER: 'hugsmidjan' DB_HOST: 'postgres-applications.internal' DB_NAME: 'regulations_admin_backend' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' diff --git a/charts/services/regulations-admin-backend/values.prod.yaml b/charts/services/regulations-admin-backend/values.prod.yaml index 1a1eb25213a8..27e0e5a3d396 100644 --- a/charts/services/regulations-admin-backend/values.prod.yaml +++ b/charts/services/regulations-admin-backend/values.prod.yaml @@ -19,6 +19,7 @@ global: name: 'regulations-admin-backend' enabled: true env: + CODE_OWNER: 'hugsmidjan' DB_HOST: 'postgres-applications.internal' DB_NAME: 'regulations_admin_backend' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/regulations-admin-backend/values.staging.yaml b/charts/services/regulations-admin-backend/values.staging.yaml index af8acd3ba0f4..8ad0927caa8f 100644 --- a/charts/services/regulations-admin-backend/values.staging.yaml +++ b/charts/services/regulations-admin-backend/values.staging.yaml @@ -19,6 +19,7 @@ global: name: 'regulations-admin-backend' enabled: true env: + CODE_OWNER: 'hugsmidjan' DB_HOST: 'postgres-applications.internal' DB_NAME: 'regulations_admin_backend' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/search-indexer-service/values.dev.yaml b/charts/services/search-indexer-service/values.dev.yaml index 6ecb31864bdf..bf1e8184f67c 100644 --- a/charts/services/search-indexer-service/values.dev.yaml +++ b/charts/services/search-indexer-service/values.dev.yaml @@ -21,6 +21,7 @@ enabled: true env: AIR_DISCOUNT_SCHEME_FRONTEND_HOSTNAME: 'loftbru.dev01.devland.is' APPLICATION_URL: 'http://search-indexer-service' + CODE_OWNER: 'stefna' CONTENTFUL_ENTRY_FETCH_CHUNK_SIZE: '40' CONTENTFUL_ENVIRONMENT: 'master' CONTENTFUL_HOST: 'preview.contentful.com' diff --git a/charts/services/search-indexer-service/values.prod.yaml b/charts/services/search-indexer-service/values.prod.yaml index 1b1d10f0dfb4..a203c282692e 100644 --- a/charts/services/search-indexer-service/values.prod.yaml +++ b/charts/services/search-indexer-service/values.prod.yaml @@ -21,6 +21,7 @@ enabled: true env: AIR_DISCOUNT_SCHEME_FRONTEND_HOSTNAME: 'loftbru.island.is' APPLICATION_URL: 'http://search-indexer-service' + CODE_OWNER: 'stefna' CONTENTFUL_ENTRY_FETCH_CHUNK_SIZE: '40' CONTENTFUL_ENVIRONMENT: 'master' CONTENTFUL_HOST: 'cdn.contentful.com' diff --git a/charts/services/search-indexer-service/values.staging.yaml b/charts/services/search-indexer-service/values.staging.yaml index e7f407cf667b..39cebc125692 100644 --- a/charts/services/search-indexer-service/values.staging.yaml +++ b/charts/services/search-indexer-service/values.staging.yaml @@ -21,6 +21,7 @@ enabled: true env: AIR_DISCOUNT_SCHEME_FRONTEND_HOSTNAME: 'loftbru.staging01.devland.is' APPLICATION_URL: 'http://search-indexer-service' + CODE_OWNER: 'stefna' CONTENTFUL_ENTRY_FETCH_CHUNK_SIZE: '40' CONTENTFUL_ENVIRONMENT: 'master' CONTENTFUL_HOST: 'cdn.contentful.com' diff --git a/charts/services/service-portal-api/values.dev.yaml b/charts/services/service-portal-api/values.dev.yaml index dd764effdcae..080007a74e71 100644 --- a/charts/services/service-portal-api/values.dev.yaml +++ b/charts/services/service-portal-api/values.dev.yaml @@ -21,6 +21,7 @@ enabled: true env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'service_portal_api' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' diff --git a/charts/services/service-portal-api/values.prod.yaml b/charts/services/service-portal-api/values.prod.yaml index 1ec1f781fb66..bf5acdd7d719 100644 --- a/charts/services/service-portal-api/values.prod.yaml +++ b/charts/services/service-portal-api/values.prod.yaml @@ -21,6 +21,7 @@ enabled: true env: AUTH_DELEGATION_API_URL: 'https://auth-delegation-api.internal.innskra.island.is' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'service_portal_api' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/service-portal-api/values.staging.yaml b/charts/services/service-portal-api/values.staging.yaml index a6c91b5bc4df..f766121d5b5b 100644 --- a/charts/services/service-portal-api/values.staging.yaml +++ b/charts/services/service-portal-api/values.staging.yaml @@ -21,6 +21,7 @@ enabled: true env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'service_portal_api' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-auth-admin-api/values.dev.yaml b/charts/services/services-auth-admin-api/values.dev.yaml index a792c06696f7..9817987951f4 100644 --- a/charts/services/services-auth-admin-api/values.dev.yaml +++ b/charts/services/services-auth-admin-api/values.dev.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-admin-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-auth-admin-api/values.prod.yaml b/charts/services/services-auth-admin-api/values.prod.yaml index cc6563a905ed..8a2c4b6576fb 100644 --- a/charts/services/services-auth-admin-api/values.prod.yaml +++ b/charts/services/services-auth-admin-api/values.prod.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-admin-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.dnugi2.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-ids.internal' diff --git a/charts/services/services-auth-admin-api/values.staging.yaml b/charts/services/services-auth-admin-api/values.staging.yaml index e67c4abfceac..b1c22013d7d8 100644 --- a/charts/services/services-auth-admin-api/values.staging.yaml +++ b/charts/services/services-auth-admin-api/values.staging.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-admin-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-auth-delegation-api/values.dev.yaml b/charts/services/services-auth-delegation-api/values.dev.yaml index da1613b5c029..3fd4ca9ae4fb 100644 --- a/charts/services/services-auth-delegation-api/values.dev.yaml +++ b/charts/services/services-auth-delegation-api/values.dev.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-delegation-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-auth-delegation-api/values.prod.yaml b/charts/services/services-auth-delegation-api/values.prod.yaml index 51a922f7506b..2e99e7c39b37 100644 --- a/charts/services/services-auth-delegation-api/values.prod.yaml +++ b/charts/services/services-auth-delegation-api/values.prod.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-delegation-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.dnugi2.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-ids.internal' diff --git a/charts/services/services-auth-delegation-api/values.staging.yaml b/charts/services/services-auth-delegation-api/values.staging.yaml index 7b1fbb8f3802..6547bd4e464b 100644 --- a/charts/services/services-auth-delegation-api/values.staging.yaml +++ b/charts/services/services-auth-delegation-api/values.staging.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-delegation-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-auth-ids-api-cleanup/values.dev.yaml b/charts/services/services-auth-ids-api-cleanup/values.dev.yaml index 5a4276deb188..7922277ce890 100644 --- a/charts/services/services-auth-ids-api-cleanup/values.dev.yaml +++ b/charts/services/services-auth-ids-api-cleanup/values.dev.yaml @@ -36,6 +36,7 @@ grantNamespaces: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: diff --git a/charts/services/services-auth-ids-api-cleanup/values.prod.yaml b/charts/services/services-auth-ids-api-cleanup/values.prod.yaml index 88701a214d23..0dbd5e238973 100644 --- a/charts/services/services-auth-ids-api-cleanup/values.prod.yaml +++ b/charts/services/services-auth-ids-api-cleanup/values.prod.yaml @@ -36,6 +36,7 @@ grantNamespaces: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: diff --git a/charts/services/services-auth-ids-api-cleanup/values.staging.yaml b/charts/services/services-auth-ids-api-cleanup/values.staging.yaml index 62add51ed018..9bc51cf470c9 100644 --- a/charts/services/services-auth-ids-api-cleanup/values.staging.yaml +++ b/charts/services/services-auth-ids-api-cleanup/values.staging.yaml @@ -36,6 +36,7 @@ grantNamespaces: - 'nginx-ingress-external' - 'user-notification' - 'portals-admin' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: diff --git a/charts/services/services-auth-ids-api/values.dev.yaml b/charts/services/services-auth-ids-api/values.dev.yaml index 3f01536db5bf..e1461ecdd4a9 100644 --- a/charts/services/services-auth-ids-api/values.dev.yaml +++ b/charts/services/services-auth-ids-api/values.dev.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-ids-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' DB_EXTENSIONS: 'uuid-ossp' @@ -62,6 +63,7 @@ env: grantNamespaces: - 'nginx-ingress-external' - 'user-notification' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: diff --git a/charts/services/services-auth-ids-api/values.prod.yaml b/charts/services/services-auth-ids-api/values.prod.yaml index 8452923e6595..48b414b22bb9 100644 --- a/charts/services/services-auth-ids-api/values.prod.yaml +++ b/charts/services/services-auth-ids-api/values.prod.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-ids-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.dnugi2.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' DB_EXTENSIONS: 'uuid-ossp' @@ -62,6 +63,7 @@ env: grantNamespaces: - 'nginx-ingress-external' - 'user-notification' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: diff --git a/charts/services/services-auth-ids-api/values.staging.yaml b/charts/services/services-auth-ids-api/values.staging.yaml index 0ed369b6862e..5b620fa22960 100644 --- a/charts/services/services-auth-ids-api/values.staging.yaml +++ b/charts/services/services-auth-ids-api/values.staging.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-ids-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' DB_EXTENSIONS: 'uuid-ossp' @@ -62,6 +63,7 @@ env: grantNamespaces: - 'nginx-ingress-external' - 'user-notification' + - 'datadog' grantNamespacesEnabled: true healthCheck: liveness: diff --git a/charts/services/services-auth-public-api/values.dev.yaml b/charts/services/services-auth-public-api/values.dev.yaml index 9b4cc091ee46..3f7a25390e7f 100644 --- a/charts/services/services-auth-public-api/values.dev.yaml +++ b/charts/services/services-auth-public-api/values.dev.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-public-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-auth-public-api/values.prod.yaml b/charts/services/services-auth-public-api/values.prod.yaml index 13e897e62429..5cfbd4ffd7ac 100644 --- a/charts/services/services-auth-public-api/values.prod.yaml +++ b/charts/services/services-auth-public-api/values.prod.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-public-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.dnugi2.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-ids.internal' diff --git a/charts/services/services-auth-public-api/values.staging.yaml b/charts/services/services-auth-public-api/values.staging.yaml index ba19f2a7a3bf..31a9e6949e53 100644 --- a/charts/services/services-auth-public-api/values.staging.yaml +++ b/charts/services/services-auth-public-api/values.staging.yaml @@ -19,6 +19,7 @@ global: name: 'services-auth-public-api' enabled: true env: + CODE_OWNER: 'aranja' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-bff-portals-admin/values.dev.yaml b/charts/services/services-bff-portals-admin/values.dev.yaml index 53970ff7cecc..ad41b2594e0f 100644 --- a/charts/services/services-bff-portals-admin/values.dev.yaml +++ b/charts/services/services-bff-portals-admin/values.dev.yaml @@ -31,6 +31,7 @@ env: BFF_NAME: 'stjornbord' BFF_PAR_SUPPORT_ENABLED: 'true' BFF_PROXY_API_ENDPOINT: 'http://web-api.islandis.svc.cluster.local/api/graphql' + CODE_OWNER: 'core' IDENTITY_SERVER_CLIENT_ID: '@admin.island.is/bff-stjornbord' IDENTITY_SERVER_CLIENT_SCOPES: '["@admin.island.is/delegations","@admin.island.is/ads","@admin.island.is/regulations","@admin.island.is/regulations:manage","@admin.island.is/icelandic-names-registry","@admin.island.is/application-system:admin","@admin.island.is/application-system:institution","@admin.island.is/document-provider","@admin.island.is/auth","@admin.island.is/auth:admin","@admin.island.is/petitions","@admin.island.is/service-desk","@admin.island.is/ads:explicit","@admin.island.is/signature-collection:manage","@admin.island.is/signature-collection:process","@admin.island.is/form-system","@admin.island.is/form-system:admin","@admin.island.is/delegation-system","@admin.island.is/delegation-system:admin"]' IDENTITY_SERVER_ISSUER_URL: 'https://identity-server.dev01.devland.is' diff --git a/charts/services/services-bff-portals-admin/values.prod.yaml b/charts/services/services-bff-portals-admin/values.prod.yaml index a5d9d89deff0..85573c54b3f8 100644 --- a/charts/services/services-bff-portals-admin/values.prod.yaml +++ b/charts/services/services-bff-portals-admin/values.prod.yaml @@ -31,6 +31,7 @@ env: BFF_NAME: 'stjornbord' BFF_PAR_SUPPORT_ENABLED: 'true' BFF_PROXY_API_ENDPOINT: 'http://web-api.islandis.svc.cluster.local/api/graphql' + CODE_OWNER: 'core' IDENTITY_SERVER_CLIENT_ID: '@admin.island.is/bff-stjornbord' IDENTITY_SERVER_CLIENT_SCOPES: '["@admin.island.is/delegations","@admin.island.is/ads","@admin.island.is/regulations","@admin.island.is/regulations:manage","@admin.island.is/icelandic-names-registry","@admin.island.is/application-system:admin","@admin.island.is/application-system:institution","@admin.island.is/document-provider","@admin.island.is/auth","@admin.island.is/auth:admin","@admin.island.is/petitions","@admin.island.is/service-desk","@admin.island.is/ads:explicit","@admin.island.is/signature-collection:manage","@admin.island.is/signature-collection:process","@admin.island.is/form-system","@admin.island.is/form-system:admin","@admin.island.is/delegation-system","@admin.island.is/delegation-system:admin"]' IDENTITY_SERVER_ISSUER_URL: 'https://innskra.island.is' diff --git a/charts/services/services-bff-portals-admin/values.staging.yaml b/charts/services/services-bff-portals-admin/values.staging.yaml index 9fe68c571325..5244c4b5efc5 100644 --- a/charts/services/services-bff-portals-admin/values.staging.yaml +++ b/charts/services/services-bff-portals-admin/values.staging.yaml @@ -31,6 +31,7 @@ env: BFF_NAME: 'stjornbord' BFF_PAR_SUPPORT_ENABLED: 'true' BFF_PROXY_API_ENDPOINT: 'http://web-api.islandis.svc.cluster.local/api/graphql' + CODE_OWNER: 'core' IDENTITY_SERVER_CLIENT_ID: '@admin.island.is/bff-stjornbord' IDENTITY_SERVER_CLIENT_SCOPES: '["@admin.island.is/delegations","@admin.island.is/ads","@admin.island.is/regulations","@admin.island.is/regulations:manage","@admin.island.is/icelandic-names-registry","@admin.island.is/application-system:admin","@admin.island.is/application-system:institution","@admin.island.is/document-provider","@admin.island.is/auth","@admin.island.is/auth:admin","@admin.island.is/petitions","@admin.island.is/service-desk","@admin.island.is/ads:explicit","@admin.island.is/signature-collection:manage","@admin.island.is/signature-collection:process","@admin.island.is/form-system","@admin.island.is/form-system:admin","@admin.island.is/delegation-system","@admin.island.is/delegation-system:admin"]' IDENTITY_SERVER_ISSUER_URL: 'https://identity-server.staging01.devland.is' diff --git a/charts/services/services-sessions-cleanup/values.dev.yaml b/charts/services/services-sessions-cleanup/values.dev.yaml index fa54d71f9cc6..ba81b8b2caf5 100644 --- a/charts/services/services-sessions-cleanup/values.dev.yaml +++ b/charts/services/services-sessions-cleanup/values.dev.yaml @@ -24,6 +24,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' diff --git a/charts/services/services-sessions-cleanup/values.prod.yaml b/charts/services/services-sessions-cleanup/values.prod.yaml index 2a436d368e82..0559731d6fa4 100644 --- a/charts/services/services-sessions-cleanup/values.prod.yaml +++ b/charts/services/services-sessions-cleanup/values.prod.yaml @@ -24,6 +24,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-sessions-cleanup/values.staging.yaml b/charts/services/services-sessions-cleanup/values.staging.yaml index df9aff0539a1..6ef083a64637 100644 --- a/charts/services/services-sessions-cleanup/values.staging.yaml +++ b/charts/services/services-sessions-cleanup/values.staging.yaml @@ -24,6 +24,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-sessions-worker/values.dev.yaml b/charts/services/services-sessions-worker/values.dev.yaml index b0fcf628cfaf..af020d71fd0a 100644 --- a/charts/services/services-sessions-worker/values.dev.yaml +++ b/charts/services/services-sessions-worker/values.dev.yaml @@ -24,6 +24,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_EXTENSIONS: 'uuid-ossp' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' diff --git a/charts/services/services-sessions-worker/values.prod.yaml b/charts/services/services-sessions-worker/values.prod.yaml index 430ba3aa97cb..45cf39972d81 100644 --- a/charts/services/services-sessions-worker/values.prod.yaml +++ b/charts/services/services-sessions-worker/values.prod.yaml @@ -24,6 +24,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_EXTENSIONS: 'uuid-ossp' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' diff --git a/charts/services/services-sessions-worker/values.staging.yaml b/charts/services/services-sessions-worker/values.staging.yaml index 3721d83be564..8637fe36f53a 100644 --- a/charts/services/services-sessions-worker/values.staging.yaml +++ b/charts/services/services-sessions-worker/values.staging.yaml @@ -24,6 +24,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'aranja' DB_EXTENSIONS: 'uuid-ossp' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' diff --git a/charts/services/services-sessions/values.dev.yaml b/charts/services/services-sessions/values.dev.yaml index dfb22e69db69..27b3d9e87183 100644 --- a/charts/services/services-sessions/values.dev.yaml +++ b/charts/services/services-sessions/values.dev.yaml @@ -19,6 +19,7 @@ global: name: 'services-sessions' enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' diff --git a/charts/services/services-sessions/values.prod.yaml b/charts/services/services-sessions/values.prod.yaml index ac6d8167fb4e..67724998dc78 100644 --- a/charts/services/services-sessions/values.prod.yaml +++ b/charts/services/services-sessions/values.prod.yaml @@ -19,6 +19,7 @@ global: name: 'services-sessions' enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-sessions/values.staging.yaml b/charts/services/services-sessions/values.staging.yaml index 5de452280635..adc3e526bdc1 100644 --- a/charts/services/services-sessions/values.staging.yaml +++ b/charts/services/services-sessions/values.staging.yaml @@ -19,6 +19,7 @@ global: name: 'services-sessions' enabled: true env: + CODE_OWNER: 'aranja' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_sessions' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-university-gateway-worker/values.dev.yaml b/charts/services/services-university-gateway-worker/values.dev.yaml index b219e85aa530..88c17a202e28 100644 --- a/charts/services/services-university-gateway-worker/values.dev.yaml +++ b/charts/services/services-university-gateway-worker/values.dev.yaml @@ -25,6 +25,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' diff --git a/charts/services/services-university-gateway-worker/values.prod.yaml b/charts/services/services-university-gateway-worker/values.prod.yaml index 2827d3e190cc..b03e71fb49b7 100644 --- a/charts/services/services-university-gateway-worker/values.prod.yaml +++ b/charts/services/services-university-gateway-worker/values.prod.yaml @@ -25,6 +25,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-university-gateway-worker/values.staging.yaml b/charts/services/services-university-gateway-worker/values.staging.yaml index e64ffd48d011..21d70f22db7c 100644 --- a/charts/services/services-university-gateway-worker/values.staging.yaml +++ b/charts/services/services-university-gateway-worker/values.staging.yaml @@ -25,6 +25,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-university-gateway/values.dev.yaml b/charts/services/services-university-gateway/values.dev.yaml index 3916a66ca657..61eecf2b6b95 100644 --- a/charts/services/services-university-gateway/values.dev.yaml +++ b/charts/services/services-university-gateway/values.dev.yaml @@ -23,6 +23,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' diff --git a/charts/services/services-university-gateway/values.prod.yaml b/charts/services/services-university-gateway/values.prod.yaml index 59ce966458e7..b7dd867587ec 100644 --- a/charts/services/services-university-gateway/values.prod.yaml +++ b/charts/services/services-university-gateway/values.prod.yaml @@ -23,6 +23,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/services-university-gateway/values.staging.yaml b/charts/services/services-university-gateway/values.staging.yaml index 688dd16644f0..975b21ae2937 100644 --- a/charts/services/services-university-gateway/values.staging.yaml +++ b/charts/services/services-university-gateway/values.staging.yaml @@ -23,6 +23,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'origo' DB_HOST: 'postgres-applications.internal' DB_NAME: 'services_university_gateway' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/user-notification-cleanup-worker/values.dev.yaml b/charts/services/user-notification-cleanup-worker/values.dev.yaml index 9e558ec19c87..f59fcf817b4b 100644 --- a/charts/services/user-notification-cleanup-worker/values.dev.yaml +++ b/charts/services/user-notification-cleanup-worker/values.dev.yaml @@ -25,6 +25,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'user_notification' DB_REPLICAS_HOST: 'postgres-applications-reader.internal' diff --git a/charts/services/user-notification-cleanup-worker/values.prod.yaml b/charts/services/user-notification-cleanup-worker/values.prod.yaml index 43ba4e7bf3c7..1bcd7b43b581 100644 --- a/charts/services/user-notification-cleanup-worker/values.prod.yaml +++ b/charts/services/user-notification-cleanup-worker/values.prod.yaml @@ -25,6 +25,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'user_notification' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/user-notification-cleanup-worker/values.staging.yaml b/charts/services/user-notification-cleanup-worker/values.staging.yaml index 946da9daabf0..47f68bae0eff 100644 --- a/charts/services/user-notification-cleanup-worker/values.staging.yaml +++ b/charts/services/user-notification-cleanup-worker/values.staging.yaml @@ -25,6 +25,7 @@ command: - 'node' enabled: true env: + CODE_OWNER: 'juni' DB_HOST: 'postgres-applications.internal' DB_NAME: 'user_notification' DB_REPLICAS_HOST: 'postgres-applications.internal' diff --git a/charts/services/user-notification-worker/values.dev.yaml b/charts/services/user-notification-worker/values.dev.yaml index 9b31936004f0..2a0ec43d43f3 100644 --- a/charts/services/user-notification-worker/values.dev.yaml +++ b/charts/services/user-notification-worker/values.dev.yaml @@ -27,6 +27,7 @@ enabled: true env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' CONTENTFUL_HOST: 'preview.contentful.com' diff --git a/charts/services/user-notification-worker/values.prod.yaml b/charts/services/user-notification-worker/values.prod.yaml index 505fd0fc1186..6ab822a0aa50 100644 --- a/charts/services/user-notification-worker/values.prod.yaml +++ b/charts/services/user-notification-worker/values.prod.yaml @@ -27,6 +27,7 @@ enabled: true env: AUTH_DELEGATION_API_URL: 'https://auth-delegation-api.internal.innskra.island.is' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.whakos.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' CONTENTFUL_HOST: 'cdn.contentful.com' diff --git a/charts/services/user-notification-worker/values.staging.yaml b/charts/services/user-notification-worker/values.staging.yaml index 20c9089348c6..4d38939c4667 100644 --- a/charts/services/user-notification-worker/values.staging.yaml +++ b/charts/services/user-notification-worker/values.staging.yaml @@ -27,6 +27,7 @@ enabled: true env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' CONTENTFUL_HOST: 'cdn.contentful.com' diff --git a/charts/services/user-notification/values.dev.yaml b/charts/services/user-notification/values.dev.yaml index 31c759a45806..2a4c2df02f1d 100644 --- a/charts/services/user-notification/values.dev.yaml +++ b/charts/services/user-notification/values.dev.yaml @@ -26,6 +26,7 @@ enabled: true env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-DEV/GOV/10006/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/services/user-notification/values.prod.yaml b/charts/services/user-notification/values.prod.yaml index b6d09de39826..00cf09f12ae3 100644 --- a/charts/services/user-notification/values.prod.yaml +++ b/charts/services/user-notification/values.prod.yaml @@ -26,6 +26,7 @@ enabled: true env: AUTH_DELEGATION_API_URL: 'https://auth-delegation-api.internal.innskra.island.is' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.whakos.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/services/user-notification/values.staging.yaml b/charts/services/user-notification/values.staging.yaml index e6dc9bc23264..9a9c1025e3bc 100644 --- a/charts/services/user-notification/values.staging.yaml +++ b/charts/services/user-notification/values.staging.yaml @@ -26,6 +26,7 @@ enabled: true env: AUTH_DELEGATION_API_URL: 'http://web-services-auth-delegation-api.identity-server-delegation.svc.cluster.local' AUTH_DELEGATION_MACHINE_CLIENT_SCOPE: '["@island.is/auth/delegations/index:system"]' + CODE_OWNER: 'juni' COMPANY_REGISTRY_REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' COMPANY_REGISTRY_XROAD_PROVIDER_ID: 'IS-TEST/GOV/5402696029/Skatturinn/ft-v1' DB_HOST: 'postgres-applications.internal' diff --git a/charts/services/web/values.dev.yaml b/charts/services/web/values.dev.yaml index a6455c2f5c34..13be4e498ef9 100644 --- a/charts/services/web/values.dev.yaml +++ b/charts/services/web/values.dev.yaml @@ -20,6 +20,7 @@ name: 'web' enabled: true env: API_URL: 'http://web-api' + CODE_OWNER: 'stefna' DISABLE_API_CATALOGUE: 'false' DISABLE_ORGANIZATION_CHATBOT: 'false' DISABLE_SYSLUMENN_PAGE: 'false' diff --git a/charts/services/web/values.prod.yaml b/charts/services/web/values.prod.yaml index a5c86c5c9db1..d86fe89b392b 100644 --- a/charts/services/web/values.prod.yaml +++ b/charts/services/web/values.prod.yaml @@ -20,6 +20,7 @@ name: 'web' enabled: true env: API_URL: 'http://web-api' + CODE_OWNER: 'stefna' DISABLE_API_CATALOGUE: 'false' DISABLE_ORGANIZATION_CHATBOT: 'false' DISABLE_SYSLUMENN_PAGE: 'false' diff --git a/charts/services/web/values.staging.yaml b/charts/services/web/values.staging.yaml index 4a0b40a3fa19..8e672b5827be 100644 --- a/charts/services/web/values.staging.yaml +++ b/charts/services/web/values.staging.yaml @@ -21,6 +21,7 @@ basicAuth: '/k8s/web/basic_auth' enabled: true env: API_URL: 'http://web-api' + CODE_OWNER: 'stefna' DISABLE_API_CATALOGUE: 'false' DISABLE_ORGANIZATION_CHATBOT: 'false' DISABLE_SYSLUMENN_PAGE: 'false' diff --git a/infra/src/cli/cli.ts b/infra/src/cli/cli.ts index 5b4d08560f0e..21d21dd4a6e0 100644 --- a/infra/src/cli/cli.ts +++ b/infra/src/cli/cli.ts @@ -140,5 +140,6 @@ const cli = yargs(process.argv.slice(2)) }) }, ) + .strict() .demandCommand(1) .parse() diff --git a/infra/src/dsl/dsl.ts b/infra/src/dsl/dsl.ts index 0427e7f0e29d..1a41e386bf74 100644 --- a/infra/src/dsl/dsl.ts +++ b/infra/src/dsl/dsl.ts @@ -1,4 +1,5 @@ import { merge } from 'lodash' +import { CodeOwners } from '../../../libs/shared/constants/src/lib/codeOwners' import { Context, EnvironmentVariables, @@ -194,6 +195,11 @@ export class ServiceBuilder { return this } + codeOwner(codeOwner: CodeOwners) { + this.serviceDef.env['CODE_OWNER'] = codeOwner + return this + } + /** * X-Road configuration blocks to inject to the container. Types of XroadConfig can contain environment variables and/or secrets that define how to contact an external service through X-Road. * @param ...configs - X-road configs @@ -565,3 +571,5 @@ export const service = ( } export const json = (value: unknown): string => JSON.stringify(value) + +export { CodeOwners } diff --git a/infra/src/dsl/value-files-generators/local-setup.ts b/infra/src/dsl/value-files-generators/local-setup.ts index 0ae7abcc702e..7ef9356772d2 100644 --- a/infra/src/dsl/value-files-generators/local-setup.ts +++ b/infra/src/dsl/value-files-generators/local-setup.ts @@ -96,7 +96,7 @@ export const getLocalrunValueFile = async ( `cd "${rootDir}"`, // Change directory to the root directory `. ./.env.${serviceNXName}`, // Source the environment variables for the service `echo "Preparing dev-services for ${name}"`, // Log preparation message - `if yarn nx show projects --with-target dev-services | grep -q '^${serviceNXName}$'; then yarn nx dev-services ${serviceNXName} || return $?; fi`, // Check and set up dev-services if needed + `if yarn nx show projects --with-target dev-services | grep -q '^${serviceNXName}$'; then yarn nx dev-services ${serviceNXName} || exit $?; fi`, // Check and set up dev-services if needed `echo "Starting ${name} in $PWD"`, `yarn nx serve ${serviceNXName}`, // Log start message and start the service ], diff --git a/infra/src/uber-charts/islandis.ts b/infra/src/uber-charts/islandis.ts index 705e3c1113f0..569b921bc2bf 100644 --- a/infra/src/uber-charts/islandis.ts +++ b/infra/src/uber-charts/islandis.ts @@ -85,7 +85,9 @@ const appSystemApi = appSystemApiSetup({ servicePortalApi, userNotificationService, }) -const appSystemApiWorker = appSystemApiWorkerSetup() +const appSystemApiWorker = appSystemApiWorkerSetup({ + userNotificationService, +}) const nameRegistryBackend = serviceNameRegistryBackendSetup() diff --git a/libs/api/domains/application/src/lib/application.resolver.ts b/libs/api/domains/application/src/lib/application.resolver.ts index 53f637de06cd..4efbe4233028 100644 --- a/libs/api/domains/application/src/lib/application.resolver.ts +++ b/libs/api/domains/application/src/lib/application.resolver.ts @@ -1,29 +1,32 @@ -import { Args, Query, Resolver, Mutation } from '@nestjs/graphql' import type { User } from '@island.is/auth-nest-tools' import { + CurrentUser, IdsUserGuard, ScopesGuard, - CurrentUser, } from '@island.is/auth-nest-tools' -import { UseGuards } from '@nestjs/common' +import { CodeOwners } from '@island.is/shared/constants' import type { Locale } from '@island.is/shared/types' +import { UseGuards } from '@nestjs/common' +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql' +import { CodeOwner } from '@island.is/nest/core' +import { Application, ApplicationPayment } from './application.model' import { ApplicationService } from './application.service' -import { Application, ApplicationPayment } from './application.model' -import { CreateApplicationInput } from './dto/createApplication.input' -import { UpdateApplicationInput } from './dto/updateApplication.input' -import { UpdateApplicationExternalDataInput } from './dto/updateApplicationExternalData.input' import { AddAttachmentInput } from './dto/addAttachment.input' -import { DeleteAttachmentInput } from './dto/deleteAttachment.input' -import { SubmitApplicationInput } from './dto/submitApplication.input' -import { AssignApplicationInput } from './dto/assignApplication.input' import { ApplicationApplicationInput } from './dto/applicationApplication.input' import { ApplicationApplicationsInput } from './dto/applicationApplications.input' -import { PresignedUrlResponse } from './dto/presignedUrl.response' +import { AssignApplicationInput } from './dto/assignApplication.input' import { AttachmentPresignedUrlInput } from './dto/AttachmentPresignedUrl.input' +import { CreateApplicationInput } from './dto/createApplication.input' import { DeleteApplicationInput } from './dto/deleteApplication.input' +import { DeleteAttachmentInput } from './dto/deleteAttachment.input' +import { PresignedUrlResponse } from './dto/presignedUrl.response' +import { SubmitApplicationInput } from './dto/submitApplication.input' +import { UpdateApplicationInput } from './dto/updateApplication.input' +import { UpdateApplicationExternalDataInput } from './dto/updateApplicationExternalData.input' @UseGuards(IdsUserGuard, ScopesGuard) +@CodeOwner(CodeOwners.NordaApplications) @Resolver(() => Application) export class ApplicationResolver { constructor(private applicationService: ApplicationService) {} diff --git a/libs/api/domains/documents/src/lib/dto/getDocumentListInput.ts b/libs/api/domains/documents/src/lib/dto/getDocumentListInput.ts index e0900dd2d914..0ab2fcd80590 100644 --- a/libs/api/domains/documents/src/lib/dto/getDocumentListInput.ts +++ b/libs/api/domains/documents/src/lib/dto/getDocumentListInput.ts @@ -21,7 +21,7 @@ export class GetDocumentListInput { typeId?: string @Field({ nullable: true }) - sortBy?: 'Date' | 'Category' | 'Type' | 'Subject' | 'Sender' + sortBy?: 'Date' | 'Category' | 'Type' | 'Subject' | 'Sender' | 'Publication' @Field({ nullable: true }) order?: 'Ascending' | 'Descending' diff --git a/libs/api/domains/documents/src/lib/models/v2/documents.input.ts b/libs/api/domains/documents/src/lib/models/v2/documents.input.ts index f8615073aa99..ed3eb3d52849 100644 --- a/libs/api/domains/documents/src/lib/models/v2/documents.input.ts +++ b/libs/api/domains/documents/src/lib/models/v2/documents.input.ts @@ -17,7 +17,8 @@ import { } from 'class-validator' export enum DocumentPageSort { - Date = 'Date', + Date = 'Date', // Date is document date + Publication = 'Publication', // Publication is document publication date (default) Category = 'Category', Type = 'Type', Sender = 'Sender', @@ -79,7 +80,10 @@ export class DocumentsInput { @IsBoolean() readonly opened?: boolean - @Field(() => DocumentPageSort, { nullable: true, defaultValue: 'Date' }) + @Field(() => DocumentPageSort, { + nullable: true, + defaultValue: 'Publication', + }) @IsOptional() @IsEnum(DocumentPageSort) readonly sortBy?: DocumentPageSort diff --git a/libs/api/domains/education/src/lib/graphql/inna.resolver.ts b/libs/api/domains/education/src/lib/graphql/inna.resolver.ts index 3c8479c3063b..fc1c2b3e9d27 100644 --- a/libs/api/domains/education/src/lib/graphql/inna.resolver.ts +++ b/libs/api/domains/education/src/lib/graphql/inna.resolver.ts @@ -23,8 +23,7 @@ import { DiplomaModel } from './inna/diplomas.model' @Resolver() @UseGuards(IdsUserGuard, ScopesGuard, FeatureFlagGuard) -@Scopes(ApiScope.internal) -@FeatureFlag(Features.servicePortalSecondaryEducationPages) +@Scopes(ApiScope.education) @Audit({ namespace: '@island.is/api/education-inna' }) export class InnaResolver { constructor(private innaService: InnaClientService) {} diff --git a/libs/api/domains/form-system/src/lib/forms/forms.resolver.ts b/libs/api/domains/form-system/src/lib/forms/forms.resolver.ts index 982b72da1d8f..59cc3a91105c 100644 --- a/libs/api/domains/form-system/src/lib/forms/forms.resolver.ts +++ b/libs/api/domains/form-system/src/lib/forms/forms.resolver.ts @@ -1,25 +1,28 @@ -import { Args, Mutation, Query, Resolver } from '@nestjs/graphql' -import { FormsService } from './forms.service' -import { FormResponse } from '../../models/formResponse.model' -import { - CreateFormInput, - GetFormInput, - GetFormsInput, - UpdateFormInput, - DeleteFormInput, -} from '../../dto/forms.input' import { CurrentUser, IdsUserGuard, type User, } from '@island.is/auth-nest-tools' -import { FormListResponse } from '../../models/formListResponse.model' import { Audit } from '@island.is/nest/audit' +import { CodeOwner } from '@island.is/nest/core' +import { CodeOwners } from '@island.is/shared/constants' import { UseGuards } from '@nestjs/common' +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql' +import { + CreateFormInput, + DeleteFormInput, + GetFormInput, + GetFormsInput, + UpdateFormInput, +} from '../../dto/forms.input' import { UpdateFormSettingsInput } from '../../dto/updateFormSettings.input' +import { FormListResponse } from '../../models/formListResponse.model' +import { FormResponse } from '../../models/formResponse.model' +import { FormsService } from './forms.service' @Resolver() @UseGuards(IdsUserGuard) +@CodeOwner(CodeOwners.Advania) @Audit({ namespace: '@island.is/api/form-system' }) export class FormsResolver { constructor(private readonly formsService: FormsService) {} diff --git a/libs/api/domains/form-system/src/lib/groups/groups.resolver.ts b/libs/api/domains/form-system/src/lib/groups/groups.resolver.ts index 4c31ecc691d9..62353b74c5cb 100644 --- a/libs/api/domains/form-system/src/lib/groups/groups.resolver.ts +++ b/libs/api/domains/form-system/src/lib/groups/groups.resolver.ts @@ -1,3 +1,5 @@ +import { CodeOwner } from '@island.is/nest/core' +import { CodeOwners } from '@island.is/shared/constants' import { Query, Args, Resolver, Mutation } from '@nestjs/graphql' import { CurrentUser, @@ -17,6 +19,7 @@ import { UseGuards } from '@nestjs/common' @Resolver() @UseGuards(IdsUserGuard) +@CodeOwner(CodeOwners.Advania) @Audit({ namespace: '@island.is/api/form-system' }) export class GroupsResolver { constructor(private readonly groupsService: GroupsService) {} diff --git a/libs/api/domains/form-system/src/lib/inputs/inputs.resolver.ts b/libs/api/domains/form-system/src/lib/inputs/inputs.resolver.ts index 3e6645025689..2596516c1c68 100644 --- a/libs/api/domains/form-system/src/lib/inputs/inputs.resolver.ts +++ b/libs/api/domains/form-system/src/lib/inputs/inputs.resolver.ts @@ -1,3 +1,5 @@ +import { CodeOwner } from '@island.is/nest/core' +import { CodeOwners } from '@island.is/shared/constants' import { Query, Args, Resolver, Mutation } from '@nestjs/graphql' import { CurrentUser, @@ -17,6 +19,7 @@ import { UseGuards } from '@nestjs/common' @Resolver() @UseGuards(IdsUserGuard) +@CodeOwner(CodeOwners.Advania) @Audit({ namespace: '@island.is/api/form-system' }) export class InputsResolver { constructor(private readonly inputsService: InputsService) {} diff --git a/libs/api/domains/form-system/src/lib/organizations/organizations.resolver.ts b/libs/api/domains/form-system/src/lib/organizations/organizations.resolver.ts index ded9859a34e3..ddc2a93a0f15 100644 --- a/libs/api/domains/form-system/src/lib/organizations/organizations.resolver.ts +++ b/libs/api/domains/form-system/src/lib/organizations/organizations.resolver.ts @@ -1,3 +1,5 @@ +import { CodeOwner } from '@island.is/nest/core' +import { CodeOwners } from '@island.is/shared/constants' import { Args, Mutation, Resolver } from '@nestjs/graphql' import { OrganizationsService } from './organizations.services' import { CreateOrganizationInput } from '../../dto/organization.input' @@ -12,6 +14,7 @@ import { UseGuards } from '@nestjs/common' @Resolver() @UseGuards(IdsUserGuard) +@CodeOwner(CodeOwners.Advania) @Audit({ namespace: '@island.is/api/form-system' }) export class OrganizationsResolver { constructor(private readonly organizationsService: OrganizationsService) {} diff --git a/libs/api/domains/form-system/src/lib/services/services.resolver.ts b/libs/api/domains/form-system/src/lib/services/services.resolver.ts index 1ba7e31fdf96..a1f9df7774ec 100644 --- a/libs/api/domains/form-system/src/lib/services/services.resolver.ts +++ b/libs/api/domains/form-system/src/lib/services/services.resolver.ts @@ -1,3 +1,5 @@ +import { CodeOwner } from '@island.is/nest/core' +import { CodeOwners } from '@island.is/shared/constants' import { Query, Args, Resolver } from '@nestjs/graphql' import { CurrentUser, @@ -12,6 +14,7 @@ import { UseGuards } from '@nestjs/common' @Resolver() @UseGuards(IdsUserGuard) +@CodeOwner(CodeOwners.Advania) @Audit({ namespace: '@island.is/api/form-system' }) export class FormSystemServicesResolver { constructor(private readonly formSystemServices: FormSystemService) {} diff --git a/libs/api/domains/form-system/src/lib/steps/steps.resolver.ts b/libs/api/domains/form-system/src/lib/steps/steps.resolver.ts index 88f46a9a5ec6..6fb6cfcc876e 100644 --- a/libs/api/domains/form-system/src/lib/steps/steps.resolver.ts +++ b/libs/api/domains/form-system/src/lib/steps/steps.resolver.ts @@ -1,3 +1,5 @@ +import { CodeOwner } from '@island.is/nest/core' +import { CodeOwners } from '@island.is/shared/constants' import { Query, Args, Resolver, Mutation } from '@nestjs/graphql' import { CurrentUser, @@ -17,6 +19,7 @@ import { UseGuards } from '@nestjs/common' @Resolver() @UseGuards(IdsUserGuard) +@CodeOwner(CodeOwners.Advania) @Audit({ namespace: '@island.is/api/form-system' }) export class StepsResolver { constructor(private readonly stepsService: StepsService) {} diff --git a/libs/api/domains/license-service/src/lib/resolvers/licenseCollection.resolver.ts b/libs/api/domains/license-service/src/lib/resolvers/licenseCollection.resolver.ts index 102d14857c0f..0a78ada05e3f 100644 --- a/libs/api/domains/license-service/src/lib/resolvers/licenseCollection.resolver.ts +++ b/libs/api/domains/license-service/src/lib/resolvers/licenseCollection.resolver.ts @@ -6,19 +6,25 @@ import { ScopesGuard, } from '@island.is/auth-nest-tools' import { ApiScope } from '@island.is/auth/scopes' +import { LOGGER_PROVIDER, type Logger } from '@island.is/logging' import { Audit } from '@island.is/nest/audit' +import { + CodeOwner, + ParsedUserAgent, + type UserAgent, +} from '@island.is/nest/core' +import { CodeOwners } from '@island.is/shared/constants' import type { Locale } from '@island.is/shared/types' import { Inject, UseGuards } from '@nestjs/common' import { Args, Query, Resolver } from '@nestjs/graphql' -import { GetGenericLicensesInput } from '../dto/GetGenericLicenses.input' -import { LicenseService } from '../licenseService.service' import { LicenseCollection } from '../dto/GenericLicenseCollection.dto' import { GenericUserLicense } from '../dto/GenericUserLicense.dto' -import { LOGGER_PROVIDER, type Logger } from '@island.is/logging' -import { ParsedUserAgent, type UserAgent } from '@island.is/nest/core' +import { GetGenericLicensesInput } from '../dto/GetGenericLicenses.input' +import { LicenseService } from '../licenseService.service' @UseGuards(IdsUserGuard, ScopesGuard) +@CodeOwner(CodeOwners.Hugsmidjan) @Scopes(ApiScope.internal, ApiScope.licenses) @Resolver(() => LicenseCollection) @Audit({ namespace: '@island.is/api/license-service' }) diff --git a/libs/api/domains/license-service/src/lib/resolvers/pkPass.resolver.ts b/libs/api/domains/license-service/src/lib/resolvers/pkPass.resolver.ts index d78ea015d5e5..13ec1766bb77 100644 --- a/libs/api/domains/license-service/src/lib/resolvers/pkPass.resolver.ts +++ b/libs/api/domains/license-service/src/lib/resolvers/pkPass.resolver.ts @@ -7,6 +7,8 @@ import { } from '@island.is/auth-nest-tools' import { ApiScope } from '@island.is/auth/scopes' import { Audit } from '@island.is/nest/audit' +import { CodeOwner } from '@island.is/nest/core' +import { CodeOwners } from '@island.is/shared/constants' import { UseGuards } from '@nestjs/common' import { Args, Mutation, Resolver } from '@nestjs/graphql' @@ -20,6 +22,7 @@ import { GenericPkPassVerification } from '../dto/GenericPkPassVerification.dto' import { VerifyPkPassInput } from '../dto/VerifyPkPass.input' @UseGuards(IdsUserGuard, ScopesGuard) +@CodeOwner(CodeOwners.Hugsmidjan) @Resolver(() => GenericPkPass) @Audit({ namespace: '@island.is/api/license-service' }) export class PkPassResolver { diff --git a/libs/api/domains/license-service/src/lib/resolvers/provider.resolver.ts b/libs/api/domains/license-service/src/lib/resolvers/provider.resolver.ts index f9d28c55d613..bcb1657a69e2 100644 --- a/libs/api/domains/license-service/src/lib/resolvers/provider.resolver.ts +++ b/libs/api/domains/license-service/src/lib/resolvers/provider.resolver.ts @@ -1,6 +1,8 @@ import { IdsUserGuard, Scopes, ScopesGuard } from '@island.is/auth-nest-tools' import { ApiScope } from '@island.is/auth/scopes' import { Audit } from '@island.is/nest/audit' +import { CodeOwner } from '@island.is/nest/core' +import { CodeOwners } from '@island.is/shared/constants' import { UseGuards } from '@nestjs/common' import { Parent, ResolveField, Resolver } from '@nestjs/graphql' import { GenericLicenseProvider } from '../dto/GenericLicenseProvider.dto' @@ -13,6 +15,7 @@ import { import { Loader } from '@island.is/nest/dataloader' @UseGuards(IdsUserGuard, ScopesGuard) +@CodeOwner(CodeOwners.Hugsmidjan) @Scopes(ApiScope.internal, ApiScope.licenses) @Resolver(() => GenericLicenseProvider) @Audit({ namespace: '@island.is/api/license-service' }) diff --git a/libs/api/domains/license-service/src/lib/resolvers/userLicense.resolver.ts b/libs/api/domains/license-service/src/lib/resolvers/userLicense.resolver.ts index cc42079d6065..127007366148 100644 --- a/libs/api/domains/license-service/src/lib/resolvers/userLicense.resolver.ts +++ b/libs/api/domains/license-service/src/lib/resolvers/userLicense.resolver.ts @@ -7,6 +7,8 @@ import { } from '@island.is/auth-nest-tools' import { ApiScope, LicenseApiScope } from '@island.is/auth/scopes' import { Audit } from '@island.is/nest/audit' +import { CodeOwner } from '@island.is/nest/core' +import { CodeOwners } from '@island.is/shared/constants' import type { Locale } from '@island.is/shared/types' import { ForbiddenException, UseGuards } from '@nestjs/common' import { Args, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql' @@ -19,6 +21,7 @@ import { logger } from '@island.is/logging' import { ParsedUserAgent, type UserAgent } from '@island.is/nest/core' @UseGuards(IdsUserGuard, ScopesGuard) +@CodeOwner(CodeOwners.Hugsmidjan) @Scopes(ApiScope.internal, ApiScope.licenses) @Resolver(() => GenericUserLicense) @Audit({ namespace: '@island.is/api/license-service' }) diff --git a/libs/api/domains/notifications/src/lib/notifications.model.ts b/libs/api/domains/notifications/src/lib/notifications.model.ts index 64436d89583a..2c83f4a8107c 100644 --- a/libs/api/domains/notifications/src/lib/notifications.model.ts +++ b/libs/api/domains/notifications/src/lib/notifications.model.ts @@ -89,6 +89,21 @@ export class Notification { message!: NotificationMessage } +@ObjectType() +export class AdminNotification { + @Field(() => Int) + id!: number + + @Field(() => ID) + notificationId!: string + + @Field(() => NotificationSender) + sender!: NotificationSender + + @Field(() => GraphQLISODateTime) + sent!: Date +} + @InputType() export class NotificationsInput extends PaginationInput() {} @@ -101,6 +116,11 @@ export class NotificationsResponse extends PaginatedResponse(Notification) { unseenCount?: number } +@ObjectType('AdminNotifications') +export class AdminNotificationsResponse extends PaginatedResponse( + AdminNotification, +) {} + @ObjectType() export class NotificationResponse { @Field(() => Notification) diff --git a/libs/api/domains/notifications/src/lib/notifications.module.ts b/libs/api/domains/notifications/src/lib/notifications.module.ts index 745702eb28bb..231c0d96c879 100644 --- a/libs/api/domains/notifications/src/lib/notifications.module.ts +++ b/libs/api/domains/notifications/src/lib/notifications.module.ts @@ -8,6 +8,8 @@ import { NotificationSenderResolver, } from './notificationsList.resolver' import { NotificationsService } from './notifications.service' +import { NotificationsAdminResolver } from './notificationsAdmin.resolver' +import { NotificationsAdminService } from './notificationsAdmin.service' @Module({ imports: [UserNotificationClientModule], @@ -15,7 +17,9 @@ import { NotificationsService } from './notifications.service' NotificationsResolver, NotificationsListResolver, NotificationSenderResolver, + NotificationsAdminResolver, NotificationsService, + NotificationsAdminService, ], exports: [], }) diff --git a/libs/api/domains/notifications/src/lib/notificationsAdmin.resolver.ts b/libs/api/domains/notifications/src/lib/notificationsAdmin.resolver.ts new file mode 100644 index 000000000000..9afd668e3173 --- /dev/null +++ b/libs/api/domains/notifications/src/lib/notificationsAdmin.resolver.ts @@ -0,0 +1,60 @@ +import { Args, Query, Resolver } from '@nestjs/graphql' +import { IdsUserGuard, CurrentUser } from '@island.is/auth-nest-tools' +import type { User } from '@island.is/auth-nest-tools' +import { Audit } from '@island.is/nest/audit' +import { Inject, UseGuards } from '@nestjs/common' + +import { NotificationsAdminService } from './notificationsAdmin.service' +import { + NotificationsInput, + AdminNotificationsResponse, +} from './notifications.model' +import type { Locale } from '@island.is/shared/types' +import { LOGGER_PROVIDER, type Logger } from '@island.is/logging' + +const LOG_CATEGORY = 'notification-admin-resolver' +export const AUDIT_NAMESPACE = 'notifications-admin-resolver' + +@UseGuards(IdsUserGuard) +@Resolver(() => AdminNotificationsResponse) +@Audit({ namespace: AUDIT_NAMESPACE }) +export class NotificationsAdminResolver { + constructor( + private readonly service: NotificationsAdminService, + @Inject(LOGGER_PROVIDER) private readonly logger: Logger, + ) {} + + @Query(() => AdminNotificationsResponse, { + name: 'adminNotifications', + nullable: true, + }) + @Audit() + async getNotifications( + @Args('nationalId') nationalId: string, + @Args('input', { type: () => NotificationsInput, nullable: true }) + input: NotificationsInput, + @CurrentUser() user: User, + @Args('locale', { type: () => String, nullable: true }) + locale: Locale = 'is', + ): Promise { + let notifications: AdminNotificationsResponse | null + + try { + notifications = await this.service.getNotifications( + locale, + nationalId, + user, + input, + ) + } catch (e) { + this.logger.error('failed to get admin notifications', { + locale, + category: LOG_CATEGORY, + error: e, + }) + throw e + } + + return notifications + } +} diff --git a/libs/api/domains/notifications/src/lib/notificationsAdmin.service.ts b/libs/api/domains/notifications/src/lib/notificationsAdmin.service.ts new file mode 100644 index 000000000000..76089eff1156 --- /dev/null +++ b/libs/api/domains/notifications/src/lib/notificationsAdmin.service.ts @@ -0,0 +1,52 @@ +import { Auth, AuthMiddleware, User } from '@island.is/auth-nest-tools' +import { LOGGER_PROVIDER } from '@island.is/logging' +import type { Logger } from '@island.is/logging' +import { Inject, Injectable } from '@nestjs/common' +import { NotificationsApi } from '@island.is/clients/user-notification' +import type { Locale } from '@island.is/shared/types' +import { + AdminNotificationsResponse, + NotificationsInput, +} from './notifications.model' +import { adminNotificationMapper } from '../utils/helpers' + +@Injectable() +export class NotificationsAdminService { + constructor( + @Inject(LOGGER_PROVIDER) + private logger: Logger, + private notificationsApi: NotificationsApi, + ) {} + + notificationsWAuth(auth: Auth) { + return this.notificationsApi.withMiddleware(new AuthMiddleware(auth)) + } + + async getNotifications( + locale: Locale, + nationalId: string, + user: User, + input?: NotificationsInput, + ): Promise { + const notifications = await this.notificationsWAuth( + user, + ).notificationsControllerFindMany({ + xQueryNationalId: nationalId, + locale, + limit: input?.limit, + before: input?.before, + after: input?.after, + }) + + if (!notifications.data) { + this.logger.debug('no admin notification found') + return null + } + + return { + data: notifications.data.map((item) => adminNotificationMapper(item)), + totalCount: notifications.totalCount, + pageInfo: notifications.pageInfo, + } + } +} diff --git a/libs/api/domains/notifications/src/utils/helpers.ts b/libs/api/domains/notifications/src/utils/helpers.ts index 3baac1e1b7fc..87932276f1e9 100644 --- a/libs/api/domains/notifications/src/utils/helpers.ts +++ b/libs/api/domains/notifications/src/utils/helpers.ts @@ -1,5 +1,5 @@ import { RenderedNotificationDto } from '@island.is/clients/user-notification' -import { Notification } from '../lib/notifications.model' +import { AdminNotification, Notification } from '../lib/notifications.model' const cleanString = (str?: string) => { if (!str) { @@ -40,3 +40,13 @@ export const notificationMapper = ( }, }, }) +export const adminNotificationMapper = ( + notification: RenderedNotificationDto, +): AdminNotification => ({ + id: notification.id, + notificationId: notification.messageId, + sent: notification.created, + sender: { + id: notification.senderId, + }, +}) diff --git a/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.input.ts b/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.input.ts index c00db538679f..868f78ae3130 100644 --- a/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.input.ts +++ b/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.input.ts @@ -28,10 +28,10 @@ export class AdvertsInput { @Field(() => [String], { nullable: true }) involvedParty?: string[] - @Field(() => Date, { nullable: true }) + @Field(() => String, { nullable: true }) dateFrom?: string - @Field(() => Date, { nullable: true }) + @Field(() => String, { nullable: true }) dateTo?: string } diff --git a/libs/application/core/src/lib/fieldBuilders.ts b/libs/application/core/src/lib/fieldBuilders.ts index d5390fb6bbb6..a1035cbc3b55 100644 --- a/libs/application/core/src/lib/fieldBuilders.ts +++ b/libs/application/core/src/lib/fieldBuilders.ts @@ -991,6 +991,7 @@ export const buildDisplayField = ( value, suffix, rightAlign, + halfWidthOwnline, } = data return { ...extractCommonFields(data), @@ -1006,5 +1007,6 @@ export const buildDisplayField = ( value, suffix, rightAlign, + halfWidthOwnline, } } diff --git a/libs/application/template-api-modules/src/lib/modules/templates/financial-statement-political-party/financial-statement-political-party.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/financial-statement-political-party/financial-statement-political-party.service.ts index 0d4ddd01cad9..3118c379c23e 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/financial-statement-political-party/financial-statement-political-party.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/financial-statement-political-party/financial-statement-political-party.service.ts @@ -140,11 +140,11 @@ export class FinancialStatementPoliticalPartyTemplateService extends BaseTemplat } private getOperatingYear(application: Application) { - const year = getValueViaPath( + const year = getValueViaPath( application.answers, 'conditionalAbout.operatingYear', ) - if (typeof year !== 'string') { + if (!year) { throw new Error('Operating year not found or invalid') } return year diff --git a/libs/application/template-api-modules/src/lib/modules/templates/financial-statement-political-party/mappers/mapValuesToPartyTypes.ts b/libs/application/template-api-modules/src/lib/modules/templates/financial-statement-political-party/mappers/mapValuesToPartyTypes.ts index bcd5b4a2a2b4..79aa40980f38 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/financial-statement-political-party/mappers/mapValuesToPartyTypes.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/financial-statement-political-party/mappers/mapValuesToPartyTypes.ts @@ -4,46 +4,59 @@ import { FormValue } from '@island.is/application/types' export const mapValuesToPartyTypes = (answers: FormValue) => { return { contributionsFromTheTreasury: Number( - getValueViaPath(answers, 'partyIncome.contributionsFromTheTreasury'), + getValueViaPath( + answers, + 'partyIncome.contributionsFromTheTreasury', + ), ), parliamentaryPartySupport: Number( - getValueViaPath(answers, 'partyIncome.parliamentaryPartySupport'), + getValueViaPath(answers, 'partyIncome.parliamentaryPartySupport'), ), municipalContributions: Number( - getValueViaPath(answers, 'partyIncome.municipalContributions'), + getValueViaPath(answers, 'partyIncome.municipalContributions'), ), contributionsFromLegalEntities: Number( - getValueViaPath(answers, 'partyIncome.contributionsFromLegalEntities'), + getValueViaPath( + answers, + 'partyIncome.contributionsFromLegalEntities', + ), ), contributionsFromIndividuals: Number( - getValueViaPath(answers, 'partyIncome.contributionsFromIndividuals'), + getValueViaPath( + answers, + 'partyIncome.contributionsFromIndividuals', + ), ), generalMembershipFees: Number( - getValueViaPath(answers, 'partyIncome.generalMembershipFees'), + getValueViaPath(answers, 'partyIncome.generalMembershipFees'), ), - otherIncome: Number(getValueViaPath(answers, 'partyIncome.otherIncome')), - capitalIncome: Number( - getValueViaPath(answers, 'capitalNumbers.capitalIncome'), + otherIncome: Number( + getValueViaPath(answers, 'partyIncome.otherIncome'), ), officeOperations: Number( - getValueViaPath(answers, 'partyExpense.electionOffice'), + getValueViaPath(answers, 'partyExpense.electionOffice'), ), otherOperatingExpenses: Number( - getValueViaPath(answers, 'partyExpense.otherCost'), + getValueViaPath(answers, 'partyExpense.otherCost'), + ), + capitalIncome: Number( + getValueViaPath(answers, 'capitalNumbers.capitalIncome'), ), financialExpenses: Number( - getValueViaPath(answers, 'capitalNumbers.capitalCost'), + getValueViaPath(answers, 'capitalNumbers.capitalCost'), ), fixedAssetsTotal: Number( - getValueViaPath(answers, 'asset.fixedAssetsTotal'), + getValueViaPath(answers, 'asset.fixedAssetsTotal'), + ), + currentAssets: Number( + getValueViaPath(answers, 'asset.currentAssets'), ), - currentAssets: Number(getValueViaPath(answers, 'asset.currentAssets')), longTermLiabilitiesTotal: Number( - getValueViaPath(answers, 'liability.longTerm'), + getValueViaPath(answers, 'liability.longTerm'), ), shortTermLiabilitiesTotal: Number( - getValueViaPath(answers, 'liability.shortTerm'), + getValueViaPath(answers, 'liability.shortTerm'), ), - equityTotal: Number(getValueViaPath(answers, 'equity.totalEquity')), + equityTotal: Number(getValueViaPath(answers, 'equity.totalEquity')), } } diff --git a/libs/application/templates/inao/financial-statement-political-party/src/components/AssetDebtEquityOverview.tsx b/libs/application/templates/inao/financial-statement-political-party/src/components/AssetDebtEquityOverview.tsx index 2f4c1335863a..330aa0ed82b8 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/components/AssetDebtEquityOverview.tsx +++ b/libs/application/templates/inao/financial-statement-political-party/src/components/AssetDebtEquityOverview.tsx @@ -5,6 +5,7 @@ import { formatCurrency } from '../utils/helpers' import { m } from '../lib/messages' import { FinancialStatementPoliticalParty } from '../lib/dataSchema' import { sectionColumn } from './css/overviewStyles.css' +import { getValueViaPath } from '@island.is/application/core' type Props = { answers: FinancialStatementPoliticalParty @@ -13,6 +14,32 @@ type Props = { export const AssetDebtEquityOverview = ({ answers }: Props) => { const { formatMessage } = useLocale() + const fixedAssetsTotal = getValueViaPath( + answers, + 'asset.fixedAssetsTotal', + ) + const currentAssets = getValueViaPath(answers, 'asset.currentAssets') + const assetsTotal = getValueViaPath( + answers, + 'equityAndLiabilitiesTotals.assetsTotal', + ) + const longTermLiability = getValueViaPath( + answers, + 'liability.longTerm', + ) + const shortTermLiability = getValueViaPath( + answers, + 'liability.shortTerm', + ) + const totalLiabilities = getValueViaPath( + answers, + 'equityAndLiabilitiesTotals.liabilitiesTotal', + ) + const totalEquity = getValueViaPath(answers, 'equity.totalEquity') + const equityAndLiabilitiesTotal = getValueViaPath( + answers, + 'equityAndLiabilitiesTotals.equityAndLiabilitiesTotal', + ) return ( @@ -23,15 +50,15 @@ export const AssetDebtEquityOverview = ({ answers }: Props) => { @@ -44,25 +71,25 @@ export const AssetDebtEquityOverview = ({ answers }: Props) => { diff --git a/libs/application/templates/inao/financial-statement-political-party/src/components/Total.tsx b/libs/application/templates/inao/financial-statement-political-party/src/components/Total.tsx deleted file mode 100644 index f0cd9b51798f..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/components/Total.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { useEffect } from 'react' -import { Box, Text } from '@island.is/island-ui/core' -import { InputController } from '@island.is/shared/form-fields' -import { useFormContext } from 'react-hook-form' - -type Props = { - name: string - total: number - label: string - title?: string -} - -export const Total = ({ name, total, label, title }: Props) => { - const { setValue } = useFormContext() - - useEffect(() => { - setValue(name, total.toString()) - }, [total]) - - return ( - - {title ? ( - - {title} - - ) : null} - - - - ) -} diff --git a/libs/application/templates/inao/financial-statement-political-party/src/fields/ElectionEquities/ElectionEquities.tsx b/libs/application/templates/inao/financial-statement-political-party/src/fields/ElectionEquities/ElectionEquities.tsx deleted file mode 100644 index cedb1027a555..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/fields/ElectionEquities/ElectionEquities.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import { useState, useEffect } from 'react' -import debounce from 'lodash/debounce' -import { useFormContext } from 'react-hook-form' -import { FieldBaseProps } from '@island.is/application/types' -import { - AlertBanner, - Box, - GridColumn, - GridContainer, - GridRow, - Text, -} from '@island.is/island-ui/core' -import { useLocale } from '@island.is/localization' -import { InputController } from '@island.is/shared/form-fields' -import { getErrorViaPath } from '@island.is/application/core' -import { m } from '../../lib/messages' -import { useTotals } from '../../hooks/useTotals' -import { - EQUITIESANDLIABILITIESIDS, - INPUTCHANGEINTERVAL, - VALIDATOR, -} from '../../utils/constants' -import { getTotal } from '../../utils/helpers' -import { Total } from '../../components/Total' - -export const ElectionEquities = ({ - setBeforeSubmitCallback, -}: FieldBaseProps) => { - const { formatMessage } = useLocale() - - const { - formState: { errors }, - clearErrors, - getValues, - setError, - } = useFormContext() - - const [getTotalEquity, totalEquity] = useTotals( - EQUITIESANDLIABILITIESIDS.equityPrefix, - ) - const [getTotalAssets, totalAssets] = useTotals( - EQUITIESANDLIABILITIESIDS.assetPrefix, - ) - const [getTotalLiabilities, totalLiabilities] = useTotals( - EQUITIESANDLIABILITIESIDS.liabilityPrefix, - ) - - const [equityAndDebts, setEquityAndDebts] = useState(0) - - useEffect(() => { - const total = totalEquity + totalLiabilities - setEquityAndDebts(total) - }, [totalEquity, totalLiabilities]) - - useEffect(() => { - clearErrors(VALIDATOR) - }, [totalEquity, totalLiabilities, totalAssets, clearErrors]) - - setBeforeSubmitCallback && - setBeforeSubmitCallback(async () => { - const values = getValues() - const assets = getTotal(values, 'asset') - const liabilties = getTotal(values, 'liability') - const equities = getTotal(values, 'equity') - - // assets should equal liabilties + equities - const isValid = liabilties + equities === assets - if (!isValid) { - setError(VALIDATOR, { - type: 'custom', - message: formatMessage(m.equityDebtsAssetsValidatorError), - }) - return [false, formatMessage(m.equityDebtsAssetsValidatorError)] - } - return [true, null] - }) - - return ( - - - - - {formatMessage(m.properties)} - - - { - getTotalAssets() - clearErrors(EQUITIESANDLIABILITIESIDS.fixedAssetsTotal) - }, INPUTCHANGEINTERVAL)} - backgroundColor="blue" - currency - /> - - - { - getTotalAssets() - clearErrors(EQUITIESANDLIABILITIESIDS.currentAssets) - }, INPUTCHANGEINTERVAL)} - label={formatMessage(m.currentAssets)} - backgroundColor="blue" - currency - /> - - - - - - {formatMessage(m.debtsAndEquity)} - - - { - getTotalLiabilities() - clearErrors(EQUITIESANDLIABILITIESIDS.longTerm) - }, INPUTCHANGEINTERVAL)} - error={ - errors && - getErrorViaPath(errors, EQUITIESANDLIABILITIESIDS.longTerm) - } - label={formatMessage(m.longTerm)} - backgroundColor="blue" - currency - /> - - - { - getTotalLiabilities() - clearErrors(EQUITIESANDLIABILITIESIDS.shortTerm) - }, INPUTCHANGEINTERVAL)} - error={ - errors && - getErrorViaPath(errors, EQUITIESANDLIABILITIESIDS.shortTerm) - } - label={formatMessage(m.shortTerm)} - backgroundColor="blue" - currency - /> - - - - { - getTotalEquity() - clearErrors(EQUITIESANDLIABILITIESIDS.totalEquity) - }, INPUTCHANGEINTERVAL)} - error={ - errors && - getErrorViaPath(errors, EQUITIESANDLIABILITIESIDS.totalEquity) - } - label={formatMessage(m.equity)} - backgroundColor="blue" - currency - /> - - - - - - - {errors && errors.validator ? ( - - - - ) : null} - - ) -} diff --git a/libs/application/templates/inao/financial-statement-political-party/src/fields/ElectionStatement/ElectionStatement.tsx b/libs/application/templates/inao/financial-statement-political-party/src/fields/ElectionStatement/ElectionStatement.tsx deleted file mode 100644 index 89b4df521eaa..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/fields/ElectionStatement/ElectionStatement.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { getErrorViaPath, getValueViaPath } from '@island.is/application/core' -import { AlertBanner, Box, InputError, Text } from '@island.is/island-ui/core' -import { m } from '../../lib/messages' -import { useLocale } from '@island.is/localization' -import { DefaultEvents, FieldBaseProps } from '@island.is/application/types' -import { format as formatNationalId } from 'kennitala' -import { useSubmitApplication } from '../../hooks/useSubmitApplication' -import BottomBar from '../../components/BottomBar' -import { useFormContext } from 'react-hook-form' -import { FinancialStatementPoliticalParty } from '../../lib/dataSchema' -import { ELECTIONLIMIT, GREATER } from '../../utils/constants' -import { formatNumber } from '../../utils/helpers' - -export const ElectionStatement = ({ - application, - goToScreen, - refetch, -}: FieldBaseProps) => { - const { formatMessage } = useLocale() - const { - formState: { errors }, - } = useFormContext() - const answers = application.answers as FinancialStatementPoliticalParty - const email = getValueViaPath(answers, 'about.email') - const [submitApplication, { loading }] = useSubmitApplication({ - application, - refetch, - event: DefaultEvents.SUBMIT, - }) - - const onBackButtonClick = () => { - const incomeLimit = getValueViaPath(answers, 'election.incomeLimit') - - if (incomeLimit === GREATER) { - goToScreen?.('attachments.file') - } else { - goToScreen?.('election') - } - } - - const onSendButtonClick = () => { - submitApplication() - } - - return ( - - - - {`${answers.about.fullName}, - ${formatMessage(m.nationalId)}: ${formatNationalId( - answers.about.nationalId, - )}, ${formatMessage(m.participated)} - ${answers.election.genitiveName}`} - - - - {`${formatMessage(m.electionDeclare)} ${formatNumber( - ELECTIONLIMIT, - )}`} - - - {formatMessage(m.electionStatementLaw)} - - - - - {errors && getErrorViaPath(errors, 'applicationApprove') ? ( - - ) : null} - - - ) -} diff --git a/libs/application/templates/inao/financial-statement-political-party/src/fields/KeyNumbersCapital/KeyNumbersCapital.tsx b/libs/application/templates/inao/financial-statement-political-party/src/fields/KeyNumbersCapital/KeyNumbersCapital.tsx deleted file mode 100644 index 17329d216f88..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/fields/KeyNumbersCapital/KeyNumbersCapital.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { useState, useEffect } from 'react' -import { - Box, - GridColumn, - GridContainer, - GridRow, -} from '@island.is/island-ui/core' -import { getValueViaPath } from '@island.is/application/core' -import debounce from 'lodash/debounce' -import { useFormContext } from 'react-hook-form' -import { useLocale } from '@island.is/localization' -import { InputController } from '@island.is/shared/form-fields' -import { m } from '../../lib/messages' -import { getErrorViaPath } from '@island.is/application/core' -import { CAPITALNUMBERS, INPUTCHANGEINTERVAL } from '../../utils/constants' -import { Total } from '../../components/Total' - -export const KeyNumbersCapital = () => { - const { formatMessage } = useLocale() - const [totalCapital, setTotalCapital] = useState(0) - const { - clearErrors, - formState: { errors }, - getValues, - } = useFormContext() - - const getTotalCapital = () => { - const values = getValues() - - const income = getValueViaPath(values, CAPITALNUMBERS.capitalIncome) || '0' - const expense = getValueViaPath(values, CAPITALNUMBERS.capitalCost) || '0' - const total = Number(income) - Number(expense) - setTotalCapital(total) - } - - useEffect(() => { - getTotalCapital() - }, [getTotalCapital]) - - return ( - - - - - { - getTotalCapital() - clearErrors(CAPITALNUMBERS.capitalIncome) - }, INPUTCHANGEINTERVAL)} - label={formatMessage(m.capitalIncome)} - backgroundColor="blue" - rightAlign - currency - /> - - - - - { - getTotalCapital() - clearErrors(CAPITALNUMBERS.capitalCost) - }, INPUTCHANGEINTERVAL)} - label={formatMessage(m.capitalCost)} - error={ - errors && getErrorViaPath(errors, CAPITALNUMBERS.capitalCost) - } - backgroundColor="blue" - rightAlign - currency - /> - - - - - - - - - - ) -} diff --git a/libs/application/templates/inao/financial-statement-political-party/src/fields/Overview/Overview.tsx b/libs/application/templates/inao/financial-statement-political-party/src/fields/Overview/Overview.tsx deleted file mode 100644 index 5748df5a3806..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/fields/Overview/Overview.tsx +++ /dev/null @@ -1,170 +0,0 @@ -import { useState } from 'react' -import { DefaultEvents, FieldBaseProps } from '@island.is/application/types' - -import { - AlertBanner, - Box, - Checkbox, - Divider, - GridColumn, - GridRow, - InputError, - Text, -} from '@island.is/island-ui/core' -import { Controller, useFormContext } from 'react-hook-form' -import { getErrorViaPath, getValueViaPath } from '@island.is/application/core' -import { useLocale } from '@island.is/localization' -import { m } from '../../lib/messages' -import { useSubmitApplication } from '../../hooks/useSubmitApplication' -import BottomBar from '../../components/BottomBar' -import { FinancialStatementPoliticalParty } from '../../lib/dataSchema' -import { AboutOverview } from '../../components/AboutOverview' -import { GREATER } from '../../utils/constants' -import { - sectionColumn, - starterColumnStyle, -} from '../../components/css/overviewStyles.css' -import { CapitalNumberOverview } from '../../components/CapitalNumberOverview' -import { AssetDebtEquityOverview } from '../../components/AssetDebtEquityOverview' -import { FileValueLine } from '../../components/FileValueLine' - -export const Overview = ({ - application, - goToScreen, - refetch, -}: FieldBaseProps) => { - const { formatMessage } = useLocale() - const { - formState: { errors }, - setError, - setValue, - } = useFormContext() - - const [approveOverview, setApproveOverview] = useState(false) - - const answers = application.answers as FinancialStatementPoliticalParty - const fileName = answers.attachments?.file?.[0]?.name - - const [submitApplication, { error: submitError, loading }] = - useSubmitApplication({ - application, - refetch, - event: DefaultEvents.SUBMIT, - }) - - const onBackButtonClick = () => { - const incomeLimit = getValueViaPath(answers, 'election.incomeLimit') - - if (incomeLimit === GREATER) { - goToScreen?.('attachments.file') - } else { - goToScreen?.('election') - } - } - - const onSendButtonClick = () => { - if (approveOverview) { - submitApplication() - } else { - setError('applicationApprove', { - type: 'error', - }) - } - } - - return ( - - - - - - - - - - {formatMessage(m.expensesIncome)} - - - - - - - {formatMessage(m.expenses)} - - - - - - - - - - - - - - {formatMessage(m.propertiesAndDebts)} - - - - - - - - {fileName ? ( - <> - - - - ) : null} - - - - - {formatMessage(m.overview)} - - - - { - return ( - { - onChange(e.target.checked) - setApproveOverview(e.target.checked) - setValue('applicationApprove' as string, e.target.checked) - }} - checked={value} - name="applicationApprove" - id="applicationApprove" - label={formatMessage(m.overviewCorrect)} - large - /> - ) - }} - /> - - {errors && getErrorViaPath(errors, 'applicationApprove') ? ( - - ) : null} - {submitError ? ( - - - - ) : null} - - - ) -} diff --git a/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOperatingIncome/PartyExpenses.tsx b/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOperatingIncome/PartyExpenses.tsx deleted file mode 100644 index 5a3eadacb74b..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOperatingIncome/PartyExpenses.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import React, { Fragment } from 'react' -import debounce from 'lodash/debounce' -import { RecordObject } from '@island.is/application/types' -import { InputController } from '@island.is/shared/form-fields' -import { Box } from '@island.is/island-ui/core' -import { useFormContext } from 'react-hook-form' -import { useLocale } from '@island.is/localization' -import { getErrorViaPath } from '@island.is/application/core' -import { m } from '../../lib/messages' -import { INPUTCHANGEINTERVAL, PARTYOPERATIONIDS } from '../../utils/constants' - -interface PropTypes { - getSum: () => void - errors: RecordObject | undefined -} - -export const PartyExpenses = ({ errors, getSum }: PropTypes): JSX.Element => { - const { formatMessage } = useLocale() - const { clearErrors } = useFormContext() - - const onInputChange = debounce((fieldId: string) => { - getSum() - clearErrors(fieldId) - }, INPUTCHANGEINTERVAL) - - return ( - - - onInputChange(PARTYOPERATIONIDS.electionOffice)} - error={ - errors && getErrorViaPath(errors, PARTYOPERATIONIDS.electionOffice) - } - rightAlign - backgroundColor="blue" - currency - /> - - - onInputChange(PARTYOPERATIONIDS.otherCost)} - error={errors && getErrorViaPath(errors, PARTYOPERATIONIDS.otherCost)} - rightAlign - backgroundColor="blue" - currency - /> - - - ) -} diff --git a/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOperatingIncome/PartyIncome.tsx b/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOperatingIncome/PartyIncome.tsx deleted file mode 100644 index 26c702129598..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOperatingIncome/PartyIncome.tsx +++ /dev/null @@ -1,206 +0,0 @@ -import React, { Fragment, useEffect } from 'react' -import debounce from 'lodash/debounce' -import { RecordObject } from '@island.is/application/types' -import { Box } from '@island.is/island-ui/core' -import { InputController } from '@island.is/shared/form-fields' -import { useFormContext } from 'react-hook-form' -import { useLocale } from '@island.is/localization' -import { getErrorViaPath, getValueViaPath } from '@island.is/application/core' -import { m } from '../../lib/messages' -import { FinancialStatementsInaoTaxInfo } from '@island.is/api/schema' -import { INPUTCHANGEINTERVAL, PARTYOPERATIONIDS } from '../../utils/constants' - -interface PropTypes { - data?: { - financialStatementsInaoTaxInfo: FinancialStatementsInaoTaxInfo[] - } | null - loading: boolean - getSum: () => void - errors: RecordObject | undefined -} - -export const PartyIncome = ({ - data, - loading, - errors, - getSum, -}: PropTypes): JSX.Element => { - const { formatMessage } = useLocale() - const { clearErrors, getValues, setValue } = useFormContext() - useEffect(() => { - const values = getValues() - - const contributionsFromTheTreasury = getValueViaPath( - values, - PARTYOPERATIONIDS.contributionsFromTheTreasury, - ) - const parliamentaryPartySupport = getValueViaPath( - values, - PARTYOPERATIONIDS.parliamentaryPartySupport, - ) - const municipalContributions = getValueViaPath( - values, - PARTYOPERATIONIDS.municipalContributions, - ) - - if (data?.financialStatementsInaoTaxInfo) { - if (!contributionsFromTheTreasury) { - setValue( - PARTYOPERATIONIDS.contributionsFromTheTreasury, - data.financialStatementsInaoTaxInfo?.[0]?.value?.toString() ?? '', - ) - } - if (!parliamentaryPartySupport) { - setValue( - PARTYOPERATIONIDS.parliamentaryPartySupport, - data.financialStatementsInaoTaxInfo?.[1]?.value?.toString() ?? '', - ) - } - if (!municipalContributions) { - setValue( - PARTYOPERATIONIDS.municipalContributions, - data.financialStatementsInaoTaxInfo?.[2]?.value?.toString() ?? '', - ) - } - } - getSum() - }, [data, getSum, setValue]) - - const onInputChange = debounce((fieldId: string) => { - getSum() - clearErrors(fieldId) - }, INPUTCHANGEINTERVAL) - - return ( - - - - onInputChange(PARTYOPERATIONIDS.contributionsFromTheTreasury) - } - rightAlign - backgroundColor="blue" - loading={loading} - currency - error={ - errors && - getErrorViaPath( - errors, - PARTYOPERATIONIDS.contributionsFromTheTreasury, - ) - } - /> - - - - onInputChange(PARTYOPERATIONIDS.parliamentaryPartySupport) - } - loading={loading} - backgroundColor="blue" - rightAlign - currency - error={ - errors && - getErrorViaPath(errors, PARTYOPERATIONIDS.parliamentaryPartySupport) - } - /> - - - - onInputChange(PARTYOPERATIONIDS.municipalContributions) - } - loading={loading} - backgroundColor="blue" - rightAlign - currency - error={ - errors && - getErrorViaPath(errors, PARTYOPERATIONIDS.municipalContributions) - } - /> - - - - onInputChange(PARTYOPERATIONIDS.contributionsFromLegalEntities) - } - backgroundColor="blue" - currency - error={ - errors && - getErrorViaPath( - errors, - PARTYOPERATIONIDS.contributionsFromLegalEntities, - ) - } - /> - - - - onInputChange(PARTYOPERATIONIDS.contributionsFromIndividuals) - } - backgroundColor="blue" - currency - error={ - errors && - getErrorViaPath( - errors, - PARTYOPERATIONIDS.contributionsFromIndividuals, - ) - } - /> - - - - onInputChange(PARTYOPERATIONIDS.generalMembershipFees) - } - rightAlign - backgroundColor="blue" - currency - error={ - errors && - getErrorViaPath(errors, PARTYOPERATIONIDS.generalMembershipFees) - } - /> - - - onInputChange(PARTYOPERATIONIDS.otherIncome)} - rightAlign - backgroundColor="blue" - currency - error={ - errors && getErrorViaPath(errors, PARTYOPERATIONIDS.otherIncome) - } - /> - - - ) -} diff --git a/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOperatingIncome/PartyOperatingIncome.tsx b/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOperatingIncome/PartyOperatingIncome.tsx deleted file mode 100644 index 14c43d56e667..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOperatingIncome/PartyOperatingIncome.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import React from 'react' -import { useFormContext } from 'react-hook-form' -import { useQuery } from '@apollo/client' -import { - GridColumn, - GridContainer, - GridRow, - Text, -} from '@island.is/island-ui/core' -import { useLocale } from '@island.is/localization' - -import { m } from '../../lib/messages' -import { PartyIncome } from './PartyIncome' -import { PartyExpenses } from './PartyExpenses' - -import { TaxInfoQuery } from '../../graphql' -import { getValueViaPath } from '@island.is/application/core' -import { FieldBaseProps } from '@island.is/application/types' -import { Total } from '../../components/Total' -import { useTotals } from '../../hooks/useTotals' -import { OPERATINGCOST, PARTYOPERATIONIDS } from '../../utils/constants' - -export const PartyOperatingIncome = ({ application }: FieldBaseProps) => { - const { answers } = application - const operatingYear = getValueViaPath( - answers, - 'conditionalAbout.operatingYear', - ) - - const { data, loading } = useQuery(TaxInfoQuery, { - variables: { year: operatingYear }, - }) - - const { - formState: { errors }, - } = useFormContext() - - const [getTotalIncome, totalIncome] = useTotals( - PARTYOPERATIONIDS.incomePrefix, - ) - const [getTotalExpense, totalExpense] = useTotals( - PARTYOPERATIONIDS.expensePrefix, - ) - const { formatMessage } = useLocale() - - return ( - - - - - {formatMessage(m.income)} - - - - - - - {formatMessage(m.expenses)} - - - - - - - - - - - - ) -} diff --git a/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOverview/PartyOverview.tsx b/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOverview/PartyOverview.tsx index 363492b42d03..ed5081de3586 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOverview/PartyOverview.tsx +++ b/libs/application/templates/inao/financial-statement-political-party/src/fields/PartyOverview/PartyOverview.tsx @@ -171,52 +171,6 @@ export const PartyOverview = ({ ) : null} - - - {formatMessage(m.overview)} - - - - { - return ( - { - onChange(e.target.checked) - setApproveOverview(e.target.checked) - setValue('applicationApprove' as string, e.target.checked) - }} - checked={value} - name="applicationApprove" - id="applicationApprove" - label={formatMessage(m.overviewCorrect)} - large - /> - ) - }} - /> - - {errors && getErrorViaPath(errors, 'applicationApprove') ? ( - - ) : null} - {submitError ? ( - - - - ) : null} - ) } diff --git a/libs/application/templates/inao/financial-statement-political-party/src/fields/Success/Success.tsx b/libs/application/templates/inao/financial-statement-political-party/src/fields/Success/Success.tsx deleted file mode 100644 index 1603815ae9d1..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/fields/Success/Success.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { - Box, - ContentBlock, - ActionCard, - AlertMessage, -} from '@island.is/island-ui/core' -import { useLocale } from '@island.is/localization' -import { CustomField, FieldBaseProps } from '@island.is/application/types' -import format from 'date-fns/format' -import { m } from '../../lib/messages' -import { FinancialStatementPoliticalParty } from '../../lib/dataSchema' - -interface PropTypes extends FieldBaseProps { - field: CustomField -} - -export const Success = ({ application }: PropTypes) => { - const applicationAnswers = - application.answers as FinancialStatementPoliticalParty - const { formatMessage } = useLocale() - - const getDescriptionText = () => { - const currentDate = format(new Date(), "dd.MM.yyyy 'kl.' kk:mm") - return `${formatMessage(m.operatingYearMsgFirst)} ${ - applicationAnswers.conditionalAbout.operatingYear - } - ${formatMessage(m.individualReceivedMsgSecond)} ${currentDate}` - } - - return ( - - - - - - - window.open('/minarsidur/postholf', '_blank'), - }} - backgroundColor="blue" - /> - - - - ) -} diff --git a/libs/application/templates/inao/financial-statement-political-party/src/fields/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/fields/index.ts index 4d9e7b24f065..9665239da2a3 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/fields/index.ts +++ b/libs/application/templates/inao/financial-statement-political-party/src/fields/index.ts @@ -1,9 +1,3 @@ export { OperatingYear } from './OperatingYear/OperatingYear' export { PowerOfAttorneyFields } from './PowerOfAttorneyFields/PowerOfAttorneyFields' -export { PartyOperatingIncome } from './PartyOperatingIncome/PartyOperatingIncome' -export { KeyNumbersCapital } from './KeyNumbersCapital/KeyNumbersCapital' -export { ElectionEquities } from './ElectionEquities/ElectionEquities' export { PartyOverview } from './PartyOverview/PartyOverview' -export { Overview } from './Overview/Overview' -export { ElectionStatement } from './ElectionStatement/ElectionStatement' -export { Success } from './Success/Success' diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/conclusionSection/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/conclusionSection/index.ts new file mode 100644 index 000000000000..1ca0e1529209 --- /dev/null +++ b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/conclusionSection/index.ts @@ -0,0 +1,19 @@ +import { buildFormConclusionSection } from '@island.is/application/ui-forms' +import { m } from '../../../lib/messages' +import { getValueViaPath } from '@island.is/application/core' + +export const conclusionSection = buildFormConclusionSection({ + multiFieldTitle: m.received, + alertTitle: m.returned, + alertMessage: (application) => { + const year = getValueViaPath( + application.answers, + 'conditionalAbout.operatingYear', + ) + return { + ...m.conclusionAlertMessage, + values: { value1: year }, + } + }, + accordion: false, +}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/financialStatementSection/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/financialStatementSection/index.ts similarity index 88% rename from libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/financialStatementSection/index.ts rename to libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/financialStatementSection/index.ts index 6f40b92fc14d..5ff1a5cf83d2 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/financialStatementSection/index.ts +++ b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/financialStatementSection/index.ts @@ -3,8 +3,8 @@ import { buildSection, getValueViaPath, } from '@island.is/application/core' -import { m } from '../../../../lib/messages' -import { LESS } from '../../../../utils/constants' +import { LESS } from '../../../utils/constants' +import { m } from '../../../lib/messages' export const financialStatementSection = buildSection({ id: 'documents', diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/index.ts index bca7ac51bc34..58fe15ed2a7e 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/index.ts +++ b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/index.ts @@ -4,19 +4,21 @@ import { Form, FormModes } from '@island.is/application/types' import Logo from '../../components/Logo' import { clientInfoSection } from './clientInfoSection' import { keyNumbersSection } from './keyNumbersSection' -import { financialStatementSection } from './keyNumbersSection/financialStatementSection' -import { overviewSection } from './keyNumbersSection/overviewSection' +import { financialStatementSection } from './financialStatementSection' +import { overviewSection } from './overviewSection' +import { conclusionSection } from './conclusionSection' export const FinancialStatementPoliticalPartyForm: Form = buildForm({ id: 'FinancialStatementPoliticalPartyForm', title: m.applicationTitle, mode: FormModes.DRAFT, - renderLastScreenButton: false, + renderLastScreenButton: true, logo: Logo, children: [ clientInfoSection, keyNumbersSection, financialStatementSection, overviewSection, + conclusionSection, ], }) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/capitalNumbersSubsection.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/capitalNumbersSubsection.ts new file mode 100644 index 000000000000..14d7b80a02f2 --- /dev/null +++ b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/capitalNumbersSubsection.ts @@ -0,0 +1,43 @@ +import { + buildDisplayField, + buildMultiField, + buildSubSection, + buildTextField, +} from '@island.is/application/core' +import { m } from '../../../lib/messages' +import { CAPITALNUMBERS } from '../../../utils/constants' +import { sumCapitalNumbers } from '../../../utils/helpers' + +export const capitalNumbersSubsection = buildSubSection({ + id: 'keynumbers.capitalNumbers', + title: m.capitalNumbers, + children: [ + buildMultiField({ + id: 'capitalNumber', + title: m.capitalNumbersSectionTitle, + children: [ + buildTextField({ + id: CAPITALNUMBERS.capitalIncome, + title: m.capitalIncome, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildTextField({ + id: CAPITALNUMBERS.capitalCost, + title: m.capitalCost, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildDisplayField({ + id: CAPITALNUMBERS.total, + title: m.totalCapital, + value: sumCapitalNumbers, + variant: 'currency', + rightAlign: true, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/capitalNumbersSubsection/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/capitalNumbersSubsection/index.ts deleted file mode 100644 index 42e21bf1259e..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/capitalNumbersSubsection/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { - buildCustomField, - buildMultiField, - buildSubSection, -} from '@island.is/application/core' -import { m } from '../../../../lib/messages' -import { CAPITALNUMBERS } from '../../../../utils/constants' - -export const capitalNumbersSubsection = buildSubSection({ - id: 'keynumbers.capitalNumbers', - title: m.capitalNumbers, - children: [ - buildMultiField({ - id: 'capitalNumber', - title: m.capitalNumbersSectionTitle, - description: m.fillOutAppopriate, - children: [ - buildCustomField({ - id: 'capitalNumberField', - title: '', - description: '', - component: 'KeyNumbersCapital', - childInputIds: Object.values(CAPITALNUMBERS), - }), - ], - }), - ], -}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/equitiesAndLiabilitiesSubsection.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/equitiesAndLiabilitiesSubsection.ts new file mode 100644 index 000000000000..fcd85ee165de --- /dev/null +++ b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/equitiesAndLiabilitiesSubsection.ts @@ -0,0 +1,122 @@ +import { + buildAlertMessageField, + buildDescriptionField, + buildDisplayField, + buildMultiField, + buildSubSection, + buildTextField, +} from '@island.is/application/core' +import { m } from '../../../lib/messages' +import { + EQUITIESANDLIABILITIESIDS, + EQUITYANDLIABILITIESTOTALS, +} from '../../../utils/constants' +import { + showEquitiesAndLiabilitiesAlert, + sumDebts, + sumEquityAndDebts, + sumProperties, +} from '../../../utils/helpers' + +export const equitiesAndLiabilitiesSubsection = buildSubSection({ + id: 'keyNumbers.equitiesAndLiabilities', + title: m.propertiesAndDebts, + children: [ + buildMultiField({ + id: 'equitiesAndLiabilitiesMultiField', + title: m.keyNumbersDebt, + children: [ + // Assets + buildDescriptionField({ + id: 'propertiesDescription', + title: m.properties, + titleVariant: 'h3', + }), + buildTextField({ + id: EQUITIESANDLIABILITIESIDS.fixedAssetsTotal, + title: m.fixedAssetsTotal, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildTextField({ + id: EQUITIESANDLIABILITIESIDS.currentAssets, + title: m.currentAssets, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildDisplayField({ + id: EQUITYANDLIABILITIESTOTALS.assetsTotal, + title: '', + label: m.totalAssets, + value: sumProperties, + variant: 'currency', + rightAlign: true, + }), + + // Debts + buildDescriptionField({ + id: 'debtsDescription', + title: m.debts, + titleVariant: 'h3', + }), + buildTextField({ + id: EQUITIESANDLIABILITIESIDS.longTerm, + title: m.longTerm, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildTextField({ + id: EQUITIESANDLIABILITIESIDS.shortTerm, + title: m.shortTerm, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildDisplayField({ + id: EQUITYANDLIABILITIESTOTALS.liabilitiesTotal, + title: '', + label: m.totalDebts, + value: sumDebts, + variant: 'currency', + rightAlign: true, + }), + + // Equity + buildDescriptionField({ + id: 'equityDescription', + title: m.equity, + titleVariant: 'h3', + }), + buildTextField({ + id: EQUITIESANDLIABILITIESIDS.totalEquity, + title: m.equity, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + + // Total Equity and Liabilities + buildDisplayField({ + id: EQUITYANDLIABILITIESTOTALS.equityAndLiabilitiesTotal, + title: m.debtsAndCash, + titleVariant: 'h3', + value: sumEquityAndDebts, + variant: 'currency', + rightAlign: true, + }), + + // Alert if total equity and liabilities do not match total assets + buildAlertMessageField({ + condition: showEquitiesAndLiabilitiesAlert, + id: 'equitiesAndLiabilitiesAlert', + title: m.equityErrorTitle, + message: m.equityDebtsAssetsValidatorError, + alertType: 'error', + }), + ], + }), + ], +}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/equitiesAndLiabilitiesSubsection/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/equitiesAndLiabilitiesSubsection/index.ts deleted file mode 100644 index 6920f444dac6..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/equitiesAndLiabilitiesSubsection/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { buildCustomField, buildSubSection } from '@island.is/application/core' -import { m } from '../../../../lib/messages' -import { EQUITIESANDLIABILITIESIDS } from '../../../../utils/constants' - -export const equitiesAndLiabilitiesSubsection = buildSubSection({ - id: 'keyNumbers.equitiesAndLiabilities', - title: m.propertiesAndDebts, - children: [ - buildCustomField({ - id: 'equitiesAndLiabilities', - title: m.keyNumbersDebt, - description: m.fillOutAppopriate, - component: 'ElectionEquities', - childInputIds: Object.values(EQUITIESANDLIABILITIESIDS), - }), - ], -}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/index.ts index dee0b831047e..d23e0707d9c1 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/index.ts +++ b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/index.ts @@ -1,8 +1,8 @@ import { buildSection } from '@island.is/application/core' import { m } from '../../../lib/messages' -import { operatingCostSubsection } from './operatingCostSubsection' -import { capitalNumbersSubsection } from './capitalNumbersSubsection' import { equitiesAndLiabilitiesSubsection } from './equitiesAndLiabilitiesSubsection' +import { capitalNumbersSubsection } from './capitalNumbersSubsection' +import { operatingCostSubsection } from './operatingCostSubsection' export const keyNumbersSection = buildSection({ id: 'keyNumbers', diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/operatingCostSubsection.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/operatingCostSubsection.ts new file mode 100644 index 000000000000..5ea3e3b7e771 --- /dev/null +++ b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/operatingCostSubsection.ts @@ -0,0 +1,129 @@ +import { + buildDescriptionField, + buildDisplayField, + buildMultiField, + buildSubSection, + buildTextField, +} from '@island.is/application/core' +import { m } from '../../../lib/messages' +import { OPERATINGCOST, PARTYOPERATIONIDS } from '../../../utils/constants' +import { sumExpenses, sumIncome, sumTotal } from '../../../utils/helpers' + +export const operatingCostSubsection = buildSubSection({ + id: 'operatingCost', + title: m.expensesIncome, + children: [ + buildMultiField({ + id: 'operatingCostMultiField', + title: m.keyNumbersIncomeAndExpenses, + children: [ + // Income + buildDescriptionField({ + id: 'incomeDescription', + title: m.income, + titleVariant: 'h3', + }), + buildTextField({ + id: PARTYOPERATIONIDS.contributionsFromTheTreasury, + title: m.contributionsFromTheTreasury, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildTextField({ + id: PARTYOPERATIONIDS.parliamentaryPartySupport, + title: m.parliamentaryPartySupport, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildTextField({ + id: PARTYOPERATIONIDS.municipalContributions, + title: m.municipalContributions, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildTextField({ + id: PARTYOPERATIONIDS.contributionsFromLegalEntities, + title: m.contributionsFromLegalEntities, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildTextField({ + id: PARTYOPERATIONIDS.contributionsFromIndividuals, + title: m.contributionsFromIndividuals, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildTextField({ + id: PARTYOPERATIONIDS.generalMembershipFees, + title: m.generalMembershipFees, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildTextField({ + id: PARTYOPERATIONIDS.otherIncome, + title: m.otherIncome, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildDisplayField({ + id: PARTYOPERATIONIDS.totalIncome, + title: '', + label: m.totalIncome, + value: sumIncome, + variant: 'currency', + rightAlign: true, + }), + + // Expenses + buildDescriptionField({ + id: 'expensesDescription', + title: m.expenses, + titleVariant: 'h3', + }), + buildTextField({ + id: PARTYOPERATIONIDS.electionOffice, + title: m.electionOffice, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildTextField({ + id: PARTYOPERATIONIDS.otherCost, + title: m.otherOperationalCost, + width: 'half', + variant: 'currency', + rightAlign: true, + }), + buildDisplayField({ + id: PARTYOPERATIONIDS.totalExpense, + title: '', + label: m.totalExpenses, + value: sumExpenses, + variant: 'currency', + rightAlign: true, + }), + + // Total + buildDescriptionField({ + id: 'totalDescription', + title: m.operatingCost, + titleVariant: 'h3', + }), + buildDisplayField({ + id: OPERATINGCOST.total, + title: '', + value: sumTotal, + variant: 'currency', + rightAlign: true, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/operatingCostSubsection/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/operatingCostSubsection/index.ts deleted file mode 100644 index fbc76af55a1b..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/operatingCostSubsection/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { buildCustomField, buildSubSection } from '@island.is/application/core' -import { m } from '../../../../lib/messages' -import { PARTYOPERATIONIDS } from '../../../../utils/constants' - -export const operatingCostSubsection = buildSubSection({ - id: 'operatingCost', - title: m.expensesIncome, - children: [ - buildCustomField({ - id: 'partyOperations', - title: m.keyNumbersIncomeAndExpenses, - description: m.fillOutAppopriate, - component: 'PartyOperatingIncome', - childInputIds: Object.values(PARTYOPERATIONIDS), - }), - ], -}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/overviewSection/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/overviewSection/index.ts deleted file mode 100644 index 543a96b5fa01..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/overviewSection/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { buildSection } from '@island.is/application/core' -import { overviewMultiField } from './overviewMultiField' -import { m } from '../../../../lib/messages' - -export const overviewSection = buildSection({ - id: 'overviewSection', - title: m.overviewSectionTitle, - children: [overviewMultiField], -}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/overviewSection/overviewMultiField.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/overviewSection/overviewMultiField.ts deleted file mode 100644 index d466187af16c..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/keyNumbersSection/overviewSection/overviewMultiField.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { - buildCustomField, - buildMultiField, - getValueViaPath, -} from '@island.is/application/core' -import { m } from '../../../../lib/messages' -import { GREATER, LESS } from '../../../../utils/constants' - -export const overviewMultiField = buildMultiField({ - id: 'overview', - title: m.yearlyOverview, - description: m.review, - children: [ - buildCustomField({ - id: 'overviewPartyField', - title: '', - doesNotRequireAnswer: true, - component: 'PartyOverview', - }), - buildCustomField({ - id: 'overviewField', - title: '', - condition: (answers) => - getValueViaPath(answers, 'election.incomeLimit') === GREATER, - doesNotRequireAnswer: true, - component: 'Overview', - }), - buildCustomField({ - id: 'overviewStatementField', - title: '', - condition: (answers) => - getValueViaPath(answers, 'election.incomeLimit') === LESS, - doesNotRequireAnswer: true, - component: 'ElectionStatement', - }), - ], -}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/overviewSection/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/overviewSection/index.ts new file mode 100644 index 000000000000..c118b90933cc --- /dev/null +++ b/libs/application/templates/inao/financial-statement-political-party/src/forms/applicationForm/overviewSection/index.ts @@ -0,0 +1,51 @@ +import { + buildCheckboxField, + buildCustomField, + buildMultiField, + buildSection, + buildSubmitField, + YES, +} from '@island.is/application/core' +import { m } from '../../../lib/messages' +import { DefaultEvents } from '@island.is/application/types' + +export const overviewSection = buildSection({ + id: 'overviewSection', + title: m.overviewSectionTitle, + children: [ + buildMultiField({ + id: 'overview', + title: m.yearlyOverview, + description: m.review, + children: [ + buildCustomField({ + id: 'overviewPartyField', + title: '', + doesNotRequireAnswer: true, + component: 'PartyOverview', + }), + buildCheckboxField({ + id: 'approveOverview', + title: '', + options: [ + { + label: m.overviewCorrect, + value: YES, + }, + ], + }), + buildSubmitField({ + id: 'overview.submit', + title: '', + actions: [ + { + event: DefaultEvents.SUBMIT, + name: m.send, + type: 'primary', + }, + ], + }), + ], + }), + ], +}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/done/conclusionSection/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/done/conclusionSection/index.ts deleted file mode 100644 index d6b9add9c2e4..000000000000 --- a/libs/application/templates/inao/financial-statement-political-party/src/forms/done/conclusionSection/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { - buildCustomField, - buildMultiField, - buildSection, -} from '@island.is/application/core' -import { m } from '../../../lib/messages' - -export const conclusionSection = buildSection({ - id: 'conclusionSection', - title: '', - children: [ - buildMultiField({ - id: 'conclusion', - title: m.received, - children: [ - buildCustomField({ - id: 'overview', - component: 'Success', - title: m.applicationAccept, - }), - ], - }), - ], -}) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/forms/done/index.ts b/libs/application/templates/inao/financial-statement-political-party/src/forms/done/index.ts index bfb95dec1cee..2f4ee479f333 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/forms/done/index.ts +++ b/libs/application/templates/inao/financial-statement-political-party/src/forms/done/index.ts @@ -1,6 +1,6 @@ import { buildForm } from '@island.is/application/core' import { Form, FormModes } from '@island.is/application/types' -import { conclusionSection } from './conclusionSection' +import { conclusionSection } from '../applicationForm/conclusionSection' export const done: Form = buildForm({ id: 'done', diff --git a/libs/application/templates/inao/financial-statement-political-party/src/lib/dataSchema.ts b/libs/application/templates/inao/financial-statement-political-party/src/lib/dataSchema.ts index 33f3ea983270..cb85a78c893a 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/lib/dataSchema.ts +++ b/libs/application/templates/inao/financial-statement-political-party/src/lib/dataSchema.ts @@ -3,6 +3,7 @@ import { m } from './messages' import * as kennitala from 'kennitala' import { parsePhoneNumberFromString } from 'libphonenumber-js/min' import { checkIfNegative } from '../utils/helpers' +import { YES } from '@island.is/application/core' const requiredNonNegativeString = z .string() @@ -16,9 +17,11 @@ const FileSchema = z.object({ key: z.string(), url: z.string().optional(), }) + const conditionalAbout = z.object({ operatingYear: requiredString, }) + const about = z.object({ nationalId: z .string() @@ -38,17 +41,7 @@ const about = z.object({ email: z.string().email(), }) -const election = z.object({ - selectElection: z.string().optional(), - electionName: z.string().optional(), - genitiveName: z.string().optional(), - incomeLimit: requiredString, -}) - -const operatingCost = z.object({ - total: requiredString, -}) - +// Key numbers - operating cost -income const partyIncome = z.object({ contributionsFromTheTreasury: requiredNonNegativeString, parliamentaryPartySupport: requiredNonNegativeString, @@ -60,54 +53,70 @@ const partyIncome = z.object({ total: z.string(), }) +// Key numbers - operating cost - expenses const partyExpense = z.object({ electionOffice: requiredNonNegativeString, otherCost: requiredNonNegativeString, total: z.string(), }) +// Key numbers - operating cost - total +const operatingCost = z.object({ + total: requiredString, +}) + +// Key numbers - capital numbers const capitalNumbers = z.object({ capitalIncome: requiredNonNegativeString, capitalCost: requiredNonNegativeString, total: z.string(), }) -const equityAndLiabilities = z.object({ - total: z.string(), -}) - +// Key numbers - equities and liabilities - assets const asset = z.object({ currentAssets: requiredNonNegativeString, fixedAssetsTotal: requiredNonNegativeString, - total: requiredString, -}) - -const equity = z.object({ - totalEquity: requiredString, }) +// Key numbers - equities and liabilities - liabilities const liability = z.object({ longTerm: requiredNonNegativeString, shortTerm: requiredNonNegativeString, - total: requiredNonNegativeString, }) +// Key numbers - equities and liabilities - equity +const equity = z.object({ + totalEquity: requiredString, +}) + +// Key numbers - equities and liabilities - total +const equityAndLiabilitiesTotals = z + .object({ + assetsTotal: z.string(), + liabilitiesTotal: z.string(), + equityAndLiabilitiesTotal: z.string(), + }) + .refine((x) => x.assetsTotal === x.equityAndLiabilitiesTotal, { + message: 'equityAndLiabilities.total must match assets.total', + path: ['equityAndLiabilitiesTotals', 'equityAndLiabilitiesTotal'], + }) + export const dataSchema = z.object({ approveExternalData: z.literal(true), conditionalAbout, about, - election, // Needed?? operatingCost, partyIncome, partyExpense, capitalNumbers, - equityAndLiabilities, + equityAndLiabilitiesTotals, asset, equity, liability, attachments: z.object({ file: z.array(FileSchema).nonempty(), }), + approveOverview: z.array(z.literal(YES)).length(1), }) export type FinancialStatementPoliticalParty = z.TypeOf diff --git a/libs/application/templates/inao/financial-statement-political-party/src/lib/messages.ts b/libs/application/templates/inao/financial-statement-political-party/src/lib/messages.ts index 917fa4927876..846a336cbe53 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/lib/messages.ts +++ b/libs/application/templates/inao/financial-statement-political-party/src/lib/messages.ts @@ -242,7 +242,7 @@ export const m = defineMessages({ }, capitalNumbersSectionTitle: { id: 'fspp.application:income.capitalNumbersSectionTitle', - defaultMessage: 'Lykiltölur Fjármagnsliðir', + defaultMessage: 'Lykiltölur - Fjármagnsliðir', description: 'capital numbers', }, capitalIncome: { @@ -267,12 +267,12 @@ export const m = defineMessages({ }, keyNumbersDebt: { id: 'fspp.application:keyNumbers.debt', - defaultMessage: 'Lykiltölur - Eignir, Skuldir og eigið fé', + defaultMessage: 'Lykiltölur - Eignir, skuldir og eigið fé', description: 'Statement debts', }, equityDebtsAssetsValidatorError: { id: 'fspp.application:equityValidatorError', - defaultMessage: 'Skuldir og eigið fé þarf að vera jafnt og eignir samtals', + defaultMessage: 'Skuldir og eigið fé þurfa að vera jöfn og eignum samtals', description: 'Equity + debts shout equal assets', }, properties: { @@ -305,6 +305,11 @@ export const m = defineMessages({ defaultMessage: 'Eignir samtals', description: 'Total assets', }, + debts: { + id: 'fspp.application:keyNumbers.debts', + defaultMessage: 'Skuldir', + description: 'debts', + }, debtsAndEquity: { id: 'fspp.application:keyNumbers.debtsAndEquity', defaultMessage: 'Skuldir og eigið fé', @@ -570,4 +575,10 @@ export const m = defineMessages({ 'Ef þú telur að þessi kennitala ætti að vera skráð sem stjórnmálasamtök þá bendum við þér á að hafa samband við Ríkisendurskoðun í síma 448 8800', description: 'Descriptionwhen user is not allowed to apply', }, + conclusionAlertMessage: { + id: 'fspp.application:conclusionAlertMessage', + defaultMessage: + 'Ársreikning fyrir rekstrarárið {value1} hefur verið skilað', + description: 'Conclusion alert message', + }, }) diff --git a/libs/application/templates/inao/financial-statement-political-party/src/utils/constants.ts b/libs/application/templates/inao/financial-statement-political-party/src/utils/constants.ts index 6a4de5c9f7b5..3027e4f74b38 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/utils/constants.ts +++ b/libs/application/templates/inao/financial-statement-political-party/src/utils/constants.ts @@ -51,17 +51,21 @@ export const EQUITIESANDLIABILITIESIDS = { assetPrefix: 'asset', currentAssets: 'asset.currentAssets', fixedAssetsTotal: 'asset.fixedAssetsTotal', - assetTotal: 'asset.total', liabilityPrefix: 'liability', longTerm: 'liability.longTerm', shortTerm: 'liability.shortTerm', asset: 'liability.asset', - totalLiability: 'liability.total', operationResult: 'equity.operationResult', equityPrefix: 'equity', totalEquity: 'equity.totalEquity', totalCash: 'equity.total', - totalEquityAndLiabilities: 'equityAndLiabilities.total', +} + +export const EQUITYANDLIABILITIESTOTALS = { + assetsTotal: 'equityAndLiabilitiesTotals.assetsTotal', + liabilitiesTotal: 'equityAndLiabilitiesTotals.liabilitiesTotal', + equityAndLiabilitiesTotal: + 'equityAndLiabilitiesTotals.equityAndLiabilitiesTotal', } // Error helpers diff --git a/libs/application/templates/inao/financial-statement-political-party/src/utils/helpers.ts b/libs/application/templates/inao/financial-statement-political-party/src/utils/helpers.ts index 82ac09edeb37..723bad714d36 100644 --- a/libs/application/templates/inao/financial-statement-political-party/src/utils/helpers.ts +++ b/libs/application/templates/inao/financial-statement-political-party/src/utils/helpers.ts @@ -1,7 +1,15 @@ import { Config } from '../types/types' import subYears from 'date-fns/subYears' import getYear from 'date-fns/getYear' -import { TOTAL } from './constants' +import { + CAPITALNUMBERS, + EQUITIESANDLIABILITIESIDS, + EQUITYANDLIABILITIESTOTALS, + PARTYOPERATIONIDS, + TOTAL, +} from './constants' +import { FormValue } from '@island.is/application/types' +import { getValueViaPath } from '@island.is/application/core' export const getConfigInfoForKey = (config: Config[], configKey: string) => { return config?.filter((config: Config) => config.key === configKey)[0].value @@ -42,3 +50,170 @@ export const formatCurrency = (answer: string) => export const formatNumber = (num: number) => num.toLocaleString('de-DE') export const checkIfNegative = (inputNumber: string) => Number(inputNumber) >= 0 + +export const sumIncome = (answers: FormValue) => { + const contributionsFromTheTreasury = getValueViaPath( + answers, + PARTYOPERATIONIDS.contributionsFromTheTreasury, + ) + const parliamentaryPartySupport = getValueViaPath( + answers, + PARTYOPERATIONIDS.parliamentaryPartySupport, + ) + const municipalContributions = getValueViaPath( + answers, + PARTYOPERATIONIDS.municipalContributions, + ) + const contributionsFromLegalEntities = getValueViaPath( + answers, + PARTYOPERATIONIDS.contributionsFromLegalEntities, + ) + const contributionsFromIndividuals = getValueViaPath( + answers, + PARTYOPERATIONIDS.contributionsFromIndividuals, + ) + const generalMembershipFees = getValueViaPath( + answers, + PARTYOPERATIONIDS.generalMembershipFees, + ) + const otherIncome = getValueViaPath( + answers, + PARTYOPERATIONIDS.otherIncome, + ) + + return `${ + parseInt(contributionsFromTheTreasury || '0') + + parseInt(parliamentaryPartySupport || '0') + + parseInt(municipalContributions || '0') + + parseInt(contributionsFromLegalEntities || '0') + + parseInt(contributionsFromIndividuals || '0') + + parseInt(generalMembershipFees || '0') + + parseInt(otherIncome || '0') + }` +} + +export const sumExpenses = (answers: FormValue) => { + const electionOffice = getValueViaPath( + answers, + PARTYOPERATIONIDS.electionOffice, + ) + const otherCost = getValueViaPath( + answers, + PARTYOPERATIONIDS.otherCost, + ) + + return `${parseInt(electionOffice || '0') + parseInt(otherCost || '0')}` +} + +export const sumTotal = (answers: FormValue) => { + const income = getValueViaPath(answers, PARTYOPERATIONIDS.totalIncome) + const expenses = getValueViaPath( + answers, + PARTYOPERATIONIDS.totalExpense, + ) + return `${parseInt(income || '0') - parseInt(expenses || '0')}` +} + +export const sumCapitalNumbers = (answers: FormValue) => { + const capitalIncome = getValueViaPath( + answers, + CAPITALNUMBERS.capitalIncome, + ) + const capitalCost = getValueViaPath( + answers, + CAPITALNUMBERS.capitalCost, + ) + return `${parseInt(capitalIncome || '0') - parseInt(capitalCost || '0')}` +} + +export const sumProperties = (answers: FormValue) => { + const fixedAssetsTotal = getValueViaPath( + answers, + EQUITIESANDLIABILITIESIDS.fixedAssetsTotal, + ) + const currentAssets = getValueViaPath( + answers, + EQUITIESANDLIABILITIESIDS.currentAssets, + ) + return `${parseInt(fixedAssetsTotal || '0') + parseInt(currentAssets || '0')}` +} + +export const sumDebts = (answers: FormValue) => { + const longTerm = getValueViaPath( + answers, + EQUITIESANDLIABILITIESIDS.longTerm, + ) + const shortTerm = getValueViaPath( + answers, + EQUITIESANDLIABILITIESIDS.shortTerm, + ) + return `${parseInt(longTerm || '0') + parseInt(shortTerm || '0')}` +} + +export const sumEquityAndDebts = (answers: FormValue) => { + const totalEquity = getValueViaPath( + answers, + EQUITIESANDLIABILITIESIDS.totalEquity, + ) + const totalLiability = getValueViaPath( + answers, + EQUITYANDLIABILITIESTOTALS.liabilitiesTotal, + ) + return `${parseInt(totalEquity || '0') + parseInt(totalLiability || '0')}` +} + +export const showEquitiesAndLiabilitiesAlert = (answers: FormValue) => { + // Assets + const fixedAssetsTotal = getValueViaPath( + answers, + EQUITIESANDLIABILITIESIDS.fixedAssetsTotal, + ) + const currentAssets = getValueViaPath( + answers, + EQUITIESANDLIABILITIESIDS.currentAssets, + ) + const totalAssets = getValueViaPath( + answers, + EQUITYANDLIABILITIESTOTALS.assetsTotal, + ) + + // Debts + const longTerm = getValueViaPath( + answers, + EQUITIESANDLIABILITIESIDS.longTerm, + ) + const shortTerm = getValueViaPath( + answers, + EQUITIESANDLIABILITIESIDS.shortTerm, + ) + const totalLiability = getValueViaPath( + answers, + EQUITYANDLIABILITIESTOTALS.liabilitiesTotal, + ) + + // Equity + const totalEquity = getValueViaPath( + answers, + EQUITIESANDLIABILITIESIDS.totalEquity, + ) + + // Total Equity and Liabilities + const totalEquityAndLiabilities = getValueViaPath( + answers, + EQUITYANDLIABILITIESTOTALS.equityAndLiabilitiesTotal, + ) + + if ( + !fixedAssetsTotal || + !currentAssets || + !totalAssets || + !longTerm || + !shortTerm || + !totalLiability || + !totalEquity || + !totalEquityAndLiabilities + ) { + return false + } + return totalAssets !== totalEquityAndLiabilities +} diff --git a/libs/application/templates/inheritance-report/src/fields/FuneralCost/index.tsx b/libs/application/templates/inheritance-report/src/fields/FuneralCost/index.tsx index 3cfe9050e922..6222ecda7f0b 100644 --- a/libs/application/templates/inheritance-report/src/fields/FuneralCost/index.tsx +++ b/libs/application/templates/inheritance-report/src/fields/FuneralCost/index.tsx @@ -76,6 +76,7 @@ export const FuneralCost: FC< const rentCost = valueToNumber(values?.rent) const foodCost = valueToNumber(values?.food) const tombstoneCost = valueToNumber(values?.tombstone) + const servicesCost = valueToNumber(values?.service) let total = buildCost + @@ -85,7 +86,8 @@ export const FuneralCost: FC< musicCost + rentCost + foodCost + - tombstoneCost + tombstoneCost + + servicesCost if (hasOther) { total += valueToNumber(values?.other) diff --git a/libs/application/templates/inheritance-report/src/fields/Overview/OverviewDebts/index.tsx b/libs/application/templates/inheritance-report/src/fields/Overview/OverviewDebts/index.tsx index 8ed7095c84c0..b7367e2a7eca 100644 --- a/libs/application/templates/inheritance-report/src/fields/Overview/OverviewDebts/index.tsx +++ b/libs/application/templates/inheritance-report/src/fields/Overview/OverviewDebts/index.tsx @@ -94,6 +94,12 @@ export const OverviewDebts: FC> = ({ getValueViaPath(answers, 'funeralCost.tombstone') || '0', )} /> + (answers, 'funeralCost.service') || '0', + )} + /> [number] export const Additions = ({ application }: Props) => { - const [asRoman, setAsRoman] = useState(false) + const [asRoman, setAsRoman] = useState( + application.answers.misc?.asRoman ?? false, + ) const { formatMessage: f } = useLocale() const { setValue } = useFormContext() @@ -57,8 +59,6 @@ export const Additions = ({ application }: Props) => { const onRemoveAddition = (index: number) => { const filtered = additions.filter((_, i) => i !== index) const mapped = filtered.map((addition, i) => { - if (addition.type !== 'html') return addition - const title = f(attachments.additions.title, { index: asRoman ? convertNumberToRoman(i + 1) : i + 1, }) @@ -83,10 +83,8 @@ export const Additions = ({ application }: Props) => { const onRomanChange = (val: boolean) => { const handleTitleChange = (addition: Addition, i: number) => { - if (addition.type !== 'html') return addition - const title = f(attachments.additions.title, { - index: asRoman ? convertNumberToRoman(i + 1) : i + 1, + index: val ? convertNumberToRoman(i + 1) : i + 1, }) return { ...addition, @@ -97,14 +95,17 @@ export const Additions = ({ application }: Props) => { const currentAnswers = structuredClone(currentApplication.answers) const updatedAdditions = additions.map(handleTitleChange) - const updatedAnswers = set( + let updatedAnswers = set( currentAnswers, InputFields.advert.additions, updatedAdditions, ) + updatedAnswers = set(updatedAnswers, InputFields.misc.asRoman, val) + setAsRoman(val) setValue(InputFields.advert.additions, updatedAdditions) + setValue(InputFields.misc.asRoman, val) updateApplication(updatedAnswers) } @@ -206,7 +207,8 @@ export const Additions = ({ application }: Props) => { diff --git a/libs/application/templates/official-journal-of-iceland/src/fields/Attachments.tsx b/libs/application/templates/official-journal-of-iceland/src/fields/Attachments.tsx index 8969e0d0b52d..8065ce013629 100644 --- a/libs/application/templates/official-journal-of-iceland/src/fields/Attachments.tsx +++ b/libs/application/templates/official-journal-of-iceland/src/fields/Attachments.tsx @@ -1,4 +1,4 @@ -import { OJOIFieldBaseProps } from '../lib/types' +import { InputFields, OJOIFieldBaseProps } from '../lib/types' import { Box, Button, InputFileUpload, Stack } from '@island.is/island-ui/core' import { useFileUpload } from '../hooks/useFileUpload' import { ALLOWED_FILE_TYPES, ApplicationAttachmentType } from '../lib/constants' @@ -6,36 +6,59 @@ import { useLocale } from '@island.is/localization' import { attachments } from '../lib/messages/attachments' import { useState } from 'react' import { Additions } from '../components/additions/Additions' +import { useApplication } from '../hooks/useUpdateApplication' +import { useFormContext } from 'react-hook-form' export const Attachments = ({ application }: OJOIFieldBaseProps) => { + const { setValue } = useFormContext() const { formatMessage: f } = useLocale() const { files, onChange, onRemove } = useFileUpload({ applicationId: application.id, attachmentType: ApplicationAttachmentType.ADDITIONS, }) - const [asAddition, setAsAddition] = useState(true) + const { updateApplication, application: currentApplication } = useApplication( + { + applicationId: application.id, + }, + ) + + const [asDocument, setAsDocument] = useState( + application.answers.misc?.asDocument ?? false, + ) + + const handleChange = () => { + const current = asDocument + setAsDocument((toggle) => !toggle) + + setValue(InputFields.misc.asDocument, !current) + updateApplication({ + ...currentApplication.answers, + misc: { + ...currentApplication.answers.misc, + asDocument: !current, + }, + }) + } return ( - {!asAddition ? ( - - ) : ( + {asDocument ? ( { icon: 'blue200', }} /> + ) : ( + )} ) diff --git a/libs/application/templates/official-journal-of-iceland/src/fields/Preview.tsx b/libs/application/templates/official-journal-of-iceland/src/fields/Preview.tsx index 3255b2e091e5..82257eeee648 100644 --- a/libs/application/templates/official-journal-of-iceland/src/fields/Preview.tsx +++ b/libs/application/templates/official-journal-of-iceland/src/fields/Preview.tsx @@ -21,7 +21,6 @@ import { import { Routes, SignatureTypes } from '../lib/constants' import { useApplication } from '../hooks/useUpdateApplication' import { advert, error, preview, signatures } from '../lib/messages' -import { useType } from '../hooks/useType' import { previewValidationSchema, signatureValidationSchema, @@ -39,10 +38,6 @@ export const Preview = ({ application, goToScreen }: OJOIFieldBaseProps) => { const { formatMessage: f } = useLocale() - const { type } = useType({ - typeId: currentApplication.answers.advert?.typeId, - }) - const { fetchPdf, error: pdfError, @@ -60,7 +55,7 @@ export const Preview = ({ application, goToScreen }: OJOIFieldBaseProps) => { const url = URL.createObjectURL(blob) let downloadName - const type = currentApplication.answers.advert?.typeName + const type = currentApplication.answers.advert?.type?.title if (type) { downloadName = type.replace('.', '') } @@ -103,14 +98,14 @@ export const Preview = ({ application, goToScreen }: OJOIFieldBaseProps) => { }) const advertMarkup = getAdvertMarkup({ - type: type?.title, + type: currentApplication.answers.advert?.type?.title, title: currentApplication.answers.advert?.title, html: currentApplication.answers.advert?.html, }) const hasMarkup = !!currentApplication.answers.advert?.html || - type?.title || + currentApplication.answers.advert?.type?.title || currentApplication.answers.advert?.title const combinedHtml = hasMarkup diff --git a/libs/application/templates/official-journal-of-iceland/src/fields/Publishing.tsx b/libs/application/templates/official-journal-of-iceland/src/fields/Publishing.tsx index b2f7d27726a9..1e6430800d5f 100644 --- a/libs/application/templates/official-journal-of-iceland/src/fields/Publishing.tsx +++ b/libs/application/templates/official-journal-of-iceland/src/fields/Publishing.tsx @@ -8,6 +8,7 @@ import { AlertMessage, Box, Icon, + Inline, Select, SkeletonLoader, Tag, @@ -18,6 +19,8 @@ import set from 'lodash/set' import addYears from 'date-fns/addYears' import { addWeekdays, getFastTrack, getWeekendDates } from '../lib/utils' import { useState } from 'react' +import { baseEntitySchema } from '../lib/dataSchema' +import { z } from 'zod' export const Publishing = ({ application }: OJOIFieldBaseProps) => { const { formatMessage: f } = useLocale() @@ -52,7 +55,7 @@ export const Publishing = ({ application }: OJOIFieldBaseProps) => { getFastTrack(new Date(defaultDate)).fastTrack, ) - const onCategoryChange = (value?: string) => { + const onCategoryChange = (value?: z.infer) => { setIsUpdatingCategory(true) if (!value) { setIsUpdatingCategory(false) @@ -62,8 +65,8 @@ export const Publishing = ({ application }: OJOIFieldBaseProps) => { const currentAnswers = structuredClone(currentApplication.answers) const selectedCategories = currentAnswers.advert?.categories || [] - const newCategories = selectedCategories.includes(value) - ? selectedCategories.filter((c) => c !== value) + const newCategories = selectedCategories.find((cat) => cat.id === value.id) + ? selectedCategories.filter((c) => c.id !== value.id) : [...selectedCategories, value] const updatedAnswers = set( @@ -77,19 +80,12 @@ export const Publishing = ({ application }: OJOIFieldBaseProps) => { }) } - const defaultCategory = { - label: f(publishing.inputs.contentCategories.placeholder), - value: '', - } - const mappedCategories = categories?.map((c) => ({ label: c.title, - value: c.id, + value: c, })) - const selectedCategories = categories?.filter((c) => - currentApplication.answers.advert?.categories?.includes(c.id), - ) + const selectedCategories = currentApplication.answers.advert?.categories return ( @@ -124,30 +120,29 @@ export const Publishing = ({ application }: OJOIFieldBaseProps) => { size="sm" label={f(publishing.inputs.contentCategories.label)} backgroundColor="blue" - defaultValue={defaultCategory} options={mappedCategories} + defaultValue={mappedCategories?.[0]} onChange={(opt) => onCategoryChange(opt?.value)} + filterConfig={{ + matchFrom: 'start', + }} /> - - {selectedCategories?.map((c) => ( - onCategoryChange(c.id)} - outlined - key={c.id} - > - - {c.title} - - - - ))} + + + {selectedCategories?.map((c) => ( + onCategoryChange(c)} + outlined + key={c.id} + > + + {c.title} + + + + ))} + )} diff --git a/libs/application/templates/official-journal-of-iceland/src/fields/Summary.tsx b/libs/application/templates/official-journal-of-iceland/src/fields/Summary.tsx index 946abdbf7d5b..dc1799e2a3ef 100644 --- a/libs/application/templates/official-journal-of-iceland/src/fields/Summary.tsx +++ b/libs/application/templates/official-journal-of-iceland/src/fields/Summary.tsx @@ -14,12 +14,9 @@ import { useUserInfo } from '@island.is/react-spa/bff' import { useEffect } from 'react' import { ZodCustomIssue } from 'zod' import { Property } from '../components/property/Property' -import { useCategories } from '../hooks/useCategories' -import { useDepartment } from '../hooks/useDepartment' import { usePrice } from '../hooks/usePrice' -import { useType } from '../hooks/useType' import { useApplication } from '../hooks/useUpdateApplication' -import { MINIMUM_WEEKDAYS, Routes } from '../lib/constants' +import { Routes } from '../lib/constants' import { advertValidationSchema, publishingValidationSchema, @@ -28,7 +25,7 @@ import { import { advert, error, publishing, summary } from '../lib/messages' import { signatures } from '../lib/messages/signatures' import { OJOIFieldBaseProps } from '../lib/types' -import { addWeekdays, getFastTrack, parseZodIssue } from '../lib/utils' +import { getFastTrack, parseZodIssue } from '../lib/utils' export const Summary = ({ application, @@ -42,26 +39,11 @@ export const Summary = ({ const user = useUserInfo() - const { type, loading: loadingType } = useType({ - typeId: currentApplication.answers.advert?.typeId, - }) - const { price, loading: loadingPrice } = usePrice({ applicationId: application.id, }) - const { department, loading: loadingDepartment } = useDepartment({ - departmentId: currentApplication.answers.advert?.departmentId, - }) - - const { categories, loading: loadingCategories } = useCategories() - - const selectedCategories = categories?.filter((c) => - currentApplication.answers?.advert?.categories?.includes(c.id), - ) - - const today = new Date() - const estimatedDate = addWeekdays(today, MINIMUM_WEEKDAYS) + const selectedCategories = application.answers?.advert?.categories const advertValidationCheck = advertValidationSchema.safeParse( currentApplication.answers, @@ -86,6 +68,10 @@ export const Summary = ({ } else { setSubmitButtonDisabled && setSubmitButtonDisabled(true) } + + return () => { + setSubmitButtonDisabled && setSubmitButtonDisabled(false) + } }, [ advertValidationCheck, signatureValidationCheck, @@ -227,18 +213,16 @@ export const Summary = ({ value={user.profile.name} /> c.title).join(', ')} /> @@ -289,7 +272,6 @@ export const Summary = ({ } /> diff --git a/libs/application/templates/official-journal-of-iceland/src/hooks/useTypes.ts b/libs/application/templates/official-journal-of-iceland/src/hooks/useTypes.ts index ca15965c5c74..8cd4ff5678ed 100644 --- a/libs/application/templates/official-journal-of-iceland/src/hooks/useTypes.ts +++ b/libs/application/templates/official-journal-of-iceland/src/hooks/useTypes.ts @@ -1,4 +1,4 @@ -import { NetworkStatus, useQuery } from '@apollo/client' +import { useLazyQuery, useQuery } from '@apollo/client' import { OfficialJournalOfIcelandAdvertsTypesResponse } from '@island.is/api/schema' import { TYPES_QUERY } from '../graphql/queries' @@ -40,21 +40,35 @@ export const useTypes = ({ params.pageSize = 1000 } - const { data, loading, error, refetch, networkStatus } = useQuery< - TypesResponse, - TypesVariables - >(TYPES_QUERY, { - variables: { - params: params, + const { data, loading, error } = useQuery( + TYPES_QUERY, + { + variables: { + params: params, + }, + onCompleted: onCompleted, }, - notifyOnNetworkStatusChange: true, - onCompleted: onCompleted, + ) + + const [ + getLazyTypes, + { data: lazyTypes, loading: lazyTypesLoading, error: lazyTypesError }, + ] = useLazyQuery(TYPES_QUERY, { + fetchPolicy: 'network-only', }) + const currentTypes = lazyTypes + ? lazyTypes.officialJournalOfIcelandTypes.types + : data?.officialJournalOfIcelandTypes.types + return { - useLazyTypes: refetch, - types: data?.officialJournalOfIcelandTypes.types, - loading: loading || networkStatus === NetworkStatus.refetch, + lazyTypes: lazyTypes?.officialJournalOfIcelandTypes.types, + lazyTypesLoading, + lazyTypesError, + getLazyTypes, + types: currentTypes, + initalTypes: data?.officialJournalOfIcelandTypes.types, + loading: loading || lazyTypesLoading, error, } } diff --git a/libs/application/templates/official-journal-of-iceland/src/lib/OJOIApplication.ts b/libs/application/templates/official-journal-of-iceland/src/lib/OJOIApplication.ts index 3e7cc7fc9289..5baf45b63a8d 100644 --- a/libs/application/templates/official-journal-of-iceland/src/lib/OJOIApplication.ts +++ b/libs/application/templates/official-journal-of-iceland/src/lib/OJOIApplication.ts @@ -41,7 +41,7 @@ const getApplicationName = (application: Application) => { const type = getValueViaPath( application.answers, - InputFields.advert.typeName, + `${InputFields.advert.type}.title`, '', ) diff --git a/libs/application/templates/official-journal-of-iceland/src/lib/dataSchema.ts b/libs/application/templates/official-journal-of-iceland/src/lib/dataSchema.ts index f617921467b5..046cbeed2664 100644 --- a/libs/application/templates/official-journal-of-iceland/src/lib/dataSchema.ts +++ b/libs/application/templates/official-journal-of-iceland/src/lib/dataSchema.ts @@ -43,6 +43,12 @@ export const regularSignatureSchema = z .array(regularSignatureItemSchema) .optional() +export const baseEntitySchema = z.object({ + id: z.string(), + title: z.string(), + slug: z.string(), +}) + export const signatureInstitutionSchema = z.enum(['institution', 'date']) export const committeeSignatureSchema = regularSignatureItemSchema @@ -61,13 +67,12 @@ export const channelSchema = z const advertSchema = z .object({ - departmentId: z.string().optional(), - typeName: z.string().optional(), - typeId: z.string().optional(), + department: baseEntitySchema.optional(), + type: baseEntitySchema.optional().nullable(), title: z.string().optional(), html: z.string().optional(), requestedDate: z.string().optional(), - categories: z.array(z.string()).optional(), + categories: z.array(baseEntitySchema).optional(), channels: z.array(channelSchema).optional(), message: z.string().optional(), additions: additionSchema.optional(), @@ -78,6 +83,8 @@ const miscSchema = z .object({ signatureType: z.string().optional(), selectedTemplate: z.string().optional(), + asDocument: z.boolean().optional(), + asRoman: z.boolean().optional(), }) .partial() @@ -108,16 +115,16 @@ export const partialSchema = z.object({ // We make properties optional to throw custom error messages export const advertValidationSchema = z.object({ advert: z.object({ - departmentId: z - .string() + department: baseEntitySchema .optional() - .refine((value) => value && value.length > 0, { + .nullable() + .refine((value) => value !== null && value !== undefined, { params: error.missingDepartment, }), - typeId: z - .string() + type: baseEntitySchema .optional() - .refine((value) => value && value.length > 0, { + .nullable() + .refine((value) => value !== null && value !== undefined, { params: error.missingType, }), title: z @@ -137,17 +144,17 @@ export const advertValidationSchema = z.object({ export const previewValidationSchema = z.object({ advert: z.object({ - departmentId: z - .string() + department: baseEntitySchema .optional() - .refine((value) => value && value.length > 0, { - params: error.missingPreviewDepartment, + .nullable() + .refine((value) => value !== null && value !== undefined, { + params: error.missingDepartment, }), - typeId: z - .string() + type: baseEntitySchema .optional() - .refine((value) => value && value.length > 0, { - params: error.missingPreviewType, + .nullable() + .refine((value) => value !== null && value !== undefined, { + params: error.missingType, }), title: z .string() @@ -173,7 +180,7 @@ export const publishingValidationSchema = z.object({ params: error.missingRequestedDate, }), categories: z - .array(z.string()) + .array(baseEntitySchema) .optional() .refine((value) => Array.isArray(value) && value.length > 0, { params: error.noCategorySelected, diff --git a/libs/application/templates/official-journal-of-iceland/src/lib/messages/attachments.ts b/libs/application/templates/official-journal-of-iceland/src/lib/messages/attachments.ts index 0046056207a4..e8a0f839b7b6 100644 --- a/libs/application/templates/official-journal-of-iceland/src/lib/messages/attachments.ts +++ b/libs/application/templates/official-journal-of-iceland/src/lib/messages/attachments.ts @@ -34,7 +34,7 @@ export const attachments = { }, asAttachment: { id: 'ojoi.application:attachments.buttons.additionType.asAttachment', - defaultMessage: 'Hlaða upp skjölum', + defaultMessage: 'Bæta við viðauka', description: 'Label of the button to upload attachments', }, removeAddition: { diff --git a/libs/application/templates/official-journal-of-iceland/src/lib/types.ts b/libs/application/templates/official-journal-of-iceland/src/lib/types.ts index ccae26abdb38..1529e2d56442 100644 --- a/libs/application/templates/official-journal-of-iceland/src/lib/types.ts +++ b/libs/application/templates/official-journal-of-iceland/src/lib/types.ts @@ -11,9 +11,8 @@ export const InputFields = { approveExternalData: 'requirements.approveExternalData', }, [Routes.ADVERT]: { - departmentId: 'advert.departmentId', - typeName: 'advert.typeName', - typeId: 'advert.typeId', + department: 'advert.department', + type: 'advert.type', title: 'advert.title', html: 'advert.html', requestedDate: 'advert.requestedDate', @@ -34,13 +33,15 @@ export const InputFields = { [Routes.MISC]: { signatureType: 'misc.signatureType', selectedTemplate: 'misc.selectedTemplate', + asDocument: 'misc.asDocument', + asRoman: 'misc.asRoman', }, } export const RequiredInputFieldsNames = { [Routes.ADVERT]: { - departmentId: 'Deild', - typeId: 'Tegund', + department: 'Deild', + type: 'Tegund', title: 'Titill', html: 'Auglýsing', requestedDate: 'Útgáfudagur', diff --git a/libs/application/templates/official-journal-of-iceland/src/lib/utils.ts b/libs/application/templates/official-journal-of-iceland/src/lib/utils.ts index 2e6f17b53156..15699f900241 100644 --- a/libs/application/templates/official-journal-of-iceland/src/lib/utils.ts +++ b/libs/application/templates/official-journal-of-iceland/src/lib/utils.ts @@ -3,6 +3,7 @@ import addYears from 'date-fns/addYears' import { z } from 'zod' import { additionSchema, + baseEntitySchema, committeeSignatureSchema, memberItemSchema, partialSchema, @@ -17,6 +18,8 @@ import is from 'date-fns/locale/is' import { SignatureTypes, OJOI_DF, FAST_TRACK_DAYS } from './constants' import { MessageDescriptor } from 'react-intl' import { v4 as uuid } from 'uuid' +import Hypher from 'hypher' +import { hyphenateText } from '@island.is/island-ui/core' export const countDaysAgo = (date: Date) => { const now = new Date() @@ -130,6 +133,11 @@ export const getSignatureDefaultValues = (signature: any, index?: number) => { return { institution: signature.institution, date: signature.date } } +export const isBaseEntity = ( + entity: unknown, +): entity is z.infer => + baseEntitySchema.safeParse(entity).success + export const isAddition = ( addition: unknown, ): addition is z.infer => @@ -184,6 +192,8 @@ export const getRegularAnswers = (answers: OJOIApplication['answers']) => { signature: null, } } +const hyphenate = (text = '') => + hyphenateText(text, { locale: 'is', minLeft: 4, minRight: 4 }) const getMembersMarkup = (member: z.infer) => { if (!member.name) return '' @@ -192,18 +202,21 @@ const getMembersMarkup = (member: z.infer) => { marginBottom: member.below ? '0' : '1.5em', } - const aboveMarkup = member.above - ? `

${member.above}

` - : '' - const afterMarkup = member.after ? ` ${member.after}` : '' - const belowMarkup = member.below - ? `

${member.below}

` + const name = hyphenate(member.name) + const above = hyphenate(member.above) + const after = hyphenate(member.after) + const below = hyphenate(member.below) + + const aboveMarkup = above + ? `

${above}

` : '' + const afterMarkup = after ? ` ${after}` : '' + const belowMarkup = below ? `

${below}

` : '' return `
${aboveMarkup} -

${member.name}${afterMarkup}

+

${name}${afterMarkup}

${belowMarkup}
` @@ -255,7 +268,9 @@ const signatureTemplate = ( .join('') const additionalMarkup = additionalSignature - ? `

${additionalSignature}

` + ? `

${hyphenate( + additionalSignature, + )}

` : '' return `${markup}${additionalMarkup}` as HTMLText diff --git a/libs/application/templates/official-journal-of-iceland/src/screens/AdvertScreen.tsx b/libs/application/templates/official-journal-of-iceland/src/screens/AdvertScreen.tsx index 56a115f61241..92d9a3911d77 100644 --- a/libs/application/templates/official-journal-of-iceland/src/screens/AdvertScreen.tsx +++ b/libs/application/templates/official-journal-of-iceland/src/screens/AdvertScreen.tsx @@ -11,13 +11,6 @@ export const AdvertScreen = (props: OJOIFieldBaseProps) => { const { formatMessage: f } = useLocale() const [modalVisible, setModalVisability] = useState(false) - const generateTimestamp = () => new Date().toISOString() - - /** - * This state here is for force rerendering of the HTML editor when a value is received from the modal - */ - const [timestamp, setTimestamp] = useState(generateTimestamp()) - return ( { } > - + setTimestamp(generateTimestamp())} + onConfirmChange={() => { + setTimeout(() => { + props.refetch && props.refetch() + }, 300) + }} /> ) diff --git a/libs/application/templates/social-insurance-administration/income-plan/src/fields/Review/index.tsx b/libs/application/templates/social-insurance-administration/income-plan/src/fields/Review/index.tsx index 09323c06371b..9a420ccf1e56 100644 --- a/libs/application/templates/social-insurance-administration/income-plan/src/fields/Review/index.tsx +++ b/libs/application/templates/social-insurance-administration/income-plan/src/fields/Review/index.tsx @@ -119,7 +119,9 @@ export const Review: FC = ({
- {formatMessage(inReviewFormMessages.description)} + {state === `${States.TRYGGINGASTOFNUN_SUBMITTED}` + ? formatMessage(inReviewFormMessages.description) + : formatMessage(inReviewFormMessages.reviewDescription)} diff --git a/libs/application/templates/social-insurance-administration/income-plan/src/lib/messages.ts b/libs/application/templates/social-insurance-administration/income-plan/src/lib/messages.ts index f77dd9c57de4..a989acf7c4ad 100644 --- a/libs/application/templates/social-insurance-administration/income-plan/src/lib/messages.ts +++ b/libs/application/templates/social-insurance-administration/income-plan/src/lib/messages.ts @@ -315,6 +315,11 @@ export const inReviewFormMessages = defineMessages({ defaultMessage: 'Tekjuáætlun þín hefur ekki verið tekin til vinnslu.', description: 'Your income plan has not been processed.', }, + reviewDescription: { + id: 'ip.application:inReview.review.description', + defaultMessage: 'Tekjuáætlun þín hefur verið tekin til vinnslu.', + description: 'Your income plan has been processed.', + }, }) export const statesMessages = defineMessages({ diff --git a/libs/application/templates/social-insurance-administration/old-age-pension/src/dataProviders/index.ts b/libs/application/templates/social-insurance-administration/old-age-pension/src/dataProviders/index.ts index e61226395830..8fabc0f9086b 100644 --- a/libs/application/templates/social-insurance-administration/old-age-pension/src/dataProviders/index.ts +++ b/libs/application/templates/social-insurance-administration/old-age-pension/src/dataProviders/index.ts @@ -34,3 +34,9 @@ export const SocialInsuranceAdministrationCurrenciesApi = defineTemplateApi({ externalDataId: 'socialInsuranceAdministrationCurrencies', namespace: 'SocialInsuranceAdministration', }) + +export const SocialInsuranceAdministrationLatestIncomePlan = defineTemplateApi({ + action: 'getLatestIncomePlan', + externalDataId: 'socialInsuranceAdministrationLatestIncomePlan', + namespace: 'SocialInsuranceAdministration', +}) diff --git a/libs/application/templates/social-insurance-administration/old-age-pension/src/fields/Conclusion/index.tsx b/libs/application/templates/social-insurance-administration/old-age-pension/src/fields/Conclusion/index.tsx new file mode 100644 index 000000000000..f9a2da047eab --- /dev/null +++ b/libs/application/templates/social-insurance-administration/old-age-pension/src/fields/Conclusion/index.tsx @@ -0,0 +1,104 @@ +import { + FieldBaseProps, + FieldComponents, + FieldTypes, +} from '@island.is/application/types' +import { Markdown } from '@island.is/shared/components' +import { + Box, + AlertMessage, + AccordionCard, + BulletList, +} from '@island.is/island-ui/core' +import { useLocale } from '@island.is/localization' +import { FC } from 'react' +import { MessageWithLinkButtonFormField } from '@island.is/application/ui-fields' +import { socialInsuranceAdministrationMessage } from '@island.is/application/templates/social-insurance-administration-core/lib/messages' +import { getApplicationExternalData } from '../../lib/oldAgePensionUtils' +import { oldAgePensionFormMessage } from '../../lib/messages' +import { coreMessages } from '@island.is/application/core' + +export const Conclusion: FC> = ( + props, +) => { + const { application } = props + const { formatMessage } = useLocale() + + const { hasIncomePlanStatus } = getApplicationExternalData( + application.externalData, + ) + + return ( + + + + + + + + + {formatMessage( + oldAgePensionFormMessage.conclusionScreen.nextStepsText, + )} + + + + + {formatMessage( + oldAgePensionFormMessage.conclusionScreen.bulletList, + )} + + + + + + + + + ) +} diff --git a/libs/application/templates/social-insurance-administration/old-age-pension/src/fields/index.ts b/libs/application/templates/social-insurance-administration/old-age-pension/src/fields/index.ts index b61a866f7ec2..49440420ab7b 100644 --- a/libs/application/templates/social-insurance-administration/old-age-pension/src/fields/index.ts +++ b/libs/application/templates/social-insurance-administration/old-age-pension/src/fields/index.ts @@ -2,3 +2,4 @@ export { ResidenceHistory } from './ResidenceHistory' export { Review } from './Review' export { default as EmployersOverview } from './EmployersOverview' export { default as EmployersRatioMonthly } from './EmployersRatioMonthly' +export { Conclusion } from './Conclusion' diff --git a/libs/application/templates/social-insurance-administration/old-age-pension/src/forms/OldAgePensionForm.ts b/libs/application/templates/social-insurance-administration/old-age-pension/src/forms/OldAgePensionForm.ts index 2d086a88fa4f..cf01c8a2b190 100644 --- a/libs/application/templates/social-insurance-administration/old-age-pension/src/forms/OldAgePensionForm.ts +++ b/libs/application/templates/social-insurance-administration/old-age-pension/src/forms/OldAgePensionForm.ts @@ -39,10 +39,7 @@ import { NO, YES, } from '@island.is/application/types' -import { - applicantInformationMultiField, - buildFormConclusionSection, -} from '@island.is/application/ui-forms' +import { applicantInformationMultiField } from '@island.is/application/ui-forms' import isEmpty from 'lodash/isEmpty' import { ApplicationType, Employment, RatioType } from '../lib/constants' import { oldAgePensionFormMessage } from '../lib/messages' @@ -787,27 +784,32 @@ export const OldAgePensionForm: Form = buildForm({ }), ], }), - buildFormConclusionSection({ - multiFieldTitle: - socialInsuranceAdministrationMessage.conclusionScreen - .receivedAwaitingIncomePlanTitle, - alertTitle: - socialInsuranceAdministrationMessage.conclusionScreen - .receivedAwaitingIncomePlanTitle, - alertMessage: - socialInsuranceAdministrationMessage.conclusionScreen - .incomePlanAlertMessage, - alertType: 'warning', - expandableDescription: - oldAgePensionFormMessage.conclusionScreen.bulletList, - expandableIntro: oldAgePensionFormMessage.conclusionScreen.nextStepsText, - bottomButtonLink: 'https://minarsidur.tr.is/forsendur/tekjuaetlun', - bottomButtonLabel: - socialInsuranceAdministrationMessage.conclusionScreen - .incomePlanCardLabel, - bottomButtonMessage: - socialInsuranceAdministrationMessage.conclusionScreen - .incomePlanCardText, + buildSection({ + id: 'conclusionSection', + title: socialInsuranceAdministrationMessage.conclusionScreen.section, + children: [ + buildMultiField({ + id: 'conclusion.multifield', + title: (application: Application) => { + const { hasIncomePlanStatus } = getApplicationExternalData( + application.externalData, + ) + return hasIncomePlanStatus + ? socialInsuranceAdministrationMessage.conclusionScreen + .receivedTitle + : socialInsuranceAdministrationMessage.conclusionScreen + .receivedAwaitingIncomePlanTitle + }, + children: [ + buildCustomField({ + component: 'Conclusion', + id: 'conclusion', + title: '', + description: '', + }), + ], + }), + ], }), ], }) diff --git a/libs/application/templates/social-insurance-administration/old-age-pension/src/forms/Prerequisites.ts b/libs/application/templates/social-insurance-administration/old-age-pension/src/forms/Prerequisites.ts index e614d43380c3..66bb30ca3601 100644 --- a/libs/application/templates/social-insurance-administration/old-age-pension/src/forms/Prerequisites.ts +++ b/libs/application/templates/social-insurance-administration/old-age-pension/src/forms/Prerequisites.ts @@ -35,6 +35,7 @@ import { SocialInsuranceAdministrationIsApplicantEligibleApi, SocialInsuranceAdministrationApplicantApi, SocialInsuranceAdministrationCurrenciesApi, + SocialInsuranceAdministrationLatestIncomePlan, } from '../dataProviders' export const PrerequisitesForm: Form = buildForm({ @@ -163,6 +164,10 @@ export const PrerequisitesForm: Form = buildForm({ provider: SocialInsuranceAdministrationCurrenciesApi, title: '', }), + buildDataProviderItem({ + provider: SocialInsuranceAdministrationLatestIncomePlan, + title: '', + }), ], }), ], 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 eb2343ca151d..493e6f50f44b 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 @@ -38,6 +38,7 @@ import { SocialInsuranceAdministrationIsApplicantEligibleApi, SocialInsuranceAdministrationApplicantApi, SocialInsuranceAdministrationCurrenciesApi, + SocialInsuranceAdministrationLatestIncomePlan, } from '../dataProviders' import { determineNameFromApplicationAnswers, @@ -97,6 +98,7 @@ const OldAgePensionTemplate: ApplicationTemplate< SocialInsuranceAdministrationIsApplicantEligibleApi, SocialInsuranceAdministrationApplicantApi, SocialInsuranceAdministrationCurrenciesApi, + SocialInsuranceAdministrationLatestIncomePlan, ], delete: true, }, 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 47a792a7f72c..4ecdcbc26838 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 @@ -261,6 +261,18 @@ export const oldAgePensionFormMessage: MessageDir = { }), conclusionScreen: defineMessages({ + title: { + id: 'oap.application:conclusionScreen.expandableDescriptionField.title', + defaultMessage: 'Hvað gerist næst?', + description: 'What happens next', + }, + alertMessage: { + id: 'oap.application:conclusionScreen.alertMessage', + defaultMessage: + 'Umsókn um ellilífeyri hefur verið send til Tryggingastofnunar', + description: + 'An application for old age pension has been sent to the Social Insurance Administration', + }, bulletList: { id: `oap.application:conclusionScreen.bulletList#markdown`, defaultMessage: `* Þú verður að skila inn tekjuáætlun, ef ekki búið nú þegar.\n* Tryggingastofnun fer yfir umsóknina og staðfestir að allar upplýsingar eru réttar.\n* Ef þörf er á er kallað eftir frekari upplýsingum/gögnum.\n* Þegar öll nauðsynleg gögn hafa borist, fer Tryggingastofnun yfir umsókn og er afstaða tekin til elllífeyris. Vinnslutími umsókna um ellilífeyri er fjórar til sex vikur.\n* **Þú gætir átt rétt á:**\n\t* Heimilisuppbót\n\t* Barnalífeyri\n\t* Uppbót á lífeyri\n\t* Ellilífeyri vegna EES.`, diff --git a/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/oldAgePensionUtils.ts b/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/oldAgePensionUtils.ts index 7ddec140d8ad..23dc874ee38f 100644 --- a/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/oldAgePensionUtils.ts +++ b/libs/application/templates/social-insurance-administration/old-age-pension/src/lib/oldAgePensionUtils.ts @@ -254,6 +254,11 @@ export const getApplicationExternalData = ( 'socialInsuranceAdministrationCurrencies.data', ) as Array + const hasIncomePlanStatus = getValueViaPath( + externalData, + 'socialInsuranceAdministrationLatestIncomePlan.data.status', + ) as string + return { residenceHistory, applicantName, @@ -268,6 +273,7 @@ export const getApplicationExternalData = ( currencies, userProfileEmail, userProfilePhoneNumber, + hasIncomePlanStatus, } } diff --git a/libs/application/types/src/lib/Fields.ts b/libs/application/types/src/lib/Fields.ts index 877dc89d4621..f89d41400fcf 100644 --- a/libs/application/types/src/lib/Fields.ts +++ b/libs/application/types/src/lib/Fields.ts @@ -783,6 +783,7 @@ export interface DisplayField extends BaseField { titleVariant?: TitleVariants suffix?: MessageDescriptor | string rightAlign?: boolean + halfWidthOwnline?: boolean variant?: TextFieldVariant label?: MessageDescriptor | string value: (answers: FormValue) => string diff --git a/libs/application/ui-fields/src/lib/DisplayFormField/DisplayFormField.tsx b/libs/application/ui-fields/src/lib/DisplayFormField/DisplayFormField.tsx index ae6faba48fed..58e29e6d6bcf 100644 --- a/libs/application/ui-fields/src/lib/DisplayFormField/DisplayFormField.tsx +++ b/libs/application/ui-fields/src/lib/DisplayFormField/DisplayFormField.tsx @@ -21,6 +21,7 @@ export const DisplayFormField = ({ field, application }: Props) => { variant, suffix, rightAlign = false, + halfWidthOwnline = false, } = field const { watch, setValue } = useFormContext() const allValues = watch() @@ -29,52 +30,66 @@ export const DisplayFormField = ({ field, application }: Props) => { useEffect(() => { const newDisplayValue = value(allValues) - setDisplayValue(newDisplayValue) - setValue(id, newDisplayValue) + if (newDisplayValue !== displayValue) { + setDisplayValue(newDisplayValue) + setValue(id, newDisplayValue) + } }, [allValues]) return ( - - {title ? ( - - {formatTextWithLocale( - title, - application, - locale as Locale, - formatMessage, - )} - - ) : null} + + + {title ? ( + + {formatTextWithLocale( + title, + application, + locale as Locale, + formatMessage, + )} + + ) : null} - + + ) } diff --git a/libs/application/ui-forms/src/lib/formConclusionSection/formConclusionSection.ts b/libs/application/ui-forms/src/lib/formConclusionSection/formConclusionSection.ts index 28f3428b7347..fc5669aaee68 100644 --- a/libs/application/ui-forms/src/lib/formConclusionSection/formConclusionSection.ts +++ b/libs/application/ui-forms/src/lib/formConclusionSection/formConclusionSection.ts @@ -18,6 +18,7 @@ type Props = Partial<{ secondButtonLink: StaticText secondButtonLabel: StaticText secondButtonMessage: StaticText + accordion?: boolean expandableHeader: FormText expandableIntro: FormText expandableDescription: FormText @@ -38,6 +39,7 @@ type Props = Partial<{ * @param alertMessage The message inside the green alert box. * @param alertType The type of alert, can be success, warning, error, info. * JUST ADDED * * @param multiFieldTitle Title of the conclusion section. * JUST ADDED * + * @param accordion If false, there will be no accordion. * @param expandableHeader Header of the expandable description section. * @param expandableIntro Intro text of the expandable description section. * @param expandableDescription Markdown code for the expandable description section, most applications use bulletpoints. @@ -54,6 +56,7 @@ export const buildFormConclusionSection = ({ alertMessage = conclusion.alertMessageField.message, alertType = 'success', multiFieldTitle = conclusion.information.formTitle, + accordion = true, expandableHeader = conclusion.expandableDescriptionField.title, expandableIntro = conclusion.expandableDescriptionField.introText, expandableDescription = conclusion.expandableDescriptionField.description, @@ -64,8 +67,20 @@ export const buildFormConclusionSection = ({ bottomButtonLink = '/minarsidur/umsoknir', bottomButtonLabel = coreMessages.openServicePortalButtonTitle, bottomButtonMessage = coreMessages.openServicePortalMessageText, -}: Props) => - buildSection({ +}: Props) => { + const expandableDescriptionField = accordion + ? [ + buildExpandableDescriptionField({ + id: 'uiForms.conclusionExpandableDescription', + title: expandableHeader, + introText: expandableIntro, + description: expandableDescription, + startExpanded: true, + }), + ] + : [] + + return buildSection({ id: 'uiForms.conclusionSection', title: sectionTitle, children: [ @@ -88,13 +103,7 @@ export const buildFormConclusionSection = ({ alertType: alertType, message: alertMessage, }), - buildExpandableDescriptionField({ - id: 'uiForms.conclusionExpandableDescription', - title: expandableHeader, - introText: expandableIntro, - description: expandableDescription, - startExpanded: true, - }), + ...expandableDescriptionField, buildMessageWithLinkButtonField({ id: 'uiForms.conclusionBottomLink', title: '', @@ -107,3 +116,4 @@ export const buildFormConclusionSection = ({ }), ], }) +} diff --git a/libs/auth-api-lib/src/lib/delegations/admin/delegation-admin-custom.service.ts b/libs/auth-api-lib/src/lib/delegations/admin/delegation-admin-custom.service.ts index 5cbb11d913b5..e1de9e93df1a 100644 --- a/libs/auth-api-lib/src/lib/delegations/admin/delegation-admin-custom.service.ts +++ b/libs/auth-api-lib/src/lib/delegations/admin/delegation-admin-custom.service.ts @@ -12,6 +12,7 @@ import { TicketStatus, ZendeskService, } from '@island.is/clients/zendesk' +import { CompanyRegistryClientService } from '@island.is/clients/rsk/company-registry' import { Delegation } from '../models/delegation.model' import { DelegationAdminCustomDto } from '../dto/delegation-admin-custom.dto' @@ -45,6 +46,7 @@ export class DelegationAdminCustomService { private delegationScopeService: DelegationScopeService, private namesService: NamesService, private sequelize: Sequelize, + private rskCompanyInfoService: CompanyRegistryClientService, ) {} private getZendeskCustomFields(ticket: Ticket): { @@ -276,9 +278,7 @@ export class DelegationAdminCustomService { }) } - if ( - !(kennitala.isPerson(fromNationalId) && kennitala.isPerson(toNationalId)) - ) { + if (!kennitala.isPerson(toNationalId)) { throw new BadRequestException({ message: 'National Ids are not valid', error: ErrorCodes.INPUT_VALIDATION_INVALID_PERSON, @@ -300,7 +300,11 @@ export class DelegationAdminCustomService { }, ): Promise { const [fromDisplayName, toName] = await Promise.all([ - this.namesService.getPersonName(delegation.fromNationalId), + kennitala.isPerson(delegation.fromNationalId) + ? this.namesService.getPersonName(delegation.fromNationalId) + : this.rskCompanyInfoService + .getCompany(delegation.fromNationalId) + .then((company) => company?.name ?? ''), this.namesService.getPersonName(delegation.toNationalId), ]) @@ -310,6 +314,7 @@ export class DelegationAdminCustomService { { fromNationalId: delegation.fromNationalId, toNationalId: delegation.toNationalId, + domainName: null, }, { referenceId: delegation.referenceId, diff --git a/libs/auth-api-lib/src/lib/delegations/delegation-scope.service.ts b/libs/auth-api-lib/src/lib/delegations/delegation-scope.service.ts index d12b1d8af8e4..bb74ed0a4d6e 100644 --- a/libs/auth-api-lib/src/lib/delegations/delegation-scope.service.ts +++ b/libs/auth-api-lib/src/lib/delegations/delegation-scope.service.ts @@ -5,6 +5,7 @@ import addDays from 'date-fns/addDays' import startOfDay from 'date-fns/startOfDay' import { Op, Transaction } from 'sequelize' import { uuid } from 'uuidv4' +import * as kennitala from 'kennitala' import { SyslumennService } from '@island.is/clients/syslumenn' import { logger } from '@island.is/logging' @@ -209,7 +210,14 @@ export class DelegationScopeService { { model: ApiScopeDelegationType, where: { - delegationType: AuthDelegationType.GeneralMandate, + delegationType: { + [Op.or]: kennitala.isCompany(fromNationalId) + ? [ + AuthDelegationType.GeneralMandate, + AuthDelegationType.ProcurationHolder, + ] + : [AuthDelegationType.GeneralMandate], + }, }, }, ], diff --git a/libs/auth-api-lib/src/lib/delegations/delegations-incoming-custom.service.ts b/libs/auth-api-lib/src/lib/delegations/delegations-incoming-custom.service.ts index ee60fb61c692..e11e509095bd 100644 --- a/libs/auth-api-lib/src/lib/delegations/delegations-incoming-custom.service.ts +++ b/libs/auth-api-lib/src/lib/delegations/delegations-incoming-custom.service.ts @@ -196,17 +196,48 @@ export class DelegationsIncomingCustomService { ) } + /** + * Finds all companies that have a general mandate for the user. + * @param user + * @param clientAllowedApiScopes + * @param requireApiScopes + */ + async findCompanyGeneralMandate( + user: User, + clientAllowedApiScopes: ApiScopeInfo[], + requireApiScopes: boolean, + ): Promise { + const delegations = await this.findAllAvailableGeneralMandate( + user, + clientAllowedApiScopes, + requireApiScopes, + [AuthDelegationType.ProcurationHolder], + ) + + return delegations.filter((d) => kennitala.isCompany(d.fromNationalId)) + } + + /** + * Finds all individuals that have a general mandate for the user. + * @param user + * @param clientAllowedApiScopes + * @param requireApiScopes + * @param supportedDelegationTypes + */ async findAllAvailableGeneralMandate( user: User, clientAllowedApiScopes: ApiScopeInfo[], requireApiScopes: boolean, + supportedDelegationTypes = [AuthDelegationType.GeneralMandate], ): Promise { const customApiScopes = clientAllowedApiScopes.filter( (s) => !s.isAccessControlled && this.filterByCustomScopeRule(s) && - s.supportedDelegationTypes?.some( - (dt) => dt.delegationType === AuthDelegationType.GeneralMandate, + s.supportedDelegationTypes?.some((dt) => + supportedDelegationTypes.includes( + dt.delegationType as AuthDelegationType, + ), ), ) diff --git a/libs/auth-api-lib/src/lib/delegations/delegations-incoming.service.ts b/libs/auth-api-lib/src/lib/delegations/delegations-incoming.service.ts index b2e0775d3b48..05ddc050ee0f 100644 --- a/libs/auth-api-lib/src/lib/delegations/delegations-incoming.service.ts +++ b/libs/auth-api-lib/src/lib/delegations/delegations-incoming.service.ts @@ -176,6 +176,25 @@ export class DelegationsIncomingService { ) } + // If procuration holder is enabled, we need to get the general mandate delegations + if (types?.includes(AuthDelegationType.ProcurationHolder)) { + const isGeneralMandateDelegationEnabled = + await this.featureFlagService.getValue( + Features.isGeneralMandateDelegationEnabled, + false, + user, + ) + if (isGeneralMandateDelegationEnabled) { + delegationPromises.push( + this.delegationsIncomingCustomService.findCompanyGeneralMandate( + user, + clientAllowedApiScopes, + client.requireApiScopes, + ), + ) + } + } + if (providers.includes(AuthDelegationProvider.CompanyRegistry)) { delegationPromises.push( this.incomingDelegationsCompanyService @@ -293,6 +312,11 @@ export class DelegationsIncomingService { new Map(), ) + // Remove duplicate delegationTypes.. + mergedDelegationMap.forEach((delegation) => { + delegation.types = Array.from(new Set(delegation.types)) + }) + return [...mergedDelegationMap.values()] } diff --git a/libs/auth-api-lib/src/lib/delegations/names.service.ts b/libs/auth-api-lib/src/lib/delegations/names.service.ts index 463f412a1ffd..43a87f8dcb9c 100644 --- a/libs/auth-api-lib/src/lib/delegations/names.service.ts +++ b/libs/auth-api-lib/src/lib/delegations/names.service.ts @@ -6,7 +6,7 @@ import { createEnhancedFetch, EnhancedFetchAPI, } from '@island.is/clients/middlewares' -import { NationalRegistryClientService } from '@island.is/clients/national-registry-v2' +import { NationalRegistryV3ClientService } from '@island.is/clients/national-registry-v3' import { DelegationConfig } from './DelegationConfig' @@ -17,7 +17,7 @@ export class NamesService { constructor( @Inject(DelegationConfig.KEY) private delegationConfig: ConfigType, - private nationalRegistryClient: NationalRegistryClientService, + private nationalRegistryClient: NationalRegistryV3ClientService, ) { this.authFetch = createEnhancedFetch({ name: 'delegation-auth-client' }) } @@ -32,12 +32,14 @@ export class NamesService { } async getPersonName(nationalId: string) { - const person = await this.nationalRegistryClient.getIndividual(nationalId) + const person = await this.nationalRegistryClient.getAllDataIndividual( + nationalId, + ) if (!person) { throw new BadRequestException( `A person with nationalId<${nationalId}> could not be found`, ) } - return person.fullName ?? person.name + return person.nafn ?? '' } } diff --git a/libs/clients/documents-v2/src/lib/dto/listDocuments.input.ts b/libs/clients/documents-v2/src/lib/dto/listDocuments.input.ts index 3070a27c91ba..5da074477c8e 100644 --- a/libs/clients/documents-v2/src/lib/dto/listDocuments.input.ts +++ b/libs/clients/documents-v2/src/lib/dto/listDocuments.input.ts @@ -8,7 +8,7 @@ export type ListDocumentsInputDto = { typeId?: string subjectContains?: string archived?: boolean - sortBy?: 'Date' | 'Category' | 'Type' | 'Sender' | 'Subject' + sortBy?: 'Date' | 'Category' | 'Type' | 'Sender' | 'Subject' | 'Publication' order?: 'Ascending' | 'Descending' opened?: boolean page?: number diff --git a/libs/clients/documents/src/lib/documentClient.ts b/libs/clients/documents/src/lib/documentClient.ts index 476024d24c5a..6b9d130b18a7 100644 --- a/libs/clients/documents/src/lib/documentClient.ts +++ b/libs/clients/documents/src/lib/documentClient.ts @@ -133,7 +133,7 @@ export class DocumentClient { type ExcludesFalse = (x: T | null | undefined | false | '') => x is T const inputs = [ - sortBy ? `sortBy=${sortBy}` : 'sortBy=Date', // first in array to skip & + sortBy ? `sortBy=${sortBy}` : 'sortBy=Publication', // first in array to skip & order ? `orderBy=${order}` : 'order=Descending', page ? `page=${page}` : 'page=1', pageSize ? `pageSize=${pageSize}` : 'pageSize=15', diff --git a/libs/clients/documents/src/lib/models/DocumentInput.ts b/libs/clients/documents/src/lib/models/DocumentInput.ts index 59af47786535..35f861663e37 100644 --- a/libs/clients/documents/src/lib/models/DocumentInput.ts +++ b/libs/clients/documents/src/lib/models/DocumentInput.ts @@ -5,7 +5,7 @@ export type GetDocumentListInput = { categoryId?: string subjectContains?: string typeId?: string - sortBy?: 'Date' | 'Category' | 'Type' | 'Subject' | 'Sender' + sortBy?: 'Date' | 'Category' | 'Type' | 'Subject' | 'Sender' | 'Publication' order?: 'Ascending' | 'Descending' opened?: boolean archived?: boolean diff --git a/libs/cms/src/lib/generated/contentfulTypes.d.ts b/libs/cms/src/lib/generated/contentfulTypes.d.ts index aa7d3875ab85..368f8fc63417 100644 --- a/libs/cms/src/lib/generated/contentfulTypes.d.ts +++ b/libs/cms/src/lib/generated/contentfulTypes.d.ts @@ -2127,6 +2127,9 @@ export interface ILatestGenericListItemsFields { /** See more link text */ seeMoreLinkText?: string | undefined + + /** Item Count */ + itemCount?: number | undefined } export interface ILatestGenericListItems diff --git a/libs/cms/src/lib/models/latestGenericListItems.model.ts b/libs/cms/src/lib/models/latestGenericListItems.model.ts index 3fe7a7a43103..3a7b5b189285 100644 --- a/libs/cms/src/lib/models/latestGenericListItems.model.ts +++ b/libs/cms/src/lib/models/latestGenericListItems.model.ts @@ -80,7 +80,7 @@ export const mapLatestGenericListItems = ({ ? 'is' : (sys.locale as ElasticsearchIndexLocale), page: 1, - size: 2, + size: fields.itemCount ?? 2, } : null, }) diff --git a/libs/infra-tracing/jest.config.ts b/libs/infra-tracing/jest.config.ts index 408bf688f2da..d763876692e5 100644 --- a/libs/infra-tracing/jest.config.ts +++ b/libs/infra-tracing/jest.config.ts @@ -3,6 +3,7 @@ export default { preset: './jest.preset.js', rootDir: '../..', roots: [__dirname], + testEnvironment: 'node', transform: { '^.+\\.[tj]sx?$': [ 'ts-jest', diff --git a/libs/infra-tracing/project.json b/libs/infra-tracing/project.json index ea0b7fb854da..0d44fc1d4663 100644 --- a/libs/infra-tracing/project.json +++ b/libs/infra-tracing/project.json @@ -3,7 +3,7 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "libs/infra-tracing/src", "projectType": "library", - "tags": ["scope:js", "lib:js"], + "tags": ["scope:node", "lib:node"], "generators": {}, "targets": { "lint": { diff --git a/libs/infra-tracing/src/index.ts b/libs/infra-tracing/src/index.ts index 911527568b58..fedc94d86666 100644 --- a/libs/infra-tracing/src/index.ts +++ b/libs/infra-tracing/src/index.ts @@ -1 +1,2 @@ export * from './lib/datadog-tracer' // must come before importing any instrumented module. +export * from './lib/code-owner' diff --git a/libs/infra-tracing/src/lib/code-owner.spec.ts b/libs/infra-tracing/src/lib/code-owner.spec.ts new file mode 100644 index 000000000000..ed860dbd7a97 --- /dev/null +++ b/libs/infra-tracing/src/lib/code-owner.spec.ts @@ -0,0 +1,49 @@ +import { setCodeOwner } from './code-owner' +import { CodeOwners } from '@island.is/shared/constants' +import { logger } from '@island.is/logging' +import tracer from 'dd-trace' + +jest.mock('dd-trace') +jest.mock('@island.is/logging') + +describe('setCodeOwner', () => { + let mockSpan: { setTag: jest.Mock } + let mockScope: jest.Mock + + beforeEach(() => { + mockSpan = { + setTag: jest.fn(), + } + mockScope = jest.fn(() => ({ + active: () => mockSpan, + })) + ;(tracer.scope as jest.Mock) = mockScope + ;(logger.warn as jest.Mock).mockClear() + }) + + it('should set code owner tag on active span', () => { + // Act + setCodeOwner(CodeOwners.Core) + + // Assert + expect(mockSpan.setTag).toHaveBeenCalledWith('codeOwner', CodeOwners.Core) + expect(logger.warn).not.toHaveBeenCalled() + }) + + it('should log warning when no active span exists', () => { + // Arrange + mockScope = jest.fn(() => ({ + active: () => null, + })) + ;(tracer.scope as jest.Mock) = mockScope + + // Act + setCodeOwner(CodeOwners.Core) + + // Assert + expect(logger.warn).toHaveBeenCalledWith( + 'Setting code owner "core" with no active dd-trace span', + { stack: expect.any(String) }, + ) + }) +}) diff --git a/libs/infra-tracing/src/lib/code-owner.ts b/libs/infra-tracing/src/lib/code-owner.ts new file mode 100644 index 000000000000..7d4d6352fe52 --- /dev/null +++ b/libs/infra-tracing/src/lib/code-owner.ts @@ -0,0 +1,22 @@ +import { logger } from '@island.is/logging' +import { CodeOwners } from '@island.is/shared/constants' +import tracer from 'dd-trace' + +/** + * Sets a code owner for the current dd-trace span. + * + * The assumption here is that each trace / request has only one "dynamic" + * code owner. This way we skip cluttering the trace with extra spans. + */ +export const setCodeOwner = (codeOwner: CodeOwners) => { + const span = tracer.scope().active() + if (span) { + span.setTag('codeOwner', codeOwner) + } else { + const stack = new Error().stack + logger.warn( + `Setting code owner "${codeOwner}" with no active dd-trace span`, + { stack }, + ) + } +} diff --git a/libs/infra-tracing/src/lib/datadog-tracer.ts b/libs/infra-tracing/src/lib/datadog-tracer.ts index e2b5516df49f..21a82abf4502 100644 --- a/libs/infra-tracing/src/lib/datadog-tracer.ts +++ b/libs/infra-tracing/src/lib/datadog-tracer.ts @@ -22,7 +22,12 @@ export const maskSpan = ( } if (process.env.NODE_ENV !== 'development') { - tracer.init({ logInjection: true }) // initialized in a different file to avoid hoisting. + tracer.init({ + logInjection: true, + tags: { + codeOwner: process.env.CODE_OWNER, + }, + }) // initialized in a different file to avoid hoisting. tracer.use('express', { blacklist: ['/liveness', '/readiness', '/metrics'], hooks: { diff --git a/libs/island-ui/core/src/lib/Header/Header.css.ts b/libs/island-ui/core/src/lib/Header/Header.css.ts index cf8a3492b455..c580b98e9c28 100644 --- a/libs/island-ui/core/src/lib/Header/Header.css.ts +++ b/libs/island-ui/core/src/lib/Header/Header.css.ts @@ -21,10 +21,14 @@ export const infoDescription = style({ fontWeight: 300, lineHeight: 1.5, fontSize: 14, + maxHeight: 40, + position: 'relative', + overflow: 'auto', ...themeUtils.responsiveStyle({ md: { fontSize: 18, + maxHeight: 66, }, }), }) diff --git a/libs/island-ui/core/src/lib/Header/Header.tsx b/libs/island-ui/core/src/lib/Header/Header.tsx index 15a28c13f892..1d6a01230f6d 100644 --- a/libs/island-ui/core/src/lib/Header/Header.tsx +++ b/libs/island-ui/core/src/lib/Header/Header.tsx @@ -93,6 +93,7 @@ export const Header = ({ height="full" marginLeft={[1, 1, 2, 4]} marginRight="auto" + paddingRight={[1, 1, 2, 4]} > {info.title} @@ -128,14 +129,14 @@ export const Header = ({ alignItems="center" justifyContent="spaceBetween" > - - {renderLogo()} + + {renderLogo()} {renderInfo()} - - + + {renderOldDropdown()} {headerItems} - + ) } diff --git a/libs/island-ui/core/src/lib/Hyphen/Hyphen.tsx b/libs/island-ui/core/src/lib/Hyphen/Hyphen.tsx index 9af8249a592e..d6f0a607b944 100644 --- a/libs/island-ui/core/src/lib/Hyphen/Hyphen.tsx +++ b/libs/island-ui/core/src/lib/Hyphen/Hyphen.tsx @@ -12,7 +12,7 @@ type HyphenateText = ( ) => string // TODO: import patterns dynamically -const hyphenateText: HyphenateText = ( +export const hyphenateText: HyphenateText = ( content, { minLeft, minRight, locale = 'is' }, ) => { diff --git a/libs/judicial-system/formatters/src/lib/formatters.ts b/libs/judicial-system/formatters/src/lib/formatters.ts index 7d9d260ddd88..91cc3013da3a 100644 --- a/libs/judicial-system/formatters/src/lib/formatters.ts +++ b/libs/judicial-system/formatters/src/lib/formatters.ts @@ -218,6 +218,29 @@ export const indictmentSubtypes: IndictmentSubtypes = { THEFT: 'þjófnaður', } +export const districtCourtAbbreviation = (courtName?: string | null) => { + switch (courtName) { + case 'Héraðsdómur Reykjavíkur': + return 'HDR' + case 'Héraðsdómur Reykjaness': + return 'HDRN' + case 'Héraðsdómur Vesturlands': + return 'HDV' + case 'Héraðsdómur Suðurlands': + return 'HDS' + case 'Héraðsdómur Norðurlands eystra': + return 'HDNE' + case 'Héraðsdómur Norðurlands vestra': + return 'HDNV' + case 'Héraðsdómur Austurlands': + return 'HDA' + case 'Héraðsdómur Vestfjarða': + return 'HDVF' + default: + return '' + } +} + export const getAppealResultTextByValue = ( value?: CaseAppealRulingDecision | null, ) => { diff --git a/libs/logging/jest.config.ts b/libs/logging/jest.config.ts index 4659aa0dfb12..181249a15e28 100644 --- a/libs/logging/jest.config.ts +++ b/libs/logging/jest.config.ts @@ -3,6 +3,7 @@ export default { preset: './jest.preset.js', rootDir: '../..', roots: [__dirname], + testEnvironment: 'node', transform: { '^.+\\.[tj]sx?$': [ 'ts-jest', diff --git a/libs/logging/src/index.ts b/libs/logging/src/index.ts index 5389a8fd32d0..dd7c324e92ad 100644 --- a/libs/logging/src/index.ts +++ b/libs/logging/src/index.ts @@ -1,4 +1,5 @@ export * from './lib/logging' export * from './lib/nest/logging.module' export * from './lib/monkeyPatch' +export { withLoggingContext } from './lib/context' export type { Logger } from './lib/nest/logging.module' diff --git a/libs/logging/src/lib/context.spec.ts b/libs/logging/src/lib/context.spec.ts new file mode 100644 index 000000000000..ca371ba27376 --- /dev/null +++ b/libs/logging/src/lib/context.spec.ts @@ -0,0 +1,77 @@ +import { includeContextFormatter, withLoggingContext } from './context' + +describe('Winston context', () => { + const originalEnv = process.env + + beforeEach(() => { + process.env = { ...originalEnv } + }) + + afterEach(() => { + process.env = originalEnv + }) + + it('should add context to log info object', () => { + // Arrange + const formatter = includeContextFormatter() + const logInfo = { + level: 'info', + message: 'Test message', + } + const context = { requestId: '123', userId: '456' } + + // Act + let formattedLog: unknown + withLoggingContext(context, () => { + formattedLog = formatter.transform(logInfo) + }) + + // Assert + expect(formattedLog).toEqual({ + level: 'info', + message: 'Test message', + requestId: '123', + userId: '456', + }) + }) + + it('should not modify log info when no context exists', () => { + // Arrange + const formatter = includeContextFormatter() + const logInfo = { + level: 'info', + message: 'Test message', + } + + // Act + const formattedLog = formatter.transform(logInfo) + + // Assert + expect(formattedLog).toEqual(logInfo) + }) + + it('should preserve existing log info properties when adding context', () => { + // Arrange + const formatter = includeContextFormatter() + const logInfo = { + level: 'info', + message: 'Test message', + existingProp: 'should remain', + } + const context = { requestId: '123' } + + // Act + let formattedLog: unknown + withLoggingContext(context, () => { + formattedLog = formatter.transform(logInfo) + }) + + // Assert + expect(formattedLog).toEqual({ + level: 'info', + message: 'Test message', + existingProp: 'should remain', + requestId: '123', + }) + }) +}) diff --git a/libs/logging/src/lib/context.ts b/libs/logging/src/lib/context.ts new file mode 100644 index 000000000000..03034f67d79d --- /dev/null +++ b/libs/logging/src/lib/context.ts @@ -0,0 +1,28 @@ +import { AsyncLocalStorage } from 'async_hooks' +import { format } from 'winston' + +const loggingContextStorage = new AsyncLocalStorage>() + +/** + * Adds context which will be included with all logging inside the callback. + */ +export const withLoggingContext = ( + context: Record, + callback: (...args: TArgs) => R, + ...args: TArgs +): R => { + const extendedContext = { + ...loggingContextStorage.getStore(), + ...context, + } + return loggingContextStorage.run(extendedContext, callback, ...args) +} + +export const includeContextFormatter = format((info) => { + const context = loggingContextStorage.getStore() + + if (context) { + Object.assign(info, context) + } + return info +}) diff --git a/libs/logging/src/lib/logging.ts b/libs/logging/src/lib/logging.ts index b250c005fa65..9576d3ab66bb 100644 --- a/libs/logging/src/lib/logging.ts +++ b/libs/logging/src/lib/logging.ts @@ -1,5 +1,6 @@ import { createLogger, format, LoggerOptions, transports } from 'winston' import { utilities } from 'nest-winston' +import { includeContextFormatter } from './context' import { maskNationalIdFormatter } from './formatters' @@ -8,6 +9,8 @@ let logLevel = 'debug' let logFormat = format.combine( format.errors({ stack: true }), format.timestamp(), + // Disable locally to reduce noise. Can be reconsidered. + // includeContextFormatter(), utilities.format.nestLike('App'), maskNationalIdFormatter(), ) @@ -18,6 +21,7 @@ if (process.env.NODE_ENV === 'production') { logFormat = format.combine( format.errors({ stack: true }), format.timestamp(), + includeContextFormatter(), format.json(), maskNationalIdFormatter(), ) diff --git a/libs/nest/core/src/index.ts b/libs/nest/core/src/index.ts index e6b84b1639ef..123d16158fc1 100644 --- a/libs/nest/core/src/index.ts +++ b/libs/nest/core/src/index.ts @@ -1,3 +1,5 @@ +export * from './lib/code-owner/code-owner.decorator' +export * from './lib/code-owner/code-owner.interceptor' export * from './lib/decorators/nationalId.decorator' export * from './lib/decorators/ParsedUserAgent.decorator' export * from './lib/validators/isPersonNationalId.decorator' diff --git a/libs/nest/core/src/lib/code-owner/code-owner.decorator.ts b/libs/nest/core/src/lib/code-owner/code-owner.decorator.ts new file mode 100644 index 000000000000..37d3f049fa03 --- /dev/null +++ b/libs/nest/core/src/lib/code-owner/code-owner.decorator.ts @@ -0,0 +1,7 @@ +import { SetMetadata } from '@nestjs/common' +import { CodeOwners } from '@island.is/shared/constants' + +export const CODE_OWNER_KEY = 'codeOwner' + +export const CodeOwner = (codeOwner: CodeOwners) => + SetMetadata(CODE_OWNER_KEY, codeOwner) diff --git a/libs/nest/core/src/lib/code-owner/code-owner.interceptor.spec.ts b/libs/nest/core/src/lib/code-owner/code-owner.interceptor.spec.ts new file mode 100644 index 000000000000..038802b02237 --- /dev/null +++ b/libs/nest/core/src/lib/code-owner/code-owner.interceptor.spec.ts @@ -0,0 +1,87 @@ +import { setCodeOwner } from '@island.is/infra-tracing' +import { CodeOwners } from '@island.is/shared/constants' +import { Controller, Get, INestApplication } from '@nestjs/common' +import { APP_INTERCEPTOR } from '@nestjs/core' +import { Test, TestingModule } from '@nestjs/testing' +import request from 'supertest' +import { CodeOwner } from './code-owner.decorator' +import { CodeOwnerInterceptor } from './code-owner.interceptor' + +// Mock the logging module +jest.mock('@island.is/infra-tracing', () => ({ + setCodeOwner: jest.fn(), +})) + +// Test controller with decorated endpoints +@Controller('test') +class TestController { + @CodeOwner(CodeOwners.Core) + @Get('with-owner') + getWithOwner() { + return { message: 'with owner' } + } + + @Get('without-owner') + getWithoutOwner() { + return { message: 'without owner' } + } +} + +describe('CodeOwnerInterceptor', () => { + let app: INestApplication + + beforeEach(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + controllers: [TestController], + providers: [ + { + provide: APP_INTERCEPTOR, + useClass: CodeOwnerInterceptor, + }, + ], + }).compile() + + app = moduleFixture.createNestApplication() + await app.init() + }) + + afterEach(async () => { + await app.close() + jest.clearAllMocks() + }) + + it('should call setCodeOwner when CodeOwner decorator is present', async () => { + // Make request to endpoint with CodeOwner decorator + await request(app.getHttpServer()) + .get('/test/with-owner') + .expect(200) + .expect({ message: 'with owner' }) + + // Verify that setCodeOwner was called with correct parameters + expect(setCodeOwner).toHaveBeenCalledWith(CodeOwners.Core) + }) + + it('should not call setCodeOwner when CodeOwner decorator is not present', async () => { + // Make request to endpoint without CodeOwner decorator + await request(app.getHttpServer()) + .get('/test/without-owner') + .expect(200) + .expect({ message: 'without owner' }) + + // Verify that setCodeOwner was not called + expect(setCodeOwner).not.toHaveBeenCalled() + }) + + it('should handle multiple requests correctly', async () => { + // Make multiple requests to both endpoints + await Promise.all([ + request(app.getHttpServer()).get('/test/with-owner'), + request(app.getHttpServer()).get('/test/without-owner'), + request(app.getHttpServer()).get('/test/with-owner'), + ]) + + // Verify that setCodeOwner was called exactly twice (for the two 'with-owner' requests) + expect(setCodeOwner).toHaveBeenCalledTimes(2) + expect(setCodeOwner).toHaveBeenCalledWith(CodeOwners.Core) + }) +}) diff --git a/libs/nest/core/src/lib/code-owner/code-owner.interceptor.ts b/libs/nest/core/src/lib/code-owner/code-owner.interceptor.ts new file mode 100644 index 000000000000..a9f992fccbc6 --- /dev/null +++ b/libs/nest/core/src/lib/code-owner/code-owner.interceptor.ts @@ -0,0 +1,28 @@ +import { setCodeOwner } from '@island.is/infra-tracing' +import { CodeOwners } from '@island.is/shared/constants' +import { + Injectable, + NestInterceptor, + ExecutionContext, + CallHandler, +} from '@nestjs/common' +import { Reflector } from '@nestjs/core' +import { Observable } from 'rxjs' +import { CODE_OWNER_KEY } from './code-owner.decorator' + +@Injectable() +export class CodeOwnerInterceptor implements NestInterceptor { + constructor(private readonly reflector: Reflector) {} + + intercept(context: ExecutionContext, next: CallHandler): Observable { + const codeOwner = this.reflector.getAllAndOverride( + CODE_OWNER_KEY, + [context.getHandler(), context.getClass()], + ) + + if (codeOwner) { + setCodeOwner(codeOwner) + } + return next.handle() + } +} diff --git a/libs/nest/pagination/src/lib/paginate.ts b/libs/nest/pagination/src/lib/paginate.ts index e289af92c053..87410488a3f0 100644 --- a/libs/nest/pagination/src/lib/paginate.ts +++ b/libs/nest/pagination/src/lib/paginate.ts @@ -117,6 +117,7 @@ export interface PaginateInput { primaryKeyField: string orderOption: any where?: any + attributes?: any after: string before?: string limit: number @@ -138,6 +139,7 @@ export async function paginate({ after, before, limit, + attributes, ...queryArgs }: PaginateInput): Promise<{ totalCount: number @@ -164,6 +166,7 @@ export async function paginate({ where: paginationWhere, limit, order, + attributes, ...queryArgs, } diff --git a/libs/portals/admin/service-desk/src/lib/messages.ts b/libs/portals/admin/service-desk/src/lib/messages.ts index 8560dcf08ef2..9e9c4008fcfd 100644 --- a/libs/portals/admin/service-desk/src/lib/messages.ts +++ b/libs/portals/admin/service-desk/src/lib/messages.ts @@ -65,6 +65,14 @@ export const m = defineMessages({ id: 'admin-portal.service-desk:info', defaultMessage: 'Upplýsingar: ', }, + notifications: { + id: 'admin-portal.service-desk:notifications', + defaultMessage: 'Tilkynningar: ', + }, + loadMore: { + id: 'admin-portal.service-desk:load-more', + defaultMessage: 'Sjá meira', + }, email: { id: 'admin-portal.service-desk:email', defaultMessage: 'Netfang', diff --git a/libs/portals/admin/service-desk/src/screens/User/User.graphql b/libs/portals/admin/service-desk/src/screens/User/User.graphql index 1d65b549f8b6..dd1f8410069b 100644 --- a/libs/portals/admin/service-desk/src/screens/User/User.graphql +++ b/libs/portals/admin/service-desk/src/screens/User/User.graphql @@ -32,3 +32,24 @@ mutation UpdateUserProfile( locale } } + +query GetAdminNotifications($nationalId: String!, $input: NotificationsInput!) { + adminNotifications(nationalId: $nationalId, input: $input) { + data { + id + notificationId + sender { + id + logoUrl + } + sent + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + totalCount + } +} diff --git a/libs/portals/admin/service-desk/src/screens/User/User.tsx b/libs/portals/admin/service-desk/src/screens/User/User.tsx index 7b16758ac36a..3a132e6512df 100644 --- a/libs/portals/admin/service-desk/src/screens/User/User.tsx +++ b/libs/portals/admin/service-desk/src/screens/User/User.tsx @@ -1,18 +1,34 @@ import format from 'date-fns/format' import { useLoaderData, useNavigate, useRevalidator } from 'react-router-dom' -import { ActionCard, Box, Stack, Text } from '@island.is/island-ui/core' +import { + ActionCard, + Box, + Stack, + Text, + Table as T, + LoadingDots, + SkeletonLoader, +} from '@island.is/island-ui/core' import { useLocale } from '@island.is/localization' import { BackButton } from '@island.is/portals/admin/core' import { IntroHeader, formatNationalId } from '@island.is/portals/core' import { dateFormat } from '@island.is/shared/constants' +import InfiniteScroll from 'react-infinite-scroller' -import { ServiceDeskPaths } from '../../lib/paths' -import { UserProfileResult } from './User.loader' import { m } from '../../lib/messages' -import { useUpdateUserProfileMutation } from './User.generated' +import { + GetAdminNotificationsQuery, + useUpdateUserProfileMutation, +} from './User.generated' import { UpdateUserProfileInput } from '@island.is/api/schema' import React from 'react' +import { isValidDate } from '@island.is/shared/utils' +import { useGetAdminNotificationsQuery } from './User.generated' +import { UserProfileResult } from './User.loader' +import { Problem } from '@island.is/react-spa/shared' + +const DEFAULT_PAGE_SIZE = 10 const User = () => { const { formatMessage } = useLocale() @@ -22,6 +38,18 @@ const User = () => { const [updateProfile] = useUpdateUserProfileMutation() const { revalidate } = useRevalidator() + const { + data: notifications, + loading, + error, + fetchMore, + } = useGetAdminNotificationsQuery({ + variables: { + nationalId: user.nationalId, + input: { limit: DEFAULT_PAGE_SIZE }, + }, + }) + const handleUpdateProfile = async (input: UpdateUserProfileInput) => { try { const updatedProfile = await updateProfile({ @@ -39,6 +67,38 @@ const User = () => { } } + const loadMore = async () => { + if ( + loading || + !notifications || + !notifications?.adminNotifications?.pageInfo.hasNextPage + ) { + return + } + + await fetchMore({ + variables: { + nationalId: user.nationalId, + input: { + limit: DEFAULT_PAGE_SIZE, + after: + notifications?.adminNotifications?.pageInfo.endCursor ?? undefined, + }, + }, + updateQuery: (prev, { fetchMoreResult }): GetAdminNotificationsQuery => { + return { + adminNotifications: { + ...fetchMoreResult.adminNotifications, + data: [ + ...(prev.adminNotifications?.data || []), + ...(fetchMoreResult.adminNotifications?.data || []), + ], + } as GetAdminNotificationsQuery['adminNotifications'], + } + }, + }) + } + return ( { + + {formatMessage(m.notifications)} + {error ? ( + + ) : loading ? ( + + ) : ( + + + + } + > + + + + ID + Message ID + Sender ID + Sent + + + + {notifications?.adminNotifications?.data.map( + (notification, index) => ( + + {notification.id} + {notification.notificationId} + {notification.sender.id} + + {notification.sent && + isValidDate(new Date(notification.sent)) + ? format(new Date(notification.sent), 'dd.MM.yyyy') + : ''} + + + ), + )} + + + + )} + ) } diff --git a/libs/portals/admin/service-desk/src/screens/Users/Users.action.ts b/libs/portals/admin/service-desk/src/screens/Users/Users.action.ts index 13454e204aaa..bfe8cbfb1104 100644 --- a/libs/portals/admin/service-desk/src/screens/Users/Users.action.ts +++ b/libs/portals/admin/service-desk/src/screens/Users/Users.action.ts @@ -1,23 +1,20 @@ import { z } from 'zod' -import { redirect } from 'react-router-dom' import { RawRouterActionResponse, WrappedActionFn, } from '@island.is/portals/core' import { - replaceParams, validateFormData, ValidateFormDataResult, } from '@island.is/react-spa/shared' -import { maskString, isSearchTermValid } from '@island.is/shared/utils' +import { isSearchTermValid } from '@island.is/shared/utils' import { GetPaginatedUserProfilesDocument, GetPaginatedUserProfilesQuery, type GetPaginatedUserProfilesQueryVariables, } from './Users.generated' -import { ServiceDeskPaths } from '../../lib/paths' export enum ErrorType { // Add more error types here when needed diff --git a/libs/shared/constants/src/index.ts b/libs/shared/constants/src/index.ts index 01420ce59242..925b5464be6e 100644 --- a/libs/shared/constants/src/index.ts +++ b/libs/shared/constants/src/index.ts @@ -1,5 +1,6 @@ export * from './lib/agent' export * from './lib/cacheControl' +export * from './lib/codeOwners' export * from './lib/locale' export * from './lib/date' export * from './lib/chargeItemCode' diff --git a/libs/shared/constants/src/lib/codeOwners.ts b/libs/shared/constants/src/lib/codeOwners.ts new file mode 100644 index 000000000000..912e323b0b61 --- /dev/null +++ b/libs/shared/constants/src/lib/codeOwners.ts @@ -0,0 +1,18 @@ +/** + * Codeowners for different projects. Should match github team names used in .github/CODEOWNERS. + */ +export enum CodeOwners { + Advania = 'Advania', + Aranja = 'aranja', + Core = 'core', + Deloitte = 'deloitte', + Devops = 'devops', + Hugsmidjan = 'hugsmidjan', + Juni = 'juni', + KolibriJusticeLeague = 'kolibri-justice-league', + KolibriRobinHood = 'kolibri-robin-hood', + NordaApplications = 'norda-applications', + Origo = 'origo', + Programm = 'programm', + Stefna = 'stefna', +} diff --git a/libs/shared/form-fields/src/lib/SelectController/SelectController.tsx b/libs/shared/form-fields/src/lib/SelectController/SelectController.tsx index d5ec6a74d63d..06639d1913c8 100644 --- a/libs/shared/form-fields/src/lib/SelectController/SelectController.tsx +++ b/libs/shared/form-fields/src/lib/SelectController/SelectController.tsx @@ -1,7 +1,12 @@ import React from 'react' import { Controller, useFormContext, RegisterOptions } from 'react-hook-form' -import { Select, Option, InputBackgroundColor } from '@island.is/island-ui/core' +import { + Select, + SelectProps, + Option, + InputBackgroundColor, +} from '@island.is/island-ui/core' import { TestSupport } from '@island.is/island-ui/utils' import { MultiValue, SingleValue } from 'react-select' @@ -26,6 +31,7 @@ interface SelectControllerProps { rules?: RegisterOptions size?: 'xs' | 'sm' | 'md' internalKey?: string + filterConfig?: SelectProps['filterConfig'] } export const SelectController = ({ @@ -47,6 +53,7 @@ export const SelectController = ({ rules, size, internalKey, + filterConfig, }: SelectControllerProps & TestSupport) => { const { clearErrors } = useFormContext() @@ -91,6 +98,7 @@ export const SelectController = ({ placeholder={placeholder} value={getValue(value)} isSearchable={isSearchable} + filterConfig={filterConfig} isMulti={isMulti} isClearable={isClearable} size={size}