Giter Club home page Giter Club logo

obs_occ's People

Contributors

amandine-sahl avatar damienfrazzoni avatar mathieubossaert avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

obs_occ's Issues

Avoir la possibilité d'avoir une liste de caractéristiques d'observations en fonction non pas du règne, mais du groupe (oiseaux, etc.)

L'idée serait de rester super simple, 3, 4 critères pas plus, mais dépendant d'une liste de groupes. cela permettrait de conserver des formulaires très simples en s'adaptant à quasi toutes les données. -> pourraient être 4 champs textes génériques dont on change l'étiquette selon le groupe. On pourrait stocker en base le couple clé/valeur pour une meilleure pérennité de la donnée ainsi collectée.

Afficher une miniature de la photo ou une icone dans le grille

Les photos sonr chargées dans leur format d'origine. Le chargement de la page peut être fortement alourdi.
L'affichage d'une icone qui sgnale qu'une photo est liée à la photo serait plus efficace et suffisant :

//Fonction de traitement de l'affichage du type image dans les grilles
    function renderIcon(val) {
        if (val != ''){
        //return '<img src="' + CST_cheminRelatifPhoto + val + '" width=20 height=15 qtip="' + 
        //    nomPhoto(val) + '">';
            return '<img src="../../../Photos/_photo.jpeg" width=20 height=15>';}
    }

Undefined index: critere

[error] [client 192.168.1.161] PHP Notice: Undefined index: critere in /var/www/html/saisie/Sources/SiCen/Modeles/Json/jEspecesUsuelles.php on line 8, referer: http://192.168.1.231/saisie/Sources/SiCen/Vues/vSelectGPX.php?GPX=20150529113255_685_MT_points_gps_280515.gpx&modeSimplifie=false
[error] [client 192.168.1.161] PHP Notice: Undefined index: critere in /var/www/html/saisie/Sources/SiCen/Modeles/Json/jEspeces.php on line 8, referer: http://192.168.1.231/saisie/Sources/SiCen/Vues/vSelectGPX.php?GPX=20150529113255_685_MT_points_gps_280515.gpx&modeSimplifie=false

Ajouter un champ déterminateur

Utile et beaucoup utilisé pour les invertébrés. Un observateur collecte une échantillon, un tiers le détermine et un autre valide/invalide cette détermination.

Séparer le nom de la BD et le nom des roles PostgreSQL

DEMANDE DU CEN

En cas de bases de données multiples, l’application oblige à créer 3 rôles de connexion par base avec un password identique. Exemple : pour une base sicen_mamm il faut un rôle sicen_mamm_amateur avec comme password sicen_mamm_amateur, un rôle sicen_mamm_expert, un rôle sicen_mamm_admin… Afin d’avoir un seul rôle amateur, expert et admin pour toutes les bases ainsi qu'un password non déterminé à l'avance

BDD : favoriser l'emploi des CTE

Il faudrait vérifier le code sql et le reprendre pour systématiquement, quand c'est possible remplacer les requêtes avec sous-requête (select * from (selete a,b from c) foo par des CTE : with foo as (select a,b from c) select * from foo.
Il ne s'agit pas d'une simple réécriture pour la forme, lesperfs sont bien meilleures.

Désactivation de la vue 45° de google

Il faut ajouter une ligne pour désactiver cette fonction par défaut d'openlayers. Aprés la ligne contenant (après carte.addLayers([gsat, g...) du fichier "ParametrageDefautCarto.js", ajouter ceci :
gsat.mapObject.setTilt(0) // Suppression de la fonction "bird eye" des fonds Google

Suivi de station/site de prospection

  • pouvoir attribuer une série d'observation à un site, une localité sur laquelle on retourne régulièrement dans le cadre d'un suivi
  • pouvoir décrire les conditions stationnelles au moment du relevé

JCdNom.php : recherche sur lb_nom

La colonne lb_nom de taxref ne contient pas de taxon terminant par ' sp.', ce qui rend le test inopérant quand un taxon a été saisi comme cela dans l'appli.
Je propose ceci (lignes 54 à 56), promis je vais me remettre à Git :

$valeur = $valeurInit . ' sp.';
 $req = "SELECT cd_nom FROM INPN.TAXREF_LATEST WHERE ordre = '" . $_POST['filtre'] ."' AND (lb_nom = '" . $valeur . "' OR lb_nom = '" . $valeurInit ."')";```

Interface saisie : duplication d'observation, champs etude et protocole affiche identifiants et non libellés

Dans le cas d'une duplication d'observation, les champs 'études' et 'protocole' affichent l'identifiant et non le libellé de ces objets.
L'enregistrement en base est bon, mais c'est déroutant pour les utilisateurs non avertis.

Complément : dans le cas ou une donnée validée est dupliquée, le statut de la nouvelle donnée est bien non validée, par contre elle prendre la date de validation de la donnée d'origine, ce qu'elle ne devrait pas bien entendu.

BDD : Amélioration de l'indexation de la table de saisie

rendre "immutable" la fonction md.liste_nom_auteur(text) afin de pouvoir ajouter un index dessus 👍

CREATE INDEX saisie_observation_liste_observateurs_idx
  ON saisie.saisie_observation
  USING gist
  (upper(md.liste_nom_auteur(observateur)) COLLATE pg_catalog."default" gist_trgm_ops);

Ajouter un outil recherche de lieu-dit

qui fonctionnerait : soit avec la table PG des lieux-dits ou mieux, avec un web service de localisation (celui de Google est bien et libre d'accès, celui de l'IGN est mieux mais demande une clé d'utilisation)

Revoir l'intégration des GPX

Envisager un stockage des GPX en base de données (table avec 3 champs : login text, date date, gpx xml) pour utiliser les fonctions xml de postgresql pour itérer sur le GPX. Cela éviterait-il les pertes de connexions qui interviennent sur le renseignement de long GPX ?

BUG : Fonction filtrer emprise

PnP : quand on clique sur "filtrer emprise", aucune donnée n'apparait, ni dans la fenêtre carte ni dans la fenêtre "données"

Ajouter un fichier css personnalisé

Notamment utile dans le cas de l'affichage de couche en tms

.olImageLoadError {
/* when OL encounters a 404, don't display the pink image */
display: none !important;
}

BDD : déploiement export SINP

/* La table md.lot_donnee est nécessaire */
CREATE TABLE md.lot_donnee
(
  id_lot serial NOT NULL,
  libelle character varying(254),
  id_etude integer,
  type_donnee md.enum_type_donnee,
  resume text,
  description_genealogie text,
  echelle_utilisation text,
  licence character varying,
  limitation_acces_public boolean,
  qualite_thematique text,
  id_protocole integer,
  code character varying,
  responsable_code_personne character varying,
  CONSTRAINT pk_lot_donnee PRIMARY KEY (id_lot),
  CONSTRAINT fk_etude_id_protocole_reference_protocole FOREIGN KEY (id_protocole)
      REFERENCES md.protocole (id_protocole) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_etude_lot_donnee_reference_etude FOREIGN KEY (id_etude)
      REFERENCES md.etude (id_etude) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE NO ACTION,
  CONSTRAINT fk_responsable_code_personne_references_personne_code_personne FOREIGN KEY (responsable_code_personne)
      REFERENCES md.personne (code_personne) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT "unique nom lot" UNIQUE (id_lot)
)
WITH (
  OIDS=FALSE
);
COMMENT ON TABLE md.lot_donnee
  IS 'Décrit les lots de données produits ou utilisé au CEN.';

/* On l'alimente avec cette vue */
-- View: md.description_lot
-- DROP VIEW md.description_lot;
CREATE OR REPLACE VIEW md.description_lot AS 
 WITH extent AS (
         SELECT COALESCE(saisie_observation.id_etude, 39) AS id_etude, 
            count(saisie_observation.id_obs) AS nb_donnees, 
            saisie_observation.id_protocole, 
            (
                CASE
                    WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Point%'::text THEN 'point'::text
                    WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%LineString%'::text THEN 'ligne'::text
                    WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Polygon%'::text THEN 'perimetre'::text
                    ELSE NULL::text
                END || '_'::text) || 
                CASE saisie_observation.regne
                    WHEN 'Plantae'::text THEN 'espece'::text
                    WHEN 'Animalia'::text THEN 'espece'::text
                    WHEN 'Fungi'::text THEN 'espece'::text
                    WHEN 'Habitat'::text THEN 'habitat'::text
                    ELSE NULL::text
                END, 
            'point_flore' AS table_nom, 
            round(st_xmin(st_extent(st_transform(saisie_observation.geometrie, 4326))::box3d)::numeric, 2) AS x_min, 
            round(st_ymin(st_extent(st_transform(saisie_observation.geometrie, 4326))::box3d)::numeric, 2) AS y_min, 
            round(st_xmax(st_extent(st_transform(saisie_observation.geometrie, 4326))::box3d)::numeric, 2) AS x_max, 
            round(st_ymax(st_extent(st_transform(saisie_observation.geometrie, 4326))::box3d)::numeric, 2) AS y_max
           FROM saisie.saisie_observation
          GROUP BY COALESCE(saisie_observation.id_etude, 39), saisie_observation.id_protocole, (
                CASE
                    WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Point%'::text THEN 'point'::text
                    WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%LineString%'::text THEN 'ligne'::text
                    WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Polygon%'::text THEN 'perimetre'::text
                    ELSE NULL::text
                END || '_'::text) || 
                CASE saisie_observation.regne
                    WHEN 'Plantae'::text THEN 'espece'::text
                    WHEN 'Animalia'::text THEN 'espece'::text
                    WHEN 'Fungi'::text THEN 'espece'::text
                    WHEN 'Habitat'::text THEN 'habitat'::text
                    ELSE NULL::text
                END
        )
 SELECT DISTINCT lot_donnee.id_lot, extent.nb_donnees, 
        CASE
            WHEN lot_donnee.libelle IS NULL THEN lot_donnee.code
            ELSE lot_donnee.libelle
        END AS lot_donnee_libelle, 
    lot_donnee.id_etude AS lot_donnee_id_etude, 
    (
        CASE
            WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Point%'::text THEN 'point'::text
            WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%LineString%'::text THEN 'ligne'::text
            WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Polygon%'::text THEN 'perimetre'::text
            ELSE NULL::text
        END || '_'::text) || 
        CASE saisie_observation.regne
            WHEN 'Plantae'::text THEN 'espece'::text
            WHEN 'Animalia'::text THEN 'espece'::text
            WHEN 'Habitat'::text THEN 'habitat'::text
            ELSE NULL::text
        END AS lot_donnee_type_donnee, 
    lot_donnee.resume AS lot_donnee_resume, 
    lot_donnee.description_genealogie AS lot_donnee_description_genealogie, 
    lot_donnee.echelle_utilisation AS lot_donnee_echelle_utilisation, 
    lot_donnee.licence AS lot_donnee_licence, 
    lot_donnee.limitation_acces_public AS lot_donnee_limitation_acces_public, 
    lot_donnee.qualite_thematique AS lot_donnee_qualite_thematique, 
    lot_donnee.id_protocole AS lot_donnee_id_protocole, 
    lot_donnee.id_etude AS etude_id_etude, etude.nom_etude AS etude_nom_etude, 
    etude.cahier_des_charges AS etude_cahier_des_charges, 
    etude.date_debut AS etude_date_debut, etude.date_fin AS etude_date_fin, 
    etude.description AS etude_description, 
    etude.lien_rapport_final AS etude_lien_rapport_final, 
    lot_donnee.id_protocole AS protocole_id_protocole, 
    protocole.resume AS protocole_resume, 
    protocole.libelle AS protocole_libelle, 
    protocole.auteurs AS protocole_auteurs, 
    protocole.id_biblio AS protocole_id_biblio, 
    (lower(spatial_ref_sys.auth_name::text) || ' '::text) || spatial_ref_sys.auth_srid AS srid, 
        CASE
            WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Point%'::text THEN 'point'::text
            WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%LineString%'::text THEN 'ligne'::text
            WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Polygon%'::text THEN 'perimetre'::text
            ELSE NULL::text
        END AS "case"
   FROM saisie.saisie_observation
   JOIN md.lot_donnee ON lot_donnee.id_protocole = saisie_observation.id_protocole AND lot_donnee.id_etude = saisie_observation.id_etude AND lot_donnee.type_donnee = (((
   CASE
       WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Point%'::text THEN 'point'::text
       WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%LineString%'::text THEN 'ligne'::text
       WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Polygon%'::text THEN 'perimetre'::text
       ELSE NULL::text
   END || '_'::text) || 
   CASE saisie_observation.regne
       WHEN 'Plantae'::text THEN 'espece'::text
       WHEN 'Animalia'::text THEN 'espece'::text
       WHEN 'Habitat'::text THEN 'habitat'::text
       ELSE NULL::text
   END)::md.enum_type_donnee)
   LEFT JOIN md.etude ON lot_donnee.id_etude = etude.id_etude
   LEFT JOIN md.protocole ON lot_donnee.id_protocole = protocole.id_protocole
   LEFT JOIN extent ON extent.id_protocole = saisie_observation.id_protocole AND extent.id_etude = saisie_observation.id_etude
   JOIN spatial_ref_sys ON st_srid(saisie_observation.geometrie) = spatial_ref_sys.srid
  ORDER BY lot_donnee.id_lot;
CREATE OR REPLACE VIEW export.sinp_dee_point_animalia AS 
 SELECT row_number() OVER (ORDER BY lpad(saisie_observation.id_obs::text, 7, '0'::text)) AS gid, 
        CASE saisie_observation.determination::text
            WHEN 'Vu'::text THEN 'te'::text
            WHEN 'Entendu'::text THEN 'te'::text
            WHEN 'Indice de présence'::text THEN 'te'::text
            WHEN 'Cadavre'::text THEN 'te'::text
            WHEN 'Capture'::text THEN 'te'::text
            WHEN 'Collection'::text THEN 'Co'::text
            WHEN 'Littérature'::text THEN 'Li'::text
            ELSE 'te'::text
        END AS statutsource, 
        CASE saisie_observation.determination::text
            WHEN 'Littérature'::text THEN 'à préciser'::text
            ELSE NULL::text
        END AS referencebiblio, 
    lpad(lot_donnee.id_lot::text, 4, '0'::text) AS jddid, 
    'SICEN-LR:00-175'::text AS jddcode, 
    lpad(saisie_observation.id_obs::text, 7, '0'::text) AS identifiantorigine, 
    NULL::text AS identifiantpermanent, 
        CASE
            WHEN lot_donnee.libelle::text ~~* 'bénévolat%'::text THEN 'Pr'::text
            WHEN saisie_observation.id_etude = ANY (ARRAY[39, 51]) THEN 'NSP'::text
            ELSE 'Ac'::text
        END AS dspublique, 
    NULL::text AS codeidcnpdispositif, 'CEN L-R'::text AS organismestandard, 
        CASE
            WHEN lower(saisie_observation.type_effectif) = 'absence'::text THEN 'No'::text
            ELSE 'Pr'::text
        END AS statutobservation, 
    btrim(pg_catalog.concat(saisie_observation.nom_vern, ' / ', saisie_observation.nom_complet), ' / '::text) AS nomcite, 
    saisie_observation.cd_nom::integer AS cdnom, 
    taxref.cd_ref::integer AS cdref, 'non'::text AS sensible, 
    COALESCE(saisie_observation.effectif, saisie_observation.effectif_min, 1::bigint)::integer AS denombrementmin, 
    COALESCE(saisie_observation.effectif, saisie_observation.effectif_max)::integer AS denombrementmax, 
        CASE
            WHEN saisie_observation.type_effectif ~~* ANY (ARRAY['abondance%'::text, 'classe%'::text]) THEN 'Es'::text
            ELSE 'Co'::text
        END AS typedenombrement, 
        CASE
            WHEN saisie_observation.type_effectif IS NOT NULL THEN 'In'::text
            ELSE NULL::text
        END AS objetdenombrement, 
        CASE
            WHEN saisie_observation.observateur = '20'::text THEN 'NSP'::text
            ELSE md.liste_nom_auteur(saisie_observation.observateur, ', '::text)
        END AS identiteobservateur, 
        CASE md.liste_nom_structure(saisie_observation.structure, ', '::text)
            WHEN 'Pas de structure'::text THEN 'indépendant'::text
            ELSE md.liste_nom_structure(saisie_observation.structure, ', '::text)
        END AS organismeobservateur, 
    'CEN L-R'::text AS organismegestionnairedonnees, 
        CASE
            WHEN saisie_observation.observateur <> '20'::text THEN md.liste_nom_auteur(saisie_observation.observateur, ', '::text)
            ELSE NULL::text
        END AS determinateur, 
    btrim(pg_catalog.concat(validateur.nom, ' ', validateur.prenom)) AS validateur, 
    saisie_observation.remarque_obs AS commentaire, 
    COALESCE(saisie_observation.date_obs, saisie_observation.date_debut_obs) AS datedebut, 
    COALESCE(saisie_observation.date_obs, saisie_observation.date_fin_obs) AS datefin, 
    NULL::time without time zone AS heuredebut, 
    NULL::time without time zone AS heurefin, 
    NULL::date AS datedeterminationobs, 
    saisie_observation.elevation::numeric AS altitudemin, 
    saisie_observation.elevation::numeric AS altitudemax, 
    NULL::numeric AS profondeurmin, NULL::numeric AS profondeurmax, 
    NULL::text AS codehabitat, NULL::text AS refhabitat, 
    st_asgml(saisie_observation.geometrie) AS geometrie, 
        CASE saisie_observation."precision"
            WHEN 'GPS'::saisie.enum_precision THEN 10
            WHEN '0 à 10m'::saisie.enum_precision THEN 10
            WHEN '10 à 100m'::saisie.enum_precision THEN 100
            WHEN '100 à 500m'::saisie.enum_precision THEN 500
            ELSE 1000
        END AS "precision", 
        CASE
            WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%POINT%'::text THEN 'St'::text
            WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%POLYGON%'::text OR st_geometrytype(saisie_observation.geometrie) ~~* '%LINE%'::text THEN 'In'::text
            ELSE 'NSP'::text
        END AS natureobjetgeo, 
    COALESCE(saisie_observation.code_insee, commune.code_insee::text) AS codecommune, 
    commune.nom AS nomcommune, NULL::text AS codeen, NULL::text AS typeen, 
    NULL::text AS codemaille, 
    saisie_observation.geometrie::geometry(Point,2154) AS geom, 
    st_x(saisie_observation.geometrie::geometry(Point,2154)) AS st_x, 
    st_y(saisie_observation.geometrie::geometry(Point,2154)) AS st_y
   FROM saisie.saisie_observation
   JOIN inpn.taxref USING (cd_nom)
   JOIN ign_bd_topo.commune ON st_intersects(commune.geometrie, saisie_observation.geometrie)
   LEFT JOIN md.lot_donnee ON saisie_observation.id_etude = lot_donnee.id_etude AND saisie_observation.id_protocole = lot_donnee.id_protocole AND ((
CASE
WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Point%'::text THEN 'point'::text
WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%LineString%'::text THEN 'ligne'::text
WHEN st_geometrytype(saisie_observation.geometrie) ~~* '%Polygon%'::text THEN 'perimetre'::text
ELSE NULL::text
END || '_'::text) || 
CASE saisie_observation.regne
    WHEN 'Plantae'::text THEN 'espece'::text
    WHEN 'Animalia'::text THEN 'espece'::text
    WHEN 'Fungi'::text THEN 'espece'::text
    WHEN 'Habitat'::text THEN 'habitat'::text
    ELSE NULL::text
END) = lot_donnee.type_donnee::text
   LEFT JOIN md.personne validateur ON saisie_observation.validateur = validateur.id_personne
  WHERE taxref.cd_nom::text ~ '^[\d+]'::text AND saisie_observation.regne = 'Animalia'::text 
  AND (md.liste_nom_structure(saisie_observation.structure, ', '::text) = ANY (ARRAY['CEN LR'::text, 'Pas de structure'::text])) 
  AND st_geometrytype(saisie_observation.geometrie) ~~* '%Point%'::text;

BDD : généraliser l'utilisation des types array

pour les colonnes obervateurs et strcutures qui utilisent des chaines de texte délimités, l'emploi du type array et des fonctions associées serait probablement plus propre et efficace. L'emploi des CTE (http://docs.postgresql.fr/9.3/queries-with.html) jouent elle aussi un rôle important :

Voici quelques pistes d'optimisation, sur la recherche de nom consistant à transformer le champ texte délimité en tableau :

SELECT observateur, string_to_array(observateur, ',') AS tab_obs FROM saisie.saisie_observation;

J'indexe la colonne tab_obs :

CREATE INDEX idx_test on temp.test_tableau USING GIN (tab_obs);

Tests de performance du filtre (les obs contenant 'ron' dans la liste des observateurs):

SELECT id_obs
FROM temp.test_tableau
WHERE md.liste_nom_auteur(observateur::text) ILIKE '%ron%';
/* -> 2700-3000 ms. C'est la méthode utilisée actuellement avec indexation de la fonction md.liste_nom_auteur(text) */

WITH observateur AS (select array_agg(distinct id_personne::text) AS tab from md.personne WHERE nom||' '||prenom ILIKE '%ron%')
SELECT id_obs FROM temp.test_tableau JOIN observateur ON tab_obs && tab
/* -> 40-50 ms */

La syntaxe sans CTE (c'est à dire sans la clause WITH en début de requête et avec une sous-requête) semble être aussi efficace :

SELECT id_obs FROM temp.test_tableau, (select array_agg(distinct id_personne::text) AS tab from md.personne WHERE nom||' '||prenom ILIKE '%ron%') AS observateur WHERE tab_obs && tab

La difficulté consiste à pouvoir implémenter ce filtre dans l'appli car actuellement on ajoute une clause where en fin de requête...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.