- Notifications
You must be signed in to change notification settings - Fork37
PRISM is an interactive map-based dashboard that simplifies the integration of geospatial data on hazards, along with information on socioeconomic vulnerability
License
WFP-VAM/prism-app
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This project is the front-end interface for the World Food Programme'sPRISM project. It displays data and impact projections on a configurable map interface.
The new PRISM frontend is built as a static website to minimize cross dependencies and simplify deployments as much as possible. Currently, PRISM frontend provides the ability to:
- Load administrative boundaries as GeoJSON (
src/config/admin_boundaries.json
) - Load admin level (vector) data as JSON, and link it to administrative boundaries
- Display WMS layers from Geoserver or Open Data Cube endpoints, with date selection capabilities
- Display point layers by applying symbology to numeric values associated with a geographic coordinate
- Display CSV tables in a left side panel
To chose which country to run PRISM for, you can set the environment variableREACT_APP_COUNTRY
. The current default country ismozambique
The configuration is split into three files that you can find insrc/config
:
prism.json
layers.json
tables.json
Since many layers are common across multiple countries, we created shared configuration files that any deployment can access. Many of these layers are generated by WFP globally and made available through the Humanitarian Data Cube. You can find the layers and their associated styles / legends insrc/config/shared
:
legends.json
layers.json
This is the primary configuration file. You can define:
- Map settings (starting point, zoom, default boundary layers)
- The server endpoints
- Categories and their respective icons which are used to organize the top navigation
- Alerts flag (to specify whether to activate the alerts module)
For each category, you can define sub categories as "subcategorie_name":[layers], a list of layers fromlayers.json
.
{ "country": "Cambodia", "map": { "latitude": 12.058, "longitude": 105.281, "zoom": 6.49 }, "serversUrls": { "wms": [ "https://geonode.wfp.org/geoserver/prism/wms/", "https://ows.earthobservation.vam.wfp.org/wms" ] }, "alertFormActive": false, "hidePanel": false, "icons": { "vulnerability": "icon_vulnerable.png", "exposure": "icon_basemap.png", "hazards": "icon_climate.png", "risk": "icon_impact.png", "capacity": "icon_capacity.png", "tables": "icon_table.png" }, "categories": { "hazards": { "floods" ....
For each country, you will need to specify the starting point (lat, long) and zoom. In addition, you can also set
- maxBounds
- minZoom
- maxZoom
To find these attributes, we created a help mode that you can activate by setting the envREACT_APP_SHOW_MAP_INFO=true
Configuring multiple boundary layersIf multiple boundary layers are configured in
layers.json
you can specify which should be displayed by default by definingdefaultDisplayBoundaries
as an array of boundaries.e.g.
{..."defaultDisplayBoundaries": ["township_boundaries","district_boundaries","state_boundaries" ]...}
In some cases, a boundary file may load without any issues but fail to provide correct results in an exposure analysis, or correctly render the 'Go To' feature. Troubleshooting this is challenging. It is recommended to use a validation tool on your boundary file before utilizing it in PRISM.https://geojsonlint.com/ works well for this purpose.
In addition, boundary files sometimes carry more precise coordinates than is neccessary which makes for a large data file. PRISM will alert you with a message in the browser if the precision is too high. You can run bash /frontend/scripts/truncate_precision.sh to fix this. The script will update any boundary file in the /frontend/public/data folder
Undercategories
, you can specify the menu structure and reference to any layer by ID that is defined under the country country specific or sharedlayers.json
. You can also create groups that can be activated all at once, or selectively.
"categories": { "rainfall": { "forecasts": ["daily_rainfall_forecast", "dekad_rainfall_forecast"], "rainfall_amount": [ { "group_title": "Rainfall Aggregate", "activate_all": false, "layers": [ { "id": "rainfall_dekad", "label": "10-day", "main": true }, { "id": "rainfall_agg_1month", "label": "1-month" }, { "id": "rainfall_agg_3month", "label": "3-month" }, { "id": "rainfall_agg_6month", "label": "6-month" }, { "id": "rainfall_agg_9month", "label": "9-month" }, { "id": "rainfall_agg_1year", "label": "1-year" } ] } ], }}
In this file, we define the specific layer settings for data access, titles, and legends. You can define a new layer from scratch, or override a layer that exists in theshared/layers.json
. In that case, you only need to specify the fields that need to be overriden. Similarly, legends can be predefined inshared/legends.json
and simply reference to by id. The"legend_text"
attribute describes the source of the data and can use Markdown syntax to renderlinks,italics, andbold text within our H5 typography.
There are 4 main types of layers.
These layers are simply processed as raster images from a WMS server and are referred to as type 'wms'
"pasture_anomaly": { "title": "Pasture anomaly", "server_type": "wms", "server_layer": "ModisAnomaly", "server_uri": "https://mongolia.sibelius-datacube.org:5000/wms?layers=ModisAnomaly", "has_date": true, "date_interval": "days", "opacity": 0.3, "legend_text": "Converts NDVI to pasture (kg/ha) values and divides the current period by the long term average to calculate pasture anomaly.", "legend": [ { "value": "12000", "color": "#ff0000" }, { "value": "14000", "color": "#ff5900" }, { "value": "16000", "color": "#ff8400" }, { "value": "18000", "color": "#ffce63" }, { "value": "19000", "color": "#ffdd94" }, { "value": "20000", "color": "#ffffbf" }, { "value": "21000", "color": "#dee09f" }, { "value": "22000", "color": "#bbbf7c" }, { "value": "24000", "color": "#9da360" }, { "value": "26000", "color": "#7e8745" }, { "value": "28000", "color": "#5b6e00" } ]}
These layers are referred to asadmin_level_data
in PRISM and represent a data value for a polygon. The layers are obtained by matching data from thedata_field
andadmin_code
fields of theadmin_level_data
layer with the administrative boundaries. The default admin boundary file will be used unless otherwise specifed in theadmin_level_data
configuration using theboundary
attribute
"improved_drinking_water": { "title": "Improved drinking water", "type": "admin_level_data", "path": "data/myanmar/nso/vulnerability-layers.json", "data_field": "improved_drinking_water", "admin_level": 3, "admin_code": "TS_PCODE", "opacity": 0.7, "legend": [ { "label": "<20%", "value": 0, "color": "#a50f15" }, { "label": "21 to 40%", "value": 21, "color": "#de2d26" }, { "label": "41 to 60%", "value": 41, "color": "#fb6a4a" }, { "label": "61 to 80%", "value": 61, "color": "#fcae91" }, { "label": "81 to 100%", "value": 81, "color": "#fee5d9" } ], "legend_text": "Percent of households with improved source of drinking water. Source: Myanmar Population and Housing Census 2014, Department of Population, Ministry of Immigration and Population" }
These layers are referred to aspoint_data
in PRISM and represent a data value for a given latitude and longitude coordinate. Point data layers visualize values specified asmeasure_field
as points on a map based on thegeom_field
which expect a lat, long coordinate.
"disaster_report": { "title": "Disaster impact report", "type": "point_data", "data": "https://prism-api.ovio.org/kobo/forms", "additional_query_params": { "form_name": "PRISM-KHM-Disaster-Report-v1", "datetime_field": "disaster_date", "geom_field": "location", "measure_field": "num_ppl_affected", } "opacity": 0.9, "legend_text": "Number of people affected", "legend": [ {"value": "0", "color": "#909090"}, {"value": "< 100", "color": "#ffeda0"}, {"value": "100 - 500", "color": "#feb24c"}, {"value": "500 or more", "color": "#f03b20"} ]
Boundary layers are loaded by defaul when the application starts and typically show administrative boundaries and are defined as typeboundary
. Multiple boundary files can be configured in layers.json. Multiple boundary files can be used to create different styles for each boundary, or to toggle between admin_level_data layers which correspond to a separate geographic specification; for example to use one boundary file for district level data, and another boundary file for ecological data.
When more than one boundary is specified, an array of boundaries needs to also be set inprism.json
using with thedefaultDisplayBoundaries
attribute.
{ "state_admin_boundaries": { "type": "boundary", "path": "data/myanmar/mmr_admin1_boundaries.json", "opacity": 0.8, "admin_code": "ST_PCODE", "admin_level_names": ["ST"], "admin_level_local_names": ["mmr_polbnd"], "styles:": { "fill": { "fill-opacity": 0 }, "line": { "line-color": "gray", "line-width": 1.5, "line-opacity": 0.8 } } }, "district_admin_boundaries": { "type": "boundary", "path": "data/myanmar/mmr_admin2_boundaries.json", "opacity": 0.8, "admin_code": "DT_PCODE", "admin_level_names": ["ST", "DT"], "admin_level_local_names": ["DT_MMR4", "TS_MMR4"], "styles:": { "fill": { "fill-opacity": 0 }, "line": { "line-color": "gray", "line-width": 1, "line-opacity": 0.8 } } }, "admin_boundaries": { "type": "boundary", "path": "data/myanmar/admin_boundaries.json", "opacity": 0.8, "admin_code": "TS_PCODE", "admin_level_names": ["ST", "DT", "TS"], "admin_level_local_names": ["mmr_polbnd", "DT_MMR4", "TS_MMR4"], "styles:": { "fill": { "fill-opacity": 0 }, "line": { "line-color": "gray", "line-width": 0.5, "line-opacity": 0.8 } } }
Impact layers are computed by combining a raster layer with a vector layer based on raster values bound by the zones of the vector layer. The impact layer computes zonal statistics for the raster, and based on a configured threshold, will display zones where the threshold has been exceeded.
"herd_pasture_impact": { "title": "Number of herder households exposed to severe pasture anomaly", "hazard_layer": "pasture_anomaly", "baseline_layer": "nsoHerders", "threshold": " <= 25000", "opacity": 0.3, "legend_text": "Number of herder households within ADMIN2 in an area where the median pasture anomaly is <= -50%", "legend": [ { "value": "25", "color": "#ffeda0”" }, { "value": "30", "color": "#feb24c”" }, { "value": "35", "color": "#f03b20”" } ]}
To display additional metadata about a layer, you can add acontent_path
attribute to any layer. The attribute expects a path to a.md
or.html
file that is stored inpublic/data/${REACT_APP_COUNTRY}/filename.ext
directory. For example:public/data/myanmar/contents.md
The application will show an icon next to the layer in the legend if this attribute is configured, and will display the content in a modal window if the icon is clicked.
This project was bootstrapped withCreate React App, using theRedux andRedux Toolkit template with TypeScript.
- Styling & UI Library UseMaterial UI. Note that to use thestyles API you can
import @material-ui/core/styles
. - Routing UsesReact Router.
- Monitoring UsesSentry.io. To send monitoring info to Sentry, simply set the
Sentry
url by adding it asREACT_APP_SENTRY_URL
in a.env
file at the root folder. - State Management UsesRedux
- Testing UsesJest
- Mapping UsesMapLibre. The app supports Maptiler and Mapbox styles. To use Mapbox styles, you will need to create a token and add it as
REACT_APP_MAPBOX_TOKEN
in a.env
file at the root folder. Then specify your style url usingREACT_APP_DEFAULT_STYLE
. - WFP authentication Usesmsal. You need to include within your .env file the variables
REACT_APP_OAUTH_CLIENT_ID
,REACT_APP_OAUTH_AUTHORITY
andREACT_APP_OAUTH_REDIRECT_URI
. Also, set theWFPAuthRequired
flag within the country prism.json file
The following commands should get you a local development instance of the frontend:
cd frontendyarn cleanyarn installyarn setup:commonREACT_APP_COUNTRY=cambodia yarn start
In the project directory, you can run:
Runs the app in the development mode.
Openhttp://localhost:3000 to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
Launches the test runner in the interactive watch mode.
See the section aboutrunning tests for more information.
Builds the app for production to thebuild
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section aboutdeployment for more information.
Runseslint
for all the source files. We use a custom Eslint configuration in./eslintrc
along withprettier
(configured with./.prettierrc
) to enforce consistency and code quality. If you would like eslint to try to automatically "fix" files if it can, runyarn lint --fix
.
By default, a pre-commit hook is defined to run linting tasks on allstaged code before allowing a commit. This occurs using thelint-staged package, and can be configured in./package.json#lint-staged
. The precommit task can be run manually usingyarn precommit
.
By default, everytime a pull request is created, a CI/CD pipeline will run tests and deploy the code to a Firebase channel preview (http://staging-prism-frontend--prism-[pr number]-[random hash].web.app). To specify a country that the build will be run on, start your pull request title withCOUNTRY=[country name]
. For example:COUNTRY=cambodia Add new config options
.