diff --git a/backend/geonature/core/gn_monitoring/models.py b/backend/geonature/core/gn_monitoring/models.py
index b764fa6a00..6ba3a45ca7 100644
--- a/backend/geonature/core/gn_monitoring/models.py
+++ b/backend/geonature/core/gn_monitoring/models.py
@@ -7,7 +7,7 @@
from geoalchemy2 import Geometry
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
-from sqlalchemy.dialects.postgresql import UUID
+from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.sql import select, func
@@ -16,12 +16,13 @@
from utils_flask_sqla.serializers import serializable
from utils_flask_sqla_geo.serializers import geoserializable
+from pypnnomenclature.models import TNomenclatures
from geonature.core.gn_commons.models import TModules
from geonature.core.gn_meta.models import TDatasets
from geonature.utils.env import DB
-corVisitObserver = DB.Table(
+cor_visit_observer = DB.Table(
"cor_visit_observer",
DB.Column(
"id_base_visit",
@@ -39,7 +40,7 @@
)
-corSiteModule = DB.Table(
+cor_site_module = DB.Table(
"cor_site_module",
DB.Column(
"id_base_site",
@@ -56,7 +57,7 @@
schema="gn_monitoring",
)
-corSiteArea = DB.Table(
+cor_site_area = DB.Table(
"cor_site_area",
DB.Column(
"id_base_site",
@@ -68,6 +69,58 @@
schema="gn_monitoring",
)
+cor_module_type = DB.Table(
+ "cor_module_type",
+ DB.Column(
+ "id_module",
+ DB.Integer,
+ DB.ForeignKey("gn_commons.t_modules.id_module"),
+ primary_key=True,
+ ),
+ DB.Column(
+ "id_type_site",
+ DB.Integer,
+ DB.ForeignKey("gn_monitoring.bib_type_site.id_nomenclature_type_site"),
+ primary_key=True,
+ ),
+ schema="gn_monitoring",
+)
+
+cor_site_type = DB.Table(
+ "cor_site_type",
+ DB.Column(
+ "id_base_site",
+ DB.Integer,
+ DB.ForeignKey("gn_monitoring.t_base_sites.id_base_site"),
+ primary_key=True,
+ ),
+ DB.Column(
+ "id_type_site",
+ DB.Integer,
+ DB.ForeignKey("gn_monitoring.bib_type_site.id_nomenclature_type_site"),
+ primary_key=True,
+ ),
+ schema="gn_monitoring",
+)
+
+
+@serializable
+class BibTypeSite(DB.Model):
+ __tablename__ = "bib_type_site"
+ __table_args__ = {"schema": "gn_monitoring"}
+
+ id_nomenclature_type_site = DB.Column(
+ DB.ForeignKey("ref_nomenclatures.t_nomenclatures.id_nomenclature"),
+ nullable=False,
+ primary_key=True,
+ )
+ config = DB.Column(JSONB)
+ nomenclature = DB.relationship(
+ TNomenclatures, uselist=False, backref=DB.backref("bib_type_site", uselist=False)
+ )
+
+ sites = DB.relationship("TBaseSites", secondary=cor_site_type, lazy="noload")
+
@serializable
class TBaseVisits(DB.Model):
@@ -84,7 +137,7 @@ class TBaseVisits(DB.Model):
# Pour le moment non défini comme une clé étrangère
# pour les questions de perfs
# a voir en fonction des usage
- id_module = DB.Column(DB.Integer)
+ id_module = DB.Column(DB.Integer, ForeignKey("gn_commons.t_modules.id_module"))
visit_date_min = DB.Column(DB.DateTime)
visit_date_max = DB.Column(DB.DateTime)
@@ -102,15 +155,16 @@ class TBaseVisits(DB.Model):
observers = DB.relationship(
User,
- secondary=corVisitObserver,
- primaryjoin=(corVisitObserver.c.id_base_visit == id_base_visit),
- secondaryjoin=(corVisitObserver.c.id_role == User.id_role),
- foreign_keys=[corVisitObserver.c.id_base_visit, corVisitObserver.c.id_role],
+ secondary=cor_visit_observer,
+ primaryjoin=(cor_visit_observer.c.id_base_visit == id_base_visit),
+ secondaryjoin=(cor_visit_observer.c.id_role == User.id_role),
+ foreign_keys=[cor_visit_observer.c.id_base_visit, cor_visit_observer.c.id_role],
)
+ observers_txt = DB.Column(DB.Unicode)
+
dataset = relationship(
TDatasets,
- lazy="joined",
primaryjoin=(TDatasets.id_dataset == id_dataset),
foreign_keys=[id_dataset],
)
@@ -128,7 +182,6 @@ class TBaseSites(DB.Model):
id_base_site = DB.Column(DB.Integer, primary_key=True)
id_inventor = DB.Column(DB.Integer, ForeignKey("utilisateurs.t_roles.id_role"))
id_digitiser = DB.Column(DB.Integer, ForeignKey("utilisateurs.t_roles.id_role"))
- id_nomenclature_type_site = DB.Column(DB.Integer)
base_site_name = DB.Column(DB.Unicode)
base_site_description = DB.Column(DB.Unicode)
base_site_code = DB.Column(DB.Unicode)
@@ -153,8 +206,23 @@ class TBaseSites(DB.Model):
"TModules",
lazy="select",
enable_typechecks=False,
- secondary=corSiteModule,
- primaryjoin=(corSiteModule.c.id_base_site == id_base_site),
- secondaryjoin=(corSiteModule.c.id_module == TModules.id_module),
- foreign_keys=[corSiteModule.c.id_base_site, corSiteModule.c.id_module],
+ secondary=cor_site_module,
+ primaryjoin=(cor_site_module.c.id_base_site == id_base_site),
+ secondaryjoin=(cor_site_module.c.id_module == TModules.id_module),
+ foreign_keys=[cor_site_module.c.id_base_site, cor_site_module.c.id_module],
+ )
+
+
+@serializable
+class TObservations(DB.Model):
+ __tablename__ = "t_observations"
+ __table_args__ = {"schema": "gn_monitoring"}
+ id_observation = DB.Column(DB.Integer, primary_key=True, nullable=False, unique=True)
+ id_base_visit = DB.Column(DB.ForeignKey("gn_monitoring.t_base_visits.id_base_visit"))
+ id_digitiser = DB.Column(DB.Integer, DB.ForeignKey("utilisateurs.t_roles.id_role"))
+ digitiser = DB.relationship(
+ User, primaryjoin=(User.id_role == id_digitiser), foreign_keys=[id_digitiser]
)
+ cd_nom = DB.Column(DB.Integer)
+ comments = DB.Column(DB.String)
+ uuid_observation = DB.Column(UUID(as_uuid=True), default=select(func.uuid_generate_v4()))
diff --git a/backend/geonature/core/gn_monitoring/routes.py b/backend/geonature/core/gn_monitoring/routes.py
index 0ad5889009..245ed06047 100644
--- a/backend/geonature/core/gn_monitoring/routes.py
+++ b/backend/geonature/core/gn_monitoring/routes.py
@@ -1,6 +1,6 @@
from flask import Blueprint, request
from geojson import FeatureCollection
-from geonature.core.gn_monitoring.models import TBaseSites, corSiteArea, corSiteModule
+from geonature.core.gn_monitoring.models import TBaseSites, cor_site_area, cor_site_module
from geonature.utils.env import DB
from ref_geo.models import LAreas
from sqlalchemy import select
@@ -79,17 +79,16 @@ def get_site_areas(id_site):
params = request.args
query = (
- # TODO@LAreas.geom_4326
- select(corSiteArea, func.ST_Transform(LAreas.geom, 4326))
- .join(LAreas, LAreas.id_area == corSiteArea.c.id_area)
- .where(corSiteArea.c.id_base_site == id_site)
+ select(cor_site_area, func.ST_Transform(LAreas.geom, 4326))
+ .join(LAreas, LAreas.id_area == cor_site_area.c.id_area)
+ .where(cor_site_area.c.id_base_site == id_site)
)
if "id_area_type" in params:
query = query.where(LAreas.id_type == params["id_area_type"])
if "id_module" in params:
- query = query.join(corSiteModule, corSiteModule.c.id_base_site == id_site).where(
- corSiteModule.c.id_module == params["id_module"]
+ query = query.join(cor_site_module, cor_site_module.c.id_base_site == id_site).where(
+ cor_site_module.c.id_module == params["id_module"]
)
data = DB.session.scalars(query).all()
diff --git a/backend/geonature/migrations/versions/6734d8f7eb2a_monitoring_add_id_digitizer_to_t_observations.py b/backend/geonature/migrations/versions/6734d8f7eb2a_monitoring_add_id_digitizer_to_t_observations.py
new file mode 100644
index 0000000000..f17add3506
--- /dev/null
+++ b/backend/geonature/migrations/versions/6734d8f7eb2a_monitoring_add_id_digitizer_to_t_observations.py
@@ -0,0 +1,67 @@
+"""[monitoring] add id_digitizer to t_observations
+
+Revision ID: 6734d8f7eb2a
+Revises: 9b88459c1298
+Create Date: 2024-01-16 15:50:30.308266
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "6734d8f7eb2a"
+down_revision = "9b88459c1298"
+branch_labels = None
+depends_on = None
+
+
+monitorings_schema = "gn_monitoring"
+table = "t_observations"
+column = "id_digitiser"
+
+foreign_schema = "utilisateurs"
+table_foreign = "t_roles"
+foreign_key = "id_role"
+
+
+def upgrade():
+ op.add_column(
+ table,
+ sa.Column(
+ column,
+ sa.Integer(),
+ sa.ForeignKey(
+ f"{foreign_schema}.{table_foreign}.{foreign_key}",
+ name=f"fk_{table}_{column}",
+ onupdate="CASCADE",
+ ),
+ ),
+ schema=monitorings_schema,
+ )
+ op.execute(
+ """
+ UPDATE gn_monitoring.t_observations o SET id_digitiser = tbv.id_digitiser
+ FROM gn_monitoring.t_base_visits AS tbv
+ WHERE tbv.id_base_visit = o.id_base_visit;
+ """
+ )
+ # Set not null constraint
+ op.alter_column(
+ table_name=table,
+ column_name=column,
+ existing_type=sa.Integer(),
+ nullable=False,
+ schema=monitorings_schema,
+ )
+
+
+def downgrade():
+ statement = sa.text(
+ f"""
+ ALTER TABLE {monitorings_schema}.{table} DROP CONSTRAINT fk_{table}_{column};
+ """
+ )
+ op.execute(statement)
+ op.drop_column(table, column, schema=monitorings_schema)
diff --git a/backend/geonature/migrations/versions/8309591841f3_monitoring_add_observers_txt_column_t_base_visit.py b/backend/geonature/migrations/versions/8309591841f3_monitoring_add_observers_txt_column_t_base_visit.py
new file mode 100644
index 0000000000..9ffe7de1de
--- /dev/null
+++ b/backend/geonature/migrations/versions/8309591841f3_monitoring_add_observers_txt_column_t_base_visit.py
@@ -0,0 +1,38 @@
+"""[monitoring] add_observers_txt_column_t_base_visit
+
+Revision ID: 8309591841f3
+Revises: 7b6a578eccd7
+Create Date: 2023-10-06 11:07:43.532623
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "8309591841f3"
+down_revision = "7b6a578eccd7"
+branch_labels = None
+depends_on = None
+
+
+monitorings_schema = "gn_monitoring"
+table = "t_base_visits"
+column = "observers_txt"
+
+
+def upgrade():
+ op.add_column(
+ table,
+ sa.Column(
+ column,
+ sa.Text(),
+ nullable=True,
+ ),
+ schema=monitorings_schema,
+ )
+
+
+def downgrade():
+ op.drop_column(table, column, schema=monitorings_schema)
diff --git a/backend/geonature/migrations/versions/9b88459c1298_monitoring_create_t_observations.py b/backend/geonature/migrations/versions/9b88459c1298_monitoring_create_t_observations.py
new file mode 100644
index 0000000000..7e5b55d11b
--- /dev/null
+++ b/backend/geonature/migrations/versions/9b88459c1298_monitoring_create_t_observations.py
@@ -0,0 +1,55 @@
+"""[monitoring] create t_observations
+
+Revision ID: 9b88459c1298
+Revises: a54bafb13ce8
+Create Date: 2024-01-16 15:41:13.331912
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "9b88459c1298"
+down_revision = "a54bafb13ce8"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.execute(
+ """
+ CREATE TABLE IF NOT EXISTS gn_monitoring.t_observations (
+ id_observation SERIAL NOT NULL,
+ id_base_visit INTEGER NOT NULL,
+ cd_nom INTEGER NOT NULL,
+ comments TEXT,
+ uuid_observation UUID DEFAULT uuid_generate_v4() NOT NULL,
+
+
+ CONSTRAINT pk_t_observations PRIMARY KEY (id_observation),
+ CONSTRAINT fk_t_observations_id_base_visit FOREIGN KEY (id_base_visit)
+ REFERENCES gn_monitoring.t_base_visits (id_base_visit) MATCH SIMPLE
+ ON UPDATE CASCADE ON DELETE CASCADE
+ );
+ """
+ )
+ op.execute(
+ """
+ INSERT INTO gn_commons.bib_tables_location(table_desc, schema_name, table_name, pk_field, uuid_field_name)
+ VALUES
+ ('Table centralisant les observations réalisées lors d''une visite sur un site', 'gn_monitoring', 't_observations', 'id_observation', 'uuid_observation')
+ ON CONFLICT(schema_name, table_name) DO NOTHING;
+ """
+ )
+
+
+def downgrade():
+ op.execute(
+ """
+ DELETE FROM gn_commons.bib_tables_location
+ WHERE schema_name = 'gn_monitoring' AND table_name = 't_observations';
+ """
+ )
+ op.drop_table("t_observations", schema="gn_monitoring")
diff --git a/backend/geonature/migrations/versions/a54bafb13ce8_monitoring_create_cor_module_type.py b/backend/geonature/migrations/versions/a54bafb13ce8_monitoring_create_cor_module_type.py
new file mode 100644
index 0000000000..3c867d9526
--- /dev/null
+++ b/backend/geonature/migrations/versions/a54bafb13ce8_monitoring_create_cor_module_type.py
@@ -0,0 +1,64 @@
+""" [monitoring] create_cor_module_type
+
+Revision ID: a54bafb13ce8
+Revises: ce54ba49ce5c
+Create Date: 2022-12-06 16:18:24.512562
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+# revision identifiers, used by Alembic.
+revision = "a54bafb13ce8"
+down_revision = "ce54ba49ce5c"
+branch_labels = None
+depends_on = None
+
+monitorings_schema = "gn_monitoring"
+referent_schema = "gn_commons"
+
+
+def upgrade():
+ op.create_table(
+ "cor_module_type",
+ sa.Column(
+ "id_type_site",
+ sa.Integer(),
+ sa.ForeignKey(
+ f"{monitorings_schema}.bib_type_site.id_nomenclature_type_site",
+ name="fk_cor_module_type_id_nomenclature",
+ ondelete="CASCADE",
+ onupdate="CASCADE",
+ ),
+ nullable=False,
+ ),
+ sa.Column(
+ "id_module",
+ sa.Integer(),
+ sa.ForeignKey(
+ f"{referent_schema}.t_modules.id_module",
+ name="fk_cor_module_type_id_module",
+ ondelete="CASCADE",
+ onupdate="CASCADE",
+ ),
+ nullable=False,
+ ),
+ sa.PrimaryKeyConstraint("id_type_site", "id_module", name="pk_cor_module_type"),
+ schema=monitorings_schema,
+ )
+
+ # Insertion des données a partir de cor_site_module
+ op.execute(
+ """
+ INSERT INTO gn_monitoring.cor_module_type (id_module, id_type_site )
+ SELECT DISTINCT csm.id_module, cts.id_type_site
+ FROM gn_monitoring.cor_site_module AS csm
+ JOIN gn_monitoring.cor_site_type AS cts
+ ON Cts.id_base_site = csm.id_base_site ;
+ """
+ )
+
+
+def downgrade():
+ op.drop_table("cor_module_type", schema=monitorings_schema)
diff --git a/backend/geonature/migrations/versions/b53bafb13ce8_monitoring_create_bib_type_site.py b/backend/geonature/migrations/versions/b53bafb13ce8_monitoring_create_bib_type_site.py
new file mode 100644
index 0000000000..0c66d8ece2
--- /dev/null
+++ b/backend/geonature/migrations/versions/b53bafb13ce8_monitoring_create_bib_type_site.py
@@ -0,0 +1,77 @@
+"""[monitoring] create_bib_type_site
+
+Revision ID: b53bafb13ce8
+Revises: 8309591841f3
+Create Date: 2022-12-06 16:18:24.512562
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+# revision identifiers, used by Alembic.
+revision = "b53bafb13ce8"
+down_revision = "8309591841f3"
+branch_labels = None
+depends_on = None
+
+monitorings_schema = "gn_monitoring"
+nomenclature_schema = "ref_nomenclatures"
+
+
+def upgrade():
+ op.create_table(
+ "bib_type_site",
+ sa.Column(
+ "id_nomenclature_type_site",
+ sa.Integer(),
+ sa.ForeignKey(
+ f"{nomenclature_schema}.t_nomenclatures.id_nomenclature",
+ name="fk_t_nomenclatures_id_nomenclature_type_site",
+ ),
+ nullable=False,
+ unique=True,
+ ),
+ sa.PrimaryKeyConstraint("id_nomenclature_type_site"),
+ sa.Column("config", sa.JSON(), nullable=True),
+ schema=monitorings_schema,
+ )
+
+ # FIXME: if sqlalchemy >= 1.4.32, it should work with postgresql_not_valid=True: cleaner
+ # op.create_check_constraint(
+ # "ck_bib_type_site_id_nomenclature_type_site",
+ # "bib_type_site",
+ # f"{nomenclature_schema}.check_nomenclature_type_by_mnemonique(id_nomenclature_type_site,'TYPE_SITE')",
+ # schema=monitorings_schema,
+ # postgresql_not_valid=True
+ # )
+ statement = sa.text(
+ f"""
+ ALTER TABLE {monitorings_schema}.bib_type_site
+ ADD
+ CONSTRAINT ck_bib_type_site_id_nomenclature_type_site CHECK (
+ {nomenclature_schema}.check_nomenclature_type_by_mnemonique(
+ id_nomenclature_type_site, 'TYPE_SITE' :: character varying
+ )
+ ) NOT VALID
+ """
+ )
+ op.execute(statement)
+ op.create_table_comment(
+ "bib_type_site",
+ "Table de définition des champs associés aux types de sites",
+ schema=monitorings_schema,
+ )
+
+ # Récupération de la liste des types de site avec ceux déja présents dans la table t_base_site
+ op.execute(
+ """
+ INSERT INTO gn_monitoring.bib_type_site AS bts (id_nomenclature_type_site)
+ SELECT DISTINCT id_nomenclature_type_site
+ FROM gn_monitoring.t_base_sites AS tbs ;
+ """
+ )
+
+
+def downgrade():
+ op.drop_table("bib_type_site", schema=monitorings_schema)
diff --git a/backend/geonature/migrations/versions/ce54ba49ce5c_monitoring_create_cor_site_type.py b/backend/geonature/migrations/versions/ce54ba49ce5c_monitoring_create_cor_site_type.py
new file mode 100644
index 0000000000..d1a4296713
--- /dev/null
+++ b/backend/geonature/migrations/versions/ce54ba49ce5c_monitoring_create_cor_site_type.py
@@ -0,0 +1,130 @@
+"""[monitoring] create_cor_site_type
+
+Revision ID: ce54ba49ce5c
+Revises: b53bafb13ce8
+Create Date: 2022-12-06 16:18:24.512562
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+# revision identifiers, used by Alembic.
+revision = "ce54ba49ce5c"
+down_revision = "b53bafb13ce8"
+branch_labels = None
+depends_on = None
+
+monitorings_schema = "gn_monitoring"
+
+
+def upgrade():
+ op.create_table(
+ "cor_site_type",
+ sa.Column(
+ "id_type_site",
+ sa.Integer(),
+ sa.ForeignKey(
+ f"{monitorings_schema}.bib_type_site.id_nomenclature_type_site",
+ name="fk_cor_site_type_id_nomenclature_type_site",
+ ondelete="CASCADE",
+ onupdate="CASCADE",
+ ),
+ nullable=False,
+ ),
+ sa.Column(
+ "id_base_site",
+ sa.Integer(),
+ sa.ForeignKey(
+ f"{monitorings_schema}.t_base_sites.id_base_site",
+ name="fk_cor_site_type_id_base_site",
+ ondelete="CASCADE",
+ onupdate="CASCADE",
+ ),
+ nullable=False,
+ ),
+ sa.PrimaryKeyConstraint("id_type_site", "id_base_site", name="pk_cor_site_type"),
+ schema=monitorings_schema,
+ )
+ op.create_table_comment(
+ "cor_site_type",
+ "Table d'association entre les sites et les types de sites",
+ schema=monitorings_schema,
+ )
+
+ op.execute(
+ """
+ INSERT INTO gn_monitoring.cor_site_type
+ SELECT id_nomenclature_type_site , id_base_site d
+ FROM gn_monitoring.t_base_sites ;
+ """
+ )
+
+ op.execute(
+ """
+ ALTER TABLE gn_monitoring.t_base_sites
+ DROP CONSTRAINT check_t_base_sites_type_site;
+ """
+ )
+ op.execute(
+ """
+ DROP INDEX gn_monitoring.idx_t_base_sites_type_site;
+ """
+ )
+ op.drop_column(
+ table_name="t_base_sites",
+ column_name="id_nomenclature_type_site",
+ schema=monitorings_schema,
+ )
+
+
+def downgrade():
+ op.add_column(
+ table_name="t_base_sites",
+ column=sa.Column(
+ "id_nomenclature_type_site",
+ sa.Integer(),
+ sa.ForeignKey(
+ "ref_nomenclatures.t_nomenclatures.id_nomenclature",
+ name="fk_t_base_sites_type_site",
+ onupdate="CASCADE",
+ ),
+ ),
+ schema=monitorings_schema,
+ )
+
+ op.execute(
+ """
+ WITH ts AS (
+ SELECT DISTINCT ON (id_base_site) id_base_site, id_type_site
+ FROM gn_monitoring.cor_site_type AS cts
+ ORDER BY id_base_site, id_type_site
+ )
+ UPDATE gn_monitoring.t_base_sites tbs
+ SET id_nomenclature_type_site = id_type_site
+ FROM ts
+ WHERE ts.id_base_site = tbs.id_base_site;
+ """
+ )
+
+ op.execute(
+ """
+ ALTER TABLE gn_monitoring.t_base_sites
+ ADD CONSTRAINT check_t_base_sites_type_site
+ CHECK (ref_nomenclatures.check_nomenclature_type_by_mnemonique(id_nomenclature_type_site,'TYPE_SITE'))
+ NOT VALID;
+ """
+ )
+
+ op.execute(
+ """
+ CREATE INDEX idx_t_base_sites_type_site ON gn_monitoring.t_base_sites USING btree (id_nomenclature_type_site);
+ """
+ )
+ op.execute(
+ """
+ ALTER TABLE gn_monitoring.t_base_sites ALTER COLUMN id_nomenclature_type_site SET NOT NULL;
+ """
+ )
+
+ op.drop_table("cor_site_type", schema=monitorings_schema)
diff --git a/frontend/src/app/GN2CommonModule/form/datalist/datalist.component.ts b/frontend/src/app/GN2CommonModule/form/datalist/datalist.component.ts
index 317a8e2cb3..0a2c830a29 100644
--- a/frontend/src/app/GN2CommonModule/form/datalist/datalist.component.ts
+++ b/frontend/src/app/GN2CommonModule/form/datalist/datalist.component.ts
@@ -1,13 +1,4 @@
-import { filter } from 'rxjs/operators';
-import {
- Component,
- OnInit,
- Input,
- OnChanges,
- DoCheck,
- IterableDiffers,
- IterableDiffer,
-} from '@angular/core';
+import { Component, OnInit, Input } from '@angular/core';
import { DataFormService } from '../data-form.service';
import { GenericFormComponent } from '@geonature_common/form/genericForm.component';
import { CommonService } from '../../service/common.service';
@@ -37,6 +28,7 @@ export class DatalistComponent extends GenericFormComponent implements OnInit {
@Input() filters = {}; // help
@Input() default;
+ @Input() nullDefault;
@Input() dataPath: string; // pour atteindre la liste si elle n'est pas à la racine de la réponse de l'api.
// si on a 'data/liste' on mettra dataPath='data'
@@ -70,7 +62,15 @@ export class DatalistComponent extends GenericFormComponent implements OnInit {
getFilteredValues() {
let values = this.values || [];
-
+ // if(this.nullDefault){
+ // values.push()
+ // }
+ if (this.nullDefault && !this.required) {
+ let obj = {};
+ obj[this.keyValue] = null;
+ obj[this.keyLabel] = '-- Aucun --';
+ values.unshift(obj);
+ }
values = values
// filter search
.filter(
@@ -133,20 +133,34 @@ export class DatalistComponent extends GenericFormComponent implements OnInit {
this.filteredValues.length === 1 &&
!(this.parentFormControl.value && this.parentFormControl.value.length)
) {
- const val = this.values[0][this.keyValue];
- this.parentFormControl.patchValue(this.multiple ? [val] : val);
+ const val = this.nullDefault ? null : this.values[0][this.keyValue];
+ this.parentFormControl.patchValue(this.multiple && !this.nullDefault ? [val] : val);
}
+
// valeur par défaut (depuis input value)
- if (!this.parentFormControl.value && this.default) {
+ if (
+ (!this.parentFormControl.value ||
+ (Array.isArray(this.parentFormControl.value) &&
+ this.parentFormControl.value.length == 0)) &&
+ this.default
+ ) {
const value = this.multiple ? this.default : [this.default];
- const res = value.map((val) =>
- typeof val === 'object'
- ? (this.filteredValues.find((v) =>
- Object.keys(val).every((key) => v[key] === val[key])
- ) || {})[this.keyValue]
- : val
- );
- this.parentFormControl.patchValue(this.multiple ? res : res[0]);
+ // check if the default value is in the provided values
+ const valuesID = this.values.map((el) => el[this.keyValue]);
+ const defaultValuesID = value.map((el) => el[this.keyValue]);
+ const defaultValueIsInValues = valuesID.some((el) => defaultValuesID.includes(el));
+
+ // patch value only if default value is in values
+ if (defaultValueIsInValues) {
+ const res = value.map((val) =>
+ typeof val === 'object'
+ ? (this.filteredValues.find((v) =>
+ Object.keys(val).every((key) => v[key] === val[key])
+ ) || {})[this.keyValue]
+ : val
+ );
+ this.parentFormControl.patchValue(this.multiple ? res : res[0]);
+ }
}
this.parentFormControl.markAsTouched();
}
diff --git a/frontend/src/app/GN2CommonModule/form/dynamic-form/dynamic-form.component.html b/frontend/src/app/GN2CommonModule/form/dynamic-form/dynamic-form.component.html
index 04200a1793..9d96cd8045 100644
--- a/frontend/src/app/GN2CommonModule/form/dynamic-form/dynamic-form.component.html
+++ b/frontend/src/app/GN2CommonModule/form/dynamic-form/dynamic-form.component.html
@@ -316,8 +316,15 @@
[idMenu]="formDefComp['id_menu']"
[idList]="formDefComp['id_list']"
[codeList]="formDefComp['code_list']"
+ [multiSelect]="formDefComp['multi_select']"
>
+
+
{{ formDefComp['help'] }}
diff --git a/frontend/src/app/GN2CommonModule/form/observers/observers.component.ts b/frontend/src/app/GN2CommonModule/form/observers/observers.component.ts
index 66e62bd5d6..9d02c18025 100644
--- a/frontend/src/app/GN2CommonModule/form/observers/observers.component.ts
+++ b/frontend/src/app/GN2CommonModule/form/observers/observers.component.ts
@@ -43,7 +43,7 @@ export class ObserversComponent extends GenericFormComponent {
ngOnInit() {
super.ngOnInit();
this.bindValue = this.bindAllItem ? null : this.bindValue;
- this.multiSelect = this.multiSelect || true;
+ this.multiSelect = this.multiSelect ? true : this.multiSelect;
// uniformise as IdList the id of list
// retrocompat: keep idMenu
if (this.idList) {