- "Channels" feature
- Shoutout config param rendered on the homepage
- "Clone" feature for campaigns
This commit is contained in:
Tomas Bures 2020-07-17 14:53:48 +02:00
parent 00432e6cfe
commit d170548cfa
25 changed files with 1009 additions and 525 deletions

View file

@ -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>