Akce - Přidání několika vlastních tlačítek spouštějících dotazy PostgreSQL
Princip
Tento modul umožňuje přidat jednu nebo více akcí do webového rozhraní. Koncept byl inspirován QGIS actions, které lze použít ke spouštění skriptů uvnitř QGIS.
Příklad akce funkce:
V současné době je jediným motorem pro akce Lizmap dotazy PostgreSQL (Python nebude podporován). K přidání specifické logiky do webové mapy můžete využít výkon PostgreSQL a PostGIS.
Varování
Akce Lizmap se proto liší od nativních akcí QGIS a nejsou vzájemně kompatibilní.
Když uživatel klikne na akční tlačítko, odešle Lizmap Web Client dotaz do databáze PostgreSQL s aktuálními kontextovými údaji (rozsah mapy, ID prvku atd.).
S těmito parametry se volá specifická funkce lizmap_get_data
, která vrací odpověď GeoJSON obsahující jeden nebo více prvků vygenerovaných dotazem SQL pro danou akci.
Webový klient Lizmap pak z této odpovědi spustí některé zpětné vazby:
přiblížení nebo vycentrování vrácené geometrie,
výběr prvků jiné vrstvy, které protínají vrácenou geometrii,
zobrazení zprávy atd.
Podporovány jsou tři akční oblasti :
project
: položka nabídky akcí je přidána na levý panel nabídky, pokud má mapa alespoň jednu akci projektu. Na novém panelu se zobrazí výběr akce a tlačítko pro spuštění vybrané akce.layer
: výběr akce se zobrazí v panelu Informace o vrstvě, který je viditelný po kliknutí na tlačítko (i) vpravo od názvu vrstvy.feature
: na vyskakovací panel nástrojů jsou přidána akční tlačítka pro funkce vrstvy, která umožňují spustit akci specifickou pro každou funkci.
Tip
Pro rozsah project
se použije výchozí databáze (soubor profiles.ini.php
v kapitole configuration.
Příklad výběru akce:
Ukázka
Ukázku o požárních hydrantech si můžete prohlédnout na ukázkové webové stránce.
Klikněte na požární hydrant a
buď vyberte budovy, které jsou ve vzdálenosti do 150 m
nebo najděte nejbližší hasičskou stanici
Předpoklady
Určité znalosti
SQL
aJSON
Chcete-li použít zpětné volání
select
, musí mít vaše vrstva povolen select. Viz Tabulka atributů - Konfigurace tabulky atributů a výběru vektorůVrstva musí být publikována jako WFS (viz WFS/OAPI) a primární klíč musí být také publikován v Vlastnosti vrstvy.
Konfigurace nástroje
V současné době nelze akce konfigurovat ze zásuvného modulu Lizmap v QGIS. Je třeba napsat zvláštní konfigurační soubor JSON a umístit jej vně projektu QGIS do stejného adresáře. Tento soubor obsahuje seznam akcí PostgreSQL, které mají být přidány do mapy.
Varování
V modulu Lizmap 3.7 se změnila syntaxe JSON.
Pokud používáte starou syntaxi JSON, zobrazí se v aplikaci Lizmap varování s výzvou k přechodu na novější verzi syntaxe.
- Každá akce je charakterizována
name
,title
,scope
,layers
,icon
, některými volitelnýmioptions
, Lze použít vlastnosti
style
,callbacks
aconfirm
.
Akci lze navrhnout pro seznam
layers
: V polilayers
by měly být použity identifikátory vrstev QGIS.Akce může mít seznam
callbacks
.
Příklad konfiguračního souboru JSON s názvem fire_hydrant_actions.qgs.action
, pokud se soubor projektu QGIS jmenuje fire_hydrant_actions.qgs
. V tomto projektu existuje vektorová vrstva s názvem Požární hydranty
s interním ID vrstvy emergency_fire_hydrant_04132268_86fb_4d5e_a426_ce3133494091
. Interní ID vrstvy QGIS můžete získat pomocí výrazu QGIS @layer_id
.
[
{
"name": "buffer_150",
"title": "Buildings in the fire hydrant area (150m)",
"scope": "feature",
"layers" : [
"emergency_fire_hydrant_04132268_86fb_4d5e_a426_ce3133494091"
],
"confirm": "Do you want to select buildings within 150m from this fire hydrant ?",
"icon": "icon-home",
"options": {
"buffer_size": 150,
"other_param": "yes"
},
"style": {
"graphicName": "circle",
"pointRadius": 6,
"fill": true,
"fillColor": "lightred",
"fillOpacity": 0.3,
"stroke": true,
"strokeWidth": 4,
"strokeColor": "red",
"strokeOpacity": 0.8
},
"callbacks": [
{"method": "zoom"},
{"method": "select", "layerId": "building_90f7692a_0ae2_4a7d_91de_b63cddb92963"}
]
},
{
"name": "closest_fire_station",
"title": "Find the closest fire station from this fire hydrant",
"scope": "feature",
"layers" : [
"emergency_fire_hydrant_04132268_86fb_4d5e_a426_ce3133494091"
],
"confirm": "Do you want to select the closest fire station from this fire hydrant ?",
"icon": "icon-resize-small",
"options": {},
"style": {
"graphicName": "circle",
"pointRadius": 6,
"fill": true,
"fillColor": "lightred",
"fillOpacity": 0.3,
"stroke": true,
"strokeWidth": 4,
"strokeColor": "red",
"strokeOpacity": 0.8
},
"callbacks": [
{"method": "zoom"},
{"method": "select", "layerId": "stations_1a71d61f_cb99_4ac4_8bd4_86304af9be44"}
]
}
]
Konfigurační soubor JSON obsahuje seznam deklarovaných akcí.
Každá akce je objekt definovaný:
a
name
, což je identifikátor akce.title
, který se používá jako popisek v rozhraní Lizmapscope
, který může být:project
,layer
nebofeature
.icon
, která se zobrazí na tlačítku akce (viz dokumentace k Bootstrap). Místo ikony bootstrapu lze jako pozadí vyskakovacích akčních tlačítek použít ikonu SVG. Použijte relativní cestu k médiím (Media).nepovinná vlastnost
potvrzení
, která obsahuje nějaký text. Pokud je nastavena, zobrazí se uživateli potvrzovací dialogové okno s dotazem, zda má být akce skutečně spuštěna, nebo ne. Použijte ji, pokud akce může změnit některá data v databázi.objekt
options
, který udává některé další parametry pro tuto akci. Můžete přidat libovolné potřebné parametry. Všimněte si, že tyto parametry jsou pevně zakódovány a uživatel je nemůže měnit.objekt
style
, který umožňuje nastavit styl vrácené geometrie. Řídí se atributy stylu OpenLayers.objekt
callbacks
umožňuje spustit některé akce po vrácení vygenerované geometrie. Jsou definovány jménemmethod
, které v současnosti může být:zoom
: přiblížení vrácené geometrieselect
: vybere prvky z dané vrstvy, které protínají vrácenou geometrii. Ve vlastnostilayerId
musí být přidáno interní ID cílové vrstvy QGIS. V příkladu budou vybrány prvky vrstvy obsahující budovy s IDbuilding_90f7692a_0ae2_4a7d_91de_b63cddb92963
.redraw
: překreslí (obnoví) danou vrstvu v mapě. ID cílové vrstvy QGIS musí být přidáno do vlastnostilayerId
.
Jak Lizmap používá tento konfigurační soubor ke spouštění akcí
Lizmap zjistí přítomnost tohoto konfiguračního souboru a při načítání mapy přidá potřebnou logiku.
Například u akcí s rozsahem feature
se po kliknutí na objekt jedné z vrstev akce v mapě zobrazí vyskakovací panel s údaji o funkci. V horní části každého vyskakovacího panelu je na panelu nástrojů zobrazeno jedno tlačítko pro každou akci vrstvy. Po najetí na tlačítko akce se zobrazí její title
.
Každé tlačítko spustí příslušnou akci, pokud ještě není aktivní (jinak se deaktivuje a vymaže geometrii na mapě):
Backend Lizmap kontroluje, zda je akce dobře nakonfigurována,
vytvoří PostgreSQL dotaz
VYBERTE veřejnou.lizmap_get_data(json)
s parametry zapsanými v JSON a provede jej ve vrstvě PostgreSQL databáze. (Viz příklad níže)Tento dotaz vrátí GeoJSON, který se poté zobrazí na mapě.
Pokud byly nakonfigurovány některé
callbacks
, spustí se (selection
,zoom
,redraw
).Je emitována událost Lizmap
actionResultReceived
s vrácenými daty a vlastnostmi akce. To umožňuje uživatelsky definovaným Javascriptovým skriptům používat výsledky akce.
Dotaz vytvořený v PostgreSQL je sestaven webovým klientem Lizmap a používá funkci PostgreSQL lizmap_get_data(json)
, která musí být předem vytvořena v databázi tabulek PostgreSQL. Tato funkce také používá obecnější funkci query_to_geojson(text)
, která transformuje libovolný řetězec dotazu PostgreSQL na výstup GeoJSON.
Níže je uveden příklad dotazu, který interně provede Lizmap Web Client v databázi PostgreSQL,
pro výše uvedenou ukázkovou konfiguraci,
když uživatel klikne na tlačítko akce buffer_150,
pro prvek s id
2592251664
vrstvyPožární hydranty
odpovídající tabulce PostgreSQL
fire_hydrant_actions.emergency_fire_hydrant
:
SELECT public.lizmap_get_data('{
"lizmap_repository": "features",
"lizmap_project": "fire_hydrant_actions",
"action_name": "buffer_150",
"action_scop": "feature",
"layer_name": "Fire hydrant",
"layer_schema": "fire_hydrant_actions",
"layer_table": "emergency_fire_hydrant",
"feature_id": 2592251664,
"map_center": "POINT(3.4345918 43.63399141565576)",
"map_extent": "POLYGON((3.429635077741169 43.63175113378633,3.439548522258832 43.63175113378633,3.439548522258832 43.63623161401291,3.429635077741169 43.63623161401291,3.429635077741169 43.63175113378633))",
"wkt": "",
"buffer_size":150,
"other_param": "yes"
}') AS data;
Vidíte, že Lizmap vytvoří parametr JSON se všemi potřebnými informacemi a spustí funkci PostgreSQL lizmap_get_data(text)
.
Aktuální rozsah mapy a střed mapy jsou rovněž odeslány jako parametry ve formátu WKT (projekce EPSG:4326
) a lze je použít ve funkci PostgreSQL.
Povinné funkce PostgreSQL
Musíte vytvořit tyto funkce PostgreSQL:
query_to_geojson(text)
, který vrací platný text GeoJSON z libovolného dotazu SELECTlizmap_get_data(text)
, což je „řídicí věž“ akcí Lizmap: vytvoří specifický dotaz pro každou akci na základě parametrů a poté spustí dotaz a vrátí GeoJSON
Následující kód SQL je příklad, který vám pomůže vytvořit potřebné funkce. Je zřejmé, že je musíte přizpůsobit svým potřebám.
-- 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 public.lizmap_get_data(parameters json)
RETURNS json AS
$$
DECLARE
feature_id varchar;
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')::varchar;
layer_name:= parameters->>'layer_name';
layer_schema:= parameters->>'layer_schema';
layer_table:= parameters->>'layer_table';
-- Action buffer_150
-- Performs a buffer on the geometry
IF action_name = 'buffer_150' THEN
datasource:= format('
SELECT %1$s AS id,
''Buildings within 150m of the fire hydrant have been selected'' AS message,
ST_Buffer(geom, 150) AS geom
FROM "%2$s"."%3$s"
WHERE osm_id = ''%1$s''
',
feature_id,
layer_schema,
layer_table
);
ELSEIF action_name = 'closest_fire_station' THEN
-- Draw a line to the closest fire station
datasource:= format('
WITH tmp_hydrant AS (
SELECT geom FROM fire_hydrant_actions.emergency_fire_hydrant WHERE osm_id = ''%1$s''
)
SELECT
id, name, ST_Distance(hydrant.geom, stations.geom),
''The closest is : '' || stations.name || '', '' || ST_Distance(hydrant.geom, stations.geom)::integer || ''m, flying air distance'' AS message,
ST_MakeLine(stations.geom, hydrant.geom) AS geom,
stations.id AS station_id
FROM
fire_hydrant_actions.stations stations,
tmp_hydrant hydrant
ORDER BY ST_Distance(hydrant.geom, stations.geom)
LIMIT 1
',
feature_id
);
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 public.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.';
Jako příklad je zde uvedena funkce
lizmap_get_data(json)
. Jelikož se jedná o klíčový vstupní bod, musíte si ji přizpůsobit svým potřebám. Jejím cílem je vytvořit dotaz pro každý název akce, dynamicky vytvořený pro zadané parametry, a vrátit reprezentaci dat výsledku dotazu ve formátu GeoJSON. Měli byste mít vrácenou pouze jednu funkci: v případě potřeby použijte agregaci. Ve výše uvedeném příkladu použijeme metoduformát
pro nastavení textu dotazu a funkciquery_to_geojson
pro vrácení formátu GeoJSON pro tento dotaz.Můžete použít všechny dané parametry (název akce, schéma zdrojových dat a název tabulky, id funkce, název vrstvy QGIS) k vytvoření příslušného dotazu pro vaše akce(akcí) pomocí PostgreSQL
IF THEN ELSIF ELSE
klauzule. Podívejte se na obsah proměnnéparametry
v příkladu výše, který obsahuje některé vlastnosti konfiguračního souboru JSON a některé vlastnosti vrstvy QGIS:Lizmap úložiště a projektové klíče mapy:
lizmap_repository
&lizmap_project
akce název
action_name
, napříkladbuffer_150
. Měli byste použít jednoduché slovo pouze s písmeny, číslicemi a_
,akce rozsah
action_scope
, napříkladfeature
,QGIS název vrstvy (jako v legendě QGIS):
layer_name
, napříkladFire hydrant
, pouze pro akcefeature
,tabulka PostgreSQL schéma
layer_schema
a název tabulkylayer_table
pro vrstvu, pouze pro akce s rozsahemfeature
alayer
objekt feature id
feature_id
, který odpovídá hodnotě pole primárního klíče pro vyskakovací objekt, pouze pro akcefeature
,ostatní vlastnosti uvedené v konfiguračním souboru JSON ve vlastnosti
options
, jako jebuffer_size
, což je v příkladu150
střed mapy
map_center
a rozsah mapymap_extent
Příkaz
IF ELSE
slouží k provedení jiného dotazu, sestaveného v proměnnédatasource
, a to kontrolou názvu akce.Pokud vrácená data obsahují pole
zpráva
, jak je uvedeno v příkladu výše, text obsažený v tomto poli se zobrazí v mapě v bublině se zprávou.Geometrie vrácená funkcí se zobrazí na mapě.
Svou funkci můžete použít k úpravě některých dat ve vaší databázi, než vrátíte GeoJSON. Chcete-li tak učinit, musíte nahradit vlastnost
IMMUTABLE
parVOLATILE
. Prosím POUŽÍVEJTE JI OPATRNĚ!
Akce a uživatelsky definované skripty JavaScript
Vzhledem k tomu, že webový klient Lizmap spouští událost actionResultReceived
, kdykoli uživatel klikne na tlačítko akce, a data jsou vrácena (ve stejné době, kdy je geometrie výsledku nakreslena na mapě), můžete použít vlastní kód JavaScript pro přidání nějaké logiky po zobrazení výsledku.
Viz také
Kapitola Přidání vlastního JavaScriptu
Například zde pouze zapíšeme do konzoly prohlížeče přijatý obsah:
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);
}
});
Tyto údaje můžete libovolně použít v kódu JS.
Akce lze také spouštět z externích skriptů JavaScript: můžete použít akce veřejné metody ke spuštění akce nebo resetování aktivní akce:
// Run an action
lizMap.mainLizmap.action.runLizmapAction(actionName, scope = 'feature', layerId = null, featureId = null, wkt = null);
// Reset the action
lizMap.mainLizmap.action.resetLizmapAction()
Geometrii WKT v EPSG:4326
lze také odeslat jako další parametr. To je možné pouze při spuštění akce pomocí JavaScriptu. To umožňuje odeslat geometrii, kterou použije akční funkce PostgreSQL lizmap_get_data
jako vlastnost proměnné SQL parameters
. (například pro získání dat z jiné tabulky s geometriemi protínajícími tuto předanou geometrii WKT)