Skip to content

Commit

Permalink
[Signalement] Ajout d'un bouton radio "Pas de réponse VHF" (#1158)
Browse files Browse the repository at this point in the history
## Related Pull Requests & Issues

- Resolve #1108
- Résolution du bug remonté ici :
#1133 (comment)

----

- [x] Tests E2E (Cypress)
  • Loading branch information
claire2212 authored Feb 2, 2024
2 parents c5903d9 + 57d737f commit 214ea78
Show file tree
Hide file tree
Showing 25 changed files with 179 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ data class ReportingEntity(
val attachedToMissionAtUtc: ZonedDateTime? = null,
val detachedFromMissionAtUtc: ZonedDateTime? = null,
val attachedEnvActionId: UUID? = null,
val withVHFAnswer: Boolean? = null,
) {
fun validate() {
when (sourceType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ data class CreateOrUpdateReportingDataInput(
val attachedToMissionAtUtc: ZonedDateTime? = null,
val detachedFromMissionAtUtc: ZonedDateTime? = null,
val attachedEnvActionId: UUID? = null,
val withVHFAnswer: Boolean? = null,
) {
fun toReportingEntity(): ReportingEntity {
return ReportingEntity(
Expand Down Expand Up @@ -65,6 +66,7 @@ data class CreateOrUpdateReportingDataInput(
attachedToMissionAtUtc = this.attachedToMissionAtUtc,
detachedFromMissionAtUtc = this.detachedFromMissionAtUtc,
attachedEnvActionId = this.attachedEnvActionId,
withVHFAnswer = this.withVHFAnswer,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ data class AttachedReportingDataOutput(
val attachedToMissionAtUtc: ZonedDateTime? = null,
val detachedFromMissionAtUtc: ZonedDateTime? = null,
val attachedEnvActionId: UUID? = null,
val withVHFAnswer: Boolean? = null,
) {
companion object {
fun fromReportingDTO(
Expand Down Expand Up @@ -88,6 +89,7 @@ data class AttachedReportingDataOutput(
attachedToMissionAtUtc = dto.reporting.attachedToMissionAtUtc,
detachedFromMissionAtUtc = dto.reporting.detachedFromMissionAtUtc,
attachedEnvActionId = dto.reporting.attachedEnvActionId,
withVHFAnswer = dto.reporting.withVHFAnswer,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ data class ReportingDataOutput(
val attachedEnvActionId: UUID? = null,
val attachedMission: ReportingMissionDataOutput? = null,
val controlStatus: ControlStatusEnum? = null,
val withVHFAnswer: Boolean? = null,
) {
companion object {
fun fromReportingDTO(
Expand Down Expand Up @@ -114,6 +115,7 @@ data class ReportingDataOutput(
null
},
controlStatus = dto.controlStatus,
withVHFAnswer = dto.reporting.withVHFAnswer,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ data class ReportingsDataOutput(
val detachedFromMissionAtUtc: ZonedDateTime? = null,
val attachedEnvActionId: UUID? = null,
val controlStatus: ControlStatusEnum? = null,
val withVHFAnswer: Boolean? = null,
) {
companion object {
fun fromReportingDTO(
Expand All @@ -55,8 +56,11 @@ data class ReportingsDataOutput(
sourceName = dto.reporting.sourceName,
displayedSource =
when (dto.reporting.sourceType) {
SourceTypeEnum.SEMAPHORE -> dto?.semaphore?.unit ?: dto?.semaphore?.name
// TODO This is really strange : `fullControlUnit?.controlUnit` can't be null and I have to add another `?`...
SourceTypeEnum.SEMAPHORE ->
dto?.semaphore?.unit
?: dto?.semaphore?.name
// TODO This is really strange : `fullControlUnit?.controlUnit`
// can't be null and I have to add another `?`...
SourceTypeEnum.CONTROL_UNIT -> dto?.controlUnit?.controlUnit?.name
SourceTypeEnum.OTHER -> dto.reporting.sourceName
else -> ""
Expand All @@ -82,6 +86,7 @@ data class ReportingsDataOutput(
detachedFromMissionAtUtc = dto.reporting.detachedFromMissionAtUtc,
attachedEnvActionId = dto.reporting.attachedEnvActionId,
controlStatus = dto.controlStatus,
withVHFAnswer = dto.reporting.withVHFAnswer,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ class Reportings(
@GetMapping("")
@Operation(summary = "Get reportings")
fun getAll(
@Parameter(description = "Is Attached to mission")
@RequestParam(name = "isAttachedToMission", required = false)
isAttachedToMission: Boolean?,
@Parameter(description = "page number")
@RequestParam(name = "pageNumber")
pageNumber: Int?,
Expand Down Expand Up @@ -119,9 +122,6 @@ class Reportings(
@Parameter(description = "Target type")
@RequestParam(name = "targetTypes", required = false)
targetTypes: List<TargetTypeEnum>?,
@Parameter(description = "Is Attached to mission")
@RequestParam(name = "isAttachedToMission", required = false)
isAttachedToMission: Boolean?,
@Parameter(description = "Search query")
@RequestParam(name = "searchQuery", required = false)
searchQuery: String?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class ReportingModel(
insertable = false,
)
val reportingId: Long? = null,

@Column(name = "source_type", columnDefinition = "reportings_source_type")
@Enumerated(EnumType.STRING)
@Type(PostgreSQLEnumType::class)
Expand Down Expand Up @@ -163,6 +164,9 @@ class ReportingModel(
referencedColumnName = "id",
)
val attachedEnvAction: EnvActionModel? = null,

@Column(name = "with_vhf_answer")
val withVHFAnswer: Boolean? = null,
) {

fun toReporting() =
Expand Down Expand Up @@ -194,7 +198,9 @@ class ReportingModel(
attachedToMissionAtUtc = attachedToMissionAtUtc?.atZone(UTC),
detachedFromMissionAtUtc = detachedFromMissionAtUtc?.atZone(UTC),
attachedEnvActionId = attachedEnvAction?.id,
withVHFAnswer = withVHFAnswer,
)

fun toReportingDTO(objectMapper: ObjectMapper) =
ReportingDTO(
reporting = this.toReporting(),
Expand Down Expand Up @@ -237,33 +243,35 @@ class ReportingModel(
missionReference: MissionModel?,
envActionReference: EnvActionModel?,
controlPlanThemeReference: ControlPlanThemeModel?,
) = ReportingModel(
id = reporting.id,
reportingId = reporting.reportingId,
sourceType = reporting.sourceType,
semaphore = semaphoreReference,
controlUnit = controlUnitReference,
sourceName = reporting.sourceName,
targetType = reporting.targetType,
vehicleType = reporting.vehicleType,
targetDetails = reporting.targetDetails,
geom = reporting.geom,
seaFront = reporting.seaFront,
description = reporting.description,
reportType = reporting.reportType,
controlPlanTheme = controlPlanThemeReference,
actionTaken = reporting.actionTaken,
isControlRequired = reporting.isControlRequired,
hasNoUnitAvailable = reporting.hasNoUnitAvailable,
createdAt = reporting.createdAt.toInstant(),
validityTime = reporting.validityTime,
isArchived = reporting.isArchived,
isDeleted = reporting.isDeleted,
openBy = reporting.openBy,
mission = missionReference,
attachedToMissionAtUtc = reporting.attachedToMissionAtUtc?.toInstant(),
detachedFromMissionAtUtc = reporting.detachedFromMissionAtUtc?.toInstant(),
attachedEnvAction = envActionReference,
)
) =
ReportingModel(
id = reporting.id,
reportingId = reporting.reportingId,
sourceType = reporting.sourceType,
semaphore = semaphoreReference,
controlUnit = controlUnitReference,
sourceName = reporting.sourceName,
targetType = reporting.targetType,
vehicleType = reporting.vehicleType,
targetDetails = reporting.targetDetails,
geom = reporting.geom,
seaFront = reporting.seaFront,
description = reporting.description,
reportType = reporting.reportType,
controlPlanTheme = controlPlanThemeReference,
actionTaken = reporting.actionTaken,
isControlRequired = reporting.isControlRequired,
hasNoUnitAvailable = reporting.hasNoUnitAvailable,
createdAt = reporting.createdAt.toInstant(),
validityTime = reporting.validityTime,
isArchived = reporting.isArchived,
isDeleted = reporting.isDeleted,
openBy = reporting.openBy,
mission = missionReference,
attachedToMissionAtUtc = reporting.attachedToMissionAtUtc?.toInstant(),
detachedFromMissionAtUtc = reporting.detachedFromMissionAtUtc?.toInstant(),
attachedEnvAction = envActionReference,
withVHFAnswer = reporting.withVHFAnswer,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

ALTER TABLE public.reportings
ADD COLUMN with_vhf_answer BOOLEAN DEFAULT null;
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class ReportingsITests {
isArchived = false,
isDeleted = false,
openBy = "CDA",
withVHFAnswer = null,
),
semaphore =
SemaphoreEntity(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ context('Reporting', () => {
})
})

it('An attached mission can be reinitialze during reporting creation', () => {
it('An attached mission can be reinitialize during reporting creation', () => {
// Given
cy.clickButton('Chercher des signalements')
cy.clickButton('Ajouter un signalement')
Expand Down Expand Up @@ -181,4 +181,64 @@ context('Reporting', () => {
expect(responseBody.attachedMission).equal(null)
})
})

it('A reporting can be created with withVHFAnswer only for `mouillage individuel` theme', () => {
cy.clickButton('Chercher des signalements')
cy.clickButton('Ajouter un signalement')

cy.intercept('PUT', '/bff/v1/reportings').as('createReporting')

cy.get('.Element-Legend').contains('Réponse à la VHF').should('not.exist')

cy.fill('Source', 'Autre')
cy.fill('Nom, société ...', 'Nom de ma société')

cy.clickButton('Ajouter un point')
cy.get('#root').click(450, 690, { timeout: 10000 })
cy.clickButton('Valider le point')
cy.fill('Type de signalement', 'Observation')
cy.fill('Thématique du signalement', 'Mouillage individuel')

cy.get('.Element-Legend').contains('Réponse à la VHF').should('be.visible')
cy.fill('Réponse à la VHF', 'Oui')

cy.fill('Saisi par', 'XYZ')

cy.clickButton('Valider le signalement')

cy.wait('@createReporting').then(({ request, response }) => {
expect(request.body.themeId).equal(100)
expect(request.body.withVHFAnswer).equal(true)

expect(response && response.statusCode).equal(201)
expect(response?.body.themeId).equal(100)
expect(response?.body.withVHFAnswer).equal(true)
})

// we update reporting theme and clean `withVHFAnswer` field
cy.intercept('PUT', '/bff/v1/reportings/*').as('updateReporting')
cy.get('#root').click(450, 690, { timeout: 10000 })

cy.clickButton('Editer le signalement')
cy.fill('Thématique du signalement', 'Bien culturel maritime')

cy.clickButton('Enregistrer et quitter')

cy.wait('@updateReporting').then(({ request, response }) => {
expect(request.body.themeId).equal(104)
expect(request.body.withVHFAnswer).equal(undefined)

expect(response && response.statusCode).equal(200)
expect(response?.body.themeId).equal(104)
expect(response?.body.withVHFAnswer).equal(null)
})

// delete reporting
cy.intercept('PUT', '/bff/v1/reportings/*').as('updateReporting')
cy.get('#root').click(450, 690, { timeout: 10000 })

cy.clickButton('Editer le signalement')
cy.clickButton('Supprimer le signalement')
cy.clickButton('Confirmer la suppression')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ const dispatch = action => cy.window().its('store').invoke('dispatch', action)
context('Side Window > Mission Form > Main Form', () => {
function visitSideWindow(isAutoSaveEnabled = 'true') {
cy.visit(`/side_window`, {
onBeforeLoad(window) {
onBeforeLoad(window: Cypress.AUTWindow & { env: { [key: string]: string } }) {
Object.defineProperty(window, 'EventSource', { value: EventSource })
Object.defineProperty(window, 'mockEventSources', { value: sources })

if (!window.env) {
Object.defineProperty(window, 'env', {
value: {
REACT_APP_CYPRESS_TEST: 'true',
REACT_APP_CYPRESS_TEST: true,
REACT_APP_MISSION_FORM_AUTO_SAVE_ENABLED: isAutoSaveEnabled,
REACT_APP_MISSION_FORM_AUTO_UPDATE: 'true'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ context('Mission', () => {

it('Missions should be created and saved in store When auto-save is not enabled', () => {
cy.visit(`/side_window`, {
onBeforeLoad(window) {
onBeforeLoad(window: Cypress.AUTWindow & { env: { [key: string]: string } }) {
if (!window.env) {
Object.defineProperty(window, 'env', {
value: {
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/domain/entities/reporting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export type Reporting = {
themeId?: number
validityTime?: number
vehicleType?: string
withVHFAnswer?: boolean | undefined
}

export type ReportingDetailed = Reporting & {
Expand Down Expand Up @@ -128,6 +129,8 @@ export enum AttachToMissionFilterLabels {
UNATTACHED = 'Non liés'
}

export const INDIVIDUAL_ANCHORING_THEME_ID = 100 // for 2024

export const getReportingStatus = ({
createdAt,
isArchived,
Expand All @@ -140,7 +143,7 @@ export const getReportingStatus = ({
validityTime?: number | undefined
}) => {
const endOfValidity = dayjs(createdAt)
.add(validityTime || 0, 'hour')
.add(validityTime ?? 0, 'hour')
.toISOString()
const timeLeft = dayjs(endOfValidity).diff(dayjs(), 'hour', true)

Expand All @@ -152,7 +155,6 @@ export const getReportingStatus = ({
return ReportingStatusEnum.OBSERVATION
}
if (reportType === ReportingTypeEnum.INFRACTION_SUSPICION) {
// TODO handle attached to mission
return ReportingStatusEnum.INFRACTION_SUSPICION
}

Expand Down
13 changes: 10 additions & 3 deletions frontend/src/domain/shared_slices/reporting.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createSlice, type PayloadAction } from '@reduxjs/toolkit'

import type { ReportingContext } from './Global'
import { ReportingContext } from './Global'

import type { AtLeast } from '../../types'
import type { Reporting, ReportingDetailed } from '../entities/reporting'

Expand Down Expand Up @@ -41,8 +42,14 @@ const reportingSlice = createSlice({
state.selectedReportingIdOnMap = undefined
}
},
resetReportings() {
return INITIAL_STATE
resetReportingsOnSideWindow(state, action: PayloadAction<Array<ReportingType>>) {
const reportingsToDelete = action.payload
reportingsToDelete.forEach(reporting => {
if (state.activeReportingId === reporting.reporting.id) {
state.activeReportingId = undefined
}
delete state.reportings[reporting.reporting.id]
})
},
setActiveReportingId(state, action: PayloadAction<number | string | undefined>) {
state.activeReportingId = action.payload
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export function Footer({ onCancel, onDelete, setMustIncreaseValidity, setShouldV
const reportingStatus = getReportingStatus(values)

const handleReopen = () => {
const endOfValidity = getLocalizedDayjs(values?.createdAt || customDayjs().toISOString()).add(
values?.validityTime || 0,
const endOfValidity = getLocalizedDayjs(values?.createdAt ?? customDayjs().toISOString()).add(
values?.validityTime ?? 0,
'hour'
)
const timeLeft = customDayjs(endOfValidity).diff(getLocalizedDayjs(customDayjs().toISOString()), 'hour', true)
Expand All @@ -39,7 +39,7 @@ export function Footer({ onCancel, onDelete, setMustIncreaseValidity, setShouldV
if (!activeReportingId || !reportings || !reportings[activeReportingId]) {
return
}
dispatch(reopenReporting({ ...values, isArchived: false }, reportingContext || ReportingContext.MAP))
dispatch(reopenReporting({ ...values, isArchived: false }, reportingContext ?? ReportingContext.MAP))

return
}
Expand Down Expand Up @@ -78,6 +78,7 @@ export function Footer({ onCancel, onDelete, setMustIncreaseValidity, setShouldV
color={THEME.color.maximumRed}
Icon={Icon.Delete}
onClick={onDelete}
title="Supprimer le signalement"
/>

<div>
Expand Down
Loading

0 comments on commit 214ea78

Please sign in to comment.