diff --git a/backend/gn_module_zh/forms.py b/backend/gn_module_zh/forms.py index a4970e62..f6d6d872 100644 --- a/backend/gn_module_zh/forms.py +++ b/backend/gn_module_zh/forms.py @@ -488,7 +488,13 @@ def update_corine_biotopes(id_zh, corine_biotopes): def post_corine_biotopes(id_zh, corine_biotopes): for corine_biotope in corine_biotopes: - DB.session.add(CorZhCb(id_zh=id_zh, lb_code=corine_biotope["CB_code"])) + DB.session.add( + CorZhCb( + id_zh=id_zh, + lb_code=corine_biotope["corinBio"]["CB_code"], + cb_cover=corine_biotope["cbCover"], + ) + ) DB.session.flush() diff --git a/backend/gn_module_zh/migrations/9ff769188d93_add_cb_cover_percentage.py b/backend/gn_module_zh/migrations/9ff769188d93_add_cb_cover_percentage.py new file mode 100644 index 00000000..f4132868 --- /dev/null +++ b/backend/gn_module_zh/migrations/9ff769188d93_add_cb_cover_percentage.py @@ -0,0 +1,29 @@ +"""add_cb_cover_percentage + +Revision ID: 9ff769188d93 +Revises: 76e89c793961 +Create Date: 2024-07-04 15:42:25.691119 + +""" + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "9ff769188d93" +down_revision = "76e89c793961" +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column( + table_name="cor_zh_cb", + column=sa.Column("cb_cover", sa.Integer, nullable=True), + schema="pr_zh", + ) + + +def downgrade(): + op.drop_column(table_name="cor_zh_cb", column_name="cb_cover", schema="pr_zh") diff --git a/backend/gn_module_zh/model/cards.py b/backend/gn_module_zh/model/cards.py index 2d4f0ccd..b6e3305a 100644 --- a/backend/gn_module_zh/model/cards.py +++ b/backend/gn_module_zh/model/cards.py @@ -531,7 +531,15 @@ def __str__(self): "area": self.area, "sdage": Utils.get_mnemo(self.id_sdage), "typologie_locale": Utils.get_mnemo(self.id_sage), - "corine_biotope": [cb.__str__() for cb in self.cb_codes_corine_biotope], + "corine_biotope": [ + { + "code": cb["lb_code"], + "label": CorineBiotope(cb["lb_code"]).__str__()["label"], + "Humidité": CorineBiotope(cb["lb_code"]).__str__()["Humidité"], + "recouvrement": cb["cb_cover"], + } + for cb in self.cb_codes_corine_biotope + ], "remarques": Utils.get_string(self.remark_pres), "ef_area": self.ef_area, } @@ -1154,7 +1162,7 @@ def __set_description(self): return self.description.__str__() def __get_cb(self): - return [CorineBiotope(cb) for cb in sorted(self.properties["cb_codes_corine_biotope"])] + return [cb for cb in self.properties["cb_codes_corine_biotope"]] def __set_use(self): self.description.use = Use() diff --git a/backend/gn_module_zh/model/zh.py b/backend/gn_module_zh/model/zh.py index 84c4a945..f9370f94 100644 --- a/backend/gn_module_zh/model/zh.py +++ b/backend/gn_module_zh/model/zh.py @@ -53,7 +53,11 @@ def get_id_references(self): def get_cb_codes(self): corine_biotopes = ZH.get_data_by_id(CorZhCb, self.zh.id_zh) - return {"cb_codes_corine_biotope": [cb_code.lb_code for cb_code in corine_biotopes]} + return { + "cb_codes_corine_biotope": [ + {"lb_code": cb.lb_code, "cb_cover": cb.cb_cover} for cb in corine_biotopes + ] + } def get_corine_landcovers(self): landcovers = ZH.get_data_by_id(CorZhCorineCover, self.zh.id_zh) diff --git a/backend/gn_module_zh/model/zh_schema.py b/backend/gn_module_zh/model/zh_schema.py index 4a006581..3f116e2d 100644 --- a/backend/gn_module_zh/model/zh_schema.py +++ b/backend/gn_module_zh/model/zh_schema.py @@ -634,11 +634,13 @@ def get_mnemo_type(id_type): return "" +# TODO: not really a CorXXX. More a TXXX. class CorZhCb(DB.Model): __tablename__ = "cor_zh_cb" __table_args__ = {"schema": "pr_zh"} id_zh = DB.Column(DB.Integer, ForeignKey(TZH.id_zh), primary_key=True) lb_code = DB.Column(DB.Integer, ForeignKey(BibCb.lb_code), primary_key=True) + cb_cover = DB.Column(DB.Integer, nullable=True) class CorZhCorineCover(DB.Model): diff --git a/frontend/app/zh-details/description/description.component.ts b/frontend/app/zh-details/description/description.component.ts index c5c10b86..268b7a65 100644 --- a/frontend/app/zh-details/description/description.component.ts +++ b/frontend/app/zh-details/description/description.component.ts @@ -16,6 +16,7 @@ export class DescriptionComponent { { name: 'code', label: 'Code Corine biotopes' }, { name: 'label', label: 'Libellé Corine biotopes' }, { name: 'Humidité', label: 'Humidité', size: '5%' }, + { name: 'recouvrement', label: 'Recouvrement sur la ZH (%)', size: '5%' }, ]; activitiesTableCols: TableColumn[] = [ { diff --git a/frontend/app/zh-details/models/description.model.ts b/frontend/app/zh-details/models/description.model.ts index 05c778da..52f38619 100644 --- a/frontend/app/zh-details/models/description.model.ts +++ b/frontend/app/zh-details/models/description.model.ts @@ -28,6 +28,7 @@ interface Corine { code: string; label: string; Humidité: string; + recouvrement: string; } interface Activities { diff --git a/frontend/app/zh-forms/tabs/tab3/zh-form-tab3.component.html b/frontend/app/zh-forms/tabs/tab3/zh-form-tab3.component.html index 93f8059b..f4fcce1d 100755 --- a/frontend/app/zh-forms/tabs/tab3/zh-form-tab3.component.html +++ b/frontend/app/zh-forms/tabs/tab3/zh-form-tab3.component.html @@ -35,21 +35,12 @@
Présentation de la zone humide et de ses milieux
Types d’habitats Corine biotopes humides (H) ou potentiellement humides (P) - +
-
@@ -57,8 +48,10 @@
Présentation de la zone humide et de ses milieux
@@ -239,5 +232,72 @@
{{ modalTitle }}
> {{ modalButtonLabel }} -
+ + + + + + + + + \ No newline at end of file diff --git a/frontend/app/zh-forms/tabs/tab3/zh-form-tab3.component.ts b/frontend/app/zh-forms/tabs/tab3/zh-form-tab3.component.ts index 9fbfa066..1a1318f8 100755 --- a/frontend/app/zh-forms/tabs/tab3/zh-form-tab3.component.ts +++ b/frontend/app/zh-forms/tabs/tab3/zh-form-tab3.component.ts @@ -26,9 +26,10 @@ export class ZhFormTab3Component implements OnInit { public currentZh: any; corinBioMetaData: any; corinTableCol = [ - { name: 'CB_code', label: 'Code Corine biotopes' }, - { name: 'CB_label', label: 'Libellé Corine biotopes' }, - { name: 'CB_humidity', label: 'Humidité', size: '5%' }, + { name: 'corinBio', label: 'Code Corine biotopes', subcell: { name: 'CB_code' } }, + { name: 'corinBio', label: 'Libellé Corine biotopes', subcell: { name: 'CB_label' } }, + { name: 'corinBio', label: 'Humidité', size: '5%', subcell: { name: 'CB_humidity' } }, + { name: 'cbCover', label: 'Recouvrement sur la ZH (%)', size: '5%' }, ]; // subcell : if the data contain a list inside the data list // example use : consider this @@ -71,18 +72,23 @@ export class ZhFormTab3Component implements OnInit { }, { name: 'remark_activity', label: 'Remarques' }, ]; - listCorinBio = []; + listCorinBio: any = []; + patchCorinBio: boolean = false; posted: boolean = false; patchActivity: boolean = false; activityForm: FormGroup; + corinBioForm: FormGroup; modalButtonLabel: string; modalTitle: string; + addModalBtnLabel: string; + cb_to_patch: any; selectedItems = []; listActivity: any = []; activitiesInput: any = []; submitted: boolean; formImpactSubmitted: boolean; + formCorinSubmitted: boolean; constructor( private fb: FormBuilder, @@ -103,6 +109,11 @@ export class ZhFormTab3Component implements OnInit { frontId: null, }); + this.corinBioForm = this.fb.group({ + corinBio: [null, Validators.required], + cbCover: [null, Validators.compose([Validators.min(0), Validators.max(100)])], + }); + this.getMetaData(); this.createForm(); @@ -121,6 +132,7 @@ export class ZhFormTab3Component implements OnInit { if (zh) { this.currentZh = zh; this.listActivity = []; + this.listCorinBio = []; const corineLandcovers = []; this.formMetaData.OCCUPATION_SOLS.forEach((critere) => { if (this.currentZh.properties.id_corine_landcovers.includes(critere.id_nomenclature)) { @@ -131,9 +143,13 @@ export class ZhFormTab3Component implements OnInit { this.currentZh.properties.cb_codes_corine_biotope && this.currentZh.properties.cb_codes_corine_biotope.length > 0 ) { - this.listCorinBio = this.corinBioMetaData.filter((v) => - this.currentZh.properties.cb_codes_corine_biotope.includes(v.CB_code) - ); + this.currentZh.properties.cb_codes_corine_biotope.forEach((cb) => { + this.corinBioMetaData.find((item) => { + if (item.CB_code == cb.lb_code) { + this.listCorinBio.push({ corinBio: item, cbCover: cb.cb_cover }); + } + }); + }); } this.currentZh.properties.activities.forEach((activity) => { let impacts = []; @@ -216,7 +232,6 @@ export class ZhFormTab3Component implements OnInit { this.form = this.fb.group({ id_sdage: [null, Validators.required], id_sage: null, - corinBio: null, id_corine_landcovers: null, remark_pres: null, id_thread: null, @@ -242,32 +257,69 @@ export class ZhFormTab3Component implements OnInit { ), // Not to display a Corine that is already in the table map((term) => - term.filter((t) => !this.listCorinBio.map((c) => c.CB_code).includes(t.CB_code)) + term.filter((t) => !this.listCorinBio.map((c) => c.corinBio.CB_code).includes(t.CB_code)) ) ); formatter = (result: any) => `${result.CB_code} ${result.CB_label}`; - onAddCorinBio() { - if (this.form.value.corinBio) { - let itemExist = this.listCorinBio.some( - (item) => item.CB_code == this.form.value.corinBio.CB_code - ); - if (!itemExist && this.form.value.corinBio.CB_code) { - this.listCorinBio.push(this.form.value.corinBio); - } - this.form.get('corinBio').reset(); - this.canChangeTab.emit(false); - } + // open the add CorinBio modal + onAddCorinBio(event: any, modal: any) { + this.canChangeTab.emit(false); + this.patchCorinBio = false; + this.addModalBtnLabel = 'Ajouter'; + + this.modalTitle = "Ajout d'un habitat Corine Biotopes"; + event.stopPropagation(); + this.ngbModal.open(modal, { + centered: true, + size: 'lg', + windowClass: 'bib-modal', + }); + this.corinBioForm.reset(); } onDeleteCorin(CB_code: string) { this.listCorinBio = this.listCorinBio.filter((item) => { - return item.CB_code != CB_code; + return item.corinBio.CB_code != CB_code; }); this.canChangeTab.emit(false); } + // open the edit corineBio modal + onEditCorinBio(modal: any, corinBio: any) { + this.patchCorinBio = true; + this.addModalBtnLabel = 'Modifier'; + this.modalTitle = 'Modifier un habitat Corine Biotopes'; + this.cb_to_patch = corinBio; + this.corinBioForm.patchValue({ + corinBio: corinBio.corinBio, + cbCover: corinBio.cbCover, + }); + this._modalService.open( + modal, + this.listCorinBio.map((item) => item.corinBio), + this.corinBioMetaData, + corinBio + ); + } + + onPatchCorinBio() { + this.patchActivity = false; + this.formCorinSubmitted = true; + if (this.corinBioForm.valid) { + let cb = this.corinBioForm.value; + this.listCorinBio = this.listCorinBio.map((item) => + item.corinBio != this.cb_to_patch.corinBio ? item : cb + ); + this.ngbModal.dismissAll(); + this.corinBioForm.reset(); + this.canChangeTab.emit(false); + this.formCorinSubmitted = false; + this.cb_to_patch = {}; + } + } + onAddActivity(event, modal) { this.resetActivityForm(); @@ -325,7 +377,7 @@ export class ZhFormTab3Component implements OnInit { onEditActivity(modal: any, activity: any) { this.patchActivity = true; this.modalButtonLabel = 'Modifier'; - this.modalTitle = "Modifier l'activié humaine"; + this.modalTitle = "Modifier l'activité humaine"; this.selectedItems = activity.impacts.impacts; const selectedActivity = this.activitiesInput.find( (item) => item.id_nomenclature == activity.human_activity.id_nomenclature @@ -392,6 +444,22 @@ export class ZhFormTab3Component implements OnInit { this.activityForm.get('impacts').setValue([]); } + // add a new CorineBio to CorineBio array + onPostCorinBio() { + this.patchCorinBio = false; + this.formCorinSubmitted = true; + if (this.corinBioForm.valid) { + this.listCorinBio.push({ + corinBio: this.corinBioForm.value.corinBio, + cbCover: this.corinBioForm.value.cbCover, + }); + this.ngbModal.dismissAll(); + this.corinBioForm.reset(); + this.canChangeTab.emit(false); + this.formCorinSubmitted = false; + } + } + onFormSubmit() { if (this.form.valid) { this.submitted = true;