Commit d4ec773f authored by Shani's avatar Shani

Merge branch 'dev_BRCD-1682' into 'brcd-1674'

BRCD-1682: (FE) Enforce fields settings for "Play" specific products/plans/services

See merge request !946
parents 4c010648 4f511fab
......@@ -539,3 +539,10 @@ export const sortFieldOption = (optionsA, optionB) => {
export const onlyLineForeignFields = lineField => lineField.has('foreign');
export const foreignFieldWithoutDates = foreignField => foreignField.getIn(['foreign', 'translate', 'type'], '') !== 'unixTimeToString';
export const shouldUsePlays = availablePlays => (availablePlays.size > 1);
export const getPlayOptions = availablePlays => availablePlays.map(play => ({
value: play.get('name', ''),
label: play.get('label', play.get('name', '')),
})).toArray();
......@@ -13,6 +13,8 @@ import {
import {
getConfig,
parseConfigSelectOptions,
shouldUsePlays,
getPlayOptions,
} from '../../common/Util';
......@@ -129,11 +131,6 @@ class CustomField extends Component {
return customFieldsConfig.find(config => config.get('id', '') === fieldtype, null, Immutable.Map());
}
getPlayOptions = () => (this.props.availablePlays.map(play => ({
value: play.get('name', ''),
label: play.get('label', play.get('name', '')),
})).toArray());
inBlackList = (option, entity) => {
const blackList = option.get('exclude', Immutable.List());
if (blackList.isEmpty()) {
......@@ -212,7 +209,7 @@ class CustomField extends Component {
}
renderAdvancedEdit = () => {
const { field, entity, customFieldsConfig } = this.props;
const { field, entity, customFieldsConfig, availablePlays } = this.props;
const { showAdvancedEdit } = this.state;
const fieldType = this.getFieldType(field);
const fieldConfig = this.getFieldTypeConfig(fieldType);
......@@ -221,8 +218,8 @@ class CustomField extends Component {
const checkboxStyle = { marginTop: 10, paddingLeft: 26 };
const helpTextStyle = { color: '#626262', verticalAlign: 'text-top' };
const playsOptions = this.getPlayOptions();
const showPlays = ['subscriber'].includes(entity) && playsOptions.length > 1;
const playsOptions = getPlayOptions(availablePlays);
const showPlays = ['subscriber', 'product', 'service', 'plan'].includes(entity) && shouldUsePlays(availablePlays);
const plays = field.get('plays', []).join(',');
const disableUnique = !this.isAllowedForProperty('unique') || !this.isEditableProperty('unique');
......
......@@ -11,7 +11,7 @@ import Actions from '../Elements/Actions';
import Field from '../Field';
import { EntityRevisionDetails } from '../Entity';
import EntityFields from '../Entity/EntityFields';
import { getSettings } from '../../actions/settingsActions';
import PlaysSelector from '../Plays/PlaysSelector';
import {
getConfig,
getItemId,
......@@ -20,10 +20,6 @@ import {
buildPageTitle,
toImmutableList,
} from '../../common/Util';
import {
availablePlaysSettingsSelector,
} from '../../selectors/settingsSelector';
class Subscription extends Component {
......@@ -34,7 +30,6 @@ class Subscription extends Component {
settings: PropTypes.instanceOf(Immutable.List), // Subscriptions Fields
allPlans: PropTypes.instanceOf(Immutable.List),
allServices: PropTypes.instanceOf(Immutable.List),
availablePlays: PropTypes.instanceOf(Immutable.List),
mode: PropTypes.string,
onSave: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
......@@ -50,7 +45,6 @@ class Subscription extends Component {
settings: Immutable.List(),
allPlans: Immutable.List(),
allServices: Immutable.List(),
availablePlays: Immutable.List(),
}
constructor(props) {
......@@ -61,10 +55,6 @@ class Subscription extends Component {
};
}
componentWillMount() {
this.props.dispatch(getSettings(['plays']));
}
componentWillReceiveProps(nextProps) {
if (!Immutable.is(this.props.subscription, nextProps.subscription)) {
this.setState({ subscription: nextProps.subscription });
......@@ -251,20 +241,15 @@ class Subscription extends Component {
getAvailableServices = () => this.formatSelectOptions(this.props.allServices);
filterCustomFields = (field) => {
const { subscription } = this.state;
const hiddenFields = ['plan', 'services', 'play'];
const isCustomField = !hiddenFields.includes(field.get('field_name'));
const isEditable = field.get('editable', false);
const isMandatory = field.get('mandatory', false);
const shouldDisplayed = field.get('display', true);
const play = subscription.get('play', '');
const fieldPlays = field.get('plays', 'all');
const isFieldOfPlay = fieldPlays === 'all' || fieldPlays.contains(play);
return isCustomField &&
(isEditable || isMandatory) &&
shouldDisplayed &&
(!this.shouldUsePlays() || isFieldOfPlay);
shouldDisplayed;
// PHP .../application/views/internalpaypage/index.phtml condition
// if ((empty($c['display']) && empty($c['mandatory']))
// || $c['field_name'] === 'plan'
......@@ -272,36 +257,6 @@ class Subscription extends Component {
// ) continue;
}
shouldUsePlays = () => (this.props.availablePlays.size > 1);
getPlayOptions = () => (this.props.availablePlays.map(play => ({
value: play.get('name', ''),
label: play.get('label', play.get('name', '')),
})).toArray());
renderPlays = (editable) => {
if (!this.shouldUsePlays()) {
return null;
}
const { subscription } = this.state;
const play = subscription.get('play', '');
return (
<FormGroup key="play">
<Col componentClass={ControlLabel}sm={3} lg={2}>Play <span className="danger-red"> *</span></Col>
<Col sm={8} lg={9}>
{ editable
? <Select
options={this.getPlayOptions()}
value={play}
onChange={this.onChangePlay}
/>
: <Field value={play} editable={false} />
}
</Col>
</FormGroup>
);
}
renderSystemFields = (editable) => {
const { subscription } = this.state;
const plansOptions = this.getAvailablePlans().toJS();
......@@ -309,9 +264,12 @@ class Subscription extends Component {
const services = subscription.get('services', Immutable.List()) || Immutable.List();
const servicesList = Immutable.Set(services.map(service => service.get('name', ''))).join(',');
const plan = subscription.get('plan', '');
const plays = this.renderPlays(editable);
return ([
plays,
(<PlaysSelector
entity={subscription}
editable={editable}
onChange={this.onChangePlay}
/>),
(<FormGroup key="plan">
<Col componentClass={ControlLabel}sm={3} lg={2}>Plan <span className="danger-red"> *</span></Col>
<Col sm={8} lg={9}>
......@@ -459,7 +417,6 @@ const mapStateToProps = (state, props) => {
return ({
revisions,
mode,
availablePlays: availablePlaysSettingsSelector(state, props),
});
};
export default connect(mapStateToProps)(Subscription);
......@@ -6,7 +6,13 @@ import classNames from 'classnames';
import { titleCase } from 'change-case';
import EntityField from './EntityField';
import { getSettings } from '../../actions/settingsActions';
import { entityFieldSelector } from '../../selectors/settingsSelector';
import {
entityFieldSelector,
availablePlaysSettingsSelector,
} from '../../selectors/settingsSelector';
import {
shouldUsePlays,
} from '../../common/Util';
class EntityFields extends Component {
......@@ -23,6 +29,7 @@ class EntityFields extends Component {
editable: PropTypes.bool,
onChangeField: PropTypes.func,
dispatch: PropTypes.func.isRequired,
availablePlays: PropTypes.instanceOf(Immutable.List),
};
static defaultProps = {
......@@ -32,6 +39,7 @@ class EntityFields extends Component {
fieldsFilter: null,
editable: true,
onChangeField: () => {},
availablePlays: Immutable.List(),
}
componentDidMount() {
......@@ -74,6 +82,18 @@ class EntityFields extends Component {
return !(fieldPath[0] === 'params' && !entity.hasIn(fieldPath));
}
filterPlayFields = (field) => {
const { availablePlays, entity } = this.props;
if (!shouldUsePlays(availablePlays)) {
return false;
}
const play = entity.get('play', '');
const plays = Immutable.List(typeof play.split === 'function' ? play.split(',') : play);
const fieldPlays = field.get('plays', 'all');
const isFieldOfPlay = fieldPlays === 'all' || plays.some(p => fieldPlays.indexOf(p) > -1);
return isFieldOfPlay;
}
renderField = (field, key) => {
const { entity, editable, onChangeField } = this.props;
return (
......@@ -91,6 +111,7 @@ class EntityFields extends Component {
const { fields, fieldsFilter } = this.props;
const fieldFilterFunction = fieldsFilter !== null ? fieldsFilter : this.filterPrintableFields;
return fields
.filter(this.filterPlayFields)
.filter(fieldFilterFunction)
.filter(this.filterParamsFields)
.map(this.renderField);
......@@ -135,6 +156,7 @@ class EntityFields extends Component {
const mapStateToProps = (state, props) => ({
fields: entityFieldSelector(state, props),
availablePlays: availablePlaysSettingsSelector(state, props),
});
export default connect(mapStateToProps)(EntityFields);
......@@ -9,6 +9,7 @@ import Field from '../Field';
import CreateButton from '../Elements/CreateButton';
import PlanPrice from './components/PlanPrice';
import EntityFields from '../Entity/EntityFields';
import PlaysSelector from '../Plays/PlaysSelector';
import {
getFieldName,
getFieldNameType,
......@@ -75,6 +76,11 @@ export default class Plan extends Component {
this.props.onChangeFieldValue(['description'], value);
}
onChangePlays = (plays) => {
const playsToSave = plays === '' ? [] : plays.split(',');
this.props.onChangeFieldValue(['play'], playsToSave);
}
onChangePlanEach = (e) => {
let value = parseInt(e.target.value);
value = isNaN(value) ? '' : value;
......@@ -177,6 +183,13 @@ export default class Plan extends Component {
<Form horizontal>
<Panel>
<PlaysSelector
entity={plan}
editable={editable}
multi={true}
onChange={this.onChangePlays}
/>
<FormGroup>
<Col componentClass={ControlLabel} sm={3} lg={2}>
{ getFieldName('description', getFieldNameType('service'), sentenceCase('title'))}
......
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import Immutable from 'immutable';
import { FormGroup, ControlLabel, Col } from 'react-bootstrap';
import Select from 'react-select';
import Field from '../Field';
import { getSettings } from '../../actions/settingsActions';
import {
availablePlaysSettingsSelector,
} from '../../selectors/settingsSelector';
import {
shouldUsePlays,
getPlayOptions,
} from '../../common/Util';
class PlaysSelector extends Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
availablePlays: PropTypes.instanceOf(Immutable.List),
entity: PropTypes.instanceOf(Immutable.Map).isRequired,
editable: PropTypes.bool,
multi: PropTypes.bool,
onChange: PropTypes.func,
}
static defaultProps = {
availablePlays: Immutable.List(),
editable: true,
multi: false,
onChange: () => {},
}
componentWillMount() {
this.props.dispatch(getSettings(['plays']));
}
render() {
const { availablePlays, entity, editable, multi, onChange } = this.props;
if (!shouldUsePlays(availablePlays)) {
return null;
}
const play = entity.get('play', '');
const label = multi ? 'Play/s' : 'Play';
const playValue = typeof play.join === 'function' ? play.join(',') : play;
return (
<FormGroup key="play">
<Col componentClass={ControlLabel}sm={3} lg={2}>{label}</Col>
<Col sm={8} lg={9}>
{ editable
? <Select
options={getPlayOptions(availablePlays)}
value={playValue}
onChange={onChange}
multi={multi}
/>
: <Field value={playValue} editable={false} />
}
</Col>
</FormGroup>
);
}
}
const mapStateToProps = (state, props) => ({
availablePlays: availablePlaysSettingsSelector(state, props),
});
export default connect(mapStateToProps)(PlaysSelector);
......@@ -10,6 +10,7 @@ import { ProductDescription } from '../../FieldDescriptions';
import ProductPrice from './components/ProductPrice';
import EntityFields from '../Entity/EntityFields';
import UsageTypesSelector from '../UsageTypes/UsageTypesSelector';
import PlaysSelector from '../Plays/PlaysSelector';
import {
getUnitLabel,
getFieldName,
......@@ -80,6 +81,10 @@ class Product extends Component {
this.props.onFieldUpdate(['key'], value);
}
onChangePlay = (play) => {
this.props.onFieldUpdate(['play'], play);
}
onChangeDescription = (e) => {
const { value } = e.target;
this.props.onFieldUpdate(['description'], value);
......@@ -229,6 +234,12 @@ class Product extends Component {
<Form horizontal>
<Panel>
<PlaysSelector
entity={product}
editable={editable}
onChange={this.onChangePlay}
/>
<FormGroup>
<Col componentClass={ControlLabel} sm={3} lg={2}>
{ getFieldName('description', getFieldNameType('service'), sentenceCase('title'))}
......
......@@ -7,6 +7,7 @@ import { ServiceDescription } from '../../FieldDescriptions';
import Help from '../Help';
import Field from '../Field';
import EntityFields from '../Entity/EntityFields';
import PlaysSelector from '../Plays/PlaysSelector';
import {
getFieldName,
getFieldNameType,
......@@ -70,6 +71,11 @@ export default class ServiceDetails extends Component {
this.props.updateItem(['quantitative'], value);
}
onChangePlays = (plays) => {
const playsToSave = plays === '' ? [] : plays.split(',');
this.props.updateItem(['play'], playsToSave);
}
onChangeDescription = (e) => {
const { value } = e.target;
this.props.updateItem(['description'], value);
......@@ -105,6 +111,13 @@ export default class ServiceDetails extends Component {
return (
<Form horizontal>
<PlaysSelector
entity={item}
editable={editable}
multi={true}
onChange={this.onChangePlays}
/>
<FormGroup>
<Col componentClass={ControlLabel} sm={3} lg={2}>
{ getFieldName('description', getFieldNameType('service'), sentenceCase('title'))}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment