mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-22 23:27:54 -05:00
Add subcategory selection if subcategories specified, and submit final report
This commit is contained in:
parent
aa31c2ed57
commit
af78e4c05e
2 changed files with 81 additions and 10 deletions
|
@ -23,8 +23,9 @@ require('./modal.scss');
|
||||||
// hard to read. Make the code easier to read by giving each step number a label.
|
// hard to read. Make the code easier to read by giving each step number a label.
|
||||||
const STEPS = {
|
const STEPS = {
|
||||||
category: 0,
|
category: 0,
|
||||||
textInput: 1,
|
subcategory: 1,
|
||||||
confirmation: 2
|
textInput: 2,
|
||||||
|
confirmation: 3
|
||||||
};
|
};
|
||||||
|
|
||||||
class ReportModal extends React.Component {
|
class ReportModal extends React.Component {
|
||||||
|
@ -32,22 +33,32 @@ class ReportModal extends React.Component {
|
||||||
super(props);
|
super(props);
|
||||||
bindAll(this, [
|
bindAll(this, [
|
||||||
'handleSetCategory',
|
'handleSetCategory',
|
||||||
'handleSubmit'
|
'handleSubmit',
|
||||||
|
'handleSetSubcategory'
|
||||||
]);
|
]);
|
||||||
this.state = {
|
this.state = {
|
||||||
step: STEPS.category,
|
step: STEPS.category,
|
||||||
categoryValue: ''
|
categoryValue: '',
|
||||||
|
subcategoryValue: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
handleSetCategory (formData) {
|
handleSetCategory (formData) {
|
||||||
|
const category = this.props.reportOptions.find(o => o.value === formData.category) || this.props.reportOptions[0];
|
||||||
|
|
||||||
return this.setState({
|
return this.setState({
|
||||||
categoryValue: formData.category,
|
categoryValue: formData.category,
|
||||||
|
step: category.subcategories ? STEPS.subcategory : STEPS.textInput
|
||||||
|
});
|
||||||
|
}
|
||||||
|
handleSetSubcategory (formData) {
|
||||||
|
return this.setState({
|
||||||
|
subcategoryValue: formData.subcategory,
|
||||||
step: STEPS.textInput
|
step: STEPS.textInput
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
handleSubmit (formData) {
|
handleSubmit (formData) {
|
||||||
this.props.onReport({
|
this.props.onReport({
|
||||||
report_category: this.state.categoryValue,
|
report_category: this.state.subcategoryValue ? this.state.subcategoryValue : this.state.categoryValue,
|
||||||
notes: formData.notes
|
notes: formData.notes
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -66,6 +77,12 @@ class ReportModal extends React.Component {
|
||||||
const contentLabel = intl.formatMessage({id: `report.${type}`});
|
const contentLabel = intl.formatMessage({id: `report.${type}`});
|
||||||
const categoryRequiredMessage = intl.formatMessage({id: 'report.reasonMissing'});
|
const categoryRequiredMessage = intl.formatMessage({id: 'report.reasonMissing'});
|
||||||
const category = reportOptions.find(o => o.value === this.state.categoryValue) || reportOptions[0];
|
const category = reportOptions.find(o => o.value === this.state.categoryValue) || reportOptions[0];
|
||||||
|
let finalCategory = category;
|
||||||
|
|
||||||
|
if (category.subcategories) {
|
||||||
|
finalCategory = category.subcategories.find(o => o.value === this.state.subcategoryValue) || category.subcategories[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Confirmation step is shown if a report has been submitted, even if state is reset by closing the modal.
|
// Confirmation step is shown if a report has been submitted, even if state is reset by closing the modal.
|
||||||
// This prevents multiple report submission within the same session because submission is stored in redux.
|
// This prevents multiple report submission within the same session because submission is stored in redux.
|
||||||
|
@ -125,6 +142,33 @@ class ReportModal extends React.Component {
|
||||||
/>
|
/>
|
||||||
</FormStep>
|
</FormStep>
|
||||||
|
|
||||||
|
{/* Subcategory selection step */}
|
||||||
|
<FormStep
|
||||||
|
nextLabel={{id: 'general.next'}}
|
||||||
|
onNext={this.handleSetSubcategory}
|
||||||
|
>
|
||||||
|
<div className="instructions">
|
||||||
|
<div className="instructions-header">
|
||||||
|
<FormattedMessage {...category.label} />
|
||||||
|
</div>
|
||||||
|
<FormattedMessage {...category.prompt} />
|
||||||
|
</div>
|
||||||
|
<Select
|
||||||
|
required
|
||||||
|
elementWrapperClassName="report-modal-field"
|
||||||
|
label={null}
|
||||||
|
name="subcategory"
|
||||||
|
options={category.subcategories ? category.subcategories.map(option => ({
|
||||||
|
value: option.value,
|
||||||
|
label: intl.formatMessage(option.label),
|
||||||
|
key: option.value
|
||||||
|
})) : []}
|
||||||
|
validationErrors={{
|
||||||
|
isDefaultRequiredValue: categoryRequiredMessage
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormStep>
|
||||||
|
|
||||||
{/* Text input step */}
|
{/* Text input step */}
|
||||||
<FormStep
|
<FormStep
|
||||||
isWaiting={isWaiting}
|
isWaiting={isWaiting}
|
||||||
|
@ -133,9 +177,9 @@ class ReportModal extends React.Component {
|
||||||
>
|
>
|
||||||
<div className="instructions">
|
<div className="instructions">
|
||||||
<div className="instructions-header">
|
<div className="instructions-header">
|
||||||
<FormattedMessage {...category.label} />
|
<FormattedMessage {...subcategory.label} />
|
||||||
</div>
|
</div>
|
||||||
<FormattedMessage {...category.prompt} />
|
<FormattedMessage {...subcategory.prompt} />
|
||||||
</div>
|
</div>
|
||||||
<TextArea
|
<TextArea
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|
|
@ -3,7 +3,8 @@ const PropTypes = require('prop-types');
|
||||||
const {
|
const {
|
||||||
arrayOf,
|
arrayOf,
|
||||||
string,
|
string,
|
||||||
shape
|
shape,
|
||||||
|
bool
|
||||||
} = PropTypes;
|
} = PropTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,10 +16,18 @@ const messageShape = shape({
|
||||||
id: string.isRequired
|
id: string.isRequired
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const subcategoryShape = shape({
|
||||||
|
value: string.isRequired,
|
||||||
|
label: messageShape.isRequired,
|
||||||
|
prompt: messageShape.isRequired,
|
||||||
|
preventSubmission: bool
|
||||||
|
});
|
||||||
|
|
||||||
const categoryShape = shape({
|
const categoryShape = shape({
|
||||||
value: string.isRequired,
|
value: string.isRequired,
|
||||||
label: messageShape.isRequired,
|
label: messageShape.isRequired,
|
||||||
prompt: messageShape.isRequired
|
prompt: messageShape.isRequired,
|
||||||
|
subcategories: arrayOf(subcategoryShape)
|
||||||
});
|
});
|
||||||
|
|
||||||
const reportOptionsShape = arrayOf(categoryShape);
|
const reportOptionsShape = arrayOf(categoryShape);
|
||||||
|
@ -67,7 +76,25 @@ const REPORT_OPTIONS = [
|
||||||
{
|
{
|
||||||
value: '6',
|
value: '6',
|
||||||
label: {id: 'general.other'},
|
label: {id: 'general.other'},
|
||||||
prompt: {id: 'report.promptGuidelines'}
|
prompt: {id: 'report.promptGuidelines'},
|
||||||
|
subcategories: [
|
||||||
|
{
|
||||||
|
value: '',
|
||||||
|
label: {id: 'report.reasonPlaceHolder'},
|
||||||
|
prompt: {id: 'report.promptPlaceholder'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '11',
|
||||||
|
label: {id: 'report.reasonCopy'},
|
||||||
|
prompt: {id: 'report.promptCopy'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '12',
|
||||||
|
label: {id: 'report.reasonPersonal'},
|
||||||
|
prompt: {id: 'report.promptPersonal'},
|
||||||
|
preventSubmission: true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue