diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 39aa13031..000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - -npx lint-staged --cwd ./frontend diff --git a/Makefile b/Makefile index 1cfd243d9..36e3e7cdc 100644 --- a/Makefile +++ b/Makefile @@ -221,4 +221,7 @@ logs-db: # ALIASES +.PHONY: dev lint-back + dev: dev-run-back-with-infra +lint-back: dev-lint-backend diff --git a/backend/pom.xml b/backend/pom.xml index 1ef86532e..e2c3f149d 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -407,7 +407,7 @@ com.pinterest ktlint - 0.48.2 + 0.50.0 diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionControlProperties.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionControlProperties.kt index ef27f29b4..8492bea50 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionControlProperties.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionControlProperties.kt @@ -13,7 +13,14 @@ data class EnvActionControlProperties( val vehicleType: VehicleTypeEnum? = null, val infractions: List? = listOf(), ) { - fun toEnvActionControlEntity(id: UUID, actionStartDateTimeUtc: ZonedDateTime?, actionEndDateTimeUtc: ZonedDateTime?, facade: String?, department: String?, geom: Geometry?) = EnvActionControlEntity( + fun toEnvActionControlEntity( + id: UUID, + actionStartDateTimeUtc: ZonedDateTime?, + actionEndDateTimeUtc: ZonedDateTime?, + facade: String?, + department: String?, + geom: Geometry?, + ) = EnvActionControlEntity( id = id, actionStartDateTimeUtc = actionStartDateTimeUtc, actionEndDateTimeUtc = actionEndDateTimeUtc, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionNoteProperties.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionNoteProperties.kt index 5ce323622..4f72c37f7 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionNoteProperties.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionNoteProperties.kt @@ -6,7 +6,11 @@ import java.util.* data class EnvActionNoteProperties( val observations: String? = null, ) { - fun toEnvActionNoteEntity(id: UUID, actionStartDateTimeUtc: ZonedDateTime?, actionEndDateTimeUtc: ZonedDateTime?) = EnvActionNoteEntity( + fun toEnvActionNoteEntity( + id: UUID, + actionStartDateTimeUtc: ZonedDateTime?, + actionEndDateTimeUtc: ZonedDateTime?, + ) = EnvActionNoteEntity( id = id, actionStartDateTimeUtc = actionStartDateTimeUtc, actionEndDateTimeUtc = actionEndDateTimeUtc, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionSurveillanceProperties.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionSurveillanceProperties.kt index 5ef02588a..608f150c8 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionSurveillanceProperties.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/EnvActionSurveillanceProperties.kt @@ -9,7 +9,14 @@ data class EnvActionSurveillanceProperties( val observations: String? = null, val coverMissionZone: Boolean? = null, ) { - fun toEnvActionSurveillanceEntity(id: UUID, actionStartDateTimeUtc: ZonedDateTime?, actionEndDateTimeUtc: ZonedDateTime?, facade: String?, department: String?, geom: Geometry?) = EnvActionSurveillanceEntity( + fun toEnvActionSurveillanceEntity( + id: UUID, + actionStartDateTimeUtc: ZonedDateTime?, + actionEndDateTimeUtc: ZonedDateTime?, + facade: String?, + department: String?, + geom: Geometry?, + ) = EnvActionSurveillanceEntity( id = id, actionStartDateTimeUtc = actionStartDateTimeUtc, actionEndDateTimeUtc = actionEndDateTimeUtc, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/VesselSizeEnum.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/VesselSizeEnum.kt index f5c71db5b..cb43f2c28 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/VesselSizeEnum.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/mission/VesselSizeEnum.kt @@ -1,10 +1,10 @@ +@file:Suppress("ktlint:standard:enum-entry-name-case") + package fr.gouv.cacem.monitorenv.domain.entities.mission -/* ktlint-disable enum-entry-name-case */ enum class VesselSizeEnum { LESS_THAN_12m, FROM_12_TO_24m, FROM_24_TO_46m, MORE_THAN_46m, } -/* ktlint-enable enum-entry-name-case */ diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/mappers/EnvActionMapper.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/mappers/EnvActionMapper.kt index 0fcaae7de..a91bad3c8 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/mappers/EnvActionMapper.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/mappers/EnvActionMapper.kt @@ -23,9 +23,32 @@ object EnvActionMapper { return try { if (!value.isNullOrEmpty() && value != jsonbNullString) { when (actionType) { - ActionTypeEnum.SURVEILLANCE -> mapper.readValue(value, EnvActionSurveillanceProperties::class.java).toEnvActionSurveillanceEntity(id, actionStartDateTimeUtc, actionEndDateTimeUtc, facade, department, geom) - ActionTypeEnum.CONTROL -> mapper.readValue(value, EnvActionControlProperties::class.java).toEnvActionControlEntity(id, actionStartDateTimeUtc, actionEndDateTimeUtc, facade, department, geom) - ActionTypeEnum.NOTE -> mapper.readValue(value, EnvActionNoteProperties::class.java).toEnvActionNoteEntity(id, actionStartDateTimeUtc, actionEndDateTimeUtc) + ActionTypeEnum.SURVEILLANCE -> mapper.readValue( + value, + EnvActionSurveillanceProperties::class.java, + ).toEnvActionSurveillanceEntity( + id, + actionStartDateTimeUtc, + actionEndDateTimeUtc, + facade, + department, + geom, + ) + ActionTypeEnum.CONTROL -> mapper.readValue( + value, + EnvActionControlProperties::class.java, + ).toEnvActionControlEntity( + id, + actionStartDateTimeUtc, + actionEndDateTimeUtc, + facade, + department, + geom, + ) + ActionTypeEnum.NOTE -> mapper.readValue( + value, + EnvActionNoteProperties::class.java, + ).toEnvActionNoteEntity(id, actionStartDateTimeUtc, actionEndDateTimeUtc) } } else { throw EntityConversionException("No action value found.") diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IReportingRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IReportingRepository.kt index 30c73d5ba..bcccd9148 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IReportingRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/repositories/IReportingRepository.kt @@ -3,19 +3,19 @@ package fr.gouv.cacem.monitorenv.domain.repositories import fr.gouv.cacem.monitorenv.domain.entities.reporting.ReportingEntity import fr.gouv.cacem.monitorenv.domain.entities.reporting.ReportingTypeEnum import fr.gouv.cacem.monitorenv.domain.entities.reporting.SourceTypeEnum -import java.time.Instant import org.springframework.data.domain.Pageable +import java.time.Instant interface IReportingRepository { fun findById(reportingId: Int): ReportingEntity fun findAll( - pageable: Pageable, - reportingType: List?, - seaFronts: List?, - sourcesType: List?, - startedAfter: Instant, - startedBefore: Instant?, - status: List?, + pageable: Pageable, + reportingType: List?, + seaFronts: List?, + sourcesType: List?, + startedAfter: Instant, + startedBefore: Instant?, + status: List?, ): List fun save(reporting: ReportingEntity): ReportingEntity fun delete(reportingId: Int) diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlThemes/GetAllControlThemes.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlThemes/GetAllControlThemes.kt index a4b24bc32..03d8f3e59 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlThemes/GetAllControlThemes.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlThemes/GetAllControlThemes.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.controlThemes // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.controlThemes import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.entities.controlTheme.ControlThemeEntity diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlThemes/GetControlThemeById.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlThemes/GetControlThemeById.kt index 1eab9ce4a..285f7b952 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlThemes/GetControlThemeById.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlThemes/GetControlThemeById.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.controlThemes // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.controlThemes import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.entities.controlTheme.ControlThemeEntity diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlUnit/DeleteControlUnitContact.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlUnit/DeleteControlUnitContact.kt new file mode 100644 index 000000000..29f39ab49 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlUnit/DeleteControlUnitContact.kt @@ -0,0 +1,11 @@ +package fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit + +import fr.gouv.cacem.monitorenv.config.UseCase +import fr.gouv.cacem.monitorenv.domain.repositories.IControlUnitContactRepository + +@UseCase +class DeleteControlUnitContact(private val controlUnitContactRepository: IControlUnitContactRepository) { + fun execute(controlUnitContactId: Int) { + return controlUnitContactRepository.deleteById(controlUnitContactId) + } +} diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlUnit/DeleteControlUnitResource.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlUnit/DeleteControlUnitResource.kt new file mode 100644 index 000000000..02d5ea929 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/controlUnit/DeleteControlUnitResource.kt @@ -0,0 +1,11 @@ +package fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit + +import fr.gouv.cacem.monitorenv.config.UseCase +import fr.gouv.cacem.monitorenv.domain.repositories.IControlUnitResourceRepository + +@UseCase +class DeleteControlUnitResource(private val controlUnitResourceRepository: IControlUnitResourceRepository) { + fun execute(controlUnitResourceId: Int) { + return controlUnitResourceRepository.deleteById(controlUnitResourceId) + } +} diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/healthcheck/GetHealthcheck.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/healthcheck/GetHealthcheck.kt index c41b2cfb5..bef235ec4 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/healthcheck/GetHealthcheck.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/healthcheck/GetHealthcheck.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.healthcheck // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.healthcheck import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.entities.health.Health diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMission.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMission.kt index c0817e2b0..c9408942f 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMission.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/CreateOrUpdateMission.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.missions // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.missions import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.entities.mission.* @@ -14,7 +16,7 @@ class CreateOrUpdateMission( private val missionRepository: IMissionRepository, private val facadeRepository: IFacadeAreasRepository, - ) { +) { @Throws(IllegalArgumentException::class) fun execute(mission: MissionEntity?): MissionEntity { require(mission != null) { @@ -24,10 +26,14 @@ class CreateOrUpdateMission( when (it.actionType) { ActionTypeEnum.CONTROL -> { (it as EnvActionControlEntity).copy( - facade = (it.geom - ?: mission.geom)?.let { geom -> facadeRepository.findFacadeFromGeometry(geom) }, - department = (it.geom - ?: mission.geom)?.let { geom -> departmentRepository.findDepartmentFromGeometry(geom) }, + facade = ( + it.geom + ?: mission.geom + )?.let { geom -> facadeRepository.findFacadeFromGeometry(geom) }, + department = ( + it.geom + ?: mission.geom + )?.let { geom -> departmentRepository.findDepartmentFromGeometry(geom) }, ) } @@ -39,9 +45,15 @@ class CreateOrUpdateMission( Ideally the fallbacks should not be needed, but if coverMissionZone is true and the mission geom is null, or if coverMissionZone is false and the action geom is null, then rather that nothing, better use the geometry that is available, if any. - */ - val geometry = if (surveillance.coverMissionZone == true) (mission.geom - ?: surveillance.geom) else (surveillance.geom ?: mission.geom) + */ + val geometry = if (surveillance.coverMissionZone == true) { + ( + mission.geom + ?: surveillance.geom + ) + } else { + (surveillance.geom ?: mission.geom) + } surveillance.copy( facade = geometry?.let { geom -> facadeRepository.findFacadeFromGeometry(geom) }, department = geometry?.let { geom -> departmentRepository.findDepartmentFromGeometry(geom) }, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/DeleteMission.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/DeleteMission.kt index c6c44ff5c..62d9b8d04 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/DeleteMission.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/DeleteMission.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.missions // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.missions import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.repositories.IMissionRepository diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissionById.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissionById.kt index 688ecc2a3..1dcda3563 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissionById.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissionById.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.missions // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.missions import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionEntity diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissions.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissions.kt index 3423112a6..4e0982c01 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissions.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMissions.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.missions // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.missions import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionEntity @@ -30,7 +32,14 @@ class GetMissions(private val missionRepository: IMissionRepository) { missionTypes = missionTypes, missionStatuses = missionStatuses, seaFronts = seaFronts, - pageable = if (pageNumber != null && pageSize != null) PageRequest.of(pageNumber, pageSize) else Pageable.unpaged(), + pageable = if (pageNumber != null && pageSize != null) { + PageRequest.of( + pageNumber, + pageSize, + ) + } else { + Pageable.unpaged() + }, ) logger.info("Found ${missions.size} mission(s)") diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMonitorEnvMissions.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMonitorEnvMissions.kt index 9cc263b4f..efee067a2 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMonitorEnvMissions.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/missions/GetMonitorEnvMissions.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.missions // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.missions import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.entities.mission.MissionEntity @@ -30,10 +32,14 @@ class GetMonitorEnvMissions(private val missionRepository: IMissionRepository) { missionStatuses = missionStatuses, missionSources = missionSources ?: listOf(MissionSourceEnum.MONITORENV, MissionSourceEnum.MONITORFISH), seaFronts = seaFronts, - pageable = if (pageNumber != null && pageSize != null) PageRequest.of( - pageNumber, - pageSize - ) else Pageable.unpaged(), + pageable = if (pageNumber != null && pageSize != null) { + PageRequest.of( + pageNumber, + pageSize, + ) + } else { + Pageable.unpaged() + }, ) logger.info("Found ${missions.size} mission(s)") diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/natinfs/GetAllNatinfs.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/natinfs/GetAllNatinfs.kt index 3d7de0e97..041c21633 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/natinfs/GetAllNatinfs.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/natinfs/GetAllNatinfs.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.natinfs // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.natinfs import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.entities.natinf.NatinfEntity diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/regulatoryAreas/GetAllRegulatoryAreas.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/regulatoryAreas/GetAllRegulatoryAreas.kt index 25f98fe93..b5e93acae 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/regulatoryAreas/GetAllRegulatoryAreas.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/regulatoryAreas/GetAllRegulatoryAreas.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.regulatoryAreas // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.regulatoryAreas import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.entities.regulatoryArea.RegulatoryAreaEntity diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/regulatoryAreas/GetRegulatoryAreaById.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/regulatoryAreas/GetRegulatoryAreaById.kt index f162f0015..bf377951c 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/regulatoryAreas/GetRegulatoryAreaById.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/regulatoryAreas/GetRegulatoryAreaById.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases.regulatoryAreas // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases.regulatoryAreas import fr.gouv.cacem.monitorenv.config.UseCase import fr.gouv.cacem.monitorenv.domain.entities.regulatoryArea.RegulatoryAreaEntity diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/ArchiveOutdatedReportings.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/ArchiveOutdatedReportings.kt index 348d13a4f..c77581229 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/ArchiveOutdatedReportings.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/ArchiveOutdatedReportings.kt @@ -8,7 +8,7 @@ import org.springframework.scheduling.annotation.Scheduled @UseCase class ArchiveOutdatedReportings( - private val reportingRepository: IReportingRepository, + private val reportingRepository: IReportingRepository, ) { private val logger: Logger = LoggerFactory.getLogger(ArchiveOutdatedReportings::class.java) diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/ArchiveReportings.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/ArchiveReportings.kt index 5a5346177..5cb329fdf 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/ArchiveReportings.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/ArchiveReportings.kt @@ -10,13 +10,13 @@ class ArchiveReportings( private val reportingRepository: IReportingRepository, ) { - private val logger: Logger = LoggerFactory.getLogger(ArchiveReportings::class.java) + private val logger: Logger = LoggerFactory.getLogger(ArchiveReportings::class.java) - @Throws(IllegalArgumentException::class) - fun execute(ids: List) { - logger.info("Archive reportings: $ids") + @Throws(IllegalArgumentException::class) + fun execute(ids: List) { + logger.info("Archive reportings: $ids") - require(ids.isNotEmpty()) { "No reportings to archive" } - return reportingRepository.archiveReportings(ids) - } + require(ids.isNotEmpty()) { "No reportings to archive" } + return reportingRepository.archiveReportings(ids) + } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/DeleteReportings.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/DeleteReportings.kt index 0c3c38931..a6b094baa 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/DeleteReportings.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/reportings/DeleteReportings.kt @@ -10,13 +10,13 @@ class DeleteReportings( private val reportingRepository: IReportingRepository, ) { - private val logger: Logger = LoggerFactory.getLogger(DeleteReportings::class.java) + private val logger: Logger = LoggerFactory.getLogger(DeleteReportings::class.java) - @Throws(IllegalArgumentException::class) - fun execute(ids: List) { - logger.info("Delete reportings: $ids") + @Throws(IllegalArgumentException::class) + fun execute(ids: List) { + logger.info("Delete reportings: $ids") - require(ids.isNotEmpty()) { "No reportings to delete" } - return reportingRepository.deleteReportings(ids) - } + require(ids.isNotEmpty()) { "No reportings to delete" } + return reportingRepository.deleteReportings(ids) + } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/inputs/CreateOrUpdateControlUnitDataInput.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/inputs/CreateOrUpdateControlUnitDataInput.kt index 1797289cb..fecdf5e80 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/inputs/CreateOrUpdateControlUnitDataInput.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/inputs/CreateOrUpdateControlUnitDataInput.kt @@ -11,8 +11,7 @@ data class CreateOrUpdateControlUnitDataInput( val name: String, val termsNote: String? = null, ) { - fun toControlUnit( - ): ControlUnitEntity { + fun toControlUnit(): ControlUnitEntity { return ControlUnitEntity( id = this.id, areaNote = this.areaNote, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/ControlUnitResourceDataOutput.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/ControlUnitResourceDataOutput.kt index a620278b0..7a78b7f2e 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/ControlUnitResourceDataOutput.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/ControlUnitResourceDataOutput.kt @@ -1,7 +1,6 @@ package fr.gouv.cacem.monitorenv.infrastructure.api.adapters.publicapi.outputs import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.ControlUnitResourceEntity -import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.ControlUnitResourceType data class ControlUnitResourceDataOutput( val id: Int, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitContactDataOutput.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitContactDataOutput.kt index 041edac38..14777e0c5 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitContactDataOutput.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitContactDataOutput.kt @@ -11,7 +11,9 @@ data class FullControlUnitContactDataOutput( val phone: String? = null, ) { companion object { - fun fromFullControlUnitContact(fullControlUnitContact: FullControlUnitContactDTO): FullControlUnitContactDataOutput { + fun fromFullControlUnitContact( + fullControlUnitContact: FullControlUnitContactDTO, + ): FullControlUnitContactDataOutput { val controlUnit = ControlUnitDataOutput.fromControlUnit(fullControlUnitContact.controlUnit) return FullControlUnitContactDataOutput( diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitDataOutput.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitDataOutput.kt index 156f34ae4..a91c8441c 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitDataOutput.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitDataOutput.kt @@ -24,7 +24,7 @@ data class FullControlUnitDataOutput( val administration = AdministrationDataOutput.fromAdministration(fullControlUnit.administration) val controlUnitContacts = fullControlUnit.controlUnitContacts.map { ControlUnitContactDataOutput.fromControlUnitContact( - it + it, ) } val controlUnitResources = fullControlUnit.controlUnitResources.map { @@ -32,7 +32,6 @@ data class FullControlUnitDataOutput( } val departmentArea = fullControlUnit.departmentArea?.let { DepartmentAreaDataOutput.fromDepartmentArea(it) } - return FullControlUnitDataOutput( id = requireNotNull(fullControlUnit.controlUnit.id), areaNote = fullControlUnit.controlUnit.areaNote, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitResourceDataOutput.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitResourceDataOutput.kt index 8f48b5c31..1d67732cd 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitResourceDataOutput.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/publicapi/outputs/FullControlUnitResourceDataOutput.kt @@ -15,7 +15,9 @@ data class FullControlUnitResourceDataOutput( val type: ControlUnitResourceType, ) { companion object { - fun fromFullControlUnitResource(fullControlUnitResource: FullControlUnitResourceDTO): FullControlUnitResourceDataOutput { + fun fromFullControlUnitResource( + fullControlUnitResource: FullControlUnitResourceDTO, + ): FullControlUnitResourceDataOutput { val base = BaseDataOutput.fromBase(fullControlUnitResource.base) val controlUnit = ControlUnitDataOutput.fromControlUnit(fullControlUnitResource.controlUnit) diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/ReportingsController.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/ReportingsController.kt index ab777bd31..b5589228d 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/ReportingsController.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/ReportingsController.kt @@ -15,7 +15,6 @@ import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.Parameter import io.swagger.v3.oas.annotations.tags.Tag import jakarta.websocket.server.PathParam -import java.time.ZonedDateTime import org.springframework.format.annotation.DateTimeFormat import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.DeleteMapping @@ -27,79 +26,80 @@ import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController +import java.time.ZonedDateTime @RestController @RequestMapping("/bff/v1/reportings") @Tag(description = "API des Signalements", name = "Reportings") class ReportingsController( - private val createOrUpdateReporting: CreateOrUpdateReporting, - private val getReportingById: GetReportingById, - private val getReportings: GetReportings, - private val deleteReporting: DeleteReporting, - private val deleteReportings: DeleteReportings, - private val archiveReportings: ArchiveReportings, + private val createOrUpdateReporting: CreateOrUpdateReporting, + private val getReportingById: GetReportingById, + private val getReportings: GetReportings, + private val deleteReporting: DeleteReporting, + private val deleteReportings: DeleteReportings, + private val archiveReportings: ArchiveReportings, ) { @GetMapping("") @Operation(summary = "Get reportings") fun getReportingsController( - @Parameter(description = "page number") - @RequestParam(name = "pageNumber") - pageNumber: Int?, - @Parameter(description = "page size") @RequestParam(name = "pageSize") pageSize: Int?, - @Parameter(description = "Reporting created after date") - @RequestParam(name = "startedAfterDateTime", required = false) - @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) - startedAfterDateTime: ZonedDateTime?, - @Parameter(description = "Reporting created before date") - @RequestParam(name = "startedBeforeDateTime", required = false) - @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) - startedBeforeDateTime: ZonedDateTime?, - @Parameter(description = "Reporting type") - @RequestParam(name = "reportingType", required = false) - reportingType: List?, - @Parameter(description = "Facades") - @RequestParam(name = "seaFronts", required = false) - seaFronts: List?, - @Parameter(description = "Reporting source types") - @RequestParam(name = "sourcesType", required = false) - sourcesType: List?, - @Parameter(description = "Reporting status") - @RequestParam(name = "status", required = false) - status: List?, + @Parameter(description = "page number") + @RequestParam(name = "pageNumber") + pageNumber: Int?, + @Parameter(description = "page size") @RequestParam(name = "pageSize") pageSize: Int?, + @Parameter(description = "Reporting created after date") + @RequestParam(name = "startedAfterDateTime", required = false) + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) + startedAfterDateTime: ZonedDateTime?, + @Parameter(description = "Reporting created before date") + @RequestParam(name = "startedBeforeDateTime", required = false) + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) + startedBeforeDateTime: ZonedDateTime?, + @Parameter(description = "Reporting type") + @RequestParam(name = "reportingType", required = false) + reportingType: List?, + @Parameter(description = "Facades") + @RequestParam(name = "seaFronts", required = false) + seaFronts: List?, + @Parameter(description = "Reporting source types") + @RequestParam(name = "sourcesType", required = false) + sourcesType: List?, + @Parameter(description = "Reporting status") + @RequestParam(name = "status", required = false) + status: List?, ): List { return getReportings.execute( - pageNumber = pageNumber, - pageSize = pageSize, - reportingType = reportingType, - seaFronts = seaFronts, - sourcesType = sourcesType, - startedAfterDateTime = startedAfterDateTime, - startedBeforeDateTime = startedBeforeDateTime, - status = status, - ) - .map { ReportingDetailedDataOutput.fromReporting(it.first, it.second, it.third) } + pageNumber = pageNumber, + pageSize = pageSize, + reportingType = reportingType, + seaFronts = seaFronts, + sourcesType = sourcesType, + startedAfterDateTime = startedAfterDateTime, + startedBeforeDateTime = startedBeforeDateTime, + status = status, + ) + .map { ReportingDetailedDataOutput.fromReporting(it.first, it.second, it.third) } } @PutMapping("", consumes = ["application/json"]) @Operation(summary = "Create a new reporting") @ResponseStatus(HttpStatus.CREATED) fun createReportingController( - @RequestBody createReporting: CreateOrUpdateReportingDataInput, + @RequestBody createReporting: CreateOrUpdateReportingDataInput, ): ReportingDataOutput { val newReporting = createReporting.toReportingEntity() val createdReporting = createOrUpdateReporting.execute(newReporting) return ReportingDataOutput.fromReporting( - createdReporting.first, - createdReporting.second, - createdReporting.third, + createdReporting.first, + createdReporting.second, + createdReporting.third, ) } @GetMapping("/{id}") @Operation(summary = "Get reporting by id") fun getReportingByIdController( - @PathParam("reporting id") @PathVariable(name = "id") id: Int, + @PathParam("reporting id") @PathVariable(name = "id") id: Int, ): ReportingDataOutput { return getReportingById.execute(id).let { ReportingDataOutput.fromReporting(it.first, it.second, it.third) @@ -109,21 +109,21 @@ class ReportingsController( @PutMapping(value = ["/{id}"], consumes = ["application/json"]) @Operation(summary = "update a reporting") fun updateReportingController( - @PathParam("reporting id") @PathVariable(name = "id") id: Int, - @RequestBody reporting: CreateOrUpdateReportingDataInput, + @PathParam("reporting id") @PathVariable(name = "id") id: Int, + @RequestBody reporting: CreateOrUpdateReportingDataInput, ): ReportingDataOutput { require(id == reporting.id) { "id in path and body must be the same" } return createOrUpdateReporting.execute( - reporting.toReportingEntity(), - ) - .let { ReportingDataOutput.fromReporting(it.first, it.second, it.third) } + reporting.toReportingEntity(), + ) + .let { ReportingDataOutput.fromReporting(it.first, it.second, it.third) } } @DeleteMapping(value = ["/{id}"]) @Operation(summary = "Delete a reporting") @ResponseStatus(HttpStatus.NO_CONTENT) fun deleteController( - @PathParam("Id") @PathVariable(name = "id") id: Int, + @PathParam("Id") @PathVariable(name = "id") id: Int, ) { deleteReporting.execute(id = id) } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/SemaphoresController.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/SemaphoresController.kt index d3b49b66e..b8aba5bb4 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/SemaphoresController.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/SemaphoresController.kt @@ -14,7 +14,10 @@ import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/bff/v1/semaphores") @Tag(description = "API Semaphores", name = "Semaphores") -class SemaphoresController(private val getAllSemaphores: GetAllSemaphores, private val getSemaphoreById: GetSemaphoreById) { +class SemaphoresController( + private val getAllSemaphores: GetAllSemaphores, + private val getSemaphoreById: GetSemaphoreById, +) { @GetMapping("") @Operation(summary = "Get all semaphores") fun getSemaphoresController(): List { diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsController.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsController.kt index d29024463..ead4d423c 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsController.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsController.kt @@ -84,7 +84,7 @@ class ApiAdministrationsController( ): AdministrationDataOutput { requireNotNull(updateAdministrationDataInput.id) { "`id` can't be null." } require(administrationId == updateAdministrationDataInput.id) { - "Body ID ('${updateAdministrationDataInput.id}') doesn't match path ID ('${administrationId}')." + "Body ID ('${updateAdministrationDataInput.id}') doesn't match path ID ('$administrationId')." } val nextAdministration = updateAdministrationDataInput.toAdministration() diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiBasesController.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiBasesController.kt index 140cff479..375e74a83 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiBasesController.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiBasesController.kt @@ -64,7 +64,7 @@ class ApiBasesController( ): BaseDataOutput { requireNotNull(updateBaseDataInput.id) { "`id` can't be null." } require(baseId == updateBaseDataInput.id) { - "Body ID ('${updateBaseDataInput.id}') doesn't match path ID ('${baseId}')." + "Body ID ('${updateBaseDataInput.id}') doesn't match path ID ('$baseId')." } val nextBase = updateBaseDataInput.toBase() diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitContactsController.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitContactsController.kt index 73b6f8eff..da14d617e 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitContactsController.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitContactsController.kt @@ -1,6 +1,7 @@ package fr.gouv.cacem.monitorenv.infrastructure.api.endpoints.publicapi import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.CreateOrUpdateControlUnitContact +import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.DeleteControlUnitContact import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.GetControlUnitContactById import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.GetControlUnitContacts import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.publicapi.inputs.CreateOrUpdateControlUnitContactDataInput @@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.* @Tag(name = "Control Unit Contacts") class ApiControlUnitContactsController( private val createOrUpdateControlUnitContact: CreateOrUpdateControlUnitContact, + private val deleteControlUnitContact: DeleteControlUnitContact, private val getControlUnitContacts: GetControlUnitContacts, private val getControlUnitContactById: GetControlUnitContactById, ) { @@ -32,6 +34,16 @@ class ApiControlUnitContactsController( return ControlUnitContactDataOutput.fromControlUnitContact(createdControlUnitContact) } + @DeleteMapping("/{controlUnitContactId}") + @Operation(summary = "Delete a control unit contact") + fun delete( + @PathParam("Control unit contact ID") + @PathVariable(name = "controlUnitContactId") + controlUnitContactId: Int, + ) { + deleteControlUnitContact.execute(controlUnitContactId) + } + @GetMapping("/{controlUnitContactId}") @Operation(summary = "Get a control unit contact by its ID") fun get( @@ -60,7 +72,7 @@ class ApiControlUnitContactsController( ): ControlUnitContactDataOutput { requireNotNull(updateControlUnitContactDataInput.id) { "`id` can't be null." } require(controlUnitContactId == updateControlUnitContactDataInput.id) { - "Body ID ('${updateControlUnitContactDataInput.id}') doesn't match path ID ('${controlUnitContactId}')." + "Body ID ('${updateControlUnitContactDataInput.id}') doesn't match path ID ('$controlUnitContactId')." } val nextControlUnitContact = updateControlUnitContactDataInput.toControlUnitContact() diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitResourcesController.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitResourcesController.kt index 277187fe1..f28df1809 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitResourcesController.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitResourcesController.kt @@ -1,6 +1,7 @@ package fr.gouv.cacem.monitorenv.infrastructure.api.endpoints.publicapi import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.CreateOrUpdateControlUnitResource +import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.DeleteControlUnitResource import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.GetControlUnitResourceById import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.GetControlUnitResources import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.publicapi.inputs.CreateOrUpdateControlUnitResourceDataInput @@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.* @Tag(name = "Control Unit Resources") class ApiControlUnitResourcesController( private val createOrUpdateControlUnitResource: CreateOrUpdateControlUnitResource, + private val deleteControlUnitResource: DeleteControlUnitResource, private val getControlUnitResources: GetControlUnitResources, private val getControlUnitResourceById: GetControlUnitResourceById, ) { @@ -33,6 +35,16 @@ class ApiControlUnitResourcesController( return ControlUnitResourceDataOutput.fromControlUnitResource(createdControlUnitResource) } + @DeleteMapping("/{controlUnitResourceId}") + @Operation(summary = "Delete a control unit resource") + fun delete( + @PathParam("Control unit resource ID") + @PathVariable(name = "controlUnitResourceId") + controlUnitResourceId: Int, + ) { + deleteControlUnitResource.execute(controlUnitResourceId) + } + @GetMapping("/{controlUnitResourceId}") @Operation(summary = "Get a control unit resource by its ID") fun get( @@ -63,7 +75,7 @@ class ApiControlUnitResourcesController( ): ControlUnitResourceDataOutput { requireNotNull(updateControlUnitResourceDataInput.id) { "`id` can't be null." } require(controlUnitResourceId == updateControlUnitResourceDataInput.id) { - "Body ID ('${updateControlUnitResourceDataInput.id}') doesn't match path ID ('${controlUnitResourceId}')." + "Body ID ('${updateControlUnitResourceDataInput.id}') doesn't match path ID ('$controlUnitResourceId')." } val controlUnitResource = updateControlUnitResourceDataInput.toControlUnitResource() diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsController.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsController.kt index e70e3fea8..123eee872 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsController.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsController.kt @@ -84,7 +84,7 @@ class ApiControlUnitsController( ): ControlUnitDataOutput { requireNotNull(updateControlUnitDataInput.id) { "`id` can't be null." } require(controlUnitId == updateControlUnitDataInput.id) { - "Body ID ('${updateControlUnitDataInput.id}') doesn't match path ID ('${controlUnitId}')." + "Body ID ('${updateControlUnitDataInput.id}') doesn't match path ID ('$controlUnitId')." } val nextControlUnit = updateControlUnitDataInput.toControlUnit() diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/AdministrationModel.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/AdministrationModel.kt index b61a04f0e..87f0df6c9 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/AdministrationModel.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/AdministrationModel.kt @@ -41,7 +41,7 @@ data class AdministrationModel( */ fun fromAdministration( administration: AdministrationEntity, - controlUnitModels: List? = mutableListOf() + controlUnitModels: List? = mutableListOf(), ): AdministrationModel { return AdministrationModel( id = administration.id, @@ -67,4 +67,3 @@ data class AdministrationModel( ) } } - diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitContactModel.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitContactModel.kt index 84a2641ed..5c6ade6c3 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitContactModel.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitContactModel.kt @@ -41,7 +41,7 @@ data class ControlUnitContactModel( companion object { fun fromControlUnitContact( controlUnitContact: ControlUnitContactEntity, - controlUnitModel: ControlUnitModel + controlUnitModel: ControlUnitModel, ): ControlUnitContactModel { return ControlUnitContactModel( id = controlUnitContact.id, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitModel.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitModel.kt index 54278e2d1..9c593106b 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitModel.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitModel.kt @@ -66,7 +66,7 @@ data class ControlUnitModel( administrationModel: AdministrationModel, departmentAreaModel: DepartmentAreaModel? = null, controlUnitContactModels: List? = null, - controlUnitResourceModels: List? = null + controlUnitResourceModels: List? = null, ): ControlUnitModel { return ControlUnitModel( id = controlUnit.id, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitResourceModel.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitResourceModel.kt index 873f7a0c8..c8a7c4240 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitResourceModel.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/ControlUnitResourceModel.kt @@ -1,12 +1,13 @@ package fr.gouv.cacem.monitorenv.infrastructure.database.model import com.fasterxml.jackson.annotation.JsonBackReference +import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.ControlUnitResourceEntity import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.ControlUnitResourceType import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.dtos.FullControlUnitResourceDTO import jakarta.persistence.* -import org.hibernate.annotations.ColumnTransformer import org.hibernate.annotations.CreationTimestamp +import org.hibernate.annotations.Type import org.hibernate.annotations.UpdateTimestamp import java.time.Instant @@ -37,9 +38,9 @@ data class ControlUnitResourceModel( @Column(name = "photo") var photo: ByteArray? = byteArrayOf(), + @Column(name = "type", nullable = false, columnDefinition = "control_unit_resource_type") @Enumerated(EnumType.STRING) - @Column(name = "type", nullable = false) - @ColumnTransformer(write = "?::control_unit_resource_type") + @Type(PostgreSQLEnumType::class) var type: ControlUnitResourceType, @Column(name = "created_at_utc", nullable = false, updatable = false) diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionControlResourceModel.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionControlResourceModel.kt index 0c81bc103..77ffdb014 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionControlResourceModel.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionControlResourceModel.kt @@ -24,7 +24,7 @@ data class MissionControlResourceModel( controlUnitResource: ControlUnitResourceEntity, baseModel: BaseModel, missionModel: MissionModel, - controlUnitModel: ControlUnitModel + controlUnitModel: ControlUnitModel, ) = MissionControlResourceModel( ressource = ControlUnitResourceModel( id = requireNotNull(controlUnitResource.id), diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionModel.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionModel.kt index e4198c12a..f8160bb28 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionModel.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/model/MissionModel.kt @@ -129,7 +129,7 @@ data class MissionModel( missionControlUnitModel.unit.toLegacyControlUnit().copy( contact = missionControlUnitModel.contact, - resources = controlUnitResources + resources = controlUnitResources, ) } @@ -159,7 +159,7 @@ data class MissionModel( fun fromMissionEntity( mission: MissionEntity, mapper: ObjectMapper, - baseModelMap: Map + baseModelMap: Map, ): MissionModel { val missionModel = MissionModel( id = mission.id, @@ -198,7 +198,7 @@ data class MissionModel( controlUnitResource, baseModel, missionModel, - controlUnitModel.unit + controlUnitModel.unit, ) } missionModel.controlResources?.addAll(missionControlUnitResourceModels) diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepository.kt index 4dc52b78e..fac967aa4 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepository.kt @@ -12,7 +12,6 @@ import org.springframework.dao.InvalidDataAccessApiUsageException import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional - @Repository class JpaAdministrationRepository( private val dbAdministrationRepository: IDBAdministrationRepository, @@ -21,7 +20,9 @@ class JpaAdministrationRepository( override fun archiveById(administrationId: Int) { val fullAdministration = findById(administrationId) if (fullAdministration.controlUnits.any { !it.isArchived }) { - throw UnarchivedChildException("Cannot archive administration (ID=$administrationId) due to some of its control units not being archived.") + throw UnarchivedChildException( + "Cannot archive administration (ID=$administrationId) due to some of its control units not being archived.", + ) } dbAdministrationRepository.archiveById(administrationId) @@ -30,7 +31,9 @@ class JpaAdministrationRepository( override fun deleteById(administrationId: Int) { val fullAdministration = findById(administrationId) if (fullAdministration.controlUnits.isNotEmpty()) { - throw ForeignKeyConstraintException("Cannot delete administration (ID=$administrationId) due to existing relationships.") + throw ForeignKeyConstraintException( + "Cannot delete administration (ID=$administrationId) due to existing relationships.", + ) } dbAdministrationRepository.deleteById(administrationId) @@ -53,7 +56,7 @@ class JpaAdministrationRepository( } catch (e: InvalidDataAccessApiUsageException) { throw NotFoundException( "Unable to find (and update) control unit administration with `id` = ${administration.id}.", - e + e, ) } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaBaseRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaBaseRepository.kt index 490e77dc9..b12798a06 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaBaseRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaBaseRepository.kt @@ -39,7 +39,7 @@ class JpaBaseRepository( } catch (e: InvalidDataAccessApiUsageException) { throw NotFoundException( "Unable to find (and update) base with `id` = ${base.id}.", - e + e, ) } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitContactRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitContactRepository.kt index 5307be20b..c881a8b68 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitContactRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitContactRepository.kt @@ -40,7 +40,7 @@ class JpaControlUnitContactRepository( } catch (e: InvalidDataAccessApiUsageException) { throw NotFoundException( "Unable to find (and update) control unit contact with `id` = ${controlUnitContact.id}.", - e + e, ) } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepository.kt index 86b3f1db7..95bb6cb4b 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepository.kt @@ -55,7 +55,7 @@ class JpaControlUnitRepository( } catch (e: InvalidDataAccessApiUsageException) { throw NotFoundException( "Unable to find (and update) control unit with `id` = ${controlUnit.id}.", - e + e, ) } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitResourceRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitResourceRepository.kt index f3f3ffb53..7f804f522 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitResourceRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitResourceRepository.kt @@ -47,7 +47,7 @@ class JpaControlUnitResourceRepository( } catch (e: InvalidDataAccessApiUsageException) { throw NotFoundException( "Unable to find (and update) control unit resource with `id` = ${controlUnitResource.id}.", - e + e, ) } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaDepartmentAreaRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaDepartmentAreaRepository.kt index f74e6164e..e60afcadc 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaDepartmentAreaRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaDepartmentAreaRepository.kt @@ -8,7 +8,7 @@ import org.springframework.stereotype.Repository @Repository class JpaDepartmentAreaRepository( - private val dbDepartmentAreasRepository: IDBDepartmentAreaRepository + private val dbDepartmentAreasRepository: IDBDepartmentAreaRepository, ) : IDepartmentAreaRepository { override fun findAll(): List { return dbDepartmentAreasRepository.findAll().map { it.toDepartmentArea() } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepository.kt index d260aa652..70f920f1d 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepository.kt @@ -70,7 +70,7 @@ class JpaMissionRepository( is DataIntegrityViolationException, is InvalidDataAccessApiUsageException -> { throw ControlResourceOrUnitNotFoundException( "Invalid control unit or resource id: not found in referential.", - e + e, ) } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepository.kt index d0b011f60..93e8adf05 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingRepository.kt @@ -7,41 +7,41 @@ import fr.gouv.cacem.monitorenv.domain.exceptions.ControlResourceOrUnitNotFoundE import fr.gouv.cacem.monitorenv.domain.repositories.IReportingRepository import fr.gouv.cacem.monitorenv.infrastructure.database.model.ReportingModel import fr.gouv.cacem.monitorenv.infrastructure.database.repositories.interfaces.IDBReportingRepository -import java.time.Instant import org.springframework.dao.InvalidDataAccessApiUsageException import org.springframework.data.domain.Pageable import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +import java.time.Instant @Repository class JpaReportingRepository( - private val dbReportingRepository: IDBReportingRepository, + private val dbReportingRepository: IDBReportingRepository, ) : IReportingRepository { override fun findById(reportingId: Int): ReportingEntity { return dbReportingRepository.findById(reportingId).get().toReporting() } override fun findAll( - pageable: Pageable, - reportingType: List?, - seaFronts: List?, - sourcesType: List?, - startedAfter: Instant, - startedBefore: Instant?, - status: List?, + pageable: Pageable, + reportingType: List?, + seaFronts: List?, + sourcesType: List?, + startedAfter: Instant, + startedBefore: Instant?, + status: List?, ): List { val sourcesTypeAsStringArray = sourcesType?.map { it.name } val reportingTypeAsStringArray = reportingType?.map { it.name } return dbReportingRepository.findAll( - pageable, - reportingType = convertToString(reportingTypeAsStringArray), - seaFronts = convertToString(seaFronts), - sourcesType = convertToString(sourcesTypeAsStringArray), - startedAfter = startedAfter, - startedBefore = startedBefore, - status = convertToString(status), - ) - .map { it.toReporting() } + pageable, + reportingType = convertToString(reportingTypeAsStringArray), + seaFronts = convertToString(seaFronts), + sourcesType = convertToString(sourcesTypeAsStringArray), + startedAfter = startedAfter, + startedBefore = startedBefore, + status = convertToString(status), + ) + .map { it.toReporting() } } @Transactional @@ -51,8 +51,8 @@ class JpaReportingRepository( dbReportingRepository.save(reportingModel).toReporting() } catch (e: InvalidDataAccessApiUsageException) { throw ControlResourceOrUnitNotFoundException( - "Invalid control unit or resource id: not found in referential", - e, + "Invalid control unit or resource id: not found in referential", + e, ) } } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBFacadeAreasRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBFacadeAreasRepository.kt index e25618a04..959069208 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBFacadeAreasRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBFacadeAreasRepository.kt @@ -38,6 +38,5 @@ interface IDBFacadeAreasRepository : CrudRepository { """, nativeQuery = true, ) - fun findFacadeFromGeometry(geometry: Geometry): String - ? + fun findFacadeFromGeometry(geometry: Geometry): String? } diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBReportingRepository.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBReportingRepository.kt index 1a6e74ea8..55f99fcc9 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBReportingRepository.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/interfaces/IDBReportingRepository.kt @@ -1,19 +1,19 @@ package fr.gouv.cacem.monitorenv.infrastructure.database.repositories.interfaces import fr.gouv.cacem.monitorenv.infrastructure.database.model.ReportingModel -import java.time.Instant import org.hibernate.annotations.DynamicUpdate import org.springframework.data.domain.Pageable import org.springframework.data.jpa.repository.Modifying import org.springframework.data.jpa.repository.Query import org.springframework.data.repository.CrudRepository +import java.time.Instant @DynamicUpdate interface IDBReportingRepository : CrudRepository { @Query( - value = - """ + value = + """ SELECT * FROM reportings WHERE is_deleted IS FALSE @@ -37,63 +37,63 @@ interface IDBReportingRepository : CrudRepository { ) ORDER BY reporting_id DESC """, - nativeQuery = true, + nativeQuery = true, ) fun findAll( - pageable: Pageable, - reportingType: String?, - seaFronts: String?, - sourcesType: String?, - startedAfter: Instant, - startedBefore: Instant?, - status: String?, + pageable: Pageable, + reportingType: String?, + seaFronts: String?, + sourcesType: String?, + startedAfter: Instant, + startedBefore: Instant?, + status: String?, ): List @Modifying(clearAutomatically = true) @Query( - value = - """ + value = + """ UPDATE reportings SET is_deleted = TRUE WHERE id = :id """, - nativeQuery = true, + nativeQuery = true, ) fun delete(id: Int) @Modifying(clearAutomatically = true) @Query( - value = - """ + value = + """ UPDATE reportings SET is_archived = TRUE WHERE (created_at + make_interval(hours => validity_time)) < NOW() AND is_archived IS FALSE """, - nativeQuery = true, + nativeQuery = true, ) fun archiveOutdatedReportings(): Int @Modifying(clearAutomatically = true) @Query( - value = - """ + value = + """ UPDATE reportings SET is_archived = TRUE WHERE id in (:ids) """, - nativeQuery = true, + nativeQuery = true, ) fun archiveReportings(ids: List) @Modifying(clearAutomatically = true) @Query( - value = - """ + value = + """ UPDATE reportings SET is_deleted = TRUE WHERE id in (:ids) """, - nativeQuery = true, + nativeQuery = true, ) fun deleteReportings(ids: List) } diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateAdministrationUTests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateAdministrationUTests.kt index 893f2133f..c9a475a06 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateAdministrationUTests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateAdministrationUTests.kt @@ -21,7 +21,7 @@ class CreateOrUpdateAdministrationUTests { fun `execute() should return save() result`() { val newAdministration = AdministrationEntity( isArchived = false, - name = "Administration Name" + name = "Administration Name", ) val expectedAdministration = newAdministration.copy(id = 0) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateControlUnitUTests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateControlUnitUTests.kt index 3d92621aa..e1d47f3a9 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateControlUnitUTests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateControlUnitUTests.kt @@ -34,7 +34,7 @@ class CreateOrUpdateControlUnitUTests { val result = CreateOrUpdateControlUnit(controlUnitRepository).execute( - newControlUnit + newControlUnit, ) verify(controlUnitRepository, times(1)).save(newControlUnit) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionUTests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionUTests.kt index 6616d31ec..cb8acb39f 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionUTests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/CreateOrUpdateMissionUTests.kt @@ -1,4 +1,6 @@ -package fr.gouv.cacem.monitorenv.domain.use_cases // ktlint-disable package-name +@file:Suppress("ktlint:standard:package-name") + +package fr.gouv.cacem.monitorenv.domain.use_cases import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.given @@ -120,9 +122,9 @@ class CreateOrUpdateMissionUTests { baseRepository, departmentRepository, missionRepository, - facadeAreasRepository + facadeAreasRepository, ).execute( - missionToCreate + missionToCreate, ) // Then diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/DepartmentAreaControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/DepartmentAreaControllerITests.kt index 187579ef3..5817bb831 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/DepartmentAreaControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/DepartmentAreaControllerITests.kt @@ -58,7 +58,7 @@ class DepartmentAreaControllerITests { DepartmentAreaEntity( inseeCode = "2", name = "Department Area Name 2", - ) + ), ) given(getDepartmentAreas.execute()).willReturn(expectedAFulldministrations) @@ -69,5 +69,4 @@ class DepartmentAreaControllerITests { BDDMockito.verify(getDepartmentAreas).execute() } - } diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/ReportingsControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/ReportingsControllerITests.kt index 2cf048cae..5248c9843 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/ReportingsControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/ReportingsControllerITests.kt @@ -18,7 +18,6 @@ import fr.gouv.cacem.monitorenv.domain.use_cases.reportings.DeleteReportings import fr.gouv.cacem.monitorenv.domain.use_cases.reportings.GetReportingById import fr.gouv.cacem.monitorenv.domain.use_cases.reportings.GetReportings import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.bff.inputs.CreateOrUpdateReportingDataInput -import java.time.ZonedDateTime import org.junit.jupiter.api.Test import org.locationtech.jts.geom.Point import org.locationtech.jts.io.WKTReader @@ -35,6 +34,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.time.ZonedDateTime @Import(WebSecurityConfig::class, MapperConfiguration::class) @WebMvcTest(value = [(ReportingsController::class)]) @@ -57,235 +57,235 @@ class ReportingsControllerITests { @MockBean private lateinit var deleteReporting: DeleteReporting - @MockBean private lateinit var deleteReportings: DeleteReportings + @MockBean private lateinit var deleteReportings: DeleteReportings - @MockBean private lateinit var archiveReportings: ArchiveReportings + @MockBean private lateinit var archiveReportings: ArchiveReportings - @Test - fun `Should create a new Reporting`() { - // Given - val polygon = - WKTReader() - .read( - "MULTIPOLYGON (((-61.0 14.0, -61.0 15.0, -60.0 15.0, -60.0 14.0, -61.0 14.0)))", - ) - val reporting = - ReportingEntity( - id = 1, - sourceType = SourceTypeEnum.SEMAPHORE, - targetType = TargetTypeEnum.VEHICLE, - vehicleType = VehicleTypeEnum.VESSEL, - geom = polygon, - seaFront = "Facade 1", - description = "description", - reportType = ReportingTypeEnum.INFRACTION_SUSPICION, - theme = "theme", - subThemes = listOf("subTheme1", "subTheme2"), - actionTaken = "actions effectuées blabla", - isControlRequired = true, - isUnitAvailable = true, - createdAt = + @Test + fun `Should create a new Reporting`() { + // Given + val polygon = + WKTReader() + .read( + "MULTIPOLYGON (((-61.0 14.0, -61.0 15.0, -60.0 15.0, -60.0 14.0, -61.0 14.0)))", + ) + val reporting = + ReportingEntity( + id = 1, + sourceType = SourceTypeEnum.SEMAPHORE, + targetType = TargetTypeEnum.VEHICLE, + vehicleType = VehicleTypeEnum.VESSEL, + geom = polygon, + seaFront = "Facade 1", + description = "description", + reportType = ReportingTypeEnum.INFRACTION_SUSPICION, + theme = "theme", + subThemes = listOf("subTheme1", "subTheme2"), + actionTaken = "actions effectuées blabla", + isControlRequired = true, + isUnitAvailable = true, + createdAt = ZonedDateTime.parse( "2022-01-15T04:50:09Z", ), - validityTime = 10, - isArchived = false, - isDeleted = false, - openBy = "CDA", - ) - val semaphore = - SemaphoreEntity( - id = 1, - name = "name", - geom = + validityTime = 10, + isArchived = false, + isDeleted = false, + openBy = "CDA", + ) + val semaphore = + SemaphoreEntity( + id = 1, + name = "name", + geom = WKTReader() .read( "POINT (-61.0 14.0)", ) as Point, - ) + ) - val request = - CreateOrUpdateReportingDataInput( - sourceType = SourceTypeEnum.SEMAPHORE, - semaphoreId = 1, - targetType = TargetTypeEnum.VEHICLE, - vehicleType = VehicleTypeEnum.VESSEL, - geom = polygon, - description = "description", - reportType = ReportingTypeEnum.INFRACTION_SUSPICION, - theme = "theme", - subThemes = listOf("subTheme1", "subTheme2"), - actionTaken = "actions effectuées blabla", - isControlRequired = true, - isUnitAvailable = true, - createdAt = + val request = + CreateOrUpdateReportingDataInput( + sourceType = SourceTypeEnum.SEMAPHORE, + semaphoreId = 1, + targetType = TargetTypeEnum.VEHICLE, + vehicleType = VehicleTypeEnum.VESSEL, + geom = polygon, + description = "description", + reportType = ReportingTypeEnum.INFRACTION_SUSPICION, + theme = "theme", + subThemes = listOf("subTheme1", "subTheme2"), + actionTaken = "actions effectuées blabla", + isControlRequired = true, + isUnitAvailable = true, + createdAt = ZonedDateTime.parse( "2022-01-15T04:50:09Z", ), - validityTime = 10, - isArchived = false, - openBy = "CDA", - ) + validityTime = 10, + isArchived = false, + openBy = "CDA", + ) - given(createOrUpdateReporting.execute(any())).willReturn(Triple(reporting, null, semaphore)) - // When - mockedApi - .perform( - put("/bff/v1/reportings") - .contentType( - MediaType.APPLICATION_JSON, - ) - .content( - objectMapper.writeValueAsString( - request, + given(createOrUpdateReporting.execute(any())).willReturn(Triple(reporting, null, semaphore)) + // When + mockedApi + .perform( + put("/bff/v1/reportings") + .contentType( + MediaType.APPLICATION_JSON, + ) + .content( + objectMapper.writeValueAsString( + request, + ), ), - ), - ) - // Then - .andExpect(status().isCreated) - .andExpect(jsonPath("$.id").value(1)) - .andExpect(jsonPath("$.sourceType").value("SEMAPHORE")) - .andExpect(jsonPath("$.targetType").value("VEHICLE")) - .andExpect(jsonPath("$.vehicleType").value("VESSEL")) - .andExpect(jsonPath("$.geom.type").value("MultiPolygon")) - .andExpect(jsonPath("$.seaFront").value("Facade 1")) - .andExpect(jsonPath("$.description").value("description")) - .andExpect(jsonPath("$.reportType").value("INFRACTION_SUSPICION")) - .andExpect(jsonPath("$.theme").value("theme")) - .andExpect(jsonPath("$.subThemes[0]").value("subTheme1")) - .andExpect(jsonPath("$.subThemes[1]").value("subTheme2")) - .andExpect( - jsonPath("$.actionTaken").value("actions effectuées blabla"), - ) - .andExpect(jsonPath("$.isControlRequired").value(true)) - .andExpect(jsonPath("$.isUnitAvailable").value(true)) - .andExpect(jsonPath("$.createdAt").value("2022-01-15T04:50:09Z")) - .andExpect(jsonPath("$.validityTime").value(10)) - .andExpect(jsonPath("$.isArchived").value(false)) - } - - @Test - fun `Should return the reporting specified in url`() { - // Given - val polygon = - WKTReader() - .read( - "MULTIPOLYGON (((-61.0 14.0, -61.0 15.0, -60.0 15.0, -60.0 14.0, -61.0 14.0)))", ) - val reporting = - ReportingEntity( - id = 1, - sourceType = SourceTypeEnum.SEMAPHORE, - targetType = TargetTypeEnum.VEHICLE, - vehicleType = VehicleTypeEnum.VESSEL, - geom = polygon, - seaFront = "Facade 1", - description = "description", - reportType = ReportingTypeEnum.INFRACTION_SUSPICION, - theme = "theme", - subThemes = listOf("subTheme1", "subTheme2"), - actionTaken = "actions effectuées blabla", - isControlRequired = true, - isUnitAvailable = true, - createdAt = + // Then + .andExpect(status().isCreated) + .andExpect(jsonPath("$.id").value(1)) + .andExpect(jsonPath("$.sourceType").value("SEMAPHORE")) + .andExpect(jsonPath("$.targetType").value("VEHICLE")) + .andExpect(jsonPath("$.vehicleType").value("VESSEL")) + .andExpect(jsonPath("$.geom.type").value("MultiPolygon")) + .andExpect(jsonPath("$.seaFront").value("Facade 1")) + .andExpect(jsonPath("$.description").value("description")) + .andExpect(jsonPath("$.reportType").value("INFRACTION_SUSPICION")) + .andExpect(jsonPath("$.theme").value("theme")) + .andExpect(jsonPath("$.subThemes[0]").value("subTheme1")) + .andExpect(jsonPath("$.subThemes[1]").value("subTheme2")) + .andExpect( + jsonPath("$.actionTaken").value("actions effectuées blabla"), + ) + .andExpect(jsonPath("$.isControlRequired").value(true)) + .andExpect(jsonPath("$.isUnitAvailable").value(true)) + .andExpect(jsonPath("$.createdAt").value("2022-01-15T04:50:09Z")) + .andExpect(jsonPath("$.validityTime").value(10)) + .andExpect(jsonPath("$.isArchived").value(false)) + } + + @Test + fun `Should return the reporting specified in url`() { + // Given + val polygon = + WKTReader() + .read( + "MULTIPOLYGON (((-61.0 14.0, -61.0 15.0, -60.0 15.0, -60.0 14.0, -61.0 14.0)))", + ) + val reporting = + ReportingEntity( + id = 1, + sourceType = SourceTypeEnum.SEMAPHORE, + targetType = TargetTypeEnum.VEHICLE, + vehicleType = VehicleTypeEnum.VESSEL, + geom = polygon, + seaFront = "Facade 1", + description = "description", + reportType = ReportingTypeEnum.INFRACTION_SUSPICION, + theme = "theme", + subThemes = listOf("subTheme1", "subTheme2"), + actionTaken = "actions effectuées blabla", + isControlRequired = true, + isUnitAvailable = true, + createdAt = ZonedDateTime.parse( "2022-01-15T04:50:09Z", ), - validityTime = 10, - isArchived = false, - isDeleted = false, - openBy = "CDA", - ) - val semaphore = - SemaphoreEntity( - id = 1, - name = "name", - geom = + validityTime = 10, + isArchived = false, + isDeleted = false, + openBy = "CDA", + ) + val semaphore = + SemaphoreEntity( + id = 1, + name = "name", + geom = WKTReader() .read( "POINT (-61.0 14.0)", ) as Point, - ) + ) - given(getReportingById.execute(any())).willReturn(Triple(reporting, null, semaphore)) + given(getReportingById.execute(any())).willReturn(Triple(reporting, null, semaphore)) - // When - mockedApi - .perform( - get("/bff/v1/reportings/1") - .contentType( - MediaType.APPLICATION_JSON, - ), - ) - // Then - .andExpect(status().isOk) - .andExpect(jsonPath("$.id").value(1)) - .andExpect(jsonPath("$.sourceType").value("SEMAPHORE")) - .andExpect(jsonPath("$.targetType").value("VEHICLE")) - .andExpect(jsonPath("$.vehicleType").value("VESSEL")) - .andExpect(jsonPath("$.geom.type").value("MultiPolygon")) - .andExpect(jsonPath("$.seaFront").value("Facade 1")) - .andExpect(jsonPath("$.description").value("description")) - .andExpect(jsonPath("$.reportType").value("INFRACTION_SUSPICION")) - .andExpect(jsonPath("$.theme").value("theme")) - .andExpect(jsonPath("$.subThemes[0]").value("subTheme1")) - .andExpect(jsonPath("$.subThemes[1]").value("subTheme2")) - .andExpect( - jsonPath("$.actionTaken").value("actions effectuées blabla"), - ) - .andExpect(jsonPath("$.isControlRequired").value(true)) - .andExpect(jsonPath("$.isUnitAvailable").value(true)) - .andExpect(jsonPath("$.createdAt").value("2022-01-15T04:50:09Z")) - .andExpect(jsonPath("$.validityTime").value(10)) - .andExpect(jsonPath("$.isArchived").value(false)) - } - - @Test - fun `Should return all reportings`() { - // Given - val polygon = - WKTReader() - .read( - "MULTIPOLYGON (((-61.0 14.0, -61.0 15.0, -60.0 15.0, -60.0 14.0, -61.0 14.0)))", + // When + mockedApi + .perform( + get("/bff/v1/reportings/1") + .contentType( + MediaType.APPLICATION_JSON, + ), + ) + // Then + .andExpect(status().isOk) + .andExpect(jsonPath("$.id").value(1)) + .andExpect(jsonPath("$.sourceType").value("SEMAPHORE")) + .andExpect(jsonPath("$.targetType").value("VEHICLE")) + .andExpect(jsonPath("$.vehicleType").value("VESSEL")) + .andExpect(jsonPath("$.geom.type").value("MultiPolygon")) + .andExpect(jsonPath("$.seaFront").value("Facade 1")) + .andExpect(jsonPath("$.description").value("description")) + .andExpect(jsonPath("$.reportType").value("INFRACTION_SUSPICION")) + .andExpect(jsonPath("$.theme").value("theme")) + .andExpect(jsonPath("$.subThemes[0]").value("subTheme1")) + .andExpect(jsonPath("$.subThemes[1]").value("subTheme2")) + .andExpect( + jsonPath("$.actionTaken").value("actions effectuées blabla"), ) - val reporting = - ReportingEntity( - id = 1, - sourceType = SourceTypeEnum.SEMAPHORE, - targetType = TargetTypeEnum.VEHICLE, - vehicleType = VehicleTypeEnum.VESSEL, - geom = polygon, - seaFront = "Facade 1", - description = "description", - reportType = ReportingTypeEnum.INFRACTION_SUSPICION, - theme = "theme", - subThemes = listOf("subTheme1", "subTheme2"), - actionTaken = "actions effectuées blabla", - isControlRequired = true, - isUnitAvailable = true, - createdAt = + .andExpect(jsonPath("$.isControlRequired").value(true)) + .andExpect(jsonPath("$.isUnitAvailable").value(true)) + .andExpect(jsonPath("$.createdAt").value("2022-01-15T04:50:09Z")) + .andExpect(jsonPath("$.validityTime").value(10)) + .andExpect(jsonPath("$.isArchived").value(false)) + } + + @Test + fun `Should return all reportings`() { + // Given + val polygon = + WKTReader() + .read( + "MULTIPOLYGON (((-61.0 14.0, -61.0 15.0, -60.0 15.0, -60.0 14.0, -61.0 14.0)))", + ) + val reporting = + ReportingEntity( + id = 1, + sourceType = SourceTypeEnum.SEMAPHORE, + targetType = TargetTypeEnum.VEHICLE, + vehicleType = VehicleTypeEnum.VESSEL, + geom = polygon, + seaFront = "Facade 1", + description = "description", + reportType = ReportingTypeEnum.INFRACTION_SUSPICION, + theme = "theme", + subThemes = listOf("subTheme1", "subTheme2"), + actionTaken = "actions effectuées blabla", + isControlRequired = true, + isUnitAvailable = true, + createdAt = ZonedDateTime.parse( "2022-01-15T04:50:09Z", ), - validityTime = 10, - isArchived = false, - isDeleted = false, - openBy = "CDA", - ) - val semaphore = - SemaphoreEntity( - id = 1, - name = "semaphore name", - geom = + validityTime = 10, + isArchived = false, + isDeleted = false, + openBy = "CDA", + ) + val semaphore = + SemaphoreEntity( + id = 1, + name = "semaphore name", + geom = WKTReader() .read( "POINT (-61.0 14.0)", ) as Point, - ) - given( + ) + given( getReportings.execute( pageNumber = anyOrNull(), pageSize = anyOrNull(), @@ -297,160 +297,160 @@ class ReportingsControllerITests { status = any(), ), ) - .willReturn(listOf(Triple(reporting, null, semaphore))) + .willReturn(listOf(Triple(reporting, null, semaphore))) - // When - mockedApi - .perform(get("/bff/v1/reportings")) - // Then - .andExpect(status().isOk) - } + // When + mockedApi + .perform(get("/bff/v1/reportings")) + // Then + .andExpect(status().isOk) + } - @Test - fun `Should update a reporting`() { - // Given - val polygon = - WKTReader() - .read( - "MULTIPOLYGON (((-61.0 14.0, -61.0 15.0, -60.0 15.0, -60.0 14.0, -61.0 14.0)))", - ) - val updatedReporting = - ReportingEntity( - id = 1, - sourceType = SourceTypeEnum.SEMAPHORE, - targetType = TargetTypeEnum.VEHICLE, - vehicleType = VehicleTypeEnum.VESSEL, - geom = polygon, - seaFront = "Facade 1", - description = "description", - reportType = ReportingTypeEnum.INFRACTION_SUSPICION, - theme = "theme", - subThemes = listOf("subTheme1", "subTheme2"), - actionTaken = "actions effectuées blabla", - isControlRequired = true, - isUnitAvailable = true, - createdAt = - ZonedDateTime.parse( - "2022-01-15T04:50:09Z", - ), - validityTime = 10, - isArchived = false, - isDeleted = false, - openBy = "CDA", - ) - val semaphore = - SemaphoreEntity( - id = 1, - name = "name", - geom = - WKTReader() - .read( - "POINT (-61.0 14.0)", - ) as - Point, - ) - val updateRequestBody = - objectMapper.writeValueAsString( - CreateOrUpdateReportingDataInput( + @Test + fun `Should update a reporting`() { + // Given + val polygon = + WKTReader() + .read( + "MULTIPOLYGON (((-61.0 14.0, -61.0 15.0, -60.0 15.0, -60.0 14.0, -61.0 14.0)))", + ) + val updatedReporting = + ReportingEntity( id = 1, sourceType = SourceTypeEnum.SEMAPHORE, targetType = TargetTypeEnum.VEHICLE, vehicleType = VehicleTypeEnum.VESSEL, geom = polygon, + seaFront = "Facade 1", description = "description", reportType = ReportingTypeEnum.INFRACTION_SUSPICION, theme = "theme", - subThemes = - listOf( - "subTheme1", - "subTheme2", - ), + subThemes = listOf("subTheme1", "subTheme2"), actionTaken = "actions effectuées blabla", isControlRequired = true, isUnitAvailable = true, createdAt = - ZonedDateTime.parse( - "2022-01-15T04:50:09Z", - ), + ZonedDateTime.parse( + "2022-01-15T04:50:09Z", + ), validityTime = 10, isArchived = false, + isDeleted = false, openBy = "CDA", - ), - ) + ) + val semaphore = + SemaphoreEntity( + id = 1, + name = "name", + geom = + WKTReader() + .read( + "POINT (-61.0 14.0)", + ) as + Point, + ) + val updateRequestBody = + objectMapper.writeValueAsString( + CreateOrUpdateReportingDataInput( + id = 1, + sourceType = SourceTypeEnum.SEMAPHORE, + targetType = TargetTypeEnum.VEHICLE, + vehicleType = VehicleTypeEnum.VESSEL, + geom = polygon, + description = "description", + reportType = ReportingTypeEnum.INFRACTION_SUSPICION, + theme = "theme", + subThemes = + listOf( + "subTheme1", + "subTheme2", + ), + actionTaken = "actions effectuées blabla", + isControlRequired = true, + isUnitAvailable = true, + createdAt = + ZonedDateTime.parse( + "2022-01-15T04:50:09Z", + ), + validityTime = 10, + isArchived = false, + openBy = "CDA", + ), + ) - given(createOrUpdateReporting.execute(any())) - .willReturn(Triple(updatedReporting, null, semaphore)) + given(createOrUpdateReporting.execute(any())) + .willReturn(Triple(updatedReporting, null, semaphore)) - // When - mockedApi - .perform( - put("/bff/v1/reportings/1") - .content(updateRequestBody) - .contentType( - MediaType.APPLICATION_JSON, - ), - ) - // Then - .andExpect(status().isOk) - .andExpect(jsonPath("$.id").value(1)) - .andExpect(jsonPath("$.sourceType").value("SEMAPHORE")) - .andExpect(jsonPath("$.targetType").value("VEHICLE")) - .andExpect(jsonPath("$.vehicleType").value("VESSEL")) - .andExpect(jsonPath("$.geom.type").value("MultiPolygon")) - .andExpect(jsonPath("$.seaFront").value("Facade 1")) - .andExpect(jsonPath("$.description").value("description")) - .andExpect(jsonPath("$.reportType").value("INFRACTION_SUSPICION")) - .andExpect(jsonPath("$.theme").value("theme")) - .andExpect(jsonPath("$.subThemes[0]").value("subTheme1")) - .andExpect(jsonPath("$.subThemes[1]").value("subTheme2")) - .andExpect( - jsonPath("$.actionTaken").value("actions effectuées blabla"), - ) - .andExpect(jsonPath("$.isControlRequired").value(true)) - .andExpect(jsonPath("$.isUnitAvailable").value(true)) - .andExpect(jsonPath("$.createdAt").value("2022-01-15T04:50:09Z")) - .andExpect(jsonPath("$.validityTime").value(10)) - .andExpect(jsonPath("$.isArchived").value(false)) - } + // When + mockedApi + .perform( + put("/bff/v1/reportings/1") + .content(updateRequestBody) + .contentType( + MediaType.APPLICATION_JSON, + ), + ) + // Then + .andExpect(status().isOk) + .andExpect(jsonPath("$.id").value(1)) + .andExpect(jsonPath("$.sourceType").value("SEMAPHORE")) + .andExpect(jsonPath("$.targetType").value("VEHICLE")) + .andExpect(jsonPath("$.vehicleType").value("VESSEL")) + .andExpect(jsonPath("$.geom.type").value("MultiPolygon")) + .andExpect(jsonPath("$.seaFront").value("Facade 1")) + .andExpect(jsonPath("$.description").value("description")) + .andExpect(jsonPath("$.reportType").value("INFRACTION_SUSPICION")) + .andExpect(jsonPath("$.theme").value("theme")) + .andExpect(jsonPath("$.subThemes[0]").value("subTheme1")) + .andExpect(jsonPath("$.subThemes[1]").value("subTheme2")) + .andExpect( + jsonPath("$.actionTaken").value("actions effectuées blabla"), + ) + .andExpect(jsonPath("$.isControlRequired").value(true)) + .andExpect(jsonPath("$.isUnitAvailable").value(true)) + .andExpect(jsonPath("$.createdAt").value("2022-01-15T04:50:09Z")) + .andExpect(jsonPath("$.validityTime").value(10)) + .andExpect(jsonPath("$.isArchived").value(false)) + } - @Test - fun `Should delete a reporting`() { - // When - mockedApi - .perform(delete("/bff/v1/reportings/123")) - // Then - .andExpect(status().isNoContent()) + @Test + fun `Should delete a reporting`() { + // When + mockedApi + .perform(delete("/bff/v1/reportings/123")) + // Then + .andExpect(status().isNoContent()) - Mockito.verify(deleteReporting).execute(123) - } + Mockito.verify(deleteReporting).execute(123) + } - @Test - fun `Should archive multiple reportings`() { - // When - mockedApi - .perform( - put("/bff/v1/reportings/archive") - .content(objectMapper.writeValueAsString(listOf(1, 2, 3))) - .contentType(MediaType.APPLICATION_JSON), - ) - // Then - .andExpect(status().isNoContent()) + @Test + fun `Should archive multiple reportings`() { + // When + mockedApi + .perform( + put("/bff/v1/reportings/archive") + .content(objectMapper.writeValueAsString(listOf(1, 2, 3))) + .contentType(MediaType.APPLICATION_JSON), + ) + // Then + .andExpect(status().isNoContent()) - Mockito.verify(archiveReportings).execute(listOf(1, 2, 3)) - } + Mockito.verify(archiveReportings).execute(listOf(1, 2, 3)) + } - @Test - fun `Should delete multiple reportings`() { - // When - mockedApi - .perform( - put("/bff/v1/reportings/delete") - .content(objectMapper.writeValueAsString(listOf(1, 2, 3))) - .contentType(MediaType.APPLICATION_JSON), - ) - // Then - .andExpect(status().isNoContent()) + @Test + fun `Should delete multiple reportings`() { + // When + mockedApi + .perform( + put("/bff/v1/reportings/delete") + .content(objectMapper.writeValueAsString(listOf(1, 2, 3))) + .contentType(MediaType.APPLICATION_JSON), + ) + // Then + .andExpect(status().isNoContent()) - Mockito.verify(deleteReportings).execute(listOf(1, 2, 3)) - } + Mockito.verify(deleteReportings).execute(listOf(1, 2, 3)) + } } diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsControllerITests.kt index 8748d9d90..33fa40220 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiAdministrationsControllerITests.kt @@ -112,7 +112,7 @@ class ApiAdministrationsControllerITests { name = "Administration Name 2", ), controlUnits = listOf(), - ) + ), ) given(getAdministrations.execute()).willReturn(expectedAFulldministrations) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiBasesControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiBasesControllerITests.kt index d36e2b92b..381ece240 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiBasesControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiBasesControllerITests.kt @@ -113,7 +113,7 @@ class ApiBasesControllerITests { name = "Base Name 2", ), controlUnitResources = listOf(), - ) + ), ) given(getBases.execute()).willReturn(expectedFullBases) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitContactsControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitContactsControllerITests.kt index 0b07d0c29..499416dbc 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitContactsControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitContactsControllerITests.kt @@ -7,6 +7,7 @@ import fr.gouv.cacem.monitorenv.config.WebSecurityConfig import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.ControlUnitContactEntity import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.ControlUnitEntity import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.CreateOrUpdateControlUnitContact +import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.DeleteControlUnitContact import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.GetControlUnitContactById import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.GetControlUnitContacts import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.dtos.FullControlUnitContactDTO @@ -35,6 +36,9 @@ class ApiControlUnitContactsControllerITests { @MockBean private lateinit var createOrUpdateControlUnitContact: CreateOrUpdateControlUnitContact + @MockBean + private lateinit var deleteControlUnitContact: DeleteControlUnitContact + @MockBean private lateinit var getControlUnitContactById: GetControlUnitContactById @@ -63,7 +67,7 @@ class ApiControlUnitContactsControllerITests { val requestBody = objectMapper.writeValueAsString(newControlUnitContactData) given(createOrUpdateControlUnitContact.execute(controlUnitContact = any())).willReturn( - expectedCreatedControlUnitContact + expectedCreatedControlUnitContact, ) mockMvc.perform( @@ -93,7 +97,7 @@ class ApiControlUnitContactsControllerITests { email = null, name = "Contact Name", phone = null, - ) + ), ) val requestedId = 1 @@ -145,7 +149,7 @@ class ApiControlUnitContactsControllerITests { name = "Contact Name 2", phone = null, ), - ) + ), ) given(getControlUnitContacts.execute()).willReturn(expectedFullControlUnitContacts) @@ -177,7 +181,7 @@ class ApiControlUnitContactsControllerITests { val requestBody = objectMapper.writeValueAsString(nextControlUnitContactData) given(createOrUpdateControlUnitContact.execute(controlUnitContact = any())).willReturn( - expectedUpdatedControlUnitContact + expectedUpdatedControlUnitContact, ) mockMvc.perform( diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitResourcesControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitResourcesControllerITests.kt index d6fc9bbb9..730b4a40b 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitResourcesControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitResourcesControllerITests.kt @@ -9,6 +9,7 @@ import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.ControlUnitEntity import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.ControlUnitResourceEntity import fr.gouv.cacem.monitorenv.domain.entities.controlUnit.ControlUnitResourceType import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.CreateOrUpdateControlUnitResource +import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.DeleteControlUnitResource import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.GetControlUnitResourceById import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.GetControlUnitResources import fr.gouv.cacem.monitorenv.domain.use_cases.controlUnit.dtos.FullControlUnitResourceDTO @@ -37,6 +38,9 @@ class ApiControlUnitResourcesControllerITests { @MockBean private lateinit var createOrUpdateControlUnitResource: CreateOrUpdateControlUnitResource + @MockBean + private lateinit var deleteControlUnitResource: DeleteControlUnitResource + @MockBean private lateinit var getControlUnitResourceById: GetControlUnitResourceById @@ -69,7 +73,7 @@ class ApiControlUnitResourcesControllerITests { val requestBody = objectMapper.writeValueAsString(newControlUnitData) given(createOrUpdateControlUnitResource.execute(controlUnitResource = any())).willReturn( - expectedCreatedControlUnitResource + expectedCreatedControlUnitResource, ) mockMvc.perform( @@ -175,7 +179,7 @@ class ApiControlUnitResourcesControllerITests { photo = null, type = ControlUnitResourceType.BARGE, ), - ) + ), ) given(getControlUnitResources.execute()).willReturn(expectedFullControlUnitResources) @@ -211,7 +215,7 @@ class ApiControlUnitResourcesControllerITests { val requestBody = objectMapper.writeValueAsString(nextControlUnitData) given(createOrUpdateControlUnitResource.execute(controlUnitResource = any())).willReturn( - expectedUpdatedControlUnitResource + expectedUpdatedControlUnitResource, ) mockMvc.perform( diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsControllerITests.kt index fe707b2b1..a7edb9fda 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiControlUnitsControllerITests.kt @@ -71,7 +71,7 @@ class ApiControlUnitsControllerITests { val requestBody = objectMapper.writeValueAsString(newControlUnitData) given(createOrUpdateControlUnit.execute(controlUnit = any())).willReturn( - expectedCreatedControlUnit + expectedCreatedControlUnit, ) mockMvc.perform( @@ -153,7 +153,7 @@ class ApiControlUnitsControllerITests { ), controlUnitContacts = listOf(), controlUnitResources = listOf(), - ) + ), ) given(getControlUnits.execute()).willReturn(expectedControlUnits) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiLegacyControlUnitsControllerITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiLegacyControlUnitsControllerITests.kt index 899dc4ce8..01943df8a 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiLegacyControlUnitsControllerITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/publicapi/ApiLegacyControlUnitsControllerITests.kt @@ -41,7 +41,7 @@ class ApiLegacyControlUnitsControllerITests { controlUnitId = 0, name = "Vedette", type = ControlUnitResourceType.BARGE, - ) + ), ), ) given(getLegacyControlUnits.execute()).willReturn(listOf(controlUnit)) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepositoryITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepositoryITests.kt index e02bb0559..d5065d243 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepositoryITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaAdministrationRepositoryITests.kt @@ -64,10 +64,10 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { administration = AdministrationEntity( id = 1, isArchived = false, - name = "Affaires Maritimes" + name = "Affaires Maritimes", ), controlUnits = listOf(), - ) + ), ) assertThat(foundFullAdministrations[34]).isEqualTo( @@ -75,10 +75,10 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { administration = AdministrationEntity( id = 2006, isArchived = false, - name = "FOSIT" + name = "FOSIT", ), controlUnits = listOf(), - ) + ), ) } @@ -92,7 +92,7 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { administration = AdministrationEntity( id = 6, isArchived = false, - name = "Gendarmerie Nationale" + name = "Gendarmerie Nationale", ), controlUnits = listOf( ControlUnitEntity( @@ -114,7 +114,7 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { termsNote = null, ), ), - ) + ), ) } @@ -126,7 +126,7 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { val newAdministration = AdministrationEntity( isArchived = false, - name = "Administration Name" + name = "Administration Name", ) val createdAdministration = jpaAdministrationRepository.save(newAdministration) @@ -139,7 +139,7 @@ class JpaAdministrationRepositoryITests : AbstractDBTests() { val nextAdministration = AdministrationEntity( id = 2007, isArchived = false, - name = "Updated Administration Name" + name = "Updated Administration Name", ) val updatedAdministration = jpaAdministrationRepository.save(nextAdministration) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaBaseRepositoryITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaBaseRepositoryITests.kt index d3348c194..781bae27d 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaBaseRepositoryITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaBaseRepositoryITests.kt @@ -26,7 +26,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { id = 1, latitude = 43.295765, longitude = 5.375486, - name = "Marseille" + name = "Marseille", ), controlUnitResources = listOf( ControlUnitResourceEntity( @@ -36,7 +36,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "Semi-rigide 1", note = null, photo = null, - type = ControlUnitResourceType.BARGE + type = ControlUnitResourceType.BARGE, ), ControlUnitResourceEntity( id = 2, @@ -45,7 +45,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "Semi-rigide 2", note = null, photo = null, - type = ControlUnitResourceType.BARGE + type = ControlUnitResourceType.BARGE, ), ), ), @@ -57,7 +57,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { id = 3, latitude = 51.035534, longitude = 2.372845, - name = "Dunkerque" + name = "Dunkerque", ), controlUnitResources = listOf( ControlUnitResourceEntity( @@ -67,7 +67,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "Voiture", note = null, photo = null, - type = ControlUnitResourceType.CAR + type = ControlUnitResourceType.CAR, ), ControlUnitResourceEntity( id = 7, @@ -76,7 +76,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "Semi-rigide", note = null, photo = null, - type = ControlUnitResourceType.BARGE + type = ControlUnitResourceType.BARGE, ), ControlUnitResourceEntity( id = 8, @@ -85,7 +85,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "PAM Jeanne Barret", note = null, photo = null, - type = ControlUnitResourceType.FRIGATE + type = ControlUnitResourceType.FRIGATE, ), ControlUnitResourceEntity( id = 9, @@ -94,7 +94,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "PAM Themis", note = null, photo = null, - type = ControlUnitResourceType.FRIGATE + type = ControlUnitResourceType.FRIGATE, ), ControlUnitResourceEntity( id = 10, @@ -103,7 +103,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "ALTAIR", note = null, photo = null, - type = ControlUnitResourceType.FRIGATE + type = ControlUnitResourceType.FRIGATE, ), ControlUnitResourceEntity( id = 11, @@ -112,7 +112,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "PHEROUSA", note = null, photo = null, - type = ControlUnitResourceType.FRIGATE + type = ControlUnitResourceType.FRIGATE, ), ControlUnitResourceEntity( id = 12, @@ -121,7 +121,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "ARIOLA", note = null, photo = null, - type = ControlUnitResourceType.FRIGATE + type = ControlUnitResourceType.FRIGATE, ), ), ), @@ -139,7 +139,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { id = 2, latitude = 48.648105, longitude = -2.013144, - name = "Saint-Malo" + name = "Saint-Malo", ), controlUnitResources = listOf( ControlUnitResourceEntity( @@ -149,7 +149,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "Semi-rigide 1", note = null, photo = null, - type = ControlUnitResourceType.BARGE + type = ControlUnitResourceType.BARGE, ), ControlUnitResourceEntity( id = 4, @@ -158,7 +158,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "Semi-rigide 2", note = null, photo = null, - type = ControlUnitResourceType.BARGE + type = ControlUnitResourceType.BARGE, ), ControlUnitResourceEntity( id = 6, @@ -167,7 +167,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { name = "AR VECHEN", note = null, photo = null, - type = ControlUnitResourceType.FRIGATE + type = ControlUnitResourceType.FRIGATE, ), ), ), @@ -183,7 +183,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { val newBase = BaseEntity( latitude = 1.2, longitude = 3.4, - name = "Base Name" + name = "Base Name", ) val createdBase = jpaBaseRepository.save(newBase) @@ -197,7 +197,7 @@ class JpaBaseRepositoryITests : AbstractDBTests() { id = 4, latitude = 5.6, longitude = 7.8, - name = "Updated Base Name" + name = "Updated Base Name", ) val updatedBase = jpaBaseRepository.save(nextBase) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitContactRepositoryITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitContactRepositoryITests.kt index bba1a98b5..9a6cfe12d 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitContactRepositoryITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitContactRepositoryITests.kt @@ -29,7 +29,7 @@ class JpaControlUnitContactRepositoryITests : AbstractDBTests() { departmentAreaInseeCode = null, isArchived = false, name = "Cultures marines – DDTM 40", - termsNote = null + termsNote = null, ), controlUnitContact = ControlUnitContactEntity( id = 1, @@ -37,7 +37,7 @@ class JpaControlUnitContactRepositoryITests : AbstractDBTests() { name = "Contact 1", phone = null, ), - ) + ), ) assertThat(foundFullControlUnitContacts[2]).isEqualTo( @@ -49,7 +49,7 @@ class JpaControlUnitContactRepositoryITests : AbstractDBTests() { departmentAreaInseeCode = null, isArchived = false, name = "DPM – DDTM 14", - termsNote = null + termsNote = null, ), controlUnitContact = ControlUnitContactEntity( id = 3, @@ -57,7 +57,7 @@ class JpaControlUnitContactRepositoryITests : AbstractDBTests() { name = "Contact 3", phone = null, ), - ) + ), ) } @@ -75,7 +75,7 @@ class JpaControlUnitContactRepositoryITests : AbstractDBTests() { departmentAreaInseeCode = null, isArchived = false, name = "Cultures marines – DDTM 40", - termsNote = null + termsNote = null, ), controlUnitContact = ControlUnitContactEntity( id = 1, @@ -83,7 +83,7 @@ class JpaControlUnitContactRepositoryITests : AbstractDBTests() { name = "Contact 1", phone = null, ), - ) + ), ) } diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepositoryITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepositoryITests.kt index ea80c8eb5..0b50ac7df 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepositoryITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitRepositoryITests.kt @@ -123,7 +123,7 @@ class JpaControlUnitRepositoryITests : AbstractDBTests() { note = null, photo = null, type = ControlUnitResourceType.BARGE, - ) + ), ), FullControlUnitResourceDTO( base = BaseEntity( @@ -149,10 +149,10 @@ class JpaControlUnitRepositoryITests : AbstractDBTests() { note = null, photo = null, type = ControlUnitResourceType.BARGE, - ) - ) + ), + ), ), - ) + ), ) assertThat(foundFullControlUnits[32]).isEqualTo( @@ -173,7 +173,7 @@ class JpaControlUnitRepositoryITests : AbstractDBTests() { ), controlUnitContacts = listOf(), controlUnitResources = listOf(), - ) + ), ) } @@ -187,7 +187,7 @@ class JpaControlUnitRepositoryITests : AbstractDBTests() { administration = AdministrationEntity( id = 1005, isArchived = false, - name = "DDTM" + name = "DDTM", ), controlUnit = ControlUnitEntity( id = 10000, @@ -204,15 +204,15 @@ class JpaControlUnitRepositoryITests : AbstractDBTests() { controlUnitId = 10000, email = null, name = "Contact 1", - phone = null + phone = null, ), ControlUnitContactEntity( id = 2, controlUnitId = 10000, email = null, name = "Contact 2", - phone = null - ) + phone = null, + ), ), controlUnitResources = listOf( FullControlUnitResourceDTO( @@ -239,7 +239,7 @@ class JpaControlUnitRepositoryITests : AbstractDBTests() { note = null, photo = null, type = ControlUnitResourceType.BARGE, - ) + ), ), FullControlUnitResourceDTO( base = BaseEntity( @@ -268,7 +268,7 @@ class JpaControlUnitRepositoryITests : AbstractDBTests() { ), ), ), - ) + ), ) } diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitResourceRepositoryITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitResourceRepositoryITests.kt index 82c7f85e8..185a2d95c 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitResourceRepositoryITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaControlUnitResourceRepositoryITests.kt @@ -30,7 +30,7 @@ class JpaControlUnitResourceRepositoryITests : AbstractDBTests() { id = 1, latitude = 43.295765, longitude = 5.375486, - name = "Marseille" + name = "Marseille", ), controlUnit = ControlUnitEntity( id = 10000, @@ -39,7 +39,7 @@ class JpaControlUnitResourceRepositoryITests : AbstractDBTests() { departmentAreaInseeCode = null, isArchived = false, name = "Cultures marines – DDTM 40", - termsNote = null + termsNote = null, ), controlUnitResource = ControlUnitResourceEntity( id = 1, @@ -50,7 +50,7 @@ class JpaControlUnitResourceRepositoryITests : AbstractDBTests() { photo = null, type = ControlUnitResourceType.BARGE, ), - ) + ), ) assertThat(foundFullControlUnitResources[11]).isEqualTo( @@ -59,7 +59,7 @@ class JpaControlUnitResourceRepositoryITests : AbstractDBTests() { id = 3, latitude = 51.035534, longitude = 2.372845, - name = "Dunkerque" + name = "Dunkerque", ), controlUnit = ControlUnitEntity( id = 10018, @@ -68,7 +68,7 @@ class JpaControlUnitResourceRepositoryITests : AbstractDBTests() { departmentAreaInseeCode = null, isArchived = false, name = "DREAL Pays-de-La-Loire", - termsNote = null + termsNote = null, ), controlUnitResource = ControlUnitResourceEntity( id = 12, @@ -79,7 +79,7 @@ class JpaControlUnitResourceRepositoryITests : AbstractDBTests() { photo = null, type = ControlUnitResourceType.FRIGATE, ), - ) + ), ) } @@ -94,7 +94,7 @@ class JpaControlUnitResourceRepositoryITests : AbstractDBTests() { id = 1, latitude = 43.295765, longitude = 5.375486, - name = "Marseille" + name = "Marseille", ), controlUnit = ControlUnitEntity( id = 10000, @@ -103,7 +103,7 @@ class JpaControlUnitResourceRepositoryITests : AbstractDBTests() { departmentAreaInseeCode = null, isArchived = false, name = "Cultures marines – DDTM 40", - termsNote = null + termsNote = null, ), controlUnitResource = ControlUnitResourceEntity( id = 1, @@ -114,7 +114,7 @@ class JpaControlUnitResourceRepositoryITests : AbstractDBTests() { photo = null, type = ControlUnitResourceType.BARGE, ), - ) + ), ) } diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepositoryITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepositoryITests.kt index 12c342ec8..64dc02f59 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepositoryITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaMissionRepositoryITests.kt @@ -88,7 +88,7 @@ class JpaMissionRepositoryITests : AbstractDBTests() { controlUnitId = 10004, name = "PAM Jeanne Barret", type = ControlUnitResourceType.BARGE, - ) + ), ), ), ), @@ -113,7 +113,7 @@ class JpaMissionRepositoryITests : AbstractDBTests() { assertThat(newMissionCreated.envActions?.get(1)?.facade).isEqualTo("Facade 2") assertThat(newMissionCreated.envActions?.get(1)?.department).isEqualTo("Department 2") assertThat((newMissionCreated.envActions?.get(2) as EnvActionNoteEntity).observations).isEqualTo( - noteObservations + noteObservations, ) val missions = jpaMissionRepository.findAll( @@ -153,7 +153,7 @@ class JpaMissionRepositoryITests : AbstractDBTests() { controlUnitId = 10004, name = "PAM Jeanne Barret", type = ControlUnitResourceType.BARGE, - ) + ), ), ), ), @@ -229,7 +229,7 @@ class JpaMissionRepositoryITests : AbstractDBTests() { controlUnitId = 5, name = "PAM Jeanne Barret", type = ControlUnitResourceType.BARGE, - ) + ), ), ), ), @@ -264,8 +264,8 @@ class JpaMissionRepositoryITests : AbstractDBTests() { name = "PAM Jeanne Barret", administration = "", isArchived = false, - resources = listOf() - ) + resources = listOf(), + ), ), isGeometryComputedFromControls = false, ) @@ -473,7 +473,7 @@ class JpaMissionRepositoryITests : AbstractDBTests() { missionSources = listOf( MissionSourceEnum.MONITORFISH, MissionSourceEnum.POSEIDON_CACEM, - MissionSourceEnum.POSEIDON_CNSP + MissionSourceEnum.POSEIDON_CNSP, ), pageable = Pageable.unpaged(), ) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingITests.kt index 65c353991..24cfb7ebc 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/database/repositories/JpaReportingITests.kt @@ -4,13 +4,13 @@ import fr.gouv.cacem.monitorenv.domain.entities.VehicleTypeEnum import fr.gouv.cacem.monitorenv.domain.entities.reporting.ReportingEntity import fr.gouv.cacem.monitorenv.domain.entities.reporting.SourceTypeEnum import fr.gouv.cacem.monitorenv.domain.entities.reporting.TargetTypeEnum -import java.time.ZonedDateTime import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.data.domain.Pageable import org.springframework.transaction.annotation.Transactional +import java.time.ZonedDateTime @SpringBootTest(properties = ["monitorenv.scheduling.enable=false"]) class JpaReportingITests : AbstractDBTests() { @@ -25,12 +25,12 @@ class JpaReportingITests : AbstractDBTests() { // When val newReporting = - ReportingEntity( - createdAt = ZonedDateTime.parse("2023-04-01T00:00:00Z"), - isArchived = false, - isDeleted = false, - openBy = "CDA", - ) + ReportingEntity( + createdAt = ZonedDateTime.parse("2023-04-01T00:00:00Z"), + isArchived = false, + isDeleted = false, + openBy = "CDA", + ) val createdReporting = jpaReportingRepository.save(newReporting) // Then @@ -58,15 +58,15 @@ class JpaReportingITests : AbstractDBTests() { @Test fun `findAll should return all reportings`() { val reportings = - jpaReportingRepository.findAll( - Pageable.unpaged(), - startedAfter = ZonedDateTime.parse("2022-01-01T00:01:00Z").toInstant(), - startedBefore = null, - reportingType = null, - seaFronts = null, - sourcesType = null, - status = null, - ) + jpaReportingRepository.findAll( + Pageable.unpaged(), + startedAfter = ZonedDateTime.parse("2022-01-01T00:01:00Z").toInstant(), + startedBefore = null, + reportingType = null, + seaFronts = null, + sourcesType = null, + status = null, + ) assertThat(reportings.size).isEqualTo(5) } @@ -80,14 +80,14 @@ class JpaReportingITests : AbstractDBTests() { // When val existingReporting = jpaReportingRepository.findById(1) val updatedReporting = - existingReporting.copy( - sourceType = SourceTypeEnum.SEMAPHORE, - semaphoreId = 23, - createdAt = ZonedDateTime.parse("2023-04-01T00:00:00Z"), - isArchived = false, - isDeleted = false, - openBy = "CDA", - ) + existingReporting.copy( + sourceType = SourceTypeEnum.SEMAPHORE, + semaphoreId = 23, + createdAt = ZonedDateTime.parse("2023-04-01T00:00:00Z"), + isArchived = false, + isDeleted = false, + openBy = "CDA", + ) val savedReporting = jpaReportingRepository.save(updatedReporting) // Then diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/MapOrElseEmptyUTest.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/MapOrElseEmptyUTest.kt index 4f87eb0fc..22cd07ae3 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/MapOrElseEmptyUTest.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/MapOrElseEmptyUTest.kt @@ -1,8 +1,8 @@ package fr.gouv.cacem.monitorenv.utils -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test @DisplayName("utils/mapOrElseEmpty()") class MapOrElseEmptyUTest { diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequireIdsUTest.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequireIdsUTest.kt index 03320581f..9389126e5 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequireIdsUTest.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequireIdsUTest.kt @@ -1,8 +1,8 @@ package fr.gouv.cacem.monitorenv.utils -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test @DisplayName("utils/requireIds()") class RequireIdsUTest { diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequireNotNullListUTest.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequireNotNullListUTest.kt index f3437417b..5255cc12a 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequireNotNullListUTest.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequireNotNullListUTest.kt @@ -1,8 +1,8 @@ package fr.gouv.cacem.monitorenv.utils -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test @DisplayName("utils/requireNotNullList()") class RequireNotNullListUTest { diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequirePresentUTest.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequirePresentUTest.kt index f0338c85d..83fbe6624 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequirePresentUTest.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/utils/RequirePresentUTest.kt @@ -1,8 +1,8 @@ package fr.gouv.cacem.monitorenv.utils -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test import java.util.Optional @DisplayName("utils/_root_ide_package_.fr.gouv.cacem.monitorenv.utils.requirePresent()") diff --git a/frontend/.husky/pre-commit b/frontend/.husky/pre-commit index f22ecd59d..582752578 100755 --- a/frontend/.husky/pre-commit +++ b/frontend/.husky/pre-commit @@ -3,4 +3,5 @@ [ -n "$CI" ] && exit 0 +make lint-back npx lint-staged --cwd ./frontend diff --git a/frontend/cypress/e2e/back_office/administration_form.spec.ts b/frontend/cypress/e2e/back_office/administration_form.spec.ts index 8f8bed997..3e695193e 100644 --- a/frontend/cypress/e2e/back_office/administration_form.spec.ts +++ b/frontend/cypress/e2e/back_office/administration_form.spec.ts @@ -59,7 +59,7 @@ context('Back Office > Administration Form', () => { cy.intercept('POST', `/api/v1/administrations/2007/archive`).as('archiveAdministration') cy.getTableRowById(2007).clickButton('Archiver cette administration') - cy.clickButton('Confirmer') + cy.clickButton('Archiver') cy.wait('@archiveAdministration') @@ -73,7 +73,7 @@ context('Back Office > Administration Form', () => { cy.intercept('DELETE', `/api/v1/administrations/2007`).as('deleteAdministration') cy.getTableRowById(2007).clickButton('Supprimer cette administration') - cy.clickButton('Confirmer') + cy.clickButton('Supprimer') cy.wait('@deleteAdministration') diff --git a/frontend/cypress/e2e/back_office/administration_list/filters.spec.ts b/frontend/cypress/e2e/back_office/administration_table/filters.spec.ts similarity index 94% rename from frontend/cypress/e2e/back_office/administration_list/filters.spec.ts rename to frontend/cypress/e2e/back_office/administration_table/filters.spec.ts index cd0da42f6..eba48f244 100644 --- a/frontend/cypress/e2e/back_office/administration_list/filters.spec.ts +++ b/frontend/cypress/e2e/back_office/administration_table/filters.spec.ts @@ -1,4 +1,4 @@ -context('Back Office > Administration List > Filters', () => { +context('Back Office > Administration Table > Filters', () => { beforeEach(() => { cy.intercept('GET', `/api/v1/administrations`).as('getAdministrations') diff --git a/frontend/cypress/e2e/back_office/administration_list/row_actions.spec.ts b/frontend/cypress/e2e/back_office/administration_table/row_actions.spec.ts similarity index 80% rename from frontend/cypress/e2e/back_office/administration_list/row_actions.spec.ts rename to frontend/cypress/e2e/back_office/administration_table/row_actions.spec.ts index 91b5af156..480115e65 100644 --- a/frontend/cypress/e2e/back_office/administration_list/row_actions.spec.ts +++ b/frontend/cypress/e2e/back_office/administration_table/row_actions.spec.ts @@ -1,5 +1,5 @@ // Successful archiving and deleting use cases are tested in `administration_form.spec.ts` for Test Idempotency purpose -context('Back Office > Administration List > Row Actions', () => { +context('Back Office > Administration Table > Row Actions', () => { beforeEach(() => { cy.intercept('GET', `/api/v1/administrations`).as('getAdministrations') @@ -12,21 +12,23 @@ context('Back Office > Administration List > Row Actions', () => { cy.intercept('POST', `/api/v1/administrations/1005/archive`).as('archiveAdministration') cy.getTableRowById(1005).clickButton('Archiver cette administration') - cy.clickButton('Confirmer') + cy.clickButton('Archiver') cy.wait('@archiveAdministration') cy.get('.Component-Dialog').should('be.visible') + cy.contains('Archivage impossible').should('be.visible') }) it('Should show a dialog when trying to delete an administration linked to some control units', () => { cy.intercept('DELETE', `/api/v1/administrations/1005`).as('deleteAdministration') cy.getTableRowById(1005).clickButton('Supprimer cette administration') - cy.clickButton('Confirmer') + cy.clickButton('Supprimer') cy.wait('@deleteAdministration') cy.get('.Component-Dialog').should('be.visible') + cy.contains('Suppression impossible').should('be.visible') }) }) diff --git a/frontend/cypress/e2e/back_office/base_list/filters.spec.ts b/frontend/cypress/e2e/back_office/base_table/filters.spec.ts similarity index 92% rename from frontend/cypress/e2e/back_office/base_list/filters.spec.ts rename to frontend/cypress/e2e/back_office/base_table/filters.spec.ts index 5427e3e21..505cdf92a 100644 --- a/frontend/cypress/e2e/back_office/base_list/filters.spec.ts +++ b/frontend/cypress/e2e/back_office/base_table/filters.spec.ts @@ -1,4 +1,4 @@ -context('Back Office > Base List > Filters', () => { +context('Back Office > Base Table > Filters', () => { beforeEach(() => { cy.intercept('GET', `/api/v1/bases`).as('getBases') diff --git a/frontend/cypress/e2e/back_office/control_unit_form.spec.ts b/frontend/cypress/e2e/back_office/control_unit_form.spec.ts index 22648d3cd..ae06ede2e 100644 --- a/frontend/cypress/e2e/back_office/control_unit_form.spec.ts +++ b/frontend/cypress/e2e/back_office/control_unit_form.spec.ts @@ -77,7 +77,7 @@ context('Back Office > Control Unit Form', () => { cy.intercept('POST', `/api/v2/control_units/10033/archive`).as('archiveControlUnit') cy.getTableRowById(10033).clickButton('Archiver cette unité de contrôle') - cy.clickButton('Confirmer') + cy.clickButton('Archiver') cy.wait('@archiveControlUnit') @@ -91,7 +91,7 @@ context('Back Office > Control Unit Form', () => { cy.intercept('DELETE', `/api/v2/control_units/10033`).as('deleteControlUnit') cy.getTableRowById(10033).clickButton('Supprimer cette unité de contrôle') - cy.clickButton('Confirmer') + cy.clickButton('Supprimer') cy.wait('@deleteControlUnit') diff --git a/frontend/cypress/e2e/back_office/control_unit_list/filters.spec.ts b/frontend/cypress/e2e/back_office/control_unit_table/filters.spec.ts similarity index 96% rename from frontend/cypress/e2e/back_office/control_unit_list/filters.spec.ts rename to frontend/cypress/e2e/back_office/control_unit_table/filters.spec.ts index f3579f144..b0608f40c 100644 --- a/frontend/cypress/e2e/back_office/control_unit_list/filters.spec.ts +++ b/frontend/cypress/e2e/back_office/control_unit_table/filters.spec.ts @@ -1,4 +1,4 @@ -context('Back Office > Control Unit List > Filters', () => { +context('Back Office > Control Unit Table > Filters', () => { beforeEach(() => { cy.intercept('GET', `/api/v2/control_units`).as('getControlUnits') diff --git a/frontend/cypress/e2e/back_office/control_unit_list/row_actions.spec.ts b/frontend/cypress/e2e/back_office/control_unit_table/row_actions.spec.ts similarity index 80% rename from frontend/cypress/e2e/back_office/control_unit_list/row_actions.spec.ts rename to frontend/cypress/e2e/back_office/control_unit_table/row_actions.spec.ts index b34ee7c52..3c4890c31 100644 --- a/frontend/cypress/e2e/back_office/control_unit_list/row_actions.spec.ts +++ b/frontend/cypress/e2e/back_office/control_unit_table/row_actions.spec.ts @@ -1,5 +1,5 @@ // Successful archiving and deleting use cases are tested in `control_unit_form.spec.ts` for Test Idempotency purpose -context('Back Office > Control Unit List > Row Actions', () => { +context('Back Office > Control Unit Table > Row Actions', () => { beforeEach(() => { cy.intercept('GET', `/api/v2/control_units`).as('getControlUnits') @@ -12,10 +12,11 @@ context('Back Office > Control Unit List > Row Actions', () => { cy.intercept('DELETE', `/api/v2/control_units/10000`).as('deleteControlUnit') cy.getTableRowById(10000).clickButton('Supprimer cette unité de contrôle') - cy.clickButton('Confirmer') + cy.clickButton('Supprimer') cy.wait('@deleteControlUnit') cy.get('.Component-Dialog').should('be.visible') + cy.contains('Suppression impossible').should('be.visible') }) }) diff --git a/frontend/cypress/e2e/main_window/control_unit_dialog/contact_list.spec.ts b/frontend/cypress/e2e/main_window/control_unit_dialog/contact_list.spec.ts new file mode 100644 index 000000000..5495e9c86 --- /dev/null +++ b/frontend/cypress/e2e/main_window/control_unit_dialog/contact_list.spec.ts @@ -0,0 +1,98 @@ +import { gotToMainWindowAndOpenControlUnit } from './utils' + +context('Main Window > Control Unit Dialog > Contact List', () => { + beforeEach(() => { + gotToMainWindowAndOpenControlUnit(10000) + }) + + it('Should show all contacts by default', () => { + cy.contains('Contact 1').should('be.visible') + cy.contains('Contact 2').should('be.visible') + }) + + it('Should validate the form', () => { + cy.clickButton('Ajouter un contact') + + cy.clickButton('Ajouter') + + cy.contains('Veuillez choisir un nom.').should('be.visible') + cy.contains('Veuillez entrer un téléphone ou un email.').should('be.visible') + + cy.clickButton('Annuler') + + cy.get('p').contains('Ajouter un contact').should('not.exist') + }) + + it('Should add, edit and delete a contact', () => { + // ------------------------------------------------------------------------- + // Create + + cy.intercept('POST', `/api/v1/control_unit_contacts`).as('createControlUnitContact') + + cy.clickButton('Ajouter un contact') + + cy.fill('Nom du contact', 'Adjoint') + cy.fill('Numéro de téléphone', '0123456789') + cy.fill('Adresse mail', 'foo@example.org') + + cy.clickButton('Ajouter') + + cy.wait('@createControlUnitContact').then(interception => { + if (!interception.response) { + assert.fail('`interception.response` is undefined.') + } + + assert.deepInclude(interception.request.body, { + email: 'foo@example.org', + name: 'ADJUNCT', + phone: '0123456789' + }) + }) + + cy.get('p').contains('Ajouter un contact').should('not.exist') + cy.contains('Adjoint').should('be.visible') + + // ------------------------------------------------------------------------- + // Edit + + cy.intercept('PUT', `/api/v1/control_unit_contacts/4`).as('updateControlUnitContact') + + cy.getDataCy('ControlUnitDialog-control-unit-contact').filter('[data-id="4"]').clickButton('Éditer ce contact') + + cy.fill('Nom du contact', 'Passerelle') + cy.fill('Numéro de téléphone', '9876543210') + cy.fill('Adresse mail', 'bar@example.org') + + cy.clickButton('Enregistrer les modifications') + + cy.wait('@updateControlUnitContact').then(interception => { + if (!interception.response) { + assert.fail('`interception.response` is undefined.') + } + + assert.deepInclude(interception.request.body, { + email: 'bar@example.org', + id: 4, + name: 'BRIDGE', + phone: '9876543210' + }) + }) + + cy.get('p').contains('Éditer un contact').should('not.exist') + cy.contains('Enregistrer les modifications').should('not.exist') + cy.contains('Passerelle').should('be.visible') + + // ------------------------------------------------------------------------- + // Delete + + cy.intercept('DELETE', `/api/v1/control_unit_contacts/4`).as('deleteControlUnitContact') + + cy.getDataCy('ControlUnitDialog-control-unit-contact').filter('[data-id="4"]').clickButton('Éditer ce contact') + cy.clickButton('Supprimer ce contact') + cy.clickButton('Supprimer') + + cy.wait('@deleteControlUnitContact') + + cy.contains('Passerelle').should('not.exist') + }) +}) diff --git a/frontend/cypress/e2e/main_window/control_unit_dialog/form.spec.ts b/frontend/cypress/e2e/main_window/control_unit_dialog/form.spec.ts new file mode 100644 index 000000000..b49f650ce --- /dev/null +++ b/frontend/cypress/e2e/main_window/control_unit_dialog/form.spec.ts @@ -0,0 +1,57 @@ +import { gotToMainWindowAndOpenControlUnit } from './utils' + +context('Main Window > Control Unit Dialog > Resource List', () => { + beforeEach(() => { + gotToMainWindowAndOpenControlUnit(10000) + }) + + it('Should edit a control unit', () => { + cy.intercept('PUT', `/api/v2/control_units/10000`).as('updateControlUnit') + + // ------------------------------------------------------------------------- + // Terms note + + cy.getDataCy('ControlUnitDialog-termsNote').forceClick() + + cy.fill('Modalités de contact avec l’unité', 'Des modalités de contact avec l’unité.') + + cy.clickButton('Valider') + + cy.wait('@updateControlUnit').then(interception => { + if (!interception.response) { + assert.fail('`interception.response` is undefined.') + } + + assert.deepInclude(interception.request.body, { + id: 10000, + termsNote: 'Des modalités de contact avec l’unité.' + }) + }) + + cy.contains('Des modalités de contact avec l’unité.').should('be.visible') + cy.get('.Element-Button').contains('Valider').should('not.exist') + + // ------------------------------------------------------------------------- + // Area note + + cy.getDataCy('ControlUnitDialog-areaNote').forceClick() + + cy.fill('Secteur d’intervention', 'Un secteur d’intervention.') + + cy.clickButton('Valider') + + cy.wait('@updateControlUnit').then(interception => { + if (!interception.response) { + assert.fail('`interception.response` is undefined.') + } + + assert.deepInclude(interception.request.body, { + areaNote: 'Un secteur d’intervention.', + id: 10000 + }) + }) + + cy.contains('Un secteur d’intervention.').should('be.visible') + cy.get('.Element-Button').contains('Valider').should('not.exist') + }) +}) diff --git a/frontend/cypress/e2e/main_window/control_unit_dialog/resource_list.spec.ts b/frontend/cypress/e2e/main_window/control_unit_dialog/resource_list.spec.ts new file mode 100644 index 000000000..04f24edd9 --- /dev/null +++ b/frontend/cypress/e2e/main_window/control_unit_dialog/resource_list.spec.ts @@ -0,0 +1,103 @@ +import { gotToMainWindowAndOpenControlUnit } from './utils' + +context('Main Window > Control Unit Dialog > Resource List', () => { + beforeEach(() => { + gotToMainWindowAndOpenControlUnit(10000) + }) + + it('Should show all resources by default', () => { + cy.contains('Barge – Semi-rigide 1').should('be.visible') + cy.contains('Barge – Semi-rigide 2').should('be.visible') + }) + + it('Should validate the form', () => { + cy.clickButton('Ajouter un moyen') + + cy.clickButton('Ajouter') + + cy.contains('Veuillez choisir un type.').should('be.visible') + cy.contains('Veuillez choisir une base.').should('be.visible') + + cy.clickButton('Annuler') + + cy.get('p').contains('Ajouter un moyen').should('not.exist') + }) + + it('Should add, edit and delete a resource', () => { + // ------------------------------------------------------------------------- + // Create + + cy.intercept('POST', `/api/v1/control_unit_resources`).as('createControlUnitResource') + + cy.clickButton('Ajouter un moyen') + + cy.fill('Type de moyen', 'Avion') + // On ne met pas de nom de moyen ici + // pour tester que ce soit bien le type qui soit utilisé comme nom lorsque le nom est vide. + cy.fill('Base du moyen', 'Dunkerque') + cy.fill('Commentaire', 'Un commentaire sur le moyen.') + + cy.clickButton('Ajouter') + + cy.wait('@createControlUnitResource').then(interception => { + if (!interception.response) { + assert.fail('`interception.response` is undefined.') + } + + assert.deepInclude(interception.request.body, { + baseId: 3, + name: 'Avion', + note: 'Un commentaire sur le moyen.', + type: 'AIRPLANE' + }) + }) + + cy.get('p').contains('Ajouter un moyen').should('not.exist') + cy.contains('Avion – Avion').should('be.visible') + + // ------------------------------------------------------------------------- + // Edit + + cy.intercept('PUT', `/api/v1/control_unit_resources/13`).as('updateControlUnitResource') + + cy.getDataCy('ControlUnitDialog-control-unit-resource').filter('[data-id="13"]').clickButton('Éditer ce moyen') + + cy.fill('Type de moyen', 'Bâtiment de soutien') + cy.fill('Nom du moyen', 'Super Moyen') + cy.fill('Base du moyen', 'Saint-Malo') + cy.fill('Commentaire', 'Un autre commentaire sur le moyen.') + + cy.clickButton('Enregistrer les modifications') + + cy.wait('@updateControlUnitResource').then(interception => { + if (!interception.response) { + assert.fail('`interception.response` is undefined.') + } + + assert.deepInclude(interception.request.body, { + baseId: 2, + id: 13, + name: 'Super Moyen', + note: 'Un autre commentaire sur le moyen.', + type: 'SUPPORT_SHIP' + }) + }) + + cy.get('p').contains('Éditer un moyen').should('not.exist') + cy.contains('Enregistrer les modifications').should('not.exist') + cy.contains('Bâtiment de soutien – Super Moyen').should('be.visible') + + // ------------------------------------------------------------------------- + // Delete + + cy.intercept('DELETE', `/api/v1/control_unit_resources/13`).as('deleteControlUnitResource') + + cy.getDataCy('ControlUnitDialog-control-unit-resource').filter('[data-id="13"]').clickButton('Éditer ce moyen') + cy.clickButton('Supprimer ce moyen') + cy.clickButton('Supprimer') + + cy.wait('@deleteControlUnitResource') + + cy.contains('Bâtiment de soutien – Super Moyen').should('not.exist') + }) +}) diff --git a/frontend/cypress/e2e/main_window/control_unit_dialog/utils.ts b/frontend/cypress/e2e/main_window/control_unit_dialog/utils.ts new file mode 100644 index 000000000..57ba47355 --- /dev/null +++ b/frontend/cypress/e2e/main_window/control_unit_dialog/utils.ts @@ -0,0 +1,8 @@ +import { goToMainWindow } from '../utils' + +export function gotToMainWindowAndOpenControlUnit(controlUnitId: number) { + goToMainWindow() + + cy.clickButton('Liste des unités de contrôle') + cy.getDataCy('ControlUnitListDialog-control-unit').filter(`[data-id="${controlUnitId}"]`).forceClick().wait(250) +} diff --git a/frontend/cypress/e2e/main_window/control_unit_list_dialog/filters.spec.ts b/frontend/cypress/e2e/main_window/control_unit_list_dialog/filters.spec.ts new file mode 100644 index 000000000..a7b8d2b99 --- /dev/null +++ b/frontend/cypress/e2e/main_window/control_unit_list_dialog/filters.spec.ts @@ -0,0 +1,53 @@ +import { FAKE_MAPBOX_RESPONSE } from '../../constants' + +context('Main Window > Control Unit List Dialog > Filters', () => { + beforeEach(() => { + cy.intercept('GET', 'https://api.mapbox.com/**', FAKE_MAPBOX_RESPONSE) + + cy.visit(`/`).wait(1000) + + cy.clickButton('Liste des unités de contrôle') + }) + + it('Should show all control units by default', () => { + cy.getDataCy('ControlUnitListDialog-control-unit').should('have.length', 33) + + cy.contains('A636 Maïto').should('exist') + cy.contains('SML 50').should('exist') + }) + + it('Should find control units matching the search query', () => { + cy.fill('Rechercher une unité', 'marine') + + cy.getDataCy('ControlUnitListDialog-control-unit').should('have.length', 4) + + cy.contains('Cultures marines – DDTM 30').should('exist') + cy.contains('A636 Maïto').should('exist') + }) + + it('Should find control units matching the selected administration', () => { + cy.fill('Administration', 'Douane') + + cy.getDataCy('ControlUnitListDialog-control-unit').should('have.length', 5) + + cy.contains('BGC Ajaccio').should('exist') + cy.contains('DF 61 Port-de-Bouc').should('exist') + }) + + it('Should find control units matching the selected resource type', () => { + cy.fill('Type de moyen', 'Barge') + + cy.getDataCy('ControlUnitListDialog-control-unit').should('have.length', 3) + + cy.contains('Cultures marines – DDTM 40').should('exist') + cy.contains('DPM – DDTM 14').should('exist') + }) + + it('Should find control units matching the selected base', () => { + cy.fill('Base du moyen', 'Marseille') + + cy.getDataCy('ControlUnitListDialog-control-unit').should('have.length', 1) + + cy.contains('Cultures marines – DDTM 40').should('exist') + }) +}) diff --git a/frontend/cypress/e2e/main_window/utils.ts b/frontend/cypress/e2e/main_window/utils.ts new file mode 100644 index 000000000..78e9173f2 --- /dev/null +++ b/frontend/cypress/e2e/main_window/utils.ts @@ -0,0 +1,7 @@ +import { FAKE_MAPBOX_RESPONSE } from '../constants' + +export function goToMainWindow() { + cy.intercept('GET', 'https://api.mapbox.com/**', FAKE_MAPBOX_RESPONSE) + + cy.visit(`/`).wait(1000) +} diff --git a/frontend/src/api/controlUnitContactsAPI.ts b/frontend/src/api/controlUnitContactsAPI.ts index 23517f66e..00b2888de 100644 --- a/frontend/src/api/controlUnitContactsAPI.ts +++ b/frontend/src/api/controlUnitContactsAPI.ts @@ -17,6 +17,14 @@ export const controlUnitContactsAPI = monitorenvPublicApi.injectEndpoints({ }) }), + deleteControlUnitContact: builder.mutation({ + invalidatesTags: () => [{ type: 'ControlUnits' }], + query: controlUnitContactId => ({ + method: 'DELETE', + url: `/v1/control_unit_contacts/${controlUnitContactId}` + }) + }), + getControlUnitContact: builder.query({ providesTags: () => [{ type: 'ControlUnits' }], query: controlUnitContactId => `/v1/control_unit_contacts/${controlUnitContactId}`, @@ -42,6 +50,7 @@ export const controlUnitContactsAPI = monitorenvPublicApi.injectEndpoints({ export const { useCreateControlUnitContactMutation, + useDeleteControlUnitContactMutation, useGetControlUnitContactQuery, useGetControlUnitContactsQuery, useUpdateControlUnitContactMutation diff --git a/frontend/src/api/controlUnitResourcesAPI.ts b/frontend/src/api/controlUnitResourcesAPI.ts index 1cf6bb76f..767531a42 100644 --- a/frontend/src/api/controlUnitResourcesAPI.ts +++ b/frontend/src/api/controlUnitResourcesAPI.ts @@ -1,8 +1,12 @@ import { monitorenvPublicApi } from './api' +import { ApiErrorCode } from './types' import { FrontendApiError } from '../libs/FrontendApiError' +import { newUserError } from '../libs/UserError' import type { ControlUnit } from '../domain/entities/controlUnit' +const DELETE_CONTROL_UNIT_RESOURCE_ERROR_MESSAGE = + "Ce moyen est rattaché à des missions. Veuillez l'en détacher avant de la supprimer." const GET_CONTROL_UNIT_RESOURCE_ERROR_MESSAGE = "Nous n'avons pas pu récupérer cette resource." const GET_CONTROL_UNIT_RESOURCES_ERROR_MESSAGE = "Nous n'avons pas pu récupérer la liste des resources." @@ -17,6 +21,21 @@ export const controlUnitResourcesAPI = monitorenvPublicApi.injectEndpoints({ }) }), + deleteControlUnitResource: builder.mutation({ + invalidatesTags: () => [{ type: 'Bases' }, { type: 'ControlUnits' }], + query: controlUnitResourceId => ({ + method: 'DELETE', + url: `/v1/control_unit_resources/${controlUnitResourceId}` + }), + transformErrorResponse: response => { + if (response.data.type === ApiErrorCode.FOREIGN_KEY_CONSTRAINT) { + return newUserError(DELETE_CONTROL_UNIT_RESOURCE_ERROR_MESSAGE) + } + + return new FrontendApiError(DELETE_CONTROL_UNIT_RESOURCE_ERROR_MESSAGE, response) + } + }), + getControlUnitResource: builder.query({ providesTags: () => [{ type: 'ControlUnits' }], query: controlUnitResourceId => `/v1/control_unit_resources/${controlUnitResourceId}`, @@ -42,6 +61,7 @@ export const controlUnitResourcesAPI = monitorenvPublicApi.injectEndpoints({ export const { useCreateControlUnitResourceMutation, + useDeleteControlUnitResourceMutation, useGetControlUnitResourceQuery, useGetControlUnitResourcesQuery, useUpdateControlUnitResourceMutation diff --git a/frontend/src/components/ConfirmationModal.tsx b/frontend/src/components/ConfirmationModal.tsx new file mode 100644 index 000000000..d2b89aa3f --- /dev/null +++ b/frontend/src/components/ConfirmationModal.tsx @@ -0,0 +1,87 @@ +import { Accent, Button, Dialog, Icon } from '@mtes-mct/monitor-ui' +import styled from 'styled-components' + +import type { Promisable } from 'type-fest' + +export type ConfirmationModalProps = { + color?: string + confirmationButtonLabel: string + iconName?: keyof typeof Icon + message: string + onCancel: () => Promisable + onConfirm: () => Promisable + title: string +} +export function ConfirmationModal({ + color, + confirmationButtonLabel, + iconName, + message, + onCancel, + onConfirm, + title +}: ConfirmationModalProps) { + const SelectedIcon = iconName ? Icon[iconName] : null + + return ( + + {title} + + {SelectedIcon && ( + + + + )} + {message} + + + + + + + ) +} + +// TODO Allow direct `width` prop control in MUI. +// This is a mess. I wonder if we should add inner classes in MUI. +const StyledDialog = styled(Dialog)` + > div:last-child { + max-width: 440px; + min-width: 440px; + + /* Dialog.Body */ + > div:nth-child(2) { + padding-top: 24px; + } + + /* Dialog.Action */ + > div:last-child { + padding: 24px 0 32px; + + > .Element-Button { + width: 136px; + + :not(:first-child) { + margin-left: 8px; + } + } + } + } +` + +const Picto = styled.div` + display: flex; + justify-content: center; + margin-bottom: 8px; +` + +/* TODO Replace the `> p` forcing the `!important`. */ +const Message = styled.p<{ + $color?: string +}>` + ${p => p.$color && `color: ${p.$color} !important;`} + font-size: 16px; + font-weight: bold; +` diff --git a/frontend/src/components/Dialog.tsx b/frontend/src/components/Dialog.tsx new file mode 100644 index 000000000..c7188e5e1 --- /dev/null +++ b/frontend/src/components/Dialog.tsx @@ -0,0 +1,82 @@ +import { Button, Dialog as MuiDialog, Icon } from '@mtes-mct/monitor-ui' +import styled from 'styled-components' + +import type { Promisable } from 'type-fest' + +export type DialogProps = { + color?: string + iconName?: keyof typeof Icon + message: string + onClose: () => Promisable + title: string + titleBackgroundColor?: string +} +export function Dialog({ color, iconName, message, onClose, title, titleBackgroundColor }: DialogProps) { + const SelectedIcon = iconName ? Icon[iconName] : null + + return ( + + {title} + + {SelectedIcon && ( + + + + )} + {message} + + + + + + ) +} + +// TODO Allow direct `width` prop control in MUI. +// This is a mess. I wonder if we should add inner classes in MUI. +const StyledDialog = styled(MuiDialog)<{ + $titleBackgroundColor: string | undefined +}>` + > div:last-child { + max-width: 440px; + min-width: 440px; + + /* Dialog.Title */ + > h4 { + ${p => p.$titleBackgroundColor && `background-color: ${p.$titleBackgroundColor};`} + } + + /* Dialog.Body */ + > div:nth-child(2) { + padding-top: 24px; + } + + /* Dialog.Action */ + > div:last-child { + padding: 24px 0 32px; + + > .Element-Button { + width: 136px; + + :not(:first-child) { + margin-left: 8px; + } + } + } + } +` + +const Picto = styled.div` + display: flex; + justify-content: center; + margin-bottom: 8px; +` + +/* TODO Replace the `> p` forcing the `!important`. */ +const Message = styled.p<{ + $color?: string +}>` + ${p => p.$color && `color: ${p.$color} !important;`} + font-size: 16px; + font-weight: bold; +` diff --git a/frontend/src/domain/shared_slices/BackOffice.ts b/frontend/src/domain/shared_slices/BackOffice.ts deleted file mode 100644 index 969c82775..000000000 --- a/frontend/src/domain/shared_slices/BackOffice.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { createSlice, type PayloadAction } from '@reduxjs/toolkit' - -import type { BackOfficeConfirmationModalActionType } from '../use_cases/backOffice/types' - -type BackOfficeState = { - confirmationModalActionId: number - confirmationModalActionType: BackOfficeConfirmationModalActionType | undefined - confirmationModalMessage: string | undefined - - dialogMessage: string | undefined - - isConfirmationModalOpen: boolean - isDialogOpen: boolean -} -const INITIAL_STATE: BackOfficeState = { - confirmationModalActionId: -1, - confirmationModalActionType: undefined, - confirmationModalMessage: undefined, - - dialogMessage: undefined, - - isConfirmationModalOpen: false, - isDialogOpen: false -} - -const backOfficeSlice = createSlice({ - initialState: INITIAL_STATE, - name: 'backOffice', - reducers: { - closeConfirmationModal(state) { - state.confirmationModalActionId = -1 - state.confirmationModalActionType = undefined - state.confirmationModalMessage = undefined - state.isConfirmationModalOpen = false - }, - - closeDialog(state) { - state.dialogMessage = undefined - state.isDialogOpen = false - }, - - openConfirmationModal( - state, - action: PayloadAction<{ - actionId: number - actionType: BackOfficeConfirmationModalActionType - message: string - }> - ) { - state.confirmationModalActionId = action.payload.actionId - state.confirmationModalActionType = action.payload.actionType - state.confirmationModalMessage = action.payload.message - state.isConfirmationModalOpen = true - }, - - openDialog( - state, - action: PayloadAction<{ - message: string - }> - ) { - state.dialogMessage = action.payload.message - state.isDialogOpen = true - } - } -}) - -export const { closeConfirmationModal, openConfirmationModal } = backOfficeSlice.actions - -export const backOfficeActions = backOfficeSlice.actions -export const backOfficeReducer = backOfficeSlice.reducer diff --git a/frontend/src/domain/shared_slices/Global.ts b/frontend/src/domain/shared_slices/Global.ts index 3ffc8d31d..ddab01d44 100644 --- a/frontend/src/domain/shared_slices/Global.ts +++ b/frontend/src/domain/shared_slices/Global.ts @@ -1,4 +1,4 @@ -// TODO It may be a good thing to either call this slice 'mainWindowSlice' (or something with "map"?) since it targets the main window. +// TODO This slice should disappear in favor of `features/MainWindow/slice.ts`. import { createSlice, type PayloadAction } from '@reduxjs/toolkit' @@ -95,6 +95,7 @@ const initialState: GlobalStateType = { // state entry for other children components whom visibility is already handled by parent components isLayersSidebarVisible: false, + // TODO Use `MainWindowDialog` or `MainWindowConfirmationModal`. isControlUnitDialogVisible: false, isControlUnitListDialogVisible: false, diff --git a/frontend/src/domain/shared_slices/index.js b/frontend/src/domain/shared_slices/index.ts similarity index 78% rename from frontend/src/domain/shared_slices/index.js rename to frontend/src/domain/shared_slices/index.ts index 5bc4c4b83..d3d960fb1 100644 --- a/frontend/src/domain/shared_slices/index.js +++ b/frontend/src/domain/shared_slices/index.ts @@ -3,7 +3,6 @@ import { combineReducers } from '@reduxjs/toolkit' import { administrativeSlicePersistedReducer } from './Administrative' -import { backOfficeReducer } from './BackOffice' import { drawReducer } from './Draw' import { globalReducer } from './Global' import { interestPointSlicePersistedReducer } from './InterestPoint' @@ -28,12 +27,14 @@ import { missionsAPI } from '../../api/missionsAPI' import { regulatoryLayersAPI } from '../../api/regulatoryLayersAPI' import { reportingsAPI } from '../../api/reportingsAPI' import { semaphoresAPI } from '../../api/semaphoresAPI' -import { backOfficeAdministrationListPersistedReducer } from '../../features/Administrations/BackOfficeAdministrationList/slice' -import { backOfficeBaseListPersistedReducer } from '../../features/Bases/BackOfficeBaseList/slice' -import { backOfficeControlUnitListPersistedReducer } from '../../features/ControlUnits/BackOfficeControlUnitList/slice' -import { mapControlUnitDialogReducer } from '../../features/ControlUnits/MapControlUnitDialog/slice' -import { mapControlUnitListDialogPersistedReducer } from '../../features/ControlUnits/MapControlUnitListDialog/slice' +import { administrationTablePersistedReducer } from '../../features/Administration/components/AdministrationTable/slice' +import { backOfficeReducer } from '../../features/BackOffice/slice' +import { baseTablePersistedReducer } from '../../features/Base/components/BaseTable/slice' +import { controlUnitDialogReducer } from '../../features/ControlUnit/components/ControlUnitDialog/slice' +import { controlUnitListDialogPersistedReducer } from '../../features/ControlUnit/components/ControlUnitListDialog/slice' +import { controlUnitTablePersistedReducer } from '../../features/ControlUnit/components/ControlUnitTable/slice' import { layerSearchSliceReducer } from '../../features/layersSelector/search/LayerSearch.slice' +import { mainWindowReducer } from '../../features/MainWindow/slice' import { sideWindowReducer } from '../../features/SideWindow/slice' // TODO Maybe add a specifc store for the backoffice? @@ -44,16 +45,17 @@ export const homeReducers = combineReducers({ administrative: administrativeSlicePersistedReducer, backOffice: backOfficeReducer, - backOfficeAdministrationList: backOfficeAdministrationListPersistedReducer, - backOfficeBaseList: backOfficeBaseListPersistedReducer, - backOfficeControlUnitList: backOfficeControlUnitListPersistedReducer, + backOfficeAdministrationList: administrationTablePersistedReducer, + backOfficeBaseList: baseTablePersistedReducer, + backOfficeControlUnitList: controlUnitTablePersistedReducer, draw: drawReducer, global: globalReducer, interestPoint: interestPointSlicePersistedReducer, layerSearch: layerSearchSliceReducer, + mainWindow: mainWindowReducer, map: mapSliceReducer, - mapControlUnitDialog: mapControlUnitDialogReducer, - mapControlUnitListDialog: mapControlUnitListDialogPersistedReducer, + mapControlUnitDialog: controlUnitDialogReducer, + mapControlUnitListDialog: controlUnitListDialogPersistedReducer, measurement: measurementSlicePersistedReducer, missionFilters: missionFiltersPersistedReducer, missionState: missionStateSliceReducer, diff --git a/frontend/src/domain/use_cases/backOffice/handleModalConfirmation.ts b/frontend/src/domain/use_cases/backOffice/handleModalConfirmation.ts deleted file mode 100644 index 7736badf6..000000000 --- a/frontend/src/domain/use_cases/backOffice/handleModalConfirmation.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { BackOfficeConfirmationModalActionType } from './types' -import { closeConfirmationModal } from '../../shared_slices/BackOffice' -import { archiveAdministration } from '../administration/archiveAdministration' -import { deleteAdministration } from '../administration/deleteAdministration' -import { archiveControlUnit } from '../controlUnit/archiveControlUnit' -import { deleteControlUnit } from '../controlUnit/deleteControlUnit' - -import type { AppThunk } from '../../../store' - -export const handleModalConfirmation = (): AppThunk => async (dispatch, getState) => { - const { confirmationModalActionType } = getState().backOffice - - switch (confirmationModalActionType) { - case BackOfficeConfirmationModalActionType.ARCHIVE_ADMINISTRATION: - await dispatch(archiveAdministration()) - break - - case BackOfficeConfirmationModalActionType.ARCHIVE_CONTROL_UNIT: - await dispatch(archiveControlUnit()) - break - - case BackOfficeConfirmationModalActionType.DELETE_ADMINISTRATION: - await dispatch(deleteAdministration()) - break - - case BackOfficeConfirmationModalActionType.DELETE_CONTROL_UNIT: - await dispatch(deleteControlUnit()) - break - - default: - break - } - - dispatch(closeConfirmationModal()) -} diff --git a/frontend/src/domain/use_cases/backOffice/types.ts b/frontend/src/domain/use_cases/backOffice/types.ts deleted file mode 100644 index 13a2e6eed..000000000 --- a/frontend/src/domain/use_cases/backOffice/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -export enum BackOfficeConfirmationModalActionType { - 'ARCHIVE_ADMINISTRATION' = 'ARCHIVE_ADMINISTRATION', - 'ARCHIVE_CONTROL_UNIT' = 'ARCHIVE_CONTROL_UNIT', - 'DELETE_ADMINISTRATION' = 'DELETE_ADMINISTRATION', - 'DELETE_CONTROL_UNIT' = 'DELETE_CONTROL_UNIT' -} diff --git a/frontend/src/domain/use_cases/controlUnit/deleteControlUnit.ts b/frontend/src/domain/use_cases/controlUnit/deleteControlUnit.ts deleted file mode 100644 index 2e75bad86..000000000 --- a/frontend/src/domain/use_cases/controlUnit/deleteControlUnit.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { logSoftError } from '@mtes-mct/monitor-ui' - -import { controlUnitsAPI } from '../../../api/controlUnitsAPI' -import { isUserError } from '../../../libs/UserError' -import { backOfficeActions } from '../../shared_slices/BackOffice' - -import type { AppThunk } from '../../../store' - -export const deleteControlUnit = (): AppThunk> => async (dispatch, getState) => { - const controlUnitId = getState().backOffice.confirmationModalActionId - - try { - const { error } = await dispatch(controlUnitsAPI.endpoints.deleteControlUnit.initiate(controlUnitId) as any) - if (error) { - throw error - } - } catch (err) { - if (isUserError(err)) { - dispatch(backOfficeActions.openDialog({ message: err.userMessage })) - - return - } - - logSoftError({ - message: `An error happened while deleting a control unit (ID=${controlUnitId}").`, - originalError: err, - userMessage: "Une erreur est survenue pendant la suppression de l'unité de contrôle." - }) - } -} diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationForm/constants.tsx b/frontend/src/features/Administration/components/AdministrationForm/constants.tsx similarity index 87% rename from frontend/src/features/Administrations/BackOfficeAdministrationForm/constants.tsx rename to frontend/src/features/Administration/components/AdministrationForm/constants.tsx index 19c846da0..76100c36d 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationForm/constants.tsx +++ b/frontend/src/features/Administration/components/AdministrationForm/constants.tsx @@ -1,11 +1,11 @@ import { Icon, Size } from '@mtes-mct/monitor-ui' import { object, string } from 'yup' -import { NavIconButton } from '../../../ui/NavIconButton' -import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../BackOfficeMenu/constants' +import { NavIconButton } from '../../../../ui/NavIconButton' +import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../../BackOfficeMenu/constants' import type { AdministrationFormValues } from './types' -import type { ControlUnit } from '../../../domain/entities/controlUnit' +import type { ControlUnit } from '../../../../domain/entities/controlUnit' import type { ColumnDef } from '@tanstack/react-table' export const ADMINISTRATION_FORM_SCHEMA = object({ diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationForm/index.tsx b/frontend/src/features/Administration/components/AdministrationForm/index.tsx similarity index 92% rename from frontend/src/features/Administrations/BackOfficeAdministrationForm/index.tsx rename to frontend/src/features/Administration/components/AdministrationForm/index.tsx index efc5f4014..32ede500d 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationForm/index.tsx +++ b/frontend/src/features/Administration/components/AdministrationForm/index.tsx @@ -6,15 +6,15 @@ import { useNavigate, useParams } from 'react-router' import styled from 'styled-components' import { ADMINISTRATION_FORM_SCHEMA, CONTROL_UNIT_TABLE_COLUMNS, INITIAL_ADMINISTRATION_FORM_VALUES } from './constants' -import { administrationsAPI, useGetAdministrationQuery } from '../../../api/administrationsAPI' -import { useAppDispatch } from '../../../hooks/useAppDispatch' -import { FrontendError } from '../../../libs/FrontendError' -import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../BackOfficeMenu/constants' +import { administrationsAPI, useGetAdministrationQuery } from '../../../../api/administrationsAPI' +import { useAppDispatch } from '../../../../hooks/useAppDispatch' +import { FrontendError } from '../../../../libs/FrontendError' +import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../../BackOfficeMenu/constants' import type { AdministrationFormValues } from './types' -import type { Administration } from '../../../domain/entities/administration' +import type { Administration } from '../../../../domain/entities/administration' -export function BackOfficeAdministrationForm() { +export function AdministrationForm() { const { administrationId } = useParams() if (!administrationId) { throw new FrontendError('`administrationId` is undefined.') diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationForm/types.ts b/frontend/src/features/Administration/components/AdministrationForm/types.ts similarity index 66% rename from frontend/src/features/Administrations/BackOfficeAdministrationForm/types.ts rename to frontend/src/features/Administration/components/AdministrationForm/types.ts index 82195d762..9c30d25a1 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationForm/types.ts +++ b/frontend/src/features/Administration/components/AdministrationForm/types.ts @@ -1,4 +1,4 @@ -import type { Administration } from '../../../domain/entities/administration' +import type { Administration } from '../../../../domain/entities/administration' import type { UndefineExceptArrays } from '@mtes-mct/monitor-ui' export type AdministrationFormValues = UndefineExceptArrays diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/FilterBar.tsx b/frontend/src/features/Administration/components/AdministrationTable/FilterBar.tsx similarity index 72% rename from frontend/src/features/Administrations/BackOfficeAdministrationList/FilterBar.tsx rename to frontend/src/features/Administration/components/AdministrationTable/FilterBar.tsx index 79c2ac714..2fe6e05cd 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationList/FilterBar.tsx +++ b/frontend/src/features/Administration/components/AdministrationTable/FilterBar.tsx @@ -2,9 +2,9 @@ import { Icon, TextInput } from '@mtes-mct/monitor-ui' import { useCallback } from 'react' import styled from 'styled-components' -import { backOfficeAdministrationListActions } from './slice' -import { useAppDispatch } from '../../../hooks/useAppDispatch' -import { useAppSelector } from '../../../hooks/useAppSelector' +import { administrationTableActions } from './slice' +import { useAppDispatch } from '../../../../hooks/useAppDispatch' +import { useAppSelector } from '../../../../hooks/useAppSelector' export function FilterBar() { const dispatch = useAppDispatch() @@ -12,7 +12,7 @@ export function FilterBar() { const updateQuery = useCallback( (nextValue: string | undefined) => { - dispatch(backOfficeAdministrationListActions.setFilter({ key: 'query', value: nextValue })) + dispatch(administrationTableActions.setFilter({ key: 'query', value: nextValue })) }, [dispatch] ) diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/TabMenu.tsx b/frontend/src/features/Administration/components/AdministrationTable/TabMenu.tsx similarity index 53% rename from frontend/src/features/Administrations/BackOfficeAdministrationList/TabMenu.tsx rename to frontend/src/features/Administration/components/AdministrationTable/TabMenu.tsx index 9a8d146e9..2c77a406d 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationList/TabMenu.tsx +++ b/frontend/src/features/Administration/components/AdministrationTable/TabMenu.tsx @@ -1,30 +1,30 @@ -import { backOfficeAdministrationListActions } from './slice' -import { useAppDispatch } from '../../../hooks/useAppDispatch' -import { useAppSelector } from '../../../hooks/useAppSelector' -import { TabBar } from '../../BackOffice/components/TabBar' +import { administrationTableActions } from './slice' +import { useAppDispatch } from '../../../../hooks/useAppDispatch' +import { useAppSelector } from '../../../../hooks/useAppSelector' +import { BackOfficeTabBar } from '../../../BackOffice/components/BackOfficeTabBar' export function TabMenu() { const dispatch = useAppDispatch() const backOfficeAdministrationList = useAppSelector(store => store.backOfficeAdministrationList) const filterArchivedAdministrations = (isArchived: boolean) => { - dispatch(backOfficeAdministrationListActions.setFilter({ key: 'isArchived', value: isArchived })) + dispatch(administrationTableActions.setFilter({ key: 'isArchived', value: isArchived })) } return ( - - + filterArchivedAdministrations(false)} > Administrations actives - - + filterArchivedAdministrations(true)} > Administrations archivées - - + + ) } diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/constants.tsx b/frontend/src/features/Administration/components/AdministrationTable/constants.tsx similarity index 85% rename from frontend/src/features/Administrations/BackOfficeAdministrationList/constants.tsx rename to frontend/src/features/Administration/components/AdministrationTable/constants.tsx index 7dfbd9cd6..53f73520c 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationList/constants.tsx +++ b/frontend/src/features/Administration/components/AdministrationTable/constants.tsx @@ -1,9 +1,9 @@ import { Icon, Size } from '@mtes-mct/monitor-ui' -import { NavIconButton } from '../../../ui/NavIconButton' -import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../BackOfficeMenu/constants' +import { NavIconButton } from '../../../../ui/NavIconButton' +import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../../BackOfficeMenu/constants' -import type { Administration } from '../../../domain/entities/administration' +import type { Administration } from '../../../../domain/entities/administration' import type { ColumnDef } from '@tanstack/react-table' export const ADMINISTRATION_TABLE_COLUMNS: Array> = [ diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/index.tsx b/frontend/src/features/Administration/components/AdministrationTable/index.tsx similarity index 84% rename from frontend/src/features/Administrations/BackOfficeAdministrationList/index.tsx rename to frontend/src/features/Administration/components/AdministrationTable/index.tsx index 11dd14741..58b951e48 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationList/index.tsx +++ b/frontend/src/features/Administration/components/AdministrationTable/index.tsx @@ -5,13 +5,13 @@ import styled from 'styled-components' import { FilterBar } from './FilterBar' import { TabMenu } from './TabMenu' import { getAdministrationTableColumns, getFilters } from './utils' -import { useGetAdministrationsQuery } from '../../../api/administrationsAPI' -import { useAppDispatch } from '../../../hooks/useAppDispatch' -import { useAppSelector } from '../../../hooks/useAppSelector' -import { NavButton } from '../../../ui/NavButton' -import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../BackOfficeMenu/constants' +import { useGetAdministrationsQuery } from '../../../../api/administrationsAPI' +import { useAppDispatch } from '../../../../hooks/useAppDispatch' +import { useAppSelector } from '../../../../hooks/useAppSelector' +import { NavButton } from '../../../../ui/NavButton' +import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../../BackOfficeMenu/constants' -export function BackOfficeAdministrationList() { +export function AdministrationTable() { const backOfficeAdministrationList = useAppSelector(store => store.backOfficeAdministrationList) const dispatch = useAppDispatch() const { data: administrations } = useGetAdministrationsQuery() diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/slice.ts b/frontend/src/features/Administration/components/AdministrationTable/slice.ts similarity index 58% rename from frontend/src/features/Administrations/BackOfficeAdministrationList/slice.ts rename to frontend/src/features/Administration/components/AdministrationTable/slice.ts index 734045163..532027f9c 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationList/slice.ts +++ b/frontend/src/features/Administration/components/AdministrationTable/slice.ts @@ -5,11 +5,11 @@ import storage from 'redux-persist/lib/storage' import type { FiltersState } from './types' -export type BackOfficeAdministrationListState = { +interface AdministrationTableState { filtersState: FiltersState } -const INITIAL_STATE: BackOfficeAdministrationListState = { +const INITIAL_STATE: AdministrationTableState = { filtersState: { isArchived: false, query: undefined @@ -17,13 +17,13 @@ const INITIAL_STATE: BackOfficeAdministrationListState = { } const persistConfig = { - key: 'backOfficeAdministrationList', + key: 'administrationList', storage } -const backOfficeAdministrationList = createSlice({ +const AdministrationTableSlice = createSlice({ initialState: INITIAL_STATE, - name: 'backOfficeAdministrationList', + name: 'administrationList', reducers: { setFilter( state, @@ -37,9 +37,6 @@ const backOfficeAdministrationList = createSlice({ } }) -export const backOfficeAdministrationListActions = backOfficeAdministrationList.actions +export const administrationTableActions = AdministrationTableSlice.actions -export const backOfficeAdministrationListPersistedReducer = persistReducer( - persistConfig, - backOfficeAdministrationList.reducer -) +export const administrationTablePersistedReducer = persistReducer(persistConfig, AdministrationTableSlice.reducer) diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/types.ts b/frontend/src/features/Administration/components/AdministrationTable/types.ts similarity index 100% rename from frontend/src/features/Administrations/BackOfficeAdministrationList/types.ts rename to frontend/src/features/Administration/components/AdministrationTable/types.ts diff --git a/frontend/src/features/Administrations/BackOfficeAdministrationList/utils.tsx b/frontend/src/features/Administration/components/AdministrationTable/utils.tsx similarity index 75% rename from frontend/src/features/Administrations/BackOfficeAdministrationList/utils.tsx rename to frontend/src/features/Administration/components/AdministrationTable/utils.tsx index fac67768e..09c1b43d6 100644 --- a/frontend/src/features/Administrations/BackOfficeAdministrationList/utils.tsx +++ b/frontend/src/features/Administration/components/AdministrationTable/utils.tsx @@ -1,22 +1,29 @@ import { CustomSearch, IconButton, type Filter, Icon, Size } from '@mtes-mct/monitor-ui' import { ADMINISTRATION_TABLE_COLUMNS } from './constants' -import { openConfirmationModal } from '../../../domain/shared_slices/BackOffice' -import { BackOfficeConfirmationModalActionType } from '../../../domain/use_cases/backOffice/types' +import { backOfficeActions } from '../../../BackOffice/slice' +import { BackOfficeConfirmationModalActionType } from '../../../BackOffice/types' import type { FiltersState } from './types' -import type { Administration } from '../../../domain/entities/administration' -import type { AppDispatch } from '../../../store' +import type { Administration } from '../../../../domain/entities/administration' +import type { AppDispatch } from '../../../../store' import type { CellContext, ColumnDef } from '@tanstack/react-table' function archiveAdministration(info: CellContext, dispatch: AppDispatch) { const administration = info.getValue() dispatch( - openConfirmationModal({ - actionId: administration.id, + backOfficeActions.openConfirmationModal({ actionType: BackOfficeConfirmationModalActionType.ARCHIVE_ADMINISTRATION, - message: `Confirmez-vous l'archivage de l'administration "${administration.name}" ? Elle n'apparaîtra plus dans MonitorEnv, elle ne sera plus utilisée que pour les statistiques.` + entityId: administration.id, + modalProps: { + confirmationButtonLabel: 'Archiver', + message: [ + `Êtes-vous sûr de vouloir archiver l'administration "${administration.name}" ?`, + `Elle n'apparaîtra plus dans MonitorEnv, elle ne sera plus utilisée que pour les statistiques.` + ].join(' '), + title: `Archivage de l'administration` + } }) ) } @@ -25,10 +32,14 @@ function deleteAdministration(info: CellContext() dispatch( - openConfirmationModal({ - actionId: administration.id, + backOfficeActions.openConfirmationModal({ actionType: BackOfficeConfirmationModalActionType.DELETE_ADMINISTRATION, - message: `Confirmez-vous la suppression de l'administration "${administration.name}" ?` + entityId: administration.id, + modalProps: { + confirmationButtonLabel: 'Supprimer', + message: `Êtes-vous sûr de vouloir supprimer l'administration "${administration.name}" ?`, + title: `Suppression de l'administration` + } }) ) } diff --git a/frontend/src/domain/use_cases/administration/archiveAdministration.ts b/frontend/src/features/Administration/useCases/archiveAdministration.ts similarity index 50% rename from frontend/src/domain/use_cases/administration/archiveAdministration.ts rename to frontend/src/features/Administration/useCases/archiveAdministration.ts index 4ad571a0f..f5ca63047 100644 --- a/frontend/src/domain/use_cases/administration/archiveAdministration.ts +++ b/frontend/src/features/Administration/useCases/archiveAdministration.ts @@ -1,30 +1,43 @@ -import { logSoftError } from '@mtes-mct/monitor-ui' +import { THEME, logSoftError } from '@mtes-mct/monitor-ui' import { administrationsAPI } from '../../../api/administrationsAPI' +import { FrontendError } from '../../../libs/FrontendError' import { isUserError } from '../../../libs/UserError' -import { backOfficeActions } from '../../shared_slices/BackOffice' +import { backOfficeActions } from '../../BackOffice/slice' import type { AppThunk } from '../../../store' export const archiveAdministration = (): AppThunk> => async (dispatch, getState) => { - const administrationId = getState().backOffice.confirmationModalActionId + const { confirmationModal } = getState().backOffice + if (!confirmationModal) { + throw new FrontendError('`confirmationModal` is undefined.') + } try { const { error } = await dispatch( - administrationsAPI.endpoints.archiveAdministration.initiate(administrationId) as any + administrationsAPI.endpoints.archiveAdministration.initiate(confirmationModal.entityId) as any ) if (error) { throw error } } catch (err) { if (isUserError(err)) { - dispatch(backOfficeActions.openDialog({ message: err.userMessage })) + dispatch( + backOfficeActions.openDialog({ + dialogProps: { + color: THEME.color.maximumRed, + message: err.userMessage, + title: `Archivage impossible`, + titleBackgroundColor: THEME.color.maximumRed + } + }) + ) return } logSoftError({ - message: `An error happened while archiving an administration (ID=${administrationId}").`, + message: `An error happened while archiving an administration (ID=${confirmationModal.entityId}").`, originalError: err, userMessage: "Une erreur est survenue pendant l'archivage de l'administration." }) diff --git a/frontend/src/domain/use_cases/administration/deleteAdministration.ts b/frontend/src/features/Administration/useCases/deleteAdministration.ts similarity index 50% rename from frontend/src/domain/use_cases/administration/deleteAdministration.ts rename to frontend/src/features/Administration/useCases/deleteAdministration.ts index 9198c015b..701f2846c 100644 --- a/frontend/src/domain/use_cases/administration/deleteAdministration.ts +++ b/frontend/src/features/Administration/useCases/deleteAdministration.ts @@ -1,30 +1,43 @@ -import { logSoftError } from '@mtes-mct/monitor-ui' +import { THEME, logSoftError } from '@mtes-mct/monitor-ui' import { administrationsAPI } from '../../../api/administrationsAPI' +import { FrontendError } from '../../../libs/FrontendError' import { isUserError } from '../../../libs/UserError' -import { backOfficeActions } from '../../shared_slices/BackOffice' +import { backOfficeActions } from '../../BackOffice/slice' import type { AppThunk } from '../../../store' export const deleteAdministration = (): AppThunk> => async (dispatch, getState) => { - const administrationId = getState().backOffice.confirmationModalActionId + const { confirmationModal } = getState().backOffice + if (!confirmationModal) { + throw new FrontendError('`confirmationModal` is undefined.') + } try { const { error } = await dispatch( - administrationsAPI.endpoints.deleteAdministration.initiate(administrationId) as any + administrationsAPI.endpoints.deleteAdministration.initiate(confirmationModal.entityId) as any ) if (error) { throw error } } catch (err) { if (isUserError(err)) { - dispatch(backOfficeActions.openDialog({ message: err.userMessage })) + dispatch( + backOfficeActions.openDialog({ + dialogProps: { + color: THEME.color.maximumRed, + message: err.userMessage, + title: `Suppression impossible`, + titleBackgroundColor: THEME.color.maximumRed + } + }) + ) return } logSoftError({ - message: `An error happened while deleting an administration (ID=${administrationId}").`, + message: `An error happened while deleting an administration (ID=${confirmationModal.entityId}").`, originalError: err, userMessage: "Une erreur est survenue pendant la suppression de l'administration." }) diff --git a/frontend/src/features/BackOffice/components/BackOfficeConfirmationModal.tsx b/frontend/src/features/BackOffice/components/BackOfficeConfirmationModal.tsx new file mode 100644 index 000000000..c96365363 --- /dev/null +++ b/frontend/src/features/BackOffice/components/BackOfficeConfirmationModal.tsx @@ -0,0 +1,27 @@ +import { useCallback } from 'react' + +import { ConfirmationModal } from '../../../components/ConfirmationModal' +import { useAppDispatch } from '../../../hooks/useAppDispatch' +import { useAppSelector } from '../../../hooks/useAppSelector' +import { FrontendError } from '../../../libs/FrontendError' +import { backOfficeActions } from '../slice' +import { handleModalConfirmation } from '../useCases/handleModalConfirmation' + +export function BackOfficeConfirmationModal() { + const dispatch = useAppDispatch() + const { confirmationModal } = useAppSelector(store => store.backOffice) + if (!confirmationModal) { + throw new FrontendError('`confirmationModal` is undefined.') + } + + const close = useCallback(() => { + dispatch(backOfficeActions.closeConfirmationModal()) + }, [dispatch]) + + const confirm = useCallback(() => { + dispatch(handleModalConfirmation()) + }, [dispatch]) + + // eslint-disable-next-line react/jsx-props-no-spreading + return +} diff --git a/frontend/src/features/BackOffice/components/BackOfficeDialog.tsx b/frontend/src/features/BackOffice/components/BackOfficeDialog.tsx new file mode 100644 index 000000000..851f03fb0 --- /dev/null +++ b/frontend/src/features/BackOffice/components/BackOfficeDialog.tsx @@ -0,0 +1,22 @@ +import { useCallback } from 'react' + +import { Dialog } from '../../../components/Dialog' +import { useAppDispatch } from '../../../hooks/useAppDispatch' +import { useAppSelector } from '../../../hooks/useAppSelector' +import { FrontendError } from '../../../libs/FrontendError' +import { backOfficeActions } from '../slice' + +export function BackOfficeDialog() { + const dispatch = useAppDispatch() + const { dialog } = useAppSelector(store => store.backOffice) + if (!dialog) { + throw new FrontendError('`dialog` is undefined.') + } + + const close = useCallback(() => { + dispatch(backOfficeActions.closeDialog()) + }, [dispatch]) + + // eslint-disable-next-line react/jsx-props-no-spreading + return +} diff --git a/frontend/src/features/BackOffice/components/TabBar/Tab.tsx b/frontend/src/features/BackOffice/components/BackOfficeTabBar/Tab.tsx similarity index 100% rename from frontend/src/features/BackOffice/components/TabBar/Tab.tsx rename to frontend/src/features/BackOffice/components/BackOfficeTabBar/Tab.tsx diff --git a/frontend/src/features/BackOffice/components/TabBar/index.tsx b/frontend/src/features/BackOffice/components/BackOfficeTabBar/index.tsx similarity index 59% rename from frontend/src/features/BackOffice/components/TabBar/index.tsx rename to frontend/src/features/BackOffice/components/BackOfficeTabBar/index.tsx index 5acbbf14e..0661cc81f 100644 --- a/frontend/src/features/BackOffice/components/TabBar/index.tsx +++ b/frontend/src/features/BackOffice/components/BackOfficeTabBar/index.tsx @@ -2,7 +2,7 @@ import styled from 'styled-components' import { Tab } from './Tab' -const BareTabBar = styled.div` +const BareBackOfficeTabBar = styled.div` display: flex; width: 100%; @@ -11,6 +11,6 @@ const BareTabBar = styled.div` } ` -export const TabBar = Object.assign(BareTabBar, { +export const BackOfficeTabBar = Object.assign(BareBackOfficeTabBar, { Tab }) diff --git a/frontend/src/features/BackOffice/components/ConfirmationModal.tsx b/frontend/src/features/BackOffice/components/ConfirmationModal.tsx deleted file mode 100644 index 6d501def7..000000000 --- a/frontend/src/features/BackOffice/components/ConfirmationModal.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Accent, Button, Dialog } from '@mtes-mct/monitor-ui' -import { useCallback } from 'react' - -import { backOfficeActions } from '../../../domain/shared_slices/BackOffice' -import { handleModalConfirmation } from '../../../domain/use_cases/backOffice/handleModalConfirmation' -import { useAppDispatch } from '../../../hooks/useAppDispatch' -import { useAppSelector } from '../../../hooks/useAppSelector' - -export function ConfirmationModal() { - const dispatch = useAppDispatch() - const backOffice = useAppSelector(store => store.backOffice) - - const cancel = useCallback(() => { - dispatch(backOfficeActions.closeConfirmationModal()) - }, [dispatch]) - - const confirm = useCallback(() => { - dispatch(handleModalConfirmation()) - }, [dispatch]) - - return ( - - -

{backOffice.confirmationModalMessage}

-
- - - - -
- ) -} diff --git a/frontend/src/features/BackOffice/components/Dialog.tsx b/frontend/src/features/BackOffice/components/Dialog.tsx deleted file mode 100644 index 6a6eb32f1..000000000 --- a/frontend/src/features/BackOffice/components/Dialog.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Button, Dialog as MonitorUiDialog } from '@mtes-mct/monitor-ui' -import { useCallback } from 'react' - -import { backOfficeActions } from '../../../domain/shared_slices/BackOffice' -import { useAppDispatch } from '../../../hooks/useAppDispatch' -import { useAppSelector } from '../../../hooks/useAppSelector' - -export function Dialog() { - const dispatch = useAppDispatch() - const backOffice = useAppSelector(store => store.backOffice) - - const close = useCallback(() => { - dispatch(backOfficeActions.closeDialog()) - }, [dispatch]) - - return ( - - -

{backOffice.dialogMessage}

-
- - - -
- ) -} diff --git a/frontend/src/features/BackOffice/slice.ts b/frontend/src/features/BackOffice/slice.ts new file mode 100644 index 000000000..941f9185a --- /dev/null +++ b/frontend/src/features/BackOffice/slice.ts @@ -0,0 +1,50 @@ +import { createSlice, type PayloadAction } from '@reduxjs/toolkit' + +import type { ConfirmationModalState, DialogState } from './types' + +interface BackOfficeState { + /** Shared Confirmation Modal */ + confirmationModal: ConfirmationModalState | undefined + + /** Shared Dialog */ + dialog: DialogState | undefined + + isConfirmationModalOpen: boolean + isDialogOpen: boolean +} +const INITIAL_STATE: BackOfficeState = { + confirmationModal: undefined, + dialog: undefined, + + isConfirmationModalOpen: false, + isDialogOpen: false +} + +const backOfficeSlice = createSlice({ + initialState: INITIAL_STATE, + name: 'backOffice', + reducers: { + closeConfirmationModal(state) { + state.confirmationModal = undefined + state.isConfirmationModalOpen = false + }, + + closeDialog(state) { + state.dialog = undefined + state.isDialogOpen = false + }, + + openConfirmationModal(state, action: PayloadAction) { + state.confirmationModal = action.payload + state.isConfirmationModalOpen = true + }, + + openDialog(state, action: PayloadAction) { + state.dialog = action.payload + state.isDialogOpen = true + } + } +}) + +export const backOfficeActions = backOfficeSlice.actions +export const backOfficeReducer = backOfficeSlice.reducer diff --git a/frontend/src/features/BackOffice/types.ts b/frontend/src/features/BackOffice/types.ts new file mode 100644 index 000000000..27e62bf87 --- /dev/null +++ b/frontend/src/features/BackOffice/types.ts @@ -0,0 +1,20 @@ +import type { ConfirmationModalProps } from '../../components/ConfirmationModal' +import type { DialogProps } from '../../components/Dialog' + +export type ConfirmationModalState = { + actionType: BackOfficeConfirmationModalActionType + /** ID of the targeted entity. */ + entityId: number + modalProps: Omit +} + +export type DialogState = { + dialogProps: Omit +} + +export enum BackOfficeConfirmationModalActionType { + 'ARCHIVE_ADMINISTRATION' = 'ARCHIVE_ADMINISTRATION', + 'ARCHIVE_CONTROL_UNIT' = 'ARCHIVE_CONTROL_UNIT', + 'DELETE_ADMINISTRATION' = 'DELETE_ADMINISTRATION', + 'DELETE_CONTROL_UNIT' = 'DELETE_CONTROL_UNIT' +} diff --git a/frontend/src/features/BackOffice/useCases/handleModalConfirmation.ts b/frontend/src/features/BackOffice/useCases/handleModalConfirmation.ts new file mode 100644 index 000000000..bc5df13d3 --- /dev/null +++ b/frontend/src/features/BackOffice/useCases/handleModalConfirmation.ts @@ -0,0 +1,39 @@ +import { FrontendError } from '../../../libs/FrontendError' +import { archiveAdministration } from '../../Administration/useCases/archiveAdministration' +import { deleteAdministration } from '../../Administration/useCases/deleteAdministration' +import { archiveControlUnit } from '../../ControlUnit/usesCases/archiveControlUnit' +import { deleteControlUnit } from '../../ControlUnit/usesCases/deleteControlUnit' +import { backOfficeActions } from '../slice' +import { BackOfficeConfirmationModalActionType } from '../types' + +import type { AppThunk } from '../../../store' + +export const handleModalConfirmation = (): AppThunk => async (dispatch, getState) => { + const { confirmationModal } = getState().backOffice + if (!confirmationModal) { + throw new FrontendError('`confirmationModal` is undefined.') + } + + switch (confirmationModal.actionType) { + case BackOfficeConfirmationModalActionType.ARCHIVE_ADMINISTRATION: + await dispatch(archiveAdministration()) + break + + case BackOfficeConfirmationModalActionType.ARCHIVE_CONTROL_UNIT: + await dispatch(archiveControlUnit()) + break + + case BackOfficeConfirmationModalActionType.DELETE_ADMINISTRATION: + await dispatch(deleteAdministration()) + break + + case BackOfficeConfirmationModalActionType.DELETE_CONTROL_UNIT: + await dispatch(deleteControlUnit()) + break + + default: + break + } + + dispatch(backOfficeActions.closeConfirmationModal()) +} diff --git a/frontend/src/features/Bases/BackOfficeBaseForm/constants.ts b/frontend/src/features/Base/components/BaseForm/constants.ts similarity index 100% rename from frontend/src/features/Bases/BackOfficeBaseForm/constants.ts rename to frontend/src/features/Base/components/BaseForm/constants.ts diff --git a/frontend/src/features/Bases/BackOfficeBaseForm/index.tsx b/frontend/src/features/Base/components/BaseForm/index.tsx similarity index 88% rename from frontend/src/features/Bases/BackOfficeBaseForm/index.tsx rename to frontend/src/features/Base/components/BaseForm/index.tsx index 7e76e8c59..02f7586dc 100644 --- a/frontend/src/features/Bases/BackOfficeBaseForm/index.tsx +++ b/frontend/src/features/Base/components/BaseForm/index.tsx @@ -7,16 +7,16 @@ import styled from 'styled-components' import { INITIAL_BASE_FORM_VALUES, BASE_FORM_SCHEMA } from './constants' import { isBase } from './utils' -import { basesAPI, useGetBaseQuery } from '../../../api/basesAPI' -import { useAppDispatch } from '../../../hooks/useAppDispatch' -import { FrontendError } from '../../../libs/FrontendError' -import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../BackOfficeMenu/constants' -import { CONTROL_UNIT_RESOURCE_TABLE_COLUMNS } from '../../ControlUnits/BackOfficeControlUnitForm/constants' +import { basesAPI, useGetBaseQuery } from '../../../../api/basesAPI' +import { useAppDispatch } from '../../../../hooks/useAppDispatch' +import { FrontendError } from '../../../../libs/FrontendError' +import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../../BackOfficeMenu/constants' +import { CONTROL_UNIT_RESOURCE_TABLE_COLUMNS } from '../../../ControlUnit/components/ControlUnitForm/constants' import type { BaseFormValues } from './types' -import type { Base } from '../../../domain/entities/base' +import type { Base } from '../../../../domain/entities/base' -export function BackOfficeBaseForm() { +export function BaseForm() { const { baseId } = useParams() if (!baseId) { throw new FrontendError('`baseId` is undefined.') diff --git a/frontend/src/features/Bases/BackOfficeBaseForm/types.ts b/frontend/src/features/Base/components/BaseForm/types.ts similarity index 68% rename from frontend/src/features/Bases/BackOfficeBaseForm/types.ts rename to frontend/src/features/Base/components/BaseForm/types.ts index 75c3086c3..8b8ebb239 100644 --- a/frontend/src/features/Bases/BackOfficeBaseForm/types.ts +++ b/frontend/src/features/Base/components/BaseForm/types.ts @@ -1,4 +1,4 @@ -import type { Base } from '../../../domain/entities/base' +import type { Base } from '../../../../domain/entities/base' import type { UndefineExceptArrays } from '@mtes-mct/monitor-ui' export type BaseFormValues = UndefineExceptArrays diff --git a/frontend/src/features/Bases/BackOfficeBaseForm/utils.ts b/frontend/src/features/Base/components/BaseForm/utils.ts similarity index 64% rename from frontend/src/features/Bases/BackOfficeBaseForm/utils.ts rename to frontend/src/features/Base/components/BaseForm/utils.ts index 4367f4fa7..2c9314b2c 100644 --- a/frontend/src/features/Bases/BackOfficeBaseForm/utils.ts +++ b/frontend/src/features/Base/components/BaseForm/utils.ts @@ -1,4 +1,4 @@ -import type { Base } from '../../../domain/entities/base' +import type { Base } from '../../../../domain/entities/base' export function isBase(baseData: Base.BaseData): baseData is Base.Base { return baseData.id !== undefined diff --git a/frontend/src/features/Bases/BackOfficeBaseList/FilterBar.tsx b/frontend/src/features/Base/components/BaseTable/FilterBar.tsx similarity index 73% rename from frontend/src/features/Bases/BackOfficeBaseList/FilterBar.tsx rename to frontend/src/features/Base/components/BaseTable/FilterBar.tsx index e5cbe189e..cc6679cd2 100644 --- a/frontend/src/features/Bases/BackOfficeBaseList/FilterBar.tsx +++ b/frontend/src/features/Base/components/BaseTable/FilterBar.tsx @@ -2,9 +2,9 @@ import { Icon, TextInput } from '@mtes-mct/monitor-ui' import { useCallback } from 'react' import styled from 'styled-components' -import { backOfficeBaseListActions } from './slice' -import { useAppDispatch } from '../../../hooks/useAppDispatch' -import { useAppSelector } from '../../../hooks/useAppSelector' +import { baseTableActions } from './slice' +import { useAppDispatch } from '../../../../hooks/useAppDispatch' +import { useAppSelector } from '../../../../hooks/useAppSelector' export function FilterBar() { const dispatch = useAppDispatch() @@ -12,7 +12,7 @@ export function FilterBar() { const updateQuery = useCallback( (nextValue: string | undefined) => { - dispatch(backOfficeBaseListActions.setFilter({ key: 'query', value: nextValue })) + dispatch(baseTableActions.setFilter({ key: 'query', value: nextValue })) }, [dispatch] ) diff --git a/frontend/src/features/Bases/BackOfficeBaseList/constants.tsx b/frontend/src/features/Base/components/BaseTable/constants.tsx similarity index 86% rename from frontend/src/features/Bases/BackOfficeBaseList/constants.tsx rename to frontend/src/features/Base/components/BaseTable/constants.tsx index d58a1b3f5..ae7cc862f 100644 --- a/frontend/src/features/Bases/BackOfficeBaseList/constants.tsx +++ b/frontend/src/features/Base/components/BaseTable/constants.tsx @@ -1,9 +1,9 @@ import { Icon, Size } from '@mtes-mct/monitor-ui' -import { NavIconButton } from '../../../ui/NavIconButton' -import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../BackOfficeMenu/constants' +import { NavIconButton } from '../../../../ui/NavIconButton' +import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../../BackOfficeMenu/constants' -import type { Base } from '../../../domain/entities/base' +import type { Base } from '../../../../domain/entities/base' import type { ColumnDef } from '@tanstack/react-table' export const BASE_TABLE_COLUMNS: Array> = [ diff --git a/frontend/src/features/Bases/BackOfficeBaseList/index.tsx b/frontend/src/features/Base/components/BaseTable/index.tsx similarity index 84% rename from frontend/src/features/Bases/BackOfficeBaseList/index.tsx rename to frontend/src/features/Base/components/BaseTable/index.tsx index 2c23943f0..c8420fed1 100644 --- a/frontend/src/features/Bases/BackOfficeBaseList/index.tsx +++ b/frontend/src/features/Base/components/BaseTable/index.tsx @@ -5,12 +5,12 @@ import styled from 'styled-components' import { BASE_TABLE_COLUMNS } from './constants' import { FilterBar } from './FilterBar' import { getFilters } from './utils' -import { useGetBasesQuery } from '../../../api/basesAPI' -import { useAppSelector } from '../../../hooks/useAppSelector' -import { NavButton } from '../../../ui/NavButton' -import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../BackOfficeMenu/constants' +import { useGetBasesQuery } from '../../../../api/basesAPI' +import { useAppSelector } from '../../../../hooks/useAppSelector' +import { NavButton } from '../../../../ui/NavButton' +import { BACK_OFFICE_MENU_PATH, BackOfficeMenuKey } from '../../../BackOfficeMenu/constants' -export function BackOfficeBaseList() { +export function BaseTable() { const backOfficeBaseList = useAppSelector(store => store.backOfficeBaseList) const { data: bases } = useGetBasesQuery() diff --git a/frontend/src/features/Bases/BackOfficeBaseList/slice.ts b/frontend/src/features/Base/components/BaseTable/slice.ts similarity index 62% rename from frontend/src/features/Bases/BackOfficeBaseList/slice.ts rename to frontend/src/features/Base/components/BaseTable/slice.ts index 5bb7d556f..a858b2535 100644 --- a/frontend/src/features/Bases/BackOfficeBaseList/slice.ts +++ b/frontend/src/features/Base/components/BaseTable/slice.ts @@ -5,22 +5,22 @@ import storage from 'redux-persist/lib/storage' import type { FiltersState } from './types' -export type BackOfficeBaseListState = { +interface BaseTableState { filtersState: FiltersState } -const INITIAL_STATE: BackOfficeBaseListState = { +const INITIAL_STATE: BaseTableState = { filtersState: {} } const persistConfig = { - key: 'backOfficeBaseList', + key: 'baseTable', storage } -const backOfficeBaseList = createSlice({ +const baseTableSlice = createSlice({ initialState: INITIAL_STATE, - name: 'backOfficeBaseList', + name: 'baseTable', reducers: { setFilter( state, @@ -34,6 +34,6 @@ const backOfficeBaseList = createSlice({ } }) -export const backOfficeBaseListActions = backOfficeBaseList.actions +export const baseTableActions = baseTableSlice.actions -export const backOfficeBaseListPersistedReducer = persistReducer(persistConfig, backOfficeBaseList.reducer) +export const baseTablePersistedReducer = persistReducer(persistConfig, baseTableSlice.reducer) diff --git a/frontend/src/features/Bases/BackOfficeBaseList/types.ts b/frontend/src/features/Base/components/BaseTable/types.ts similarity index 100% rename from frontend/src/features/Bases/BackOfficeBaseList/types.ts rename to frontend/src/features/Base/components/BaseTable/types.ts diff --git a/frontend/src/features/Bases/BackOfficeBaseList/utils.ts b/frontend/src/features/Base/components/BaseTable/utils.ts similarity index 90% rename from frontend/src/features/Bases/BackOfficeBaseList/utils.ts rename to frontend/src/features/Base/components/BaseTable/utils.ts index 0f2dac9d1..43ff6533d 100644 --- a/frontend/src/features/Bases/BackOfficeBaseList/utils.ts +++ b/frontend/src/features/Base/components/BaseTable/utils.ts @@ -1,7 +1,7 @@ import { CustomSearch, type Filter } from '@mtes-mct/monitor-ui' import type { FiltersState } from './types' -import type { Base } from '../../../domain/entities/base' +import type { Base } from '../../../../domain/entities/base' export function getFilters(data: Base.Base[], filtersState: FiltersState): Filter[] { const customSearch = new CustomSearch(data, ['name'], { diff --git a/frontend/src/features/ControlUnit/components/ControlUnitDialog/AreaNote.tsx b/frontend/src/features/ControlUnit/components/ControlUnitDialog/AreaNote.tsx new file mode 100644 index 000000000..41bdab247 --- /dev/null +++ b/frontend/src/features/ControlUnit/components/ControlUnitDialog/AreaNote.tsx @@ -0,0 +1,35 @@ +import styled from 'styled-components' + +import { Section } from './shared/Section' +import { TextareaForm } from './shared/TextareaForm' + +import type { ControlUnit } from '../../../../domain/entities/controlUnit' + +type AreaNoteProps = { + controlUnit: ControlUnit.ControlUnit + onSubmit: (nextControlUnit: ControlUnit.ControlUnit) => any +} +export function AreaNote({ controlUnit, onSubmit }: AreaNoteProps) { + return ( +
+ Secteur d’intervention + + + +
+ ) +} + +const StyledSectionBody = styled(Section.Body)` + padding: 24px 32px; + + > div:not(:first-child) { + margin-top: 8px; + } +` diff --git a/frontend/src/features/ControlUnit/components/ControlUnitDialog/ControlUnitContactList/Form.tsx b/frontend/src/features/ControlUnit/components/ControlUnitDialog/ControlUnitContactList/Form.tsx new file mode 100644 index 000000000..a5f7cd087 --- /dev/null +++ b/frontend/src/features/ControlUnit/components/ControlUnitDialog/ControlUnitContactList/Form.tsx @@ -0,0 +1,114 @@ +import { Accent, Button, FormikTextInput, Icon, IconButton, THEME, useKey } from '@mtes-mct/monitor-ui' +import { Formik } from 'formik' +import { useCallback } from 'react' +import styled from 'styled-components' + +import { CONTROL_UNIT_CONTACT_FORM_SCHEMA } from './constants' +import { FormikNameSelect } from './FormikNameSelect' +import { useAppDispatch } from '../../../../../hooks/useAppDispatch' +import { mainWindowActions } from '../../../../MainWindow/slice' +import { MainWindowConfirmationModalActionType } from '../../../../MainWindow/types' + +import type { ControlUnitContactFormValues } from './types' + +export type FormProps = { + initialValues: ControlUnitContactFormValues + isNew: boolean + onCancel: () => void + onSubmit: (controlUnitContactFormValues: ControlUnitContactFormValues) => void +} +export function Form({ initialValues, isNew, onCancel, onSubmit }: FormProps) { + const dispatch = useAppDispatch() + const key = useKey([initialValues]) + + const askForDeletionConfirmation = useCallback(async () => { + if (!initialValues.id) { + return + } + + dispatch( + mainWindowActions.openConfirmationModal({ + actionType: MainWindowConfirmationModalActionType.DELETE_CONTROL_UNIT_CONTACT, + entityId: initialValues.id, + modalProps: { + color: THEME.color.maximumRed, + confirmationButtonLabel: 'Supprimer', + iconName: 'Delete', + message: `Êtes-vous sûr de vouloir supprimer ce contact ?`, + title: `Suppression du contact` + } + }) + ) + }, [initialValues.id, dispatch]) + + return ( + + {({ handleSubmit }) => ( + <> + {isNew ? 'Ajouter un contact' : 'Éditer un contact'} + + + + + + +
+ + +
+ {!isNew && ( + + )} +
+
+ + )} +
+ ) +} + +const Title = styled.p` + background-color: ${p => p.theme.color.gainsboro}; + margin: 16px 0 2px; + padding: 8px 16px; + /* TODO This should be the default height everywhere to have a consistent and exact height of 18px. */ + /* Monitor UI provides that value: https://github.com/MTES-MCT/monitor-ui/blob/main/src/GlobalStyle.ts#L76. */ + line-height: 1.3846; +` + +const StyledForm = styled.form` + background-color: ${p => p.theme.color.gainsboro}; + padding: 16px; + + > div:not(:first-child) { + margin-top: 16px; + } +` + +const ActionBar = styled.div` + display: flex; + justify-content: space-between; + + > div:first-child { + > .Element-Button:last-child { + margin-left: 8px; + } + } +` diff --git a/frontend/src/features/ControlUnit/components/ControlUnitDialog/ControlUnitContactList/FormikNameSelect.tsx b/frontend/src/features/ControlUnit/components/ControlUnitDialog/ControlUnitContactList/FormikNameSelect.tsx new file mode 100644 index 000000000..fc710171e --- /dev/null +++ b/frontend/src/features/ControlUnit/components/ControlUnitDialog/ControlUnitContactList/FormikNameSelect.tsx @@ -0,0 +1,78 @@ +import { Accent, FormikTextInput, Icon, IconButton, Select } from '@mtes-mct/monitor-ui' +import { useField } from 'formik' +import { useCallback, useEffect, useState } from 'react' +import styled from 'styled-components' + +import { CONTROL_UNIT_CONTACT_NAMES, CONTROL_UNIT_CONTACT_NAMES_AS_OPTIONS } from './constants' +import { ControlUnit } from '../../../../../domain/entities/controlUnit' + +export function FormikNameSelect() { + const [field, meta, helpers] = useField('name') + + const [isCustomName, setIsCustomName] = useState( + !!field.value && !ControlUnit.ControlUnitContactName[field.value] + ) + + const cancelCustomName = useCallback( + () => { + setIsCustomName(false) + helpers.setValue(undefined) + }, + + // We don't want to trigger infinite re-rendering since `helpers.setValue` changes after each rendering + // eslint-disable-next-line react-hooks/exhaustive-deps + [] + ) + + const handleChange = useCallback( + (nextName: string | undefined) => { + if (nextName === 'SWITCH_TO_CUSTOM_NAME') { + setIsCustomName(true) + + return + } + + helpers.setValue(nextName) + }, + + // We don't want to trigger infinite re-rendering since `helpers.setValue` changes after each rendering + // eslint-disable-next-line react-hooks/exhaustive-deps + [] + ) + + useEffect(() => { + if (!isCustomName && field.value && CONTROL_UNIT_CONTACT_NAMES.includes(field.value)) { + setIsCustomName(false) + } + }, [field.value, isCustomName]) + + return isCustomName ? ( + + + + + ) : ( +