Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.dev.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ FRONTEND_MISSION_FORM_AUTO_SAVE_ENABLED=true
FRONTEND_REPORTING_FORM_AUTO_SAVE_ENABLED=true
FRONTEND_REPORTING_FORM_AUTO_UPDATE=true
FRONTEND_VESSELS_ENABLED=true
FRONTEND_REGULATORY_AREAS_BO_ENABLED=true

################################################################################
# METABASE
Expand Down
1 change: 1 addition & 0 deletions .env.infra.example
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ FRONTEND_MISSION_FORM_AUTO_SAVE_ENABLED=
FRONTEND_REPORTING_FORM_AUTO_SAVE_ENABLED=
FRONTEND_REPORTING_FORM_AUTO_UPDATE=
FRONTEND_VESSELS_ENABLED=
FRONTEND_REGULATORY_AREAS_BO_ENABLED=

################################################################################
# METABASE
Expand Down
1 change: 1 addition & 0 deletions .env.test.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ FRONTEND_MISSION_FORM_AUTO_SAVE_ENABLED=true
FRONTEND_REPORTING_FORM_AUTO_SAVE_ENABLED=true
FRONTEND_REPORTING_FORM_AUTO_UPDATE=true
FRONTEND_VESSELS_ENABLED=true
FRONTEND_REGULATORY_AREAS_BO_ENABLED=true

################################################################################
# METABASE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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
import fr.gouv.cacem.monitorenv.domain.repositories.IRegulatoryAreaRepository
import org.slf4j.LoggerFactory

@UseCase
class GetAllRegulatoryAreas(
private val regulatoryAreaRepository: IRegulatoryAreaRepository,
) {
private val logger = LoggerFactory.getLogger(GetAllRegulatoryAreas::class.java)

fun execute(): List<RegulatoryAreaEntity> {
logger.info("Attempt to GET all regulatory areas")
val regulatoryAreas = regulatoryAreaRepository.findAll()
logger.info("Found ${regulatoryAreas.size} regulatory areas")

return regulatoryAreas
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package fr.gouv.cacem.monitorenv.infrastructure.database.model

import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import fr.gouv.cacem.monitorenv.domain.entities.regulatoryArea.RegulatoryAreaEntity
import fr.gouv.cacem.monitorenv.infrastructure.database.model.TagRegulatoryAreaModel.Companion.toTagEntities
import fr.gouv.cacem.monitorenv.infrastructure.database.model.ThemeRegulatoryAreaModel.Companion.toThemeEntities
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.FetchType
import jakarta.persistence.Id
import jakarta.persistence.OneToMany
import jakarta.persistence.Table
import org.locationtech.jts.geom.MultiPolygon
import org.n52.jackson.datatype.jts.GeometryDeserializer
import org.n52.jackson.datatype.jts.GeometrySerializer

@Entity
@Table(name = "regulations_cacem")
data class RegulatoryAreaModel(
@Id @Column(name = "id") val id: Int,
@Column(name = "plan") val plan: String?,
@Column(name = "date") val date: String?,
@Column(name = "date_fin") val dateFin: String?,
@Column(name = "duree_validite") val dureeValidite: String?,
@Column(name = "editeur") val editeur: String?,
@Column(name = "edition") val edition: String?,
@Column(name = "facade") val facade: String?,
@JsonSerialize(using = GeometrySerializer::class)
@JsonDeserialize(contentUsing = GeometryDeserializer::class)
@Column(name = "geom")
val geom: MultiPolygon?,
@Column(name = "layer_name") val layerName: String?,
@Column(name = "observation") val observation: String?,
@Column(name = "poly_name") val polyName: String?,
@Column(name = "ref_reg") val refReg: String?,
@Column(name = "source") val source: String?,
@Column(name = "temporalite") val temporalite: String?,
@OneToMany(
mappedBy = "regulatoryArea",
fetch = FetchType.LAZY,
)
var tags: List<TagRegulatoryAreaModel>,
@OneToMany(
mappedBy = "regulatoryArea",
fetch = FetchType.LAZY,
)
var themes: List<ThemeRegulatoryAreaModel>,
@Column(name = "resume") val resume: String?,
@Column(name = "type") val type: String?,
@Column(name = "url") val url: String?,
) {
fun toRegulatoryArea() =
RegulatoryAreaEntity(
id = id,
plan = plan,
date = date,
dateFin = dateFin,
dureeValidite = dureeValidite,
editeur = editeur,
edition = edition,
facade = facade,
geom = geom,
layerName = layerName,
polyName = polyName,
observation = observation,
refReg = refReg,
resume = resume,
source = source,
temporalite = temporalite,
tags = toTagEntities(tags),
themes = toThemeEntities(themes),
type = type,
url = url,
)

override fun toString(): String =
"RegulatoryAreaModel(id=$id, plan=$plan, date=$date, dateFin=$dateFin, dureeValidite=$dureeValidite, editeur=$editeur, edition=$edition, facade=$facade, geom=$geom, layerName=$layerName, observation=$observation, polyName=$polyName, refReg=$refReg, resume=$resume, source=$source, temporalite=$temporalite, type=$type, url=$url)"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

CREATE TABLE public.regulatory_areas (
id serial,
geom public.geometry(MultiPolygon,4326),
url character varying,
layer_name character varying,
facade character varying,
ref_reg character varying,
creation character varying,
edition_bo character varying,
edition_cacem character varying,
editeur character varying,
source character varying,
observation character varying,
thematique character varying,
date character varying,
duree_validite character varying,
date_fin character varying,
temporalite character varying,
type character varying,
resume text,
poly_name text,
plan text,
row_hash text
);

Large diffs are not rendered by default.

27 changes: 14 additions & 13 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
app:
profiles: [ production, test ]
profiles: [production, test]
image: $MONITORENV_IMAGE:$MONITORENV_VERSION
container_name: monitorenv_backend
user: "monitorenv:${MONITORENV_LOGS_AND_BACKUPS_GID}"
Expand All @@ -26,6 +26,7 @@ services:
- FRONTEND_SHOM_KEY=${FRONTEND_SHOM_KEY}
- FRONTEND_MISSION_FORM_AUTO_UPDATE=${FRONTEND_MISSION_FORM_AUTO_UPDATE}
- FRONTEND_MISSION_FORM_AUTO_SAVE_ENABLED=${FRONTEND_MISSION_FORM_AUTO_SAVE_ENABLED}
- FRONTEND_REGULATORY_AREAS_BO_ENABLED=${FRONTEND_REGULATORY_AREAS_BO_ENABLED}
- FRONTEND_REPORTING_FORM_AUTO_SAVE_ENABLED=${FRONTEND_REPORTING_FORM_AUTO_SAVE_ENABLED}
- FRONTEND_REPORTING_FORM_AUTO_UPDATE=${FRONTEND_REPORTING_FORM_AUTO_UPDATE}
- FRONTEND_VESSELS_ENABLED=${FRONTEND_VESSELS_ENABLED}
Expand Down Expand Up @@ -83,7 +84,7 @@ services:
- db
restart: always
healthcheck:
test: [ "CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1" ]
test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
Expand All @@ -109,7 +110,7 @@ services:
ports:
- ${POSTGRES_PORT}:5432
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 1s
timeout: 1s
retries: 30
Expand All @@ -120,7 +121,7 @@ services:

geoserver:
container_name: monitorenv_geoserver
profiles: [ dev, production ]
profiles: [dev, production]
image: kartoza/geoserver:2.18.0
environment:
- GEOSERVER_ADMIN_PASSWORD=${GEOSERVER_ADMIN_PASSWORD}
Expand All @@ -131,7 +132,7 @@ services:
- geoserver-data:/opt/geoserver/data_dir
- geoserver-settings:/settings
healthcheck:
test: [ "CMD-SHELL", "curl --fail -s http://localhost:8080/geoserver/index.html || exit 1" ]
test: ["CMD-SHELL", "curl --fail -s http://localhost:8080/geoserver/index.html || exit 1"]
interval: 1m30s
timeout: 1s
retries: 30
Expand All @@ -141,7 +142,7 @@ services:

keycloak:
container_name: monitorenv_keycloak
profiles: [ dev ]
profiles: [dev]
image: quay.io/keycloak/keycloak:latest
environment:
- KEYCLOAK_ADMIN=admin
Expand All @@ -157,7 +158,7 @@ services:
- --import-realm

mock-geoserver:
profiles: [ test ]
profiles: [test]
image: wiremock/wiremock:3.8.0
networks:
- backend_network
Expand All @@ -176,7 +177,7 @@ services:
retries: 30

mock-monitorfish:
profiles: [ dev, test ]
profiles: [dev, test]
image: wiremock/wiremock:3.8.0
networks:
- backend_network
Expand All @@ -185,13 +186,13 @@ services:
volumes:
- ./frontend/cypress/mappings/monitorfish:/home/wiremock/mappings
healthcheck:
test: [ "CMD-SHELL", "curl --fail http://localhost:8080/api/v1/mission_actions?missionId=34 || exit 1 " ]
test: ["CMD-SHELL", "curl --fail http://localhost:8080/api/v1/mission_actions?missionId=34 || exit 1 "]
interval: 1s
timeout: 1s
retries: 30

mock-rapportnav:
profiles: [ dev, test ]
profiles: [dev, test]
image: wiremock/wiremock:3.8.0
networks:
- backend_network
Expand All @@ -200,14 +201,14 @@ services:
volumes:
- ./frontend/cypress/mappings/rapportnav:/home/wiremock/mappings
healthcheck:
test: [ "CMD-SHELL", "curl --fail http://localhost:8080/api/v1/missions/34 || exit 1 " ]
test: ["CMD-SHELL", "curl --fail http://localhost:8080/api/v1/missions/34 || exit 1 "]
interval: 1s
timeout: 1s
retries: 30

kafka:
container_name: kafka
profiles: [ dev, test ]
profiles: [dev, test]
image: confluentinc/cp-kafka:8.1.0
ports:
- "9093:9093"
Expand All @@ -221,7 +222,7 @@ services:
KAFKA_ADVERTISED_LISTENERS: SSL://localhost:9093
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_NUM_PARTITIONS: 1
KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
KAFKA_BROKER_ID: 1
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@localhost:9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
Expand Down
1 change: 1 addition & 0 deletions frontend/.env.frontend.example
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ FRONTEND_MISSION_FORM_AUTO_SAVE_ENABLED=
FRONTEND_REPORTING_FORM_AUTO_SAVE_ENABLED=
FRONTEND_REPORTING_FORM_AUTO_UPDATE=
FRONTEND_VESSELS_ENABLED=
FRONTEND_REGULATORY_AREAS_BO_ENABLED=

################################################################################
# Version
Expand Down
67 changes: 67 additions & 0 deletions frontend/src/api/regulatoryLayersAPI.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getExtentOfLayersGroup } from '@features/layersSelector/utils/getExtentOfLayersGroup'
import { FrontendApiError } from '@libs/FrontendApiError'
import { createEntityAdapter, createSelector, type EntityId, type EntityState } from '@reduxjs/toolkit'
import { SeaFrontLabels } from 'domain/entities/seaFrontType'
import { boundingExtent, createEmpty } from 'ol/extent'
import { createCachedSelector } from 're-reselect'

Expand All @@ -13,6 +14,7 @@ import type {
} from '../domain/entities/regulatory'
import type { HomeRootState } from '@store/index'
import type { Coordinate } from 'ol/coordinate'
import type { StringDigit } from 'type-fest/source/internal'

const GET_REGULATORY_LAYER_ERROR_MESSAGE = "Nous n'avons pas pu récupérer la zones réglementaire"
const GET_REGULATORY_LAYERS_ERROR_MESSAGE = "Nous n'avons pas pu récupérer la/les zones réglementaires"
Expand Down Expand Up @@ -121,3 +123,68 @@ export const getExtentOfRegulatoryLayersGroupByGroupName = createCachedSelector(
return createEmpty()
}
)((_, groupName: string) => groupName)

export const getRegulatoryLayersByControlPlan = createSelector(
[regulatoryLayersAPI.endpoints.getRegulatoryLayers.select()],
regulatoryLayers => {
const entities = regulatoryLayers?.data?.entities
const ids = regulatoryLayers?.data?.ids

if (!ids || !entities) {
return {}
}

return ids.reduce((acc, layerId) => {
const entity = entities[layerId]
const layerName = entity?.layerName
const planRaw = entity?.plan

if (!layerName || !planRaw) {
return acc
}

const plans = planRaw.split(',').map(p => p.trim())

plans.forEach(plan => {
acc[plan] ??= {}
acc[plan][layerName] ??= []
acc[plan][layerName].push(entities[layerId])
})

return acc
}, {} as Record<'PIRC' | 'PSCEM', Record<string, RegulatoryLayerCompact[]>>)
}
)

export const getRegulatoryLayersBySeaFront = createSelector(
[regulatoryLayersAPI.endpoints.getRegulatoryLayers.select()],
regulatoryLayers => {
const entities = regulatoryLayers?.data?.entities
const ids = regulatoryLayers?.data?.ids

if (!ids || !entities) {
return {}
}

return ids.reduce((acc, layerId) => {
const entity = entities[layerId]
const layerName = entity?.layerName
const seaFront = entity?.facade

if (!layerName || !seaFront) {
return acc
}
const allSeaFronts = Object.values(SeaFrontLabels).map(seaFrontLabel => seaFrontLabel.label)

allSeaFronts.forEach(seaFrontLabel => {
if (seaFront === seaFrontLabel) {
acc[seaFrontLabel] ??= {}
acc[seaFrontLabel][layerName] ??= []
acc[seaFrontLabel][layerName].push(entities[layerId])
}
})

return acc
}, {} as Record<StringDigit, Record<string, RegulatoryLayerCompact[]>>)
}
)
Loading
Loading