Commit 8c9ccd03 authored by Roman's avatar Roman

manual merge with DEV

parents d28f0563 7c4c67ee
......@@ -5,7 +5,7 @@ var globalSetting = {
// serverUrl : "http://10.162.20.247", // Shani
serverUrl: "http://billrun",
//serverUrl: "",
serverApiVersion: '5.8.8',
serverApiVersion: '5.9',
serverApiTimeOut: 300000, // 5 minutes
serverApiDebug: false,
serverApiDebugQueryString: 'XDEBUG_SESSION_START=netbeans-xdebug',
......@@ -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',
......
var globalSetting = {
storageVersion: '0.0.1',
serverUrl: "",
serverApiVersion: '5.8.8',
serverApiVersion: '5.9',
serverApiTimeOut: 300000, // 5 minutes
serverApiDebug: false,
serverApiDebugQueryString: 'XDEBUG_SESSION_START=netbeans-xdebug',
......@@ -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',
......
......@@ -430,6 +430,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;
......@@ -798,6 +801,9 @@ ul.revision-history-list li.active .cycle {
margin-left: 0;
margin-right: 0;
}
.Importer .form-group.rangesField {
padding: 0;
}
.Importer .panel,
.Importer .Select-control {
/* set select input transparent to not hide wrapper div shadows */
......@@ -815,10 +821,10 @@ ul.revision-history-list li.active .cycle {
min-height: 200px;
}
.Importer .StepMapper {
max-height: 258px;
max-height: 50vh;
}
.Importer .StepValidate .row-fields {
max-height: 300px;
max-height: 50vh;
margin: 0;
}
.Importer .StepResult ol {
......
......@@ -42,6 +42,11 @@ export const saveSubscription = (subscription, action) => dispatch =>
dispatch(saveEntity('subscribers', subscription, action))
.then(response => Object.assign(response, { subscription, action }));
export const removeCustomerField = path => ({
type: actions.DELETE_ENTITY_FIELD,
collection: 'customer',
path,
});
export const updateCustomerField = (path, value) => ({
type: actions.UPDATE_ENTITY_FIELD,
......
......@@ -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,
......
......@@ -18,6 +18,7 @@ export const PRODUCT_CLEAR = 'PRODUCT_CLEAR';
export const PRODUCT_CLONE_RESET = 'PRODUCT_CLONE_RESET';
export const PRODUCT_ADD_RATE = 'PRODUCT_ADD_RATE';
export const PRODUCT_REMOVE_RATE = 'PRODUCT_REMOVE_RATE';
export const PRODUCT_DELETE_FIELD = 'PRODUCT_DELETE_FIELD';
export const PRODUCT_UPDATE_FIELD_VALUE = 'PRODUCT_UPDATE_FIELD_VALUE';
export const PRODUCT_UPDATE_USAGET_VALUE = 'PRODUCT_UPDATE_USAGET_VALUE';
export const PRODUCT_UPDATE_TO_VALUE = 'PRODUCT_UPDATE_TO_VALUE';
......@@ -38,6 +39,11 @@ export const onFieldUpdate = (path, value) => ({
value,
});
export const onFieldRemove = path => ({
type: PRODUCT_DELETE_FIELD,
path,
});
export const onToUpdate = (path, index, value) => ({
type: PRODUCT_UPDATE_TO_VALUE,
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 {
......
......@@ -16,6 +16,7 @@ import {
export const GOT_SERVICE = 'GOT_SERVICE';
export const UPDATE_SERVICE = 'UPDATE_SERVICE';
export const DELETE_SERVICE_FIELD = 'DELETE_SERVICE_FIELD';
export const SAVE_SERVICE = 'SAVE_SERVICE';
export const CLEAR_SERVICE = 'CLEAR_SERVICE';
export const CLONE_RESET_SERVICE = 'CLONE_RESET_SERVICE';
......@@ -44,6 +45,11 @@ export const updateService = (path, value) => ({
value,
});
export const deleteServiceField = path => ({
type: DELETE_SERVICE_FIELD,
path,
});
export const addGroup = (groupName, usages, unit, value, shared, pooled, quantityAffected, products) => ({
type: ADD_GROUP_SERVICE,
groupName,
......
......@@ -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'),
......
......@@ -362,6 +362,12 @@ const getItemConvertedRates = (propertyTypes, usageTypes, item, toBaseUnit, type
ratesWithMutations.setIn([...ratePath, 'to'], newTo);
ratesWithMutations.setIn([...ratePath, 'interval'], newInterval);
});
const percentage = rate.get('percentage', null);
if (percentage !== null) {
const ratePath = (type === 'product' ? [usaget, plan] : [plan, usaget]);
const convertedPercentage = toBaseUnit ? percentage / 100 : percentage * 100;
ratesWithMutations.setIn([...ratePath, 'percentage'], convertedPercentage);
}
});
});
});
......@@ -511,6 +517,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();
......@@ -539,3 +557,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');
......
......@@ -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']),
......
......@@ -11,11 +11,10 @@ import { ConfirmModal } from '../../components/Elements';
import { currencySelector, paymentGatewaysSelector } from '../../selectors/settingsSelector';
import OfflinePayment from '../Payments/OfflinePayment';
import CyclesSelector from '../Cycle/CyclesSelector';
import { getExpectedInvoiceQuery, getSettingsQuery } from '../../common/ApiQueries'
import { buildRequestUrl, apiBillRun } from '../../common/Api'
import { getExpectedInvoiceQuery } from '../../common/ApiQueries';
import { buildRequestUrl } from '../../common/Api';
import EntityFields from '../Entity/EntityFields';
import { getSettings } from '../../actions/settingsActions';
import { getList } from '../../actions/listActions';
import Credit from '../Credit/Credit';
class Customer extends Component {
......@@ -26,6 +25,7 @@ class Customer extends Component {
supportedGateways: PropTypes.instanceOf(Immutable.List),
onChangePaymentGateway: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onRemoveField: PropTypes.func.isRequired,
action: PropTypes.string,
currency: PropTypes.string,
fields: PropTypes.instanceOf(Immutable.List),
......@@ -80,6 +80,10 @@ class Customer extends Component {
this.props.onChange(e);
};
onRemoveCustomField = (fieldPath) => {
this.props.onRemoveField(fieldPath);
};
renderPaymentGatewayLabel = () => {
const { customer, supportedGateways } = this.props;
const customerPgName = customer.getIn(['payment_gateway', 'active', 'name'], '');
......@@ -178,8 +182,8 @@ class Customer extends Component {
onClickExpectedInvoice = () => {
const { customer } = this.props;
const { expectedCyclesNames } = this.state;
let query = getExpectedInvoiceQuery(customer.get('aid'),expectedCyclesNames);
window.open(buildRequestUrl(query))
const query = getExpectedInvoiceQuery(customer.get('aid'), expectedCyclesNames);
window.open(buildRequestUrl(query));
}
......@@ -299,6 +303,7 @@ class Customer extends Component {
entityName={['subscribers', 'account']}
entity={customer}
onChangeField={this.onChangeCustomField}
onRemoveField={this.onRemoveCustomField}
/>
{ (action !== 'create') && this.renderChangePaymentGateway() }
{ (action !== 'create') && this.renderDebt() }
......
......@@ -18,6 +18,7 @@ import {
saveSubscription,
saveCustomer,
updateCustomerField,
removeCustomerField,
clearCustomer,
getCustomer,
getSubscription,
......@@ -89,7 +90,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()));
}
}
......@@ -131,6 +132,10 @@ class CustomerSetup extends Component {
this.props.dispatch(updateCustomerField(id, value));
}
onRemoveCustomerField = (path) => {
this.props.dispatch(removeCustomerField(path));
}
afterSaveCustomer = (response) => {
const { mode } = this.props;
if (response.status) {
......@@ -248,6 +253,7 @@ class CustomerSetup extends Component {
fields={accountFields}
supportedGateways={gateways}
onChange={this.onChangeCustomerField}
onRemoveField={this.onRemoveCustomerField}
onChangePaymentGateway={this.onClickChangePaymentGateway}
/>
</Panel>
......
......@@ -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 });
......@@ -139,6 +129,8 @@ class Subscription extends Component {
onChangePlay = (play) => {
this.updateSubscriptionField(['play'], play);
this.filterSubscriptionServicesByPlay(play);
this.filterSubscriptionPlanByPlay(play);
}
onChangeServiceDetails = (index, key, value) => {
......@@ -153,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;
......@@ -231,12 +249,26 @@ class Subscription extends Component {
this.setState(prevState => ({ subscription: prevState.subscription.setIn(path, value) }));
}
removeSubscriptionField = (path, value) => {
this.setState(prevState => ({ subscription: prevState.subscription.deleteIn(path, value) }));
}
formatSelectOptions = items => items.map(item => ({
value: item.get('name', ''),
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 === '') {
......@@ -248,23 +280,28 @@ 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 { 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,46 +309,21 @@ 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 { mode } = this.props;
const plansOptions = this.getAvailablePlans().toJS();
const servicesOptions = this.getAvailableServices().toJS();
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 && mode === 'create'}
mandatory={true}
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}>
......@@ -430,6 +442,7 @@ class Subscription extends Component {
entityName={['subscribers', 'subscriber']}
entity={subscription}
onChangeField={this.updateSubscriptionField}
onRemoveField={this.removeSubscriptionField}
fieldsFilter={this.filterCustomFields}
editable={allowEdit}
/>
......@@ -459,7 +472,6 @@ const mapStateToProps = (state, props) => {
return ({
revisions,
mode,
availablePlays: availablePlaysSettingsSelector(state, props),
});
};
export default connect(mapStateToProps)(Subscription);
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 { isPlaysEnabledSelector } 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 {