diff --git a/apps/judicial-system/api/src/app/modules/defendant/models/defendant.model.ts b/apps/judicial-system/api/src/app/modules/defendant/models/defendant.model.ts index 589709247bd9..437900ffb488 100644 --- a/apps/judicial-system/api/src/app/modules/defendant/models/defendant.model.ts +++ b/apps/judicial-system/api/src/app/modules/defendant/models/defendant.model.ts @@ -110,6 +110,9 @@ export class Defendant { @Field(() => String, { nullable: true }) readonly sentToPrisonAdminDate?: string + @Field(() => String, { nullable: true }) + readonly openedByPrisonAdminDate?: string + @Field(() => PunishmentType, { nullable: true }) readonly punishmentType?: PunishmentType } 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 75fe945637d3..3adf5cac8f0d 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 @@ -417,6 +417,16 @@ export const caseListInclude: Includeable[] = [ as: 'defendants', required: false, order: [['created', 'ASC']], + include: [ + { + model: DefendantEventLog, + as: 'eventLogs', + required: false, + where: { eventType: defendantEventTypes }, + order: [['created', 'DESC']], + separate: true, + }, + ], separate: true, }, { diff --git a/apps/judicial-system/backend/src/app/modules/case/interceptors/case.interceptor.ts b/apps/judicial-system/backend/src/app/modules/case/interceptors/case.interceptor.ts index 85e302ad6754..adfb51abe7f2 100644 --- a/apps/judicial-system/backend/src/app/modules/case/interceptors/case.interceptor.ts +++ b/apps/judicial-system/backend/src/app/modules/case/interceptors/case.interceptor.ts @@ -7,6 +7,8 @@ import { NestInterceptor, } from '@nestjs/common' +import { DefendantEventType } from '@island.is/judicial-system/types' + import { Defendant, DefendantEventLog } from '../../defendant' import { Case } from '../models/case.model' import { CaseString } from '../models/caseString.model' @@ -15,8 +17,15 @@ export const transformDefendants = (defendants?: Defendant[]) => { return defendants?.map((defendant) => ({ ...defendant.toJSON(), sentToPrisonAdminDate: defendant.isSentToPrisonAdmin - ? DefendantEventLog.sentToPrisonAdminDate(defendant.eventLogs)?.created + ? DefendantEventLog.getDefendantEventLogTypeDate({ + defendantEventLogs: defendant.eventLogs, + eventType: DefendantEventType.SENT_TO_PRISON_ADMIN, + }) : undefined, + openedByPrisonAdminDate: DefendantEventLog.getDefendantEventLogTypeDate({ + defendantEventLogs: defendant.eventLogs, + eventType: DefendantEventType.OPENED_BY_PRISON_ADMIN, + }), })) } diff --git a/apps/judicial-system/backend/src/app/modules/case/interceptors/defendantIndictmentAccessed.interceptor.ts b/apps/judicial-system/backend/src/app/modules/case/interceptors/defendantIndictmentAccessed.interceptor.ts new file mode 100644 index 000000000000..64d122d8db7c --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/case/interceptors/defendantIndictmentAccessed.interceptor.ts @@ -0,0 +1,63 @@ +import { + CallHandler, + ExecutionContext, + Injectable, + NestInterceptor, +} from '@nestjs/common' + +import { + DefendantEventType, + isIndictmentCase, + isPrisonAdminUser, + User, +} from '@island.is/judicial-system/types' + +import { DefendantEventLog, DefendantService } from '../../defendant' +import { Case } from '../models/case.model' + +const hasValidOpenByPrisonAdminEvent = ( + defendantEventLogs: DefendantEventLog[], +) => { + const sentToPrisonAdminDate = DefendantEventLog.getDefendantEventLogTypeDate({ + defendantEventLogs, + eventType: DefendantEventType.SENT_TO_PRISON_ADMIN, + }) + const openedByPrisonAdminDate = + DefendantEventLog.getDefendantEventLogTypeDate({ + defendantEventLogs, + eventType: DefendantEventType.OPENED_BY_PRISON_ADMIN, + }) + return ( + sentToPrisonAdminDate && + openedByPrisonAdminDate && + sentToPrisonAdminDate <= openedByPrisonAdminDate + ) +} + +@Injectable() +export class DefendantIndictmentAccessedInterceptor implements NestInterceptor { + constructor(private readonly defendantService: DefendantService) {} + + intercept(context: ExecutionContext, next: CallHandler) { + const request = context.switchToHttp().getRequest() + const user: User = request.user + const theCase: Case = request.case + + if (isIndictmentCase(theCase.type) && isPrisonAdminUser(user)) { + const defendantsIndictmentNotOpened = theCase.defendants?.filter( + ({ isSentToPrisonAdmin, eventLogs = [] }) => + isSentToPrisonAdmin && !hasValidOpenByPrisonAdminEvent(eventLogs), + ) + + // create new events for all defendants that prison admin has not accessed according to defendant event logs + defendantsIndictmentNotOpened?.forEach((defendant) => + this.defendantService.createDefendantEvent({ + caseId: theCase.id, + defendantId: defendant.id, + eventType: DefendantEventType.OPENED_BY_PRISON_ADMIN, + }), + ) + } + return next.handle() + } +} diff --git a/apps/judicial-system/backend/src/app/modules/case/limitedAccessCase.controller.ts b/apps/judicial-system/backend/src/app/modules/case/limitedAccessCase.controller.ts index c263e83f455d..be63d588328f 100644 --- a/apps/judicial-system/backend/src/app/modules/case/limitedAccessCase.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/case/limitedAccessCase.controller.ts @@ -30,13 +30,16 @@ import type { User as TUser } from '@island.is/judicial-system/types' import { CaseState, CaseType, + DefendantEventType, indictmentCases, investigationCases, restrictionCases, + UserRole, } from '@island.is/judicial-system/types' import { nowFactory } from '../../factories' import { defenderRule, prisonSystemStaffRule } from '../../guards' +import { DefendantService } from '../defendant' import { EventService } from '../event' import { User } from '../user' import { TransitionCaseDto } from './dto/transitionCase.dto' @@ -57,6 +60,7 @@ import { } from './guards/rolesRules' import { CaseInterceptor } from './interceptors/case.interceptor' import { CompletedAppealAccessedInterceptor } from './interceptors/completedAppealAccessed.interceptor' +import { DefendantIndictmentAccessedInterceptor } from './interceptors/defendantIndictmentAccessed.interceptor' import { LimitedAccessCaseFileInterceptor } from './interceptors/limitedAccessCaseFile.interceptor' import { Case } from './models/case.model' import { transitionCase } from './state/case.state' @@ -73,6 +77,7 @@ export class LimitedAccessCaseController { private readonly limitedAccessCaseService: LimitedAccessCaseService, private readonly eventService: EventService, private readonly pdfService: PdfService, + private readonly defendantService: DefendantService, @Inject(LOGGER_PROVIDER) private readonly logger: Logger, ) {} @@ -84,6 +89,7 @@ export class LimitedAccessCaseController { ) @RolesRules(prisonSystemStaffRule, defenderRule) @UseInterceptors( + DefendantIndictmentAccessedInterceptor, CompletedAppealAccessedInterceptor, LimitedAccessCaseFileInterceptor, CaseInterceptor, @@ -100,7 +106,7 @@ export class LimitedAccessCaseController { ): Promise { this.logger.debug(`Getting limitedAccess case ${caseId} by id`) - if (!theCase.openedByDefender) { + if (user.role === UserRole.DEFENDER && !theCase.openedByDefender) { const updated = await this.limitedAccessCaseService.update( theCase, { openedByDefender: nowFactory() }, diff --git a/apps/judicial-system/backend/src/app/modules/case/test/limitedAccessCaseController/getById.spec.ts b/apps/judicial-system/backend/src/app/modules/case/test/limitedAccessCaseController/getById.spec.ts index 034bded816f0..4036446f36ed 100644 --- a/apps/judicial-system/backend/src/app/modules/case/test/limitedAccessCaseController/getById.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/case/test/limitedAccessCaseController/getById.spec.ts @@ -1,6 +1,6 @@ import { uuid } from 'uuidv4' -import type { User } from '@island.is/judicial-system/types' +import { type User, UserRole } from '@island.is/judicial-system/types' import { createTestingCaseModule } from '../createTestingCaseModule' @@ -14,14 +14,18 @@ interface Then { error: Error } -type GivenWhenThen = (caseId: string, theCase: Case) => Promise +type GivenWhenThen = ( + caseId: string, + theCase: Case, + user?: User, +) => Promise describe('LimitedAccessCaseController - Get by id', () => { let givenWhenThen: GivenWhenThen const openedBeforeDate = randomDate() const openedNowDate = randomDate() const caseId = uuid() - const user = { id: uuid() } as User + const defaultUser = { id: uuid() } as User let mockCaseModel: typeof Case @@ -42,7 +46,11 @@ describe('LimitedAccessCaseController - Get by id', () => { const mockFindOne = mockCaseModel.findOne as jest.Mock mockFindOne.mockResolvedValue(updatedCase) - givenWhenThen = async (caseId: string, theCase: Case) => { + givenWhenThen = async ( + caseId: string, + theCase: Case, + user = defaultUser, + ) => { const then = {} as Then try { @@ -79,11 +87,11 @@ describe('LimitedAccessCaseController - Get by id', () => { describe('case exists and has not been opened by defender before', () => { const theCase = { id: caseId } as Case - + const user = { ...defaultUser, role: UserRole.DEFENDER } as User let then: Then beforeEach(async () => { - then = await givenWhenThen(caseId, theCase) + then = await givenWhenThen(caseId, theCase, user) }) it('should update openedByDefender and return case', () => { diff --git a/apps/judicial-system/backend/src/app/modules/defendant/defendant.service.ts b/apps/judicial-system/backend/src/app/modules/defendant/defendant.service.ts index 6276f0634115..d1f24d828393 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/defendant.service.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/defendant.service.ts @@ -271,6 +271,22 @@ export class DefendantService { return updatedDefendant } + async createDefendantEvent({ + caseId, + defendantId, + eventType, + }: { + caseId: string + defendantId: string + eventType: DefendantEventType + }): Promise { + await this.defendantEventLogModel.create({ + caseId, + defendantId, + eventType, + }) + } + async updateIndictmentCaseDefendant( theCase: Case, defendant: Defendant, @@ -284,7 +300,7 @@ export class DefendantService { ) if (update.isSentToPrisonAdmin) { - this.defendantEventLogModel.create({ + this.createDefendantEvent({ caseId: theCase.id, defendantId: defendant.id, eventType: DefendantEventType.SENT_TO_PRISON_ADMIN, diff --git a/apps/judicial-system/backend/src/app/modules/defendant/models/defendantEventLog.model.ts b/apps/judicial-system/backend/src/app/modules/defendant/models/defendantEventLog.model.ts index ca0a332704ee..df19027fd0f9 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/models/defendantEventLog.model.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/models/defendantEventLog.model.ts @@ -20,11 +20,17 @@ import { Defendant } from './defendant.model' timestamps: true, }) export class DefendantEventLog extends Model { - static sentToPrisonAdminDate(defendantEventLogs?: DefendantEventLog[]) { + // gets the latest log date of a given type, since the defendant event logs are sorted + static getDefendantEventLogTypeDate({ + defendantEventLogs, + eventType, + }: { + defendantEventLogs?: DefendantEventLog[] + eventType: DefendantEventType + }) { return defendantEventLogs?.find( - (defendantEventLog) => - defendantEventLog.eventType === DefendantEventType.SENT_TO_PRISON_ADMIN, - ) + (defendantEventLog) => defendantEventLog.eventType === eventType, + )?.created } @Column({ diff --git a/apps/judicial-system/web/src/components/FormProvider/case.graphql b/apps/judicial-system/web/src/components/FormProvider/case.graphql index 4aec6d983d4b..069e36645c3f 100644 --- a/apps/judicial-system/web/src/components/FormProvider/case.graphql +++ b/apps/judicial-system/web/src/components/FormProvider/case.graphql @@ -35,6 +35,7 @@ query Case($input: CaseQueryInput!) { subpoenaType isSentToPrisonAdmin sentToPrisonAdminDate + openedByPrisonAdminDate punishmentType subpoenas { id diff --git a/apps/judicial-system/web/src/components/FormProvider/limitedAccessCase.graphql b/apps/judicial-system/web/src/components/FormProvider/limitedAccessCase.graphql index dea05680c538..8d31030894bc 100644 --- a/apps/judicial-system/web/src/components/FormProvider/limitedAccessCase.graphql +++ b/apps/judicial-system/web/src/components/FormProvider/limitedAccessCase.graphql @@ -47,6 +47,7 @@ query LimitedAccessCase($input: CaseQueryInput!) { subpoenaType isSentToPrisonAdmin sentToPrisonAdminDate + openedByPrisonAdminDate punishmentType subpoenas { id diff --git a/apps/judicial-system/web/src/components/Tags/utils.ts b/apps/judicial-system/web/src/components/Tags/utils.ts index e4f1b3ac9f83..1b047e13806a 100644 --- a/apps/judicial-system/web/src/components/Tags/utils.ts +++ b/apps/judicial-system/web/src/components/Tags/utils.ts @@ -119,3 +119,19 @@ export const getIndictmentRulingDecisionTag = ( return { color: 'darkerBlue', text: strings.complete } } } + +export const getPrisonCaseStateTag = ( + prisonCaseState: CaseState, +): { + color: TagVariant + text: { id: string; defaultMessage: string; description: string } +} => { + switch (prisonCaseState) { + case CaseState.NEW: + return { color: 'purple', text: strings.new } + case CaseState.RECEIVED: + return { color: 'blue', text: strings.received } + default: + return { color: 'darkerBlue', text: strings.complete } + } +} diff --git a/apps/judicial-system/web/src/routes/Defender/Cases/components/DefenderCasesTable.tsx b/apps/judicial-system/web/src/routes/Defender/Cases/components/DefenderCasesTable.tsx index 169584028e9b..7a52c93d46ff 100644 --- a/apps/judicial-system/web/src/routes/Defender/Cases/components/DefenderCasesTable.tsx +++ b/apps/judicial-system/web/src/routes/Defender/Cases/components/DefenderCasesTable.tsx @@ -57,6 +57,9 @@ export const DefenderCasesTable: FC = ({ ) { return entry.defendants[0].name ?? '' } + if (column === 'courtDate') { + return entry.courtDate + } return entry.created } const { sortedData, requestSort, getClassNamesFor, isActiveColumn } = useSort( @@ -129,9 +132,13 @@ export const DefenderCasesTable: FC = ({ ) : ( - - {formatMessage(tables.hearingArrangementDate)} - + requestSort('courtDate')} + sortAsc={getClassNamesFor('courtDate') === 'ascending'} + sortDes={getClassNamesFor('courtDate') === 'descending'} + isActive={isActiveColumn('courtDate')} + /> )} diff --git a/apps/judicial-system/web/src/routes/Prison/IndictmentOverview/IndictmentOverview.strings.ts b/apps/judicial-system/web/src/routes/Prison/IndictmentOverview/IndictmentOverview.strings.ts index d574238883e5..bc87e97beef8 100644 --- a/apps/judicial-system/web/src/routes/Prison/IndictmentOverview/IndictmentOverview.strings.ts +++ b/apps/judicial-system/web/src/routes/Prison/IndictmentOverview/IndictmentOverview.strings.ts @@ -14,7 +14,12 @@ export const strings = defineMessages({ indictmentCompletedTitle: { id: 'judicial.system.core:indictment_overview.indictment_completed_title', defaultMessage: 'Dómsuppkvaðning {date}', - description: 'Titill á yfirliti ákæru fyrir fangelsi', + description: 'Undirtitill á yfirliti ákæru fyrir fangelsi', + }, + indictmentReceivedTitle: { + id: 'judicial.system.core:indictment_overview.indictment_received_title', + defaultMessage: 'Móttekið {date}', + description: 'Undirtitill á yfirliti ákæru fyrir fangelsi', }, infoCardDefendantsTitle: { id: 'judicial.system.core:indictment_overview.info_card_defendants_title', diff --git a/apps/judicial-system/web/src/routes/Prison/IndictmentOverview/IndictmentOverview.tsx b/apps/judicial-system/web/src/routes/Prison/IndictmentOverview/IndictmentOverview.tsx index beab42f136a8..82065184df56 100644 --- a/apps/judicial-system/web/src/routes/Prison/IndictmentOverview/IndictmentOverview.tsx +++ b/apps/judicial-system/web/src/routes/Prison/IndictmentOverview/IndictmentOverview.tsx @@ -81,6 +81,13 @@ const IndictmentOverview = () => { })} )} + {defendant?.openedByPrisonAdminDate && ( + + {formatMessage(strings.indictmentReceivedTitle, { + date: formatDate(defendant.openedByPrisonAdminDate, 'PPP'), + })} + + )} diff --git a/apps/judicial-system/web/src/routes/Shared/Cases/PrisonCases.tsx b/apps/judicial-system/web/src/routes/Shared/Cases/PrisonCases.tsx index 3027b2e998f6..1e4046e8e11e 100644 --- a/apps/judicial-system/web/src/routes/Shared/Cases/PrisonCases.tsx +++ b/apps/judicial-system/web/src/routes/Shared/Cases/PrisonCases.tsx @@ -14,6 +14,7 @@ import { titles, } from '@island.is/judicial-system-web/messages' import { + CaseTag, Logo, PageHeader, SectionHeading, @@ -31,6 +32,7 @@ import { getDurationDate, } from '@island.is/judicial-system-web/src/components/Table' import Table from '@island.is/judicial-system-web/src/components/Table/Table' +import { getPrisonCaseStateTag } from '@island.is/judicial-system-web/src/components/Tags/utils' import { CaseListEntry, CaseState, @@ -217,11 +219,23 @@ export const PrisonCases: FC = () => { ), }, { - cell: () => ( - - {'Nýtt'} - - ), + cell: (row) => { + const prisonCaseState = + row.defendants && + row.defendants?.length > 0 && + row.defendants[0].openedByPrisonAdminDate + ? CaseState.RECEIVED + : CaseState.NEW + const prisonCaseStateTag = + getPrisonCaseStateTag(prisonCaseState) + + return ( + + ) + }, }, ]} generateContextMenuItems={(row) => [openCaseInNewTabMenuItem(row.id)]} 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 4001b83c6fcb..0bcfe4933c95 100644 --- a/apps/judicial-system/web/src/routes/Shared/Cases/cases.graphql +++ b/apps/judicial-system/web/src/routes/Shared/Cases/cases.graphql @@ -28,6 +28,7 @@ query Cases { defenderChoice verdictViewDate isSentToPrisonAdmin + openedByPrisonAdminDate } courtDate isValidToDateInThePast diff --git a/apps/judicial-system/web/src/routes/Shared/Cases/prisonCases.graphql b/apps/judicial-system/web/src/routes/Shared/Cases/prisonCases.graphql index 04f635815e1e..321f459f4a7c 100644 --- a/apps/judicial-system/web/src/routes/Shared/Cases/prisonCases.graphql +++ b/apps/judicial-system/web/src/routes/Shared/Cases/prisonCases.graphql @@ -26,6 +26,7 @@ query PrisonCases { name noNationalId defenderChoice + openedByPrisonAdminDate } courtDate isValidToDateInThePast 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 868f78ae3130..0e17f4f59ecd 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 @@ -1,5 +1,5 @@ import { AdvertSignatureTypeEnum } from '@island.is/clients/official-journal-of-iceland' -import { InputType, Field, registerEnumType } from '@nestjs/graphql' +import { InputType, Field, registerEnumType, Int } from '@nestjs/graphql' registerEnumType(AdvertSignatureTypeEnum, { name: 'OfficialJournalOfIcelandAdvertSignatureType', @@ -10,10 +10,10 @@ export class AdvertsInput { @Field(() => String, { nullable: true }) search?: string - @Field(() => Number, { nullable: true }) + @Field(() => Int, { nullable: true }) page?: number - @Field(() => Number, { nullable: true }) + @Field(() => Int, { nullable: true }) pageSize?: number @Field(() => [String], { nullable: true }) @@ -43,10 +43,10 @@ export class TypeQueryParams { @Field(() => String, { nullable: true }) department?: string - @Field(() => Number, { nullable: true }) + @Field(() => Int, { nullable: true }) page?: number - @Field(() => Number, { nullable: true }) + @Field(() => Int, { nullable: true }) pageSize?: number } @@ -61,10 +61,10 @@ export class QueryParams { @Field(() => String, { nullable: true }) search?: string - @Field(() => Number, { nullable: true }) + @Field(() => Int, { nullable: true }) page?: number - @Field(() => Number, { nullable: true }) + @Field(() => Int, { nullable: true }) pageSize?: number } @@ -134,3 +134,15 @@ export class SubmitApplicationInput { @Field(() => AdvertSignature) signature!: AdvertSignature } + +@InputType('OfficialJournalOfIcelandMainTypesInput') +export class MainTypesQueryParams { + @Field(() => String, { nullable: true }) + department?: string + + @Field(() => Int, { nullable: true }) + page?: number + + @Field(() => Int, { nullable: true }) + pageSize?: number +} diff --git a/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.model.ts b/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.model.ts index 30d22c9840f5..70a9135f7d45 100644 --- a/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.model.ts +++ b/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.model.ts @@ -136,3 +136,21 @@ export class Advert { @Field(() => AdvertDocument) document!: AdvertDocument } + +@ObjectType('OfficialJournalOfIcelandAdvertsMainType') +export class AdvertMainType { + @Field() + id!: string + + @Field() + title!: string + + @Field() + slug!: string + + @Field(() => AdvertEntity) + department!: AdvertEntity + + @Field(() => [AdvertType]) + types!: AdvertType[] +} diff --git a/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.response.ts b/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.response.ts index 633157789400..baa06f7a4f6f 100644 --- a/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.response.ts +++ b/libs/api/domains/official-journal-of-iceland/src/lib/models/advert.response.ts @@ -5,6 +5,7 @@ import { AdvertEntity, AdvertMainCategory, AdvertType, + AdvertMainType, } from './advert.model' import { AdvertPaging } from './advert-paging.model' @@ -79,3 +80,12 @@ export class AdvertResponse { @Field(() => Advert) advert?: Advert } + +@ObjectType('OfficialJournalOfIcelandMainTypesResponse') +export class MainTypesResponse { + @Field(() => [AdvertMainType]) + mainTypes!: AdvertMainType[] + + @Field(() => AdvertPaging) + paging!: AdvertPaging +} diff --git a/libs/api/domains/official-journal-of-iceland/src/lib/officialJournalOfIceland.resolver.ts b/libs/api/domains/official-journal-of-iceland/src/lib/officialJournalOfIceland.resolver.ts index cde591d90f87..1fddbf0d108a 100644 --- a/libs/api/domains/official-journal-of-iceland/src/lib/officialJournalOfIceland.resolver.ts +++ b/libs/api/domains/official-journal-of-iceland/src/lib/officialJournalOfIceland.resolver.ts @@ -8,6 +8,7 @@ import { AdvertsInput, QueryParams, TypeQueryParams, + MainTypesQueryParams, } from './models/advert.input' import { AdvertCategoryResponse, @@ -19,6 +20,7 @@ import { AdvertsResponse, AdvertTypeResponse, AdvertTypesResponse, + MainTypesResponse, } from './models/advert.response' import { Features } from '@island.is/feature-flags' import { FeatureFlag } from '@island.is/nest/feature-flags' @@ -72,6 +74,13 @@ export class OfficialJournalOfIcelandResolver { return this.ojoiService.getAdvertTypes(params) } + @Query(() => MainTypesResponse, { + name: 'officialJournalOfIcelandMainTypes', + }) + getAdvertMainTypes(@Args('params') params: MainTypesQueryParams) { + return this.ojoiService.getMainTypes(params) + } + @Query(() => AdvertMainCategoriesResponse, { name: 'officialJournalOfIcelandMainCategories', }) diff --git a/libs/api/domains/official-journal-of-iceland/src/lib/officialJournalOfIceland.service.ts b/libs/api/domains/official-journal-of-iceland/src/lib/officialJournalOfIceland.service.ts index 954a7ab1d8ad..39d9c4c2507d 100644 --- a/libs/api/domains/official-journal-of-iceland/src/lib/officialJournalOfIceland.service.ts +++ b/libs/api/domains/official-journal-of-iceland/src/lib/officialJournalOfIceland.service.ts @@ -8,6 +8,7 @@ import { AdvertSingleParams, QueryParams, TypeQueryParams, + MainTypesQueryParams, } from './models/advert.input' import { AdvertCategoryResponse, @@ -17,6 +18,7 @@ import { AdvertResponse, AdvertsResponse, AdvertTypesResponse, + MainTypesResponse, } from './models/advert.response' import { CasesInProgressResponse } from './models/cases.response' @@ -54,6 +56,10 @@ export class OfficialJournalOfIcelandService { return await this.ojoiService.getAdvertTypes(params) } + async getMainTypes(params: MainTypesQueryParams): Promise { + return await this.ojoiService.getAdvertMainTypes(params) + } + async getInstitutions( params: QueryParams, ): Promise { diff --git a/libs/application/templates/official-journal-of-iceland/src/components/htmlEditor/HTMLEditor.tsx b/libs/application/templates/official-journal-of-iceland/src/components/htmlEditor/HTMLEditor.tsx index f8cb1367ec92..0b91a291d5e7 100644 --- a/libs/application/templates/official-journal-of-iceland/src/components/htmlEditor/HTMLEditor.tsx +++ b/libs/application/templates/official-journal-of-iceland/src/components/htmlEditor/HTMLEditor.tsx @@ -3,7 +3,7 @@ import { Editor, EditorFileUploader } from '@island.is/regulations-tools/Editor' import { useEffect, useRef, useState } from 'react' import { Controller } from 'react-hook-form' import { classes, editorWrapper, errorStyle } from './HTMLEditor.css' -import { Box, Text } from '@island.is/island-ui/core' +import { Box, Stack, Text } from '@island.is/island-ui/core' type Props = { title?: string name: string @@ -50,12 +50,8 @@ export const HTMLEditor = ({ defaultValue={initialValue} render={({ field: { onChange: updateFormValue, value } }) => { return ( - <> - {title && ( - - {title} - - )} + + {title && {title}} {error &&
{error}
} - +
) }} /> diff --git a/libs/application/templates/official-journal-of-iceland/src/components/input/OJOISelectController.tsx b/libs/application/templates/official-journal-of-iceland/src/components/input/OJOISelectController.tsx index 00eac25ff080..799ed40704d8 100644 --- a/libs/application/templates/official-journal-of-iceland/src/components/input/OJOISelectController.tsx +++ b/libs/application/templates/official-journal-of-iceland/src/components/input/OJOISelectController.tsx @@ -4,7 +4,12 @@ import { useApplication } from '../../hooks/useUpdateApplication' import { OJOIApplication } from '../../lib/types' import { useFormContext } from 'react-hook-form' import set from 'lodash/set' -import { Select, SkeletonLoader } from '@island.is/island-ui/core' +import { + Box, + Select, + SkeletonLoader, + useBreakpoint, +} from '@island.is/island-ui/core' import { OJOI_INPUT_HEIGHT } from '../../lib/constants' import { isBaseEntity } from '../../lib/utils' import { getValueViaPath } from '@island.is/application/core' @@ -23,6 +28,7 @@ type Props = { loading?: boolean applicationId: string disabled?: boolean + width?: 'full' | 'half' onBeforeChange?: (answers: OJOIApplication['answers'], value: T) => void onChange?: (value: T) => void } @@ -36,6 +42,7 @@ export const OJOISelectController = ({ loading, applicationId, disabled, + width = 'full', onBeforeChange, onChange, }: Props) => { @@ -46,6 +53,9 @@ export const OJOISelectController = ({ const { setValue } = useFormContext() + const { xs, sm, md } = useBreakpoint() + const isSmOrSmaller = xs || (sm && !md) + const placeholderText = typeof placeholder === 'string' ? placeholder : f(placeholder) @@ -68,35 +78,33 @@ export const OJOISelectController = ({ return opt.value.id === defaultVal.id } - return false + return undefined }) - if (loading) { - return ( - - ) - } - return ( - { + if (!opt?.value) return + return handleChange(opt.value) + }} + /> + )} +
) } diff --git a/libs/application/templates/official-journal-of-iceland/src/fields/Advert.tsx b/libs/application/templates/official-journal-of-iceland/src/fields/Advert.tsx index 0e81b3062f40..fcaa5cfdb6fc 100644 --- a/libs/application/templates/official-journal-of-iceland/src/fields/Advert.tsx +++ b/libs/application/templates/official-journal-of-iceland/src/fields/Advert.tsx @@ -1,8 +1,7 @@ import { InputFields, OJOIFieldBaseProps } from '../lib/types' -import { Box } from '@island.is/island-ui/core' +import { Stack } from '@island.is/island-ui/core' import { FormGroup } from '../components/form/FormGroup' import { advert } from '../lib/messages' -import * as styles from './Advert.css' import { useDepartments } from '../hooks/useDepartments' import { OJOISelectController } from '../components/input/OJOISelectController' import { useTypes } from '../hooks/useTypes' @@ -12,25 +11,23 @@ import { useFormContext } from 'react-hook-form' import { useApplication } from '../hooks/useUpdateApplication' import set from 'lodash/set' import { HTMLEditor } from '../components/htmlEditor/HTMLEditor' -import { getAdvertMarkup } from '../lib/utils' +import { cleanTypename, getAdvertMarkup } from '../lib/utils' +import { DEPARTMENT_A } from '../lib/constants' export const Advert = ({ application }: OJOIFieldBaseProps) => { const { setValue } = useFormContext() const { application: currentApplication } = useApplication({ applicationId: application.id, }) + const { departments, loading: loadingDepartments } = useDepartments() - const { - getLazyTypes, - types, - loading: loadingTypes, - } = useTypes({ - initalDepartmentId: application.answers?.advert?.department?.id, - }) - const titlePreview = getAdvertMarkup({ - type: currentApplication.answers.advert?.type?.title, - title: currentApplication.answers.advert?.title, + const defaultDepartment = + application.answers?.advert?.department?.id || DEPARTMENT_A + + const { getLazyMainTypes, mainTypes, mainTypeLoading } = useTypes({ + initalDepartmentId: defaultDepartment, + pageSize: 300, }) const departmentOptions = departments?.map((d) => ({ @@ -42,20 +39,28 @@ export const Advert = ({ application }: OJOIFieldBaseProps) => { }, })) - const typeOptions = types?.map((d) => ({ + const mainTypeOptions = mainTypes?.map((d) => ({ label: d.title, - value: { - id: d.id, - title: d.title, - slug: d.slug, - }, + value: d, })) + const currentTypes = + currentApplication?.answers?.advert?.mainType?.types?.map((d) => ({ + label: d.title, + value: d, + })) ?? [] + + const titlePreview = getAdvertMarkup({ + type: currentApplication.answers.advert?.type?.title, + title: currentApplication.answers.advert?.title, + }) + return ( - <> + - + { set(answers, InputFields.advert.type, null) }} onChange={(value) => - getLazyTypes({ + getLazyMainTypes({ variables: { params: { department: value.id, @@ -78,19 +83,36 @@ export const Advert = ({ application }: OJOIFieldBaseProps) => { }) } /> - - + { + if (value.types.length === 1) { + const cleaned = cleanTypename(value.types[0]) + set(answers, InputFields.advert.type, cleaned) + } else { + set(answers, InputFields.advert.type, null) + } + }} /> - - + + {currentTypes.length > 1 && ( + + )} + { textarea={true} maxLength={600} /> - - + - + - + { applicationId={application.id} disabled={true} /> - - + { // because this is not a controlled component onChange={(value) => setValue(InputFields.advert.html, value)} /> - + - + ) } diff --git a/libs/application/templates/official-journal-of-iceland/src/fields/AdvertModal.tsx b/libs/application/templates/official-journal-of-iceland/src/fields/AdvertModal.tsx index 8327cefa5e93..5020d1b8fbe7 100644 --- a/libs/application/templates/official-journal-of-iceland/src/fields/AdvertModal.tsx +++ b/libs/application/templates/official-journal-of-iceland/src/fields/AdvertModal.tsx @@ -26,6 +26,7 @@ import debounce from 'lodash/debounce' import { InputFields } from '../lib/types' import { useFormContext } from 'react-hook-form' import { OfficialJournalOfIcelandAdvert } from '@island.is/api/schema' +import { cleanTypename } from '../lib/utils' type Props = { applicationId: string visible: boolean @@ -75,20 +76,12 @@ export const AdvertModal = ({ return } - const clean = (obj: { - __typename?: string - id: string - title: string - slug: string - }) => { - const { __typename: _, ...rest } = obj - return rest - } - - const department = clean(advert.department) - const type = clean(advert.type) + const department = cleanTypename(advert.department) + const type = cleanTypename(advert.type) - const categories = advert.categories.map((category) => clean(category)) + const categories = advert.categories.map((category) => + cleanTypename(category), + ) setValue(InputFields.advert.department, department) setValue(InputFields.advert.type, type) diff --git a/libs/application/templates/official-journal-of-iceland/src/graphql/queries.ts b/libs/application/templates/official-journal-of-iceland/src/graphql/queries.ts index ebe437b894ad..cfe4f70ab68b 100644 --- a/libs/application/templates/official-journal-of-iceland/src/graphql/queries.ts +++ b/libs/application/templates/official-journal-of-iceland/src/graphql/queries.ts @@ -117,6 +117,38 @@ export const ADVERT_QUERY = gql` } ` +export const MAIN_TYPES_QUERY = gql` + query AdvertMainTypes($params: OfficialJournalOfIcelandMainTypesInput!) { + officialJournalOfIcelandMainTypes(params: $params) { + mainTypes { + id + title + slug + department { + id + title + slug + } + types { + id + title + slug + } + } + paging { + page + pageSize + totalPages + totalItems + hasNextPage + hasPreviousPage + nextPage + previousPage + } + } + } +` + export const TYPES_QUERY = gql` query AdvertTypes($params: OfficialJournalOfIcelandTypesInput!) { officialJournalOfIcelandTypes(params: $params) { 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 8cd4ff5678ed..7ff98ea1949f 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,7 +1,10 @@ import { useLazyQuery, useQuery } from '@apollo/client' -import { OfficialJournalOfIcelandAdvertsTypesResponse } from '@island.is/api/schema' +import { + OfficialJournalOfIcelandAdvertsTypesResponse, + OfficialJournalOfIcelandMainTypesResponse, +} from '@island.is/api/schema' -import { TYPES_QUERY } from '../graphql/queries' +import { MAIN_TYPES_QUERY, TYPES_QUERY } from '../graphql/queries' type UseTypesParams = { initalDepartmentId?: string @@ -14,6 +17,10 @@ type TypesResponse = { officialJournalOfIcelandTypes: OfficialJournalOfIcelandAdvertsTypesResponse } +type MainTypesResponse = { + officialJournalOfIcelandMainTypes: OfficialJournalOfIcelandMainTypesResponse +} + type TypesVariables = { params: { department?: string @@ -50,6 +57,16 @@ export const useTypes = ({ }, ) + const { + data: mainTypesData, + loading: mainTypeLoading, + error: mainTypeError, + } = useQuery(MAIN_TYPES_QUERY, { + variables: { + params: params, + }, + }) + const [ getLazyTypes, { data: lazyTypes, loading: lazyTypesLoading, error: lazyTypesError }, @@ -57,11 +74,33 @@ export const useTypes = ({ fetchPolicy: 'network-only', }) + const [ + getLazyMainTypes, + { + data: lazyMainTypes, + loading: lazyMainTypesLoading, + error: lazyMainTypesError, + }, + ] = useLazyQuery(MAIN_TYPES_QUERY, { + fetchPolicy: 'network-only', + }) + const currentTypes = lazyTypes ? lazyTypes.officialJournalOfIcelandTypes.types : data?.officialJournalOfIcelandTypes.types + const currentMainTypes = lazyMainTypes + ? lazyMainTypes.officialJournalOfIcelandMainTypes.mainTypes + : mainTypesData?.officialJournalOfIcelandMainTypes.mainTypes + return { + mainTypes: currentMainTypes, + mainTypeLoading, + mainTypeError, + lazyMainTypesLoading, + lazyMainTypesError, + getLazyMainTypes, + lazyMainTypes: lazyMainTypes?.officialJournalOfIcelandMainTypes.mainTypes, lazyTypes: lazyTypes?.officialJournalOfIcelandTypes.types, lazyTypesLoading, lazyTypesError, diff --git a/libs/application/templates/official-journal-of-iceland/src/lib/constants.ts b/libs/application/templates/official-journal-of-iceland/src/lib/constants.ts index e05b15dcaf66..ed4ea3efc463 100644 --- a/libs/application/templates/official-journal-of-iceland/src/lib/constants.ts +++ b/libs/application/templates/official-journal-of-iceland/src/lib/constants.ts @@ -14,6 +14,10 @@ export enum AnswerOption { NO = 'no', } +export const DEPARTMENT_A = 'a-deild' +export const DEPARTMENT_B = 'b-deild' +export const DEPARTMENT_C = 'c-deild' + export enum ApplicationAttachmentType { ORIGINAL = 'frumrit', ADDITIONS = 'fylgiskjol', 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 046cbeed2664..8dcfe02c7bbd 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 @@ -69,6 +69,9 @@ const advertSchema = z .object({ department: baseEntitySchema.optional(), type: baseEntitySchema.optional().nullable(), + mainType: baseEntitySchema + .extend({ types: z.array(baseEntitySchema).optional() }) + .optional(), title: z.string().optional(), html: z.string().optional(), requestedDate: z.string().optional(), diff --git a/libs/application/templates/official-journal-of-iceland/src/lib/messages/advert.ts b/libs/application/templates/official-journal-of-iceland/src/lib/messages/advert.ts index 681773cf8393..0bde1ec2be09 100644 --- a/libs/application/templates/official-journal-of-iceland/src/lib/messages/advert.ts +++ b/libs/application/templates/official-journal-of-iceland/src/lib/messages/advert.ts @@ -63,15 +63,27 @@ export const advert = { description: 'Placeholder for the department input', }, }), + mainType: defineMessages({ + label: { + id: 'ojoi.application:advert.inputs.mainType.label', + defaultMessage: 'Tegund birtingar', + description: 'Label for the main type input', + }, + placeholder: { + id: 'ojoi.application:advert.inputs.mainType.placeholder', + defaultMessage: 'Veldu tegund birtingar', + description: 'Placeholder for the main type input', + }, + }), type: defineMessages({ label: { id: 'ojoi.application:advert.inputs.type.label', - defaultMessage: 'Tegund birtingar', + defaultMessage: 'Undirtegund birtingar', description: 'Label for the type input', }, placeholder: { id: 'ojoi.application:advert.inputs.type.placeholder', - defaultMessage: 'Veldu tegund birtingar', + defaultMessage: 'Veldu undirtegund birtingar', description: 'Placeholder for the type input', }, }), 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 1529e2d56442..032d13c63692 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 @@ -12,6 +12,7 @@ export const InputFields = { }, [Routes.ADVERT]: { department: 'advert.department', + mainType: 'advert.mainType', type: 'advert.type', title: 'advert.title', html: 'advert.html', 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 15699f900241..fdfaad3ab0d9 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 @@ -388,3 +388,13 @@ export const convertNumberToRoman = (num: number) => { const roman = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X'] return roman[num - 1] } + +export const cleanTypename = (obj: { + __typename?: string + id: string + title: string + slug: string +}) => { + const { __typename: _, ...rest } = obj + return rest +} diff --git a/libs/application/templates/official-journal-of-iceland/src/screens/InvolvedPartyScreen.tsx b/libs/application/templates/official-journal-of-iceland/src/screens/InvolvedPartyScreen.tsx index 7ed23a605848..b35efca32233 100644 --- a/libs/application/templates/official-journal-of-iceland/src/screens/InvolvedPartyScreen.tsx +++ b/libs/application/templates/official-journal-of-iceland/src/screens/InvolvedPartyScreen.tsx @@ -90,21 +90,20 @@ export const InvolvedPartyScreen = ({ /> )} - - { - setSubmitButtonDisabled && setSubmitButtonDisabled(false) - }} - /> - + { + setSubmitButtonDisabled && setSubmitButtonDisabled(false) + }} + /> ) diff --git a/libs/clients/official-journal-of-iceland/public/src/clientConfig.json b/libs/clients/official-journal-of-iceland/public/src/clientConfig.json index 092ccd7520e1..6206b173263a 100644 --- a/libs/clients/official-journal-of-iceland/public/src/clientConfig.json +++ b/libs/clients/official-journal-of-iceland/public/src/clientConfig.json @@ -169,15 +169,40 @@ } } }, - "/api/v1/types/{id}": { + "/api/v1/maincategories": { "get": { - "operationId": "getAdvertTypeById", + "operationId": "getMainCategories", "parameters": [ { - "name": "id", - "required": true, - "in": "path", + "name": "search", + "description": "String to search for", + "required": false, + "in": "query", "schema": { "type": "string" } + }, + { + "name": "ids", + "required": false, + "in": "query", + "schema": { + "default": [], + "type": "array", + "items": { "type": "string" } + } + }, + { + "name": "page", + "description": "Page number to return.", + "required": false, + "in": "query", + "schema": { "type": "number" } + }, + { + "name": "pageSize", + "description": "Page size number to return.", + "required": false, + "in": "query", + "schema": { "type": "number" } } ], "responses": { @@ -186,7 +211,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetAdvertTypeResponse" + "$ref": "#/components/schemas/GetMainCategoriesResponse" } } } @@ -194,23 +219,26 @@ } } }, - "/api/v1/types": { + "/api/v1/categories": { "get": { - "operationId": "getAdvertTypes", + "operationId": "getCategories", "parameters": [ { - "name": "department", - "description": "Department slug to get categories for.", + "name": "search", + "description": "String to search for", "required": false, "in": "query", "schema": { "type": "string" } }, { - "name": "search", - "description": "String to search for in types.", + "name": "ids", "required": false, "in": "query", - "schema": { "type": "string" } + "schema": { + "default": [], + "type": "array", + "items": { "type": "string" } + } }, { "name": "page", @@ -221,7 +249,7 @@ }, { "name": "pageSize", - "description": "Number of items per page.", + "description": "Page size number to return.", "required": false, "in": "query", "schema": { "type": "number" } @@ -233,7 +261,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetAdvertTypesResponse" + "$ref": "#/components/schemas/GetCategoriesResponse" } } } @@ -241,9 +269,9 @@ } } }, - "/api/v1/maincategories": { + "/api/v1/institutions": { "get": { - "operationId": "getMainCategories", + "operationId": "getInstitutions", "parameters": [ { "name": "search", @@ -283,7 +311,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetMainCategoriesResponse" + "$ref": "#/components/schemas/GetInstitutionsResponse" } } } @@ -291,37 +319,36 @@ } } }, - "/api/v1/categories": { + "/api/v1/signatures": { "get": { - "operationId": "getCategories", + "operationId": "getSignatures", "parameters": [ { - "name": "search", - "description": "String to search for", + "description": "Search for a specific signature by id", "required": false, + "name": "id", "in": "query", "schema": { "type": "string" } }, { - "name": "ids", + "description": "Search for a specific signature by type", + "example": "Regular", "required": false, + "name": "type", "in": "query", - "schema": { - "default": [], - "type": "array", - "items": { "type": "string" } - } + "schema": { "type": "string" } }, { - "name": "page", - "description": "Page number to return.", + "description": "Search for a specific signature", + "example": "Dagur B. Eggertsson", "required": false, + "name": "search", "in": "query", - "schema": { "type": "number" } + "schema": { "type": "string" } }, { - "name": "pageSize", - "description": "Page size number to return.", + "name": "page", + "description": "Page number to return.", "required": false, "in": "query", "schema": { "type": "number" } @@ -333,7 +360,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetCategoriesResponse" + "$ref": "#/components/schemas/GetAdvertSignatureResponse" } } } @@ -341,9 +368,9 @@ } } }, - "/api/v1/institutions": { + "/api/v1/cases": { "get": { - "operationId": "getInstitutions", + "operationId": "getCasesInProgress", "parameters": [ { "name": "search", @@ -383,7 +410,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetInstitutionsResponse" + "$ref": "#/components/schemas/GetCasesInProgressReponse" } } } @@ -391,115 +418,384 @@ } } }, - "/api/v1/signatures": { + "/api/v1/error": { "get": { - "operationId": "getSignatures", + "operationId": "error", + "parameters": [], + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ValidationResponse" } + } + } + } + } + } + }, + "/api/v1/advert-types/types": { + "get": { + "operationId": "getTypes", + "summary": "", "parameters": [ { - "description": "Search for a specific signature by id", "required": false, + "description": "Search by id", "name": "id", "in": "query", "schema": { "type": "string" } }, { - "description": "Search for a specific signature by type", - "example": "Regular", "required": false, - "name": "type", + "description": "Filter by unassigned", + "name": "unassigned", + "in": "query", + "schema": { "type": "boolean" } + }, + { + "required": false, + "description": "Search by main type id", + "name": "mainType", "in": "query", "schema": { "type": "string" } }, { - "description": "Search for a specific signature", - "example": "Dagur B. Eggertsson", "required": false, + "description": "Search by title", "name": "search", "in": "query", "schema": { "type": "string" } }, { + "required": false, + "description": "Search by slug", + "name": "slug", + "in": "query", + "schema": { "type": "string" } + }, + { + "required": false, + "description": "Search by department slug, title or id", + "name": "department", + "in": "query", + "schema": { "type": "string" } + }, + { + "required": false, + "description": "The page number", "name": "page", - "description": "Page number to return.", + "in": "query", + "schema": { "type": "number" } + }, + { "required": false, + "description": "The page size", + "name": "pageSize", "in": "query", "schema": { "type": "number" } } ], "responses": { - "default": { + "200": { "description": "", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/GetAdvertSignatureResponse" - } + "schema": { "$ref": "#/components/schemas/GetAdvertTypes" } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/AdvertTypeError" } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/AdvertTypeError" } } } } } } }, - "/api/v1/cases": { + "/api/v1/advert-types/main-types": { "get": { - "operationId": "getCasesInProgress", + "operationId": "getMainTypes", + "summary": "", "parameters": [ { + "required": false, + "description": "Search by id", + "name": "id", + "in": "query", + "schema": { "type": "string" } + }, + { + "required": false, + "description": "Filter by unassigned", + "name": "unassigned", + "in": "query", + "schema": { "type": "boolean" } + }, + { + "required": false, + "description": "Search by main type id", + "name": "mainType", + "in": "query", + "schema": { "type": "string" } + }, + { + "required": false, + "description": "Search by title", "name": "search", - "description": "String to search for", + "in": "query", + "schema": { "type": "string" } + }, + { "required": false, + "description": "Search by slug", + "name": "slug", "in": "query", "schema": { "type": "string" } }, { - "name": "ids", "required": false, + "description": "Search by department slug, title or id", + "name": "department", "in": "query", - "schema": { - "default": [], - "type": "array", - "items": { "type": "string" } - } + "schema": { "type": "string" } }, { - "name": "page", - "description": "Page number to return.", "required": false, + "description": "The page number", + "name": "page", "in": "query", "schema": { "type": "number" } }, { - "name": "pageSize", - "description": "Page size number to return.", "required": false, + "description": "The page size", + "name": "pageSize", "in": "query", "schema": { "type": "number" } } ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/GetAdvertMainTypes" } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/AdvertTypeError" } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/AdvertTypeError" } + } + } + } + } + } + }, + "/api/v1/advert-types/types/{id}": { + "get": { + "operationId": "getTypeById", + "summary": "", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { "type": "string" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/GetAdvertType" } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/AdvertTypeError" } + } + } + }, + "404": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/AdvertTypeError" } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/AdvertTypeError" } + } + } + } + } + } + }, + "/api/v1/advert-types/main-types/{id}": { + "get": { + "operationId": "getMainTypeById", + "summary": "", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { "type": "string" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/GetAdvertMainType" } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/AdvertTypeError" } + } + } + }, + "404": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/AdvertTypeError" } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/AdvertTypeError" } + } + } + } + } + } + }, + "/api/v1/pdf/case/{id}": { + "get": { + "operationId": "getPdfByCaseId", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { "type": "string" } + } + ], "responses": { "default": { "description": "", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/GetCasesInProgressReponse" - } + "schema": { "$ref": "#/components/schemas/GetPdfRespone" } } } } } } }, - "/api/v1/error": { + "/api/v1/pdf/application/{id}": { "get": { - "operationId": "error", - "parameters": [], + "operationId": "getPdfByApplicationId", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { "type": "string" } + } + ], "responses": { "default": { "description": "", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ValidationResponse" } + "schema": { "$ref": "#/components/schemas/GetPdfRespone" } + } + } + } + } + } + }, + "/api/v1/pdf/case/{id}/url": { + "get": { + "operationId": "getPdfUrlByCaseId", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { "type": "string" } + } + ], + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/GetPdfUrlResponse" } + } + } + } + } + } + }, + "/api/v1/pdf/application/{id}/url": { + "get": { + "operationId": "getPdfUrlByApplicationId", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { "type": "string" } + } + ], + "responses": { + "default": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/GetPdfUrlResponse" } } } } @@ -551,23 +847,18 @@ "properties": { "id": { "type": "string", - "description": "Unique ID for the advert type, GUID format.", - "example": "00000000-0000-0000-0000-000000000000", - "nullable": false + "description": "The id of the main advert type" }, "title": { "type": "string", - "description": "Title of the advert type, always uppercased.", - "example": "AUGLÝSING" + "description": "The title of the main advert type" }, "slug": { "type": "string", - "description": "Slug of the advert type, used in URLs and API requests.", - "example": "auglysing" + "description": "The slug of the main advert type" }, "department": { - "description": "Department the advert type belongs to.", - "nullable": true, + "description": "The department of the main advert type", "allOf": [{ "$ref": "#/components/schemas/Department" }] } }, @@ -977,31 +1268,6 @@ }, "required": ["departments", "paging"] }, - "GetAdvertTypeResponse": { - "type": "object", - "properties": { - "type": { - "description": "Advert type", - "allOf": [{ "$ref": "#/components/schemas/AdvertType" }] - } - }, - "required": ["type"] - }, - "GetAdvertTypesResponse": { - "type": "object", - "properties": { - "types": { - "description": "List of advert types", - "type": "array", - "items": { "$ref": "#/components/schemas/AdvertType" } - }, - "paging": { - "description": "Paging info", - "allOf": [{ "$ref": "#/components/schemas/Paging" }] - } - }, - "required": ["types", "paging"] - }, "MainCategory": { "type": "object", "properties": { @@ -1190,6 +1456,108 @@ } }, "required": ["message", "statusCode"] + }, + "GetAdvertTypes": { + "type": "object", + "properties": { + "types": { + "description": "List of advert types", + "type": "array", + "items": { "$ref": "#/components/schemas/AdvertType" } + }, + "paging": { + "description": "Paging information", + "allOf": [{ "$ref": "#/components/schemas/Paging" }] + } + }, + "required": ["types", "paging"] + }, + "AdvertTypeError": { + "type": "object", + "properties": { + "errorType": { + "type": "string", + "enum": ["DuplicateError", "ValidationError", "NotFoundError"] + }, + "name": { "type": "string" }, + "message": { "type": "string" }, + "severity": { "type": "string", "enum": ["info", "warning", "error"] } + }, + "required": ["errorType", "name", "message", "severity"] + }, + "AdvertMainType": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The id of the main advert type" + }, + "title": { + "type": "string", + "description": "The title of the main advert type" + }, + "slug": { + "type": "string", + "description": "The slug of the main advert type" + }, + "department": { + "description": "The department this main type belongs to", + "allOf": [{ "$ref": "#/components/schemas/Department" }] + }, + "types": { + "description": "All types under this main type", + "type": "array", + "items": { "$ref": "#/components/schemas/AdvertType" } + } + }, + "required": ["id", "title", "slug", "department", "types"] + }, + "GetAdvertMainTypes": { + "type": "object", + "properties": { + "mainTypes": { + "description": "List of all main advert types", + "type": "array", + "items": { "$ref": "#/components/schemas/AdvertMainType" } + }, + "paging": { + "description": "Paging information", + "allOf": [{ "$ref": "#/components/schemas/Paging" }] + } + }, + "required": ["mainTypes", "paging"] + }, + "GetAdvertType": { + "type": "object", + "properties": { + "type": { + "description": "The advert type", + "allOf": [{ "$ref": "#/components/schemas/AdvertType" }] + } + }, + "required": ["type"] + }, + "GetAdvertMainType": { + "type": "object", + "properties": { + "mainType": { + "description": "The main advert type", + "allOf": [{ "$ref": "#/components/schemas/AdvertMainType" }] + } + }, + "required": ["mainType"] + }, + "GetPdfRespone": { + "type": "object", + "properties": { + "content": { "type": "string", "description": "Base64 encoded PDF" } + }, + "required": ["content"] + }, + "GetPdfUrlResponse": { + "type": "object", + "properties": { "url": { "type": "string" } }, + "required": ["url"] } } } diff --git a/libs/clients/official-journal-of-iceland/public/src/lib/officialJournalOfIcelandClient.service.ts b/libs/clients/official-journal-of-iceland/public/src/lib/officialJournalOfIcelandClient.service.ts index 1ab4b33951c9..a600c48cb36e 100644 --- a/libs/clients/official-journal-of-iceland/public/src/lib/officialJournalOfIcelandClient.service.ts +++ b/libs/clients/official-journal-of-iceland/public/src/lib/officialJournalOfIcelandClient.service.ts @@ -7,11 +7,13 @@ import { GetDepartmentsRequest, GetInstitutionsRequest, GetMainCategoriesRequest, - GetAdvertTypesRequest, GetDepartmentByIdRequest, - GetAdvertTypeByIdRequest, GetCasesInProgressRequest, + GetTypeByIdRequest, + GetTypesRequest, + GetMainTypesRequest, } from '../../gen/fetch/apis' +import { GetAdvertMainTypes } from '../../gen/fetch' @Injectable() export class OfficialJournalOfIcelandClientService { @@ -33,12 +35,18 @@ export class OfficialJournalOfIcelandClientService { return this.api.getDepartments(params ?? {}) } - public async getAdvertTypeById(params: GetAdvertTypeByIdRequest) { - return this.api.getAdvertTypeById(params) + public async getAdvertTypeById(params: GetTypeByIdRequest) { + return this.api.getTypeById(params) } - public async getAdvertTypes(params: GetAdvertTypesRequest) { - return this.api.getAdvertTypes(params) + public async getAdvertMainTypes( + params: GetMainTypesRequest, + ): Promise { + return this.api.getMainTypes(params) + } + + public async getAdvertTypes(params: GetTypesRequest) { + return this.api.getTypes(params) } public async getMainCategories(params: GetMainCategoriesRequest) { diff --git a/libs/judicial-system/types/src/lib/eventLog.ts b/libs/judicial-system/types/src/lib/eventLog.ts index fca7b91f81ea..5aa84c863960 100644 --- a/libs/judicial-system/types/src/lib/eventLog.ts +++ b/libs/judicial-system/types/src/lib/eventLog.ts @@ -15,6 +15,7 @@ export const eventTypes = Object.values(EventType) export enum DefendantEventType { SENT_TO_PRISON_ADMIN = 'SENT_TO_PRISON_ADMIN', + OPENED_BY_PRISON_ADMIN = 'OPENED_BY_PRISON_ADMIN', } export const defendantEventTypes = Object.values(DefendantEventType)