Action dans une popup
C’est une fonctionnalité dans Lizmap 3.4.
Principe
Ce module permet d’ajouter un ou plusieurs boutons d’action dans la popup Lizmap affichée pour un objet PostgreSQL, qui déclenchera une requête dans la base de données et renverra une **géométrie ** à afficher sur la carte.
Il lit un fichier de configuration JSON qui doit être placé à côté du projet QGIS dans le même répertoire. 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 un
layer_id
, unname
, untitle
, uneicon
, quelquesoptions
facultatives,style` ` et ``callbacks
. Une nouvelle propriétéconfirm
peut être utilisée depuis Lizmap 3.5Un calque peut avoir une ou plusieurs actions
Vous pouvez avoir un ou plusieurs calques avec leurs propres actions
Exemple avec ce fichier de configuration JSON, nom myproject.qgs.action
si le fichier de projet QGIS est nommé myproject.qgs
. Dans ce projet, il existe une couche vectorielle appelée Points
avec l’ID de couche interne points_a7e8943b_7138_4788_a775_f94cbd0ad8b6
(vous pouvez obtenir l’ID interne de la couche QGIS avec l’expression @layer_id
)
{
"points_a7e8943b_7138_4788_a775_f94cbd0ad8b6": [
{
"name": "buffer_500",
"title": "Buffer 500m around this object",
"confirm": "Do you really want to show the buffer ?",
"icon": "icon-leaf",
"options": {
"buffer_size": 500,
"other_param": "yes"
},
"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": "bati_1a016229_287a_4b5e_a4f7_a2080333f440"},
{"method": "redraw", "layerId": "bati_1a016229_287a_4b5e_a4f7_a2080333f440"}
]
}
]
}
Le fichier 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 Lizmapun
icon
qui sera affiché sur le bouton de l’action (voir https://getbootstrap.com/2.3.2/base-css.html#icons)une propriété facultative
confirm
, depuis Lizmap 3.5, contenant du texte. Si défini, une boîte de dialogue de confirmation sera affichée à l’utilisateur pour demander si l’action doit vraiment être lancée ou non. Utilisez-le si l’action peut modifier certaines données de votre base de données.un objet
options
, donnant quelques paramètres supplémentaires pour cette action. Vous pouvez ajouter n’importe quel paramètre nécessaire.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 demethod
, qui peut actuellement être :zoom
: zoome vers la géométrie retournéeselect
: sélectionnez les entités d’une couche donnée coupant la géométrie renvoyée. La couche cible QGIS internal ID doit être ajoutée dans la propriétélayerId
. Dans l’exemple, les entités de la couche contenant les bâtiments, l’IDbati_1a016229_287a_4b5e_a4f7_a2080333f440
sera sélectionnéredraw
: redessine (rafraîchit) une couche donnée dans la carte. 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. L’action titre
s’affichera en survolant le bouton d’action.
Chaque bouton déclenche l’action correspondante, s’il n’est pas encore actif (sinon il désactive et efface la géométrie) :
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. (Voir exemple ci-dessous)
Cette requête retourne un GeoJSON qui est ensuite affiché sur la carte.
Si des callbacks ont été configurés, ils sont lancés
Depuis Lizmap 3.5, un événement Lizmap
actionResultReceived
est émis avec les données et les propriétés de l’action.
La requête PostgreSQL créée est construite par le client Web Lizmap et utilise la fonction PostgreSQL lizmap_get_data(json)
qui doit être créée au préalable dans la table de la base de données PostgreSQL. Cette fonction utilise également une fonction plus générique query_to_geojson(text)
qui transforme n’importe quelle chaîne de requête PostgreSQL en une sortie GeoJSON.
Voici un exemple ci-dessous de la requête exécutée dans la base de données PostgreSQL par Lizmap Web Client en interne, pour l’exemple de configuration donné ci-dessus, lorsque les utilisateurs cliquent sur le bouton action buffer_500, pour l”entité avec l’id 1
de la couche Points
correspondant à la table PostgreSQL test.points
:
SELECT public.lizmap_get_data('{
"layer_name":"points",
"layer_schema":"test",
"layer_table":"points",
"feature_id":1,
"action_name":"buffer_500",
"buffer_size":500,
"other_param": "yes"
}') AS data;
Vous pouvez voir que Lizmap crée des paramètres JSON avec toutes les informations nécessaires et exécute la fonction PostgreSQL lizmap_get_data(text)
.
Vous devez créer cette fonction PostgreSQL lizmap_get_data(text)
qui renvoie un texte GeoJSON valide contenant un seul objet. Le code SQL suivant est un exemple pour vous aider à créer les fonctions nécessaires. Évidemment, vous devez l’adapter à vos besoins.
-- 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 valid GEOJSON from a given SQL text 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 buffer_500
-- Written here as an example
-- Performs a buffer on the geometry
IF action_name = 'buffer_500' THEN
datasource:= format('
SELECT
%1$s AS id,
''The buffer '' || %4$s || ''m has been displayed in the map'' AS message,
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,
''The geometry of the object have been displayed in the map'' AS message
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 valid 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 additional 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. Il vise à créer une requête pour chaque action, créée dynamiquement pour les paramètres donnés, et à renvoyer une représentation GeoJSON des données par rapport à la requête. Vous devriez avoir une seule entité renvoyée : utilisez l’agrégation si nécessaire. Dans l’exemple ci-dessus, nous utilisons la méthodeformat
pour définir le texte de la requête et la fonctionquery_to_geojson
pour renvoyer le GeoJSON pour cette requête.Vous pouvez utiliser tous les paramètres donnés (nom d’action, schéma de données source et nom de table, identifiant d’entité, nom de couche QGIS) pour créer la requête appropriée pour votre/vos action(s), en utilisant les clauses PostgreSQL
IF THEN ELSIF ELSE
. Voir le contenu de la variableparameters
dans l’exemple ci-dessus, contenant certaines des propriétés du fichier de configuration JSON et certaines propriétés de la couche QGIS :le nom de l’action
action_name
, par exemplebuffer_500
. Vous devez utiliser un mot simple avec uniquement des lettres, des chiffres et_
,QGIS nom de la couche (comme dans la légende QGIS) :
layer_name
, par exemplePoints
,le schema PostgreSQL de la table
layer_schema
et nom de la tablelayer_table
pour cette couche,l’objet feature id
feature_id
, qui correspond à la valeur du champ clé primaire de l’objet popup,les autres propriétés données dans le fichier de configuration JSON, dans la propriété
options
, commebuffer_size
qui vaut500
dans l’exemple
Le
IF ELSE
est utilisé pour faire une requête différente, construite dans la variabledatasource
, en vérifiant le nom de l’actionSi les données de retour contiennent un champ
message
, comme illustré dans l’exemple ci-dessus, le texte contenu dans ce champ sera affiché dans la carte dans une bulle de message.La géométrie renvoyée par la fonction sera affichée sur la carte.
Vous pouvez utiliser votre fonction pour éditer certaines données dans votre base de données, avant de renvoyer un GeoJSON. Pour ce faire, vous devez remplacer la propriété
IMMUTABLE
parVOLATILE
. Veuillez l’utiliser avec précaution !
Étant donné que Lizmap Web Client déclenche un événement actionResultReceived
à chaque fois que l’utilisateur clique sur un bouton d’action et que les données sont renvoyées (en même temps que la géométrie du résultat est dessinée sur la carte), vous pouvez utiliser votre propre code Javascript pour ajouter une logique après l’affichage du résultat.
Voir aussi
Chapitre Ajouter votre propre JavaScript
Par exemple, ici nous écrivons simplement dans la console du navigateur le contenu reçu :
lizMap.events.on({
actionResultReceived: function(e) {
// QGIS Layer id
var layerId = e.layerId;
console.log('Layer ID = ' + layerId);
// Feature ID, which means the value of the primary key field
var featureId = e.featureId;
console.log('Feature ID = ' + featureId);
// Action item with its name and other properties: name, title, options, styles, etc.
var action = e.action;
console.log('Action properties = ');
console.log(action);
// Features returned by the action
var features = e.features;
console.log('Returned object = ');
console.log(features);
}
});
Vous pouvez utiliser ces données à votre guise dans votre code JS.