Actions — Add some custom buttons

Tato funkce je součástí aplikace Lizmap 3.4.

Princip

Tento modul umožňuje přidat jedno nebo více akčních tlačítek do vyskakovacího okna Lizmap zobrazeného pro objekt PostgreSQL, které spustí dotaz v databázi a vrátí geometrii pro zobrazení na mapě.

Čte konfigurační soubor JSON, který musí být umístěn vedle projektu QGIS ve stejném adresáři. Tento soubor obsahuje seznam akcí PostgreSQL, které mají být přidány do popupu pro jednu nebo více vektorových vrstev QGIS PostgreSQL.

../../_images/publish-configuration-action-popup.gif

Konfigurace nástroje

  • Každá akce je charakterizována pomocí layer id, name, title, icon, lze použít některé volitelné vlastnosti options, style, callbacks a confirm.

  • Vrstva může mít jednu nebo více akcí.

  • Můžete mít jednu nebo více vrstev s vlastními akcemi.

Příklad tohoto konfiguračního souboru JSON, název myproject.qgs.action, pokud se soubor projektu QGIS jmenuje myproject.qgs. V tomto projektu existuje vektorová vrstva s názvem Points s interním ID vrstvy points_a7e8943b_7138_4788_a775_f94cbd0ad8b6 (interní ID vrstvy QGIS můžete získat pomocí výrazu @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"}
            ]
        }
    ]
}

Konfigurační soubor JSON obsahuje seznam vrstev QGIS, pro které chcete deklarovat akce. Každá vrstva je definována svým ID vrstvy QGIS, například zde points_a7e8943b_7138_4788_a775_f94cbd0ad8b6, a pro každé ID seznam objektů popisujících akce, které mají být povoleny.

Každá akce je objekt definovaný:

  • a name, což je identifikátor akce.

  • title, který se používá jako popisek v rozhraní Lizmap

  • ikona, která se zobrazí na akčním tlačítku ( viz https://getbootstrap.com/2.3.2/base-css.html#icons ).

  • nepovinná vlastnost potvrzení, od Lizmap 3.5 obsahující nějaký text. Je-li 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ý parametr.

  • objekt style umožňující konfigurovat vrácený styl geometrie. Řídí se atributy stylů OpenLayers.

  • objekt callbacks umožňuje spustit některé akce po vrácení vygenerované geometrie. Jsou definovány jménem method, které v současnosti může být:

    • zoom: přiblížení vrácené geometrie

    • select: vybere prvky z dané vrstvy, které protínají vrácenou geometrii. Ve vlastnosti layerId musí být přidáno interní ID cílové vrstvy QGIS. V příkladu budou vybrány prvky vrstvy obsahující budovy s ID bati_1a016229_287a_4b5e_a4f7_a2080333f440.

    • redraw: překreslí (obnoví) danou vrstvu v mapě. ID cílové vrstvy QGIS musí být přidáno do vlastnosti layerId.

Lizmap zjistí přítomnost tohoto konfiguračního souboru a při načítání mapy přidá potřebnou logiku. Když uživatelé kliknou na objekt jedné z těchto vrstev v mapě, zobrazí se na rozbalovacím panelu údaje o prvku. V horní části každého vyskakovacího panelu se na panelu nástrojů zobrazí jedno tlačítko pro každou akci vrstvy. Po najetí na tlačítko akce se zobrazí její název.

Každé tlačítko spustí příslušnou akci, pokud ještě není aktivní (jinak se deaktivuje a geometrie se vymaže):

  • Backend Lizmap kontroluje, zda je akce dobře nakonfigurována,

  • vytvoří dotaz PostgreSQL a provede jej ve vrstvě databáze PostgreSQL. (Viz příklad níže)

  • Tento dotaz vrátí GeoJSON, který se poté zobrazí na mapě.

  • Pokud byly nakonfigurovány některé zpětné odkazy, spustí se.

  • Od Lizmap 3.5 je emitována událost Lizmap actionResultReceived s vrácenými daty a vlastnostmi akce.

Vytvořený dotaz 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 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 příkladovou konfiguraci, když uživatel klikne na tlačítko akce buffer_500`, pro funkci s id 1 vrstvy Points odpovídající tabulce 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;

Vidíte, že Lizmap vytvoří parametry JSON se všemi potřebnými informacemi a spustí funkci PostgreSQL lizmap_get_data(text).

Je třeba vytvořit tuto funkci PostgreSQL lizmap_get_data(text), která vrátí platný text GeoJSON s jedním jediným objektem. Následující kód SQL je příkladem, který vám pomůže vytvořit potřebné funkce. Je zřejmé, že je třeba jej upravit podle svých potřeb.

-- 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.';
  • 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 metodu formát pro nastavení textu dotazu a funkci query_to_geojson pro vrácení formátu GeoJSON pro tento dotaz.

  • Pomocí klauzulí PostgreSQL IF THEN ELSIF ELSE můžete použít všechny zadané parametry (název akce, schéma zdrojových dat a název tabulky, ID prvku, název vrstvy QGIS) k vytvoření vhodného dotazu pro vaši akci (akce). Viz obsah proměnné parameters ve výše uvedeném příkladu, která obsahuje některé vlastnosti konfiguračního souboru JSON a některé vlastnosti vrstvy QGIS:

    • název akce název_akce, například buffer_500. Měli byste použít jednoduché slovo obsahující pouze písmena, číslice a _,

    • QGIS název vrstvy (jako v legendě QGIS): název_vrstvy, například Body,

    • schema tabulky PostgreSQL layer_schema a název tabulky layer_table pro tuto vrstvu,

    • id objektu feature feature_id, které odpovídá hodnotě pole primární klíč pro vyskakovací objekt,

    • další vlastnosti uvedené v konfiguračním souboru JSON ve vlastnosti options, například buffer_size, která je v příkladu 500.

  • 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ě.

  • Funkci můžete použít k úpravě některých dat v databázi a teprve poté vrátit soubor GeoJSON. K tomu je třeba nahradit vlastnost IMMUTABLE za VOLATILE. Používejte ji prosím opatrně !

Vzhledem k tomu, že Lizmap Web Client spouští událost actionResultReceived pokaždé, když uživatel klikne na tlačítko akce, a data jsou vrácena (ve stejnou dobu, kdy je geometrie výsledku vykreslena na mapě), můžete použít vlastní kód Javascriptu a přidat nějakou logiku po zobrazení výsledku.

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.