Skip to content

Commit

Permalink
Merge pull request #1201 from osmlab/prerelease
Browse files Browse the repository at this point in the history
v3.5.9
  • Loading branch information
nrotstan authored Apr 8, 2020
2 parents 6e72cab + 0215f61 commit 034d106
Show file tree
Hide file tree
Showing 27 changed files with 1,839 additions and 1,670 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ The format is based on
This project adheres to
[Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [v3.5.9] - 2020-04-09
### Added
- Require interaction before loading tasks in Review Map on Review Page
- Default to showing tasks with Fixed status on Review Page
- New "unnecessary" task-review status for use by challenge managers
- Update translations

### Fixed
- Transient display of incorrect challenge leaderboard results while loading
- Incorrect task count shown when bundling a large number of tasks with lasso
- Erroneous inclusion of virtual project destinations when moving a challenge
- Mixed-case or uppercase MapRoulette tags not saving on tasks (#1192)


## [v3.5.8] - 2020-03-25
### Added
- OpenStreetCam imagery map overlay during task completion
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "maproulette3",
"version": "3.5.8",
"version": "3.5.9",
"private": true,
"dependencies": {
"@mapbox/geo-viewport": "^0.4.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { recordChallengeSnapshot }
import { bulkUpdateTasks, deleteChallengeTasks, bulkTaskStatusChange }
from '../../../../services/Task/Task'
import { TaskStatus } from '../../../../services/Task/TaskStatus/TaskStatus'
import { removeReviewRequest } from '../../../../services/Task/TaskReview/TaskReview'
import { addError } from '../../../../services/Error/Error'
import AppErrors from '../../../../services/Error/AppErrors'
import { ChallengeStatus }
Expand Down Expand Up @@ -212,6 +213,10 @@ const mapDispatchToProps = (dispatch, ownProps) => ({

applyBulkTaskStatusChange: (newStatus, challengeId, searchCriteria) => {
return dispatch(bulkTaskStatusChange(newStatus, challengeId, searchCriteria))
},

removeReviewRequest: (challengeId, taskIds, searchCriteria) => {
return dispatch(removeReviewRequest(challengeId, taskIds, searchCriteria))
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ export default
ProjectPickerModal,
'candidateProjects',
'pagedCandidateProjects',
'projectPickerModal'
'projectPickerModal',
false
),
'projectPickerModal',
'projects',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,20 @@ export class ViewChallengeTasks extends Component {
}
}

removeReviewRequests = (selectedIds) => {
if (selectedIds.length === 0) {
return
}
const selectedTasks = this.props.allTasksAreSelected() ? null : selectedIds

this.setState({bulkUpdating: true})
this.props.removeReviewRequest(this.props.challenge.id, selectedTasks, this.props.criteria).then(() => {
this.props.refreshChallenge()
this.props.refreshTasks()
this.setState({bulkUpdating: false})
})
}

resetMapBounds = () => {
this.setState({boundsReset: true})
this.props.clearMapBounds(this.props.searchGroup)
Expand Down Expand Up @@ -214,6 +228,7 @@ export class ViewChallengeTasks extends Component {
<TaskAnalysisTable
taskData={_get(this.props, 'taskInfo.tasks')}
changeStatus={this.changeStatus}
removeReviewRequests={this.removeReviewRequests}
totalTaskCount={_get(this.props, 'taskInfo.totalCount')}
totalTasksInChallenge={ calculateTasksInChallenge(this.props) }
loading={this.props.loadingChallenge}
Expand Down
5 changes: 3 additions & 2 deletions src/components/EnhancedMap/EnhancedMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { geoJSON, LatLngBounds, LatLng, latLng } from 'leaflet'
import _isEmpty from 'lodash/isEmpty'
import _isEqual from 'lodash/isEqual'
import _isFunction from 'lodash/isFunction'
import _isFinite from 'lodash/isFinite'
import AsSimpleStyleableFeature
from '../../interactions/TaskFeature/AsSimpleStyleableFeature'
import PropertyList from './PropertyList/PropertyList'
Expand Down Expand Up @@ -200,13 +201,13 @@ export default class EnhancedMap extends Map {
}
}

if (this.props.initialBounds) {
if (this.props.initialBounds && _isFinite(this.props.initialBounds.getNorth())) {
this.leafletElement.fitBounds(this.props.initialBounds)
}
}

componentDidUpdate(prevProps, prevState) {
if (this.props.initialBounds) {
if (this.props.initialBounds && _isFinite(this.props.initialBounds.getNorth())) {
this.leafletElement.fitBounds(this.props.initialBounds)
}
else if (!this.props.center.equals(prevProps.center)) {
Expand Down
36 changes: 22 additions & 14 deletions src/components/HOCs/WithLeaderboard/WithLeaderboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import _isEqual from 'lodash/isEqual'
import _clone from 'lodash/clone'
import _get from 'lodash/get'
import _merge from 'lodash/merge'
import _uniqueId from 'lodash/uniqueId'
import queryString from 'query-string'
import { fetchLeaderboard, fetchLeaderboardForUser,
DEFAULT_LEADERBOARD_COUNT } from '../../../services/Leaderboard/Leaderboard'
Expand All @@ -22,15 +23,17 @@ const WithLeaderboard = function(WrappedComponent, initialMonthsPast=1, initialO
leaderboard: null,
leaderboardLoading: false,
showingCount: DEFAULT_LEADERBOARD_COUNT,
leaderboardOptions: initialOptions,
fetchId: -1,
}

/** merge the given userLeaderboard in with the main leaderboard */
mergeInUserLeaderboard = userLeaderboard => {
if (userLeaderboard && userLeaderboard.length > 0) {
const merged = _clone(this.state.leaderboard)
merged.splice(userLeaderboard[0].rank - 1, userLeaderboard.length, ...userLeaderboard)
this.setState({leaderboard: merged})
if (merged) {
merged.splice(userLeaderboard[0].rank - 1, userLeaderboard.length, ...userLeaderboard)
this.setState({leaderboard: merged})
}
}
}

Expand All @@ -41,8 +44,7 @@ const WithLeaderboard = function(WrappedComponent, initialMonthsPast=1, initialO
['forChallenges', null],
['forUsers', null],
['forCountries', null]])

const leaderboardOptions = _merge(this.state.leaderboardOptions, this.props.leaderboardOptions)
const leaderboardOptions = _merge({}, initialOptions, this.props.leaderboardOptions)
if (leaderboardOptions) {
if (_isBoolean(leaderboardOptions.onlyEnabled)) {
params.set('onlyEnabled', leaderboardOptions.onlyEnabled)
Expand Down Expand Up @@ -75,23 +77,29 @@ const WithLeaderboard = function(WrappedComponent, initialMonthsPast=1, initialO

// If we are filtering by challenges and no challenges are provided then
// we don't need to go to the server.
const options = _merge(this.state.leaderboardOptions, this.props.leaderboardOptions)
const options = _merge({}, initialOptions, this.props.leaderboardOptions)
if (options.filterChallenges && _isArray(this.props.challenges) &&
this.props.challenges.length < 1) {
return
}

this.setState({leaderboardLoading: true, showingCount})
const currentFetch = _uniqueId()
this.setState({leaderboardLoading: true, showingCount, fetchId: currentFetch})

fetchLeaderboard(...this.leaderboardParams(numberMonths, countryCode), showingCount).then(leaderboard => {
this.setState({leaderboard})

const userId = _get(this.props, 'user.id')
if (userId && !this.state.leaderboardOptions.ignoreUser) {
fetchLeaderboardForUser(userId, 1, ...this.leaderboardParams(numberMonths, countryCode)).then(userLeaderboard => {
this.mergeInUserLeaderboard(userLeaderboard)
if (currentFetch >= this.state.fetchId) {
this.setState({leaderboard})

const userId = _get(this.props, 'user.id')
if (userId && !options.ignoreUser) {
fetchLeaderboardForUser(userId, 1, ...this.leaderboardParams(numberMonths, countryCode)).then(userLeaderboard => {
this.mergeInUserLeaderboard(userLeaderboard)
this.setState({leaderboardLoading: false})
})
}
else {
this.setState({leaderboardLoading: false})
})
}
}
else {
this.setState({leaderboardLoading: false})
Expand Down
6 changes: 5 additions & 1 deletion src/components/HOCs/WithPagedProjects/WithPagedProjects.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import { RESULTS_PER_PAGE } from '../../../services/Search/Search'
export default function(WrappedComponent,
projectsProp,
outputProp,
pageSearchGroup) {
pageSearchGroup,
allowVirtual = true) {
class WithPagedProjects extends Component {
render() {
const searchGroups = this.props.adminChallengesSearchActive ? ["adminProjects", "adminChallenges"] : ["adminProjectList"]
Expand All @@ -29,6 +30,9 @@ export default function(WrappedComponent,
const numberResultsToShow = (currentPage + 1) * resultsPerPage

let pagedProjects = this.props[projectsProp]
if (!allowVirtual) {
pagedProjects = _filter(pagedProjects, p => !p.isVirtual)
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,42 @@ export const WithReviewTaskClusters = function(WrappedComponent) {
return class extends Component {
state = {
loading: false,
loadMap: false,
}

updateBounds(bounds) {
if (!this.state.loadMap) {
this.setState({loadMap: true})
}
const criteria = _cloneDeep(this.props.reviewCriteria)
criteria.boundingBox = fromLatLngBounds(bounds).join(',')
this.props.updateReviewTasks(criteria)
}

fetchUpdatedClusters() {
this.setState({loading: true})
if (this.state.loadMap) {
this.setState({loading: true})

this.props.fetchClusteredReviewTasks(
this.props.reviewTasksType, this.props.reviewCriteria
).catch(e => {}).then(() => this.setState({loading: false}))
this.props.fetchClusteredReviewTasks(
this.props.reviewTasksType, this.props.reviewCriteria
).catch(e => {}).then(() => this.setState({loading: false}))
}
}

componentDidMount() {
this.fetchUpdatedClusters()
}

componentDidUpdate(prevProps) {
componentDidUpdate(prevProps, prevState) {
if (prevProps.reviewTasksType !== this.props.reviewTasksType) {
this.fetchUpdatedClusters()
}
else if (prevProps.reviewCriteria !== this.props.reviewCriteria) {
this.fetchUpdatedClusters()
}
else if (this.state.loadMap !== prevState.loadMap) {
this.fetchUpdatedClusters()
}
}

render() {
Expand All @@ -57,8 +66,10 @@ export const WithReviewTaskClusters = function(WrappedComponent) {
{..._omit(this.props, ['reviewClusters', 'fetchId', 'updateReviewClusters'])}
taskClusters = {this.props.reviewClusters}
boundingBox={bounds}
updateBounds = {bounds => this.updateBounds(bounds)}
loading = {this.state.loading}
updateBounds={bounds => this.updateBounds(bounds)}
loading={this.state.loading}
delayMapLoad={!this.state.loadMap}
forceMapLoad={() => this.setState({loadMap: true})}
/>
)
}
Expand Down
4 changes: 4 additions & 0 deletions src/components/HOCs/WithReviewTasks/WithReviewTasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import _cloneDeep from 'lodash/cloneDeep'
import _isUndefined from 'lodash/isUndefined'
import WithCurrentUser from '../WithCurrentUser/WithCurrentUser'
import { ReviewTasksType } from '../../../services/Task/TaskReview/TaskReview'
import { TaskStatus } from '../../../services/Task/TaskStatus/TaskStatus'
import { fetchReviewNeededTasks }
from '../../../services/Task/TaskReview/TaskReviewNeeded'
import { fetchReviewedTasks }
Expand Down Expand Up @@ -96,6 +97,9 @@ export const WithReviewTasks = function(WrappedComponent, reviewStatus=0) {

const stateCriteria = this.state.criteria
stateCriteria[this.props.reviewTasksType] = criteria
if (this.props.reviewTasksType === ReviewTasksType.toBeReviewed) {
stateCriteria[this.props.reviewTasksType].filters = {status: TaskStatus.fixed}
}
this.setState({criteria: stateCriteria})
}

Expand Down
5 changes: 5 additions & 0 deletions src/components/TaskAnalysisTable/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ export default defineMessages({
defaultMessage: "Choose ... ",
},

changeReviewStatusLabel: {
id: "Admin.manageTasks.controls.changeReviewStatus.label",
defaultMessage: "Remove from review queue ",
},

showReviewColumnsLabel: {
id: "Admin.manageTasks.controls.showReviewColumns.label",
defaultMessage: "Show Review Columns",
Expand Down
5 changes: 5 additions & 0 deletions src/components/TaskAnalysisTable/TaskAnalysisTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ export class TaskAnalysisTable extends Component {
_filter([...this.props.selectedTasks.keys()],
taskId => _find(data, task => task.id === taskId))

// If this is for bundling then we really do want to the full count of
// selected tasks since they could have used the "lasso" tool.
const selectedTaskCount = this.props.forBundling ?
this.props.selectedTasks.size : selectedDataTasks.length

if (_get(this.props, 'criteria.filters')) {
defaultFiltered = _map(this.props.criteria.filters,
Expand All @@ -203,6 +207,7 @@ export class TaskAnalysisTable extends Component {
countShown={data.length}
configureColumns={this.configureColumns.bind(this)}
selectedTasks={selectedDataTasks}
selectedTaskCount={selectedTaskCount}
/>
</header>
}
Expand Down
Loading

0 comments on commit 034d106

Please sign in to comment.