Skip to content

Commit

Permalink
fix(j-s): Resolving merge conflicts with main
Browse files Browse the repository at this point in the history
  • Loading branch information
thorhildurt committed Dec 19, 2024
2 parents 503ed03 + 68f32f0 commit 3630a37
Show file tree
Hide file tree
Showing 192 changed files with 4,743 additions and 3,040 deletions.
16 changes: 16 additions & 0 deletions apps/contentful-apps/pages/fields/admin-only-boolean-field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { FieldExtensionSDK } from '@contentful/app-sdk'
import { Paragraph } from '@contentful/f36-components'
import { BooleanEditor } from '@contentful/field-editor-boolean'
import { useSDK } from '@contentful/react-apps-toolkit'

const AdminOnlyBooleanField = () => {
const sdk = useSDK<FieldExtensionSDK>()

if (!sdk.user.spaceMembership.admin) {
return <Paragraph>(Only admins can edit this field)</Paragraph>
}

return <BooleanEditor field={sdk.field} isInitiallyDisabled={false} />
}

export default AdminOnlyBooleanField
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
10 changes: 10 additions & 0 deletions apps/judicial-system/backend/src/app/modules/case/case.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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,
}),
}))
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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'
Expand All @@ -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,
) {}

Expand All @@ -84,6 +89,7 @@ export class LimitedAccessCaseController {
)
@RolesRules(prisonSystemStaffRule, defenderRule)
@UseInterceptors(
DefendantIndictmentAccessedInterceptor,
CompletedAppealAccessedInterceptor,
LimitedAccessCaseFileInterceptor,
CaseInterceptor,
Expand All @@ -100,7 +106,7 @@ export class LimitedAccessCaseController {
): Promise<Case> {
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() },
Expand Down
Original file line number Diff line number Diff line change
@@ -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'

Expand All @@ -14,14 +14,18 @@ interface Then {
error: Error
}

type GivenWhenThen = (caseId: string, theCase: Case) => Promise<Then>
type GivenWhenThen = (
caseId: string,
theCase: Case,
user?: User,
) => Promise<Then>

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

Expand All @@ -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 {
Expand Down Expand Up @@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,22 @@ export class DefendantService {
return updatedDefendant
}

async createDefendantEvent({
caseId,
defendantId,
eventType,
}: {
caseId: string
defendantId: string
eventType: DefendantEventType
}): Promise<void> {
await this.defendantEventLogModel.create({
caseId,
defendantId,
eventType,
})
}

async updateIndictmentCaseDefendant(
theCase: Case,
defendant: Defendant,
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ query Case($input: CaseQueryInput!) {
subpoenaType
isSentToPrisonAdmin
sentToPrisonAdminDate
openedByPrisonAdminDate
punishmentType
subpoenas {
id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ query LimitedAccessCase($input: CaseQueryInput!) {
subpoenaType
isSentToPrisonAdmin
sentToPrisonAdminDate
openedByPrisonAdminDate
punishmentType
subpoenas {
id
Expand Down
16 changes: 16 additions & 0 deletions apps/judicial-system/web/src/components/Tags/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,19 @@ export const getPunishmentTypeTag = (
text: getPunishmentTypeLabel(punishmentType),
}
}

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 }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ export const DefenderCasesTable: FC<Props> = ({
) {
return entry.defendants[0].name ?? ''
}
if (column === 'courtDate') {
return entry.courtDate
}
return entry.created
}
const { sortedData, requestSort, getClassNamesFor, isActiveColumn } = useSort(
Expand Down Expand Up @@ -129,9 +132,13 @@ export const DefenderCasesTable: FC<Props> = ({
</th>
) : (
<th>
<Text fontWeight="regular">
{formatMessage(tables.hearingArrangementDate)}
</Text>
<SortButton
title={formatMessage(tables.hearingArrangementDate)}
onClick={() => requestSort('courtDate')}
sortAsc={getClassNamesFor('courtDate') === 'ascending'}
sortDes={getClassNamesFor('courtDate') === 'descending'}
isActive={isActiveColumn('courtDate')}
/>
</th>
)}
<th></th>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ const IndictmentOverview = () => {
})}
</Text>
)}
{defendant?.openedByPrisonAdminDate && (
<Text variant="h4" as="h3">
{formatMessage(strings.indictmentReceivedTitle, {
date: formatDate(defendant.openedByPrisonAdminDate, 'PPP'),
})}
</Text>
)}
</Box>
<Box marginBottom={5}>
<InfoCardClosedIndictment displayVerdictViewDate />
Expand Down
Loading

0 comments on commit 3630a37

Please sign in to comment.