The modules are customizable extensions to the OpenBioMaps web application. There are project-level modules (e.g., PostgreSQL repository creation, photo manager), and modules specific to individual data tables (e.g., text filters for the map page, CSV export).
Modules can be assigned to different users or user groups.
The modules are linked to module hooks in the application, which are mostly located on the map page and profile tab. Most modules can be configured with simple parameters (JSON), but some modules have a custom administrative interface.
Module administration¶
The modules can be enabled and configured on the project_administration -> modules page.
Add a custom module¶
You can upload your modules and add them to your project. To develop a module, check out the example modules in modules/examples/.
Module access¶
You can add each module to your list several times. This allows us to give each module multiple access levels. This is important for modules where we want to give different access to different users or groups, for example, the allowed_columns module. Another example is that if we have multiple data tables, we can specify, for each table separately, which column values we can filter by when querying, for example, using the text_filter module. In the Access column, we can choose whether our settings are public (everybody) or only logged-in users (logged-in users) can use the given option. In the Group Access column, we can further refine our access options by selecting predefined groups or assigning specific people to a particular setting.
Drop a module¶
Currently, there is no such option.
Turn off a module¶
Once we have our list of modules, we can switch each module on and off.
Parameters for modules¶
Most modules can be directly parameterised with JSON format parameters. Some modules have their administrative tab, through which administrative tasks related to the module can be performed. An example is the box_load_selection module.
Project-level modules¶
box_load_selection¶
Allows you to upload your spatial shapes (points, lines, polygons). These are usually SHP files, but can also be other standard spatial data formats.
The uploaded spatial shapes can be used by users for data queries or data uploads. In both cases, the spatial object can be used to refer to the shape name, either to spatially delimit the data query or to specify the spatial location of the uploaded data record.
Uploaded spatial objects can be shared with other users, who can decide whether they want to use these shapes. By default, newly uploaded spatial shapes are not visible to other users. To use objects uploaded by others, you need to allow queries or data uploads. Project owners can set these permissions for each user for each spatial object.
Users can access spatial shapes via the “Shared Geometries “ module block found in the module section at the bottom of their profile page. Project administrators can make these settings in the administration interface of the box_load_selection module, on the module settings tab.
Once the module is activated, the “Spatial query “ box appears on the Map page. Here you will see a drop-down list of the names of the spatial shapes available to you, from which you can perform a spatial query on the database. In the case of a polygon, you can choose to query only the data that is inside the polygon or also the data that falls under the edges of the polygon.
For web and file uploads, if the “obm_geometry “ column type is used for coordinate capture, clicking on the map marker icon in a pop-up window will display a drop-down menu with “geometry from list “, in which you can select the required spatial shape by name, for which the application will load the WKT coordinate into the corresponding geometry field of the upload form.
The spatial shapes available for upload will also be downloaded by the mobile app and will be semi-transparently drawn on the map in the upload forms, labelled with their names.
No parameters
photos¶
Enable the use of photo or other attachment boxes on upload forms and show attached images on the data sheet page.
No parameters
create_pg_user¶
After enabling the module, the Create Postgres user box will appear on the profile page.
By enabling the module, users who are granted the right to use the module will be able to create their own Postgres user.
By default, the module creates a POSTGRES user with limited access, who can read all database tables in your project. He can connect to the database from only one client program at a time, and his access automatically expires after 1 year.
The created Postgres user will be added to the *project_name*_user group, which is the Postgres Group automatically created by the system. With Postgres admin access, you can grant additional rights to certain users, e.g., write access to specific tables.
Users can renew their access at any time.
The Postgres user can be used to connect to the database from QGIS, for example. An example of how to set this up:
No parameters
computation¶
No parameters
custom_filetype¶
Custom file preparation. E.g. observado style CSV
No parameters
taxon_meta¶
No parameters
Table-level modules¶
additional_columns¶
If a database consists of several data tables, they can be linked by different variables.
When queried, all data for an identifier is queried. This function can be ignored by checking “ignore table JOINS “ on the map page.
For example, in some burrow projects, we keep the data for parents and offspring in separate tables. If we want to get all the data for a burrow, we can specify the “odu_asonosito “ column as the “join” variable.
Use it together with the join_tables module
return with an array: co [0] columns array c [1] column name assoc array
Parameters:
["column names"]
allowed_columns¶
This is an extension of data access rule settings. The rules control access to complete rows in tables.
With this module, you can set which column should be visible at different access levels if there is row level restriction by rules (‘restricted’, ‘no-geom’).
It can be used only if the basic access level of the project is not public, and maybe if the data table has a “rules “ table.
Parameters:
{
"for_sensitive_data": [
"List of columns we want to make visible for sensitive records."
]
"for_no-geom_data": [
"List of columns we want to make visible for no-geom rows. If not set, all columns are accessible"
]
"for_general": [
"List of columns we want to make visible if there are no rules. If not set, all columns are restricted."
]
}
bold_yellow¶
Column names in yellow bold in the result lists. After a query, column names in bold yellow appear in the detailed description attached to the “Drop-down list “ table.
This module is also used to specify which data should be displayed in the “Recorded data “ summary labels in the mobile application.
Parameters:
["column names"]
box_load_coord¶
On the map page, a “position “ block will appear below the map. If you move the cursor around the map, you will see that the coordinate in the “position “ block is constantly changing, tracking the position of your cursor on the map.
Also in the “position “ block, if you type in the latitude and longitude, clicking on the little black “lollipop “ will display your point on the map.
Parameters:
{
"wgs84": "4326",
"eov": "23700"
}
box_load_last_data¶
Create a Quick queries option on the map page on the right side of the map. There are three options to choose from:
last own upload,
last upload (anyone’s)
last uploaded rows.
On the module page, you can set the number of last uploaded rows to be queried. For the other two options, the module always returns 1 row.
Parameters:
["Number of records in last uploads, default is 10"]
box_custom¶
Custom box on the map page - only the user-defined version exists. The custom module has to be placed in the local/includes/modules/ folder.
Parameters:
[A file's basename includes/modules/private folder. E.g. hrsz_query]
Where hrsz_query_Class is a class in local/includes/modules/hrsz_query.php file.
This Class should include at least print_box() and print_js() functions.
identify_point¶
Identify one or more points on the map.
Display in a small bubble some information about the data point that has been previously set.
Parameters:
["column names"]
custom_notify¶
Creates custom Postgres-based notify events. This is just an idea; the module is not ready.
No parameters
custom_data_check¶
Custom data checks of the upload data.
No parameters
download_restricted¶
Admin-controlled download authorization
No parameters
extra_params¶
Extra input parameters for forms.
grid_view¶
View data on a custom polygon grid. E.g UTM 2.5km, UTM 10KM, KEF grid, snap to grid, …
When using grid modules, the original geometry of the data is also taken from the grid module.
Methods: print_box(), default_grid_geom(), get_grid_layer()
Parameters: layer_options
Parameters example:
{
"layer_options": [
"kef_5 (layer_data_grid)",
"original (layer_data_points)"
]
}
The layer_options contains the data view modes and their options that users can choose, i.e. which layer should be associated with which MapServer layer.
The name of the MapServer layer should be given in parentheses. The string before the parentheses is the corresponding column name of the YOURTABLE_qgrids table, i.e. the column containing the desired grid geometry is linked to the MapServer layer that manages it.
The grid layer is a polygon layer, so you need to create a polygon layer in the Mapfile. Eg: layer_data_grid
The module will create a YOURTABLE_qgrids table for you if it does not already exist, and you can modify it to apply the grid types you want.
The module will also create an update_grid_geoms trigger and set the comments for you, but you will most likely need to modify them.
In the YOURTABLE_qgrids table, set the visible names of the layers in the comment field. These are the names users will see in the options list.
COMMENT ON COLUMN public.YOURTABLE_qgrids.original IS 'original';
COMMENT ON COLUMN public.YOURTABLE_qgrids.kef5 IS 'KEF 5x5';
Example trigger functions:
Trigger on YOURTABLE_qgrids. Arguments are in the function:
CREATE TRIGGER update_grid_geoms BEFORE INSERT OR UPDATE ON public.tytoalba_qgrids FOR EACH ROW EXECUTE PROCEDURE public.update_qgrid_geoms_arg('0.1', '0.1', 't', 't', 't', 't', '0.05');
Trigger on YOURTABLE table:
CREATE TRIGGER qgrids BEFORE INSERT OR DELETE OR UPDATE ON public. YOURTABLE FOR EACH ROW EXECUTE PROCEDURE insert_originalgeom_into_qgrids()
Function insert_originalgeom_into_qgrids()
BEGIN
IF tg_op = 'INSERT' THEN
EXECUTE format('INSERT INTO %I_qgrids (row_id,original) SELECT %L,%L::geometry',TG_TABLE_NAME,NEW.obm_id,NEW.obm_geometry);
RETURN NEW;
END IF;
IF tg_op = 'UPDATE' THEN
EXECUTE format('UPDATE %I_qgrids SET "original"=%L::geometry WHERE row_id=%L', TG_TABLE_NAME,NEW.obm_geometry,NEW.obm_id);
RETURN NEW;
END IF;
IF tg_op = 'DELETE' THEN
EXECUTE format('DELETE FROM %I_qgrids WHERE row_id=%L',TG_TABLE_NAME,OLD.obm_id);
RETURN OLD;
END IF;
END;
Function update_qgrid_geoms_arg()
DECLARE
snap_x numeric := TG_ARGV[0];
snap_y numeric := TG_ARGV[1];
kef5 boolean := TG_ARGV[2];
utm10 boolean := TG_ARGV[5];
snap boolean := TG_ARGV[6];
snap_polygon boolean := TG_ARGV[7];
snap_polygon_size numeric := TG_ARGV[8];
BEGIN
IF tg_op = 'UPDATE' THEN
IF kef5 THEN
EXECUTE FORMAT('SELECT geometry FROM shared."kef_5x5" WHERE st_within(%L::geometry,geometry)',NEW.original) INTO NEW."kef_5";
END IF;
IF snap THEN
EXECUTE FORMAT('SELECT st_SnapToGrid(%L::geometry,%L,%L)',NEW.original,snap_x,snap_y) INTO NEW."snap";
END IF;
IF snap_polygon THEN
EXECUTE FORMAT('SELECT st_expand(st_SnapToGrid(%L::geometry,%L,%L),%L)',NEW.original,snap_x,snap_y,snap_polygon_size) INTO NEW."snap_polygon";
END IF;
RETURN NEW;
END IF;
IF tg_op = 'INSERT' THEN
IF kef5 THEN
EXECUTE FORMAT('SELECT geometry FROM shared."kef_5x5" WHERE st_within(%L::geometry,geometry)',NEW.original) INTO NEW."kef_5";
END IF;
IF snap THEN
EXECUTE FORMAT('SELECT st_SnapToGrid(%L::geometry,%L,%L)',NEW.original,snap_x,snap_y) INTO NEW."snap";
END IF;
IF snap_polygon THEN
EXECUTE FORMAT('SELECT st_expand(st_SnapToGrid(%L::geometry,%L,%L),%L)',NEW.original,snap_x,snap_y,snap_polygon_size) INTO NEW."snap_polygon";
END IF;
RETURN NEW;
END IF;
END;
When you are ready to prepare the _qgrids table, add the existing geometries from the target table if it is not already empty.
INSERT INTO YOURTABLE_qgrids (row_id,"original") SELECT obm_id,obm_geometry FROM YOURTABLE;
UPDATE YOURTABLE_qgrids SET "snap"=foo.obm_geometry FROM (SELECT st_SnapToGrid(obm_geometry,0.13,0.09) as obm_geometry,obm_id FROM YOURTABLE) AS foo WHERE row_id=obm_id
UPDATE YOURTABLE_qgrids SET "kef_5"=foo.obm_geometry
FROM (
SELECT d.obm_id,k.obm_geometry FROM YOURTABLE d LEFT JOIN shared."kef_5x5" k ON (st_within(d.obm_geometry,k.obm_geometry) )
) as foo
WHERE row_id=foo.obm_id
In this example, the “shared” “kef_5x5” table contains the polygons we want to use, and we also created a custom polygon, “snap”, on the fly.
job_manager (validation)¶
General description:
* The job_manager (validation) module is used for managing the background processes of the project. Its parameters are the job names.
* On the admin page, you can set the time of running (simplified cron style: minute, hour, day), and the job parameters as JSON
* Adding a new parameter will register the job in the jobs database table and create the necessary template files in the modules/validation_modules and jobs folders.
Parameters:
* The names of the background processes
Published jobs:
observation_lists
description:
This job processes and copies the observation lists collected and uploaded by the mobile app. The observations land in a temporary table, where this job populates
the obm_observation_list_id column and the list's start, end, and duration columns. If the uploaded list is incomplete, it is skipped.
parameters:
* list_start_column (string): column name of list start
* list_end_column (string): column name of list end
* list_duration_column (string): column name of list duration
* only_time (boolean): store whole timestamp or just time
* time_as_int (boolean): convert time to minutes
{
"tablename": {
"list_start_column": "time_of_start",
"list_end_column": "time_of_end",
"list_duration_column": "duration",
"only_time": true,
"time_as_int": true
}
}
}
incomplete_observation_lists
description:
If the uploaded list is incomplete, this module processes it. If the difference is less than the tolerance value, the list will be uploaded by the
next observation_list process, and a system message will be sent. In another case, when the difference exceeds the tolerance, only a system message is sent; the rest
must be processed manually.
Parameters:
* mail_to (int): role_id - who will get the messages
* diff_tolerance (int): tolerance of difference
* days_offset (int): number of days to wait until the list is processed
{
"tablename": {
"mail_to": 1265,
"diff_tolerance": 2,
"days_offset": 2
}
}
join_tables¶
This module enables the display of joined data on the data-sheet page. At the moment, it supports only simple LEFT JOINS on one equation.
Parameters:
[
{
"table": "teszt_events",
"join_on": [
{
"ref_field": "obm_id",
"join_field": "patient_id"
}
]
},
{
"table": "teszt_masik",
"join_on": [
{
"ref_field": "obm_id",
"join_field": "fid"
}
]
}
]
list_manager¶
No parameters
massive_edit¶
Allows bulk editing of selected data on the map page via the file upload interface
No parameters
move_project¶
Move the project to another server. This is an experimental module.
No parameters
read_table¶
Present a SQL table or an SQL view as a rollable HTML table. This table is available through a unique link.
Parameters:
[
{
"table": "schema.table",
"label": "something",
"orderby": "column"
}, {}
]
results_asList¶
Create foldable slides-like results output.
No parameters
results_asGPX¶
Save results as a GPX file.
Parameters:
{
"name": "column",
"description": ["column-1", "column-2"]
}
results_asCSV¶
Save results as a csv file.
Parameters:
{
"sep": ",",
"quote":"\""
}
results_asJSON¶
Save results as a JSON file.
No parameters
results_asSHP¶
Results can be saved as SHP files. Separate files are created for each geometry type. These can be downloaded in a zip archive.
No parameters
results_asKML¶
Save results as a KML file.
Parameters:
{
"name": "column",
"description": ["column-1", "column-2"]
}
results_asStable¶
Compact results table on the map page.
Parameters:
[
"column names"
]
results_specieslist¶
Species list summary on the map page
No parameters
results_summary¶
A summary of results.
No parameters
results_table¶
Create a full HTML table of the results.
No parameters
restricted_data¶
Rule-based data restriction
No parameters
text_filter¶
Text filters on the map page and for the query API. Create the WHERE part of the SQL query string.
Parameters:
[
"magyar",
"obm_taxon",
"megj::colour_rings",
"obm_datum",
"obm_uploading_date",
"obm_uploader_user",
"d.szamossag:nested(d.egyedszam):autocomplete",
"d.egyedszam:values():",
"obm_files_id",
"faj::autocomplete"
]
text_filter2¶
Advanced taxon and other text filters. Create the WHERE part of the SQL query string.
Parameters:
{}
transform_data¶
Transform fields to improve readability in web tables and exports. E.g. In the result list, it can transform geometry to WKT.
Parameters:
{
"obm_geometry": "geom",
"obm_uploading_id": "uplid",
"tema":"mmm"
}
