From 682f2c12be1bc5ae2f2da2be1a65787861a69523 Mon Sep 17 00:00:00 2001 From: "Adam J. Pain" Date: Tue, 19 Jun 2018 12:30:25 +0200 Subject: [PATCH 1/2] Update tables, add helpers --- .../javascripts/services/CountryService.js | 14 +++++----- app/javascript/services/country.js | 27 ++++++++----------- app/javascript/services/total-area.js | 13 ++++----- app/javascript/services/whitelists.js | 23 ++++++++-------- app/javascript/utils/format.js | 13 +++++++++ 5 files changed, 50 insertions(+), 40 deletions(-) diff --git a/app/assets/javascripts/services/CountryService.js b/app/assets/javascripts/services/CountryService.js index b4287fcbc9..c6a2561781 100644 --- a/app/assets/javascripts/services/CountryService.js +++ b/app/assets/javascripts/services/CountryService.js @@ -11,11 +11,11 @@ define(['Class', 'uri', 'bluebird', 'map/services/DataService'], function( countriesConfigDataset: '134caa0a-21f7-451d-a7fe-30db31a424aa', countriesConfigTable: 'gfw_countries_config', countriesDataset: '134caa0a-21f7-451d-a7fe-30db31a424aa', - countriesTable: 'gadm28_countries', + countriesTable: 'gadm36_countries', regionsDataset: '098b33df-6871-4e53-a5ff-b56a7d989f9a', - regionsTable: 'gadm28_adm1', + regionsTable: 'gadm36_adm1', subRegionsDataset: 'b3d076cc-b150-4ccb-a93e-eca05d9ac2bf', - subRegionsTable: 'gadm28_adm2' + subRegionsTable: 'gadm36_adm2' }; var GET_REQUEST_COUNTRY_CONFIG_ID = 'CountryService:getCountries', @@ -34,13 +34,13 @@ define(['Class', 'uri', 'bluebird', 'map/services/DataService'], function( getCountriesList: "/query/{countriesDataset}?sql=SELECT name_engli as name, iso FROM {countriesTable} WHERE iso != 'XCA' AND iso != 'TWN' ORDER BY name", showCountry: - "/query/{countriesDataset}?sql=SELECT name_engli as name, iso, topojson FROM {countriesTable} WHERE iso='{iso}'", + "/query/{countriesDataset}?sql=SELECT name_engli as name, iso, ST_AsGeoJSON(the_geom) AS topojson FROM {countriesTable} WHERE iso='{iso}'", getRegionsList: - "/query/{regionsDataset}?sql=SELECT cartodb_id, iso, bbox as bounds, id_1, name_1 FROM {regionsTable} WHERE iso='{iso}' ORDER BY name_1", + "/query/{regionsDataset}?sql=SELECT cartodb_id, iso, bbox as bounds, gid_1, name_1 FROM {regionsTable} WHERE iso='{iso}' ORDER BY name_1", showRegion: - "/query/{regionsDataset}?sql=SELECT id_1, name_1, geojson FROM {regionsTable} WHERE iso='{iso}' AND id_1={region} ORDER BY name_1", + "/query/{regionsDataset}?sql=SELECT gid_1, name_1, ST_AsGeoJSON(the_geom) AS geojson FROM {regionsTable} WHERE iso='{iso}' AND gid_1='{region}' ORDER BY name_1", getSubRegionsList: - "/sql?q=SELECT id_2 as id, name_2 as name FROM gadm28_adm2 WHERE iso = '{iso}' AND id_1 = '{region}' ORDER BY name" + "/sql?q=SELECT gid_2 as id, name_2 as name FROM gadm36_adm2 WHERE iso = '{iso}' AND gid_1 = '{region}' ORDER BY name" }; var CountriesService = Class.extend({ diff --git a/app/javascript/services/country.js b/app/javascript/services/country.js index 4edd6d3528..a2fa0ac1c0 100644 --- a/app/javascript/services/country.js +++ b/app/javascript/services/country.js @@ -1,4 +1,5 @@ import request from 'utils/request'; +import { buildGadm36Id } from 'utils/format'; const REQUEST_URL = `${process.env.CARTO_API_URL}/sql?q=`; @@ -8,13 +9,13 @@ const SQL_QUERIES = { getFAOCountries: 'SELECT DISTINCT country AS iso, name FROM table_1_forest_area_and_characteristics', getRegions: - "SELECT id_1 as id, name_1 as name FROM gadm36_adm1 WHERE iso = '{iso}' ORDER BY name ", + "SELECT gid_1 as id, name_1 as name FROM gadm36_adm1 WHERE iso = '{iso}' ORDER BY name ", getSubRegions: - "SELECT id_2 as id, name_2 as name FROM gadm36_adm2 WHERE iso = '{iso}' AND id_1 = '{admin1}' ORDER BY name", + "SELECT gid_2 as id, name_2 as name FROM gadm36_adm2 WHERE iso = '{iso}' AND gid_1 = '{adm1}' ORDER BY name", getCountryLinks: 'SELECT iso, external_links FROM external_links_gfw WHERE forest_atlas is true', getRanking: - "WITH mytable AS (SELECT fao.iso, fao.name, fao.forest_primary, fao.extent forest_extent, a.land as area_ha FROM gfw2_countries as fao INNER JOIN umd_nat_staging as a ON fao.iso = a.iso WHERE fao.forest_primary > 0 AND a.year = 2001 AND a.thresh = 30), rank AS ( SELECT forest_extent * (forest_primary/100)/area_ha * 100 as percent_primary ,iso from mytable ORDER BY percent_primary DESC), item as (select percent_primary from rank where iso = '{country}') select count(*) as rank from rank WHERE percent_primary > (select percent_primary from item )", + "WITH mytable AS (SELECT fao.iso, fao.name, fao.forest_primary, fao.extent forest_extent, a.land as area_ha FROM gfw2_countries as fao INNER JOIN umd_nat_staging as a ON fao.iso = a.iso WHERE fao.forest_primary > 0 AND a.year = 2001 AND a.thresh = 30), rank AS ( SELECT forest_extent * (forest_primary/100)/area_ha * 100 as percent_primary ,iso from mytable ORDER BY percent_primary DESC), item as (select percent_primary from rank where iso = '{adm0}') select count(*) as rank from rank WHERE percent_primary > (select percent_primary from item )", getCountriesLatLng: 'SELECT latitude_average, longitude_average, alpha_3_code as iso FROM country_list_iso_3166_codes_latitude_longitude' }; @@ -29,18 +30,15 @@ export const getFAOCountriesProvider = () => { return request.get(url); }; -export const getRegionsProvider = country => { - const url = `${REQUEST_URL}${SQL_QUERIES.getRegions}`.replace( - '{iso}', - country - ); +export const getRegionsProvider = adm0 => { + const url = `${REQUEST_URL}${SQL_QUERIES.getRegions}`.replace('{iso}', adm0); return request.get(url); }; -export const getSubRegionsProvider = (admin0, admin1) => { +export const getSubRegionsProvider = (adm0, adm1) => { const url = `${REQUEST_URL}${SQL_QUERIES.getSubRegions}` - .replace('{iso}', admin0) - .replace('{admin1}', admin1); + .replace('{iso}', adm0) + .replace('{adm1}', buildGadm36Id(adm0, adm1)); return request.get(url); }; @@ -54,10 +52,7 @@ export const getCountriesLatLng = () => { return request.get(url); }; -export const getRanking = ({ country }) => { - const url = `${REQUEST_URL}${SQL_QUERIES.getRanking}`.replace( - '{country}', - country - ); +export const getRanking = ({ adm0 }) => { + const url = `${REQUEST_URL}${SQL_QUERIES.getRanking}`.replace('{adm0}', adm0); return request.get(url); }; diff --git a/app/javascript/services/total-area.js b/app/javascript/services/total-area.js index a2ab777084..748768e319 100644 --- a/app/javascript/services/total-area.js +++ b/app/javascript/services/total-area.js @@ -1,14 +1,15 @@ import request from 'utils/request'; +import { buildGadm36Id } from 'utils/format'; const REQUEST_URL = `${process.env.CARTO_API_URL}/sql?q=`; const SQL_QUERIES = { getCountryArea: - "SELECT land as value FROM umd_nat_staging WHERE iso = '{adm0}' AND year = 2001 and thresh = 30", + "SELECT area_ha as value FROM gadm36_countries WHERE iso = '{adm0}'", getRegionArea: - "SELECT area_ha as value FROM gadm36_adm1 WHERE iso = '{adm0}' AND id_1 = {adm1}", + "SELECT area_ha as value FROM gadm36_adm1 WHERE iso = '{adm0}' AND gid_1 = '{adm1}'", getSubRegionArea: - "SELECT ROUND(ST_AREA(the_geom::geography) * 0.0001) as value FROM gadm36_adm2 WHERE iso = '{adm0}' AND id_1 = {adm1} AND id_2 = {adm2}" + "SELECT area_ha as value FROM gadm36_adm2 WHERE iso = '{adm0}' AND gid_1 = '{adm1}' AND gid_2 = '{adm2}'" }; export const getArea = ({ country, region, subRegion }) => { @@ -16,12 +17,12 @@ export const getArea = ({ country, region, subRegion }) => { if (subRegion) { url = `${REQUEST_URL}${SQL_QUERIES.getSubRegionArea}` .replace('{adm0}', country) - .replace('{adm1}', region) - .replace('{adm2}', subRegion); + .replace('{adm1}', buildGadm36Id(country, region)) + .replace('{adm2}', buildGadm36Id(country, region, subRegion)); } else if (region) { url = `${REQUEST_URL}${SQL_QUERIES.getRegionArea}` .replace('{adm0}', country) - .replace('{adm1}', region); + .replace('{adm1}', buildGadm36Id(country, region)); } else { url = `${REQUEST_URL}${SQL_QUERIES.getCountryArea}`.replace( '{adm0}', diff --git a/app/javascript/services/whitelists.js b/app/javascript/services/whitelists.js index 51a7d2e43d..20266a22e6 100644 --- a/app/javascript/services/whitelists.js +++ b/app/javascript/services/whitelists.js @@ -1,4 +1,5 @@ import request from 'utils/request'; +import { buildGadm36Id } from 'utils/format'; const DATASET = process.env.COUNTRIES_PAGE_DATASET; const REQUEST_URL = `${process.env.GFW_API_HOST_PROD}/query/${DATASET}?sql=`; @@ -10,33 +11,33 @@ const SQL_QUERIES = { getRegionWhitelist: 'SELECT polyname, SUM(area_extent_2000) as total_extent_2000, SUM(area_extent) as total_extent_2010, SUM(area_gain) as total_gain, SUM(year_data.area_loss) as total_loss FROM data WHERE thresh = 0 AND {location} GROUP BY polyname', getWaterBodiesWhitelist: - "SELECT iso, adm1, adm2 from water_bodies_gadm36 WHERE iso = '{country}' AND adm1 = {region}" + "SELECT iso, gid_1, gid_2 from water_bodies_gadm36 WHERE iso = '{adm0}' AND gid_1 = '{adm1}'" }; -const getLocationQuery = (country, region, subRegion) => - `iso = '${country}'${region ? ` AND adm1 = ${region}` : ''}${ - subRegion ? ` AND adm2 = ${subRegion}` : '' +const getLocationQuery = (adm0, adm1, adm2) => + `iso = '${adm0}'${adm1 ? ` AND adm1 = ${adm1}` : ''}${ + adm2 ? ` AND adm2 = ${adm2}` : '' }`; -export const getCountryWhitelistProvider = admin0 => { +export const getCountryWhitelistProvider = adm0 => { const url = `${REQUEST_URL}${SQL_QUERIES.getCountryWhitelist}`.replace( '{iso}', - admin0 + adm0 ); return request.get(url); }; -export const getRegionWhitelistProvider = (admin0, admin1, admin2) => { +export const getRegionWhitelistProvider = (adm0, adm1, adm2) => { const url = `${REQUEST_URL}${SQL_QUERIES.getRegionWhitelist}`.replace( '{location}', - getLocationQuery(admin0, admin1, admin2) + getLocationQuery(adm0, adm1, adm2) ); return request.get(url); }; -export const getWaterBodiesBlacklistProvider = (admin0, admin1) => { +export const getWaterBodiesBlacklistProvider = (adm0, adm1) => { const url = `${CARTO_REQUEST_URL}${SQL_QUERIES.getWaterBodiesWhitelist}` - .replace('{country}', admin0) - .replace('{region}', admin1); + .replace('{adm0}', buildGadm36Id(adm0)) + .replace('{adm1}', buildGadm36Id(adm0, adm1)); return request.get(url); }; diff --git a/app/javascript/utils/format.js b/app/javascript/utils/format.js index 9275b47dc8..d53169c811 100644 --- a/app/javascript/utils/format.js +++ b/app/javascript/utils/format.js @@ -18,3 +18,16 @@ export const formatNumber = ({ num, unit }) => { } return `${formattedNum}${unit || ''}`; }; + +export const buildGadm36Id = (country, region, subRegion) => + `${country}${region ? `.${region}` : ''}${ + subRegion ? `.${subRegion}_1` : '_1' + }`; + +export const parseGadm36Id = gid => { + const ids = gid.split('.'); + const adm0 = ids[0] || null; + const adm1 = ids[1] && ids[1].split('_')[0]; + const adm2 = ids[2] && ids[2].split('_')[0]; + return { adm0, adm1, adm2 }; +}; From 9f103ca5ef28f6413673535948bc2e448bd1e992 Mon Sep 17 00:00:00 2001 From: "Adam J. Pain" Date: Tue, 19 Jun 2018 12:31:05 +0200 Subject: [PATCH 2/2] Update actions --- .../country-data-provider-actions.js | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/app/javascript/providers/country-data-provider/country-data-provider-actions.js b/app/javascript/providers/country-data-provider/country-data-provider-actions.js index 2a9f6a71bc..af2163eabb 100644 --- a/app/javascript/providers/country-data-provider/country-data-provider-actions.js +++ b/app/javascript/providers/country-data-provider/country-data-provider-actions.js @@ -1,5 +1,6 @@ import { createAction } from 'redux-actions'; import { createThunkAction } from 'utils/redux'; +import { parseGadm36Id } from 'utils/format'; import axios from 'axios'; import uniqBy from 'lodash/uniqBy'; @@ -57,7 +58,14 @@ export const getRegions = createThunkAction( dispatch(setRegionsLoading(true)); getRegionsProvider(country) .then(response => { - dispatch(setRegions(uniqBy(response.data.rows), 'id')); + const parsedResponse = []; + uniqBy(response.data.rows).forEach(row => { + parsedResponse.push({ + id: parseGadm36Id(row.id).adm1, + name: row.name + }); + }); + dispatch(setRegions(parsedResponse, 'id')); dispatch(setRegionsLoading(false)); }) .catch(error => { @@ -81,9 +89,17 @@ export const getSubRegions = createThunkAction( .then( axios.spread((subRegions, blacklistResponse) => { const { rows } = subRegions.data; + const parsedResponse = []; + uniqBy(rows).forEach(row => { + parsedResponse.push({ + id: parseGadm36Id(row.id).adm2, + name: row.name + }); + }); const blackList = blacklistResponse.data.rows.map(i => i.adm2); const subRegionList = - rows && rows.filter(r => blackList.indexOf(r.id) === -1); + parsedResponse && + parsedResponse.filter(r => blackList.indexOf(r.id) === -1); dispatch(setSubRegions(uniqBy(subRegionList, 'id'))); dispatch(setSubRegionsLoading(false)); })