Skip to content

Commit

Permalink
release(2.15.1) : minor fixes (#3293)
Browse files Browse the repository at this point in the history
* feat(mapping,import): enable save of public mapping when user got U>3 + TODO -> check if user is owner
* feat(import, fieldmapping): now owner of public mapping can edit
* feat(install): add new grid layer to database population script
* fix(import,upload): fix autofill of the dataset form with query params
* feat(import, mapping) : update public mapping : (owner + u>0) ou (u>3)
* fix(admin) import mapping
* fix(import, mapping) fix checkbox and import step
* fix(doc): fix some rendering issues in the documentation
* Delete docs/import-level-2.rst

Moved to https://github.com/PnX-SI/Ressources-techniques/blob/master/GeoNature/V2/import-avance/readme.md

* Delete docs/import-level-1.rst
* change theme to furo
* feat(doc): limit depth of right section


Moved to https://github.com/PnX-SI/Ressources-techniques/blob/master/GeoNature/V2/import-basique/readme.md

* Doc admin - Move manual import into https://github.com/PnX-SI/Ressources-techniques/tree/master/GeoNature/V2

* Complement CHANGELOG 2.15.1

* feat(gitignore): add geonature.local.env in the gitignore

* fix(pdf_ca): make modifs for acquisition framework pdf export

List of modifications:
- Display label rather than ID for nomenclature_territorial_level associated to "Etendue territoriale"
- Do not display "Cible taxonomique" section if `data['target_description']` is empty i.e. if there is no information to display
- Change "Liste des jeux de données associés au cadre" to "Liste des jeux de données associés"
- Add count of Synthese observations for each dataset listed, associated to "Nombre d'observations" // change `get_export_pdf_acquisition_frameworks` endpoint to add these counts
- Use `data.datasets` rather than `data.t_datasets`

* fix(pdf_ca): fix typo error in af pdf export
* Feat(CA, pdf) add occhabs by datasets
* feat(tests) add test
* feat(ca) add dataset detail to acquisiton framework
* update version and requirements
* fix(test): fix frontend test on field mapping with the modification on the public mapping update

---------

Co-authored-by: Pierre-Narcisi <pierre.narcisi@epitech.eu>
Co-authored-by: Camille Monchicourt <camille.monchicourt@ecrins-parcnational.fr>
Co-authored-by: VincentCauchois <vincent.cauchois@mnhn.fr>
  • Loading branch information
4 people authored Jan 8, 2025
1 parent ae30979 commit 8fa697b
Show file tree
Hide file tree
Showing 36 changed files with 481 additions and 915 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,5 @@ install_all/install_all.log
/docs/CHANGELOG.html

/contrib/*/frontend/node_modules
Makefile.local
Makefile.local
geonature.local.env
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.15.0
2.15.1
21 changes: 21 additions & 0 deletions backend/geonature/core/gn_meta/models/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,27 @@ def user_actors(self):
def organism_actors(self):
return [actor.organism for actor in self.cor_dataset_actor if actor.organism is not None]

@hybrid_property
def obs_count(self):
from geonature.core.gn_synthese.models import Synthese

return db.session.scalar(
select(func.count(Synthese.id_synthese))
.select_from(Synthese)
.where(Synthese.id_dataset == self.id_dataset)
)

@hybrid_property
def hab_count(self):
from gn_module_occhab.models import OccurenceHabitat, Station

return db.session.scalar(
select(func.count(OccurenceHabitat.id_habitat))
.select_from(OccurenceHabitat)
.where(Station.id_station == OccurenceHabitat.id_station)
.where(Station.id_dataset == self.id_dataset)
)

def is_deletable(self):
return not DB.session.execute(self.synthese_records.exists().select()).scalar()

Expand Down
2 changes: 2 additions & 0 deletions backend/geonature/core/gn_meta/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class Meta:
cor_territories = MA.Nested(NomenclatureSchema, many=True, unknown=EXCLUDE)
acquisition_framework = MA.Nested("AcquisitionFrameworkSchema", dump_only=True)
sources = MA.Nested(SourceSchema, many=True, dump_only=True)
obs_count = fields.Int(dump_only=True)
hab_count = fields.Int(dump_only=True)

@post_dump(pass_many=False, pass_original=True)
def module_input(self, item, original, many, **kwargs):
Expand Down
36 changes: 14 additions & 22 deletions backend/geonature/core/imports/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from pypnnomenclature.models import TNomenclatures

from geonature.core.imports.models import FieldMapping, ContentMapping
from geonature.core.imports.models import Destination, FieldMapping, ContentMapping

from flask_admin.contrib.sqla.form import AdminModelConverter
from flask_admin.model.form import converts
Expand All @@ -25,51 +25,43 @@ class MappingView(CruvedProtectedMixin, ModelView):
object_code = "MAPPING"

can_view_details = True
column_list = (
"label",
"active",
"public",
)
column_list = ("label", "active", "public", "destination")
column_searchable_list = ("label",)
column_filters = (
"active",
"public",
)
form_columns = (
"label",
"active",
"public",
"owners",
"values",
)
column_details_list = (
"label",
"active",
"public",
"owners",
"values",
)
form_columns = ("label", "active", "public", "owners", "values", "destination")
column_details_list = ("label", "active", "public", "owners", "values", "destination")
column_labels = {
"active": "Actif",
"owners": "Propriétaires",
"values": "Correspondances",
"destination": "Destinations",
}
column_formatters = {"destination": lambda v, c, m, p: m.destination.label}
column_export_list = (
"label",
"values",
)


def FieldMappingValuesValidator(form, field):
destination = db.session.execute(
db.select(Destination).where(Destination.id_destination == form.destination.raw_data[0])
).scalar_one_or_none()
try:
FieldMapping.validate_values(field.data)
FieldMapping.validate_values(field.data, destination)
except ValueError as e:
raise StopValidation(*e.args)


def ContentMappingValuesValidator(form, field):
destination = db.session.execute(
db.select(Destination).where(Destination.id_destination == form.destination.raw_data[0])
).scalar_one_or_none()
try:
ContentMapping.validate_values(field.data)
ContentMapping.validate_values(field.data, destination)
except ValueError as e:
raise StopValidation(*e.args)

Expand Down
23 changes: 17 additions & 6 deletions backend/geonature/core/imports/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ def has_instance_permission(self, user: Optional[User] = None, action_code: str
]
return max_scope > 0

def __repr__(self):
return self.label


@serializable
class BibThemes(db.Model):
Expand Down Expand Up @@ -520,7 +523,7 @@ class MappingTemplate(db.Model):
__table_args__ = {"schema": "gn_imports"}

id = db.Column(db.Integer, primary_key=True)
id_destination = db.Column(db.Integer, ForeignKey(Destination.id_destination))
id_destination = db.Column(db.Integer, ForeignKey(Destination.id_destination), nullable=False)
destination = relationship(Destination)
label = db.Column(db.Unicode(255), nullable=False)
type = db.Column(db.Unicode(10), nullable=False)
Expand Down Expand Up @@ -667,7 +670,7 @@ class FieldMapping(MappingTemplate):
}

@staticmethod
def validate_values(field_mapping_json):
def validate_values(field_mapping_json, destination=None):
"""
Validate the field mapping values returned by the client form.
Expand All @@ -689,8 +692,13 @@ def validate_values(field_mapping_json):
"optional_conditions",
"mandatory_conditions",
]
(g.destination if (destination is None) else destination)
entities_for_destination: List[Entity] = (
Entity.query.filter_by(destination=g.destination).order_by(sa.desc(Entity.order)).all()
Entity.query.filter_by(
destination=(g.destination if (destination is None) else destination)
)
.order_by(sa.desc(Entity.order))
.all()
)
fields = []
for entity in entities_for_destination:
Expand All @@ -717,7 +725,9 @@ def validate_values(field_mapping_json):
entity,
columns=bib_fields_col,
optional_where_clause=sa.and_(
BibFields.destination == g.destination, BibFields.display == True
BibFields.destination
== (g.destination if (destination is None) else destination),
BibFields.display == True,
),
)
)
Expand Down Expand Up @@ -771,10 +781,11 @@ class ContentMapping(MappingTemplate):
}

@staticmethod
def validate_values(values):
def validate_values(values, destination=None):
nomenclature_fields = (
BibFields.query.filter(
BibFields.destination == g.destination, BibFields.nomenclature_type != None
BibFields.destination == (g.destination if (destination is None) else destination),
BibFields.nomenclature_type != None,
)
.options(
joinedload(BibFields.nomenclature_type).joinedload(
Expand Down
2 changes: 2 additions & 0 deletions backend/geonature/core/imports/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from utils_flask_sqla.schema import SmartRelationshipsMixin

from geonature.core.imports.models import Destination, FieldMapping, MappingTemplate
from pypnusershub.schemas import UserSchema
from geonature.core.gn_commons.schemas import ModuleSchema
from marshmallow import fields

Expand All @@ -27,3 +28,4 @@ class Meta:

cruved = fields.Dict()
values = fields.Dict()
owners = fields.List(fields.Nested(UserSchema(only=["identifiant"])))
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
<p class="info-titre">Territoires concernés</p>
<p class="info-contenu">
{% if data['id_nomenclature_territorial_level']: %}
Etendue territoriale : {{ data['id_nomenclature_territorial_level'] }}
Étendue territoriale : {{ data['nomenclature_territorial_level']['label_fr'] }}
{% endif %}
<!-- <br>
Territoires : ??
Expand All @@ -212,15 +212,14 @@
{% endif %}



{% if data['target_description']: %}
<div class="information">
<p class="info-titre">Cible taxonomique</p>
<p class="info-contenu">
{% if data['target_description']: %}
{{ data['target_description'] }}
{% endif %}
</p>
</div>
{% endif %}

{% if data.cor_af_actor: %}
<div class="information">
Expand Down Expand Up @@ -273,7 +272,7 @@
</div>
{% endif %}

{% if data.t_datasets: %}
{% if data.datasets: %}
<div class="jdd">
<hr
class="ligne-jeux-donnees ligne"
Expand All @@ -283,8 +282,8 @@
id="ligne-jeux-donnees-defaut"
{% endif %}
>
<p class="liste-jdd">Liste des jeux de données associés au cadre</p>
{% for dataset in data.t_datasets -%}
<p class="liste-jdd">Liste des jeux de données associés</p>
{% for dataset in data.datasets -%}
<div class="jdd-details">
<img
class="logo-jdd"
Expand All @@ -299,6 +298,14 @@
{% if dataset['dataset_name']: %}
{{ dataset['dataset_name'] }}
{% endif %}
<br>
{% if dataset['obs_count'] > 0: %}
Nombre d'observations dans la Synthèse : {{ dataset['obs_count'] }}
{% endif %}
<br>
{% if dataset['hab_count'] > 0: %}
Nombre d'habitats dans occhab : {{ dataset['hab_count'] }}
{% endif %}
</p>
</div>
{%- endfor %}
Expand Down
3 changes: 3 additions & 0 deletions backend/geonature/tests/imports/jsonschema_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@
"values": {
"type": ["null", "object"],
},
"owners": {
"type": ["null", "array"],
},
},
"minProperties": 7,
"additionalProperties": False,
Expand Down
13 changes: 13 additions & 0 deletions backend/geonature/tests/test_gn_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,19 @@ def test_get_export_pdf_acquisition_frameworks(self, users, acquisition_framewor

assert response.status_code == 200

def test_get_export_pdf_acquisition_frameworks_with_data(
self, users, acquisition_frameworks, datasets
):
af_id = acquisition_frameworks["af_1"].id_acquisition_framework

set_logged_user(self.client, users["user"])

response = self.client.post(
url_for("gn_meta.get_export_pdf_acquisition_frameworks", id_acquisition_framework=af_id)
)

assert response.status_code == 200

def test_get_export_pdf_acquisition_frameworks_unauthorized(self, acquisition_frameworks):
af_id = acquisition_frameworks["own_af"].id_acquisition_framework

Expand Down
Loading

0 comments on commit 8fa697b

Please sign in to comment.