Skip to content

Commit

Permalink
Merge pull request #24 from nrotstan/bug-3-improper-completed-task-co…
Browse files Browse the repository at this point in the history
…ntrols

Show task controls based on task status. Fixes #3
  • Loading branch information
nrotstan authored Jan 29, 2018
2 parents 48fedd0 + e961ce5 commit 66fa6bf
Show file tree
Hide file tree
Showing 76 changed files with 27,223 additions and 8,475 deletions.
10 changes: 6 additions & 4 deletions src/KeyMappings.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
* > [key values](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
*/
export default {
taskEditing: {
openEditor: {
editId: {key: 'e', label: 'Edit in Id'},
editJosm: {key: 'r', label: 'Edit in JOSM'},
editJosmLayer: {key: 't', label: 'Edit in new JOSM layer'},
falsePositive: {key: 'q', label: 'Not an Issue'},
skip: {key: 'w', label: 'Skip'},
},
taskCompletion: {
taskEditing: {
cancel: {key: 'Escape', label: 'Cancel Editing', keyLabel: 'ESC'}
},
taskCompletion: {
skip: {key: 'w', label: 'Skip'},
falsePositive: {key: 'q', label: 'Not an Issue'},
},
}
25 changes: 18 additions & 7 deletions src/components/HOCs/WithKeyboardShortcuts/WithKeyboardShortcuts.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
import { connect } from 'react-redux'
import { get as _get } from 'lodash'
import { setKeyboardShortcuts,
clearKeyboardShortcuts } from '../../../services/KeyboardShortcuts/KeyboardShortcuts'
import { addKeyboardShortcutGroup,
removeKeyboardShortcutGroup,
addKeyboardShortcut,
removeKeyboardShortcut }
from '../../../services/KeyboardShortcuts/KeyboardShortcuts'
import KeyMappings from '../../../KeyMappings'

const mapStateToProps = state => {
return {
keyboardShortcutGroups: KeyMappings,
activeKeyboardShortcuts: _get(state, 'currentKeyboardShortcuts.group'),
activeKeyboardShortcuts: _get(state, 'currentKeyboardShortcuts.groups', {}),
}
}

const mapDispatchToProps = dispatch => {
return {
activateKeyboardShortcuts: (shortcutGroup, handler) => {
activateKeyboardShortcutGroup: (shortcutGroup, handler) => {
document.addEventListener("keydown", handler, false)
dispatch(setKeyboardShortcuts(shortcutGroup))
dispatch(addKeyboardShortcutGroup(shortcutGroup))
},
deactivateKeyboardShortcuts: (shortcutGroup, handler) => {
deactivateKeyboardShortcutGroup: (groupName, handler) => {
document.removeEventListener("keydown", handler)
dispatch(clearKeyboardShortcuts())
dispatch(removeKeyboardShortcutGroup(groupName))
},
activateKeyboardShortcut: (groupName, shortcut, handler) => {
document.addEventListener("keydown", handler, false)
dispatch(addKeyboardShortcut(groupName, shortcut))
},
deactivateKeyboardShortcut: (groupName, shortcutName, handler) => {
document.removeEventListener("keydown", handler)
dispatch(removeKeyboardShortcut(groupName, shortcutName))
},
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Sprites/Sprites.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import { injectIntl } from 'react-intl'
import { get as _get } from 'lodash'
import { isCompleted } from '../../../../services/Task/TaskStatus/TaskStatus'
import { get as _get,
isNumber as _isNumber,
omit as _omit } from 'lodash'
import { allowedStatusProgressions,
TaskStatus } from '../../../../services/Task/TaskStatus/TaskStatus'
import TaskCommentInput from './TaskCommentInput/TaskCommentInput'
import SignInButton from '../../../SignInButton/SignInButton'
import WithMapBoundsState from '../../../HOCs/WithMapBounds/WithMapBoundsState'
import WithKeyboardShortcuts from '../../../HOCs/WithKeyboardShortcuts/WithKeyboardShortcuts'
import BusySpinner from '../../../BusySpinner/BusySpinner'
import TaskEditControls from './TaskEditControls/TaskEditControls'
import TaskCompletionControls from './TaskCompletionControls/TaskCompletionControls'
import TaskDoneControls from './TaskDoneControls/TaskDoneControls'
import TaskStatusIndicator from './TaskStatusIndicator/TaskStatusIndicator'
import TaskCompletionStep1 from './TaskCompletionStep1/TaskCompletionStep1'
import TaskCompletionStep2 from './TaskCompletionStep2/TaskCompletionStep2'
import TaskNextControl from './TaskNextControl/TaskNextControl'
import './ActiveTaskControls.css'

/**
* ActiveTaskControls renders the appropriate controls for the given
Expand All @@ -22,41 +30,95 @@ export class ActiveTaskControls extends Component {
comment: "",
}

setTaskBeingCompleted = taskId => {
this.setState({taskBeingCompleted: taskId})
setComment = comment => this.setState({comment})

/** Choose which editor to launch for fixing a task */
pickEditor = ({ value }) => {
this.setState({taskBeingCompleted: this.props.task.id})
this.props.editTask(value, this.props.task, this.props.mapBounds.task)
}

setComment = comment => this.setState({comment})
cancelEditing = () => {
this.setState({taskBeingCompleted: null})
this.props.closeEditor()
}

/** Mark the task as complete with the given status */
complete = taskStatus => {
this.setState({taskBeingCompleted: this.props.task.id})
this.props.completeTask(this.props.task.id, this.props.task.parent.id,
taskStatus, this.state.comment)
}

render() {
if (!this.props.task) {
// If the user is not logged in, show a sign-in button instead of controls.
if (!_get(this.props, 'user.isLoggedIn')) {
return (
<div className={classNames('active-task-controls', this.props.className,
{'is-minimized': this.props.isMinimized})}>
<div className="has-centered-children">
<SignInButton className="active-task-controls--signin" {...this.props} />
</div>
</div>
)
}
else if (!this.props.task) {
return null
}

const isEditingTask =
_get(this.props, 'editor.taskId') === this.props.task.id &&
_get(this.props, 'editor.success') === true

if (isCompleted(_get(this.props, 'task.status'))) {
return <TaskDoneControls {...this.props} />
}
else if (isEditingTask) {
// Editor is open, show completion options
return <TaskCompletionControls setTaskBeingCompleted={this.setTaskBeingCompleted}
comment={this.state.comment}
setComment={this.setComment}
{...this.props} />
}
else if (_get(this.props, 'editor.taskId') !== this.props.task.id &&
this.state.taskBeingCompleted === this.props.task.id) {
// Busy spinner until editor catches up with us
const editorLoading =
_get(this.props, 'editor.taskId') !== this.props.task.id &&
this.state.taskBeingCompleted === this.props.task.id

if (editorLoading) {
return <BusySpinner />
}
else {
return <TaskEditControls setTaskBeingCompleted={this.setTaskBeingCompleted}
comment={this.state.comment}
setComment={this.setComment}
{...this.props} />
const allowedProgressions =
allowedStatusProgressions(this.props.task.status)

const canProgress = allowedProgressions.size > 0

const hasExistingStatus = _isNumber(this.props.task.status) &&
this.props.task.status !== TaskStatus.created

return (
<div className={classNames('active-task-controls', this.props.className,
{'is-minimized': this.props.isMinimized})}>
{hasExistingStatus &&
<TaskStatusIndicator {...this.props} />
}

{canProgress &&
<TaskCommentInput className="active-task-controls__task-comment"
value={this.state.comment}
commentChanged={this.setComment}
{..._omit(this.props, 'className')} />
}

{!isEditingTask &&
<TaskCompletionStep1 allowedProgressions={allowedProgressions}
pickEditor={this.pickEditor}
complete={this.complete}
{...this.props} />
}

{!isEditingTask && hasExistingStatus &&
<TaskNextControl {...this.props} />
}

{isEditingTask &&
<TaskCompletionStep2 allowedProgressions={allowedProgressions}
complete={this.complete}
cancelEditing={this.cancelEditing}
{...this.props} />
}
</div>
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
@import '../../../../variables.scss';

.active-task-controls {
&__control-block {
display: flex;
justify-content: space-between;
flex-wrap: wrap;

button.button.large-and-wide {
margin-bottom: 10px;

.control-icon svg {
height: 20px;
width: auto;
margin-right: 10px;
}
}
}

&__vertical-control-block {
display: flex;
flex-direction: column;

button {
margin-bottom: 10px;
}
}

&__task-comment {
width: 100%;
margin-bottom: 20px;

input {
width: 100%;
font-size: 16px;
padding: 5px;
border: 2px solid $grey;
border-radius: $radius-medium;
}
}

&.is-minimized {
.active-task-controls__control-block {
flex-direction: column;

.control-label {
display: none;
}
}

button {
margin-bottom: 5px;
}

.active-task-controls__icon {
height: 26px;
width: auto;
margin-left: 0px;
margin-right: 0px;
fill: $default-icon-color;
}

.active-task-controls__task-comment {
display: none;
}

.control-label {
display: none;
}
}
}
Loading

0 comments on commit 66fa6bf

Please sign in to comment.