Action dans une popup

C’est une fonctionnalité dans Lizmap 3.4.

Principe

Ce module permet l’ajout de boutons d’action dans la popup qui déclencheront des requêtes PostgreSQL et retourneront une géométrie à afficher sur la carte.

Il lit un fichier de configuration JSON qui doit être placé à côté du projet QGIS. Ce fichier répertorie les actions PostgreSQL à ajouter dans la popup pour une ou plusieurs couches vectorielles QGIS PostgreSQL.

Configurer l’outil

Chaque action est caractérisée par une couche, un nom, un titre, une icône, quelques options facultatives, style et callbacks.

Exemple de ce fichier de configuration JSON, nom myproject.qgs.action si le fichier de projet QGIS est nommé myproject.qgs :

{
    "points_a7e8943b_7138_4788_a775_f94cbd0ad8b6": [
        {
            "name": "liztest",
            "title": "Tampon",
            "icon": "icon-leaf",
            "options": {
                "buffer_size": 5000
            },
            "style": {
                "graphicName": "circle",
                "pointRadius": 6,
                "fill": true,
                "fillColor": "lightblue",
                "fillOpacity": 0.3,
                "stroke": true,
                "strokeWidth": 4,
                "strokeColor": "blue",
                "strokeOpacity": 0.8
            },
            "callbacks": [
                {"method": "zoom"},
                {"method": "select", "layerId": "admin_level_8_fcfdc9e0_c9b9_4563_b803_e36f9e2eca6a"},
                {"method": "redraw", "layerId": "admin_level_8_fcfdc9e0_c9b9_4563_b803_e36f9e2eca6a"}
            ]
        }
    ]
}

Le fichier de configuration JSON répertorie les couches QGIS pour lesquelles vous souhaitez déclarer des actions. Chaque couche est définie par son ID de couche QGIS, par exemple ici points_a7e8943b_7138_4788_a775_f94cbd0ad8b6, et pour chaque ID, une liste d’objets décrivant les actions à autoriser. Chaque action est un objet défini par :

  • un name qui est l’identifiant de l’action.

  • un title qui est utilisé comme étiquette dans l’interface Lizmap

  • un icon qui sera affiché sur le bouton de l’action (voir https://getbootstrap.com/2.3.2/base-css.html#icons)

  • un objet options afin de donner des paramètres supplémentaires à l’action

  • un objet style permettant de configurer le style de géométrie renvoyé. Il suit les attributs de style OpenLayers.

  • un objet callbacks permet de déclencher certaines actions après le retour de la géométrie générée. Ils sont définis par un nom de method, qui peut actuellement être :

    • zoom: zoome vers la géométrie retournée

    • select : sélectionnez les entités d’une couche donnée intersectant la géométrie renvoyée. L’ID QGIS de la couche cible doit être ajouté dans la propriété layerId

    • redraw : redessine une couche donné. L’ID QGIS de la couche cible doit être ajouté dans la propriété layerId.

Lizmap détecte la présence de ce fichier de configuration et ajoute la logique nécessaire lors du chargement de la carte. Lorsque les utilisateurs cliquent sur un objet de l’une de ces couches sur la carte, le panneau contextuel affiche les données de l’entité. En haut de chaque élément contextuel, une barre d’outils affichera un bouton pour chaque action de couche.

Chaque bouton déclenche l’action correspondante :

  • l’application Lizmap vérifie si l’action est bien configuré,

  • crée la requête PostgreSQL et l’exécute dans la couche de base de données PostgreSQL.

  • Cette requête retourne un GeoJSON qui est ensuite affiché sur la carte.

The created query is build up by Lizmap web client and uses the PostgreSQL function lizmap_get_data(json) which must be created beforehand in the PostgreSQL database. This function also uses a more generic function query_to_geojson(text) which transforms any PostgreSQL query into a GeoJSON output. Here is an example below of the query executed by Lizmap, for the example configuration given above, when the users clicks on the button action liztest, for the feature with id 1 of the layer points corresponding to the PostgreSQL table test.points:

SELECT public.lizmap_get_data('{"layer_name":"points","layer_schema":"test","layer_table":"points","feature_id":1,"action_name":"liztest","buffer_size":5000}') AS data

Vous pouvez voir que Lizmap crée un paramètre JSON avec toutes les informations nécessaires et exécute la fonction PostgreSQL lizmap_get_data. Le code SQL suivant vous permet de créer les fonctions nécessaires :

-- Returns a valid GeoJSON from any query
CREATE OR REPLACE FUNCTION query_to_geojson(datasource text)
RETURNS json AS
$$
DECLARE
    sqltext text;
    ajson json;
BEGIN
    sqltext:= format('
        SELECT jsonb_build_object(
            ''type'',  ''FeatureCollection'',
            ''features'', jsonb_agg(features.feature)
        )::json
        FROM (
          SELECT jsonb_build_object(
            ''type'',       ''Feature'',
            ''id'',         id,
            ''geometry'',   ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,
            ''properties'', to_jsonb(inputs) - ''geom''
          ) AS feature
          FROM (
              SELECT * FROM (%s) foo
          ) AS inputs
        ) AS features
    ', datasource);
    RAISE NOTICE 'SQL = %s', sqltext;
    EXECUTE sqltext INTO ajson;
    RETURN ajson;
END;
$$
LANGUAGE 'plpgsql'
IMMUTABLE STRICT;
COMMENT ON FUNCTION query_to_geojson(text) IS 'Generate a valide GEOJSON from a given SQL query.';

-- Create a query depending on the action, layer and feature and returns a GeoJSON.
CREATE OR REPLACE FUNCTION lizmap_get_data(parameters json)
RETURNS json AS
$$
DECLARE
    feature_id integer;
    layer_name text;
    layer_table text;
    layer_schema text;
    action_name text;
    sqltext text;
    datasource text;
    ajson json;
BEGIN

    action_name:= parameters->>'action_name';
    feature_id:= (parameters->>'feature_id')::integer;
    layer_name:= parameters->>'layer_name';
    layer_schema:= parameters->>'layer_schema';
    layer_table:= parameters->>'layer_table';

    -- Action liztest
    -- Written here as an example
    -- Performs a buffer on the geometry
    IF action_name = 'liztest' THEN
        datasource:= format('
            SELECT
            %1$s AS id,
            ST_Buffer(geom, %4$s) AS geom
            FROM "%2$s"."%3$s"
            WHERE id = %1$s
        ',
        feature_id,
        layer_schema,
        layer_table,
        parameters->>'buffer_size'
        );
    ELSE
    -- Default : return geometry
        datasource:= format('
            SELECT
            %1$s AS id,
            geom
            FROM "%2$s"."%3$s"
            WHERE id = %1$s
        ',
        feature_id,
        layer_schema,
        layer_table
        );

    END IF;

    SELECT query_to_geojson(datasource)
    INTO ajson
    ;
    RETURN ajson;
END;
$$
LANGUAGE 'plpgsql'
IMMUTABLE STRICT;
COMMENT ON FUNCTION lizmap_get_data(json) IS 'Generate a valide GEOJSON from an action described by a name, PostgreSQL schema and table name of the source data, a QGIS layer name, a feature id and additionnal options.';

La fonction lizmap_get_data(json) est fournie ici à titre d’exemple. Puisqu’il s’agit du point d’entrée clé, vous devez l’adapter à vos besoins.

Vous pouvez utiliser tous les paramètres donnés (nom de l’action, schéma de données source et nom de la table, identifiant de l’entité, nom de la couche QGIS) pour créer la requête appropriée pour votre/vos action(s), en utilisant les clauses PostgreSQL IF THEN ELSIF ELSE.