From 298308edf52c18d78a9f64be254aa4ef2b8bf001 Mon Sep 17 00:00:00 2001 From: Simao Rodrigues Date: Thu, 25 Jul 2024 12:35:05 +0100 Subject: [PATCH 1/8] Translate geodescriber params (AOI area sentences) before building a final sentence --- providers/geodescriber-provider/selectors.js | 11 +++++++++-- utils/translate-geodescriber-params.js | 10 ++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 utils/translate-geodescriber-params.js diff --git a/providers/geodescriber-provider/selectors.js b/providers/geodescriber-provider/selectors.js index 97b3fb3ec7..b92dc77219 100644 --- a/providers/geodescriber-provider/selectors.js +++ b/providers/geodescriber-provider/selectors.js @@ -7,6 +7,7 @@ import { getDataLocation, buildFullLocationName } from 'utils/location'; import { getActiveArea } from 'providers/areas-provider/selectors'; import { parseSentence } from 'services/sentences'; +import { translateGeodescriberParams } from 'utils/translate-geodescriber-params'; export const selectGeojson = (state) => state.geostore && state.geostore.data && state.geostore.data.geojson; @@ -98,9 +99,12 @@ export const getGeodescriberTitle = createSelector( // if not an admin we can use geodescriber if (!['global', 'country'].includes(location.type)) { + // geodescriber params need to be translated as well + const translatedParams = translateGeodescriberParams(geodescriber.title_params); + return { sentence: geodescriber.title, - params: geodescriber.title_params, + params: translatedParams, }; } @@ -168,10 +172,13 @@ export const getGeodescriberDescription = createSelector( '$1 ' ); + // geodescriber params need to be translated as well + const translatedParams = translateGeodescriberParams(description_params); + return { sentence: description, params: { - ...description_params, + ...translatedParams, area_0: areaFormatted, }, }; diff --git a/utils/translate-geodescriber-params.js b/utils/translate-geodescriber-params.js new file mode 100644 index 0000000000..bf29061ddd --- /dev/null +++ b/utils/translate-geodescriber-params.js @@ -0,0 +1,10 @@ +import { translateText } from './lang'; + +export const translateGeodescriberParams = (params = {}) => { + const paramsKeys = Object.keys(params); + if (!paramsKeys.length) return {}; + + return paramsKeys.reduce((translatedParams, key) => ({ + ...translatedParams, [key]: translateText(params[key]) + }), {}); +}; From ec3e7e0d884978ce0f2fe2578d67fa5b19071f98 Mon Sep 17 00:00:00 2001 From: Simao Rodrigues Date: Wed, 31 Jul 2024 13:08:17 +0100 Subject: [PATCH 2/8] translate-geodescriber-params to allow key exclusions - for known area values prevents cluttering transifex with unnecessary values that don't need to be translated --- providers/geodescriber-provider/selectors.js | 6 ++++-- utils/translate-geodescriber-params.js | 15 +++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/providers/geodescriber-provider/selectors.js b/providers/geodescriber-provider/selectors.js index b92dc77219..710a57564c 100644 --- a/providers/geodescriber-provider/selectors.js +++ b/providers/geodescriber-provider/selectors.js @@ -100,7 +100,7 @@ export const getGeodescriberTitle = createSelector( // if not an admin we can use geodescriber if (!['global', 'country'].includes(location.type)) { // geodescriber params need to be translated as well - const translatedParams = translateGeodescriberParams(geodescriber.title_params); + const translatedParams = translateGeodescriberParams({ params: geodescriber.title_params }); return { sentence: geodescriber.title, @@ -173,7 +173,9 @@ export const getGeodescriberDescription = createSelector( ); // geodescriber params need to be translated as well - const translatedParams = translateGeodescriberParams(description_params); + // area_0 is a known area value that is formatted above, so we'll not translate that one as to prevent + // cluttering transifex with area values. + const translatedParams = translateGeodescriberParams({ params: description_params, excludeKeys: ['area_0'] }); return { sentence: description, diff --git a/utils/translate-geodescriber-params.js b/utils/translate-geodescriber-params.js index bf29061ddd..ab459c103c 100644 --- a/utils/translate-geodescriber-params.js +++ b/utils/translate-geodescriber-params.js @@ -1,10 +1,17 @@ import { translateText } from './lang'; -export const translateGeodescriberParams = (params = {}) => { +export const translateGeodescriberParams = ({params = {}, excludeKeys = []}) => { const paramsKeys = Object.keys(params); + if (!paramsKeys.length) return {}; - return paramsKeys.reduce((translatedParams, key) => ({ - ...translatedParams, [key]: translateText(params[key]) - }), {}); + return paramsKeys.reduce((translatedParams, key) => { + const paramValue = params[key]; + const shouldTranslate = !excludeKeys.includes(key); + + return { + ...translatedParams, + [key]: shouldTranslate ? translateText(paramValue) : paramValue, + } + }, {}); }; From 254eacd89486df784f8d0f9d57cb4548a39a2f60 Mon Sep 17 00:00:00 2001 From: Simao Rodrigues Date: Wed, 31 Jul 2024 13:35:37 +0100 Subject: [PATCH 3/8] Minor variable renaming for the geodescriber provider To make it easier to follow the code --- providers/geodescriber-provider/selectors.js | 13 +++++++++---- utils/translate-geodescriber-params.js | 10 +++++----- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/providers/geodescriber-provider/selectors.js b/providers/geodescriber-provider/selectors.js index 710a57564c..8080a1db90 100644 --- a/providers/geodescriber-provider/selectors.js +++ b/providers/geodescriber-provider/selectors.js @@ -100,11 +100,13 @@ export const getGeodescriberTitle = createSelector( // if not an admin we can use geodescriber if (!['global', 'country'].includes(location.type)) { // geodescriber params need to be translated as well - const translatedParams = translateGeodescriberParams({ params: geodescriber.title_params }); + const translatedTitleParams = translateGeodescriberParams({ + params: geodescriber.title_params, + }); return { sentence: geodescriber.title, - params: translatedParams, + params: translatedTitleParams, }; } @@ -175,12 +177,15 @@ export const getGeodescriberDescription = createSelector( // geodescriber params need to be translated as well // area_0 is a known area value that is formatted above, so we'll not translate that one as to prevent // cluttering transifex with area values. - const translatedParams = translateGeodescriberParams({ params: description_params, excludeKeys: ['area_0'] }); + const translatedDescriptionParams = translateGeodescriberParams({ + params: description_params, + excludeKeys: ['area_0'], + }); return { sentence: description, params: { - ...translatedParams, + ...translatedDescriptionParams, area_0: areaFormatted, }, }; diff --git a/utils/translate-geodescriber-params.js b/utils/translate-geodescriber-params.js index ab459c103c..eff9b16ab5 100644 --- a/utils/translate-geodescriber-params.js +++ b/utils/translate-geodescriber-params.js @@ -1,17 +1,17 @@ import { translateText } from './lang'; -export const translateGeodescriberParams = ({params = {}, excludeKeys = []}) => { +export const translateGeodescriberParams = ({ params = {}, excludeKeys = [] }) => { const paramsKeys = Object.keys(params); if (!paramsKeys.length) return {}; - return paramsKeys.reduce((translatedParams, key) => { - const paramValue = params[key]; - const shouldTranslate = !excludeKeys.includes(key); + return paramsKeys.reduce((translatedParams, paramKey) => { + const paramValue = params[paramKey]; + const shouldTranslateParam = !excludeKeys.includes(paramKey); return { ...translatedParams, - [key]: shouldTranslate ? translateText(paramValue) : paramValue, + [paramKey]: shouldTranslateParam ? translateText(paramValue) : paramValue, } }, {}); }; From 83bc5647e00c64e5ac9d7e5132d49f791ea52f15 Mon Sep 17 00:00:00 2001 From: Simao Rodrigues Date: Wed, 31 Jul 2024 13:54:41 +0100 Subject: [PATCH 4/8] Extract shared geodescriber sentence/params parsing code into the util file --- providers/geodescriber-provider/selectors.js | 43 ++++------------- utils/geodescriber.js | 49 ++++++++++++++++++++ utils/translate-geodescriber-params.js | 17 ------- 3 files changed, 58 insertions(+), 51 deletions(-) create mode 100644 utils/geodescriber.js delete mode 100644 utils/translate-geodescriber-params.js diff --git a/providers/geodescriber-provider/selectors.js b/providers/geodescriber-provider/selectors.js index 8080a1db90..94929862b5 100644 --- a/providers/geodescriber-provider/selectors.js +++ b/providers/geodescriber-provider/selectors.js @@ -7,7 +7,7 @@ import { getDataLocation, buildFullLocationName } from 'utils/location'; import { getActiveArea } from 'providers/areas-provider/selectors'; import { parseSentence } from 'services/sentences'; -import { translateGeodescriberParams } from 'utils/translate-geodescriber-params'; +import { isGeodescriberLocation, dynamicGeodescriberSentence } from 'utils/geodescriber'; export const selectGeojson = (state) => state.geostore && state.geostore.data && state.geostore.data.geojson; @@ -80,6 +80,8 @@ export const getGeodescriberTitle = createSelector( getActiveArea, ], (geodescriber, wdpaLocation, location, adminTitle, activeArea) => { + const { title, title_params } = geodescriber; + if (isEmpty(geodescriber)) return null; if ( @@ -97,17 +99,9 @@ export const getGeodescriberTitle = createSelector( }; } - // if not an admin we can use geodescriber - if (!['global', 'country'].includes(location.type)) { - // geodescriber params need to be translated as well - const translatedTitleParams = translateGeodescriberParams({ - params: geodescriber.title_params, - }); - - return { - sentence: geodescriber.title, - params: translatedTitleParams, - }; + // if not an admin we'll parse the geodescriber information + if (isGeodescriberLocation(location)) { + return dynamicGeodescriberSentence(title, title_params); } return { @@ -166,29 +160,10 @@ export const getGeodescriberDescription = createSelector( }, }; } - // if not an admin we can use geodescriber - if (!['global', 'country'].includes(location.type)) { - // adding space between number and unit - const areaFormatted = description_params?.area_0.replace( - /([\d|.|,]+)/, - '$1 ' - ); - - // geodescriber params need to be translated as well - // area_0 is a known area value that is formatted above, so we'll not translate that one as to prevent - // cluttering transifex with area values. - const translatedDescriptionParams = translateGeodescriberParams({ - params: description_params, - excludeKeys: ['area_0'], - }); - return { - sentence: description, - params: { - ...translatedDescriptionParams, - area_0: areaFormatted, - }, - }; + // if not an admin we'll parse the geodescriber information + if (isGeodescriberLocation(location)) { + return dynamicGeodescriberSentence(description, description_params) } // if an admin we needs to calculate the params diff --git a/utils/geodescriber.js b/utils/geodescriber.js new file mode 100644 index 0000000000..5bf3bcd66d --- /dev/null +++ b/utils/geodescriber.js @@ -0,0 +1,49 @@ +import { translateText } from './lang'; + +const translateGeodescriberParams = ({ params = {}, excludeKeys = [] }) => { + const paramsKeys = Object.keys(params); + + if (!paramsKeys.length) return {}; + + return paramsKeys.reduce((translatedParams, paramKey) => { + const paramValue = params[paramKey]; + const shouldTranslateParam = !excludeKeys.includes(paramKey); + + return { + ...translatedParams, + [paramKey]: shouldTranslateParam ? translateText(paramValue) : paramValue, + } + }, {}); +}; + +const isGeodescriberLocation = (location) => { + return !['global', 'country'].includes(location?.type); +} + +const dynamicGeodescriberSentence = (sentence, params) => { + // adding space between number and unit for area_0, if it exists + const areaFormatted = params?.area_0?.replace( + /([\d|.|,]+)/, + '$1 ' + ); + + // geodescriber params need to be translated as well + // area_0 is a known area value that is formatted above, so we'll not translate that one as to prevent + // cluttering transifex with area values. + const translatedDescriptionParams = translateGeodescriberParams({ + params, excludeKeys: ['area_0'], + }); + + return { + sentence, + params: { + ...translatedDescriptionParams, + area_0: areaFormatted, + }, + }; +}; + +export { + isGeodescriberLocation, + dynamicGeodescriberSentence, +}; diff --git a/utils/translate-geodescriber-params.js b/utils/translate-geodescriber-params.js deleted file mode 100644 index eff9b16ab5..0000000000 --- a/utils/translate-geodescriber-params.js +++ /dev/null @@ -1,17 +0,0 @@ -import { translateText } from './lang'; - -export const translateGeodescriberParams = ({ params = {}, excludeKeys = [] }) => { - const paramsKeys = Object.keys(params); - - if (!paramsKeys.length) return {}; - - return paramsKeys.reduce((translatedParams, paramKey) => { - const paramValue = params[paramKey]; - const shouldTranslateParam = !excludeKeys.includes(paramKey); - - return { - ...translatedParams, - [paramKey]: shouldTranslateParam ? translateText(paramValue) : paramValue, - } - }, {}); -}; From 3540cf4dae765ffdcd3d672591a0d762284f9281 Mon Sep 17 00:00:00 2001 From: Simao Rodrigues Date: Wed, 31 Jul 2024 14:13:05 +0100 Subject: [PATCH 5/8] Centralize area processing in the geodescriber utils file, which also handles sentence parsing --- utils/geodescriber.js | 48 ++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/utils/geodescriber.js b/utils/geodescriber.js index 5bf3bcd66d..4160565151 100644 --- a/utils/geodescriber.js +++ b/utils/geodescriber.js @@ -1,6 +1,10 @@ import { translateText } from './lang'; -const translateGeodescriberParams = ({ params = {}, excludeKeys = [] }) => { +const isGeodescriberLocation = (location) => { + return !['global', 'country'].includes(location?.type); +} + +const translateSentenceParams = ({ params = {}, excludeKeys = [] }) => { const paramsKeys = Object.keys(params); if (!paramsKeys.length) return {}; @@ -16,29 +20,39 @@ const translateGeodescriberParams = ({ params = {}, excludeKeys = [] }) => { }, {}); }; -const isGeodescriberLocation = (location) => { - return !['global', 'country'].includes(location?.type); -} +const formatAreaParams = ({ params, includeKeys = [] }) => { + const paramsKeys = Object.keys(params); + + if (!paramsKeys.length) return {}; + + return paramsKeys.reduce((translatedParams, paramKey) => { + const paramValue = params[paramKey]; + const shouldFormatParam = includeKeys.includes(paramKey); + + return { + ...translatedParams, + // We're not using the formatNumber utility here because this comes as a string from the endpoint. + // It'd require complicated processing to know the actual unit (ha, kha, etc), pull out the number, then + // use the formatNumber utility when we can just use regex to add the space between number and units. + [paramKey]: shouldFormatParam ? params?.[paramKey]?.replace(/([\d|.|,]+)/, '$1 ') : paramValue, + }; + }, {}); +}; const dynamicGeodescriberSentence = (sentence, params) => { - // adding space between number and unit for area_0, if it exists - const areaFormatted = params?.area_0?.replace( - /([\d|.|,]+)/, - '$1 ' - ); - - // geodescriber params need to be translated as well - // area_0 is a known area value that is formatted above, so we'll not translate that one as to prevent - // cluttering transifex with area values. - const translatedDescriptionParams = translateGeodescriberParams({ - params, excludeKeys: ['area_0'], + const translatedSentenceParams = translateSentenceParams({ + params, excludeKeys: ['area_0'], // we know this is always an area, let's not clutter Transifex + }); + + const formattedAreaParams = formatAreaParams({ + params, includeKeys: ['area_0'], // we know this is always an area, we just need to add a space between number and unit }); return { sentence, params: { - ...translatedDescriptionParams, - area_0: areaFormatted, + ...translatedSentenceParams, + ...formattedAreaParams, }, }; }; From d946762999a78d780302ce304a064c8160b8dc5f Mon Sep 17 00:00:00 2001 From: Simao Rodrigues Date: Thu, 1 Aug 2024 11:42:40 +0100 Subject: [PATCH 6/8] Minor renaming of geodescriber util variables --- utils/geodescriber.js | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/utils/geodescriber.js b/utils/geodescriber.js index 4160565151..fdd358daac 100644 --- a/utils/geodescriber.js +++ b/utils/geodescriber.js @@ -2,21 +2,21 @@ import { translateText } from './lang'; const isGeodescriberLocation = (location) => { return !['global', 'country'].includes(location?.type); -} +}; const translateSentenceParams = ({ params = {}, excludeKeys = [] }) => { const paramsKeys = Object.keys(params); if (!paramsKeys.length) return {}; - return paramsKeys.reduce((translatedParams, paramKey) => { + return paramsKeys.reduce((paramsAccumulator, paramKey) => { const paramValue = params[paramKey]; const shouldTranslateParam = !excludeKeys.includes(paramKey); return { - ...translatedParams, + ...paramsAccumulator, [paramKey]: shouldTranslateParam ? translateText(paramValue) : paramValue, - } + }; }, {}); }; @@ -25,27 +25,31 @@ const formatAreaParams = ({ params, includeKeys = [] }) => { if (!paramsKeys.length) return {}; - return paramsKeys.reduce((translatedParams, paramKey) => { + return paramsKeys.reduce((paramsAccumulator, paramKey) => { const paramValue = params[paramKey]; const shouldFormatParam = includeKeys.includes(paramKey); return { - ...translatedParams, + ...paramsAccumulator, // We're not using the formatNumber utility here because this comes as a string from the endpoint. // It'd require complicated processing to know the actual unit (ha, kha, etc), pull out the number, then // use the formatNumber utility when we can just use regex to add the space between number and units. - [paramKey]: shouldFormatParam ? params?.[paramKey]?.replace(/([\d|.|,]+)/, '$1 ') : paramValue, + [paramKey]: shouldFormatParam + ? params?.[paramKey]?.replace(/([\d|.|,]+)/, '$1 ') + : paramValue, }; }, {}); }; const dynamicGeodescriberSentence = (sentence, params) => { const translatedSentenceParams = translateSentenceParams({ - params, excludeKeys: ['area_0'], // we know this is always an area, let's not clutter Transifex + params, + excludeKeys: ['area_0'], // we know this is always an area, let's not clutter Transifex }); const formattedAreaParams = formatAreaParams({ - params, includeKeys: ['area_0'], // we know this is always an area, we just need to add a space between number and unit + params, + includeKeys: ['area_0'], // we know this is always an area, we just need to add a space between number and unit }); return { @@ -57,7 +61,4 @@ const dynamicGeodescriberSentence = (sentence, params) => { }; }; -export { - isGeodescriberLocation, - dynamicGeodescriberSentence, -}; +export { isGeodescriberLocation, dynamicGeodescriberSentence }; From 7f261adf81eb0fec02d01ef21519b26cc8f682b4 Mon Sep 17 00:00:00 2001 From: Simao Rodrigues Date: Thu, 1 Aug 2024 13:07:01 +0100 Subject: [PATCH 7/8] Fix issue with utils/geodescriber failing when there aren't area params --- utils/geodescriber.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/geodescriber.js b/utils/geodescriber.js index fdd358daac..983c6b0707 100644 --- a/utils/geodescriber.js +++ b/utils/geodescriber.js @@ -20,7 +20,7 @@ const translateSentenceParams = ({ params = {}, excludeKeys = [] }) => { }, {}); }; -const formatAreaParams = ({ params, includeKeys = [] }) => { +const formatAreaParams = ({ params = {}, includeKeys = [] }) => { const paramsKeys = Object.keys(params); if (!paramsKeys.length) return {}; From c3162ec40a96c2ca3a70a333668844ca4ad739c1 Mon Sep 17 00:00:00 2001 From: Simao Rodrigues Date: Fri, 2 Aug 2024 14:49:53 +0100 Subject: [PATCH 8/8] Pass status to widgets' 'getData' - fix precomputed tables never being used --- components/widget/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/widget/index.js b/components/widget/index.js index c4a951cebb..972977e9fd 100644 --- a/components/widget/index.js +++ b/components/widget/index.js @@ -136,6 +136,7 @@ class WidgetContainer extends Component { dashboard, embed, analysis, + status, } = this.props; this.cancelWidgetDataFetch(); this.widgetDataFetch = CancelToken.source(); @@ -147,6 +148,9 @@ class WidgetContainer extends Component { dashboard, embed, analysis, + // Needed for widgets that will decide whether to use precalculated tables + // (when status is 'saved') or OTF (when the nightly run has not occurred yet) + status, }) .then((data) => { setWidgetData(data);