mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2025-02-17 00:21:20 -05:00
Merge pull request #3753 from LLK/hotfix/multi-step-report
[Hotfix/Develop] Split project report flow into two steps
This commit is contained in:
commit
c23805f543
5 changed files with 292 additions and 189 deletions
|
@ -84,6 +84,12 @@ row to appear to contain overflow. */
|
||||||
margin-bottom: .9375rem;
|
margin-bottom: .9375rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For action button row where left/right margin is handled by parent element */
|
||||||
|
.action-buttons.action-buttons-no-inset {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.action-button {
|
.action-button {
|
||||||
margin: 0 0 0 .54625rem;
|
margin: 0 0 0 .54625rem;
|
||||||
border-radius: .25rem;
|
border-radius: .25rem;
|
||||||
|
|
89
src/components/modal/report/form-step.jsx
Normal file
89
src/components/modal/report/form-step.jsx
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
const bindAll = require('lodash.bindall');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
const React = require('react');
|
||||||
|
const FormattedMessage = require('react-intl').FormattedMessage;
|
||||||
|
const classNames = require('classnames');
|
||||||
|
|
||||||
|
const Form = require('../../forms/form.jsx');
|
||||||
|
const Button = require('../../forms/button.jsx');
|
||||||
|
const Spinner = require('../../spinner/spinner.jsx');
|
||||||
|
const FlexRow = require('../../flex-row/flex-row.jsx');
|
||||||
|
require('../../forms/button.scss');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step to be used in a form progression. Provides wrapping form element,
|
||||||
|
* renders children input elements, then provides a next button row
|
||||||
|
* that responds to form validation and submission spinner.
|
||||||
|
*/
|
||||||
|
class FormStep extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
valid: false
|
||||||
|
};
|
||||||
|
bindAll(this, [
|
||||||
|
'handleValid',
|
||||||
|
'handleInvalid'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
handleValid () {
|
||||||
|
this.setState({valid: true});
|
||||||
|
}
|
||||||
|
handleInvalid () {
|
||||||
|
this.setState({valid: false});
|
||||||
|
}
|
||||||
|
render () {
|
||||||
|
const {onNext, children, isWaiting, nextLabel} = this.props;
|
||||||
|
// Submit button is enabled if form isn't already submitting, and either the form passes validation,
|
||||||
|
// or the submitEnabled prop is true. This lets submitEnabled prop override validation.
|
||||||
|
const submitEnabled = (this.props.submitEnabled || this.state.valid) && !isWaiting;
|
||||||
|
const submitDisabledParam = submitEnabled ? {} : {disabled: 'disabled'};
|
||||||
|
return (
|
||||||
|
<Form
|
||||||
|
onInvalid={this.handleInvalid}
|
||||||
|
onValid={this.handleValid}
|
||||||
|
onValidSubmit={onNext}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<FlexRow className={classNames('action-buttons', 'action-buttons-no-inset')}>
|
||||||
|
<Button
|
||||||
|
className={classNames(
|
||||||
|
'action-button',
|
||||||
|
'submit-button',
|
||||||
|
{disabled: !submitEnabled}
|
||||||
|
)}
|
||||||
|
{...submitDisabledParam}
|
||||||
|
key="submitButton"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
{isWaiting ? (
|
||||||
|
<div className="action-button-text">
|
||||||
|
<Spinner />
|
||||||
|
<FormattedMessage id="report.sending" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="action-button-text">
|
||||||
|
<FormattedMessage {...nextLabel} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</FlexRow>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FormStep.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
isWaiting: PropTypes.bool,
|
||||||
|
nextLabel: PropTypes.shape({id: PropTypes.string.isRequired}).isRequired,
|
||||||
|
onNext: PropTypes.func.isRequired,
|
||||||
|
submitEnabled: PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
|
FormStep.defaultProps = {
|
||||||
|
isWaiting: false,
|
||||||
|
submitEnabled: false
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = FormStep;
|
|
@ -6,95 +6,50 @@ const FormattedMessage = require('react-intl').FormattedMessage;
|
||||||
const injectIntl = require('react-intl').injectIntl;
|
const injectIntl = require('react-intl').injectIntl;
|
||||||
const intlShape = require('react-intl').intlShape;
|
const intlShape = require('react-intl').intlShape;
|
||||||
const Modal = require('../base/modal.jsx');
|
const Modal = require('../base/modal.jsx');
|
||||||
const classNames = require('classnames');
|
|
||||||
|
|
||||||
const ModalTitle = require('../base/modal-title.jsx');
|
const ModalTitle = require('../base/modal-title.jsx');
|
||||||
const ModalInnerContent = require('../base/modal-inner-content.jsx');
|
const ModalInnerContent = require('../base/modal-inner-content.jsx');
|
||||||
const Form = require('../../forms/form.jsx');
|
|
||||||
const Button = require('../../forms/button.jsx');
|
|
||||||
const Select = require('../../forms/select.jsx');
|
const Select = require('../../forms/select.jsx');
|
||||||
const Spinner = require('../../spinner/spinner.jsx');
|
|
||||||
const TextArea = require('../../forms/textarea.jsx');
|
const TextArea = require('../../forms/textarea.jsx');
|
||||||
const FlexRow = require('../../flex-row/flex-row.jsx');
|
|
||||||
const previewActions = require('../../../redux/preview.js');
|
const previewActions = require('../../../redux/preview.js');
|
||||||
|
const Progression = require('../../progression/progression.jsx');
|
||||||
|
const FormStep = require('./form-step.jsx');
|
||||||
|
const {reportOptionsShape, REPORT_OPTIONS} = require('./report-options.js');
|
||||||
|
|
||||||
require('../../forms/button.scss');
|
require('../../forms/button.scss');
|
||||||
require('./modal.scss');
|
require('./modal.scss');
|
||||||
|
|
||||||
const REPORT_OPTIONS = [
|
// The Progression component uses numbers to track which step it's on, but that's
|
||||||
{
|
// hard to read. Make the code easier to read by giving each step number a label.
|
||||||
value: '',
|
const STEPS = {
|
||||||
label: {id: 'report.reasonPlaceHolder'},
|
category: 0,
|
||||||
prompt: {id: 'report.promptPlaceholder'}
|
textInput: 1,
|
||||||
},
|
confirmation: 2
|
||||||
{
|
};
|
||||||
value: '0',
|
|
||||||
label: {id: 'report.reasonCopy'},
|
|
||||||
prompt: {id: 'report.promptCopy'}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: '1',
|
|
||||||
label: {id: 'report.reasonUncredited'},
|
|
||||||
prompt: {id: 'report.promptUncredited'}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: '2',
|
|
||||||
label: {id: 'report.reasonScary'},
|
|
||||||
prompt: {id: 'report.promptScary'}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: '3',
|
|
||||||
label: {id: 'report.reasonLanguage'},
|
|
||||||
prompt: {id: 'report.promptLanguage'}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: '4',
|
|
||||||
label: {id: 'report.reasonMusic'},
|
|
||||||
prompt: {id: 'report.promptMusic'}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: '8',
|
|
||||||
label: {id: 'report.reasonImage'},
|
|
||||||
prompt: {id: 'report.promptImage'}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: '5',
|
|
||||||
label: {id: 'report.reasonPersonal'},
|
|
||||||
prompt: {id: 'report.promptPersonal'}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: '6',
|
|
||||||
label: {id: 'general.other'},
|
|
||||||
prompt: {id: 'report.promptGuidelines'}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
class ReportModal extends React.Component {
|
class ReportModal extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
bindAll(this, [
|
bindAll(this, [
|
||||||
'handleCategorySelect',
|
'handleSetCategory',
|
||||||
'handleValid',
|
'handleSubmit'
|
||||||
'handleInvalid'
|
|
||||||
]);
|
]);
|
||||||
this.state = {
|
this.state = {
|
||||||
category: '',
|
step: STEPS.category,
|
||||||
notes: '',
|
categoryValue: ''
|
||||||
valid: false
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
handleCategorySelect (name, value) {
|
handleSetCategory (formData) {
|
||||||
this.setState({category: value});
|
return this.setState({
|
||||||
|
categoryValue: formData.category,
|
||||||
|
step: STEPS.textInput
|
||||||
|
});
|
||||||
}
|
}
|
||||||
handleValid () {
|
handleSubmit (formData) {
|
||||||
this.setState({valid: true});
|
this.props.onReport({
|
||||||
}
|
report_category: this.state.categoryValue,
|
||||||
handleInvalid () {
|
notes: formData.notes
|
||||||
this.setState({valid: false});
|
});
|
||||||
}
|
|
||||||
lookupPrompt (value) {
|
|
||||||
const prompt = REPORT_OPTIONS.find(item => item.value === value).prompt;
|
|
||||||
return this.props.intl.formatMessage(prompt);
|
|
||||||
}
|
}
|
||||||
render () {
|
render () {
|
||||||
const {
|
const {
|
||||||
|
@ -103,14 +58,19 @@ class ReportModal extends React.Component {
|
||||||
isError,
|
isError,
|
||||||
isOpen,
|
isOpen,
|
||||||
isWaiting,
|
isWaiting,
|
||||||
onReport, // eslint-disable-line no-unused-vars
|
|
||||||
onRequestClose,
|
onRequestClose,
|
||||||
type,
|
type,
|
||||||
|
reportOptions,
|
||||||
...modalProps
|
...modalProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const submitEnabled = this.state.valid && !isWaiting;
|
|
||||||
const submitDisabledParam = submitEnabled ? {} : {disabled: 'disabled'};
|
|
||||||
const contentLabel = intl.formatMessage({id: `report.${type}`});
|
const contentLabel = intl.formatMessage({id: `report.${type}`});
|
||||||
|
const categoryRequiredMessage = intl.formatMessage({id: 'report.reasonMissing'});
|
||||||
|
const category = reportOptions.find(o => o.value === this.state.categoryValue) || reportOptions[0];
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
const step = isConfirmed ? STEPS.confirmation : this.state.step;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
useStandardSizes
|
useStandardSizes
|
||||||
|
@ -124,120 +84,93 @@ class ReportModal extends React.Component {
|
||||||
<div className="report-modal-header modal-header">
|
<div className="report-modal-header modal-header">
|
||||||
<ModalTitle title={contentLabel} />
|
<ModalTitle title={contentLabel} />
|
||||||
</div>
|
</div>
|
||||||
|
<ModalInnerContent className="report-modal-content">
|
||||||
|
{isError && (
|
||||||
|
<div className="error-text">
|
||||||
|
<FormattedMessage id="report.error" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<Progression step={step}>
|
||||||
|
{/* Category selection step */}
|
||||||
|
<FormStep
|
||||||
|
nextLabel={{id: 'general.next'}}
|
||||||
|
onNext={this.handleSetCategory}
|
||||||
|
>
|
||||||
|
<div className="instructions">
|
||||||
|
<FormattedMessage
|
||||||
|
id={`report.${type}Instructions`}
|
||||||
|
key={`report.${type}Instructions`}
|
||||||
|
values={{
|
||||||
|
CommunityGuidelinesLink: (
|
||||||
|
<a href="/community_guidelines">
|
||||||
|
<FormattedMessage id="report.CommunityGuidelinesLinkText" />
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Select
|
||||||
|
required
|
||||||
|
elementWrapperClassName="report-modal-field"
|
||||||
|
label={null}
|
||||||
|
name="category"
|
||||||
|
options={reportOptions.map(option => ({
|
||||||
|
value: option.value,
|
||||||
|
label: intl.formatMessage(option.label),
|
||||||
|
key: option.value
|
||||||
|
}))}
|
||||||
|
validationErrors={{
|
||||||
|
isDefaultRequiredValue: categoryRequiredMessage
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormStep>
|
||||||
|
|
||||||
<Form
|
{/* Text input step */}
|
||||||
className="report"
|
<FormStep
|
||||||
onInvalid={this.handleInvalid}
|
isWaiting={isWaiting}
|
||||||
onValid={this.handleValid}
|
nextLabel={{id: 'report.send'}}
|
||||||
onValidSubmit={onReport}
|
onNext={this.handleSubmit}
|
||||||
>
|
>
|
||||||
<ModalInnerContent className="report-modal-content">
|
<div className="instructions">
|
||||||
{isConfirmed ? (
|
<div className="instructions-header">
|
||||||
<div className="received">
|
<FormattedMessage {...category.label} />
|
||||||
<div className="received-header">
|
</div>
|
||||||
|
<FormattedMessage {...category.prompt} />
|
||||||
|
</div>
|
||||||
|
<TextArea
|
||||||
|
autoFocus
|
||||||
|
required
|
||||||
|
className="report-text"
|
||||||
|
elementWrapperClassName="report-modal-field"
|
||||||
|
label={null}
|
||||||
|
name="notes"
|
||||||
|
validationErrors={{
|
||||||
|
isDefaultRequiredValue: intl.formatMessage({id: 'report.textMissing'}),
|
||||||
|
maxLength: intl.formatMessage({id: 'report.tooLongError'}),
|
||||||
|
minLength: intl.formatMessage({id: 'report.tooShortError'})
|
||||||
|
}}
|
||||||
|
validations={{
|
||||||
|
maxLength: 500,
|
||||||
|
minLength: 20
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormStep>
|
||||||
|
|
||||||
|
{/* Confirmation step */}
|
||||||
|
<FormStep
|
||||||
|
submitEnabled
|
||||||
|
nextLabel={{id: 'general.close'}}
|
||||||
|
onNext={onRequestClose}
|
||||||
|
>
|
||||||
|
<div className="instructions">
|
||||||
|
<div className="instructions-header">
|
||||||
<FormattedMessage id="report.receivedHeader" />
|
<FormattedMessage id="report.receivedHeader" />
|
||||||
</div>
|
</div>
|
||||||
<FormattedMessage id="report.receivedBody" />
|
<FormattedMessage id="report.receivedBody" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
</FormStep>
|
||||||
<div>
|
</Progression>
|
||||||
<div className="instructions">
|
</ModalInnerContent>
|
||||||
<FormattedMessage
|
|
||||||
id={`report.${type}Instructions`}
|
|
||||||
key={`report.${type}Instructions`}
|
|
||||||
values={{
|
|
||||||
CommunityGuidelinesLink: (
|
|
||||||
<a href="/community_guidelines">
|
|
||||||
<FormattedMessage id="report.CommunityGuidelinesLinkText" />
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Select
|
|
||||||
required
|
|
||||||
elementWrapperClassName="report-modal-field"
|
|
||||||
label={null}
|
|
||||||
name="report_category"
|
|
||||||
options={REPORT_OPTIONS.map(option => ({
|
|
||||||
value: option.value,
|
|
||||||
label: this.props.intl.formatMessage(option.label),
|
|
||||||
key: option.value
|
|
||||||
}))}
|
|
||||||
validationErrors={{
|
|
||||||
isDefaultRequiredValue: this.props.intl.formatMessage({
|
|
||||||
id: 'report.reasonMissing'
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
value={this.state.category}
|
|
||||||
onChange={this.handleCategorySelect}
|
|
||||||
/>
|
|
||||||
<TextArea
|
|
||||||
required
|
|
||||||
className="report-text"
|
|
||||||
elementWrapperClassName="report-modal-field"
|
|
||||||
label={null}
|
|
||||||
name="notes"
|
|
||||||
placeholder={this.lookupPrompt(this.state.category)}
|
|
||||||
validationErrors={{
|
|
||||||
isDefaultRequiredValue: this.props.intl.formatMessage({
|
|
||||||
id: 'report.textMissing'
|
|
||||||
}),
|
|
||||||
maxLength: this.props.intl.formatMessage({id: 'report.tooLongError'}),
|
|
||||||
minLength: this.props.intl.formatMessage({id: 'report.tooShortError'})
|
|
||||||
}}
|
|
||||||
validations={{
|
|
||||||
maxLength: 500,
|
|
||||||
minLength: 20
|
|
||||||
}}
|
|
||||||
value={this.state.notes}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{isError && (
|
|
||||||
<div className="error-text">
|
|
||||||
<FormattedMessage id="report.error" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</ModalInnerContent>
|
|
||||||
<FlexRow className="action-buttons">
|
|
||||||
<div className="action-buttons-overflow-fix">
|
|
||||||
{isConfirmed ? (
|
|
||||||
<Button
|
|
||||||
className="action-button submit-button"
|
|
||||||
type="button"
|
|
||||||
onClick={onRequestClose}
|
|
||||||
>
|
|
||||||
<div className="action-button-text">
|
|
||||||
<FormattedMessage id="general.close" />
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button
|
|
||||||
className={classNames(
|
|
||||||
'action-button',
|
|
||||||
'submit-button',
|
|
||||||
{disabled: !submitEnabled}
|
|
||||||
)}
|
|
||||||
{...submitDisabledParam}
|
|
||||||
key="submitButton"
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
{isWaiting ? (
|
|
||||||
<div className="action-button-text">
|
|
||||||
<Spinner />
|
|
||||||
<FormattedMessage id="report.sending" />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="action-button-text">
|
|
||||||
<FormattedMessage id="report.send" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</FlexRow>
|
|
||||||
</Form>
|
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
@ -252,9 +185,14 @@ ReportModal.propTypes = {
|
||||||
isWaiting: PropTypes.bool,
|
isWaiting: PropTypes.bool,
|
||||||
onReport: PropTypes.func,
|
onReport: PropTypes.func,
|
||||||
onRequestClose: PropTypes.func,
|
onRequestClose: PropTypes.func,
|
||||||
|
reportOptions: reportOptionsShape,
|
||||||
type: PropTypes.string
|
type: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ReportModal.defaultProps = {
|
||||||
|
reportOptions: REPORT_OPTIONS
|
||||||
|
};
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
isConfirmed: state.preview.status.report === previewActions.Status.FETCHED,
|
isConfirmed: state.preview.status.report === previewActions.Status.FETCHED,
|
||||||
isError: state.preview.status.report === previewActions.Status.ERROR,
|
isError: state.preview.status.report === previewActions.Status.ERROR,
|
||||||
|
|
|
@ -13,15 +13,8 @@
|
||||||
|
|
||||||
.instructions {
|
.instructions {
|
||||||
line-height: 1.5rem;
|
line-height: 1.5rem;
|
||||||
}
|
|
||||||
|
|
||||||
.received {
|
.instructions-header {
|
||||||
margin: 0 auto;
|
|
||||||
width: 90%;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 1.65rem;
|
|
||||||
|
|
||||||
.received-header {
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
77
src/components/modal/report/report-options.js
Normal file
77
src/components/modal/report/report-options.js
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
|
||||||
|
const {
|
||||||
|
arrayOf,
|
||||||
|
string,
|
||||||
|
shape
|
||||||
|
} = PropTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define both the PropType shape and default value for report options
|
||||||
|
* to ensure structure is validated by PropType checking going forward.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const messageShape = shape({
|
||||||
|
id: string.isRequired
|
||||||
|
});
|
||||||
|
|
||||||
|
const categoryShape = shape({
|
||||||
|
value: string.isRequired,
|
||||||
|
label: messageShape.isRequired,
|
||||||
|
prompt: messageShape.isRequired
|
||||||
|
});
|
||||||
|
|
||||||
|
const reportOptionsShape = arrayOf(categoryShape);
|
||||||
|
|
||||||
|
const REPORT_OPTIONS = [
|
||||||
|
{
|
||||||
|
value: '',
|
||||||
|
label: {id: 'report.reasonPlaceHolder'},
|
||||||
|
prompt: {id: 'report.promptPlaceholder'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '0',
|
||||||
|
label: {id: 'report.reasonCopy'},
|
||||||
|
prompt: {id: 'report.promptCopy'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '1',
|
||||||
|
label: {id: 'report.reasonUncredited'},
|
||||||
|
prompt: {id: 'report.promptUncredited'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '2',
|
||||||
|
label: {id: 'report.reasonScary'},
|
||||||
|
prompt: {id: 'report.promptScary'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '3',
|
||||||
|
label: {id: 'report.reasonLanguage'},
|
||||||
|
prompt: {id: 'report.promptLanguage'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '4',
|
||||||
|
label: {id: 'report.reasonMusic'},
|
||||||
|
prompt: {id: 'report.promptMusic'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '8',
|
||||||
|
label: {id: 'report.reasonImage'},
|
||||||
|
prompt: {id: 'report.promptImage'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '5',
|
||||||
|
label: {id: 'report.reasonPersonal'},
|
||||||
|
prompt: {id: 'report.promptPersonal'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '6',
|
||||||
|
label: {id: 'general.other'},
|
||||||
|
prompt: {id: 'report.promptGuidelines'}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
reportOptionsShape,
|
||||||
|
REPORT_OPTIONS
|
||||||
|
};
|
Loading…
Reference in a new issue