Skip to content

Commit 034d106

Browse files
authored
Merge pull request #1201 from osmlab/prerelease
v3.5.9
2 parents 6e72cab + 0215f61 commit 034d106

File tree

27 files changed

+1839
-1670
lines changed

27 files changed

+1839
-1670
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ The format is based on
77
This project adheres to
88
[Semantic Versioning](http://semver.org/spec/v2.0.0.html).
99

10+
## [v3.5.9] - 2020-04-09
11+
### Added
12+
- Require interaction before loading tasks in Review Map on Review Page
13+
- Default to showing tasks with Fixed status on Review Page
14+
- New "unnecessary" task-review status for use by challenge managers
15+
- Update translations
16+
17+
### Fixed
18+
- Transient display of incorrect challenge leaderboard results while loading
19+
- Incorrect task count shown when bundling a large number of tasks with lasso
20+
- Erroneous inclusion of virtual project destinations when moving a challenge
21+
- Mixed-case or uppercase MapRoulette tags not saving on tasks (#1192)
22+
23+
1024
## [v3.5.8] - 2020-03-25
1125
### Added
1226
- OpenStreetCam imagery map overlay during task completion

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "maproulette3",
3-
"version": "3.5.8",
3+
"version": "3.5.9",
44
"private": true,
55
"dependencies": {
66
"@mapbox/geo-viewport": "^0.4.0",

src/components/AdminPane/HOCs/WithChallengeManagement/WithChallengeManagement.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { recordChallengeSnapshot }
1717
import { bulkUpdateTasks, deleteChallengeTasks, bulkTaskStatusChange }
1818
from '../../../../services/Task/Task'
1919
import { TaskStatus } from '../../../../services/Task/TaskStatus/TaskStatus'
20+
import { removeReviewRequest } from '../../../../services/Task/TaskReview/TaskReview'
2021
import { addError } from '../../../../services/Error/Error'
2122
import AppErrors from '../../../../services/Error/AppErrors'
2223
import { ChallengeStatus }
@@ -212,6 +213,10 @@ const mapDispatchToProps = (dispatch, ownProps) => ({
212213

213214
applyBulkTaskStatusChange: (newStatus, challengeId, searchCriteria) => {
214215
return dispatch(bulkTaskStatusChange(newStatus, challengeId, searchCriteria))
216+
},
217+
218+
removeReviewRequest: (challengeId, taskIds, searchCriteria) => {
219+
return dispatch(removeReviewRequest(challengeId, taskIds, searchCriteria))
215220
}
216221
})
217222

src/components/AdminPane/Manage/ProjectPickerModal/ProjectPickerModal.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ export default
111111
ProjectPickerModal,
112112
'candidateProjects',
113113
'pagedCandidateProjects',
114-
'projectPickerModal'
114+
'projectPickerModal',
115+
false
115116
),
116117
'projectPickerModal',
117118
'projects',

src/components/AdminPane/Manage/ViewChallengeTasks/ViewChallengeTasks.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ export class ViewChallengeTasks extends Component {
9898
}
9999
}
100100

101+
removeReviewRequests = (selectedIds) => {
102+
if (selectedIds.length === 0) {
103+
return
104+
}
105+
const selectedTasks = this.props.allTasksAreSelected() ? null : selectedIds
106+
107+
this.setState({bulkUpdating: true})
108+
this.props.removeReviewRequest(this.props.challenge.id, selectedTasks, this.props.criteria).then(() => {
109+
this.props.refreshChallenge()
110+
this.props.refreshTasks()
111+
this.setState({bulkUpdating: false})
112+
})
113+
}
114+
101115
resetMapBounds = () => {
102116
this.setState({boundsReset: true})
103117
this.props.clearMapBounds(this.props.searchGroup)
@@ -214,6 +228,7 @@ export class ViewChallengeTasks extends Component {
214228
<TaskAnalysisTable
215229
taskData={_get(this.props, 'taskInfo.tasks')}
216230
changeStatus={this.changeStatus}
231+
removeReviewRequests={this.removeReviewRequests}
217232
totalTaskCount={_get(this.props, 'taskInfo.totalCount')}
218233
totalTasksInChallenge={ calculateTasksInChallenge(this.props) }
219234
loading={this.props.loadingChallenge}

src/components/EnhancedMap/EnhancedMap.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { geoJSON, LatLngBounds, LatLng, latLng } from 'leaflet'
66
import _isEmpty from 'lodash/isEmpty'
77
import _isEqual from 'lodash/isEqual'
88
import _isFunction from 'lodash/isFunction'
9+
import _isFinite from 'lodash/isFinite'
910
import AsSimpleStyleableFeature
1011
from '../../interactions/TaskFeature/AsSimpleStyleableFeature'
1112
import PropertyList from './PropertyList/PropertyList'
@@ -200,13 +201,13 @@ export default class EnhancedMap extends Map {
200201
}
201202
}
202203

203-
if (this.props.initialBounds) {
204+
if (this.props.initialBounds && _isFinite(this.props.initialBounds.getNorth())) {
204205
this.leafletElement.fitBounds(this.props.initialBounds)
205206
}
206207
}
207208

208209
componentDidUpdate(prevProps, prevState) {
209-
if (this.props.initialBounds) {
210+
if (this.props.initialBounds && _isFinite(this.props.initialBounds.getNorth())) {
210211
this.leafletElement.fitBounds(this.props.initialBounds)
211212
}
212213
else if (!this.props.center.equals(prevProps.center)) {

src/components/HOCs/WithLeaderboard/WithLeaderboard.js

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import _isEqual from 'lodash/isEqual'
66
import _clone from 'lodash/clone'
77
import _get from 'lodash/get'
88
import _merge from 'lodash/merge'
9+
import _uniqueId from 'lodash/uniqueId'
910
import queryString from 'query-string'
1011
import { fetchLeaderboard, fetchLeaderboardForUser,
1112
DEFAULT_LEADERBOARD_COUNT } from '../../../services/Leaderboard/Leaderboard'
@@ -22,15 +23,17 @@ const WithLeaderboard = function(WrappedComponent, initialMonthsPast=1, initialO
2223
leaderboard: null,
2324
leaderboardLoading: false,
2425
showingCount: DEFAULT_LEADERBOARD_COUNT,
25-
leaderboardOptions: initialOptions,
26+
fetchId: -1,
2627
}
2728

2829
/** merge the given userLeaderboard in with the main leaderboard */
2930
mergeInUserLeaderboard = userLeaderboard => {
3031
if (userLeaderboard && userLeaderboard.length > 0) {
3132
const merged = _clone(this.state.leaderboard)
32-
merged.splice(userLeaderboard[0].rank - 1, userLeaderboard.length, ...userLeaderboard)
33-
this.setState({leaderboard: merged})
33+
if (merged) {
34+
merged.splice(userLeaderboard[0].rank - 1, userLeaderboard.length, ...userLeaderboard)
35+
this.setState({leaderboard: merged})
36+
}
3437
}
3538
}
3639

@@ -41,8 +44,7 @@ const WithLeaderboard = function(WrappedComponent, initialMonthsPast=1, initialO
4144
['forChallenges', null],
4245
['forUsers', null],
4346
['forCountries', null]])
44-
45-
const leaderboardOptions = _merge(this.state.leaderboardOptions, this.props.leaderboardOptions)
47+
const leaderboardOptions = _merge({}, initialOptions, this.props.leaderboardOptions)
4648
if (leaderboardOptions) {
4749
if (_isBoolean(leaderboardOptions.onlyEnabled)) {
4850
params.set('onlyEnabled', leaderboardOptions.onlyEnabled)
@@ -75,23 +77,29 @@ const WithLeaderboard = function(WrappedComponent, initialMonthsPast=1, initialO
7577

7678
// If we are filtering by challenges and no challenges are provided then
7779
// we don't need to go to the server.
78-
const options = _merge(this.state.leaderboardOptions, this.props.leaderboardOptions)
80+
const options = _merge({}, initialOptions, this.props.leaderboardOptions)
7981
if (options.filterChallenges && _isArray(this.props.challenges) &&
8082
this.props.challenges.length < 1) {
8183
return
8284
}
8385

84-
this.setState({leaderboardLoading: true, showingCount})
86+
const currentFetch = _uniqueId()
87+
this.setState({leaderboardLoading: true, showingCount, fetchId: currentFetch})
8588

8689
fetchLeaderboard(...this.leaderboardParams(numberMonths, countryCode), showingCount).then(leaderboard => {
87-
this.setState({leaderboard})
88-
89-
const userId = _get(this.props, 'user.id')
90-
if (userId && !this.state.leaderboardOptions.ignoreUser) {
91-
fetchLeaderboardForUser(userId, 1, ...this.leaderboardParams(numberMonths, countryCode)).then(userLeaderboard => {
92-
this.mergeInUserLeaderboard(userLeaderboard)
90+
if (currentFetch >= this.state.fetchId) {
91+
this.setState({leaderboard})
92+
93+
const userId = _get(this.props, 'user.id')
94+
if (userId && !options.ignoreUser) {
95+
fetchLeaderboardForUser(userId, 1, ...this.leaderboardParams(numberMonths, countryCode)).then(userLeaderboard => {
96+
this.mergeInUserLeaderboard(userLeaderboard)
97+
this.setState({leaderboardLoading: false})
98+
})
99+
}
100+
else {
93101
this.setState({leaderboardLoading: false})
94-
})
102+
}
95103
}
96104
else {
97105
this.setState({leaderboardLoading: false})

src/components/HOCs/WithPagedProjects/WithPagedProjects.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import { RESULTS_PER_PAGE } from '../../../services/Search/Search'
1515
export default function(WrappedComponent,
1616
projectsProp,
1717
outputProp,
18-
pageSearchGroup) {
18+
pageSearchGroup,
19+
allowVirtual = true) {
1920
class WithPagedProjects extends Component {
2021
render() {
2122
const searchGroups = this.props.adminChallengesSearchActive ? ["adminProjects", "adminChallenges"] : ["adminProjectList"]
@@ -29,6 +30,9 @@ export default function(WrappedComponent,
2930
const numberResultsToShow = (currentPage + 1) * resultsPerPage
3031

3132
let pagedProjects = this.props[projectsProp]
33+
if (!allowVirtual) {
34+
pagedProjects = _filter(pagedProjects, p => !p.isVirtual)
35+
}
3236

3337
const hasMoreResults = (pagedProjects.length > numberResultsToShow) || this.props.isLoading
3438

src/components/HOCs/WithReviewTaskClusters/WithReviewTaskClusters.js

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,33 +19,42 @@ export const WithReviewTaskClusters = function(WrappedComponent) {
1919
return class extends Component {
2020
state = {
2121
loading: false,
22+
loadMap: false,
2223
}
2324

2425
updateBounds(bounds) {
26+
if (!this.state.loadMap) {
27+
this.setState({loadMap: true})
28+
}
2529
const criteria = _cloneDeep(this.props.reviewCriteria)
2630
criteria.boundingBox = fromLatLngBounds(bounds).join(',')
2731
this.props.updateReviewTasks(criteria)
2832
}
2933

3034
fetchUpdatedClusters() {
31-
this.setState({loading: true})
35+
if (this.state.loadMap) {
36+
this.setState({loading: true})
3237

33-
this.props.fetchClusteredReviewTasks(
34-
this.props.reviewTasksType, this.props.reviewCriteria
35-
).catch(e => {}).then(() => this.setState({loading: false}))
38+
this.props.fetchClusteredReviewTasks(
39+
this.props.reviewTasksType, this.props.reviewCriteria
40+
).catch(e => {}).then(() => this.setState({loading: false}))
41+
}
3642
}
3743

3844
componentDidMount() {
3945
this.fetchUpdatedClusters()
4046
}
4147

42-
componentDidUpdate(prevProps) {
48+
componentDidUpdate(prevProps, prevState) {
4349
if (prevProps.reviewTasksType !== this.props.reviewTasksType) {
4450
this.fetchUpdatedClusters()
4551
}
4652
else if (prevProps.reviewCriteria !== this.props.reviewCriteria) {
4753
this.fetchUpdatedClusters()
4854
}
55+
else if (this.state.loadMap !== prevState.loadMap) {
56+
this.fetchUpdatedClusters()
57+
}
4958
}
5059

5160
render() {
@@ -57,8 +66,10 @@ export const WithReviewTaskClusters = function(WrappedComponent) {
5766
{..._omit(this.props, ['reviewClusters', 'fetchId', 'updateReviewClusters'])}
5867
taskClusters = {this.props.reviewClusters}
5968
boundingBox={bounds}
60-
updateBounds = {bounds => this.updateBounds(bounds)}
61-
loading = {this.state.loading}
69+
updateBounds={bounds => this.updateBounds(bounds)}
70+
loading={this.state.loading}
71+
delayMapLoad={!this.state.loadMap}
72+
forceMapLoad={() => this.setState({loadMap: true})}
6273
/>
6374
)
6475
}

src/components/HOCs/WithReviewTasks/WithReviewTasks.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import _cloneDeep from 'lodash/cloneDeep'
66
import _isUndefined from 'lodash/isUndefined'
77
import WithCurrentUser from '../WithCurrentUser/WithCurrentUser'
88
import { ReviewTasksType } from '../../../services/Task/TaskReview/TaskReview'
9+
import { TaskStatus } from '../../../services/Task/TaskStatus/TaskStatus'
910
import { fetchReviewNeededTasks }
1011
from '../../../services/Task/TaskReview/TaskReviewNeeded'
1112
import { fetchReviewedTasks }
@@ -96,6 +97,9 @@ export const WithReviewTasks = function(WrappedComponent, reviewStatus=0) {
9697

9798
const stateCriteria = this.state.criteria
9899
stateCriteria[this.props.reviewTasksType] = criteria
100+
if (this.props.reviewTasksType === ReviewTasksType.toBeReviewed) {
101+
stateCriteria[this.props.reviewTasksType].filters = {status: TaskStatus.fixed}
102+
}
99103
this.setState({criteria: stateCriteria})
100104
}
101105

0 commit comments

Comments
 (0)