From 06c0dec10991f0069097520b090df901ac5e917e Mon Sep 17 00:00:00 2001 From: COPPEJANS Matthieu Date: Thu, 28 Dec 2023 09:28:17 +0100 Subject: [PATCH 01/11] test ajout analyse postgres --- .gitlab-ci.yml | 14 +++++++------- ci/jobs/analyse_trivy.yml | 11 +++++++++++ ci/jobs/construction_image.yml | 1 + 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 154a9bcd..6b1c20af 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,12 +30,12 @@ variables: description: "Détermine la commande à passer à Trivy pour bloquer ou non le job. --severity CRITICAL fait échouer le job si Trivy remonte des anomalies critiques." include: - - "/ci/jobs/verif_image_checksum.yml" - - "/ci/jobs/build_projet_maven.yml" - - "/ci/jobs/build_projet_npm.yml" + # - "/ci/jobs/verif_image_checksum.yml" + # - "/ci/jobs/build_projet_maven.yml" + # - "/ci/jobs/build_projet_npm.yml" - "/ci/jobs/construction_image.yml" - - "/ci/jobs/dependency-check.yml" - - "/ci/jobs/analyse_sonar.yml" + # - "/ci/jobs/dependency-check.yml" + # - "/ci/jobs/analyse_sonar.yml" - "/ci/jobs/analyse_trivy.yml" - - "/ci/jobs/deploiement_image_int.yml" - - "/ci/jobs/deploiement_image_prod.yml" + # - "/ci/jobs/deploiement_image_int.yml" + # - "/ci/jobs/deploiement_image_prod.yml" diff --git a/ci/jobs/analyse_trivy.yml b/ci/jobs/analyse_trivy.yml index 7fbbffc1..d10e2bb8 100644 --- a/ci/jobs/analyse_trivy.yml +++ b/ci/jobs/analyse_trivy.yml @@ -12,6 +12,7 @@ analyse_trivy: TRIVY_NON_SSL: "true" TRIVY_SERVER: "http://trivy.dsi.damgm.i2" FULL_IMAGE_NAME: $TAG_LATEST + BDD_IMAGE_NAME: $NEXUS_DOCKER_PROXY/postgres:15-bookworm HTTP_PROXY: "http://172.27.229.197:8090" HTTPS_PROXY: "http://172.27.229.197:8090" NO_PROXY: "gitlab-sml.din.developpement-durable.gouv.fr,int-docker01,localhost,127.0.0.1,0.0.0.0,.dsi.damgm.i2" @@ -27,6 +28,16 @@ analyse_trivy: # Builds report and puts it in the default workdir $CI_PROJECT_DIR, so `artifacts:` can take it from there time trivy image -d --server $TRIVY_SERVER --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report.html" "$FULL_IMAGE_NAME" fi + + - time trivy image -d --server $TRIVY_SERVER $BDD_IMAGE_NAME --clear-cache --timeout 120m --cache-dir .trivycache/ + - | + if [[ "$FAIL_TRIVY_CONDITION" != "" && "$KEEP_RUNNING" != "true" ]]; then + # Fail on critical vulnerabilities + time trivy image -d --server $TRIVY_SERVER --exit-code 1 --cache-dir .trivycache/ $FAIL_TRIVY_CONDITION --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report.html" "$BDD_IMAGE_NAME" + else + # Builds report and puts it in the default workdir $CI_PROJECT_DIR, so `artifacts:` can take it from there + time trivy image -d --server $TRIVY_SERVER --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report.html" "$BDD_IMAGE_NAME" + fi cache: paths: - .trivycache/ diff --git a/ci/jobs/construction_image.yml b/ci/jobs/construction_image.yml index 4d7fc1e3..b25f0362 100644 --- a/ci/jobs/construction_image.yml +++ b/ci/jobs/construction_image.yml @@ -28,6 +28,7 @@ construction_image: - docker login $NEXUS_DOCKER_REPO -u $NEXUS_USER -p $NEXUS_PWD - docker image push --all-tags $NEXUS_DOCKER_REPO/$PROJECT_NAME - docker logout $NEXUS_DOCKER_REPO + - docker pull $NEXUS_DOCKER_PROXY/postgres:15-bookworm tags: - build From 8ab4e76dda215296cb8cc16af4fe13a7cb2f5a25 Mon Sep 17 00:00:00 2001 From: COPPEJANS Matthieu Date: Thu, 28 Dec 2023 09:29:44 +0100 Subject: [PATCH 02/11] test ajout analyse postgres --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6b1c20af..97384d0b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -31,8 +31,8 @@ variables: include: # - "/ci/jobs/verif_image_checksum.yml" - # - "/ci/jobs/build_projet_maven.yml" - # - "/ci/jobs/build_projet_npm.yml" + - "/ci/jobs/build_projet_maven.yml" + - "/ci/jobs/build_projet_npm.yml" - "/ci/jobs/construction_image.yml" # - "/ci/jobs/dependency-check.yml" # - "/ci/jobs/analyse_sonar.yml" From 1cc9ddda81d30819b364fef7466112e2551b7263 Mon Sep 17 00:00:00 2001 From: COPPEJANS Matthieu Date: Thu, 28 Dec 2023 09:48:43 +0100 Subject: [PATCH 03/11] test ajout analyse postgres --- ci/jobs/construction_image.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ci/jobs/construction_image.yml b/ci/jobs/construction_image.yml index b25f0362..98768aa0 100644 --- a/ci/jobs/construction_image.yml +++ b/ci/jobs/construction_image.yml @@ -27,8 +27,9 @@ construction_image: --build-arg GITHUB_SHA=$CI_COMMIT_SHA - docker login $NEXUS_DOCKER_REPO -u $NEXUS_USER -p $NEXUS_PWD - docker image push --all-tags $NEXUS_DOCKER_REPO/$PROJECT_NAME - - docker logout $NEXUS_DOCKER_REPO - docker pull $NEXUS_DOCKER_PROXY/postgres:15-bookworm + - docker logout $NEXUS_DOCKER_REPO + tags: - build From 197fed0c909272b1bd292bc567a05c6ced08ef50 Mon Sep 17 00:00:00 2001 From: COPPEJANS Matthieu Date: Thu, 28 Dec 2023 10:05:07 +0100 Subject: [PATCH 04/11] test ajout analyse postgres --- ci/jobs/construction_image.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ci/jobs/construction_image.yml b/ci/jobs/construction_image.yml index 98768aa0..f46439dd 100644 --- a/ci/jobs/construction_image.yml +++ b/ci/jobs/construction_image.yml @@ -27,9 +27,10 @@ construction_image: --build-arg GITHUB_SHA=$CI_COMMIT_SHA - docker login $NEXUS_DOCKER_REPO -u $NEXUS_USER -p $NEXUS_PWD - docker image push --all-tags $NEXUS_DOCKER_REPO/$PROJECT_NAME - - docker pull $NEXUS_DOCKER_PROXY/postgres:15-bookworm - docker logout $NEXUS_DOCKER_REPO - + - docker login $NEXUS_DOCKER_PROXY -u $NEXUS_USER -p $NEXUS_PWD + - docker pull $NEXUS_DOCKER_PROXY/postgres:15-bookworm + - docker logout $NEXUS_DOCKER_PROXY tags: - build From ad9eecba7dd39be03b4a11af6d7d9a86bfeca140 Mon Sep 17 00:00:00 2001 From: COPPEJANS Matthieu Date: Thu, 28 Dec 2023 10:17:35 +0100 Subject: [PATCH 05/11] test ajout analyse postgres --- ci/jobs/analyse_trivy.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ci/jobs/analyse_trivy.yml b/ci/jobs/analyse_trivy.yml index d10e2bb8..17e5e043 100644 --- a/ci/jobs/analyse_trivy.yml +++ b/ci/jobs/analyse_trivy.yml @@ -26,7 +26,7 @@ analyse_trivy: time trivy image -d --server $TRIVY_SERVER --exit-code 1 --cache-dir .trivycache/ $FAIL_TRIVY_CONDITION --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report.html" "$FULL_IMAGE_NAME" else # Builds report and puts it in the default workdir $CI_PROJECT_DIR, so `artifacts:` can take it from there - time trivy image -d --server $TRIVY_SERVER --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report.html" "$FULL_IMAGE_NAME" + time trivy image -d --server $TRIVY_SERVER --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report-app.html" "$FULL_IMAGE_NAME" fi - time trivy image -d --server $TRIVY_SERVER $BDD_IMAGE_NAME --clear-cache --timeout 120m --cache-dir .trivycache/ @@ -36,7 +36,7 @@ analyse_trivy: time trivy image -d --server $TRIVY_SERVER --exit-code 1 --cache-dir .trivycache/ $FAIL_TRIVY_CONDITION --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report.html" "$BDD_IMAGE_NAME" else # Builds report and puts it in the default workdir $CI_PROJECT_DIR, so `artifacts:` can take it from there - time trivy image -d --server $TRIVY_SERVER --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report.html" "$BDD_IMAGE_NAME" + time trivy image -d --server $TRIVY_SERVER --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report-bdd.html" "$BDD_IMAGE_NAME" fi cache: paths: @@ -44,7 +44,8 @@ analyse_trivy: artifacts: when: always paths: - - container-scanning-report.html + - container-scanning-report-app.html + - container-scanning-report-bdd.html tags: - analyze From 2223d99316f37125b2ac6c2801e9db8f426a758c Mon Sep 17 00:00:00 2001 From: COPPEJANS Matthieu Date: Thu, 28 Dec 2023 10:28:44 +0100 Subject: [PATCH 06/11] test ajout analyse postgres --- ci/jobs/analyse_trivy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/jobs/analyse_trivy.yml b/ci/jobs/analyse_trivy.yml index 17e5e043..7fec170e 100644 --- a/ci/jobs/analyse_trivy.yml +++ b/ci/jobs/analyse_trivy.yml @@ -23,7 +23,7 @@ analyse_trivy: - | if [[ "$FAIL_TRIVY_CONDITION" != "" && "$KEEP_RUNNING" != "true" ]]; then # Fail on critical vulnerabilities - time trivy image -d --server $TRIVY_SERVER --exit-code 1 --cache-dir .trivycache/ $FAIL_TRIVY_CONDITION --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report.html" "$FULL_IMAGE_NAME" + time trivy image -d --server $TRIVY_SERVER --exit-code 1 --cache-dir .trivycache/ $FAIL_TRIVY_CONDITION --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report-app.html" "$FULL_IMAGE_NAME" else # Builds report and puts it in the default workdir $CI_PROJECT_DIR, so `artifacts:` can take it from there time trivy image -d --server $TRIVY_SERVER --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report-app.html" "$FULL_IMAGE_NAME" @@ -33,7 +33,7 @@ analyse_trivy: - | if [[ "$FAIL_TRIVY_CONDITION" != "" && "$KEEP_RUNNING" != "true" ]]; then # Fail on critical vulnerabilities - time trivy image -d --server $TRIVY_SERVER --exit-code 1 --cache-dir .trivycache/ $FAIL_TRIVY_CONDITION --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report.html" "$BDD_IMAGE_NAME" + time trivy image -d --server $TRIVY_SERVER --exit-code 1 --cache-dir .trivycache/ $FAIL_TRIVY_CONDITION --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report_bdd.html" "$BDD_IMAGE_NAME" else # Builds report and puts it in the default workdir $CI_PROJECT_DIR, so `artifacts:` can take it from there time trivy image -d --server $TRIVY_SERVER --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report-bdd.html" "$BDD_IMAGE_NAME" From 374a3f29811ef8d27d0ff3121f7737a648a08e26 Mon Sep 17 00:00:00 2001 From: COPPEJANS Matthieu Date: Thu, 28 Dec 2023 10:37:42 +0100 Subject: [PATCH 07/11] test ajout analyse postgres --- ci/jobs/analyse_trivy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/jobs/analyse_trivy.yml b/ci/jobs/analyse_trivy.yml index 7fec170e..d25c1232 100644 --- a/ci/jobs/analyse_trivy.yml +++ b/ci/jobs/analyse_trivy.yml @@ -33,7 +33,7 @@ analyse_trivy: - | if [[ "$FAIL_TRIVY_CONDITION" != "" && "$KEEP_RUNNING" != "true" ]]; then # Fail on critical vulnerabilities - time trivy image -d --server $TRIVY_SERVER --exit-code 1 --cache-dir .trivycache/ $FAIL_TRIVY_CONDITION --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report_bdd.html" "$BDD_IMAGE_NAME" + time trivy image -d --server $TRIVY_SERVER --exit-code 1 --cache-dir .trivycache/ $FAIL_TRIVY_CONDITION --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report-bdd.html" "$BDD_IMAGE_NAME" else # Builds report and puts it in the default workdir $CI_PROJECT_DIR, so `artifacts:` can take it from there time trivy image -d --server $TRIVY_SERVER --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/contrib/html.tpl" --output "container-scanning-report-bdd.html" "$BDD_IMAGE_NAME" From 0b78ebc45fc10297d5dd37bb31b688e45527c370 Mon Sep 17 00:00:00 2001 From: COPPEJANS Matthieu Date: Thu, 28 Dec 2023 11:09:46 +0100 Subject: [PATCH 08/11] testajout analyse postgres --- .gitlab-ci.yml | 13 ++++++++----- ci/jobs/analyse_trivy.yml | 2 +- ci/jobs/construction_image.yml | 2 +- .../templates/docker-compose.yml.j2 | 2 +- ci/roles/start_docker_containers/vars/main.yml | 1 + 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 97384d0b..00be0ff1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -11,6 +11,9 @@ variables: PROJECT_NAME: value: rapportnav-v2 description: "Nom du projet à déployer" + BDD_IAMGE: + value: postgres:15-bookworm + description: "Image de la base de données" PROJECT_VERSION: value: "0.0.1-alpha.10" description: "Version du projet à déployer" @@ -30,12 +33,12 @@ variables: description: "Détermine la commande à passer à Trivy pour bloquer ou non le job. --severity CRITICAL fait échouer le job si Trivy remonte des anomalies critiques." include: - # - "/ci/jobs/verif_image_checksum.yml" + - "/ci/jobs/verif_image_checksum.yml" - "/ci/jobs/build_projet_maven.yml" - "/ci/jobs/build_projet_npm.yml" - "/ci/jobs/construction_image.yml" - # - "/ci/jobs/dependency-check.yml" - # - "/ci/jobs/analyse_sonar.yml" + - "/ci/jobs/dependency-check.yml" + - "/ci/jobs/analyse_sonar.yml" - "/ci/jobs/analyse_trivy.yml" - # - "/ci/jobs/deploiement_image_int.yml" - # - "/ci/jobs/deploiement_image_prod.yml" + - "/ci/jobs/deploiement_image_int.yml" + - "/ci/jobs/deploiement_image_prod.yml" diff --git a/ci/jobs/analyse_trivy.yml b/ci/jobs/analyse_trivy.yml index d25c1232..242f0d42 100644 --- a/ci/jobs/analyse_trivy.yml +++ b/ci/jobs/analyse_trivy.yml @@ -12,7 +12,7 @@ analyse_trivy: TRIVY_NON_SSL: "true" TRIVY_SERVER: "http://trivy.dsi.damgm.i2" FULL_IMAGE_NAME: $TAG_LATEST - BDD_IMAGE_NAME: $NEXUS_DOCKER_PROXY/postgres:15-bookworm + BDD_IMAGE_NAME: $NEXUS_DOCKER_PROXY/$BDD_IAMGE HTTP_PROXY: "http://172.27.229.197:8090" HTTPS_PROXY: "http://172.27.229.197:8090" NO_PROXY: "gitlab-sml.din.developpement-durable.gouv.fr,int-docker01,localhost,127.0.0.1,0.0.0.0,.dsi.damgm.i2" diff --git a/ci/jobs/construction_image.yml b/ci/jobs/construction_image.yml index f46439dd..ffd9506f 100644 --- a/ci/jobs/construction_image.yml +++ b/ci/jobs/construction_image.yml @@ -29,7 +29,7 @@ construction_image: - docker image push --all-tags $NEXUS_DOCKER_REPO/$PROJECT_NAME - docker logout $NEXUS_DOCKER_REPO - docker login $NEXUS_DOCKER_PROXY -u $NEXUS_USER -p $NEXUS_PWD - - docker pull $NEXUS_DOCKER_PROXY/postgres:15-bookworm + - docker pull $NEXUS_DOCKER_PROXY/$BDD_IAMGE - docker logout $NEXUS_DOCKER_PROXY tags: - build diff --git a/ci/roles/start_docker_containers/templates/docker-compose.yml.j2 b/ci/roles/start_docker_containers/templates/docker-compose.yml.j2 index 1ab40030..433fc66a 100644 --- a/ci/roles/start_docker_containers/templates/docker-compose.yml.j2 +++ b/ci/roles/start_docker_containers/templates/docker-compose.yml.j2 @@ -26,7 +26,7 @@ services: max-size: "1024m" db: - image: postgres:15-bookworm + image: {{ image_bdd }} volumes: # - "${RAPPORTNAV_BACKUPS_FOLDER}:/opt/rapportnav_backups" - db:/var/lib/postgresql/data diff --git a/ci/roles/start_docker_containers/vars/main.yml b/ci/roles/start_docker_containers/vars/main.yml index 0d80fe8a..0b01c001 100644 --- a/ci/roles/start_docker_containers/vars/main.yml +++ b/ci/roles/start_docker_containers/vars/main.yml @@ -4,3 +4,4 @@ docker_image_path: "{{ lookup('env', 'TAG_VERSION') }}" docker_compose_path: "/opt/dockers/{{ project_name }}" project_ports: "{{ lookup('env', 'PROJECT_PORTS') }}" project_volumes: "{{ lookup('env', 'PROJECT_VOLUMES') }}" +image_bdd: "{{ lookup('env', 'BDD_IAMGE') }}" \ No newline at end of file From 55ff2f71c1e9d4f91b908be2c5c9086e4ff005b1 Mon Sep 17 00:00:00 2001 From: lwih Date: Thu, 28 Dec 2023 18:30:50 +0100 Subject: [PATCH 09/11] Allow editing target for Env infractions on targets reported by the unit + various fixes --- .../IInfractionEnvTargetRepository.kt | 11 + .../AddOrUpdateInfractionEnvTarget.kt | 16 + .../mission/infraction/GetInfractionById.kt | 8 +- .../IsControlledAllowedForTarget.kt | 20 + .../infrastructure/bff/ActionEnvController.kt | 4 +- .../bff/InfractionController.kt | 63 +- .../model/infraction/InfractionsByVessel.kt | 4 +- .../infraction/InfractionEnvTargetModel.kt | 24 +- .../mission/infraction/InfractionModel.kt | 31 +- .../IDBInfractionEnvTargetRepository.kt | 9 + .../JPAInfractionEnvTargetRepository.kt | 44 ++ .../resources/graphql/infraction.graphqls | 2 +- frontend/src/auth/test-server.ts | 6 - .../mission/actions/action-control-env.tsx | 420 +++++++------- .../pam/mission/actions/use-action-by-id.tsx | 2 +- .../env-infraction-add-new-target.tsx | 102 ++++ .../env-infraction-existing-target-form.tsx | 180 ------ .../env-infraction-existing-target.tsx | 116 ---- .../env-infraction-existing-targets.tsx | 151 +++++ .../env-infraction-new-target-form.tsx | 98 ---- .../infractions/env-infraction-new-target.tsx | 92 --- .../infractions/env-infraction-summary.tsx | 160 ++--- ...-infraction-target-added-by-cacem-form.tsx | 156 +++++ ...v-infraction-target-added-by-unit-form.tsx | 99 ++++ frontend/src/pam/mission/infractions/utils.ts | 50 +- frontend/src/pam/mission/page-footer.tsx | 74 +-- frontend/src/pam/mission/queries.ts | 2 +- .../pam/mission/timeline/timeline-item.tsx | 548 +++++++++--------- frontend/src/types/infraction-types.ts | 2 +- 29 files changed, 1320 insertions(+), 1174 deletions(-) create mode 100644 backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/repositories/mission/infraction/IInfractionEnvTargetRepository.kt create mode 100644 backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/AddOrUpdateInfractionEnvTarget.kt create mode 100644 backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/IsControlledAllowedForTarget.kt create mode 100644 backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/repositories/interfaces/mission/infraction/IDBInfractionEnvTargetRepository.kt create mode 100644 backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/repositories/mission/infraction/JPAInfractionEnvTargetRepository.kt create mode 100644 frontend/src/pam/mission/infractions/env-infraction-add-new-target.tsx delete mode 100644 frontend/src/pam/mission/infractions/env-infraction-existing-target-form.tsx delete mode 100644 frontend/src/pam/mission/infractions/env-infraction-existing-target.tsx create mode 100644 frontend/src/pam/mission/infractions/env-infraction-existing-targets.tsx delete mode 100644 frontend/src/pam/mission/infractions/env-infraction-new-target-form.tsx delete mode 100644 frontend/src/pam/mission/infractions/env-infraction-new-target.tsx create mode 100644 frontend/src/pam/mission/infractions/env-infraction-target-added-by-cacem-form.tsx create mode 100644 frontend/src/pam/mission/infractions/env-infraction-target-added-by-unit-form.tsx diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/repositories/mission/infraction/IInfractionEnvTargetRepository.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/repositories/mission/infraction/IInfractionEnvTargetRepository.kt new file mode 100644 index 00000000..12d03df7 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/repositories/mission/infraction/IInfractionEnvTargetRepository.kt @@ -0,0 +1,11 @@ +package fr.gouv.dgampa.rapportnav.domain.repositories.mission.infraction + +import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEntity +import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEnvTargetEntity +import fr.gouv.dgampa.rapportnav.infrastructure.database.model.mission.infraction.InfractionEnvTargetModel + +interface IInfractionEnvTargetRepository { + fun save(infractionTarget: InfractionEnvTargetEntity, infraction: InfractionEntity): InfractionEnvTargetModel + + fun findByActionIdAndVesselIdentifier(actionId: String, vesselIdentifier: String): List +} diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/AddOrUpdateInfractionEnvTarget.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/AddOrUpdateInfractionEnvTarget.kt new file mode 100644 index 00000000..55322321 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/AddOrUpdateInfractionEnvTarget.kt @@ -0,0 +1,16 @@ +package fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction + +import fr.gouv.dgampa.rapportnav.config.UseCase +import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEntity +import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEnvTargetEntity +import fr.gouv.dgampa.rapportnav.domain.repositories.mission.infraction.IInfractionEnvTargetRepository + +@UseCase +class AddOrUpdateInfractionEnvTarget( + private val repo: IInfractionEnvTargetRepository, +) { + fun execute(infractionTarget: InfractionEnvTargetEntity, infraction: InfractionEntity): InfractionEnvTargetEntity { + val savedData = repo.save(infractionTarget, infraction).toInfractionEnvTargetEntity() + return savedData + } +} diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/GetInfractionById.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/GetInfractionById.kt index 4af51b98..369f6e1e 100644 --- a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/GetInfractionById.kt +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/GetInfractionById.kt @@ -8,7 +8,11 @@ import java.util.* @UseCase class GetInfractionById(private val repo: IInfractionRepository) { fun execute(id: UUID): InfractionEntity? { - val optionalInfractionModel = repo.findById(id) - return optionalInfractionModel.map { it.toInfractionEntity() }.orElse(null) + val infractionModel = repo.findById(id) + if (infractionModel.isPresent) { + return infractionModel.get().toInfractionEntity() + } else { + return null + } } } diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/IsControlledAllowedForTarget.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/IsControlledAllowedForTarget.kt new file mode 100644 index 00000000..2e59ebe6 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/domain/use_cases/mission/infraction/IsControlledAllowedForTarget.kt @@ -0,0 +1,20 @@ +package fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction + +import fr.gouv.dgampa.rapportnav.config.UseCase +import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.control.ControlType +import fr.gouv.dgampa.rapportnav.domain.repositories.mission.infraction.IInfractionEnvTargetRepository + +@UseCase +class IsControlledAllowedForTarget( + private val repo: IInfractionEnvTargetRepository, + private val getInfractionById: GetInfractionById, +) { + fun execute(actionId: String, vesselIdentifier: String, controlType: ControlType): Boolean { + val targets = repo.findByActionIdAndVesselIdentifier(actionId = actionId, vesselIdentifier = vesselIdentifier) + val controlledAllowed = targets.map { + val infraction = it.infraction?.toInfractionEntity() + return controlType != infraction?.controlType + } + return controlledAllowed.all { true } + } +} diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/ActionEnvController.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/ActionEnvController.kt index e3b7b7a9..e9da99b7 100644 --- a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/ActionEnvController.kt +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/ActionEnvController.kt @@ -86,14 +86,14 @@ class ActionEnvController( infractionsByVessel = infractionsByVessel.map { byVessel -> // a target reported by monitorEnv will have an infraction with controlType null // the next field is to help the frontend hide/show information according to whom has reported the target - val targetAddedInRapportNav = !byVessel.infractions.any { it.controlType == null } + val targetAddedByUnit = !byVessel.infractions.any { it.controlType == null } // the next field is to help the frontend show different options for which control type to report an infraction val reportedControlTypes = byVessel.infractions.mapNotNull { it.controlType } val updatedByVessel = byVessel.copy( controlTypesWithInfraction = reportedControlTypes, - targetAddedInRapportNav = targetAddedInRapportNav + targetAddedByUnit = targetAddedByUnit ) updatedByVessel } diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/InfractionController.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/InfractionController.kt index dc0899ec..54ecc5d9 100644 --- a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/InfractionController.kt +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/InfractionController.kt @@ -1,14 +1,15 @@ package fr.gouv.dgampa.rapportnav.infrastructure.bff +import fr.gouv.dgampa.rapportnav.domain.entities.mission.env.envActions.VesselSizeEnum +import fr.gouv.dgampa.rapportnav.domain.entities.mission.env.envActions.VesselTypeEnum +import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.control.ControlType import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEnvTargetEntity -import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction.AddOrUpdateInfraction -import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction.DeleteInfraction -import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction.GetInfractionById -import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction.GetNatinfs +import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.infraction.* import fr.gouv.dgampa.rapportnav.infrastructure.bff.adapters.infraction.InfractionInput import fr.gouv.dgampa.rapportnav.infrastructure.bff.adapters.infraction.InfractionWithNewTargetInput import fr.gouv.dgampa.rapportnav.infrastructure.bff.model.infraction.Infraction import fr.gouv.dgampa.rapportnav.infrastructure.bff.model.infraction.Natinf +import org.slf4j.LoggerFactory import org.springframework.graphql.data.method.annotation.Argument import org.springframework.graphql.data.method.annotation.MutationMapping import org.springframework.graphql.data.method.annotation.QueryMapping @@ -22,8 +23,13 @@ class InfractionController( private val deleteInfraction: DeleteInfraction, private val getInfractionById: GetInfractionById, private val getNatinfs: GetNatinfs, + private val addOrUpdateInfractionEnvTarget: AddOrUpdateInfractionEnvTarget, + private val isControlledAllowedForTarget: IsControlledAllowedForTarget, ) { + private val logger = LoggerFactory.getLogger(InfractionController::class.java) + + @QueryMapping fun natinfs(): List { return getNatinfs.execute().map { Natinf.fromNatinfEntity(it) } @@ -49,22 +55,57 @@ class InfractionController( @MutationMapping fun addOrUpdateInfractionForEnvTarget(@Argument infraction: InfractionWithNewTargetInput): Infraction? { - val target: InfractionEnvTargetEntity? + var target: InfractionEnvTargetEntity? + + + if (infraction.id == null) { + // check if there is not already an infraction with the same controlType for this target + val isAllowed = isControlledAllowedForTarget.execute( + actionId = infraction.actionId, + vesselIdentifier = infraction.vesselIdentifier, + controlType = ControlType.valueOf(infraction.controlType) + ) + if (!isAllowed) { + logger.error("addOrUpdateInfractionForEnvTarget - controlType=${infraction.controlType} already exists for target name=${infraction.vesselIdentifier}") + throw Exception("Ce type de contrôle a déjà été reporté pour cette cible. Veuillez annuler et modifier le contrôle déjà existant.") + } else { + target = null + } + } else { - // get the infraction if it already exists and set its target - if (infraction.id != null) { + // get the infraction if it already exists and set its target val repoInfraction = getInfractionById.execute(id = UUID.fromString(infraction.id)) target = repoInfraction?.target - } else { - target = null - } - // TODO must also verify that there is not already an infraction for this target and this controlType + // Check if target has changed or not by crossing fields between InfractionWithNewTargetInput and InfractionEnvTargetEntity + if (target != null && hasTargetChanged(infraction, target)) { + // Update the target + val newTarget = InfractionEnvTargetEntity( + id = target.id, + missionId = target.missionId, + actionId = target.actionId, + infractionId = target.infractionId, + vesselIdentifier = infraction.vesselIdentifier, + vesselSize = VesselSizeEnum.valueOf(infraction.vesselSize), + vesselType = VesselTypeEnum.valueOf(infraction.vesselType), + identityControlledPerson = infraction.identityControlledPerson + ) + target = addOrUpdateInfractionEnvTarget.execute(newTarget, infraction.toInfractionEntity(newTarget)) + } + } val input = infraction.toInfractionEntity(target) val infractionEntity = addOrUpdateInfraction.execute(input) return Infraction.fromInfractionEntity(infractionEntity) } + // Function to check if the target has changed + private fun hasTargetChanged(input: InfractionWithNewTargetInput, target: InfractionEnvTargetEntity): Boolean { + return input.vesselType != target.vesselType.name || + input.vesselSize != target.vesselSize.name || + input.vesselIdentifier != target.vesselIdentifier || + input.identityControlledPerson != target.identityControlledPerson + } + } diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/model/infraction/InfractionsByVessel.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/model/infraction/InfractionsByVessel.kt index ec42d271..fa06d092 100644 --- a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/model/infraction/InfractionsByVessel.kt +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/bff/model/infraction/InfractionsByVessel.kt @@ -8,7 +8,7 @@ data class InfractionsByVessel( val vesselIdentifier: String? = null, val vesselType: VesselTypeEnum? = null, val controlTypesWithInfraction: List? = null, - val targetAddedInRapportNav: Boolean? = null, + val targetAddedByUnit: Boolean? = null, val infractions: List ) { fun groupInfractionsByVesselIdentifier(infractions: List): List { @@ -20,7 +20,7 @@ data class InfractionsByVessel( vesselType = infractions.firstOrNull()?.target?.vesselType, infractions = infractions, controlTypesWithInfraction = controlTypesWithInfraction, - targetAddedInRapportNav = targetAddedInRapportNav, + targetAddedByUnit = targetAddedByUnit, ) } } diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/model/mission/infraction/InfractionEnvTargetModel.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/model/mission/infraction/InfractionEnvTargetModel.kt index f6406818..ef01a86a 100644 --- a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/model/mission/infraction/InfractionEnvTargetModel.kt +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/model/mission/infraction/InfractionEnvTargetModel.kt @@ -3,6 +3,7 @@ package fr.gouv.dgampa.rapportnav.infrastructure.database.model.mission.infracti import com.fasterxml.jackson.annotation.JsonIgnore import fr.gouv.dgampa.rapportnav.domain.entities.mission.env.envActions.VesselSizeEnum import fr.gouv.dgampa.rapportnav.domain.entities.mission.env.envActions.VesselTypeEnum +import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEntity import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEnvTargetEntity import jakarta.persistence.* import java.util.* @@ -53,14 +54,19 @@ data class InfractionEnvTargetModel( } companion object { - fun fromInfractionEnvTargetEntity(infraction: InfractionEnvTargetEntity) = InfractionEnvTargetModel( - id = infraction.id, - missionId = infraction.missionId, - actionId = infraction.actionId, - vesselIdentifier = infraction.vesselIdentifier, - identityControlledPerson = infraction.identityControlledPerson, - vesselType = infraction.vesselType.toString(), - vesselSize = infraction.vesselSize.toString(), - ) + fun fromInfractionEnvTargetEntity( + infractionTarget: InfractionEnvTargetEntity, + infraction: InfractionEntity? = null + ) = + InfractionEnvTargetModel( + id = infractionTarget.id, + missionId = infractionTarget.missionId, + actionId = infractionTarget.actionId, + infraction = infraction?.let { it -> InfractionModel.fromInfractionEntity(it) }, + vesselIdentifier = infractionTarget.vesselIdentifier, + identityControlledPerson = infractionTarget.identityControlledPerson, + vesselType = infractionTarget.vesselType.toString(), + vesselSize = infractionTarget.vesselSize.toString(), + ) } } diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/model/mission/infraction/InfractionModel.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/model/mission/infraction/InfractionModel.kt index d5686bc0..afb38af8 100644 --- a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/model/mission/infraction/InfractionModel.kt +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/model/mission/infraction/InfractionModel.kt @@ -69,21 +69,20 @@ class InfractionModel( } companion object { - fun fromInfractionEntity(infraction: InfractionEntity) = InfractionModel( - id = infraction.id, - missionId = infraction.missionId, - actionId = infraction.actionId, - controlType = infraction.controlType.toString(), - infractionType = infraction.infractionType?.toString(), - natinfs = infraction.natinfs, - observations = infraction.observations, - target = infraction.target?.let { - listOf( - InfractionEnvTargetModel.fromInfractionEnvTargetEntity( - infraction.target!! - ) - ) - } - ) + fun fromInfractionEntity(infraction: InfractionEntity): InfractionModel { + return InfractionModel( + id = infraction.id, + missionId = infraction.missionId, + actionId = infraction.actionId, + controlType = infraction.controlType.toString(), + infractionType = infraction.infractionType?.toString(), + natinfs = infraction.natinfs, + observations = infraction.observations, + target = infraction.target?.let { + listOf(InfractionEnvTargetModel.fromInfractionEnvTargetEntity(it)) + } ?: emptyList() // Provide an empty list if target is null + ) + } + } } diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/repositories/interfaces/mission/infraction/IDBInfractionEnvTargetRepository.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/repositories/interfaces/mission/infraction/IDBInfractionEnvTargetRepository.kt new file mode 100644 index 00000000..e91c4245 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/repositories/interfaces/mission/infraction/IDBInfractionEnvTargetRepository.kt @@ -0,0 +1,9 @@ +package fr.gouv.dgampa.rapportnav.infrastructure.database.repositories.interfaces.mission.infraction + +import fr.gouv.dgampa.rapportnav.infrastructure.database.model.mission.infraction.InfractionEnvTargetModel +import org.springframework.data.jpa.repository.JpaRepository +import java.util.* + +interface IDBInfractionEnvTargetRepository : JpaRepository { + fun findByActionIdAndVesselIdentifier(actionId: String, vesselIdentifier: String): List +} diff --git a/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/repositories/mission/infraction/JPAInfractionEnvTargetRepository.kt b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/repositories/mission/infraction/JPAInfractionEnvTargetRepository.kt new file mode 100644 index 00000000..0fa9d53a --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/dgampa/rapportnav/infrastructure/database/repositories/mission/infraction/JPAInfractionEnvTargetRepository.kt @@ -0,0 +1,44 @@ +package fr.gouv.dgampa.rapportnav.infrastructure.database.repositories.mission.infraction + +import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEntity +import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.infraction.InfractionEnvTargetEntity +import fr.gouv.dgampa.rapportnav.domain.repositories.mission.infraction.IInfractionEnvTargetRepository +import fr.gouv.dgampa.rapportnav.infrastructure.database.model.mission.infraction.InfractionEnvTargetModel +import fr.gouv.dgampa.rapportnav.infrastructure.database.repositories.interfaces.mission.infraction.IDBInfractionEnvTargetRepository +import org.springframework.dao.InvalidDataAccessApiUsageException +import org.springframework.stereotype.Repository +import org.springframework.transaction.annotation.Transactional + + +@Repository +class JPAInfractionEnvTargetRepository( + private val dbRepo: IDBInfractionEnvTargetRepository, +) : IInfractionEnvTargetRepository { + + @Transactional + override fun save( + infractionTarget: InfractionEnvTargetEntity, + infraction: InfractionEntity + ): InfractionEnvTargetModel { + return try { + val model = InfractionEnvTargetModel.fromInfractionEnvTargetEntity(infractionTarget, infraction) + dbRepo.save(model) + } catch (e: InvalidDataAccessApiUsageException) { + throw Exception("Error saving or updating Infraction Env Target", e) + } + } + + override fun findByActionIdAndVesselIdentifier( + actionId: String, + vesselIdentifier: String + ): List { + return try { + val models = dbRepo.findByActionIdAndVesselIdentifier(actionId, vesselIdentifier) + models + } catch (e: InvalidDataAccessApiUsageException) { + throw Exception("Error findByActionIdAndVesselIdentifier Infraction Env Target", e) + } + } + + +} diff --git a/backend/src/main/resources/graphql/infraction.graphqls b/backend/src/main/resources/graphql/infraction.graphqls index 152ef611..840bcc42 100644 --- a/backend/src/main/resources/graphql/infraction.graphqls +++ b/backend/src/main/resources/graphql/infraction.graphqls @@ -37,7 +37,7 @@ type InfractionByTarget { vesselIdentifier: String vesselType: VesselType controlTypesWithInfraction: [ControlType] - targetAddedInRapportNav: Boolean + targetAddedByUnit: Boolean infractions: [Infraction] } diff --git a/frontend/src/auth/test-server.ts b/frontend/src/auth/test-server.ts index 8802fa1e..00abda01 100644 --- a/frontend/src/auth/test-server.ts +++ b/frontend/src/auth/test-server.ts @@ -5,17 +5,11 @@ import { LOGIN_ENDPOINT } from "./login.tsx"; export const loginSuccessHandler = [ http.post(LOGIN_ENDPOINT, () => { - // return new HttpResponse(null, { - // status: 202, - // }).json({ token: 'jwt' }) return HttpResponse.json({token: 'jwt'}, {status: 200}) - // return res(ctx.status(200), ctx.json({token: 'jwt'})) }) ] export const loginFailedHandler = http.post(LOGIN_ENDPOINT, (_req, res, ctx) => { - // return HttpResponse.error().json({ message: 'Login Failed' }) return HttpResponse.json({message: 'Login Failed'}, {status: 400}) - // return res(ctx.status(400), ctx.json({message: 'Login Failed'})) }) // This configures a request mocking server with the given request handlers. diff --git a/frontend/src/pam/mission/actions/action-control-env.tsx b/frontend/src/pam/mission/actions/action-control-env.tsx index 8b3948bb..4f66d77e 100644 --- a/frontend/src/pam/mission/actions/action-control-env.tsx +++ b/frontend/src/pam/mission/actions/action-control-env.tsx @@ -10,242 +10,218 @@ import { Action } from '../../../types/action-types' import { ControlType } from '../../../types/control-types' import { actionTargetTypeLabels, EnvActionControl, vehicleTypeLabels } from '../../../types/env-mission-types' import { useParams } from 'react-router-dom' -import EnvInfractionNewTarget from '../infractions/env-infraction-new-target' -import EnvInfractionExistingTarget from '../infractions/env-infraction-existing-target' +import EnvInfractionAddNewTarget from '../infractions/env-infraction-add-new-target.tsx' +import EnvInfractionExistingTargets from '../infractions/env-infraction-existing-targets.tsx' import useActionById from "./use-action-by-id.tsx"; import { extractLatLonFromMultiPoint } from "../../../utils/geometry.ts"; interface ActionControlPropsEnv { - action: Action + action: Action } const ActionControlEnv: React.FC = ({action}) => { - const {missionId, actionId} = useParams() + const {missionId, actionId} = useParams() - const { - data: envAction, - loading, - error, - } = useActionById(actionId, missionId, action.source, action.type) + const { + data: envAction, + loading, + error, + } = useActionById(actionId, missionId, action.source, action.type) - if (loading) { - return ( -
loading
- ) - } - if (error) { - return ( -
error
- ) - } - if (envAction) { - const actionData: EnvActionControl = envAction.data - return ( - - - - - - - - - Contrôles {envAction.startDateTimeUtc && `(${formatDateTimeForFrenchHumans(envAction.startDateTimeUtc)})`} - - - - - - - - {actionData?.themes[0].theme ?? 'inconnue'} - - - - - - {actionData?.themes[0].subThemes?.length - ? actionData?.themes[0].subThemes?.join(', ') - : 'inconnues'} - - - - - - - - - {true && (() => { - const [latitude, longitude] = extractLatLonFromMultiPoint(actionData?.geom); - return ( - - ); - })()} - - - {/**/} - - - - - - - - - - - - - - {actionData?.actionNumberOfControls ?? 'inconnu'} - - - - - - {!!actionData?.actionTargetType - ? actionTargetTypeLabels[actionData?.actionTargetType].libelle - : 'inconnu'} - - - - - - {!!actionData?.vehicleType ? vehicleTypeLabels[actionData?.vehicleType].libelle : 'inconnu'} - - - - - - {actionData?.observations ?? 'aucunes'} - - - + if (loading) { + return ( +
loading
+ ) + } + if (error) { + return ( +
error
+ ) + } + if (envAction) { + const actionData: EnvActionControl = envAction.data + return ( + + + + + + + + + Contrôles {envAction.startDateTimeUtc && `(${formatDateTimeForFrenchHumans(envAction.startDateTimeUtc)})`} + + + + + + + + {actionData?.themes[0].theme ?? 'inconnue'} + + + + + + {actionData?.themes[0].subThemes?.length + ? actionData?.themes[0].subThemes?.join(', ') + : 'inconnues'} + + + + + + + + + {true && (() => { + const [latitude, longitude] = extractLatLonFromMultiPoint(actionData?.geom); + return ( + + ); + })()} + + + + + + + + + + + + + {actionData?.actionNumberOfControls ?? 'inconnu'} + + + + + + {!!actionData?.actionTargetType + ? actionTargetTypeLabels[actionData?.actionTargetType].libelle + : 'inconnu'} + + + + + + {!!actionData?.vehicleType ? vehicleTypeLabels[actionData?.vehicleType].libelle : 'inconnu'} + + + + + + {actionData?.observations ?? 'aucunes'} + + + + - - - {(actionData?.controlsToComplete?.length || 0) > 0 && ( - - - - )} + + + {(actionData?.controlsToComplete?.length || 0) > 0 && ( + + + + )} - - - dont... - - - - - - - - - - - - - - - + + + dont... + + + + + + + + + + + + + + + + + + + + + + + + + - -
- - - - - - -
-
-
- ) - } +
+ ) + } - return null + return null } export default ActionControlEnv diff --git a/frontend/src/pam/mission/actions/use-action-by-id.tsx b/frontend/src/pam/mission/actions/use-action-by-id.tsx index c68ccd4c..4127e76e 100644 --- a/frontend/src/pam/mission/actions/use-action-by-id.tsx +++ b/frontend/src/pam/mission/actions/use-action-by-id.tsx @@ -154,7 +154,7 @@ export const GET_ACTION_BY_ID = gql` infractions { vesselIdentifier vesselType - targetAddedInRapportNav + targetAddedByUnit controlTypesWithInfraction infractions { id diff --git a/frontend/src/pam/mission/infractions/env-infraction-add-new-target.tsx b/frontend/src/pam/mission/infractions/env-infraction-add-new-target.tsx new file mode 100644 index 00000000..6a90c5e4 --- /dev/null +++ b/frontend/src/pam/mission/infractions/env-infraction-add-new-target.tsx @@ -0,0 +1,102 @@ +import React, { useState } from 'react' +import { Accent, Button, Icon, Size, THEME } from '@mtes-mct/monitor-ui' +import { ControlType } from '../../../types/control-types' +import { Infraction, InfractionEnvNewTarget } from '../../../types/infraction-types' +import { MUTATION_ADD_OR_UPDATE_INFRACTION_ENV } from '../queries' +import { useMutation } from '@apollo/client' +import { useParams } from 'react-router-dom' +import omit from 'lodash/omit' +import { Stack } from 'rsuite' +import EnvInfractionTargetAddedByUnitForm from './env-infraction-target-added-by-unit-form.tsx' +import { GET_MISSION_TIMELINE } from "../timeline/use-mission-timeline.tsx"; +import { GET_ACTION_BY_ID } from "../actions/use-action-by-id.tsx"; + +export interface EnvInfractionNewTargetProps { + availableControlTypesForInfraction?: ControlType[] + infractions?: Infraction[] +} + +const EnvInfractionAddNewTarget: React.FC = ({availableControlTypesForInfraction}) => { + const {missionId, actionId} = useParams() + + const [showInfractionForNewTarget, setShowInfractionForNewTarget] = useState(false) + + const [formData, setFormData] = useState(undefined) // only 1 infraction for nav and fish + + const onChangeFormField = (field: string, value: any) => { + setFormData((prevData: any) => ({...(prevData || {}), [field]: value})) + } + + const onChangeTargetFormField = (field: string, value: any) => { + setFormData((prevData: any) => ({...(prevData || {}), target: {...(prevData || {}).target, [field]: value}})) + } + + const [mutate, { + mutateData, + mutateLoading, + mutateError + }] = useMutation(MUTATION_ADD_OR_UPDATE_INFRACTION_ENV, { + refetchQueries: [GET_MISSION_TIMELINE, GET_ACTION_BY_ID] + }) + + const onSubmit = async (e: React.FormEvent, infraction?: Infraction) => { + e.preventDefault() + const mutationData = { + ...omit(infraction, '__typename', 'target'), + id: infraction?.id, + missionId, + actionId, + // controlType: infraction?.controlType, + vesselType: infraction?.target?.vesselType, + vesselSize: infraction?.target?.vesselSize, + vesselIdentifier: infraction?.target?.vesselIdentifier, + identityControlledPerson: infraction?.target?.identityControlledPerson + // controlId, + // controlType + } as unknown as InfractionEnvNewTarget + + await mutate({variables: {infraction: mutationData}}) + setShowInfractionForNewTarget(false) + } + + return ( + <> + {showInfractionForNewTarget ? ( +
+
onSubmit(e, formData)}> + { + setFormData(undefined) + setShowInfractionForNewTarget(false) + }} + /> + +
+ ) : ( + + + + + + )} + + ) +} + +export default EnvInfractionAddNewTarget diff --git a/frontend/src/pam/mission/infractions/env-infraction-existing-target-form.tsx b/frontend/src/pam/mission/infractions/env-infraction-existing-target-form.tsx deleted file mode 100644 index 486964bb..00000000 --- a/frontend/src/pam/mission/infractions/env-infraction-existing-target-form.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import React from 'react' -import { Stack } from 'rsuite' -import { Checkbox, Legend, MultiRadio, Select, THEME } from '@mtes-mct/monitor-ui' -import { ControlType } from '../../../types/control-types' -import { Infraction, InfractionByTarget } from '../../../types/infraction-types' -import InfractionForm from './infraction-form' -import { - controlTitle, - getDisabledControlTypes, - vesselSizeToHumanString, - vesselTypeToHumanString -} from '../controls/utils' -import Text from '../../../ui/text' -import { formalNoticeLabels, infractionTypeLabels, transformFormatToOptions } from '../../../types/env-mission-types' -import NatinfsFullNameList from "./natinfs-fullname-list.tsx"; - -const CONTROL_TYPE_OPTIONS = [ - { - label: `Infraction - ${controlTitle(ControlType.ADMINISTRATIVE)}`, - value: ControlType.ADMINISTRATIVE - }, - { - label: `Infraction - ${controlTitle(ControlType.SECURITY)}`, - value: ControlType.SECURITY - }, - { - label: `Infraction - ${controlTitle(ControlType.NAVIGATION)}`, - value: ControlType.NAVIGATION - }, - { - label: `Infraction - ${controlTitle(ControlType.GENS_DE_MER)}`, - value: ControlType.GENS_DE_MER - } -] - -interface EnvInfractionNewTargetFormProps { - infraction?: InfractionByTarget - formData?: Infraction - availableControlTypesForInfraction?: ControlType[] - targetAddedInRapportNav?: boolean - onChange: (field: string, value: any) => void - onCancel: () => void -} - -const EnvInfractionNewTargetForm: React.FC = ({ - infraction, - formData, - availableControlTypesForInfraction, - targetAddedInRapportNav, - onChange, - onCancel - }) => { - - return ( - - - - - Immatriculation - - {formData?.target?.vesselIdentifier} - - - - Type de navire - - {vesselTypeToHumanString(formData?.target?.vesselType)} - - - - Taille du navire - - {vesselSizeToHumanString(formData?.target?.vesselSize)} - - - - - - Identité de la personne contrôlée - - {formData?.target?.identityControlledPerson} - - - { - !targetAddedInRapportNav && ( - - - - ) - } - { - !targetAddedInRapportNav && ( - - - - ) - } - - { - !targetAddedInRapportNav && ( - - NATINF - - - ) - } - - { - !targetAddedInRapportNav && ( - - - - Tribunal compétent - - {formData?.target?.relevantCourt || '--'} - - - -   - - - - - ) - } - { - !targetAddedInRapportNav && ( - - Observations - - {formData?.target?.observations ?? '--'} - - - ) - } - - Ajout d’une infraction pour cette cible - - - onChange('controlType', nextValue)} - /> - - - - - - - onChange('vesselType', nextValue)} - /> - - - - - - - onChange('vesselIdentifier', nextValue)} - /> - - - onChange('identityControlledPerson', nextValue)} - /> - - - - - - - - - - ) -} - -export default EnvInfractionNewTargetForm diff --git a/frontend/src/pam/mission/infractions/env-infraction-new-target.tsx b/frontend/src/pam/mission/infractions/env-infraction-new-target.tsx deleted file mode 100644 index cd336759..00000000 --- a/frontend/src/pam/mission/infractions/env-infraction-new-target.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import React, { useState } from 'react' -import { Accent, Button, Icon, Size, THEME } from '@mtes-mct/monitor-ui' -import { ControlType } from '../../../types/control-types' -import { Infraction, InfractionEnvNewTarget } from '../../../types/infraction-types' -import { MUTATION_ADD_OR_UPDATE_INFRACTION_ENV } from '../queries' -import { useMutation } from '@apollo/client' -import { useParams } from 'react-router-dom' -import omit from 'lodash/omit' -import { Stack } from 'rsuite' -import EnvInfractionNewTargetForm from './env-infraction-new-target-form' -import { GET_MISSION_TIMELINE } from "../timeline/use-mission-timeline.tsx"; - -export interface EnvInfractionNewTargetProps { - availableControlTypesForInfraction?: ControlType[] - infractions?: Infraction[] -} - -const EnvInfractionNewTarget: React.FC = ({availableControlTypesForInfraction}) => { - const {missionId, actionId} = useParams() - - const [showInfractionForNewTarget, setShowInfractionForNewTarget] = useState(false) - - const [formData, setFormData] = useState(undefined) // only 1 infraction for nav and fish - - const onChangeFormField = (field: string, value: any) => { - setFormData((prevData: any) => ({...prevData, [field]: value})) - } - - const [mutate, { - mutateData, - mutateLoading, - mutateError - }] = useMutation(MUTATION_ADD_OR_UPDATE_INFRACTION_ENV, { - refetchQueries: [GET_MISSION_TIMELINE] - }) - - const onSubmit = async (e: React.FormEvent, data?: InfractionEnvNewTarget) => { - e.preventDefault() - const mutationData = { - ...omit(data, '__typename'), - id: data?.id, - missionId, - actionId - // controlId, - // controlType - } - - await mutate({variables: {infraction: mutationData}}) - setShowInfractionForNewTarget(false) - } - - return ( - <> - {showInfractionForNewTarget ? ( -
-
onSubmit(e, formData)}> - { - setFormData(undefined) - setShowInfractionForNewTarget(false) - }} - /> - -
- ) : ( - - - {' '} - - - - )} - - ) -} - -export default EnvInfractionNewTarget diff --git a/frontend/src/pam/mission/infractions/env-infraction-summary.tsx b/frontend/src/pam/mission/infractions/env-infraction-summary.tsx index c2553f33..e847cf0e 100644 --- a/frontend/src/pam/mission/infractions/env-infraction-summary.tsx +++ b/frontend/src/pam/mission/infractions/env-infraction-summary.tsx @@ -8,95 +8,95 @@ import InfractionTypeTag from './infraction-type-tag.tsx' import NatinfsTag from "./natinfs-tag.tsx"; interface EnvInfractionSummaryProps { - infractionByTarget?: InfractionByTarget - onAddInfractionForTarget: (infraction?: Partial) => void - onEditInfractionForTarget: (infraction: Infraction) => void - onDeleteInfraction: (infractionId: string) => void + infractionByTarget?: InfractionByTarget + onAddInfractionForTarget: (infraction?: Partial) => void + onEditInfractionForTarget: (infraction: Infraction) => void + onDeleteInfraction: (infractionId: string) => void } const EnvInfractionSummary: React.FC = ({ - infractionByTarget, - onAddInfractionForTarget, - onEditInfractionForTarget, - onDeleteInfraction + infractionByTarget, + onAddInfractionForTarget, + onEditInfractionForTarget, + onDeleteInfraction }) => { - return ( - - - - - - {`${vesselTypeToHumanString(infractionByTarget?.vesselType)} - ${infractionByTarget?.vesselIdentifier}`} - - - - - - - - {infractionByTarget?.infractions.map((infraction: Infraction) => ( - - - - - - - {!infraction?.controlType - ? 'Infraction contrôle de l’environnement' - : controlTitle(infraction.controlType)} - - - - + return ( + + + - + + {`${vesselTypeToHumanString(infractionByTarget?.vesselType)} - ${infractionByTarget?.vesselIdentifier}`} + - + - - - - - {infraction.controlType !== null && ( - - - - onEditInfractionForTarget(infraction)} - /> - - - onDeleteInfraction(infraction.id)} - /> - - - )} - - - ))} - - ) + + {infractionByTarget?.infractions.map((infraction: Infraction) => ( + + + + + + + {!infraction?.controlType + ? 'Infraction contrôle de l’environnement' + : controlTitle(infraction.controlType)} + + + + + + + + + + + + + + + {infraction.controlType !== null && ( + + + + onEditInfractionForTarget(infraction)} + /> + + + onDeleteInfraction(infraction.id)} + /> + + + + )} + + + ))} + + ) } export default EnvInfractionSummary diff --git a/frontend/src/pam/mission/infractions/env-infraction-target-added-by-cacem-form.tsx b/frontend/src/pam/mission/infractions/env-infraction-target-added-by-cacem-form.tsx new file mode 100644 index 00000000..9ef53a08 --- /dev/null +++ b/frontend/src/pam/mission/infractions/env-infraction-target-added-by-cacem-form.tsx @@ -0,0 +1,156 @@ +import React from 'react' +import { Stack } from 'rsuite' +import { Checkbox, Legend, MultiRadio, Select, THEME } from '@mtes-mct/monitor-ui' +import { ControlType } from '../../../types/control-types' +import { Infraction, InfractionByTarget } from '../../../types/infraction-types' +import InfractionForm from './infraction-form' +import { + controlTitle, + getDisabledControlTypes, + vesselSizeToHumanString, + vesselTypeToHumanString +} from '../controls/utils' +import Text from '../../../ui/text' +import { formalNoticeLabels, infractionTypeLabels, transformFormatToOptions } from '../../../types/env-mission-types' +import NatinfsFullNameList from "./natinfs-fullname-list.tsx"; + +const CONTROL_TYPE_OPTIONS = [ + { + label: `Infraction - ${controlTitle(ControlType.ADMINISTRATIVE)}`, + value: ControlType.ADMINISTRATIVE + }, + { + label: `Infraction - ${controlTitle(ControlType.SECURITY)}`, + value: ControlType.SECURITY + }, + { + label: `Infraction - ${controlTitle(ControlType.NAVIGATION)}`, + value: ControlType.NAVIGATION + }, + { + label: `Infraction - ${controlTitle(ControlType.GENS_DE_MER)}`, + value: ControlType.GENS_DE_MER + } +] + +interface EnvInfractionNewTargetFormProps { + infraction?: InfractionByTarget + formData?: Infraction + availableControlTypesForInfraction?: ControlType[] + onChange: (field: string, value: any) => void + onCancel: () => void +} + +const EnvInfractionTargetAddedByCacemForm: React.FC = ({ + infraction, + formData, + availableControlTypesForInfraction, + onChange, + onCancel + }) => { + + return ( + + + + + Immatriculation + + {formData?.target?.vesselIdentifier} + + + + Type de navire + + {vesselTypeToHumanString(formData?.target?.vesselType)} + + + + Taille du navire + + {vesselSizeToHumanString(formData?.target?.vesselSize)} + + + + + + Identité de la personne contrôlée + + {formData?.target?.identityControlledPerson} + + + + + + + + + + NATINF + + + + + + Tribunal compétent + + {formData?.target?.relevantCourt || '--'} + + + +   + + + + + + Observations + + {formData?.target?.observations ?? '--'} + + + + Ajout d’une infraction pour cette cible + + + onChange('controlType', nextValue)} + /> + + + + + + + onChangeTarget('vesselType', nextValue)} + /> + + + + + + + onChangeTarget('vesselIdentifier', nextValue)} + /> + + + onChangeTarget('identityControlledPerson', nextValue)} + /> + + + + + + + + + + ) +} + +export default EnvInfractionTargetAddedByUnitForm diff --git a/frontend/src/pam/mission/infractions/utils.ts b/frontend/src/pam/mission/infractions/utils.ts index 0b377176..f5340444 100644 --- a/frontend/src/pam/mission/infractions/utils.ts +++ b/frontend/src/pam/mission/infractions/utils.ts @@ -1,30 +1,32 @@ import { ControlType } from '../../../types/control-types' +import { Infraction, InfractionByTarget, InfractionEnvNewTarget } from "../../../types/infraction-types.ts"; +import { VesselSizeEnum, VesselTypeEnum } from "../../../types/env-mission-types.ts"; export const infractionTitleForControlType = (controlType: ControlType): string => { - switch (controlType) { - case ControlType.ADMINISTRATIVE: - return 'Infraction administrative' - case ControlType.NAVIGATION: - return 'Infraction règles de navigation' - case ControlType.SECURITY: - return 'Infraction equipements et respect des normes de sécurité' - case ControlType.GENS_DE_MER: - return 'Infraction administrative gens de mer' - default: - return '' - } + switch (controlType) { + case ControlType.ADMINISTRATIVE: + return 'Infraction administrative' + case ControlType.NAVIGATION: + return 'Infraction règles de navigation' + case ControlType.SECURITY: + return 'Infraction equipements et respect des normes de sécurité' + case ControlType.GENS_DE_MER: + return 'Infraction administrative gens de mer' + default: + return '' + } } export const infractionButtonTitle = (controlType: ControlType): string => { - switch (controlType) { - case ControlType.ADMINISTRATIVE: - return 'Ajouter une infraction administrative' - case ControlType.NAVIGATION: - return 'Ajouter une infraction règle de navigation' - case ControlType.SECURITY: - return 'Ajouter une infraction sécurité' - case ControlType.GENS_DE_MER: - return 'Ajouter une infraction administrative' - default: - return '' - } + switch (controlType) { + case ControlType.ADMINISTRATIVE: + return 'Ajouter une infraction administrative' + case ControlType.NAVIGATION: + return 'Ajouter une infraction règle de navigation' + case ControlType.SECURITY: + return 'Ajouter une infraction sécurité' + case ControlType.GENS_DE_MER: + return 'Ajouter une infraction administrative' + default: + return '' + } } diff --git a/frontend/src/pam/mission/page-footer.tsx b/frontend/src/pam/mission/page-footer.tsx index dd8380a4..6290ef0b 100644 --- a/frontend/src/pam/mission/page-footer.tsx +++ b/frontend/src/pam/mission/page-footer.tsx @@ -14,49 +14,49 @@ const StyledFooter = styled.div` ` interface MissionPageFooterProps { - missionName: string - exitMission: () => void + missionName: string + exitMission: () => void } const MissionPageFooter: React.FC = ({missionName, exitMission}) => { - const deleteMission = () => { - // TODO add delete - alert('Fonctionnalité pas encore implémentée') - exitMission() - } + const deleteMission = () => { + // TODO add delete + alert('Fonctionnalité pas encore implémentée') + exitMission() + } - return ( - - - - - - - - RapportNav - Version test #0 -Janvier 2024 - - - - - - - - ) + return ( + + + + + + + + RapportNav - Version test - Janvier 2024 + + + + + + + + ) } export default MissionPageFooter diff --git a/frontend/src/pam/mission/queries.ts b/frontend/src/pam/mission/queries.ts index d85dec08..6c0bf4cf 100644 --- a/frontend/src/pam/mission/queries.ts +++ b/frontend/src/pam/mission/queries.ts @@ -142,7 +142,7 @@ export const GET_MISSION_BY_ID = gql` infractions { vesselIdentifier vesselType - targetAddedInRapportNav + targetAddedByUnit controlTypesWithInfraction infractions { id diff --git a/frontend/src/pam/mission/timeline/timeline-item.tsx b/frontend/src/pam/mission/timeline/timeline-item.tsx index e9fa7235..7971a0d0 100644 --- a/frontend/src/pam/mission/timeline/timeline-item.tsx +++ b/frontend/src/pam/mission/timeline/timeline-item.tsx @@ -1,10 +1,10 @@ import React from 'react' import { Accent, Icon, Tag, THEME } from '@mtes-mct/monitor-ui' import { - actionTargetTypeLabels, - ActionTypeEnum, - EnvActionControl, - MissionSourceEnum + actionTargetTypeLabels, + ActionTypeEnum, + EnvActionControl, + MissionSourceEnum } from '../../../types/env-mission-types' import { FlexboxGrid, Stack } from 'rsuite' import { Action, ActionControl, ActionStatus as NavActionStatus } from '../../../types/action-types' @@ -18,322 +18,324 @@ import { useParams } from 'react-router-dom' import { vesselNameOrUnknown } from "../actions/utils.ts"; interface MissionTimelineItemProps { - action: Action - onClick: (action: Action) => void + action: Action + onClick: (action: Action) => void } const Wrapper: React.FC<{ onClick: any; children: any; borderWhenSelected?: boolean }> = ({ - onClick, - children, - borderWhenSelected = null + onClick, + children, + borderWhenSelected = null }) => { - return ( -
- - {children} - -
- ) + return ( +
+ + {children} + +
+ ) } const ActionEnvControl: React.FC<{ action: Action; onClick: any }> = ({action, onClick}) => { - const {actionId} = useParams() - const actionData = action.data as unknown as EnvActionControl - return ( - - - - - - - - - - - - - Contrôle - - - - - {actionData && 'themes' in actionData && actionData?.themes[0].theme ? actionData?.themes[0].theme : ''} - - - - - - - - {actionData && 'actionNumberOfControls' in actionData && actionData.actionNumberOfControls - ? `${actionData.actionNumberOfControls} ${ - actionData.actionNumberOfControls > 1 ? 'contrôles' : 'contrôle' - }` - : 'Nombre de contrôles inconnu'} - -   - {actionData && - 'actionNumberOfControls' in actionData && - actionData.actionNumberOfControls && - actionData.actionNumberOfControls > 1 - ? 'réalisés' - : 'réalisé'}{' '} - sur des cibles de type  - - {actionData && 'actionTargetType' in actionData && actionData.actionTargetType - ? actionTargetTypeLabels[actionData.actionTargetType]?.libelle?.toLowerCase() - : 'inconnu'} - - - + const {actionId} = useParams() + const actionData = action.data as unknown as EnvActionControl + return ( + + + + + + + + + + + + + Contrôle + + + + + {actionData && 'themes' in actionData && actionData?.themes[0].theme ? actionData?.themes[0].theme : ''} + + + + + + + + {actionData && 'actionNumberOfControls' in actionData && actionData.actionNumberOfControls + ? `${actionData.actionNumberOfControls} ${ + actionData.actionNumberOfControls > 1 ? 'contrôles' : 'contrôle' + }` + : 'Nombre de contrôles inconnu'} + +   + {actionData && + 'actionNumberOfControls' in actionData && + actionData.actionNumberOfControls && + actionData.actionNumberOfControls > 1 + ? 'réalisés' + : 'réalisé'}{' '} + sur des cibles de type  + + {actionData && 'actionTargetType' in actionData && actionData.actionTargetType + ? actionTargetTypeLabels[actionData.actionTargetType]?.libelle?.toLowerCase() + : 'inconnu'} + + + - - - - {actionData?.controlsToComplete !== undefined && - actionData?.controlsToComplete?.length > 0 ? ( - - ) : ( - <> - { - action.summaryTags?.map((tag: string) => ( - {tag} - )) - } - - )} - - - - - - ajouté par CACEM - - - - + + + + {actionData?.controlsToComplete !== undefined && + actionData?.controlsToComplete?.length > 0 ? ( + + ) : ( + <> + { + action.summaryTags?.map((tag: string) => ( + {tag} + )) + } + + )} + + + + + + ajouté par CACEM + + + + + + + + - - - - - - - ) + + + ) } const ActionFishControl: React.FC<{ action: Action; onClick: any }> = ({action, onClick}) => { - const {actionId} = useParams() - const actionData = action.data as unknown as FishAction - return ( - - - - - - - - - - - {formatMissionActionTypeForHumans(actionData?.actionType)} - {vesselNameOrUnknown(actionData?.vesselName)} - - + const {actionId} = useParams() + const actionData = action.data as unknown as FishAction + return ( + + + + + + + + + + + {formatMissionActionTypeForHumans(actionData?.actionType)} - {vesselNameOrUnknown(actionData?.vesselName)} + + - - - - {actionData?.controlsToComplete !== undefined && - actionData?.controlsToComplete?.length > 0 ? ( - - ) : ( - <> - { - action.summaryTags?.map((tag: string) => ( - {tag} - )) - } - - )} - - - - - - ajouté par CNSP - - - - + + + + {actionData?.controlsToComplete !== undefined && + actionData?.controlsToComplete?.length > 0 ? ( + + ) : ( + <> + { + action.summaryTags?.map((tag: string) => ( + {tag} + )) + } + + )} + + + + + + ajouté par CNSP + + + + + + + + - - - - - - - ) + + + ) } const ActionNavControl: React.FC<{ action: Action; onClick: any }> = ({action, onClick}) => { - const {actionId} = useParams() - const actionData = action.data as unknown as ActionControl - return ( - - + const {actionId} = useParams() + const actionData = action.data as unknown as ActionControl + return ( + + - - - - - - - - - - Contrôles {`${controlMethodToHumanString(actionData?.controlMethod)} - ${vesselTypeToHumanString( - actionData?.vesselType - )}`} - - - - - { - action.summaryTags?.length > 0 && ( - - { - action.summaryTags?.map((tag: string) => ( - {tag} - )) - } - - ) - } - - + + + + + + + + + + Contrôles {`${controlMethodToHumanString(actionData?.controlMethod)} - ${vesselTypeToHumanString( + actionData?.vesselType + )}`} + + + + + { + action.summaryTags?.length > 0 && ( + + { + action.summaryTags?.map((tag: string) => ( + {tag} + )) + } + + ) + } + + - - - - ) +
+ + + ) } const ActionSurveillance: React.FC = () => { - // Implementation for ActionSurveillance - return null + // Implementation for ActionSurveillance + return null } const ActionNote: React.FC = () => { - // Implementation for ActionNote - return null + // Implementation for ActionNote + return null } const ActionOther: React.FC = () => { - // Implementation for ActionOther - return null + // Implementation for ActionOther + return null } const ActionStatus: React.FC<{ action: Action; onClick: any }> = ({action, onClick}) => { - const {actionId} = useParams() - const isSelected = action.id === actionId - const actionData = action.data as unknown as NavActionStatus - return ( - - - - - - - -

- {`${mapStatusToText(actionData?.status)} - ${actionData?.isStart ? 'début' : 'fin'} ${ - !!actionData?.reason ? ' - ' + statusReasonToHumanString(actionData?.reason) : '' - }`} - {!!actionData?.observations ? ' - ' + actionData?.observations : ''} -

-
-
- - - -
-
- ) + const {actionId} = useParams() + const isSelected = action.id === actionId + const actionData = action.data as unknown as NavActionStatus + return ( + + + + + + + +

+ {`${mapStatusToText(actionData?.status)} - ${actionData?.isStart ? 'début' : 'fin'} ${ + !!actionData?.reason ? ' - ' + statusReasonToHumanString(actionData?.reason) : '' + }`} + {!!actionData?.observations ? ' - ' + actionData?.observations : ''} +

+
+
+ + + +
+
+ ) } const ActionContact: React.FC = () => { - // Implementation for ActionContact - return null + // Implementation for ActionContact + return null } const getActionComponent = (action: Action) => { - if (action.source === MissionSourceEnum.MONITORENV) { - if (action.type === ActionTypeEnum.CONTROL) { - return ActionEnvControl - } - } else if (action.source === MissionSourceEnum.MONITORFISH) { - if (action.type === ActionTypeEnum.CONTROL) { - return ActionFishControl + if (action.source === MissionSourceEnum.MONITORENV) { + if (action.type === ActionTypeEnum.CONTROL) { + return ActionEnvControl + } + } else if (action.source === MissionSourceEnum.MONITORFISH) { + if (action.type === ActionTypeEnum.CONTROL) { + return ActionFishControl + } + } else if (action.source === MissionSourceEnum.RAPPORTNAV) { + switch (action.type) { + case ActionTypeEnum.CONTROL: + return ActionNavControl + case ActionTypeEnum.STATUS: + return ActionStatus + default: + return null + } } - } else if (action.source === MissionSourceEnum.RAPPORTNAV) { - switch (action.type) { - case ActionTypeEnum.CONTROL: - return ActionNavControl - case ActionTypeEnum.STATUS: - return ActionStatus - default: - return null - } - } - return null + return null } const MissionTimelineItem: React.FC = ({ - action, - onClick - // componentMap = ActionComponentMap + action, + onClick + // componentMap = ActionComponentMap }) => { - const Component = getActionComponent(action) - // const Component = componentMap[action.actionType] + const Component = getActionComponent(action) + // const Component = componentMap[action.actionType] - if (!Component) { - return null - } + if (!Component) { + return null + } - return + return } export default MissionTimelineItem diff --git a/frontend/src/types/infraction-types.ts b/frontend/src/types/infraction-types.ts index 6d29233b..56b65402 100644 --- a/frontend/src/types/infraction-types.ts +++ b/frontend/src/types/infraction-types.ts @@ -30,7 +30,7 @@ export type InfractionByTarget = { vesselType: VesselTypeEnum infractions: Infraction[] controlTypesWithInfraction?: ControlType[] - targetAddedInRapportNav?: boolean + targetAddedByUnit?: boolean } export type InfractionEnvNewTarget = Infraction & { From 5b229090a0ab55a38cf651dfa7cf3610b2e09151 Mon Sep 17 00:00:00 2001 From: lwih Date: Thu, 28 Dec 2023 18:38:01 +0100 Subject: [PATCH 10/11] Lint frontend --- .../mission/actions/action-control-nav.tsx | 492 +++++++++--------- .../mission/actions/action-status-form.tsx | 324 ++++++------ .../pam/mission/controls/env-control-form.tsx | 224 ++++---- .../src/pam/mission/crew/mission-crew.tsx | 332 ++++++------ .../env-infraction-add-new-target.tsx | 6 +- .../env-infraction-existing-targets.tsx | 2 +- .../infractions/infraction-for-control.tsx | 150 +++--- frontend/src/pam/mission/infractions/utils.ts | 4 +- .../src/pam/mission/mission-component.tsx | 320 ++++++------ .../pam/mission/timeline/timeline-item.tsx | 4 +- frontend/src/pam/missions/missions.tsx | 94 ++-- frontend/src/ui/text.tsx | 60 +-- 12 files changed, 1003 insertions(+), 1009 deletions(-) diff --git a/frontend/src/pam/mission/actions/action-control-nav.tsx b/frontend/src/pam/mission/actions/action-control-nav.tsx index d7776154..8801ae73 100644 --- a/frontend/src/pam/mission/actions/action-control-nav.tsx +++ b/frontend/src/pam/mission/actions/action-control-nav.tsx @@ -1,20 +1,20 @@ import React, { useEffect, useState } from 'react' import { - Accent, - Button, - Coordinates, - CoordinatesFormat, - CoordinatesInput, - DateRange, - DateRangePicker, - Icon, - Label, - OptionValue, - Select, - Size, - Textarea, - TextInput, - THEME + Accent, + Button, + Coordinates, + CoordinatesFormat, + CoordinatesInput, + DateRange, + DateRangePicker, + Icon, + Label, + OptionValue, + Select, + Size, + Textarea, + TextInput, + THEME } from '@mtes-mct/monitor-ui' import { VesselTypeEnum } from '../../../types/mission-types' import { Action, ActionControl } from '../../../types/action-types' @@ -34,266 +34,266 @@ import { GET_MISSION_TIMELINE } from "../timeline/use-mission-timeline.tsx"; import useActionById from "./use-action-by-id.tsx"; interface ActionControlNavProps { - action: Action + action: Action } const ActionControlNav: React.FC = ({action}) => { - const navigate = useNavigate() - const {missionId, actionId} = useParams() - const [observationsValue, setObservationsValue] = useState( - undefined - ) - const [identityControlledPersonValue, setIdentityControlledPersonValue] = useState( - undefined - ) - - const [mutateControl] = useMutation( - MUTATION_ADD_OR_UPDATE_ACTION_CONTROL, - { - refetchQueries: [GET_MISSION_TIMELINE] - } - ) - const [deleteControl] = useMutation(DELETE_ACTION_CONTROL, { - refetchQueries: [GET_MISSION_TIMELINE] - }) - - const {data: navAction, loading, error} = useActionById(actionId, missionId, action.source, action.type) - - useEffect(() => { - setObservationsValue(navAction?.data.observations) - setIdentityControlledPersonValue(navAction?.data.identityControlledPerson) - }, [navAction]) - - - if (loading) { - return ( -
loading
+ const navigate = useNavigate() + const {missionId, actionId} = useParams() + const [observationsValue, setObservationsValue] = useState( + undefined ) - } - if (error) { - return ( -
error
+ const [identityControlledPersonValue, setIdentityControlledPersonValue] = useState( + undefined ) - } - if (navAction) { - const control = navAction?.data as ActionControl + const [mutateControl] = useMutation( + MUTATION_ADD_OR_UPDATE_ACTION_CONTROL, + { + refetchQueries: [GET_MISSION_TIMELINE] + } + ) + const [deleteControl] = useMutation(DELETE_ACTION_CONTROL, { + refetchQueries: [GET_MISSION_TIMELINE] + }) - const handleObservationsChange = (nextValue?: string) => { - setObservationsValue(nextValue) - } - const handleObservationsBlur = () => { - onChange('observations', observationsValue) - } + const {data: navAction, loading, error} = useActionById(actionId, missionId, action.source, action.type) - const handleIdentityControlledPersonChange = (nextValue?: string) => { - setIdentityControlledPersonValue(nextValue) + useEffect(() => { + setObservationsValue(navAction?.data.observations) + setIdentityControlledPersonValue(navAction?.data.identityControlledPerson) + }, [navAction]) + + + if (loading) { + return ( +
loading
+ ) } - const handleIdentityControlledPersonBlur = () => { - onChange('identityControlledPerson', identityControlledPersonValue) + if (error) { + return ( +
error
+ ) } + if (navAction) { + const control = navAction?.data as ActionControl - const onChange = (field: string, value: any) => { - let updatedField = {} - if (field === 'dates') { - debugger - const startDateTimeUtc = value[0].toISOString() - const endDateTimeUtc = value[1].toISOString() - updatedField = { - startDateTimeUtc, - endDateTimeUtc + const handleObservationsChange = (nextValue?: string) => { + setObservationsValue(nextValue) } - } else if (field === 'geom') { - updatedField = { - latitude: value[0], - longitude: value[1] + const handleObservationsBlur = () => { + onChange('observations', observationsValue) } - } else { - updatedField = { - [field]: value + + const handleIdentityControlledPersonChange = (nextValue?: string) => { + setIdentityControlledPersonValue(nextValue) + } + const handleIdentityControlledPersonBlur = () => { + onChange('identityControlledPerson', identityControlledPersonValue) } - } - const updatedData = { - missionId: missionId, - ...omit(control, [ - '__typename', - 'controlAdministrative', - 'controlGensDeMer', - 'controlNavigation', - 'controlSecurity' - ]), - startDateTimeUtc: action.startDateTimeUtc, - endDateTimeUtc: action.endDateTimeUtc, - ...updatedField - } - mutateControl({variables: {controlAction: updatedData}}) - } + const onChange = (field: string, value: any) => { + let updatedField = {} + if (field === 'dates') { + debugger + const startDateTimeUtc = value[0].toISOString() + const endDateTimeUtc = value[1].toISOString() + updatedField = { + startDateTimeUtc, + endDateTimeUtc + } + } else if (field === 'geom') { + updatedField = { + latitude: value[0], + longitude: value[1] + } + } else { + updatedField = { + [field]: value + } + } + + const updatedData = { + missionId: missionId, + ...omit(control, [ + '__typename', + 'controlAdministrative', + 'controlGensDeMer', + 'controlNavigation', + 'controlSecurity' + ]), + startDateTimeUtc: action.startDateTimeUtc, + endDateTimeUtc: action.endDateTimeUtc, + ...updatedField + } - const deleteAction = () => { - deleteControl({ - variables: { - id: action.id! + mutateControl({variables: {controlAction: updatedData}}) } - }) - navigate(`/pam/missions/${missionId}`) - } + const deleteAction = () => { + deleteControl({ + variables: { + id: action.id! + } + }) + navigate(`/pam/missions/${missionId}`) + } - return ( - - {/* TITLE AND BUTTONS */} - - - - - - - - - - Contrôles {action.startDateTimeUtc && `(${formatDateTimeForFrenchHumans(action.startDateTimeUtc)})`} - + + return ( + + {/* TITLE AND BUTTONS */} + + + + + + + + + + Contrôles {action.startDateTimeUtc && `(${formatDateTimeForFrenchHumans(action.startDateTimeUtc)})`} + + + + + {controlMethodToHumanString(control.controlMethod)} - {vesselTypeToHumanString(control.vesselType)} + + + + + + + + + + + + + + + + {/* INFO TEXT */} - - {controlMethodToHumanString(control.controlMethod)} - {vesselTypeToHumanString(control.vesselType)} - + + + + + + + Pour la saisie des contrôles de la pêche et de l’environnement marin, veuillez appeler + les + centres + concernés. +
+ Pêche : CNSP / Environnement Marin : CACEM +
+
+
-
-
- - + {/* DATE FIELDS */} - + { + onChange('dates', nextUtcDateRange) + }} + /> + {/* CONTROL ZONES FIELD */} - + onChange('geom', nextCoordinates)} + /> - - -
-
- {/* INFO TEXT */} - - - - - - - - Pour la saisie des contrôles de la pêche et de l’environnement marin, veuillez appeler - les - centres - concernés. -
- Pêche : CNSP / Environnement Marin : CACEM -
-
-
-
- {/* DATE FIELDS */} - - { - onChange('dates', nextUtcDateRange) - }} - /> - - {/* CONTROL ZONES FIELD */} - - onChange('geom', nextCoordinates)} - /> - - {/* VESSEL INFORMATION */} - - - -