Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new report type "map" #271

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added a service for notifications called "notify" (based actually on PNotify)
- Added Spanish translation
- Added report type pyramid
- Added report type map
- Added gulp task `dev` that combine `watch` and `nodemon`

### Changed
Expand All @@ -30,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Dependencies

- Added leaflet 1.7.1
- Updated angular to 1.8.2
- Updated angular-gettext to 2.4.2
- Updated arg to 5.0.1
Expand Down
8 changes: 4 additions & 4 deletions dist/templates/templates.js

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions doc/user/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@ Supported databases
configuration
start-the-server
upgrade

.. toctree::
:caption: Reports
:maxdepth: 2
:hidden:

report-types
6 changes: 6 additions & 0 deletions doc/user/report-types.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Report types
============

.. toctree::

report-types/map
Binary file added doc/user/report-types/image/map-empty.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/user/report-types/image/map-result.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 76 additions & 0 deletions doc/user/report-types/map.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
Map
===

The *map* report type allows to display `GeoJSON <https://geojson.org/>`_ objects on a map.

.. figure:: image/map-result.png

Example of a map report

To use it, select the map marker icon.

.. figure:: image/map-empty.png

Screenshot of an empty map report

There are six different places where you can put your columns:

GeoJSON column
This is the most important one. Place the column containing GeoJSON data here.

If your database does not contain GeoJSON data, you can probably convert
other formats to GeoJSON using SQL functions. For instance, MySQL has
`ST_AsGeoJSON <https://dev.mysql.com/doc/refman/5.7/en/spatial-geojson-functions.html#function_st-asgeojson>`_
(you may need to modify the layer to use those functions).

Note that icons rendering works only for GeoJSON 'point' type and maybe for a 'multipoint' object (not tested).

Label column
If you drop a column here, its text content will be shown next to the map marker.

Value column
If you drop a column here, its numeric content will be used to calculate a
color intensity. Low values get low intensity and high values get high
intensity.

Group column
If you drop a column here, its content will be used to group markers
together. If two rows have the same value in this column, they belong to the
same group. Each group is then assigned a unique color hue (automatically
chosen by Urungi) for the map marker.

Type column
If you drop a column here, its content will be used to assign a type to a
row. Each type can then be associated with a specific icon to change the map
marker appearance.

Filters
These are regular filters and work the same as for other report types.


Report settings
---------------

.. figure:: image/map-report-settings.png

Screenshot of the map report settings modal window

In the report settings you can change the map layer. It's the map that will be
drawn under the GeoJSON objects. You can find different map layers on `the
OpenStreetMap Wiki <https://wiki.openstreetmap.org/wiki/Tile_servers>`_.


Configure icons
---------------

If you use a *type* column, you can associate an icon with each type. To do
that, click on the gear wheel icon next to the type column.

.. figure:: image/map-type-column-settings.png

Screenshot of the map type column settings modal window

Each distinct value contained in the type column will be displayed in the form.
Associate an icon with a type by entering the icon's name. Only
`Font Awesome 4 icons <https://fontawesome.com/v4.7/icons/>`_ are available at
the moment.
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"js-xlsx": "^0.8.22",
"jsplumb": "^2.15.6",
"knex": "^0.21.21",
"leaflet": "^1.7.1",
"malihu-custom-scrollbar-plugin": "^3.1.5",
"migrate-mongo": "^8.2.3",
"moment": "^2.29.1",
Expand Down
10 changes: 10 additions & 0 deletions public/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -3181,3 +3181,13 @@ a.list-group-item:hover {
border-color: #999;
color: white;
}

.leaflet-tooltip {
background: none;
border: none;
box-shadow: none;
}

.report-map-icon i {
font-size: 16px;
}
Binary file added public/images/gps-pin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion public/js/core/constants.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global PNotify: false, PNotifyBootstrap3: false, PNotifyFontAwesome4: false, moment: false, numeral: false */
/* global PNotify: false, PNotifyBootstrap3: false, PNotifyFontAwesome4: false, moment: false, numeral: false, L : false */
(function () {
'use strict';

Expand All @@ -11,5 +11,6 @@
.constant('PNotifyFontAwesome4', PNotifyFontAwesome4)
.constant('moment', moment)
.constant('numeral', numeral)
.constant('L', L)
.constant('base', base);
})();
34 changes: 34 additions & 0 deletions public/js/report/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ angular.module('app').controller('reportCtrl', function ($scope, connection, $co
$scope.selectedReport.properties.pivotKeys = {};
$scope.selectedReport.properties.pivotKeys.columns = [];
$scope.selectedReport.properties.pivotKeys.rows = [];
$scope.selectedReport.properties.map = {
geojson: [],
value: [],
label: [],
group: [],
type: [],
};
$scope.selectedReport.properties.order = [];
$scope.selectedReport.properties.filters = [];
$scope.selectedReport.reportType = 'grid';
Expand All @@ -118,6 +125,7 @@ angular.module('app').controller('reportCtrl', function ($scope, connection, $co

$scope.selectedReport.properties.height = 300;
$scope.selectedReport.properties.range = '';
$scope.selectedReport.properties.mapLayerUrl = '';

$scope.selectedReport.properties.legendPosition = 'bottom';

Expand Down Expand Up @@ -149,6 +157,13 @@ angular.module('app').controller('reportCtrl', function ($scope, connection, $co
if (!report.properties.pivotKeys.rows) { report.properties.pivotKeys.rows = []; }
if (!report.properties.order) { report.properties.order = []; }
if (!report.properties.range) { report.properties.range = ''; }
if (!report.properties.map) { report.properties.map = {}; }
if (!report.properties.map.geojson) { report.properties.map.geojson = []; }
if (!report.properties.map.value) { report.properties.map.value = []; }
if (!report.properties.map.label) { report.properties.map.label = []; }
if (!report.properties.map.group) { report.properties.map.group = []; }
if (!report.properties.map.type) { report.properties.map.type = []; }
if (!report.properties.mapLayerUrl) { report.properties.mapLayerUrl = ''; }
};

/*
Expand Down Expand Up @@ -422,6 +437,12 @@ angular.module('app').controller('reportCtrl', function ($scope, connection, $co
role: 'column'
};
break;
case 'map':
choice = {
propertyBind: $scope.selectedReport.properties.ykeys,
role: 'column'
};
break;
}

return choice;
Expand Down Expand Up @@ -523,6 +544,14 @@ angular.module('app').controller('reportCtrl', function ($scope, connection, $co
report.reportType = 'pyramid';
break;

case 'map':
moveContent(report.properties.columns, movedColumns);
moveContent(report.properties.xkeys, movedColumns);
moveContent(report.properties.pivotKeys.columns, movedColumns);
moveContent(report.properties.pivotKeys.rows, movedColumns);
report.reportType = 'map';
break;

default:
notify.error(gettextCatalog.getString('report type does not exist'));
break;
Expand Down Expand Up @@ -639,6 +668,10 @@ angular.module('app').controller('reportCtrl', function ($scope, connection, $co
case 'pyramid':
available = report.properties.xkeys.length > 0 && report.properties.ykeys.length > 0;
break;

case 'map':
available = report.properties.map.geojson.length === 1;
break;
}

return available;
Expand Down Expand Up @@ -767,6 +800,7 @@ angular.module('app').controller('reportCtrl', function ($scope, connection, $co
$scope.selectedReport.properties.legendPosition = settings.legendPosition;
$scope.selectedReport.properties.height = settings.height;
$scope.selectedReport.properties.maxValue = settings.maxValue;
$scope.selectedReport.properties.mapLayerUrl = settings.mapLayerUrl;
$scope.selectedReport.theme = settings.theme;
$scope.selectedReport.properties.range = settings.range;
}, () => {});
Expand Down
6 changes: 5 additions & 1 deletion public/js/report/directives/reportView.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
angular.module('app').directive('reportView', function ($q, $timeout, reportModel, $compile, c3Charts, reportHtmlWidgets, grid, pivot, uuid, gettextCatalog, api) {
angular.module('app').directive('reportView', function ($q, $timeout, reportModel, $compile, c3Charts, reportHtmlWidgets, grid, pivot, map, uuid, gettextCatalog, api) {
return {

scope: {
Expand Down Expand Up @@ -84,6 +84,10 @@ angular.module('app').directive('reportView', function ($q, $timeout, reportMode
case 'indicator':
$scope.changeContent(reportHtmlWidgets.generateIndicator($scope.report, $scope.data));
break;

case 'map':
$scope.changeContent(`<div id="map" style="height:${$scope.report.properties.height}px"></div>`);
return map.createMap($scope.report, $scope.data);
}
} else {
$scope.changeContent('<div style="width: 100%; height: 100%; display: flex; align-items: center;"><span style="color: darkgray; font-size: initial; width:100%; text-align: center;"><img src="images/empty.png">' + gettextCatalog.getString('No data for this report') + '</span></div>');
Expand Down
3 changes: 3 additions & 0 deletions public/js/report/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ angular.module('app').service('reportModel', function ($q, api, connection, uuid
case 'pyramid':
chart.type = 'pyramid';
break;
case 'map':
chart.type = 'map';
break;
}

if (['chart-line', 'chart-donut', 'chart-pie', 'pyramid'].indexOf(report.reportType) >= 0 &&
Expand Down
6 changes: 6 additions & 0 deletions public/js/reports/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(function () {
'use strict';

angular.module('app.reports')
.constant('mapDefaultTileLayerUrlTemplate', 'https://tile.openstreetmap.org/{z}/{x}/{y}.png');
})();
Loading