travail sur la taxonomie de geonature
modèle de données pour réflexion
J'ai commencé à traduire ça dans le code. Pas simple mais ça fonctionne. Maintenant pour le traduire de manière générique entre la base, l'interface client et le backend de géonature : ça va être du sport.
Pas simple de passer en paramètres + en interface, des champs d'attributs qui ne préexistent pas en base. Pour le moment, j'ai mis des valeurs en dur : comme patrimonial (oui ou non), protection_stricte (oui ou non) mais si on veut faire du générique, sans connaître les valeurs de l'attribut, ça va être complexe.
Je n'ai pas encore commité mes modifs dans geonature.
La table centrale bib_taxons :
La table bib_attributs avec ici la notion de patrimonial et de protection stricte. On a ici une liste de valeurs correspondant à un boolean mais on peut mettre par exemple, pour répondre à Amandine, un attribut avec l'id 3 pour "liste rouge" et lister les 4,5 ou 6 valeurs dans "liste_valeur_attribut"
Dans cor_taxon_attribut On affecte pour chaque taxon concerné la valeur de l'attribut. Si liste rouge on pourrait avoir par exemple pour le lynx : 64;3;vulnérable
C'est le remplissage de cette table qu'il faut faire via une interface car difficile de se fader ça à la main.
Pour la partie liste : bib_listes, le but est de construire des menus déroulant, notamment pour définir les taxons dont la saisie est autorisée. Mais on peut envisager un autre usage. Il s'agit simplement de dire dans la liste A, il y a tel et tel taxon, dans la liste B, tel et tel autre
Dans cor_taxon_liste on dit liste par liste quel taxon est dans la liste :
Pour les groupes, dans bib_groupes, la discussion est ouverte. Le modèle proposé permet de mettre un taxon dans plusieurs groupe. Par exemple, le grand murin dans le groupe des mammifères et dans un groupe des murins. On peut aussi faire un groupe des plantes vasculaires et un groupe des orchidées. Maintenant, il faut voir l'usage de ces groupes en saisie ou dans l'interface que l'on doit créer. L'avantage des groupes est que l'on peut ajouter un groupe entier dans une liste, ce qui accélère la saisie. Mais cette possibilité n'est pas présente dans le modèle.
cor_taxon_groupe
J'ajoute qu'il ne va pas être simple d'implémenter ça en interface car on ne connait pas le contenu des tables à l'avance.
Autant il est simple de filtrer une liste de taxon sur la base de critères type "mammifères, poissons, oiseaux" connu à l'avance, autant prévoir d'activer ou non ce critère, ou un autre type liste rouge (permettre de n'afficher que les taxons vulnérables par exemple) s'il n'est pas connu à l'avance, demande une grosse modification de l'interface extjs de GeoNature mais aussi de la logique des requêtes correspondantes en backend.
La difficulté est de prévoir le fonctionnement des filtres sans les connaitre au moment des dev.
Pour le moment, j'ai traduit ce modèle dans GeoNature et j'ai conservé le fonctionnement existant avec patrimonial et protection_stricte. Mais si on retire l'enregistrement de ces filtres en base où qu'on change leur nom, tout pète... A affiner donc.
Une V2
Ici on créér les champs de filtres en dur dans la tables taxons 5 booléens et 5 strings et on les décrits dans une table isolée qui servira au fonctionnement du front-end et du back-end.
J'ai aussi ajouter un lien entre les groupes et les listes. On peut ainsi ajouter un groupe à une liste et pour retrouver les tous les taxons, qu'ils soient issus de groupes ou pas, on doit pouvoir faire ça avec une requête UNION.
Analyse rapide et qq propositions
pour la traduction possible de ces modèles dans les dev, une liste des points à adapter ou supprimer dans le cadre de la mise en place de filtres non prédéfinis.
Partie liste des observations
- Présence ou non du filtre dans le store de la grid des résultats : lors de la construction du store on donne la liste des champs de ce store. Ce store est ensuite alimenté (rempli) par le backend. Ce store gère le contenu du tableau de résultats (grid dans extjs). Il faut passer dynamiquement ce nom de champ au store est à la grid. Il faut aussi que la requête en backend soit construite avec le champ correspondant : même nom et même type.
- Gestion éventuelle d'un icone dans le tableau de résultat (grid) dans une colonne action (exemple une colonne "patrimoniale" avec un icône logo_pne) :
= présence de l'image png ou jpg dans le répertoire images de l'application avec le nom de l'attribut (par exemple "patrimonial.jpg")
o = aussi présence ou non de cette colonne action dans le grid.
o Lien stricte entre le front et le backend-end car le comportement de l'interface, affichage ou non de l'icone patrimonial, dépendra de la valeur du champ "patrimonial" dans le store et donc de la valeur renvoyée par le backend pour ce champ "patrimonial")
- Présence ou non de la valeur de l'attribut dans le bandeau présentant des informations relatives au taxon choisi dans la grid (tableau de résultats). Il y a là une phrase en dur dans le code qui dit ce qu'il en est de ce taxon pour l'attribut : ex : "Ce taxon n'est pas patrimonial pour le PNE"
Partie construction d'une requête (rechercher)
- Filtrage du menu déroulant des taxons affichés : le frontend écoute les actions de l'utilisateur sur l'interface. Par exemple si on coche la case "taxon patrimonial" :
o le menu déroulant (combobox) des taxons est filtrée pour n'afficher que les taxons patrimoniaux = filtrage du store du combobox sur le champ "patrimonial". Il faut donc (ou non)
§ créer ce champ "patrimonial" au moment de la construction du store
§ créer ce champ "patrimonial" au moment de la construction du combobox
§ créer un champ "hidden", dans le formulaire de requêtage général de recherche des observations. ex :
{ xtype:'hidden',id:'hidden-patri',name:'patrimonial',value:''}
voir point suivant concernant la recherche des observations
§ créér la case à cocher "patrimoniale" (possibilité de créer une liste déroulante avec oui, non ou autre valeur).
§ créer le listener (écouteur) qui va déclencher les actions sur modification de la case à cocher ou de la liste pour
- filtrer le store et donc la liste taxons
- transmettre la valeur modifiée au champ "hidden-patri" du formulaire
§ Enfin qu'une action symfony alimente ce store des taxons en backend et qu'elle comporte un champ "patrimonial" avec comme valeur true;false ou oui;non.
= Grosse réflexion à conduire ici pour faire qq chose de générique.
- Filtrage de la liste des observations correspondant aux critères de la requête :
o le frontend-end transmet au backend une liste de critères avec leur valeur : par exemple
patrimonial = true.
Le backend reçoit ces critères et s'ils ont un contenu, il complète la clause "WHERE" de la requête SQL avec pour l'exemple :
$sql .= " AND patrimonial = true";
Ici, c'est le champ "hidden-patri" du formulaire est utilisé.
La backend va renvoyer une liste des observations avec ou non la présence du champ patrimonial pour utilisation en front-end comme vu au début dans la partie liste des observations.
Réflexions
A ce stade, il faut se poser les bonnes questions et on a le choix entre
- prédéfinir les critères de recherches des observations et de filtrage des taxons (à la limite activable ou non). C'est ce qui est en place dans GéoNature pour le moment avec 2 filtres (patrimonial et protection_stricte)
Avantage : on sait leur nom, leur type, le comportement attendu en interface, les labels utilisés en interface, etc... Donc cohérence facile à gérer entre frontend et backend.
Inconvénients : ils sont prédéfinis et on ne peut pas en ajouter sans revoir les devs.
- Utiliser le modèle que je propose et tout mettre en paramètres et en conditions
Avantage : on peut en ajouter à volonté et totalement personnalisables
Inconvénients : ils sont nombreux :
§ faire une usine à gaz pour le dev (décrite ci-dessus avec une faisabilité restant à évaluer)
§ rendre complexe la mise en place de l'appli et surtout son paramétrage (il faudra que celui qui installe comprenne l'usine à gaz et les liens entre fichier de config, comportement de l'appli, contenu des tables)
- Faire qq chose d'intermédiaire comme :
créer dans le modèle de données (table bib_taxons) 6, 8 ou 10 champs de filtres nommés filtres filtre0, filtre1, filtre2, ..., filtre9 (qq booléen, qq string avec leur valeurs qq part)
Pour le front, en paramètre on met un tableau ou un objet js qui fait une description des filtres et de leur comportement en interface genre
filters = [ {"field":"filter0","actif":true,"name":"patrimonial","combo_label":"Taxons patrimoniaux","query_label":"Patrimonial","info_label":"Ce taxon est patrimonial","img":"patri.png"} ,{"field":"filter1","actif":true,"name":"protection","combo_label":"Taxons protégé","query_label":"Protection stricte","info_label":"Ce taxon bénéficie d'un statut de protection","img":"prot.png"}
,{"field":"filter2","actif":false,"name":""," combo_label":"","query_label":"","info_label":"","img":""}
,{"field":"filter5","actif":true,"name":"liste_rouge","combo_label":"Statut liste rouge","query_label":"liste rouge","info_label":"Ce taxon est inscrit en liste rouge comme ","img":"","values":["en danger","menacé","vulnérable","c foutu"]}
,{"field":"filter6","actif":false,"name":"","combo_label":"","query_label":"","info_label":"","img":"","values[]}
, {...}
];
On peut aussi envisager de mettre ces informations dans la base et de faire construire ce json dynamiquement à l'ouverture de l'appli par une action symfony en backend.
o avantages : on garde la souplesse, on peut utiliser les noms de champ (filter0, filter1, filter2,...) en dur coté frontend et coté backend. On connait le type : par exemple les 5 premiers sont des booléens et les 5 suivants sont des strings (ou des integer) avec des valeurs textuelles (ou des ID)
o inconvénients : le nombre de filtres ne peut pas dépasser le nombre prévus dans les dev mais facile à changer pour l'étendre, la structure est en place. C'est un peu pourri en terme de modèle car on aura des champs vides (tous les filtres inutilisés) pour tous les enregistrements. Idéalement il faudrait créer la gestion de la description de ces filtres dans le back-office taxon.