Skip to content

Commit

Permalink
Merge pull request #1115 from osmlab/prerelease
Browse files Browse the repository at this point in the history
v3.5.5
  • Loading branch information
nrotstan authored Feb 19, 2020
2 parents 11c7af1 + 812985a commit aa1d8d5
Show file tree
Hide file tree
Showing 131 changed files with 3,870 additions and 2,153 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.5] - 2020-02-19
### Added
- Featured projects
- Custom task styling based on arbitrary feature properties
- Simpler OR'ing of multiple values on feature property search
- Tabulation of Review Status metrics by task priority
- Custom date range option when viewing user metrics
- Ability to work on task bundles from any member task
- [internal] upgrade Tailwind and other package dependencies

### Fixed
- Users not being made admins of projects they create (#433)


## [v3.5.4] - 2020-02-07
### Added
- Ability to designate task property as OSM id in challenge creation
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ CSS](https://tailwindcss.com) with PostCSS. New CSS classes are prefixed with
transition there are still situations where a mix of both Tailwind and Bulma
are in play.

Tailwind configuration is controlled with the `src/tailwind.js` file. New CSS
classes can be found in `src/styles/`
Tailwind configuration is controlled with the `src/tailwind.config.js` file.
New CSS classes can be found in `src/styles/`

## Internationalization and Localization

Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "maproulette3",
"version": "3.5.4",
"version": "3.5.5",
"private": true,
"dependencies": {
"@mapbox/geo-viewport": "^0.4.0",
Expand Down Expand Up @@ -89,18 +89,18 @@
"enzyme": "^3.2.0",
"enzyme-adapter-react-16": "^1.1.1",
"npm-run-all": "^4.1.1",
"postcss-cli": "^6.1.0",
"postcss-cli": "^7.1.0",
"postcss-import": "^12.0.1",
"postcss-nested": "^4.1.1",
"postcss-nested": "^4.2.0",
"postcss-simple-vars": "^5.0.1",
"react-test-renderer": "^16.2.0",
"redux-mock-store": "^1.4.0",
"shelljs": "^0.8.2",
"tailwindcss": "^0.7.3",
"tailwindcss-gradients": "^1.1.0",
"tailwindcss": "^1.0",
"tailwindcss-gradients": "^2.3.0",
"tailwindcss-grid": "^1.2.0",
"tailwindcss-owl": "^1.1.1",
"tailwindcss-transforms": "^1.0.2",
"tailwindcss-owl": "^2.0.0",
"tailwindcss-transforms": "^2.2.0",
"tailwindcss-transition": "^1.0.5",
"tailwindcss-visuallyhidden": "^1.0.2"
},
Expand Down
2 changes: 1 addition & 1 deletion postcss.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ const tailwindcss = require('tailwindcss')
module.exports = () => ({
plugins: [
require('postcss-import'),
tailwindcss('./src/tailwind.js'),
require('postcss-simple-vars'),
tailwindcss('./src/tailwind.config.js'),
require('postcss-nested'),
require('autoprefixer'),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ export const WithChallengeReviewMetrics = function(WrappedComponent) {
}
}

const mapStateToProps = state => ({allReviewMetrics: _get(state, 'currentReviewTasks.metrics')})
const mapStateToProps = state => (
{reviewMetrics: _get(state, 'currentReviewTasks.metrics.reviewActions'),
reviewMetricsByPriority: _get(state, 'currentReviewTasks.metrics.priorityReviewActions')}
)

const mapDispatchToProps = (dispatch, ownProps) => ({
updateReviewMetrics: (userId, criteria) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ export const WithProjectReviewMetrics = function(WrappedComponent) {
}
}

const mapStateToProps = state => ({ reviewMetrics: _get(state, 'currentReviewTasks.metrics') })
const mapStateToProps = state => (
{reviewMetrics: _get(state, 'currentReviewTasks.metrics.reviewActions'),
reviewMetricsByPriority: _get(state, 'currentReviewTasks.metrics.priorityReviewActions')}
)

const mapDispatchToProps = (dispatch, ownProps) => ({
refreshReviewMetrics: (userId, challengeIds) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import React, { Component } from 'react'
import _cloneDeep from 'lodash/cloneDeep'
import _pullAt from 'lodash/pullAt'
import _get from 'lodash/get'
import _isEqual from 'lodash/isEqual'
import _each from 'lodash/each'
import _isEmpty from 'lodash/isEmpty'
import _fill from 'lodash/fill'
import _filter from 'lodash/filter'
import { PROPERTY_RULE_ERRORS } from '../../../TaskPropertyQueryBuilder/TaskPropertyRules'

export const EMPTY_STYLE_RULE = {styles:[{}]}

/**
* WithTaskPropertyStyleRules keeps track of taskPropertyStyleRules with methods
* to manipulate the object.
*
* @author [Kelli Rotstan](https://github.com/krotstan)
*/
export const WithTaskPropertyStyleRules = function(WrappedComponent) {
return class extends Component {
state = {
styleRules: [_cloneDeep(EMPTY_STYLE_RULE)], //Setup with one initial style rule
validationErrors:[[]], // And one empty errors.
}

removeStyleRule = (index) => {
const newRules = _cloneDeep(this.state.styleRules)
const newErrors = _cloneDeep(this.state.validationErrors)
_pullAt(newRules, index)
_pullAt(newErrors, index)
if (newRules.length < 1) {
newRules.push(_cloneDeep(EMPTY_STYLE_RULE))
newErrors.push([])
}
this.setState({styleRules: newRules, validationErrors: newErrors})
}

setStyleName = (name, index, position) => {
const newRules = _cloneDeep(this.state.styleRules)
const newErrors = _cloneDeep(this.state.validationErrors)
newRules[index].styles[position].styleName = name
newErrors[index] =
_filter(newErrors[index],
(e) => e !== PROPERTY_RULE_ERRORS.missingStyleValue)

this.setState({styleRules: newRules, validationErrors: newErrors})
}

setStyleValue = (value, index, position) => {
const newRules = _cloneDeep(this.state.styleRules)
const newErrors = _cloneDeep(this.state.validationErrors)
newRules[index].styles[position].styleValue = value
newErrors[index] =
_filter(newErrors[index],
(e) => e !== PROPERTY_RULE_ERRORS.missingStyleValue)

this.setState({styleRules: newRules, validationErrors: newErrors})
}

updateStyleRule = (data, index, errors) => {
const newRules = _cloneDeep(this.state.styleRules)
const newErrors = _cloneDeep(this.state.validationErrors)

newRules[index].propertySearch = data
newErrors[index] = errors || []
this.setState({styleRules: newRules, validationErrors: newErrors})
}

addNewStyleRule = () => {
const newRules = _cloneDeep(this.state.styleRules)
const newErrors = _cloneDeep(this.state.validationErrors)
newRules.push(_cloneDeep(EMPTY_STYLE_RULE))
newErrors.push([])
this.setState({styleRules: newRules, validationErrors: newErrors})
}

addNewStyle = (index) => {
const newRules = _cloneDeep(this.state.styleRules)
newRules[index].styles.push({})
this.setState({styleRules: newRules})
}

removeStyle = (index, position) => {
const newRules = _cloneDeep(this.state.styleRules)
_pullAt(newRules[index].styles, position)
if (newRules[index].styles.length < 1) {
newRules[index].styles.push({})
}
this.setState({styleRules: newRules})
}

clearStyleRules = () => {
this.setState({
styleRules: [_cloneDeep(EMPTY_STYLE_RULE)],
validationErrors:[[]]
})
}

componentDidMount() {
if (_get(this.props.challenge, 'taskStyles')) {
let taskStyles = _cloneDeep(this.props.challenge.taskStyles)
if (_isEmpty(taskStyles)) {
taskStyles.push(_cloneDeep(EMPTY_STYLE_RULE))
}

this.setState({styleRules: taskStyles,
validationErrors: _fill(Array(taskStyles.length), [])})
}
}

componentDidUpdate(prevProps) {
if (!_isEqual(_get(this.props.challenge, 'taskStyles'),
_get(prevProps.challenge, 'taskStyles'))) {
let taskStyles = _cloneDeep(this.props.challenge.taskStyles)
if (_isEmpty(taskStyles)) {
taskStyles.push(_cloneDeep(EMPTY_STYLE_RULE))
}
this.setState({styleRules: taskStyles,
validationErrors: _fill(Array(taskStyles.length), [])})
}
}

render() {
const errors = this.state.validationErrors
_each(this.state.styleRules, (rule, index) => {
_each(rule.styles, style => {
if (style.styleName && !style.styleValue) {
// Missing style value
errors[index].push(PROPERTY_RULE_ERRORS.missingStyleValue)
}
else if (style.styleValue && !style.styleName) {
// Missing syle name
errors[index].push(PROPERTY_RULE_ERRORS.missingStyleName)
}
})
})

let hasAnyStyleErrors = false
_each(errors, (e) => {
if (!_isEmpty(e)) {
hasAnyStyleErrors = true
}
})

return <WrappedComponent
{...this.props}
taskPropertyStyleRules={this.state.styleRules}
styleRuleErrors={errors}
hasAnyStyleRuleErrors = {hasAnyStyleErrors}
clearStyleRules={this.clearStyleRules}
removeStyleRule={this.removeStyleRule}
updateStyleRule={this.updateStyleRule}
addNewStyleRule={this.addNewStyleRule}
setStyleName={this.setStyleName}
setStyleValue={this.setStyleValue}
addNewStyle={this.addNewStyle}
removeStyle={this.removeStyle}
/>
}
}
}

export default WrappedComponent => WithTaskPropertyStyleRules(WrappedComponent)
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default class ChallengeCard extends Component {
/>

{_isFinite(_get(this.props.challenge, 'actions.total')) &&
<div className="mr-absolute mr-pin-b mr-pin-r mr-z-50 mr-text-grey-light mr-text-xxs">
<div className="mr-absolute mr-bottom-0 mr-right-0 mr-z-50 mr-text-grey-light mr-text-xxs">
{this.props.challenge.actions.total} <FormattedMessage {...messages.totalTasks} />
</div>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class ChallengeProgressBorder extends Component {
<div
key={status}
className={classNames(overrides.border ? overrides.border : "mr-border-grey-light",
"mr-absolute mr-pin-b mr-mb-n2px mr-border-b-2 mr-h-5px")}
"mr-absolute mr-bottom-0 mr-mb-n2px mr-border-b-2 mr-h-5px")}
style={{
left: `${cumulativeWidth}px`,
width: `${segmentWidth}px`,
Expand Down
4 changes: 2 additions & 2 deletions src/components/AdminPane/Manage/EditProject/EditProject.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ export class EditProject extends Component {

<div className="mr-max-w-2xl mr-mx-auto mr-bg-white mr-mt-8 mr-p-4 md:mr-p-8 mr-rounded">
<Form
schema={jsSchema(this.props.intl, this.props.project)}
uiSchema={uiSchema(this.props.intl, this.props.project)}
schema={jsSchema(this.props.intl, this.props.user, this.props.project)}
uiSchema={uiSchema(this.props.intl, this.props.user, this.props.project)}
widgets={{SelectWidget: CustomSelectWidget}}
className="form"
liveValidate
Expand Down
22 changes: 19 additions & 3 deletions src/components/AdminPane/Manage/EditProject/EditProjectSchema.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import React from 'react'
import AsManager from '../../../../interactions/User/AsManager'
import MarkdownContent from '../../../MarkdownContent/MarkdownContent'
import messages from './Messages'

/**
Expand All @@ -11,7 +14,7 @@ import messages from './Messages'
*
* @author [Neil Rotstan](https://github.com/nrotstan)
*/
export const jsSchema = (intl, project) => {
export const jsSchema = (intl, user, project) => {
const schemaFields = {
"$schema": "http://json-schema.org/draft-07/schema#",
type: "object",
Expand All @@ -34,6 +37,15 @@ export const jsSchema = (intl, project) => {
required: ["displayName"],
}

// Only show Featured option to superusers
if (AsManager(user).isSuperUser()) {
schemaFields.properties.featured = {
title: intl.formatMessage(messages.featuredLabel),
type: "boolean",
default: false,
}
}

// Show 'isVirtual' option only if this is a new project
if (!project) {
schemaFields.properties.isVirtual = {
Expand All @@ -56,8 +68,12 @@ export const jsSchema = (intl, project) => {
* > the form configuration will help the Bulma/RJSFFormFieldAdapter generate the
* > proper Bulma-compliant markup.
*/
export const uiSchema = (intl, project) => {
export const uiSchema = (intl, user, project) => {
const uiSchemaFields = {
featured: {
"ui:widget": "radio",
"ui:help": <MarkdownContent markdown={intl.formatMessage(messages.featuredDescription)} />,
},
displayName: {
"ui:help": intl.formatMessage(messages.displayNameDescription),
},
Expand All @@ -74,7 +90,7 @@ export const uiSchema = (intl, project) => {
"ui:help": intl.formatMessage(messages.descriptionDescription),
},
"ui:order": [
"displayName", "enabled", "description", "isVirtual"
"featured", "displayName", "enabled", "description", "isVirtual"
],
}

Expand Down
13 changes: 13 additions & 0 deletions src/components/AdminPane/Manage/EditProject/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,19 @@ export default defineMessages({
"Visible, you can see your Project as testing ground for Challenges.",
},

featuredLabel: {
id: 'Admin.EditProject.form.featured.label',
defaultMessage: "Featured",
},

featuredDescription: {
id: 'Admin.EditProject.form.featured.description',
defaultMessage: "Featured projects are shown on the home page and " +
"top of the Find Challenges page to bring attention to them. Note " +
"that featuring a project does **not** also feature its challenges. " +
"Only super-users may mark a project as featured.",
},

isVirtualLabel: {
id: 'Admin.EditProject.form.isVirtual.label',
defaultMessage: "Virtual",
Expand Down
Loading

0 comments on commit aa1d8d5

Please sign in to comment.