Skip to content

[EPIC] GADM #4892

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

Draft
wants to merge 10 commits into
base: feat/GADM-country-list-FLAG-997
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import PropTypes from 'prop-types';
import DynamicSentence from 'components/ui/dynamic-sentence';
import Button from 'components/ui/button';

/**
* Displays a sentence describing the area clicked by the user on the map.
* @param {string} sentence - A string with the area's description
* @param {function} onAnalyze - Function for onClick event.
*/
const BoundarySentence = ({ sentence, onAnalyze }) => (
<div className="c-boundary-sentence">
<DynamicSentence className="sentence" sentence={sentence} />
Expand All @@ -15,7 +20,7 @@ const BoundarySentence = ({ sentence, onAnalyze }) => (

BoundarySentence.propTypes = {
data: PropTypes.shape({
level: PropTypes.number,
adm_level: PropTypes.number,
}),
sentence: PropTypes.shape({
sentence: PropTypes.string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,47 @@ import { translateText } from 'utils/lang';

const getInteractionData = (state, { data }) => data;

/**
* Returns an object with the selected location name, its area and a sentence do be displayed.
* @param {method} createSelector - return a memoized outut selector.
* @see https://reselect.js.org/introduction/getting-started/#output-selector for implementation details
* @param {selector} getInteractionData - data from the area clicked by user
* @return {object} sentence, location name and area.
*/
export const getSentence = createSelector(
[getInteractionData],
({ data } = {}) => {
const { level, gid_0, name_1, name_0 } = data;
let name = data[`name_${level || '0'}`];
const { adm_level, gid_0, name_1, country } = data;
let name = adm_level > 0 ? data[`name_${adm_level}`] : country;

if (!gid_0) {
name = data[Object.keys(data).find((k) => k.includes('name'))];
}

const area = data[Object.keys(data).find((k) => k.includes('area'))];
const locationNameTranslated = translateText(name);

let locationNames = [locationNameTranslated];

if (level === 2) {
if (Number(adm_level) === 2) {
locationNames = [
locationNameTranslated,
translateText(name_1),
translateText(name_0),
translateText(country),
];
} else if (level === 1) {
locationNames = [locationNameTranslated, translateText(name_0)];
}

const locationName = locationNames.join(', ');
if (Number(adm_level) === '1') {
locationNames = [locationNameTranslated, translateText(country)];
}

const locationName = locationNames.join(', ');
const sentence = translateText('{location}, with a total area of {area}.');
const params = {
location: locationName,
area: formatNumber({ num: area, unit: 'ha' }),
};

const sentence = translateText('{location}, with a total area of {area}.');

return {
sentence,
params,
Expand Down
90 changes: 50 additions & 40 deletions layouts/map/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,53 +6,63 @@ import useRouter from 'utils/router';

export const setMainMapSettings = createAction('setMainMapSettings');

/**
* Push the parameters from the area clicked to the URL query
* @param {function} createThunkAction - A string with the area's description
* @see https://redux.js.org/usage/writing-logic-thunks for implementation details
* @param {string} setMainMapAnalysisView - Action name
* @param {function} - Arrow function
* @param {object} data - area data (adm_level, gid_0, country, ...)
* @param {object} layer - political boundaries obejct from Layer API
*/
export const setMainMapAnalysisView = createThunkAction(
'setMainMapAnalysisView',
({ data, layer }) => () => {
const { cartodb_id, wdpaid } = data || {};
const { analysisEndpoint, tableName } = layer || {};
const { query, pushQuery } = useRouter();
const { map, mainMap } = query || {};
({ data, layer }) =>
() => {
const { cartodb_id, wdpaid } = data || {};
const { analysisEndpoint, tableName } = layer || {};
const { query, pushQuery } = useRouter();
const { map, mainMap } = query || {};

let payload = {};

// get location payload based on layer type
let payload = {};
if (data) {
if (analysisEndpoint === 'admin') {
payload = {
type: 'country',
...getGadmLocationByLevel(data),
};
} else if (analysisEndpoint === 'wdpa' && (cartodb_id || wdpaid)) {
payload = {
type: analysisEndpoint,
adm0: wdpaid || cartodb_id,
};
} else if (cartodb_id && tableName) {
payload = {
type: 'use',
adm0: tableName,
adm1: cartodb_id,
};
if (data) {
if (analysisEndpoint === 'admin') {
payload = {
type: 'country',
...getGadmLocationByLevel(data),
};
} else if (analysisEndpoint === 'wdpa' && wdpaid) {
payload = {
type: analysisEndpoint,
adm0: wdpaid,
};
} else if (cartodb_id && tableName) {
payload = {
type: 'use',
adm0: tableName,
adm1: cartodb_id,
};
}
}
}

if (payload && payload.adm0) {
pushQuery({
pathname: `/map/${compact(Object.values(payload))?.join('/')}/`,
query: {
...query,
map: {
...map,
canBound: true,
},
mainMap: {
...mainMap,
showAnalysis: true,
if (payload && payload.adm0) {
pushQuery({
pathname: `/map/${compact(Object.values(payload))?.join('/')}/`,
query: {
...query,
map: {
...map,
canBound: true,
},
mainMap: {
...mainMap,
showAnalysis: true,
},
},
},
});
});
}
}
}
);

export const setDrawnGeostore = createThunkAction(
Expand Down
6 changes: 2 additions & 4 deletions pages/api/data/[...params].js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import httpProxyMiddleware from 'next-http-proxy-middleware';

import { GFW_DATA_API, GFW_STAGING_DATA_API } from 'utils/apis';
import { GFW_DATA_API } from 'utils/apis';
import { PROXIES } from 'utils/proxies';

const ENVIRONMENT = process.env.NEXT_PUBLIC_FEATURE_ENV;
const GFW_API_KEY = process.env.NEXT_PUBLIC_GFW_API_KEY;
const DATA_API_URL =
ENVIRONMENT === 'staging' ? GFW_STAGING_DATA_API : GFW_DATA_API;
const DATA_API_URL = GFW_DATA_API;
Copy link
Collaborator Author

@willian-viana willian-viana Feb 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rollback this change before deploy it to PROD.


// https://github.com/stegano/next-http-proxy-middleware/issues/32#issuecomment-1031015850
export const config = {
Expand Down
48 changes: 29 additions & 19 deletions providers/geostore-provider/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,19 @@ export const setGeostoreLoading = createAction('setGeostoreLoading');
export const setGeostore = createAction('setGeostore');
export const clearGeostore = createAction('clearGeostore');

/**
* Push the parameters from the area clicked to the URL query
* @param {function} createThunkAction - A string with the area's description
* @see https://redux.js.org/usage/writing-logic-thunks for implementation details
* @param {string} fetchGeostore - Action name
* @param {function} - Arrow function
* @param {object} params - Url query parameters
*/
export const fetchGeostore = createThunkAction(
'fetchGeostore',
(params) => (dispatch) => {
const { type, adm0, adm1, adm2, token } = params;

if (type && adm0) {
dispatch(setGeostoreLoading({ loading: true, error: false }));
getGeostore({ type, adm0, adm1, adm2, token })
Expand All @@ -28,26 +37,27 @@ export const fetchGeostore = createThunkAction(

export const getGeostoreId = createThunkAction(
'getGeostoreId',
({ geojson, callback }) => (dispatch) => {
if (geojson) {
dispatch(setGeostoreLoading({ loading: true, error: false }));
saveGeostore(geojson)
.then((geostore) => {
if (geostore && geostore.data && geostore.data.data) {
const { id } = geostore.data.data;
if (callback) {
callback(id);
} else {
dispatch(setGeostoreLoading({ loading: false, error: false }));
({ geojson, callback }) =>
(dispatch) => {
if (geojson) {
dispatch(setGeostoreLoading({ loading: true, error: false }));
saveGeostore(geojson)
.then((geostore) => {
if (geostore && geostore.data && geostore.data.data) {
const { id } = geostore.data.data;
if (callback) {
callback(id);
} else {
dispatch(setGeostoreLoading({ loading: false, error: false }));
}
}
}
})
.catch(() => {
setGeostoreLoading({
loading: false,
error: true,
})
.catch(() => {
setGeostoreLoading({
loading: false,
error: true,
});
});
});
}
}
}
);
5 changes: 2 additions & 3 deletions services/geostore.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,8 @@ export const getGeostore = ({ type, adm0, adm1, adm2, token }) => {
switch (type) {
case 'country':
return fetchGeostore({
url: `/geostore/admin/${adm0}${adm1 ? `/${adm1}` : ''}${
adm2 ? `/${adm2}` : ''
}`,
url: `/geostore/admin/${adm0}${adm1 ? `/${adm1}` : ''}${adm2 ? `/${adm2}` : ''
}`,
queryParams: `${queryParams}&${threshold}`,
token,
});
Expand Down
9 changes: 7 additions & 2 deletions utils/gadm.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ export const parseGadm36Id = (gid) => {
};
};

export const getGadmLocationByLevel = ({ level, ...location }) => ({
/**
* @param {string} adm_level - The administrative level
* @param {object} location - Location object from user's clicked area
* @return {object} - Object with area type, location and gadm properties
*/
export const getGadmLocationByLevel = ({ adm_level, ...location }) => ({
type: 'country',
...(location?.gid_0 && {
...parseGadm36Id(location[`gid_${level || '0'}`]),
...parseGadm36Id(location[`gid_${adm_level || '0'}`]),
}),
});
Loading