- Fix for #890
- "Channels" feature - Shoutout config param rendered on the homepage - "Clone" feature for campaigns
This commit is contained in:
parent
00432e6cfe
commit
d170548cfa
25 changed files with 1009 additions and 525 deletions
|
|
@ -34,8 +34,6 @@ import styles from "./styles.scss";
|
|||
import moment from "moment";
|
||||
import {getUrl} from "./urls";
|
||||
import {createComponentMixin, withComponentMixins} from "./decorator-helpers";
|
||||
import cudStyles from "../../../mvis/ivis-core/client/src/settings/jobs/CUD.scss";
|
||||
import {campaignOverridables, CampaignSource, CampaignType} from "../../../shared/campaigns";
|
||||
|
||||
|
||||
const FormState = {
|
||||
|
|
@ -931,207 +929,6 @@ class ButtonRow extends Component {
|
|||
}
|
||||
|
||||
|
||||
@withComponentMixins([
|
||||
withTranslation,
|
||||
withFormStateOwner
|
||||
], null, ['submitFormValuesMutator', 'getFormValueIdForPicker'])
|
||||
class ListCreator extends Component {
|
||||
static propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
className: PropTypes.string,
|
||||
withOrder: PropTypes.bool,
|
||||
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this._nextEntryId = 0;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const values = this.props.initValues;
|
||||
if (values && values.length > 0) {
|
||||
this.getFormStateOwner().updateForm(mutState => {
|
||||
let entryIds = mutState.getIn([this.props.id, 'value']);
|
||||
|
||||
if (!entryIds) {
|
||||
entryIds = [];
|
||||
}
|
||||
|
||||
for (const entryValue of values) {
|
||||
const entryId = this.getNextEntryId();
|
||||
mutState.setIn([this.getFormValueId(entryId), 'value'], entryValue);
|
||||
entryIds.push(entryId);
|
||||
}
|
||||
|
||||
mutState.setIn([this.props.id, 'value'], entryIds);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static getFormValuesMutator(pickerId, data) {
|
||||
const elems = [];
|
||||
for (const elem of data[pickerId]) {
|
||||
const uid = this.getNextEntryId();
|
||||
|
||||
const prefix = this.getFormValueId(uid);
|
||||
|
||||
data[prefix + 'list'] = elem.list;
|
||||
data[prefix + 'segment'] = elem.segment;
|
||||
data[prefix + 'useSegmentation'] = !!elem.segment;
|
||||
|
||||
elems.push(uid);
|
||||
}
|
||||
data[pickerId] = elems;
|
||||
}
|
||||
|
||||
|
||||
static submitFormValuesMutator(pickerId, data) {
|
||||
const entryValues = [];
|
||||
const entryIds = data[pickerId];
|
||||
|
||||
if (!entryIds) {
|
||||
return entryValues;
|
||||
}
|
||||
|
||||
for (const entryId of entryIds) {
|
||||
const entryFormId = ListCreator.getFormValueIdForPicker(pickerId, entryId);
|
||||
const value = data[entryFormId];
|
||||
entryValues.push(value);
|
||||
delete data[entryFormId]
|
||||
}
|
||||
|
||||
data[pickerId] = entryValues;
|
||||
}
|
||||
|
||||
static getFormValueIdForPicker(pickerId, entryId) {
|
||||
return `${pickerId}_${entryId}`;
|
||||
}
|
||||
|
||||
getFormValueId(entryId) {
|
||||
return ListCreator.getFormValueIdForPicker(this.props.id, entryId);
|
||||
}
|
||||
|
||||
getNextEntryId() {
|
||||
return this._nextEntryId++;
|
||||
}
|
||||
|
||||
onAddListEntry(positionBefore) {
|
||||
this.getFormStateOwner().updateForm(mutState => {
|
||||
let entryIds = mutState.getIn([this.props.id, 'value']);
|
||||
|
||||
if (!entryIds) {
|
||||
entryIds = [];
|
||||
}
|
||||
|
||||
if (positionBefore == null) {
|
||||
positionBefore = entryIds.length;
|
||||
}
|
||||
|
||||
const entryId = this.getNextEntryId();
|
||||
|
||||
mutState.setIn([this.getFormValueId(entryId), 'value'], null);
|
||||
mutState.setIn([this.props.id, 'value'], [...entryIds.slice(0, positionBefore), entryId, ...entryIds.slice(positionBefore)]);
|
||||
});
|
||||
}
|
||||
|
||||
onRemoveSetEntry(entryId) {
|
||||
this.getFormStateOwner().updateForm(mutState => {
|
||||
const entryIds = mutState.getIn([this.props.id, 'value']);
|
||||
|
||||
mutState.delete(this.getFormValueId(entryId));
|
||||
|
||||
mutState.setIn([this.props.id, 'value'], entryIds.filter(id => id !== entryId));
|
||||
});
|
||||
}
|
||||
|
||||
onListEntryMoveUp(position) {
|
||||
const owner = this.getFormStateOwner();
|
||||
const entryIds = owner.getFormValue(this.props.id);
|
||||
owner.updateFormValue(this.props.id, [...entryIds.slice(0, position - 1), entryIds[position], entryIds[position - 1], ...entryIds.slice(position + 1)]);
|
||||
}
|
||||
|
||||
onListEntryMoveDown(position) {
|
||||
const owner = this.getFormStateOwner();
|
||||
const entryIds = owner.getFormValue(this.props.id);
|
||||
owner.updateFormValue(this.props.id, [...entryIds.slice(0, position), entryIds[position + 1], entryIds[position], ...entryIds.slice(position + 2)]);
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const owner = this.getFormStateOwner();
|
||||
const id = props.id;
|
||||
const t = props.t;
|
||||
const withOrder = props.withOrder;
|
||||
const entries = [];
|
||||
const entryIds = owner.getFormValue(id) || [];
|
||||
|
||||
const entryButtonsStyles = withOrder ? cudStyles.entryButtonsWithOrder : cudStyles.entryButtons;
|
||||
for (let pos = 0; pos < entryIds.length; pos++) {
|
||||
const entryId = entryIds[pos];
|
||||
const elementId = this.getFormValueId(entryId);
|
||||
entries.push(
|
||||
<div key={entryId}
|
||||
className={cudStyles.entry + (withOrder ? ' ' + cudStyles.withOrder : '') + ' ' + cudStyles.entryWithButtons}>
|
||||
<div className={entryButtonsStyles}>
|
||||
<Button
|
||||
className="btn-secondary"
|
||||
icon={`trash-alt ${withOrder ? "" : "fa-2x"}`}
|
||||
title={t('remove')}
|
||||
onClickAsync={() => this.onRemoveSetEntry(entryId)}
|
||||
/>
|
||||
{withOrder &&
|
||||
<Button
|
||||
className="btn-secondary"
|
||||
icon="plus"
|
||||
title={t('Insert new entry before this one')}
|
||||
onClickAsync={() => this.onAddListEntry(pos)}
|
||||
/>
|
||||
}
|
||||
{withOrder && pos > 0 &&
|
||||
<Button
|
||||
className="btn-secondary"
|
||||
icon="chevron-up"
|
||||
title={t('Move up')}
|
||||
onClickAsync={() => this.onListEntryMoveUp(pos)}
|
||||
/>
|
||||
}
|
||||
{withOrder && pos < entryIds.length - 1 &&
|
||||
<Button
|
||||
className="btn-secondary"
|
||||
icon="chevron-down"
|
||||
title={t('Move down')}
|
||||
onClickAsync={() => this.onListEntryMoveDown(pos)}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
<div className={cudStyles.entryContent}>
|
||||
{React.cloneElement(this.props.entryElement, {id: elementId})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Fieldset id={id} className={props.classname} help={props.help} flat={props.flat} label={props.label}>
|
||||
{entries}
|
||||
<div key="newEntry" className={cudStyles.newEntry}>
|
||||
<Button
|
||||
className="btn-secondary"
|
||||
icon="plus"
|
||||
label={t('Add entry')}
|
||||
onClickAsync={() => this.onAddListEntry(entryIds.length)}
|
||||
/>
|
||||
</div>
|
||||
</Fieldset>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@withComponentMixins([
|
||||
withFormStateOwner
|
||||
])
|
||||
|
|
@ -1200,6 +997,7 @@ class TableSelect extends Component {
|
|||
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
format: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
withClear: PropTypes.bool,
|
||||
|
||||
pageLength: PropTypes.number
|
||||
}
|
||||
|
|
@ -1245,6 +1043,15 @@ class TableSelect extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
async clear() {
|
||||
const owner = this.getFormStateOwner();
|
||||
if (this.props.selectMode === TableSelectMode.SINGLE && !this.props.selectionAsArray) {
|
||||
owner.updateFormValue(this.props.id, null);
|
||||
} else {
|
||||
owner.updateFormValue(this.props.id, []);
|
||||
}
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.table.refresh();
|
||||
}
|
||||
|
|
@ -1256,6 +1063,8 @@ class TableSelect extends Component {
|
|||
const htmlId = 'form_' + id;
|
||||
const t = props.t;
|
||||
|
||||
const selection = owner.getFormValue(id);
|
||||
|
||||
if (props.dropdown) {
|
||||
const className = owner.addFormValidationClass('form-control', id);
|
||||
|
||||
|
|
@ -1271,6 +1080,7 @@ class TableSelect extends Component {
|
|||
{!props.disabled &&
|
||||
<div className="input-group-append">
|
||||
<Button label={t('select')} className="btn-secondary" onClickAsync={::this.toggleOpen}/>
|
||||
{props.withClear && selection && <Button icon="times" title={t('Clear')} className="btn-secondary" onClickAsync={::this.clear}/>}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
|
@ -1285,7 +1095,7 @@ class TableSelect extends Component {
|
|||
selectionAsArray={this.props.selectionAsArray}
|
||||
withHeader={props.withHeader}
|
||||
selectionKeyIndex={props.selectionKeyIndex}
|
||||
selection={owner.getFormValue(id)}
|
||||
selection={selection}
|
||||
onSelectionDataAsync={::this.onSelectionDataAsync}
|
||||
onSelectionChangedAsync={::this.onSelectionChangedAsync}/>
|
||||
</div>
|
||||
|
|
@ -1305,7 +1115,7 @@ class TableSelect extends Component {
|
|||
selectionAsArray={this.props.selectionAsArray}
|
||||
withHeader={props.withHeader}
|
||||
selectionKeyIndex={props.selectionKeyIndex}
|
||||
selection={owner.getFormValue(id)}
|
||||
selection={selection}
|
||||
onSelectionChangedAsync={::this.onSelectionChangedAsync}/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue