From 10560f2e57ed85b634c2469897aa13bcb9486805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9E=C3=B3r=C3=B0ur=20H?= Date: Tue, 29 Oct 2024 13:26:22 +0000 Subject: [PATCH 01/28] fix(service-portal): no longer req poststod for name display (#16598) * no longer req poststod, for name display * poststod * fallback --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../src/lib/shared/models/address.model.ts | 4 ++-- libs/api/domains/national-registry/src/lib/v3/mapper.ts | 4 ++-- .../national-registry/src/lib/v3/types/user.type.ts | 2 +- libs/service-portal/information/src/helpers/formatting.ts | 8 +++++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/libs/api/domains/national-registry/src/lib/shared/models/address.model.ts b/libs/api/domains/national-registry/src/lib/shared/models/address.model.ts index bae36887f35d..50daacbc1e4f 100644 --- a/libs/api/domains/national-registry/src/lib/shared/models/address.model.ts +++ b/libs/api/domains/national-registry/src/lib/shared/models/address.model.ts @@ -16,8 +16,8 @@ export class Address { @Field(() => String, { nullable: true }) apartment?: string | null - @Field(() => String) - city!: string + @Field(() => String, { nullable: true }) + city?: string | null @Field(() => String, { nullable: true }) postalCode?: string | null diff --git a/libs/api/domains/national-registry/src/lib/v3/mapper.ts b/libs/api/domains/national-registry/src/lib/v3/mapper.ts index 20b097a8a8ad..fd3535dbc32c 100644 --- a/libs/api/domains/national-registry/src/lib/v3/mapper.ts +++ b/libs/api/domains/national-registry/src/lib/v3/mapper.ts @@ -170,7 +170,7 @@ export const formatSpouse = ( export const formatAddress = ( address?: EinstaklingurDTOHeimili | null, ): Address | null => { - if (!address || !address.husHeiti || !address.poststod) { + if (!address || !address.husHeiti) { return null } @@ -178,7 +178,7 @@ export const formatAddress = ( streetAddress: address.husHeiti, postalCode: address.postnumer ?? null, apartment: address.ibud ?? null, - city: address.poststod, + city: address.poststod ?? null, municipalityText: address.sveitarfelag ?? null, } } diff --git a/libs/api/domains/national-registry/src/lib/v3/types/user.type.ts b/libs/api/domains/national-registry/src/lib/v3/types/user.type.ts index 417877dee7d1..77cca6e7ed6b 100644 --- a/libs/api/domains/national-registry/src/lib/v3/types/user.type.ts +++ b/libs/api/domains/national-registry/src/lib/v3/types/user.type.ts @@ -24,7 +24,7 @@ export interface User { code?: string | null lastUpdated?: string | null streetAddress?: string | null - city: string + city?: string | null postalCode?: string | null } | null birthPlace: { diff --git a/libs/service-portal/information/src/helpers/formatting.ts b/libs/service-portal/information/src/helpers/formatting.ts index b819b252ea97..4cb0a28f4064 100644 --- a/libs/service-portal/information/src/helpers/formatting.ts +++ b/libs/service-portal/information/src/helpers/formatting.ts @@ -34,9 +34,11 @@ export const formatAddress = ( ): string | undefined => { if (!address) return undefined - if (address.streetAddress === address.city) { - return address.streetAddress + const { streetAddress = '', city = '', postalCode = '' } = address + + if (streetAddress && (streetAddress === city || (!postalCode && !city))) { + return streetAddress } - return `${address.streetAddress}, ${address.postalCode} ${address.city}` + return `${streetAddress}, ${postalCode} ${city}` } From b86cd042facb1a9f3083e8c2b3d4f27a092e8ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3hanna=20Magn=C3=BAsd=C3=B3ttir?= Date: Tue, 29 Oct 2024 13:50:15 +0000 Subject: [PATCH 02/28] fix(haskolagatt): Remove obsolete program course code (#16604) * Dropping Course table and all code related to Program Course * Cleanup --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- apps/services/university-gateway/README.md | 2 +- .../migrations/20241024081539-drop-courses.js | 135 ++++++++++++++++++ .../program/internalProgram.service.ts | 1 - .../modules/program/model/programCourse.ts | 93 ------------ .../app/modules/program/program.controller.ts | 2 +- .../app/modules/program/program.service.ts | 2 - .../src/app/worker/worker.module.ts | 2 - .../src/lib/graphql/models/program.model.ts | 42 ------ ...lturalUniversityOfIcelandClient.service.ts | 28 +--- .../src/lib/apiConfiguration.ts | 4 +- .../src/lib/apiConfiguration.ts | 4 +- .../lib/bifrostUniversityClient.service.ts | 29 +--- .../src/lib/apiConfiguration.ts | 4 +- .../src/lib/holarUniversityClient.service.ts | 28 +--- .../src/lib/apiConfiguration.ts | 4 +- ...celandUniversityOfTheArtsClient.service.ts | 28 +--- .../lib/reykjavikUniversityClient.service.ts | 60 -------- .../src/lib/apiConfiguration.ts | 4 +- .../lib/universityOfAkureyriClient.service.ts | 28 +--- .../university-of-iceland/src/index.ts | 1 - .../src/lib/apiConfiguration.ts | 55 ++++--- .../lib/universityOfIcelandClient.service.ts | 21 +-- .../src/lib/utils/mapUglaApplication.ts | 2 +- .../src/lib/utils/mapUglaCourses.ts | 84 ----------- libs/university-gateway/src/index.ts | 2 - .../src/lib/model/course.ts | 16 --- .../src/lib/types/requirement.ts | 5 - .../src/lib/types/season.ts | 8 -- 28 files changed, 194 insertions(+), 500 deletions(-) create mode 100644 apps/services/university-gateway/migrations/20241024081539-drop-courses.js delete mode 100644 apps/services/university-gateway/src/app/modules/program/model/programCourse.ts delete mode 100644 libs/clients/university-application/university-of-iceland/src/lib/utils/mapUglaCourses.ts delete mode 100644 libs/university-gateway/src/lib/model/course.ts delete mode 100644 libs/university-gateway/src/lib/types/requirement.ts diff --git a/apps/services/university-gateway/README.md b/apps/services/university-gateway/README.md index dec62e77f33e..53f7f806ef4c 100644 --- a/apps/services/university-gateway/README.md +++ b/apps/services/university-gateway/README.md @@ -47,7 +47,7 @@ yarn nx run services-university-gateway:codegen/backend-schema ### Worker -This service is for running scheduled tasks. Currently, fetching programs and courses from university APIs and adding data to out database. +This service is for running scheduled tasks. Currently, fetching programs from university APIs and adding data to out database. ## Running locally diff --git a/apps/services/university-gateway/migrations/20241024081539-drop-courses.js b/apps/services/university-gateway/migrations/20241024081539-drop-courses.js new file mode 100644 index 000000000000..5fb30f6c96f0 --- /dev/null +++ b/apps/services/university-gateway/migrations/20241024081539-drop-courses.js @@ -0,0 +1,135 @@ +'use strict' + +module.exports = { + async up(queryInterface) { + return queryInterface.sequelize.transaction(async (transaction) => { + await queryInterface.dropTable('program_course', { transaction }) + await queryInterface.dropTable('course', { transaction }) + }) + }, + + async down(queryInterface, Sequelize) { + return queryInterface.sequelize.transaction(async (t) => { + await queryInterface.createTable( + 'course', + { + id: { + type: Sequelize.UUID, + primaryKey: true, + allowNull: false, + defaultValue: Sequelize.UUIDV4, + }, + external_id: { + type: Sequelize.STRING, + allowNull: false, + }, + name_is: { + type: Sequelize.STRING, + allowNull: false, + }, + name_en: { + type: Sequelize.STRING, + allowNull: false, + }, + university_id: { + type: Sequelize.UUID, + references: { + model: 'university', + key: 'id', + }, + allowNull: false, + }, + credits: { + type: Sequelize.FLOAT, + allowNull: false, + }, + description_is: { + type: Sequelize.TEXT, + allowNull: true, + }, + description_en: { + type: Sequelize.TEXT, + allowNull: true, + }, + external_url_is: { + type: Sequelize.STRING(500), + allowNull: true, + }, + external_url_en: { + type: Sequelize.STRING(500), + allowNull: true, + }, + created: { + type: Sequelize.DATE, + allowNull: false, + }, + modified: { + type: Sequelize.DATE, + allowNull: false, + }, + }, + { transaction: t }, + ) + + await queryInterface.createTable( + 'program_course', + { + id: { + type: Sequelize.UUID, + primaryKey: true, + defaultValue: Sequelize.UUIDV4, + allowNull: false, + }, + program_id: { + type: Sequelize.UUID, + references: { + model: 'program', + key: 'id', + }, + allowNull: false, + }, + course_id: { + type: Sequelize.UUID, + onDelete: 'CASCADE', + references: { + model: 'course', + key: 'id', + }, + allowNull: false, + }, + requirement: { + type: Sequelize.ENUM( + 'MANDATORY', + 'FREE_ELECTIVE', + 'RESTRICTED_ELECTIVE', + ), + allowNull: false, + }, + semester_year: { + type: Sequelize.INTEGER, + allowNull: true, + }, + semester_season: { + type: Sequelize.ENUM( + 'FALL', + 'SPRING', + 'SUMMER', + 'WHOLE_YEAR', + 'ANY', + ), + allowNull: false, + }, + created: { + type: Sequelize.DATE, + allowNull: false, + }, + modified: { + type: Sequelize.DATE, + allowNull: false, + }, + }, + { transaction: t }, + ) + }) + }, +} diff --git a/apps/services/university-gateway/src/app/modules/program/internalProgram.service.ts b/apps/services/university-gateway/src/app/modules/program/internalProgram.service.ts index 0daffc39bb5e..c0fac39e58c3 100644 --- a/apps/services/university-gateway/src/app/modules/program/internalProgram.service.ts +++ b/apps/services/university-gateway/src/app/modules/program/internalProgram.service.ts @@ -161,7 +161,6 @@ export class InternalProgramService { specializationNameIs: specialization?.nameIs, specializationNameEn: specialization?.nameEn, universityId, - courses: [], modeOfDelivery: [], extraApplicationFields: [], } diff --git a/apps/services/university-gateway/src/app/modules/program/model/programCourse.ts b/apps/services/university-gateway/src/app/modules/program/model/programCourse.ts deleted file mode 100644 index 3c8982b91f1b..000000000000 --- a/apps/services/university-gateway/src/app/modules/program/model/programCourse.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { - ApiHideProperty, - ApiProperty, - ApiPropertyOptional, -} from '@nestjs/swagger' -import { - BelongsTo, - Column, - CreatedAt, - DataType, - ForeignKey, - Model, - Table, - UpdatedAt, -} from 'sequelize-typescript' -import { Program } from './program' -import { CourseSeason, Requirement } from '@island.is/university-gateway' -import { - CreationOptional, - InferAttributes, - InferCreationAttributes, -} from 'sequelize' - -@Table({ - tableName: 'program_course', -}) -export class ProgramCourse extends Model< - InferAttributes, - InferCreationAttributes -> { - @ApiHideProperty() - @Column({ - type: DataType.UUID, - primaryKey: true, - defaultValue: DataType.UUIDV4, - allowNull: false, - }) - id!: CreationOptional - - @ApiHideProperty() - @Column({ - type: DataType.UUID, - allowNull: false, - }) - @ForeignKey(() => Program) - programId!: string - - @ApiHideProperty() - @BelongsTo(() => Program, 'programId') - program?: Program - - @ApiProperty({ - description: 'Whether the course is required or not', - example: Requirement.MANDATORY, - enum: Requirement, - }) - @Column({ - type: DataType.ENUM, - values: Object.values(Requirement), - allowNull: false, - }) - requirement!: Requirement - - @ApiPropertyOptional({ - description: 'Which year this course is taught on', - example: 2023, - }) - @Column({ - type: DataType.INTEGER, - allowNull: true, - }) - semesterYear?: number - - @ApiProperty({ - description: 'Which season this course is taught on', - example: CourseSeason.FALL, - enum: CourseSeason, - }) - @Column({ - type: DataType.ENUM, - values: Object.values(CourseSeason), - allowNull: false, - }) - semesterSeason!: CourseSeason - - @ApiHideProperty() - @CreatedAt - readonly created!: CreationOptional - - @ApiHideProperty() - @UpdatedAt - readonly modified!: CreationOptional -} diff --git a/apps/services/university-gateway/src/app/modules/program/program.controller.ts b/apps/services/university-gateway/src/app/modules/program/program.controller.ts index 3363bac3e7dd..61f72b53edd5 100644 --- a/apps/services/university-gateway/src/app/modules/program/program.controller.ts +++ b/apps/services/university-gateway/src/app/modules/program/program.controller.ts @@ -183,7 +183,7 @@ export class ProgramController { @BypassAuth() @Get('programs/:id') @Documentation({ - description: 'Get program (and courses) by ID', + description: 'Get program by ID', response: { status: 200, type: Program, diff --git a/apps/services/university-gateway/src/app/modules/program/program.service.ts b/apps/services/university-gateway/src/app/modules/program/program.service.ts index 3d29dbf480e6..033fd8210cc5 100644 --- a/apps/services/university-gateway/src/app/modules/program/program.service.ts +++ b/apps/services/university-gateway/src/app/modules/program/program.service.ts @@ -61,7 +61,6 @@ export class ProgramService { 'costInformationIs', 'costInformationEn', 'allowThirdLevelQualification', - 'courses', 'extraApplicationFields', ], }, @@ -154,7 +153,6 @@ export class ProgramService { 'costPerYear', 'iscedCode', 'tmpActive', - 'courses', ], }, include: [ diff --git a/apps/services/university-gateway/src/app/worker/worker.module.ts b/apps/services/university-gateway/src/app/worker/worker.module.ts index 5f9dd2076471..8975954022a9 100644 --- a/apps/services/university-gateway/src/app/worker/worker.module.ts +++ b/apps/services/university-gateway/src/app/worker/worker.module.ts @@ -37,7 +37,6 @@ import { environment } from '../../environments' import { InternalProgramService } from '../modules/program/internalProgram.service' import { InternalApplicationService } from '../modules/application/internalApplication.service' import { University } from '../modules/university/model/university' -import { ProgramCourse } from '../modules/program/model/programCourse' import { ProgramModeOfDelivery } from '../modules/program/model/programModeOfDelivery' import { Program } from '../modules/program/model/program' import { ProgramExtraApplicationField } from '../modules/program/model/programExtraApplicationField' @@ -58,7 +57,6 @@ import { Application } from '../modules/application/model/application' Program, ProgramModeOfDelivery, ProgramExtraApplicationField, - ProgramCourse, Application, ]), ReykjavikUniversityApplicationClientModule, diff --git a/libs/api/domains/university-gateway/src/lib/graphql/models/program.model.ts b/libs/api/domains/university-gateway/src/lib/graphql/models/program.model.ts index 6698dbd5d9d3..e7743bb79252 100644 --- a/libs/api/domains/university-gateway/src/lib/graphql/models/program.model.ts +++ b/libs/api/domains/university-gateway/src/lib/graphql/models/program.model.ts @@ -143,48 +143,6 @@ export class UniversityGatewayProgramDetails extends UniversityGatewayProgram { extraApplicationFields!: UniversityGatewayProgramExtraApplicationField[] } -@ObjectType('UniversityGatewayProgramCourse') -class UniversityGatewayProgramCourse { - @Field() - id!: string - - @Field() - externalId!: string - - @Field() - nameIs!: string - - @Field() - nameEn!: string - - @Field() - credits!: number - - @Field({ nullable: true }) - semesterYear?: number - - @Field({ nullable: true }) - semesterYearNumber?: number - - @Field() - semesterSeason!: string - - @Field({ nullable: true }) - descriptionIs?: string - - @Field({ nullable: true }) - descriptionEn?: string - - @Field({ nullable: true }) - externalUrlIs?: string - - @Field({ nullable: true }) - externalUrlEn?: string - - @Field() - requirement!: string -} - @ObjectType('UniversityGatewayProgramExtraApplicationField') class UniversityGatewayProgramExtraApplicationField { @Field() diff --git a/libs/clients/university-application/agricultural-university-of-iceland/src/lib/agriculturalUniversityOfIcelandClient.service.ts b/libs/clients/university-application/agricultural-university-of-iceland/src/lib/agriculturalUniversityOfIcelandClient.service.ts index 78dd6f764631..296527640b9e 100644 --- a/libs/clients/university-application/agricultural-university-of-iceland/src/lib/agriculturalUniversityOfIcelandClient.service.ts +++ b/libs/clients/university-application/agricultural-university-of-iceland/src/lib/agriculturalUniversityOfIcelandClient.service.ts @@ -1,36 +1,16 @@ import { Injectable } from '@nestjs/common' -import { CoursesApi, ProgramsApi } from '../../gen/fetch/apis' -import { ICourse, IProgram } from '@island.is/university-gateway' +import { ProgramsApi } from '../../gen/fetch/apis' +import { IProgram } from '@island.is/university-gateway' import { logger } from '@island.is/logging' -import { - mapUglaPrograms, - mapUglaCourses, -} from '@island.is/clients/university-application/university-of-iceland' +import { mapUglaPrograms } from '@island.is/clients/university-application/university-of-iceland' @Injectable() export class AgriculturalUniversityOfIcelandApplicationClient { - constructor( - private readonly programsApi: ProgramsApi, - private readonly coursesApi: CoursesApi, - ) {} + constructor(private readonly programsApi: ProgramsApi) {} async getPrograms(): Promise { const res = await this.programsApi.activeProgramsGet() return mapUglaPrograms(res, 'agricultural-university-of-iceland') } - - async getCourses(programExternalId: string): Promise { - const res = await this.coursesApi.programExternalIdCoursesGet({ - externalId: programExternalId, - // specializationExternalId // TODO missing in api - }) - - return mapUglaCourses(res, (courseExternalId: string, e: Error) => { - logger.error( - `Failed to map course with externalId ${courseExternalId} for program with externalId ${programExternalId} (agricultural-university-of-iceland), reason:`, - e, - ) - }) - } } diff --git a/libs/clients/university-application/agricultural-university-of-iceland/src/lib/apiConfiguration.ts b/libs/clients/university-application/agricultural-university-of-iceland/src/lib/apiConfiguration.ts index 69c373f66d56..3f041e4a822d 100644 --- a/libs/clients/university-application/agricultural-university-of-iceland/src/lib/apiConfiguration.ts +++ b/libs/clients/university-application/agricultural-university-of-iceland/src/lib/apiConfiguration.ts @@ -4,7 +4,7 @@ import { IdsClientConfig, XRoadConfig, } from '@island.is/nest/config' -import { Configuration, CoursesApi, ProgramsApi } from '../../gen/fetch' +import { Configuration, ProgramsApi } from '../../gen/fetch' import { AgriculturalUniversityOfIcelandApplicationClientConfig } from './agriculturalUniversityOfIcelandClient.config' const configFactory = ( @@ -35,7 +35,7 @@ const configFactory = ( basePath, }) -export const exportedApis = [ProgramsApi, CoursesApi].map((Api) => ({ +export const exportedApis = [ProgramsApi].map((Api) => ({ provide: Api, useFactory: ( xRoadConfig: ConfigType, diff --git a/libs/clients/university-application/bifrost-university/src/lib/apiConfiguration.ts b/libs/clients/university-application/bifrost-university/src/lib/apiConfiguration.ts index c889d3c09872..5d6b6e826994 100644 --- a/libs/clients/university-application/bifrost-university/src/lib/apiConfiguration.ts +++ b/libs/clients/university-application/bifrost-university/src/lib/apiConfiguration.ts @@ -4,7 +4,7 @@ import { IdsClientConfig, XRoadConfig, } from '@island.is/nest/config' -import { Configuration, CoursesApi, ProgramsApi } from '../../gen/fetch' +import { Configuration, ProgramsApi } from '../../gen/fetch' import { BifrostUniversityApplicationClientConfig } from './bifrostUniversityClient.config' const configFactory = ( @@ -33,7 +33,7 @@ const configFactory = ( basePath, }) -export const exportedApis = [ProgramsApi, CoursesApi].map((Api) => ({ +export const exportedApis = [ProgramsApi].map((Api) => ({ provide: Api, useFactory: ( xRoadConfig: ConfigType, diff --git a/libs/clients/university-application/bifrost-university/src/lib/bifrostUniversityClient.service.ts b/libs/clients/university-application/bifrost-university/src/lib/bifrostUniversityClient.service.ts index e249643e0ea0..333c7c76cc8d 100644 --- a/libs/clients/university-application/bifrost-university/src/lib/bifrostUniversityClient.service.ts +++ b/libs/clients/university-application/bifrost-university/src/lib/bifrostUniversityClient.service.ts @@ -1,36 +1,15 @@ import { Injectable } from '@nestjs/common' -import { CoursesApi, ProgramsApi } from '../../gen/fetch/apis' -import { ICourse, IProgram } from '@island.is/university-gateway' -import { logger } from '@island.is/logging' -import { - mapUglaPrograms, - mapUglaCourses, -} from '@island.is/clients/university-application/university-of-iceland' +import { ProgramsApi } from '../../gen/fetch/apis' +import { IProgram } from '@island.is/university-gateway' +import { mapUglaPrograms } from '@island.is/clients/university-application/university-of-iceland' @Injectable() export class BifrostUniversityApplicationClient { - constructor( - private readonly programsApi: ProgramsApi, - private readonly coursesApi: CoursesApi, - ) {} + constructor(private readonly programsApi: ProgramsApi) {} async getPrograms(): Promise { const res = await this.programsApi.activeProgramsGet() return mapUglaPrograms(res, 'bifrost-university') } - - async getCourses(programExternalId: string): Promise { - const res = await this.coursesApi.programExternalIdCoursesGet({ - externalId: programExternalId, - // specializationExternalId // TODO missing in api - }) - - return mapUglaCourses(res, (courseExternalId: string, e: Error) => { - logger.error( - `Failed to map course with externalId ${courseExternalId} for program with externalId ${programExternalId} (bifrost-university), reason:`, - e, - ) - }) - } } diff --git a/libs/clients/university-application/holar-university/src/lib/apiConfiguration.ts b/libs/clients/university-application/holar-university/src/lib/apiConfiguration.ts index e5b3761408aa..4bd520388020 100644 --- a/libs/clients/university-application/holar-university/src/lib/apiConfiguration.ts +++ b/libs/clients/university-application/holar-university/src/lib/apiConfiguration.ts @@ -4,7 +4,7 @@ import { IdsClientConfig, XRoadConfig, } from '@island.is/nest/config' -import { Configuration, CoursesApi, ProgramsApi } from '../../gen/fetch' +import { Configuration, ProgramsApi } from '../../gen/fetch' import { HolarUniversityApplicationClientConfig } from './holarUniversityClient.config' const configFactory = ( @@ -33,7 +33,7 @@ const configFactory = ( basePath, }) -export const exportedApis = [ProgramsApi, CoursesApi].map((Api) => ({ +export const exportedApis = [ProgramsApi].map((Api) => ({ provide: Api, useFactory: ( xRoadConfig: ConfigType, diff --git a/libs/clients/university-application/holar-university/src/lib/holarUniversityClient.service.ts b/libs/clients/university-application/holar-university/src/lib/holarUniversityClient.service.ts index d1786670124c..6b669f3332cc 100644 --- a/libs/clients/university-application/holar-university/src/lib/holarUniversityClient.service.ts +++ b/libs/clients/university-application/holar-university/src/lib/holarUniversityClient.service.ts @@ -1,36 +1,16 @@ import { Injectable } from '@nestjs/common' -import { CoursesApi, ProgramsApi } from '../../gen/fetch/apis' -import { ICourse, IProgram } from '@island.is/university-gateway' +import { ProgramsApi } from '../../gen/fetch/apis' +import { IProgram } from '@island.is/university-gateway' import { logger } from '@island.is/logging' -import { - mapUglaPrograms, - mapUglaCourses, -} from '@island.is/clients/university-application/university-of-iceland' +import { mapUglaPrograms } from '@island.is/clients/university-application/university-of-iceland' @Injectable() export class HolarUniversityApplicationClient { - constructor( - private readonly programsApi: ProgramsApi, - private readonly coursesApi: CoursesApi, - ) {} + constructor(private readonly programsApi: ProgramsApi) {} async getPrograms(): Promise { const res = await this.programsApi.activeProgramsGet() return mapUglaPrograms(res, 'holar-university') } - - async getCourses(programExternalId: string): Promise { - const res = await this.coursesApi.programExternalIdCoursesGet({ - externalId: programExternalId, - // specializationExternalId // TODO missing in api - }) - - return mapUglaCourses(res, (courseExternalId: string, e: Error) => { - logger.error( - `Failed to map course with externalId ${courseExternalId} for program with externalId ${programExternalId} (holar-university), reason:`, - e, - ) - }) - } } diff --git a/libs/clients/university-application/iceland-university-of-the-arts/src/lib/apiConfiguration.ts b/libs/clients/university-application/iceland-university-of-the-arts/src/lib/apiConfiguration.ts index 55fc1abe7ab7..9a41a03978a7 100644 --- a/libs/clients/university-application/iceland-university-of-the-arts/src/lib/apiConfiguration.ts +++ b/libs/clients/university-application/iceland-university-of-the-arts/src/lib/apiConfiguration.ts @@ -4,7 +4,7 @@ import { IdsClientConfig, XRoadConfig, } from '@island.is/nest/config' -import { Configuration, CoursesApi, ProgramsApi } from '../../gen/fetch' +import { Configuration, ProgramsApi } from '../../gen/fetch' import { IcelandUniversityOfTheArtsApplicationClientConfig } from './icelandUniversityOfTheArtsClient.config' const configFactory = ( @@ -33,7 +33,7 @@ const configFactory = ( basePath, }) -export const exportedApis = [ProgramsApi, CoursesApi].map((Api) => ({ +export const exportedApis = [ProgramsApi].map((Api) => ({ provide: Api, useFactory: ( xRoadConfig: ConfigType, diff --git a/libs/clients/university-application/iceland-university-of-the-arts/src/lib/icelandUniversityOfTheArtsClient.service.ts b/libs/clients/university-application/iceland-university-of-the-arts/src/lib/icelandUniversityOfTheArtsClient.service.ts index 2cd4ca3041bb..cd25ee257998 100644 --- a/libs/clients/university-application/iceland-university-of-the-arts/src/lib/icelandUniversityOfTheArtsClient.service.ts +++ b/libs/clients/university-application/iceland-university-of-the-arts/src/lib/icelandUniversityOfTheArtsClient.service.ts @@ -1,36 +1,16 @@ import { Injectable } from '@nestjs/common' -import { CoursesApi, ProgramsApi } from '../../gen/fetch/apis' -import { ICourse, IProgram } from '@island.is/university-gateway' +import { ProgramsApi } from '../../gen/fetch/apis' +import { IProgram } from '@island.is/university-gateway' import { logger } from '@island.is/logging' -import { - mapUglaPrograms, - mapUglaCourses, -} from '@island.is/clients/university-application/university-of-iceland' +import { mapUglaPrograms } from '@island.is/clients/university-application/university-of-iceland' @Injectable() export class IcelandUniversityOfTheArtsApplicationClient { - constructor( - private readonly programsApi: ProgramsApi, - private readonly coursesApi: CoursesApi, - ) {} + constructor(private readonly programsApi: ProgramsApi) {} async getPrograms(): Promise { const res = await this.programsApi.activeProgramsGet() return mapUglaPrograms(res, 'iceland-university-of-the-arts') } - - async getCourses(programExternalId: string): Promise { - const res = await this.coursesApi.programExternalIdCoursesGet({ - externalId: programExternalId, - // specializationExternalId // TODO missing in api - }) - - return mapUglaCourses(res, (courseExternalId: string, e: Error) => { - logger.error( - `Failed to map course with externalId ${courseExternalId} for program with externalId ${programExternalId} (iceland-university-of-the-arts), reason:`, - e, - ) - }) - } } diff --git a/libs/clients/university-application/reykjavik-university/src/lib/reykjavikUniversityClient.service.ts b/libs/clients/university-application/reykjavik-university/src/lib/reykjavikUniversityClient.service.ts index ba9fb6a6cac2..559beae57679 100644 --- a/libs/clients/university-application/reykjavik-university/src/lib/reykjavikUniversityClient.service.ts +++ b/libs/clients/university-application/reykjavik-university/src/lib/reykjavikUniversityClient.service.ts @@ -9,14 +9,11 @@ import { } from '../../gen/fetch' import { ApplicationStatus, - CourseSeason, DegreeType, FieldType, IApplication, - ICourse, IProgram, ModeOfDelivery, - Requirement, Season, mapStringToEnum, EnumError, @@ -114,63 +111,6 @@ export class ReykjavikUniversityApplicationClient { return mappedRes } - async getCourses(externalId: string): Promise { - const res = await this.hvinApi.hvinActivePrograms({ version: '1' }) - - const program = res.find((p) => p.externalId === externalId) - - if (!program) { - throw new Error('Did not find program for courses by program external id') - } - - const mappedRes = [] - const courseList = program.courses || [] - for (let i = 0; i < courseList.length; i++) { - const course = courseList[i] - try { - let semesterSeason: CourseSeason | undefined = undefined - // TODO what value is this - if (course.semesterSeason === 'NOTSET') { - semesterSeason = CourseSeason.ANY - } else { - semesterSeason = mapStringToEnum( - course.semesterSeason, - CourseSeason, - 'CourseSeason', - ) - } - if (!semesterSeason) { - throw new Error( - `Not able to map semester season: ${course.semesterSeason?.toString()}`, - ) - } - - mappedRes.push({ - externalId: course.externalId || '', - nameIs: course.nameIs || '', - nameEn: course.nameEn || '', - credits: course.credits || 0, - descriptionIs: course.descriptionIs, - descriptionEn: course.descriptionEn, - externalUrlIs: course.externalUrlIs, - externalUrlEn: course.externalUrlEn, - requirement: course.required - ? Requirement.MANDATORY - : Requirement.FREE_ELECTIVE, //TODO missing in api - semesterYear: course.semesterYear, - semesterSeason: semesterSeason, - }) - } catch (e) { - logger.error( - `Failed to map course with externalId ${course.externalId} for program with externalId ${externalId} (reykjavik-university), reason:`, - e, - ) - } - } - - return mappedRes - } - async getApplicationStatus(externalId: string): Promise { const application = await this.hvinApi.hvinGetApplicationById({ id: Number(externalId), diff --git a/libs/clients/university-application/university-of-akureyri/src/lib/apiConfiguration.ts b/libs/clients/university-application/university-of-akureyri/src/lib/apiConfiguration.ts index 8255e3239219..eee21e84ba3b 100644 --- a/libs/clients/university-application/university-of-akureyri/src/lib/apiConfiguration.ts +++ b/libs/clients/university-application/university-of-akureyri/src/lib/apiConfiguration.ts @@ -4,7 +4,7 @@ import { IdsClientConfig, XRoadConfig, } from '@island.is/nest/config' -import { Configuration, CoursesApi, ProgramsApi } from '../../gen/fetch' +import { Configuration, ProgramsApi } from '../../gen/fetch' import { UniversityOfAkureyriApplicationClientConfig } from './universityOfAkureyriClient.config' const configFactory = ( @@ -33,7 +33,7 @@ const configFactory = ( basePath, }) -export const exportedApis = [ProgramsApi, CoursesApi].map((Api) => ({ +export const exportedApis = [ProgramsApi].map((Api) => ({ provide: Api, useFactory: ( xRoadConfig: ConfigType, diff --git a/libs/clients/university-application/university-of-akureyri/src/lib/universityOfAkureyriClient.service.ts b/libs/clients/university-application/university-of-akureyri/src/lib/universityOfAkureyriClient.service.ts index fd3cb7005a97..615c518a5568 100644 --- a/libs/clients/university-application/university-of-akureyri/src/lib/universityOfAkureyriClient.service.ts +++ b/libs/clients/university-application/university-of-akureyri/src/lib/universityOfAkureyriClient.service.ts @@ -1,36 +1,16 @@ import { Injectable } from '@nestjs/common' -import { CoursesApi, ProgramsApi } from '../../gen/fetch/apis' -import { ICourse, IProgram } from '@island.is/university-gateway' +import { ProgramsApi } from '../../gen/fetch/apis' +import { IProgram } from '@island.is/university-gateway' import { logger } from '@island.is/logging' -import { - mapUglaPrograms, - mapUglaCourses, -} from '@island.is/clients/university-application/university-of-iceland' +import { mapUglaPrograms } from '@island.is/clients/university-application/university-of-iceland' @Injectable() export class UniversityOfAkureyriApplicationClient { - constructor( - private readonly programsApi: ProgramsApi, - private readonly coursesApi: CoursesApi, - ) {} + constructor(private readonly programsApi: ProgramsApi) {} async getPrograms(): Promise { const res = await this.programsApi.activeProgramsGet() return mapUglaPrograms(res, 'university-of-akureyri') } - - async getCourses(programExternalId: string): Promise { - const res = await this.coursesApi.programExternalIdCoursesGet({ - externalId: programExternalId, - // specializationExternalId // TODO missing in api - }) - - return mapUglaCourses(res, (courseExternalId: string, e: Error) => { - logger.error( - `Failed to map course with externalId ${courseExternalId} for program with externalId ${programExternalId} (university-of-akureyri), reason:`, - e, - ) - }) - } } diff --git a/libs/clients/university-application/university-of-iceland/src/index.ts b/libs/clients/university-application/university-of-iceland/src/index.ts index 8ead803a509b..585572de5c3e 100644 --- a/libs/clients/university-application/university-of-iceland/src/index.ts +++ b/libs/clients/university-application/university-of-iceland/src/index.ts @@ -3,4 +3,3 @@ export { UniversityOfIcelandApplicationClientConfig } from './lib/universityOfIc export { UniversityOfIcelandApplicationClient } from './lib/universityOfIcelandClient.service' export { mapUglaPrograms } from './lib/utils/mapUglaPrograms' -export { mapUglaCourses } from './lib/utils/mapUglaCourses' diff --git a/libs/clients/university-application/university-of-iceland/src/lib/apiConfiguration.ts b/libs/clients/university-application/university-of-iceland/src/lib/apiConfiguration.ts index 6c43735a67e6..dfe844cfd4b1 100644 --- a/libs/clients/university-application/university-of-iceland/src/lib/apiConfiguration.ts +++ b/libs/clients/university-application/university-of-iceland/src/lib/apiConfiguration.ts @@ -4,12 +4,7 @@ import { IdsClientConfig, XRoadConfig, } from '@island.is/nest/config' -import { - ApplicationApi, - Configuration, - CoursesApi, - ProgramsApi, -} from '../../gen/fetch' +import { ApplicationApi, Configuration, ProgramsApi } from '../../gen/fetch' import { UniversityOfIcelandApplicationClientConfig } from './universityOfIcelandClient.config' const configFactory = ( @@ -38,29 +33,27 @@ const configFactory = ( basePath, }) -export const exportedApis = [ProgramsApi, CoursesApi, ApplicationApi].map( - (Api) => ({ - provide: Api, - useFactory: ( - xRoadConfig: ConfigType, - config: ConfigType, - idsClientConfig: ConfigType, - ) => { - return new Api( - new Configuration( - configFactory( - xRoadConfig, - config, - idsClientConfig, - `${xRoadConfig.xRoadBasePath}/r1/${config.xroadPath}`, - ), +export const exportedApis = [ProgramsApi, ApplicationApi].map((Api) => ({ + provide: Api, + useFactory: ( + xRoadConfig: ConfigType, + config: ConfigType, + idsClientConfig: ConfigType, + ) => { + return new Api( + new Configuration( + configFactory( + xRoadConfig, + config, + idsClientConfig, + `${xRoadConfig.xRoadBasePath}/r1/${config.xroadPath}`, ), - ) - }, - inject: [ - XRoadConfig.KEY, - UniversityOfIcelandApplicationClientConfig.KEY, - IdsClientConfig.KEY, - ], - }), -) + ), + ) + }, + inject: [ + XRoadConfig.KEY, + UniversityOfIcelandApplicationClientConfig.KEY, + IdsClientConfig.KEY, + ], +})) diff --git a/libs/clients/university-application/university-of-iceland/src/lib/universityOfIcelandClient.service.ts b/libs/clients/university-application/university-of-iceland/src/lib/universityOfIcelandClient.service.ts index 9906779aa65e..8337fbb4b3aa 100644 --- a/libs/clients/university-application/university-of-iceland/src/lib/universityOfIcelandClient.service.ts +++ b/libs/clients/university-application/university-of-iceland/src/lib/universityOfIcelandClient.service.ts @@ -1,14 +1,12 @@ import { Injectable } from '@nestjs/common' -import { ApplicationApi, CoursesApi, ProgramsApi } from '../../gen/fetch/apis' +import { ApplicationApi, ProgramsApi } from '../../gen/fetch/apis' import { ApplicationStatus, IApplication, - ICourse, IProgram, } from '@island.is/university-gateway' import { logger } from '@island.is/logging' import { mapUglaPrograms } from './utils/mapUglaPrograms' -import { mapUglaCourses } from './utils/mapUglaCourses' import { mapUglaApplication } from './utils/mapUglaApplication' import { InlineResponse2004 } from '../../gen/fetch' @@ -16,7 +14,6 @@ import { InlineResponse2004 } from '../../gen/fetch' export class UniversityOfIcelandApplicationClient { constructor( private readonly programsApi: ProgramsApi, - private readonly coursesApi: CoursesApi, private readonly applicationApi: ApplicationApi, ) {} @@ -26,20 +23,6 @@ export class UniversityOfIcelandApplicationClient { return mapUglaPrograms(res, 'university-of-iceland') } - async getCourses(programExternalId: string): Promise { - const res = await this.coursesApi.programExternalIdCoursesGet({ - externalId: programExternalId, - // specializationExternalId // TODO missing in api - }) - - return mapUglaCourses(res, (courseExternalId: string, e: Error) => { - logger.error( - `Failed to map course with externalId ${courseExternalId} for program with externalId ${programExternalId} (university-of-iceland), reason:`, - e, - ) - }) - } - async getApplicationStatus(externalId: string): Promise { // TODOx connect to HÍ API return ApplicationStatus.IN_REVIEW @@ -50,7 +33,7 @@ export class UniversityOfIcelandApplicationClient { ): Promise { const mappedApplication = await mapUglaApplication( application, - (courseExternalId: string, e: Error) => { + (e: Error) => { logger.error( `Failed to map application for user ${application.applicant.nationalId} to University of Iceland, reason:`, e, diff --git a/libs/clients/university-application/university-of-iceland/src/lib/utils/mapUglaApplication.ts b/libs/clients/university-application/university-of-iceland/src/lib/utils/mapUglaApplication.ts index 46602aca0111..933ff9f1ddef 100644 --- a/libs/clients/university-application/university-of-iceland/src/lib/utils/mapUglaApplication.ts +++ b/libs/clients/university-application/university-of-iceland/src/lib/utils/mapUglaApplication.ts @@ -11,7 +11,7 @@ import { export const mapUglaApplication = async ( application: IApplication, - logError: (courseExternalId: string, error: Error) => void, + logError: (error: Error) => void, ): Promise => { const uglaApplication: ApplicationsPostRequest = { inlineObject: { diff --git a/libs/clients/university-application/university-of-iceland/src/lib/utils/mapUglaCourses.ts b/libs/clients/university-application/university-of-iceland/src/lib/utils/mapUglaCourses.ts deleted file mode 100644 index 2814c69ddf82..000000000000 --- a/libs/clients/university-application/university-of-iceland/src/lib/utils/mapUglaCourses.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { - CourseSeason, - ICourse, - Requirement, - mapStringToEnum, -} from '@island.is/university-gateway' -import { InlineResponse2003 } from '../../../gen/fetch' - -export const mapUglaCourses = ( - res: InlineResponse2003, - logError: (courseExternalId: string, error: Error) => void, -): ICourse[] => { - const mappedRes = [] - const courseList = res.data || [] - for (let i = 0; i < courseList.length; i++) { - const course = courseList[i] - try { - let requirement: Requirement | undefined = undefined - switch (course.required) { - case 'MANDATORY': - requirement = Requirement.MANDATORY - break - case 'ELECTIVE': - requirement = Requirement.FREE_ELECTIVE - break - case 'RESTRICTED_ELECTIVE': - requirement = Requirement.RESTRICTED_ELECTIVE - break - } - if (requirement === undefined) { - throw new Error(`Not able to map requirement: ${course.required}`) - } - - const semesterSeason = mapStringToEnum( - course.semesterSeason?.toString(), - CourseSeason, - 'CourseSeason', - ) - if (!semesterSeason) { - throw new Error( - `Not able to map semester season: ${course.semesterSeason?.toString()}`, - ) - } - - // Note: these fields are all array since we get "bundin skylda" as - // as array of courses. We will display them on out side are separate - // disconnected courses - const externalIdList = course.externalId || [] - const nameIsList = course.nameIs || [] - const nameEnList = course.nameEn || [] - const descriptionIsList = course.descriptionIs || [] - const descriptionEnList = course.descriptionEn || [] - const externalUrlIsList = course.externalUrlIs || [] - const externalUrlEnList = course.externalUrlEn || [] - - // If more than one item in the array, then this is a "bundin skylda". - // We need to set the requirement as RESTRICTED_ELECTIVE ("bundið val"), - // since there is not a requirement type for RESTRICTED_MANDATORY - if (externalIdList.length > 1) { - requirement = Requirement.RESTRICTED_ELECTIVE - } - - for (let i = 0; i < externalIdList.length; i++) { - mappedRes.push({ - externalId: externalIdList[i], - nameIs: nameIsList[i], - nameEn: nameEnList[i], - credits: Number(course.credits?.replace(',', '.')) || 0, - descriptionIs: descriptionIsList[i], - descriptionEn: descriptionEnList[i], - externalUrlIs: externalUrlIsList[i], - externalUrlEn: externalUrlEnList[i], - requirement: requirement, - semesterYear: Number(course.semesterYear), - semesterSeason: semesterSeason, - }) - } - } catch (e) { - logError(course.externalId?.toString() || '', e) - } - } - - return mappedRes -} diff --git a/libs/university-gateway/src/index.ts b/libs/university-gateway/src/index.ts index e0add8eada88..726e1ac77462 100644 --- a/libs/university-gateway/src/index.ts +++ b/libs/university-gateway/src/index.ts @@ -1,6 +1,5 @@ export * from './lib/consts/universityNationalIds' export * from './lib/model/application' -export * from './lib/model/course' export * from './lib/model/program' export * from './lib/model/programExtraApplicationField' export * from './lib/model/programSpecialization' @@ -10,7 +9,6 @@ export * from './lib/types/degreeType' export * from './lib/types/entryRequirementFulfillment' export * from './lib/types/fieldType' export * from './lib/types/modeOfDelivery' -export * from './lib/types/requirement' export * from './lib/types/season' export * from './lib/types/applicationTypes' export * from './lib/utils/enum' diff --git a/libs/university-gateway/src/lib/model/course.ts b/libs/university-gateway/src/lib/model/course.ts deleted file mode 100644 index db72f9fc89d8..000000000000 --- a/libs/university-gateway/src/lib/model/course.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Requirement } from '../types/requirement' -import { CourseSeason } from '../types/season' - -export interface ICourse { - externalId: string - nameIs: string - nameEn: string - credits: number - descriptionIs?: string - descriptionEn?: string - externalUrlIs?: string - externalUrlEn?: string - requirement: Requirement - semesterYear?: number - semesterSeason: CourseSeason -} diff --git a/libs/university-gateway/src/lib/types/requirement.ts b/libs/university-gateway/src/lib/types/requirement.ts deleted file mode 100644 index 9d3c69e5551e..000000000000 --- a/libs/university-gateway/src/lib/types/requirement.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum Requirement { - MANDATORY = 'MANDATORY', - FREE_ELECTIVE = 'FREE_ELECTIVE', - RESTRICTED_ELECTIVE = 'RESTRICTED_ELECTIVE', -} diff --git a/libs/university-gateway/src/lib/types/season.ts b/libs/university-gateway/src/lib/types/season.ts index 2d4c46d7d37f..7659ad17e5d2 100644 --- a/libs/university-gateway/src/lib/types/season.ts +++ b/libs/university-gateway/src/lib/types/season.ts @@ -3,11 +3,3 @@ export enum Season { SPRING = 'SPRING', SUMMER = 'SUMMER', } - -export enum CourseSeason { - FALL = 'FALL', - SPRING = 'SPRING', - SUMMER = 'SUMMER', - WHOLE_YEAR = 'WHOLE_YEAR', - ANY = 'ANY', -} From e50ded344da35632a3bc9a0ee663b905badd913a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93lafur=20Bj=C3=B6rn=20Magn=C3=BAsson?= Date: Tue, 29 Oct 2024 14:09:49 +0000 Subject: [PATCH 03/28] feat(application-system): On delete template api (#16605) * on delete * fix if block --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../application/application.controller.ts | 55 +++++++++++++++++++ .../core/src/lib/ApplicationTemplateHelper.ts | 9 +++ .../application/types/src/lib/StateMachine.ts | 1 + .../ApplicationList/ApplicationList.tsx | 8 ++- .../src/hooks/useDeleteApplication.ts | 6 ++ 5 files changed, 78 insertions(+), 1 deletion(-) diff --git a/apps/application-system/api/src/app/modules/application/application.controller.ts b/apps/application-system/api/src/app/modules/application/application.controller.ts index d8d3180484aa..734796589e4a 100644 --- a/apps/application-system/api/src/app/modules/application/application.controller.ts +++ b/apps/application-system/api/src/app/modules/application/application.controller.ts @@ -1079,6 +1079,7 @@ export class ApplicationController { async delete( @Param('id', new ParseUUIDPipe()) id: string, @CurrentUser() user: User, + @CurrentLocale() locale: Locale, ) { const { nationalId } = user const existingApplication = @@ -1097,6 +1098,53 @@ export class ApplicationController { ) } + const template = await getApplicationTemplateByTypeId( + existingApplication.typeId, + ) + if (template === null) { + throw new BadRequestException( + `No application template exists for type: ${existingApplication.typeId}`, + ) + } + + let onDeleteActions = new ApplicationTemplateHelper( + existingApplication, + template, + ).getOnDeleteStateAPIAction() + if (onDeleteActions) { + const namespaces = await getApplicationTranslationNamespaces( + existingApplication, + ) + if (!Array.isArray(onDeleteActions)) { + onDeleteActions = [onDeleteActions] + } + + const intl = await this.intlService.useIntl(namespaces, locale) + const deletingApplication = await this.templateApiActionRunner.run( + existingApplication, + onDeleteActions, + user, + locale, + intl.formatMessage, + ) + + for (const api of onDeleteActions) { + const result = + deletingApplication.externalData[api.externalDataId || api.action] + + this.logger.debug( + `Performing action ${api.action} on ${JSON.stringify( + template.name, + )} ended with ${result.status}`, + ) + + if (result.status === 'failure' && api.throwOnError) { + const reason = result.reason ?? 'Unknown error' + throw new TemplateApiError(reason, 500) + } + } + } + // delete charge in FJS await this.applicationChargeService.deleteCharge(existingApplication) @@ -1111,5 +1159,12 @@ export class ApplicationController { ) await this.applicationService.delete(existingApplication.id) + + this.auditService.audit({ + auth: user, + action: 'delete', + resources: existingApplication.id, + meta: { type: existingApplication.typeId }, + }) } } diff --git a/libs/application/core/src/lib/ApplicationTemplateHelper.ts b/libs/application/core/src/lib/ApplicationTemplateHelper.ts index f7d35edcd394..7af4692c2cfd 100644 --- a/libs/application/core/src/lib/ApplicationTemplateHelper.ts +++ b/libs/application/core/src/lib/ApplicationTemplateHelper.ts @@ -118,6 +118,15 @@ export class ApplicationTemplateHelper< return this.getTemplateAPIAction(action) } + getOnDeleteStateAPIAction( + stateKey: string = this.application.state, + ): TemplateApi | TemplateApi[] | null { + const action = + this.template.stateMachineConfig.states[stateKey]?.meta?.onDelete ?? null + + return this.getTemplateAPIAction(action) + } + getApplicationStateInformation( stateKey: string = this.application.state, ): ApplicationStateMeta | undefined { diff --git a/libs/application/types/src/lib/StateMachine.ts b/libs/application/types/src/lib/StateMachine.ts index cad79844abe8..8dd8c370cc7d 100644 --- a/libs/application/types/src/lib/StateMachine.ts +++ b/libs/application/types/src/lib/StateMachine.ts @@ -131,6 +131,7 @@ export interface ApplicationStateMeta< roles?: RoleInState[] onExit?: TemplateApi[] | TemplateApi onEntry?: TemplateApi[] | TemplateApi + onDelete?: TemplateApi[] | TemplateApi } export interface ApplicationStateSchema diff --git a/libs/application/ui-components/src/components/ApplicationList/ApplicationList.tsx b/libs/application/ui-components/src/components/ApplicationList/ApplicationList.tsx index 5a2c56984266..682899678b9a 100644 --- a/libs/application/ui-components/src/components/ApplicationList/ApplicationList.tsx +++ b/libs/application/ui-components/src/components/ApplicationList/ApplicationList.tsx @@ -1,5 +1,10 @@ import React, { useCallback, useState } from 'react' -import { Box, Pagination, Stack } from '@island.is/island-ui/core' +import { + Box, + Pagination, + Stack, + ToastContainer, +} from '@island.is/island-ui/core' import { Application, ApplicationTypes, @@ -95,6 +100,7 @@ const ApplicationList = ({ /> ) : null} + ) } diff --git a/libs/application/ui-components/src/hooks/useDeleteApplication.ts b/libs/application/ui-components/src/hooks/useDeleteApplication.ts index a30fec5fcba8..6171c56ee2e7 100644 --- a/libs/application/ui-components/src/hooks/useDeleteApplication.ts +++ b/libs/application/ui-components/src/hooks/useDeleteApplication.ts @@ -1,13 +1,19 @@ import { useMutation } from '@apollo/client' import { DELETE_APPLICATION } from '@island.is/application/graphql' +import { handleServerError } from '../utilities/handleServerError' +import { useLocale } from '@island.is/localization' export const useDeleteApplication = (refetch?: (() => void) | undefined) => { + const { formatMessage } = useLocale() const [deleteApplicationMutation, { error, loading }] = useMutation( DELETE_APPLICATION, { onCompleted: () => { refetch?.() }, + onError: (error) => { + handleServerError(error, formatMessage) + }, }, ) From 2c50ca696a816e3efc849e27e8573b31c6259faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Tue, 29 Oct 2024 14:43:48 +0000 Subject: [PATCH 04/28] chore(j-s): Strings in ServicePortal (#16602) * Display court assistant on minar-sidur when the judge is a assistant * Add to subpoenaServed string * Rename assistant judge * Fix lint --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../src/app/modules/cases/models/case.response.ts | 6 +++++- .../modules/cases/models/utils/translations.strings.ts | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/judicial-system/digital-mailbox-api/src/app/modules/cases/models/case.response.ts b/apps/judicial-system/digital-mailbox-api/src/app/modules/cases/models/case.response.ts index 6398f668c5e7..34bcc62a519d 100644 --- a/apps/judicial-system/digital-mailbox-api/src/app/modules/cases/models/case.response.ts +++ b/apps/judicial-system/digital-mailbox-api/src/app/modules/cases/models/case.response.ts @@ -4,6 +4,7 @@ import { formatDate } from '@island.is/judicial-system/formatters' import { DateType, isSuccessfulServiceStatus, + UserRole, } from '@island.is/judicial-system/types' import { InternalCaseResponse } from './internal/internalCase.response' @@ -89,7 +90,10 @@ export class CaseResponse { value: internalCase.court.name, }, { - label: t.judge, + label: + internalCase.judge.role === UserRole.DISTRICT_COURT_ASSISTANT + ? t.districtCourtAssistant + : t.judge, value: internalCase.judge.name, }, { diff --git a/apps/judicial-system/digital-mailbox-api/src/app/modules/cases/models/utils/translations.strings.ts b/apps/judicial-system/digital-mailbox-api/src/app/modules/cases/models/utils/translations.strings.ts index 6ca747677b74..9b44994e54dd 100644 --- a/apps/judicial-system/digital-mailbox-api/src/app/modules/cases/models/utils/translations.strings.ts +++ b/apps/judicial-system/digital-mailbox-api/src/app/modules/cases/models/utils/translations.strings.ts @@ -20,6 +20,7 @@ type Translations = { institution: string indictment: string judge: string + districtCourtAssistant: string location: string name: string nationalId: string @@ -57,6 +58,7 @@ const translations: Translations = { institution: 'Institution', indictment: 'Indictment', judge: 'Judge', + districtCourtAssistant: 'Assistant judge', location: 'Location', name: 'Name', nationalId: 'National ID', @@ -68,7 +70,7 @@ const translations: Translations = { subpoena: 'Subpoena', subpoenaSent: 'Subpoena sent', subpoenaServed: - 'Confirmation of subpoena service has been sent to the court', + 'Confirmation of subpoena service has been sent to the police and court', type: 'Type', waiveRightToCounsel: 'Right to counsel waived', }, @@ -92,6 +94,7 @@ const translations: Translations = { institution: 'Embætti', indictment: 'Ákæra', judge: 'Dómari', + districtCourtAssistant: 'Aðstoðarmaður dómara', location: 'Staður', name: 'Nafn', nationalId: 'Kennitala', @@ -102,7 +105,8 @@ const translations: Translations = { prosecutorsOffice: 'Embætti', subpoena: 'Fyrirkall', subpoenaSent: 'Fyrirkall sent', - subpoenaServed: 'Staðfesting á móttöku hefur verið send á dómstóla', + subpoenaServed: + 'Staðfesting á móttöku hefur verið send á lögreglu og dómstóla', type: 'Tegund', waiveRightToCounsel: 'Ekki er óskað eftir verjanda', }, From 701c1e8927e385a75450eb36f423cba025c3b593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Tue, 29 Oct 2024 15:03:53 +0000 Subject: [PATCH 05/28] chore(j-s): Add loading state to create subpoena button (#16612) * Add role to service certificate * Add loading state to button to create subpoena * Remove toast --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx index 9fa89eb677ca..fc37df693344 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx @@ -32,6 +32,7 @@ const Subpoena: FC = () => { useContext(FormContext) const [navigateTo, setNavigateTo] = useState() const [newSubpoenas, setNewSubpoenas] = useState([]) + const [isCreatingSubpoena, setIsCreatingSubpoena] = useState(false) const { updateDefendantState, updateDefendant } = useDefendants() const { formatMessage } = useIntl() const { @@ -51,6 +52,8 @@ const Subpoena: FC = () => { const handleNavigationTo = useCallback( async (destination: keyof stepValidationsType) => { + setIsCreatingSubpoena(true) + if (!isSchedulingArraignmentDate) { router.push(`${destination}/${workingCase.id}`) return @@ -74,6 +77,7 @@ const Subpoena: FC = () => { const allDefendantsUpdated = await Promise.all(promises) if (!allDefendantsUpdated.every((result) => result)) { + setIsCreatingSubpoena(false) return } @@ -96,6 +100,7 @@ const Subpoena: FC = () => { const courtDateUpdated = await sendCourtDateToServer(clearedConclusion) if (!courtDateUpdated) { + setIsCreatingSubpoena(false) return } @@ -254,7 +259,7 @@ const Subpoena: FC = () => { }} primaryButtonText={formatMessage(strings.modalPrimaryButtonText)} secondaryButtonText={formatMessage(strings.modalSecondaryButtonText)} - isPrimaryButtonLoading={false} + isPrimaryButtonLoading={isCreatingSubpoena} /> )} From dc950b2664bb019f4578cbc3c499d1c66e088438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Tue, 29 Oct 2024 15:19:28 +0000 Subject: [PATCH 06/28] fix(j-s): Generated PDFs (#16625) Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../Court/Indictments/Overview/Overview.tsx | 8 +++--- .../Indictments/Overview/Overview.tsx | 8 +++--- .../IndictmentOverview/IndictmentOverview.tsx | 26 +++++++++---------- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx index 7e1dd48f65b8..f22e56f7832d 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx @@ -132,11 +132,9 @@ const IndictmentOverview = () => { ))} )} - {workingCase.caseFiles && ( - - - - )} + + + {workingCase.defendants && ( { diff --git a/apps/judicial-system/web/src/routes/PublicProsecutor/Indictments/Overview/Overview.tsx b/apps/judicial-system/web/src/routes/PublicProsecutor/Indictments/Overview/Overview.tsx index 5bc841c71ab6..83f2a65fe56d 100644 --- a/apps/judicial-system/web/src/routes/PublicProsecutor/Indictments/Overview/Overview.tsx +++ b/apps/judicial-system/web/src/routes/PublicProsecutor/Indictments/Overview/Overview.tsx @@ -165,11 +165,9 @@ export const Overview = () => { )} */} - {workingCase.caseFiles && ( - - - - )} + + + { ) && workingCase.indictmentDecision !== IndictmentDecision.POSTPONING_UNTIL_VERDICT - const shouldDisplayGeneratedPDFs = + const shouldDisplayGeneratedPdfFiles = + isProsecutionUser(user) || workingCase.defendants?.some( (defendant) => defendant.isDefenderChoiceConfirmed && @@ -171,7 +173,7 @@ const IndictmentOverview: FC = () => { ))} @@ -179,17 +181,15 @@ const IndictmentOverview: FC = () => { )} )} - {workingCase.caseFiles && ( // TODO: Find a more accurate condition, there may be generated PDFs to display even if there are no uploaded files to display - - - - )} + + + {canAddFiles && (