Skip to content

Commit

Permalink
Merge pull request #662 from osmlab/prerelease
Browse files Browse the repository at this point in the history
v3.2.2 release
  • Loading branch information
nrotstan authored Mar 1, 2019
2 parents e09aa07 + 28cbaf5 commit 6d1323a
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 19 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ The format is based on
This project adheres to
[Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [v3.2.2] - 2019-02-28
### Added
- Offer "Not an Issue" on step 2 of task completion
- Zoom JOSM to task map bounding box after loading just features

### Fixed
- Ensure OSM Data Layer is deactivated after completing a task
- Honor task priorities when loading the next random task


## [v3.2.1] - 2019-02-25
### Added
- Create & Manage widget for managing project managers (#534)
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.2.1",
"version": "3.2.2",
"private": true,
"dependencies": {
"@mapbox/geojsonhint": "^2.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import TaskFixedControl from '../TaskFixedControl/TaskFixedControl'
import TaskTooHardControl from '../TaskTooHardControl/TaskTooHardControl'
import TaskAlreadyFixedControl from '../TaskAlreadyFixedControl/TaskAlreadyFixedControl'
import TaskSkipControl from '../TaskSkipControl/TaskSkipControl'
import TaskFalsePositiveControl from '../TaskFalsePositiveControl/TaskFalsePositiveControl'
import TaskCancelEditingControl from '../TaskCancelEditingControl/TaskCancelEditingControl'
import Dropdown from '../../../../Dropdown/Dropdown'
import './TaskCompletionStep2.scss'

/**
Expand All @@ -17,6 +19,10 @@ import './TaskCompletionStep2.scss'
* @author [Neil Rotstan](https://github.com/nrotstan)
*/
export default class TaskCompletionStep2 extends Component {
state = {
moreOptionsOpen: false,
}

render() {
return (
<div>
Expand All @@ -33,8 +39,17 @@ export default class TaskCompletionStep2 extends Component {
<TaskAlreadyFixedControl {...this.props} />
}

{this.props.allowedProgressions.has(TaskStatus.skipped) &&
<TaskSkipControl {...this.props} suppressIcon />
{(this.props.allowedProgressions.has(TaskStatus.skipped) ||
this.props.allowedProgressions.has(TaskStatus.falsePositive)) &&
<Dropdown
className="mr-dropdown--fixed mr-w-full"
dropdownButton={dropdown =>
<MoreOptionsButton toggleDropdownVisible={dropdown.toggleDropdownVisible} />
}
dropdownContent={dropdown =>
<ListMoreOptionsItems {...this.props} />
}
/>
}
</div>

Expand All @@ -44,6 +59,34 @@ export default class TaskCompletionStep2 extends Component {
}
}

const MoreOptionsButton = function(props) {
return (
<button
className="mr-dropdown__button mr-button mr-text-green-lighter mr-w-full"
onClick={props.toggleDropdownVisible}
>
Other&hellip;
</button>
)
}

const ListMoreOptionsItems = function(props) {
return (
<ol className="mr-list-dropdown">
{props.allowedProgressions.has(TaskStatus.skipped) &&
<li>
<TaskSkipControl {...props} asLink />
</li>
}
{props.allowedProgressions.has(TaskStatus.falsePositive) &&
<li>
<TaskFalsePositiveControl {...props} asLink />
</li>
}
</ol>
)
}

TaskCompletionStep2.propTypes = {
/** The task being completed */
task: PropTypes.object.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ export default class TaskFalsePositiveControl extends Component {
}

render() {
if (this.props.asLink) {
return (
// eslint-disable-next-line jsx-a11y/anchor-is-valid
<a onClick={() => this.props.complete(TaskStatus.falsePositive)}>
<FormattedMessage {...messages.falsePositiveLabel} />
</a>
)
}

return (
<Button
className="mr-button--blue-fill"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ export default class TaskSkipControl extends Component {
}

render() {
if (this.props.asLink) {
return (
// eslint-disable-next-line jsx-a11y/anchor-is-valid
<a onClick={() => this.props.complete(TaskStatus.skipped)}>
<FormattedMessage {...messages.skipLabel} />
</a>
)
}

return (
<Button
className="mr-button--blue-fill"
Expand Down
13 changes: 12 additions & 1 deletion src/components/TaskPane/TaskMap/TaskMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ export class TaskMap extends Component {
this.setState({showOSMData: !this.state.showOSMData})
}

/**
* Ensures the OSM Data Layer is deactivated
*/
deactivateOSMDataLayer = () => {
this.setState({showOSMData: false, osmData: null, osmDataLoading: false})
}

/**
* Invoked by LayerToggle when the user wishes to toggle visibility of
* Mapillary markers on or off.
Expand Down Expand Up @@ -132,8 +139,12 @@ export class TaskMap extends Component {
this.loadMapillaryIfNeeded()
}

componentDidUpdate() {
componentDidUpdate(prevProps) {
this.loadMapillaryIfNeeded()

if (_get(this.props, 'task.id') !== _get(prevProps, 'task.id')) {
this.deactivateOSMDataLayer()
}
}

shouldComponentUpdate(nextProps, nextState) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/UserEditorSelector/UserEditorSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default class UserEditorSelector extends Component {
</span>
{this.state.isSaving ? <BusySpinner /> :
<Dropdown
className="mr-dropdown"
className="mr-dropdown mr-dropdown--fixed"
dropdownButton={dropdown =>
<EditorButton
editorLabels={localizedEditorLabels}
Expand Down
56 changes: 42 additions & 14 deletions src/services/Editor/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,21 @@ export const editTask = function(editor, task, mapBounds) {
dispatch(editorOpened(editor, task.id, RequestStatus.success))
}
else if (isJosmEditor(editor)) {
const josmURIFunction =
editor === JOSM_FEATURES ? josmLoadObjectURI : josmLoadAndZoomURI

openJOSM(dispatch, editor, task, mapBounds, josmURIFunction)
if (editor === JOSM_FEATURES) {
// Load the features, then zoom JOSM to the task map's bounding box.
// Otherwise if there are long features like a highway, the user could
// end up zoomed way out by default. We have to do this as two separate
// calls to JOSM, with a bit of a delay to give JOSM the chance to load
// the object before we try to zoom
openJOSM(
dispatch, editor, task, mapBounds, josmLoadObjectURI
).then(
() => setTimeout(() => sendJOSMCommand(josmZoomURI(task, mapBounds)), 1000)
)
}
else {
openJOSM(dispatch, editor, task, mapBounds, josmLoadAndZoomURI)
}
}
}
}
Expand Down Expand Up @@ -268,6 +279,15 @@ export const josmLoadAndZoomURI = function(dispatch, editor, task, mapBounds) {
].join('&')
}

/*
* Builds a URI for the JOSM zoom remote control command
*
* @see See https://josm.openstreetmap.de/wiki/Help/RemoteControlCommands#zoom
*/
export const josmZoomURI = function(task, mapBounds) {
return josmHost() + 'zoom?' + josmBoundsParams(task, mapBounds)
}

/*
* Builds a URI for the JOSM load_object remote control command, useful for loading
* just a task's features. If the task contains no features with OSM identifiers
Expand All @@ -294,29 +314,37 @@ export const josmLoadObjectURI = function(dispatch, editor, task, mapBounds) {
].join('&')
}

/**
* Sends a command to JOSM and returns a promise that resolves to true on
* success, false on failure
*/
const sendJOSMCommand = function(uri) {
return fetch(uri).then(
response => response.status === 200
).catch(error => {
console.log(error)
return false
})
}

/**
* Execute an ajax request to open the JOSM editor. The given josmURIFunction
* will be invoked to generate the remote-control command URI
*/
const openJOSM = function(dispatch, editor, task, mapBounds, josmURIFunction) {
const uri = josmURIFunction(dispatch, editor, task, mapBounds)
if (!uri) {
return
return Promise.resolve()
}

fetch(uri).then(response => {
if (response.status === 200) {
dispatch(editorOpened(editor, task.id, RequestStatus.success))
return sendJOSMCommand(uri).then(success => {
if (success) {
return dispatch(editorOpened(editor, task.id, RequestStatus.success))
}
else {
dispatch(addError(AppErrors.josm.noResponse))
dispatch(editorOpened(editor, task.id, RequestStatus.error))
return dispatch(editorOpened(editor, task.id, RequestStatus.error))
}
}).catch(error => {
// Could be no response, but could also be download too large or some other
// JOSM error
dispatch(addError(AppErrors.josm.noResponse))
dispatch(editorOpened(editor, task.id, RequestStatus.error))
})
}

Expand Down

0 comments on commit 6d1323a

Please sign in to comment.