Commit 9474eaf8 authored by Shani's avatar Shani

Merge branch 'BRCD-1676' into 'brcd-1674'

BRCD-1676 Play Field support in for Settings custom fields, Plan/Service/product/subscribers, Report, Input Processor

See merge request !950
parents d4ec773f 7d865d53
......@@ -25,9 +25,9 @@ var globalSetting = {
serviceCycleUnlimitedValue: 'UNLIMITED',
productUnlimitedValue: 'UNLIMITED',
keyUppercaseRegex: /^[A-Z0-9_]+$/,
keyUppercaseCleanRegex: /[^A-Z|0-9_']/g,
keyUppercaseCleanRegex: /[^A-Z|0-9_]/g,
keyRegex: /^[A-Za-z0-9_]*$/,
keyCleanRegex: /[^a-z|A-Z|0-9_']/g,
keyCleanRegex: /[^a-z|A-Z|0-9_]/g,
defaultLogo: 'billRun-cloud-logo.png',
billrunCloudLogo: 'billRun-cloud-logo.png',
billrunLogo: 'billRun-logo.png',
......
......@@ -21,9 +21,9 @@ var globalSetting = {
serviceCycleUnlimitedValue: 'UNLIMITED',
productUnlimitedValue: 'UNLIMITED',
keyUppercaseRegex: /^[A-Z0-9_]+$/,
keyUppercaseCleanRegex: /[^A-Z|0-9_']/g,
keyUppercaseCleanRegex: /[^A-Z|0-9_]/g,
keyRegex: /^[A-Za-z0-9_]*$/,
keyCleanRegex: /[^a-z|A-Z|0-9_']/g,
keyCleanRegex: /[^a-z|A-Z|0-9_]/g,
defaultLogo: 'billRun-cloud-logo.png',
billrunCloudLogo: 'billRun-cloud-logo.png',
billrunLogo: 'billRun-logo.png',
......
......@@ -418,6 +418,9 @@ fieldset[disabled] .btn {
.List.invoices-list form {
margin-bottom: 0;
}
.List .table td {
vertical-align: middle;
}
/* Global page + table */
.page-header {
border-bottom: none;
......
......@@ -11,6 +11,7 @@ export const CONFIRM_HIDE = 'CONFIRM_HIDE';
export const EDIT_FORM_SHOW = 'EDIT_FORM_SHOW';
export const EDIT_FORM_HIDE = 'EDIT_FORM_HIDE';
export const EDIT_FORM_SET_ITEM = 'EDIT_FORM_SET_ITEM';
export const EDIT_FORM_SET_ERROR = 'EDIT_FORM_SET_ERROR';
export const EDIT_FORM_UPDATE_ITEM_FIELD = 'EDIT_FORM_UPDATE_ITEM_FIELD';
export const EDIT_FORM_DELETE_ITEM_FIELD = 'EDIT_FORM_DELETE_ITEM_FIELD';
......@@ -102,11 +103,18 @@ export const setFormModalItem = item => ({
item,
});
export const setFormModalError = (fieldId, message = null) => ({
type: EDIT_FORM_SET_ERROR,
fieldId,
message,
});
export const updateFormModalItemField = (path, value) => ({
type: EDIT_FORM_UPDATE_ITEM_FIELD,
path,
value,
});
export const removeFormModalItemField = path => ({
type: EDIT_FORM_DELETE_ITEM_FIELD,
path,
......
......@@ -119,6 +119,8 @@ export const getFileTypesOptions = () => dispatch => dispatch(getSettings('file_
export const getEventCodeOptions = () => dispatch => dispatch(getSettings('events'));
export const getPlayTypeOptions = () => dispatch => dispatch(getSettings('plays'));
export const getGroupsOptions = () => dispatch => apiBillRun(getAllGroupsQuery())
.then((success) => {
try {
......
......@@ -3,7 +3,7 @@ import moment from 'moment';
import { escapeRegExp } from './Util';
// TODO: fix to uniqueget (for now billAoi can't search by 'rates')
export const searchProductsByKeyAndUsagetQuery = (usages, notKeys) => {
export const searchProductsByKeyAndUsagetQuery = (usages, notKeys, plays = '') => {
const usagesToQuery = Array.isArray(usages) ? usages : [usages];
const query = {
key: {
......@@ -11,9 +11,20 @@ export const searchProductsByKeyAndUsagetQuery = (usages, notKeys) => {
},
to: { $gt: moment().toISOString() }, // only active and future
tariff_category: 'retail', // only retail products
$and: [], // for addition conditions
};
if (usagesToQuery[0] !== 'cost') {
query.$or = usagesToQuery.map(usage => ({ [`rates.${usage}`]: { $exists: true } }));
query.$and.push(
{ $or: usagesToQuery.map(usage => ({ [`rates.${usage}`]: { $exists: true } })) },
);
}
if (plays !== '') {
query.$and.push(
{ $or: [
{ play: { $exists: true, $in: [...plays.split(','), '', null] } },
{ play: { $exists: false } },
] },
);
}
const formData = new FormData();
......@@ -307,7 +318,7 @@ export const getEntityByIdQuery = (collection, id) => ({
],
});
export const getEntitesQuery = (collection, project = {}, query = {}) => {
export const getEntitesQuery = (collection, project = {}, query = {}, sort = null) => {
let action;
switch (collection) {
case 'users':
......@@ -324,7 +335,7 @@ export const getEntitesQuery = (collection, project = {}, query = {}) => {
{ size: 9999 },
{ query: JSON.stringify(query) },
{ project: JSON.stringify(project) },
{ sort: JSON.stringify(project) },
{ sort: JSON.stringify(sort || project) },
],
});
};
......@@ -353,9 +364,10 @@ export const getDeleteLineQuery = id => ({
// List
export const getPlansQuery = (project = { name: 1 }) => getEntitesQuery('plans', project);
export const getServicesQuery = (project = { name: 1 }) => getEntitesQuery('services', project);
export const getServicesKeysWithInfoQuery = () => getEntitesQuery('services', { name: 1, description: 1, quantitative: 1, balance_period: 1 });
export const getServicesKeysWithInfoQuery = () => getEntitesQuery('services', { name: 1, description: 1, play: 1, quantitative: 1, balance_period: 1 }, {}, { name: 1 });
export const getPrepaidIncludesQuery = () => getEntitesQuery('prepaidincludes');
export const getProductsKeysQuery = (project = { key: 1, description: 1 }, query = {}) => getEntitesQuery('rates', project, query);
export const getProductsKeysQuery = (project = { key: 1, description: 1, play: 1 }, query = {}, sort = { key: 1 }) =>
getEntitesQuery('rates', project, query, sort);
export const getRetailProductsKeysQuery = (project = { key: 1, description: 1 }) => {
const query = { tariff_category: 'retail' };
return getEntitesQuery('rates', project, query);
......@@ -365,11 +377,11 @@ export const getRetailProductsWithRatesQuery = () =>
export const getProductsWithRatesQuery = () =>
getProductsKeysQuery({ key: 1, description: 1, rates: 1 });
export const getServicesKeysQuery = () => getEntitesQuery('services', { name: 1 });
export const getIncludedServicesKeysQuery = () => getEntitesQuery('services', { name: 1 }, {
export const getIncludedServicesKeysQuery = () => getEntitesQuery('services', { name: 1, play: 1 }, {
quantitative: { $ne: true },
balance_period: { $exists: false },
});
export const getPlansKeysQuery = (project = { name: 1, description: 1 }) => getEntitesQuery('plans', project);
export const getPlansKeysQuery = (project = { name: 1, description: 1 }, query = {}, sort = { name: 1 }) => getEntitesQuery('plans', project, query, sort);
export const getUserKeysQuery = () => getEntitesQuery('users', { username: 1 });
export const getAllGroupsQuery = () => ([
getGroupsQuery('plans'),
......
......@@ -511,6 +511,18 @@ export const setFieldTitle = (field, entity, keyProperty = 'field_name') => {
return field.set('title', getFieldName(key, entityName, defaultLable));
};
export const addPlayToFieldTitle = (field, plays = Immutable.Map()) => {
const fieldPlays = field.get('plays', Immutable.List());
if (!fieldPlays.isEmpty()) {
const fieldPlayLabels = fieldPlays.reduce(
(result, playName) => result.push(plays.get(playName, playName)),
Immutable.List(),
).join(', ');
return field.set('title', `${field.get('title', '')} (${fieldPlayLabels})`);
}
return field;
};
export const toImmutableList = (value) => {
if ([undefined, null].includes(value)) {
return Immutable.List();
......
......@@ -49,10 +49,10 @@ class CustomFields extends Component {
}),
defaultHiddenFields: Immutable.Map({
customer: Immutable.List(['aid', 'payment_gateway']),
subscriber: Immutable.List(['sid', 'aid', 'plan_activation']),
product: Immutable.List(['from', 'to']),
service: Immutable.List(['from', 'to', 'include']),
plan: Immutable.List(['from', 'to']),
subscriber: Immutable.List(['sid', 'aid', 'plan_activation', 'play']),
product: Immutable.List(['from', 'to', 'play']),
service: Immutable.List(['from', 'to', 'include', 'play']),
plan: Immutable.List(['from', 'to', 'play']),
}),
unReorderFields: Immutable.Map({
product: Immutable.List(['key', 'description', 'rates']),
......
......@@ -89,7 +89,7 @@ class CustomerSetup extends Component {
this.props.dispatch(setPageTitle(pageTitle));
} else {
this.props.dispatch(getList('available_gateways', getPaymentGatewaysQuery()));
this.props.dispatch(getList('available_plans', getPlansKeysQuery({ name: 1, description: 1, 'include.services': 1 })));
this.props.dispatch(getList('available_plans', getPlansKeysQuery({ name: 1, play: 1, description: 1, 'include.services': 1 })));
this.props.dispatch(getList('available_services', getServicesKeysWithInfoQuery()));
}
}
......
......@@ -129,6 +129,8 @@ class Subscription extends Component {
onChangePlay = (play) => {
this.updateSubscriptionField(['play'], play);
this.filterSubscriptionServicesByPlay(play);
this.filterSubscriptionPlanByPlay(play);
}
onChangeServiceDetails = (index, key, value) => {
......@@ -143,6 +145,32 @@ class Subscription extends Component {
this.updateSubscriptionField(['services'], newServices);
}
filterSubscriptionPlanByPlay = (play) => {
const { subscription } = this.state;
const { allPlans } = this.props;
const selectedPlanPlays = allPlans.find(
plan => plan.get('name', '') === subscription.get('plan', ''),
null, Immutable.Map(),
).get('play', Immutable.List());
if (!selectedPlanPlays.isEmpty() && !selectedPlanPlays.includes(play)) {
this.updateSubscriptionField(['plan'], '');
}
}
filterSubscriptionServicesByPlay = (play) => {
const { allServices } = this.props;
const { subscription } = this.state;
const services = subscription.get('services', Immutable.List()) || Immutable.List();
const newServices = services.filter((service) => {
const servicePlays = allServices.find(
option => option.get('name', '') === service.get('name', ''),
null, Immutable.Map(),
).get('play', Immutable.List());
return servicePlays.isEmpty() || servicePlays.includes(play);
});
this.updateSubscriptionField(['services'], newServices);
}
getServiceType = (service) => {
const { allServices } = this.props;
const serviceName = (Immutable.Map.isMap(service)) ? service.get('name', '') : service;
......@@ -226,7 +254,17 @@ class Subscription extends Component {
label: item.get('description', item.get('name', '')),
}));
getAvailablePlans = () => this.formatSelectOptions(this.props.allPlans);
getAvailablePlans = () => {
const { subscription } = this.state;
const { allPlans } = this.props;
const play = subscription.get('play', false);
if ([false, ''].includes(play)) {
return this.formatSelectOptions(allPlans);
}
return this.formatSelectOptions(allPlans
.filter(allPlan => allPlan.get('play', Immutable.List()).isEmpty() || allPlan.get('play', Immutable.List()).includes(play)),
);
}
getPlanIncludedServices = (planName) => {
if (planName === '') {
......@@ -238,7 +276,17 @@ class Subscription extends Component {
return includedServices.size ? includedServices.join(', ') : '-';
}
getAvailableServices = () => this.formatSelectOptions(this.props.allServices);
getAvailableServices = () => {
const { subscription } = this.state;
const { allServices } = this.props;
const play = subscription.get('play', false);
if ([false, ''].includes(play)) {
return this.formatSelectOptions(allServices);
}
return this.formatSelectOptions(allServices
.filter(allService => allService.get('play', Immutable.List()).isEmpty() || allService.get('play', Immutable.List()).includes(play)),
);
}
filterCustomFields = (field) => {
const hiddenFields = ['plan', 'services', 'play'];
......@@ -259,6 +307,7 @@ class Subscription extends Component {
renderSystemFields = (editable) => {
const { subscription } = this.state;
const { mode } = this.props;
const plansOptions = this.getAvailablePlans().toJS();
const servicesOptions = this.getAvailableServices().toJS();
const services = subscription.get('services', Immutable.List()) || Immutable.List();
......@@ -267,7 +316,8 @@ class Subscription extends Component {
return ([
(<PlaysSelector
entity={subscription}
editable={editable}
editable={editable && mode === 'create'}
mandatory={true}
onChange={this.onChangePlay}
/>),
(<FormGroup key="plan">
......
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import Immutable from 'immutable';
import changeCase from 'change-case';
import EntityList from '../EntityList';
import { getItemDateValue, getConfig } from '../../common/Util';
import { playsIsEnabledSelector } from '../../selectors/settingsSelector';
export default class SubscriptionsList extends Component {
class SubscriptionsList extends Component {
static propTypes = {
settings: PropTypes.instanceOf(Immutable.List),
isPlaysEnabled: PropTypes.bool,
aid: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
......@@ -21,6 +24,7 @@ export default class SubscriptionsList extends Component {
static defaultProps = {
settings: Immutable.List(),
defaultListFields: [],
isPlaysEnabled: false,
aid: '',
};
......@@ -53,9 +57,18 @@ export default class SubscriptionsList extends Component {
this.props.onNew(aid, e);
}
filterPlayField = (field) => {
const { isPlaysEnabled } = this.props;
if (field.get('field_name', '') !== 'play') {
return true;
}
return isPlaysEnabled;
}
getFields = () => {
const { settings, defaultListFields } = this.props;
return settings
.filter(this.filterPlayField)
.filter(field => (field.get('show_in_list', false) || defaultListFields.includes(field.get('field_name', ''))))
.map((field) => {
const fieldname = field.get('field_name');
......@@ -154,3 +167,10 @@ export default class SubscriptionsList extends Component {
);
}
}
const mapStateToProps = (state, props) => ({
isPlaysEnabled: playsIsEnabledSelector(state, props),
});
export default connect(mapStateToProps)(SubscriptionsList);
......@@ -53,6 +53,26 @@ class EntityFields extends Component {
}
}
componentDidUpdate(prevProps, prevState) { // eslint-disable-line no-unused-vars
const { fields, entity } = this.props;
const { entity: oldEntity } = prevProps;
const isMultiple = fields.find(field => field.get('field_name', '') === 'play',
null, Immutable.Map(),
).get('multiple', false);
const shouldResetFields = isMultiple ?
!Immutable.is(entity.get('play', Immutable.List()), oldEntity.get('play', Immutable.List()))
: entity.get('play', '') !== oldEntity.get('play', '')
if (shouldResetFields) {
fields.forEach((field) => {
const shoudPlayBeDisplayd = this.filterPlayFields(field);
if (!shoudPlayBeDisplayd) {
this.props.onChangeField(field.get('field_name', '').split('.'), '');
}
});
}
}
getParamsOptions = () => {
const { fields, fieldsFilter, highlightPramas } = this.props;
const fieldFilterFunction = fieldsFilter !== null ? fieldsFilter : this.filterPrintableFields;
......@@ -74,6 +94,7 @@ class EntityFields extends Component {
field.get('display', false) !== false
&& field.get('editable', false) !== false
&& field.get('field_name', '') !== 'tariff_category'
&& field.get('field_name', '') !== 'play'
);
filterParamsFields = (field) => {
......
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import Immutable from 'immutable';
import classNames from 'classnames';
import Field from '../../Field';
import { showConfirmModal } from '../../../actions/guiStateActions/pageActions';
import { getFieldName, getAvailableFields } from '../../../common/Util';
export default class CustomerMapping extends Component {
class CustomerMapping extends Component {
static propTypes = {
settings: PropTypes.instanceOf(Immutable.Map),
usaget: PropTypes.string.isRequired,
......@@ -11,6 +14,7 @@ export default class CustomerMapping extends Component {
priority: PropTypes.number.isRequired,
onSetCustomerMapping: PropTypes.func.isRequired,
subscriberFields: PropTypes.instanceOf(Immutable.List),
dispatch: PropTypes.func.isRequired,
}
static defaultProps = {
......@@ -24,6 +28,30 @@ export default class CustomerMapping extends Component {
this.props.onSetCustomerMapping(id, value, usaget, priority);
}
onSetCustomerMappingTarget = (e) => {
const { value, id } = e.target;
const { subscriberFields } = this.props;
const event = { target: { id, value } };
const isUnique = subscriberFields.find(
subscriberField => subscriberField.get('field_name', '') === value,
null, Immutable.Map(),
).get('unique', false);
// If new field is unique -> update, if not unique - show confirm
if (isUnique) {
return this.onSetCustomerMapping(event);
}
const onOk = () => {
this.onSetCustomerMapping(event);
};
const confirm = {
message: 'You selected a non-unique field for subscriber matching. Continue?',
onOk,
type: 'delete',
labelOk: 'Continue',
};
return this.props.dispatch(showConfirmModal(confirm));
}
onChangeClearRegex = (value) => {
const { usaget, priority } = this.props;
this.props.onSetCustomerMapping('clear_regex', value, usaget, priority);
......@@ -37,14 +65,23 @@ export default class CustomerMapping extends Component {
getAvailableTargetFields = () => {
const { subscriberFields } = this.props;
const optionsKeys = subscriberFields
.filter(field => field.get('unique', false))
.map(field => field.get('field_name', ''));
const options = [
(<option disabled value="-1" key={-1}>Select Field...</option>),
...optionsKeys.map((field, key) => <option value={field} key={key}>{getFieldName(field, 'customerIdentification')}</option>),
return [
(<option disabled value="-1" key="target-field-selecte">Select Field...</option>),
subscriberFields
.sort(field => (field.get('unique', false) ? -1 : 1))
.map((field, key) => {
const value = field.get('field_name', '');
const label = getFieldName(value, 'customerIdentification', field.get('title', ''));
const optionClass = classNames({
'label-text': field.get('unique', false),
disabled: !field.get('unique', false),
});
return (
<option value={value} key={`target-field-${key}`} className={optionClass}>{label}</option>
);
},
),
];
return options;
}
render() {
......@@ -72,7 +109,7 @@ export default class CustomerMapping extends Component {
/>
</div>
<div className="col-lg-4">
<select id="target_key" className="form-control" onChange={this.onSetCustomerMapping} value={targetKey}>
<select id="target_key" className="form-control" onChange={this.onSetCustomerMappingTarget} value={targetKey}>
{ availableTargetFields }
</select>
</div>
......@@ -80,3 +117,5 @@ export default class CustomerMapping extends Component {
);
}
}
export default connect(null)(CustomerMapping);
......@@ -50,7 +50,13 @@ import { getSettings } from '../../actions/settingsActions';
import { showSuccess, showDanger } from '../../actions/alertsActions';
import { getList, clearList } from '../../actions/listActions';
import { setPageTitle } from '../../actions/guiStateActions/pageActions';
import { usageTypeSelector, usageTypesDataSelector, propertyTypeSelector } from '../../selectors/settingsSelector';
import {
usageTypeSelector,
usageTypesDataSelector,
propertyTypeSelector,
productFieldsSelector,
subscriberFieldsWithPlaySelector,
} from '../../selectors/settingsSelector';
class InputProcessor extends Component {
......@@ -583,8 +589,8 @@ const mapStateToProps = (state, props) => {
usageTypes: usageTypeSelector(state, props),
propertyTypes: propertyTypeSelector(state, props),
usageTypesData: usageTypesDataSelector(state, props),
subscriberFields: state.settings.getIn(['subscribers', 'subscriber', 'fields'], Immutable.List()),
customRatingFields: state.settings.getIn(['rates', 'fields'], Immutable.List()),
subscriberFields: subscriberFieldsWithPlaySelector(state, props),
customRatingFields: productFieldsSelector(state, props),
fileType,
action,
template,
......
......@@ -20,6 +20,10 @@ import {
removeRatingPriorityField,
removeRatingField,
} from '../../../actions/inputProcessorActions';
import {
customerIdentificationFieldsPlaySelector,
} from '../../../selectors/inputProcessorSelector';
class RateMapping extends Component {
static propTypes = {
......@@ -29,11 +33,13 @@ class RateMapping extends Component {
settings: PropTypes.instanceOf(Immutable.Map),
customRatingFields: PropTypes.instanceOf(Immutable.List),
rateCalculators: PropTypes.instanceOf(Immutable.List),
plays: PropTypes.instanceOf(Immutable.Set),
}
static defaultProps = {
settings: Immutable.Map(),
customRatingFields: Immutable.List(),
rateCalculators: Immutable.List(),
plays: Immutable.Set(),
};
state = {
......@@ -52,10 +58,23 @@ class RateMapping extends Component {
});
};
sortFiledByPlay = field => (field.get('plays', Immutable.List()).isEmpty() ? 1 : -1)
filterFiledByPlay = (field) => {
const { plays } = this.props;
const fieldPlays = field.get('plays', Immutable.List());
if (fieldPlays.isEmpty()) {
return true;
}
return plays.intersect(Immutable.Set(fieldPlays)).size > 0;
}
getCustomRatingFields = () => {
const { customRatingFields } = this.props;
return customRatingFields
.filter(field => (field.get('field_name', '').startsWith('params.')))
.filter(this.filterFiledByPlay)
.sort(this.sortFiledByPlay)
.map(field => ({
value: field.get('field_name', ''),
label: field.get('title', ''),
......@@ -543,6 +562,7 @@ class RateMapping extends Component {
}
const mapStateToProps = (state, props) => ({
plays: customerIdentificationFieldsPlaySelector(state, props),
rateCalculators: props.settings.getIn(['rate_calculators', props.rateCategory, props.usaget]),
});
......
......@@ -17,12 +17,14 @@ class PlanIncludedServicesTab extends Component {
services: PropTypes.instanceOf(List),
dispatch: PropTypes.func.isRequired,
onChangeFieldValue: PropTypes.func.isRequired,
plays: PropTypes.instanceOf(List),
};
static defaultProps = {
includedServices: List(),
mode: 'create',
services: List(),
plays: List(),
};
componentWillMount() {
......@@ -34,9 +36,19 @@ class PlanIncludedServicesTab extends Component {
this.props.onChangeFieldValue(['include', 'services'], List(servicesList));
}
filterByPlay = (option) => {
const { plays } = this.props;
const servicePlays = option.get('play', List());
if (plays && !plays.isEmpty() && !servicePlays.isEmpty()) {
return !plays.filter(entityPlay => servicePlays.includes(entityPlay)).isEmpty();
}
return true;
}
getServicesOptions = () => {
const { services } = this.props;
return services
.filter(this.filterByPlay)
.map(service => ({
value: service.get('name', ''),
label: service.get('name', ''),
......
......@@ -36,6 +36,7 @@ class PlanIncludesTab extends Component {
mode: PropTypes.string,
dispatch: PropTypes.func.isRequired,
type: PropTypes.string,
plays: PropTypes.string,
}
static defaultProps = {
......@@ -45,6 +46,7 @@ class PlanIncludesTab extends Component {
propertyTypes: Immutable.List(),
mode: 'create',
type: '',
plays: '',
};
constructor(props) {
......@@ -117,6 +119,7 @@ class PlanIncludesTab extends Component {
}
return includeGroups.map((include, groupName) => {
const { plays } = this.props;
const shared = include.get('account_shared', false);
const pooled = include.get('account_pool', false);
const quantityAffected = include.get('quantity_affected', false);
......@@ -146,6 +149,7 @@ class PlanIncludesTab extends Component {
usaget={usaget}
usageTypes={usageTypes}
type={this.props.type}
plays={plays}
/>
);
}).toArray();
......@@ -166,7 +170,7 @@ class PlanIncludesTab extends Component {
);
render() {
const { mode } = this.props;
const { mode, plays } = this.props;
const { existingGroups, usedProducts } = this.state;
const allowCreate = mode !== 'view';
......@@ -190,6 +194,7 @@ class PlanIncludesTab extends Component {
usedProducts={usedProducts}
addGroup={this.onGroupAdd}
type={this.props.type}
plays={plays}
/>
}
</Col>
......
......@@ -40,6 +40,7 @@ class PlanProductsPriceTab extends Component {
planRates: PropTypes.instanceOf(Immutable.Map),
usageTypesData: PropTypes.instanceOf(Immutable.List),
propertyTypes: PropTypes.instanceOf(Immutable.List),
plays: PropTypes.string,
mode: PropTypes.string,
originalRates: PropTypes.instanceOf(Immutable.Map),
products: PropTypes.instanceOf(Immutable.List),
......@@ -52,6 +53,7 @@ class PlanProductsPriceTab extends Component {
planRates: Immutable.Map(),
usageTypesData: Immutable.List(),
propertyTypes: Immutable.List(),
plays: '',
mode: 'create',
originalRates: Immutable.Map(),
products: Immutable.List(),
......@@ -228,6 +230,14 @@ class PlanProductsPriceTab extends Component {
.toArray();
}
filterByPlay = (option) => {
const { plays } = this.props;