From 036e1ce94281e9a85bc612fd4e28017dba0940eb Mon Sep 17 00:00:00 2001 From: CollinBeczak Date: Mon, 3 Jun 2024 13:16:58 -0500 Subject: [PATCH 01/13] connect to new endpoint for fetching specifically task markers --- .../WithChallengeTaskClusters.jsx | 6 +- .../TaskClusterMap/TaskClusterMap.jsx | 2 +- src/services/Server/APIRoutes.js | 1 + src/services/Task/BoundedTask.js | 104 +++++++++++++++++- 4 files changed, 108 insertions(+), 5 deletions(-) diff --git a/src/components/HOCs/WithChallengeTaskClusters/WithChallengeTaskClusters.jsx b/src/components/HOCs/WithChallengeTaskClusters/WithChallengeTaskClusters.jsx index e409cfdac..233300802 100644 --- a/src/components/HOCs/WithChallengeTaskClusters/WithChallengeTaskClusters.jsx +++ b/src/components/HOCs/WithChallengeTaskClusters/WithChallengeTaskClusters.jsx @@ -17,7 +17,7 @@ import { fromLatLngBounds, boundsWithinAllowedMaxDegrees } from '../../../services/MapBounds/MapBounds' import { fetchTaskClusters, clearTaskClusters } from '../../../services/Task/TaskClusters' -import { fetchBoundedTasks, clearBoundedTasks } +import { fetchBoundedTaskMarkers, fetchBoundedTasks, clearBoundedTasks } from '../../../services/Task/BoundedTask' import { MAX_ZOOM, UNCLUSTER_THRESHOLD } from '../../TaskClusterMap/TaskClusterMap' @@ -109,7 +109,7 @@ export const WithChallengeTaskClusters = function(WrappedComponent, storeTasks=f searchCriteria.page = 0 // Fetch up to threshold+1 individual tasks (eg. 1001 tasks) - this.props.fetchBoundedTasks(searchCriteria, UNCLUSTER_THRESHOLD + 1, !storeTasks, ignoreLocked, true).then(results => { + this.props.fetchBoundedTaskMarkers(searchCriteria, UNCLUSTER_THRESHOLD + 1, !storeTasks, ignoreLocked).then(results => { if (currentFetchId >= this.state.fetchId) { // If we retrieved 1001 tasks then there might be more tasks and // they should be clustered. So fetch as clusters @@ -256,7 +256,7 @@ export const WithChallengeTaskClusters = function(WrappedComponent, storeTasks=f export const mapDispatchToProps = dispatch => Object.assign( {}, - bindActionCreators({ fetchTaskClusters, fetchBoundedTasks }, dispatch), + bindActionCreators({ fetchTaskClusters, fetchBoundedTaskMarkers, fetchBoundedTasks }, dispatch), { clearTasksAndClusters: () => { dispatch(clearBoundedTasks()) diff --git a/src/components/TaskClusterMap/TaskClusterMap.jsx b/src/components/TaskClusterMap/TaskClusterMap.jsx index 2c3fa3744..41c482344 100644 --- a/src/components/TaskClusterMap/TaskClusterMap.jsx +++ b/src/components/TaskClusterMap/TaskClusterMap.jsx @@ -34,7 +34,7 @@ export const MIN_ZOOM = 2 * An uncluster option will be offered if no more than number of tasks * will be shown. */ -export const UNCLUSTER_THRESHOLD = 1000 // max number of tasks +export const UNCLUSTER_THRESHOLD = 500 // max number of tasks /** * The number of clusters to show. diff --git a/src/services/Server/APIRoutes.js b/src/services/Server/APIRoutes.js index c4b69b550..627d4eacb 100644 --- a/src/services/Server/APIRoutes.js +++ b/src/services/Server/APIRoutes.js @@ -105,6 +105,7 @@ const apiRoutes = (factory) => { tasks: { random: factory.get("/tasks/random", { noCache: true }), withinBounds: factory.put("/tasks/box/:left/:bottom/:right/:top"), + markersWithinBounds: factory.put("/markers/box/:left/:bottom/:right/:top"), bulkUpdate: factory.put("/tasks"), bulkStatusChange: factory.put("/tasks/changeStatus"), review: factory.get("/tasks/review"), diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index 9d0b28774..842b18754 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -43,7 +43,109 @@ export const receiveBoundedTasks = function(tasks, } } -// async action creators +/** + * Retrieve all task markers (up to the given limit) matching the given search + * criteria, which should at least include a boundingBox field, and may + * optionally include a filters field with additional constraints + */ +export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispatch = false, ignoreLocked = true, withGeometries) { + return function(dispatch) { + if (!skipDispatch) { + // The map is either showing task clusters or bounded tasks so we shouldn't + // have both in redux. + // (ChallengeLocation needs to know which challenge tasks pass the location) + dispatch(clearTaskClusters()) + } + + const normalizedBounds = toLatLngBounds(criteria.boundingBox) + if (!normalizedBounds) { + return null + } + + const filters = _get(criteria, 'filters', {}) + const searchParameters = generateSearchParametersString( + filters, + null, + _get(criteria, 'savedChallengesOnly'), + null, + null, + _get(criteria, 'invertFields') + ) + + if (!filters.challengeId) { + const onlyEnabled = _isUndefined(criteria.onlyEnabled) ? + true : + criteria.onlyEnabled + const challengeStatus = criteria.challengeStatus + if (challengeStatus) { + searchParameters.cStatus = challengeStatus.join(',') + } + + // ce: limit to enabled challenges + // pe: limit to enabled projects + searchParameters.ce = onlyEnabled ? 'true' : 'false' + searchParameters.pe = onlyEnabled ? 'true' : 'false' + + // if we are restricting to onlyEnabled challenges then let's + // not show 'local' challenges either. + searchParameters.cLocal = onlyEnabled ? CHALLENGE_EXCLUDE_LOCAL : + CHALLENGE_INCLUDE_LOCAL + } + + // If we are searching within map bounds we need to ensure the parent + // challenge is also within those bounds + if (filters.location === CHALLENGE_LOCATION_WITHIN_MAPBOUNDS) { + if (_isArray(criteria.boundingBox)) { + searchParameters.bb = criteria.boundingBox.join(',') + } else { + searchParameters.bb = criteria.boundingBox + } + } + + const fetchId = uuidv1() + !skipDispatch && dispatch(receiveBoundedTasks(null, RequestStatus.inProgress, fetchId)) + + return new Endpoint( + api.tasks.markersWithinBounds, { + schema: { + tasks: [taskSchema()] + }, + variables: { + left: normalizedBounds.getWest(), + bottom: normalizedBounds.getSouth(), + right: normalizedBounds.getEast(), + top: normalizedBounds.getNorth(), + }, + params: { + limit, + excludeLocked: ignoreLocked, + ...searchParameters, + }, + json: filters.taskPropertySearch ? { + taskPropertySearch: filters.taskPropertySearch + } : null, + } + ).execute().then(normalizedResults => { + const totalCount = normalizedResults.result.total + + let tasks = _values(_get(normalizedResults, 'entities.tasks', {})) + tasks = _map(tasks, task => + Object.assign(task, {}, task.pointReview) + ) + + !skipDispatch && dispatch(receiveBoundedTasks(tasks, RequestStatus.success, fetchId, totalCount)) + + return { + tasks, + totalCount + } + }).catch(error => { + dispatch(receiveBoundedTasks([], RequestStatus.error, fetchId)) + dispatch(addError(AppErrors.boundedTask.fetchFailure)) + console.log(error.response || error) + }) + } +} /** * Retrieve all tasks (up to the given limit) matching the given search From 232c8135cd5d2da479087d17ba6cb942b0983c89 Mon Sep 17 00:00:00 2001 From: CollinBeczak Date: Mon, 3 Jun 2024 14:52:38 -0500 Subject: [PATCH 02/13] change UNCLUSTER_THRESHOLD back to 1000 --- src/components/TaskClusterMap/TaskClusterMap.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TaskClusterMap/TaskClusterMap.jsx b/src/components/TaskClusterMap/TaskClusterMap.jsx index 41c482344..2c3fa3744 100644 --- a/src/components/TaskClusterMap/TaskClusterMap.jsx +++ b/src/components/TaskClusterMap/TaskClusterMap.jsx @@ -34,7 +34,7 @@ export const MIN_ZOOM = 2 * An uncluster option will be offered if no more than number of tasks * will be shown. */ -export const UNCLUSTER_THRESHOLD = 500 // max number of tasks +export const UNCLUSTER_THRESHOLD = 1000 // max number of tasks /** * The number of clusters to show. From abb0581480e6ba9bed4d1e78923f79a8df2f23ce Mon Sep 17 00:00:00 2001 From: CollinBeczak Date: Mon, 3 Jun 2024 15:03:15 -0500 Subject: [PATCH 03/13] remove unused param from new endpoint call function --- src/services/Task/BoundedTask.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index 842b18754..1c521e0f1 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -48,7 +48,7 @@ export const receiveBoundedTasks = function(tasks, * criteria, which should at least include a boundingBox field, and may * optionally include a filters field with additional constraints */ -export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispatch = false, ignoreLocked = true, withGeometries) { +export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispatch = false, ignoreLocked = true) { return function(dispatch) { if (!skipDispatch) { // The map is either showing task clusters or bounded tasks so we shouldn't From f23180611524784ef572586b094bca0746bc124e Mon Sep 17 00:00:00 2001 From: CollinBeczak Date: Fri, 19 Jul 2024 12:47:44 -0500 Subject: [PATCH 04/13] update implementation of totalTaskCounts --- src/services/Task/BoundedTask.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index 1c521e0f1..74a8638fd 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -126,9 +126,8 @@ export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispat } : null, } ).execute().then(normalizedResults => { - const totalCount = normalizedResults.result.total - - let tasks = _values(_get(normalizedResults, 'entities.tasks', {})) + let tasks = _values(_get(normalizedResults, 'result', {})) + const totalCount = tasks.length tasks = _map(tasks, task => Object.assign(task, {}, task.pointReview) ) From 08e8d82e015d689204575a405bb9206fda117c5f Mon Sep 17 00:00:00 2001 From: Collin Beczak <88843144+CollinBeczak@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:06:50 -0600 Subject: [PATCH 05/13] reduce reliance on lodash Co-authored-by: Jake Low --- src/services/Task/BoundedTask.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index 74a8638fd..32fb60504 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -62,7 +62,7 @@ export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispat return null } - const filters = _get(criteria, 'filters', {}) + const filters = criteria.filters ?? {}; const searchParameters = generateSearchParametersString( filters, null, From 583cc0e4bf12c3adbfab2f6de8da22cbbbff497c Mon Sep 17 00:00:00 2001 From: Collin Beczak <88843144+CollinBeczak@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:07:02 -0600 Subject: [PATCH 06/13] reduce reliance on lodash Co-authored-by: Jake Low --- src/services/Task/BoundedTask.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index 32fb60504..cb0284e9e 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -66,7 +66,7 @@ export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispat const searchParameters = generateSearchParametersString( filters, null, - _get(criteria, 'savedChallengesOnly'), + criteria.savedChallengesOnly, null, null, _get(criteria, 'invertFields') From bae729616085924fe90de02986c9bab6b999da2f Mon Sep 17 00:00:00 2001 From: Collin Beczak <88843144+CollinBeczak@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:07:49 -0600 Subject: [PATCH 07/13] reduce reliance on lodash Co-authored-by: Jake Low --- src/services/Task/BoundedTask.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index cb0284e9e..904d64213 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -69,7 +69,7 @@ export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispat criteria.savedChallengesOnly, null, null, - _get(criteria, 'invertFields') + criteria.invertFields ) if (!filters.challengeId) { From 180bc55948edc1883ff70b8e30b5bbc774983144 Mon Sep 17 00:00:00 2001 From: Collin Beczak <88843144+CollinBeczak@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:08:19 -0600 Subject: [PATCH 08/13] simplify condition Co-authored-by: Jake Low --- src/services/Task/BoundedTask.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index 904d64213..6fc16dbd6 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -73,9 +73,7 @@ export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispat ) if (!filters.challengeId) { - const onlyEnabled = _isUndefined(criteria.onlyEnabled) ? - true : - criteria.onlyEnabled + const onlyEnabled = criteria.onlyEnabled ?? true; const challengeStatus = criteria.challengeStatus if (challengeStatus) { searchParameters.cStatus = challengeStatus.join(',') From c96d96e84c4e65833cdb2b55f465a495f42cb6b1 Mon Sep 17 00:00:00 2001 From: Collin Beczak <88843144+CollinBeczak@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:09:08 -0600 Subject: [PATCH 09/13] reduce reliance on lodash Co-authored-by: Jake Low --- src/services/Task/BoundedTask.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index 6fc16dbd6..3b28caaa5 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -123,8 +123,8 @@ export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispat taskPropertySearch: filters.taskPropertySearch } : null, } - ).execute().then(normalizedResults => { - let tasks = _values(_get(normalizedResults, 'result', {})) + ).execute().then(({ result }) => { + let tasks = result ? Object.values(result) : []; const totalCount = tasks.length tasks = _map(tasks, task => Object.assign(task, {}, task.pointReview) From 37d926c0252bd7defd14ce526c0f88c5b5bffd5e Mon Sep 17 00:00:00 2001 From: Collin Beczak <88843144+CollinBeczak@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:10:06 -0600 Subject: [PATCH 10/13] reduce reliance on lodash Co-authored-by: Jake Low --- src/services/Task/BoundedTask.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index 3b28caaa5..cba17cdf9 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -126,11 +126,11 @@ export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispat ).execute().then(({ result }) => { let tasks = result ? Object.values(result) : []; const totalCount = tasks.length - tasks = _map(tasks, task => - Object.assign(task, {}, task.pointReview) - ) + tasks = tasks.map(task => Object.assign(task, task.pointReview)) - !skipDispatch && dispatch(receiveBoundedTasks(tasks, RequestStatus.success, fetchId, totalCount)) + if (!skipDispatch) { + dispatch(receiveBoundedTasks(tasks, RequestStatus.success, fetchId, totalCount)) + } return { tasks, From 224e7843022826a5bf0021417c91a043495ceb89 Mon Sep 17 00:00:00 2001 From: CollinBeczak Date: Tue, 3 Dec 2024 13:11:45 -0600 Subject: [PATCH 11/13] reduce reliance on lodash --- src/services/Task/BoundedTask.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index cba17cdf9..fd0d922fd 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -9,7 +9,6 @@ import { addError } from '../Error/Error' import AppErrors from '../Error/AppErrors' import _get from 'lodash/get' import _values from 'lodash/values' -import _isArray from 'lodash/isArray' import _isUndefined from 'lodash/isUndefined' import _map from 'lodash/map' import { generateSearchParametersString } from '../Search/Search' @@ -93,7 +92,7 @@ export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispat // If we are searching within map bounds we need to ensure the parent // challenge is also within those bounds if (filters.location === CHALLENGE_LOCATION_WITHIN_MAPBOUNDS) { - if (_isArray(criteria.boundingBox)) { + if (Array.isArray(criteria.boundingBox)) { searchParameters.bb = criteria.boundingBox.join(',') } else { searchParameters.bb = criteria.boundingBox @@ -200,7 +199,7 @@ export const fetchBoundedTasks = function(criteria, limit=50, skipDispatch=false // If we are searching within map bounds we need to ensure the parent // challenge is also within those bounds if (filters.location === CHALLENGE_LOCATION_WITHIN_MAPBOUNDS) { - if (_isArray(criteria.boundingBox)) { + if (Array.isArray(criteria.boundingBox)) { searchParameters.bb = criteria.boundingBox.join(',') } else { @@ -276,7 +275,7 @@ export const currentBoundedTasks = function(state={}, action) { updatedTasks.loading = true } else { - updatedTasks.tasks = _isArray(action.tasks) ? action.tasks : [] + updatedTasks.tasks = Array.isArray(action.tasks) ? action.tasks : [] updatedTasks.loading = false updatedTasks.totalCount = action.totalCount } From 35705d01ca4853fff94002a2543acddf1ffd2163 Mon Sep 17 00:00:00 2001 From: CollinBeczak Date: Tue, 3 Dec 2024 14:01:49 -0600 Subject: [PATCH 12/13] reduce redundancy --- .../WithChallengeTaskClusters.jsx | 7 ++++--- src/services/Task/BoundedTask.js | 8 ++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/components/HOCs/WithChallengeTaskClusters/WithChallengeTaskClusters.jsx b/src/components/HOCs/WithChallengeTaskClusters/WithChallengeTaskClusters.jsx index 233300802..e9b338386 100644 --- a/src/components/HOCs/WithChallengeTaskClusters/WithChallengeTaskClusters.jsx +++ b/src/components/HOCs/WithChallengeTaskClusters/WithChallengeTaskClusters.jsx @@ -111,10 +111,11 @@ export const WithChallengeTaskClusters = function(WrappedComponent, storeTasks=f // Fetch up to threshold+1 individual tasks (eg. 1001 tasks) this.props.fetchBoundedTaskMarkers(searchCriteria, UNCLUSTER_THRESHOLD + 1, !storeTasks, ignoreLocked).then(results => { if (currentFetchId >= this.state.fetchId) { + const totalCount = results.length // If we retrieved 1001 tasks then there might be more tasks and // they should be clustered. So fetch as clusters // (unless we are zoomed all the way in already) - if (results.totalCount > UNCLUSTER_THRESHOLD && + if (totalCount > UNCLUSTER_THRESHOLD && _get(this.props, 'criteria.zoom', 0) < MAX_ZOOM) { this.props.fetchTaskClusters(challengeId, searchCriteria, 25, overrideDisable ).then(results => { @@ -127,8 +128,8 @@ export const WithChallengeTaskClusters = function(WrappedComponent, storeTasks=f }) } else { - this.setState({clusters: results.tasks, loading: false, - taskCount: results.totalCount}) + this.setState({clusters: results, loading: false, + taskCount: totalCount}) } } }).catch(error => { diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index fd0d922fd..a49c30391 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -124,17 +124,13 @@ export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispat } ).execute().then(({ result }) => { let tasks = result ? Object.values(result) : []; - const totalCount = tasks.length tasks = tasks.map(task => Object.assign(task, task.pointReview)) if (!skipDispatch) { - dispatch(receiveBoundedTasks(tasks, RequestStatus.success, fetchId, totalCount)) + dispatch(receiveBoundedTasks(tasks, RequestStatus.success, fetchId, tasks.length)) } - return { - tasks, - totalCount - } + return tasks }).catch(error => { dispatch(receiveBoundedTasks([], RequestStatus.error, fetchId)) dispatch(addError(AppErrors.boundedTask.fetchFailure)) From d660975b081fe47e0388c99233dc36ce156c5572 Mon Sep 17 00:00:00 2001 From: CollinBeczak Date: Tue, 3 Dec 2024 14:03:30 -0600 Subject: [PATCH 13/13] simplify function syntax --- src/services/Task/BoundedTask.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/Task/BoundedTask.js b/src/services/Task/BoundedTask.js index a49c30391..86e3faa24 100644 --- a/src/services/Task/BoundedTask.js +++ b/src/services/Task/BoundedTask.js @@ -47,7 +47,7 @@ export const receiveBoundedTasks = function(tasks, * criteria, which should at least include a boundingBox field, and may * optionally include a filters field with additional constraints */ -export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispatch = false, ignoreLocked = true) { +export function fetchBoundedTaskMarkers(criteria, limit = 50, skipDispatch = false, ignoreLocked = true) { return function(dispatch) { if (!skipDispatch) { // The map is either showing task clusters or bounded tasks so we shouldn't @@ -144,7 +144,7 @@ export const fetchBoundedTaskMarkers = function(criteria, limit = 50, skipDispat * criteria, which should at least include a boundingBox field, and may * optionally include a filters field with additional constraints */ -export const fetchBoundedTasks = function(criteria, limit=50, skipDispatch=false, ignoreLocked=true, withGeometries) { +export function fetchBoundedTasks(criteria, limit=50, skipDispatch=false, ignoreLocked=true, withGeometries) { return function(dispatch) { if (!skipDispatch) { // The map is either showing task clusters or bounded tasks so we shouldn't