@capillarytech/creatives-library 3.0.7 → 3.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/containers/Email/index.js +9 -7
- package/containers/MobilePush/Edit/index.js +0 -1
- package/containers/Templates/index.js +1 -1
- package/package.json +1 -1
- package/v2Components/DateFilter/index.js +349 -0
- package/v2Components/DateFilter/messages.js +17 -0
- package/v2Components/DateFilter/tests/index.test.js +15 -0
- package/v2Components/DateRange/index.js +113 -0
- package/v2Components/DateRange/messages.js +13 -0
- package/v2Components/DateRange/tests/index.test.js +10 -0
- package/v2Components/EmailMobilePreview/index.js +9 -0
- package/v2Components/NavigationBar/index.js +18 -7
- package/v2Components/NavigationBar/messages.js +2 -6
- package/v2Components/PageHeader/_pageHeader.scss +22 -0
- package/v2Components/PageHeader/index.js +37 -0
- package/v2Components/PageHeader/messages.js +13 -0
- package/v2Components/PageHeader/tests/index.test.js +10 -0
- package/v2Components/Sidebar/_sidebar.scss +115 -0
- package/v2Components/Sidebar/index.js +208 -0
- package/v2Components/Sidebar/messages.js +21 -0
- package/v2Components/Sidebar/tests/index.test.js +10 -0
- package/v2Components/SmsEditor/index.js +55 -0
- package/v2Components/SmsEditor/tests/index.test.js +10 -0
- package/v2Components/TopBar/_topbar.scss +46 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +3 -3
|
@@ -2537,13 +2537,15 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2537
2537
|
});
|
|
2538
2538
|
}
|
|
2539
2539
|
});
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2540
|
+
if (temp.standalone.sections && temp.standalone.sections.length > 0) {
|
|
2541
|
+
_.forEach(temp.standalone.sections[1].inputFields[0].cols, (inputField) => {
|
|
2542
|
+
if (inputField.id === "template-version") {
|
|
2543
|
+
const iF = inputField;
|
|
2544
|
+
iF.colStyle = {};
|
|
2545
|
+
iF.colStyle.display = "none";
|
|
2546
|
+
}
|
|
2547
|
+
});
|
|
2548
|
+
}
|
|
2547
2549
|
//}
|
|
2548
2550
|
temp = type === 'embedded' ? this.removeStandAlone(temp) : temp;
|
|
2549
2551
|
this.setState({schema: temp, isSchemaChanged: true, loadingStatus: this.state.loadingStatus + 1}, () => {
|
|
@@ -1128,7 +1128,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1128
1128
|
{template._id === this.state.hoveredItem ? <CapButton onClick={(e) => this.handleEditClick(e, template._id)} className="edit-button" type="secondary">{type === 'embedded' ? this.props.intl.formatMessage(messages.selectButton) : this.props.intl.formatMessage(messages.editButton)}</CapButton> : ''}
|
|
1129
1129
|
{template._id === this.state.hoveredItem ? <CapButton onClick={() => this.handlePreviewClick(template)} className="preview-button" type="cancel">{this.props.intl.formatMessage(messages.previewButton)}</CapButton> : ''}
|
|
1130
1130
|
</div>);
|
|
1131
|
-
} else if (this.state.channel.toLowerCase() === 'line') {
|
|
1131
|
+
} else if (this.state.channel.toLowerCase() === 'line' && template.type.toLowerCase() === 'line') {
|
|
1132
1132
|
//content = template.versions.base.messages[0].Text;
|
|
1133
1133
|
content = {
|
|
1134
1134
|
bodyText: template.versions.base.content.messages[0].text ? template.versions.base.content.messages[0].text : '',
|
package/package.json
CHANGED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* DateFilter
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
|
|
9
|
+
import React from 'react';
|
|
10
|
+
// import styled from 'styled-components';
|
|
11
|
+
|
|
12
|
+
import { FormattedMessage } from 'react-intl';
|
|
13
|
+
import { Popup, Input, Button, Grid, Checkbox, Dimmer, Loader } from 'semantic-ui-react';
|
|
14
|
+
import DateRange from 'components/DateRange';
|
|
15
|
+
import moment from 'moment';
|
|
16
|
+
import _ from 'lodash';
|
|
17
|
+
import messages from './messages';
|
|
18
|
+
|
|
19
|
+
class DateFilter extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
20
|
+
constructor(props) {
|
|
21
|
+
super(props);
|
|
22
|
+
this.state = {
|
|
23
|
+
selectedDateRange: this.props.selectedDateRange,
|
|
24
|
+
showChartCompareOptions: this.props.isCompareSelected,
|
|
25
|
+
compareDateRange: this.props.compareDateRange,
|
|
26
|
+
selectedDateText: '',
|
|
27
|
+
isDateSelectorOpen: false,
|
|
28
|
+
loading: this.props.loading,
|
|
29
|
+
openCustomDatePicker: false,
|
|
30
|
+
compareCustomDateSelected: false,
|
|
31
|
+
customDateSelected: false,
|
|
32
|
+
pastStateData: {},
|
|
33
|
+
componentWidth: 270,
|
|
34
|
+
};
|
|
35
|
+
this.handleToggleDateSelector = this.handleToggleDateSelector.bind(this);
|
|
36
|
+
this.renderDateSelector = this.renderDateSelector.bind(this);
|
|
37
|
+
this.handleDateTypeClick = this.handleDateTypeClick.bind(this);
|
|
38
|
+
this.printSelectedDate = this.printSelectedDate.bind(this);
|
|
39
|
+
this.handleCancel = this.handleCancel.bind(this);
|
|
40
|
+
this.handleChartCompareToggle = this.handleChartCompareToggle.bind(this);
|
|
41
|
+
this.handleCompareDateChange = this.handleCompareDateChange.bind(this);
|
|
42
|
+
this.handleCustomDatePickerCancel = this.handleCustomDatePickerCancel.bind(this);
|
|
43
|
+
this.handleDatePickerApply = this.handleDatePickerApply.bind(this);
|
|
44
|
+
this.compareDateValueSetting = this.compareDateValueSetting.bind(this);
|
|
45
|
+
this.handleApply = this.handleApply.bind(this);
|
|
46
|
+
this.restoreInitialState = this.restoreInitialState.bind(this);
|
|
47
|
+
this.storeInitialState = this.storeInitialState.bind(this);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
componentWillMount() {
|
|
51
|
+
const dateText = this.printSelectedDate(this.state.selectedDateRange.startDate, this.state.selectedDateRange.endDate, this.state.selectedDateRange.dateType);
|
|
52
|
+
this.setState({ selectedDateText: dateText });
|
|
53
|
+
this.setState({ loading: false });
|
|
54
|
+
this.storeInitialState();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
componentDidMount() {
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
componentWillReceiveProps(nextProp) {
|
|
61
|
+
this.setState({ selectedDateRange: nextProp.selectedDateRange, showChartCompareOptions: nextProp.isCompareSelected }, () => {
|
|
62
|
+
let dateText = this.printSelectedDate(this.state.selectedDateRange.startDate, this.state.selectedDateRange.endDate, this.state.selectedDateRange.dateType);
|
|
63
|
+
if (this.state.showChartCompareOptions) {
|
|
64
|
+
this.setState({ componentWidth: 450 });
|
|
65
|
+
dateText = `${dateText} vs ${this.printSelectedDate(this.state.compareDateRange.startDate, this.state.compareDateRange.endDate, this.state.compareDateRange.dateType, true)}`;
|
|
66
|
+
} else {
|
|
67
|
+
this.setState({ componentWidth: 270 });
|
|
68
|
+
}
|
|
69
|
+
this.setState({ selectedDateText: dateText });
|
|
70
|
+
});
|
|
71
|
+
this.storeInitialState();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
storeInitialState() {
|
|
75
|
+
const stateData = _.cloneDeep(this.state);
|
|
76
|
+
const tmpState = {
|
|
77
|
+
selectedDateRange: stateData.selectedDateRange,
|
|
78
|
+
showChartCompareOptions: stateData.showChartCompareOptions,
|
|
79
|
+
compareDateRange: stateData.compareDateRange,
|
|
80
|
+
};
|
|
81
|
+
this.setState({ pastStateData: tmpState });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
handleToggleDateSelector() {
|
|
85
|
+
this.setState({ isDateSelectorOpen: !this.state.isDateSelectorOpen });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
handleDateTypeClick(specifier) {
|
|
89
|
+
const date = this.state.selectedDateRange;
|
|
90
|
+
if (specifier !== 'custom') {
|
|
91
|
+
date.dateType = specifier;
|
|
92
|
+
if (specifier === 'week') {
|
|
93
|
+
date.startDate = moment().isoWeekday(1);
|
|
94
|
+
} else {
|
|
95
|
+
date.startDate = moment().startOf(specifier);
|
|
96
|
+
}
|
|
97
|
+
date.endDate = moment();
|
|
98
|
+
this.setState({ selectedDateRange: date }, () => {
|
|
99
|
+
if (this.state.showChartCompareOptions) {
|
|
100
|
+
this.compareDateValueSetting(specifier);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
this.setState({ customDateSelected: true, openCustomDatePicker: true });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
printSelectedDate(startDate, endDate, specifier, isCompare) {
|
|
109
|
+
let specifierType = '';
|
|
110
|
+
if (isCompare) {
|
|
111
|
+
if (specifier === 'week') {
|
|
112
|
+
specifierType = 'Previous Week';
|
|
113
|
+
} else if (specifier === 'month') {
|
|
114
|
+
specifierType = 'Previous Month';
|
|
115
|
+
} else if (specifier === 'year') {
|
|
116
|
+
specifierType = 'Previous Year';
|
|
117
|
+
} else {
|
|
118
|
+
specifierType = 'Custom';
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (!isCompare) {
|
|
122
|
+
if (specifier === 'week') {
|
|
123
|
+
specifierType = 'WTD';
|
|
124
|
+
} else if (specifier === 'month') {
|
|
125
|
+
specifierType = 'MTD';
|
|
126
|
+
} else if (specifier === 'year') {
|
|
127
|
+
specifierType = 'YTD';
|
|
128
|
+
} else {
|
|
129
|
+
specifierType = 'Custom';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let tmpDateString = '';
|
|
134
|
+
if (moment(startDate).year() === moment(endDate).year()) {
|
|
135
|
+
tmpDateString = `${specifierType} ( ${moment(startDate).format('MMM D').toString()} - ${moment(endDate).format('MMM D YYYY').toString()} )`;
|
|
136
|
+
} else {
|
|
137
|
+
tmpDateString = `${specifierType} ( ${moment(startDate).format('MMM D YYYY').toString()} - ${moment(endDate).format('MMM D YYYY').toString()} )`;
|
|
138
|
+
}
|
|
139
|
+
return tmpDateString;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
handleCancel() {
|
|
143
|
+
this.setState({ isDateSelectorOpen: false });
|
|
144
|
+
if (this.props.handleCancel !== undefined) {
|
|
145
|
+
this.props.handleCancel();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Need to improve this function
|
|
149
|
+
this.restoreInitialState();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
compareDateValueSetting(specifier) {
|
|
153
|
+
const dateRange = (this.state.compareDateRange) ? this.state.compareDateRange : _.cloneDeep(this.state.selectedDateRange);
|
|
154
|
+
if (specifier === 'week') {
|
|
155
|
+
dateRange.startDate = moment(this.state.selectedDateRange.startDate).subtract(7, 'days');
|
|
156
|
+
dateRange.endDate = moment(this.state.selectedDateRange.endDate).subtract(7, 'days');
|
|
157
|
+
dateRange.dateType = specifier;
|
|
158
|
+
} else if (specifier === 'month') {
|
|
159
|
+
dateRange.startDate = moment(this.state.selectedDateRange.startDate).subtract(1, 'months');
|
|
160
|
+
dateRange.endDate = moment(this.state.selectedDateRange.endDate).subtract(1, 'months');
|
|
161
|
+
dateRange.dateType = specifier;
|
|
162
|
+
} else if (specifier === 'year' || specifier === 'custom') {
|
|
163
|
+
dateRange.startDate = moment(this.state.selectedDateRange.startDate).subtract(1, 'years');
|
|
164
|
+
dateRange.endDate = moment(this.state.selectedDateRange.endDate).subtract(1, 'years');
|
|
165
|
+
dateRange.dateType = specifier;
|
|
166
|
+
}
|
|
167
|
+
this.setState({ compareDateRange: dateRange });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
handleChartCompareToggle() {
|
|
171
|
+
this.setState({ showChartCompareOptions: !this.state.showChartCompareOptions });
|
|
172
|
+
const compareDateType = (this.state.compareDateRange) ? this.state.compareDateRange.dateType : this.state.selectedDateRange.dateType;
|
|
173
|
+
this.compareDateValueSetting(compareDateType);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
handleCompareDateChange(specifier) {
|
|
177
|
+
if (specifier === 'custom') {
|
|
178
|
+
this.setState({ compareCustomDateSelected: true, openCustomDatePicker: true });
|
|
179
|
+
} else {
|
|
180
|
+
this.compareDateValueSetting(specifier);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
handleCustomDatePickerCancel(e) {
|
|
185
|
+
if (e) {
|
|
186
|
+
e.preventDefault();
|
|
187
|
+
}
|
|
188
|
+
this.setState({ customDateSelected: false });
|
|
189
|
+
this.setState({ compareCustomDateSelected: false });
|
|
190
|
+
this.setState({ openCustomDatePicker: false });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
handleDatePickerApply(startDate, endDate, dateType) {
|
|
194
|
+
if (this.state.customDateSelected) {
|
|
195
|
+
const dateRange = _.cloneDeep(this.state.selectedDateRange);
|
|
196
|
+
dateRange.startDate = startDate;
|
|
197
|
+
dateRange.endDate = endDate;
|
|
198
|
+
dateRange.dateType = dateType;
|
|
199
|
+
this.setState({ selectedDateRange: dateRange });
|
|
200
|
+
this.setState({ customDateSelected: false });
|
|
201
|
+
} else {
|
|
202
|
+
const dateRange = _.cloneDeep(this.state.compareDateRange);
|
|
203
|
+
dateRange.startDate = startDate;
|
|
204
|
+
dateRange.endDate = endDate;
|
|
205
|
+
dateRange.dateType = dateType;
|
|
206
|
+
this.setState({ compareDateRange: dateRange });
|
|
207
|
+
this.setState({ compareCustomDateSelected: false });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
handleApply() {
|
|
212
|
+
let dateText = this.printSelectedDate(this.state.selectedDateRange.startDate, this.state.selectedDateRange.endDate, this.state.selectedDateRange.dateType);
|
|
213
|
+
if (this.state.showChartCompareOptions) {
|
|
214
|
+
this.setState({ componentWidth: 450 });
|
|
215
|
+
dateText = `${dateText} vs ${this.printSelectedDate(this.state.compareDateRange.startDate, this.state.compareDateRange.endDate, this.state.compareDateRange.dateType, true)}`;
|
|
216
|
+
} else {
|
|
217
|
+
this.setState({ componentWidth: 270 });
|
|
218
|
+
}
|
|
219
|
+
this.setState({ selectedDateText: dateText });
|
|
220
|
+
this.setState({ isDateSelectorOpen: false });
|
|
221
|
+
this.props.handleApply(this.state.selectedDateRange, this.state.showChartCompareOptions, this.state.compareDateRange);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
restoreInitialState() {
|
|
225
|
+
this.setState({ selectedDateRange: this.state.pastStateData.selectedDateRange });
|
|
226
|
+
this.setState({ compareDateRange: this.state.pastStateData.compareDateRange, showChartCompareOptions: this.state.pastStateData.showChartCompareOptions });
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
renderDateSelector() {
|
|
230
|
+
const dateType = this.state.selectedDateRange.dateType;
|
|
231
|
+
return (
|
|
232
|
+
<div className="date-filter-wrapper">
|
|
233
|
+
{ this.state.loading ? <Dimmer active inverted className={'hide'}><Loader inverted><FormattedMessage {...messages.loaderMessage} /> </Loader></Dimmer> :
|
|
234
|
+
<Grid>
|
|
235
|
+
<Grid.Row className={this.state.openCustomDatePicker ? 'hide' : ''}>
|
|
236
|
+
<Grid.Column width={16}>
|
|
237
|
+
<Button.Group fluid className="btn-group till-date">
|
|
238
|
+
<Button className={dateType === 'week' ? 'active' : ''} onClick={() => this.handleDateTypeClick('week')}>WTD</Button>
|
|
239
|
+
<Button className={dateType === 'month' ? 'active' : ''} onClick={() => this.handleDateTypeClick('month')}>MTD</Button>
|
|
240
|
+
<Button className={dateType === 'year' ? 'active' : ''} onClick={() => this.handleDateTypeClick('year')}>YTD</Button>
|
|
241
|
+
<Button className={dateType === 'custom' ? 'active' : ''} onClick={() => this.handleDateTypeClick('custom')}>Custom</Button>
|
|
242
|
+
</Button.Group>
|
|
243
|
+
</Grid.Column>
|
|
244
|
+
<Grid.Column width={16} className="selectedDateText">
|
|
245
|
+
{this.printSelectedDate(this.state.selectedDateRange.startDate, this.state.selectedDateRange.endDate, this.state.selectedDateRange.dateType)}
|
|
246
|
+
{dateType === 'custom' ? <span className="editSelectedDate" onClick={() => this.handleDateTypeClick('custom')}><FormattedMessage {...messages.editText} /></span> : ''}
|
|
247
|
+
</Grid.Column>
|
|
248
|
+
</Grid.Row>
|
|
249
|
+
<Grid.Row className={this.state.openCustomDatePicker ? 'hide' : 'compareDateToggle'}>
|
|
250
|
+
<Grid.Column width={16}>
|
|
251
|
+
<Checkbox className={!this.props.compareMode ? 'hide' : 'dateCompareCheckbox'} checked={this.state.showChartCompareOptions} label="Compare" onClick={this.handleChartCompareToggle} />
|
|
252
|
+
</Grid.Column>
|
|
253
|
+
</Grid.Row>
|
|
254
|
+
{ this.state.showChartCompareOptions ?
|
|
255
|
+
<Grid.Row className={!this.state.openCustomDatePicker ? '' : 'hide'}>
|
|
256
|
+
<Grid.Column width={16}>
|
|
257
|
+
<Button.Group fluid className="btn-group till-date">
|
|
258
|
+
{dateType !== 'week' ? '' :
|
|
259
|
+
<Button className={this.state.compareDateRange.dateType !== 'week' ? '' : 'active'} onClick={() => this.handleCompareDateChange('week')}>Previous Week</Button> }
|
|
260
|
+
{dateType !== 'month' ? '' :
|
|
261
|
+
<Button className={this.state.compareDateRange.dateType !== 'month' ? '' : 'active'} onClick={() => this.handleCompareDateChange('month')}>Previous Month</Button>}
|
|
262
|
+
<Button className={this.state.compareDateRange.dateType === 'year' ? 'active' : ''} onClick={() => this.handleCompareDateChange('year')}>Previous Year</Button>
|
|
263
|
+
<Button className={this.state.compareDateRange.dateType === 'custom' ? 'active' : ''} onClick={() => this.handleCompareDateChange('custom')}>Custom</Button>
|
|
264
|
+
</Button.Group>
|
|
265
|
+
</Grid.Column>
|
|
266
|
+
<Grid.Column width={16} className="selectedDateText">
|
|
267
|
+
{this.printSelectedDate(this.state.compareDateRange.startDate, this.state.compareDateRange.endDate, this.state.compareDateRange.dateType, true)}
|
|
268
|
+
{this.state.compareDateRange.dateType === 'custom' ? <span className="editSelectedDate" onClick={() => this.handleCompareDateChange('custom')}><FormattedMessage {...messages.editText} /></span> : ''}
|
|
269
|
+
</Grid.Column>
|
|
270
|
+
</Grid.Row>
|
|
271
|
+
: ''
|
|
272
|
+
}
|
|
273
|
+
<Grid.Row className={this.state.openCustomDatePicker ? 'hide' : ''}>
|
|
274
|
+
<Grid.Column width={16}>
|
|
275
|
+
<Button primary onClick={this.handleApply}>Apply</Button>
|
|
276
|
+
<Button basic onClick={this.handleCancel}>Cancel</Button>
|
|
277
|
+
</Grid.Column>
|
|
278
|
+
</Grid.Row>
|
|
279
|
+
|
|
280
|
+
{ this.state.customDateSelected ?
|
|
281
|
+
<Grid.Row className={!this.state.openCustomDatePicker ? 'hide' : ''}>
|
|
282
|
+
<Grid.Column className="selectDateRangeTitle" width={16}>
|
|
283
|
+
<a href="" className="backButton" onClick={this.handleCustomDatePickerCancel}><i className="material-icons">keyboard_backspace</i></a>
|
|
284
|
+
<span className="dateRangeTitle">Select Date Range</span>
|
|
285
|
+
</Grid.Column>
|
|
286
|
+
<Grid.Column width={16} className="dateRangeWrapper">
|
|
287
|
+
<DateRange prevSelectedDate={this.state.selectedDateRange} handleDatePickerApply={this.handleDatePickerApply} handleDatePickerCancel={this.handleCustomDatePickerCancel} />
|
|
288
|
+
</Grid.Column>
|
|
289
|
+
{/* { this.state.showChartCompareOptions ? <Grid.Column width={16}>
|
|
290
|
+
{this.printSelectedDate(this.props.selectedDateRange.startDate, this.props.selectedDateRange.endDate, this.state.selectedDateRange.dateType)} vs
|
|
291
|
+
</Grid.Column> : '' } */}
|
|
292
|
+
</Grid.Row> : ''
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
{ this.state.compareCustomDateSelected ?
|
|
296
|
+
<Grid.Row className={!this.state.openCustomDatePicker ? 'hide' : ''}>
|
|
297
|
+
<Grid.Column width={16}>
|
|
298
|
+
<a href="" className="backButton" onClick={this.handleCustomDatePickerCancel}><i className="material-icons">keyboard_backspace</i></a>
|
|
299
|
+
<span className="dateRangeTitle">Select Date Range</span>
|
|
300
|
+
</Grid.Column>
|
|
301
|
+
<Grid.Column width={16}>
|
|
302
|
+
{this.printSelectedDate(this.state.selectedDateRange.startDate, this.state.selectedDateRange.endDate, this.state.selectedDateRange.dateType)} vs
|
|
303
|
+
</Grid.Column>
|
|
304
|
+
<Grid.Column width={16} className="dateRangeWrapper">
|
|
305
|
+
<DateRange prevSelectedDate={this.state.compareDateRange} handleDatePickerApply={this.handleDatePickerApply} handleDatePickerCancel={this.handleCustomDatePickerCancel} />
|
|
306
|
+
</Grid.Column>
|
|
307
|
+
</Grid.Row> : ''
|
|
308
|
+
}
|
|
309
|
+
</Grid>}
|
|
310
|
+
</div>
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
render() {
|
|
315
|
+
const { isDateSelectorOpen } = this.state;
|
|
316
|
+
// const loading = this.state.loading;
|
|
317
|
+
return (
|
|
318
|
+
<span>
|
|
319
|
+
<Popup
|
|
320
|
+
trigger={
|
|
321
|
+
<Input
|
|
322
|
+
id="compareDate"
|
|
323
|
+
style={{ width: `${this.state.componentWidth}px` }}
|
|
324
|
+
readOnly
|
|
325
|
+
icon="caret down"
|
|
326
|
+
value={this.state.selectedDateText}
|
|
327
|
+
/>
|
|
328
|
+
}
|
|
329
|
+
content={this.renderDateSelector()}
|
|
330
|
+
on="click"
|
|
331
|
+
open={isDateSelectorOpen}
|
|
332
|
+
onOpen={this.handleToggleDateSelector}
|
|
333
|
+
/>
|
|
334
|
+
</span>
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
DateFilter.propTypes = {
|
|
340
|
+
selectedDateRange: PropTypes.object.isRequired,
|
|
341
|
+
compareMode: PropTypes.bool,
|
|
342
|
+
compareDateRange: PropTypes.object,
|
|
343
|
+
isCompareSelected: PropTypes.bool,
|
|
344
|
+
handleApply: PropTypes.func.isRequired,
|
|
345
|
+
handleCancel: PropTypes.func,
|
|
346
|
+
loading: PropTypes.bool,
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
export default DateFilter;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* DateFilter Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the DateFilter component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
export default defineMessages({
|
|
9
|
+
loaderMessage: {
|
|
10
|
+
id: 'reon.components.DateFilter.loaderMessage',
|
|
11
|
+
defaultMessage: 'Fetching Data',
|
|
12
|
+
},
|
|
13
|
+
editText: {
|
|
14
|
+
id: 'reon.components.DateFilter.editText',
|
|
15
|
+
defaultMessage: 'Edit',
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// import React from 'react';
|
|
2
|
+
// import { shallow } from 'enzyme';
|
|
3
|
+
//
|
|
4
|
+
// import moment from 'moment';
|
|
5
|
+
// import DateFilter from '../index';
|
|
6
|
+
|
|
7
|
+
// describe('<DateFilter />', () => {
|
|
8
|
+
// it('Expect to have unit tests specified', () => {
|
|
9
|
+
// expect(true).toEqual(false);
|
|
10
|
+
// });
|
|
11
|
+
// it('Expect to have selectDateRange Prop', () => {
|
|
12
|
+
// const wrapper = shallow(<DateFilter selectedDateRange={moment()} />);
|
|
13
|
+
// expect(wrapper.props().selectedDateRange).toEqual(moment());
|
|
14
|
+
// });
|
|
15
|
+
// });
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* DateRange
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
|
|
9
|
+
import React from 'react';
|
|
10
|
+
// import styled from 'styled-components';
|
|
11
|
+
|
|
12
|
+
import { FormattedMessage } from 'react-intl';
|
|
13
|
+
import { Grid, Button } from 'semantic-ui-react';
|
|
14
|
+
|
|
15
|
+
import DatePicker from 'react-datepicker';
|
|
16
|
+
import 'react-datepicker/dist/react-datepicker.css';
|
|
17
|
+
|
|
18
|
+
import moment from 'moment';
|
|
19
|
+
|
|
20
|
+
class DateRange extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
21
|
+
constructor(props) {
|
|
22
|
+
super(props);
|
|
23
|
+
this.state = {
|
|
24
|
+
startDate: this.props.prevSelectedDate.startDate,
|
|
25
|
+
endDate: this.props.prevSelectedDate.endDate,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
this.handleChangeStart = this.handleChangeStart.bind(this);
|
|
29
|
+
this.handleChangeEnd = this.handleChangeEnd.bind(this);
|
|
30
|
+
this.closeAndUpdate = this.closeAndUpdate.bind(this);
|
|
31
|
+
this.closeAndCancel = this.closeAndCancel.bind(this);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
handleChangeStart(date) {
|
|
35
|
+
this.setState({ startDate: date });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
handleChangeEnd(date) {
|
|
39
|
+
this.setState({ endDate: date });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
closeAndUpdate() {
|
|
43
|
+
this.props.handleDatePickerApply(this.state.startDate, this.state.endDate, 'custom');
|
|
44
|
+
this.props.handleDatePickerCancel();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
closeAndCancel() {
|
|
48
|
+
this.props.handleDatePickerCancel();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
render() {
|
|
52
|
+
const { startDate, endDate } = this.state;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<Grid className="dateRangeWrapper" columns={2}>
|
|
56
|
+
<Grid.Row className="selectedDateTitleWrapper">
|
|
57
|
+
<Grid.Column style={{ paddingLeft: 0, paddingBottom: `${8}px` }}>
|
|
58
|
+
<span className="selectedDateTitle">From</span>
|
|
59
|
+
<input className="selectedDateRange" type="text" readOnly defaultValue={moment(startDate).format('MM/DD/YYYY').toString()} />
|
|
60
|
+
<i className="calenderIcon material-icons">today</i>
|
|
61
|
+
</Grid.Column>
|
|
62
|
+
<Grid.Column style={{ paddingLeft: 0 }}>
|
|
63
|
+
<span className="selectedDateTitle">To</span>
|
|
64
|
+
<input className="selectedDateRange" readOnly type="text" defaultValue={moment(endDate).format('MM/DD/YYYY').toString()} />
|
|
65
|
+
<i className="calenderIcon material-icons">today</i>
|
|
66
|
+
</Grid.Column>
|
|
67
|
+
</Grid.Row>
|
|
68
|
+
<Grid.Row style={{ paddingTop: 0, paddingBottom: `${2}px` }}>
|
|
69
|
+
<Grid.Column style={{ paddingLeft: 0 }}>
|
|
70
|
+
<DatePicker
|
|
71
|
+
inline
|
|
72
|
+
selected={startDate}
|
|
73
|
+
startDate={startDate}
|
|
74
|
+
endDate={endDate}
|
|
75
|
+
onChange={this.handleChangeStart}
|
|
76
|
+
showMonthDropdown
|
|
77
|
+
showYearDropdown
|
|
78
|
+
dropdownMode="select"
|
|
79
|
+
/>
|
|
80
|
+
</Grid.Column>
|
|
81
|
+
<Grid.Column style={{ paddingLeft: 0 }}>
|
|
82
|
+
<DatePicker
|
|
83
|
+
inline
|
|
84
|
+
selected={endDate}
|
|
85
|
+
startDate={startDate}
|
|
86
|
+
endDate={endDate}
|
|
87
|
+
minDate={startDate}
|
|
88
|
+
maxDate={moment()}
|
|
89
|
+
onChange={this.handleChangeEnd}
|
|
90
|
+
showMonthDropdown
|
|
91
|
+
showYearDropdown
|
|
92
|
+
dropdownMode="select"
|
|
93
|
+
/>
|
|
94
|
+
</Grid.Column>
|
|
95
|
+
</Grid.Row>
|
|
96
|
+
<Grid.Row>
|
|
97
|
+
<Grid.Column width={16} style={{ paddingLeft: 0 }}>
|
|
98
|
+
<Button onClick={this.closeAndUpdate} className="btn-primary" floated="left"><FormattedMessage id="customdatepicker.done" defaultMessage="Done" /></Button>
|
|
99
|
+
<Button onClick={this.closeAndCancel} className="btn-secondary" floated="left"><FormattedMessage id="customdatepicker.cancel" defaultMessage="Cancel" /></Button>
|
|
100
|
+
</Grid.Column>
|
|
101
|
+
</Grid.Row>
|
|
102
|
+
</Grid>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
DateRange.propTypes = {
|
|
108
|
+
prevSelectedDate: PropTypes.object.isRequired,
|
|
109
|
+
handleDatePickerCancel: PropTypes.func,
|
|
110
|
+
handleDatePickerApply: PropTypes.func,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export default DateRange;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* DateRange Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the DateRange component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
export default defineMessages({
|
|
9
|
+
header: {
|
|
10
|
+
id: 'app.components.DateRange.header',
|
|
11
|
+
defaultMessage: 'This is the DateRange component !',
|
|
12
|
+
},
|
|
13
|
+
});
|
|
@@ -30,6 +30,14 @@ const deviceAspectRatio = {
|
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
class EmailMobilePreview extends React.Component {
|
|
33
|
+
static getDerivedStateFromProps(props) {
|
|
34
|
+
if (props.showAllDevices) {
|
|
35
|
+
return {
|
|
36
|
+
showAllDevices: true,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
33
41
|
constructor() {
|
|
34
42
|
super();
|
|
35
43
|
this.state = {
|
|
@@ -115,6 +123,7 @@ EmailMobilePreview.propTypes = {
|
|
|
115
123
|
|
|
116
124
|
EmailMobilePreview.defaultProps = {
|
|
117
125
|
showDeviceSelection: true,
|
|
126
|
+
showAllDevices: false,
|
|
118
127
|
};
|
|
119
128
|
|
|
120
129
|
const mapStateToProps = (state, props) => createStructuredSelector({
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import PropTypes from 'prop-types';
|
|
9
9
|
import styled from 'styled-components';
|
|
10
|
-
import { isEmpty, forEach } from 'lodash';
|
|
10
|
+
import { isEmpty, forEach, find } from 'lodash';
|
|
11
11
|
import { loadItem } from 'services/localStorageApi';
|
|
12
12
|
import { intlShape, injectIntl } from 'react-intl';
|
|
13
13
|
import TopBar from '../TopBar';
|
|
@@ -104,9 +104,10 @@ class NavigationBar extends React.Component {
|
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
getProductsList = () => {
|
|
107
|
+
const { campaignOrgV2Status } = this.props;
|
|
107
108
|
const { currentOrgDetails } = this.props.userData;
|
|
108
109
|
const productsList = [];
|
|
109
|
-
if (currentOrgDetails) {
|
|
110
|
+
if (!isEmpty(currentOrgDetails)) {
|
|
110
111
|
forEach(currentOrgDetails.module_details, (module) => {
|
|
111
112
|
if (module.name.toLowerCase() !== PRODUCT_MASTERS) {
|
|
112
113
|
productsList.push({
|
|
@@ -116,14 +117,22 @@ class NavigationBar extends React.Component {
|
|
|
116
117
|
});
|
|
117
118
|
}
|
|
118
119
|
});
|
|
120
|
+
//below changes are temporary and should be fixed once we get correct modules list
|
|
121
|
+
//changing campaigns module name to engage+
|
|
122
|
+
if ( !campaignOrgV2Status ) {
|
|
123
|
+
const campaignsModule = find(productsList, ['value', 'campaigns']);
|
|
124
|
+
campaignsModule.value = 'Engage+';
|
|
125
|
+
}
|
|
126
|
+
//adding insights+ to module list
|
|
127
|
+
productsList.push({
|
|
128
|
+
value: 'Insights+',
|
|
129
|
+
url: 'analytics/v2/',
|
|
130
|
+
key: 'analytics/v2/',
|
|
131
|
+
});
|
|
119
132
|
}
|
|
120
133
|
return productsList;
|
|
121
134
|
};
|
|
122
135
|
|
|
123
|
-
setDefaultSelectedProduct = () => {
|
|
124
|
-
const { intl, campaignOrgV2Status } = this.props;
|
|
125
|
-
return campaignOrgV2Status ? intl.formatMessage(messages.selectedProductDefaultEngage) : intl.formatMessage(messages.selectedProductDefaultCampaigns);
|
|
126
|
-
}
|
|
127
136
|
getTopbarIcons = () => [
|
|
128
137
|
{
|
|
129
138
|
iconType: 'help',
|
|
@@ -181,6 +190,7 @@ class NavigationBar extends React.Component {
|
|
|
181
190
|
topbarMenuData,
|
|
182
191
|
loggedIn,
|
|
183
192
|
type,
|
|
193
|
+
intl,
|
|
184
194
|
} = this.props;
|
|
185
195
|
const productsList = this.getProductsList();
|
|
186
196
|
const proxyOrgList = this.getProxyOrgList();
|
|
@@ -195,7 +205,8 @@ class NavigationBar extends React.Component {
|
|
|
195
205
|
<TopBar
|
|
196
206
|
productsList={productsList}
|
|
197
207
|
selectedProduct={
|
|
198
|
-
selectedProduct ||
|
|
208
|
+
selectedProduct ||
|
|
209
|
+
intl.formatMessage(messages.selectedProductDefault)
|
|
199
210
|
}
|
|
200
211
|
handleProductChange={this.handleProductChange}
|
|
201
212
|
proxyOrgList={proxyOrgList}
|
|
@@ -13,12 +13,8 @@ export default defineMessages({
|
|
|
13
13
|
id: `${scope}.header`,
|
|
14
14
|
defaultMessage: 'This is the NavigationBar component!',
|
|
15
15
|
},
|
|
16
|
-
|
|
17
|
-
id: `${scope}.
|
|
16
|
+
selectedProductDefault: {
|
|
17
|
+
id: `${scope}.selectedProductDefault`,
|
|
18
18
|
defaultMessage: 'Engage+',
|
|
19
19
|
},
|
|
20
|
-
selectedProductDefaultCampaigns: {
|
|
21
|
-
id: `${scope}.selectedProductDefaultCampaigns`,
|
|
22
|
-
defaultMessage: 'Campaigns',
|
|
23
|
-
},
|
|
24
20
|
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.pageHeader{
|
|
2
|
+
.pageHeader-wrapper{
|
|
3
|
+
padding-top: 8px;
|
|
4
|
+
padding-bottom: 8px;
|
|
5
|
+
|
|
6
|
+
.title-container {
|
|
7
|
+
padding-left: 0px !important;
|
|
8
|
+
|
|
9
|
+
.title {
|
|
10
|
+
font-size: 24px;
|
|
11
|
+
line-height: 32px;
|
|
12
|
+
color: #323B4E;
|
|
13
|
+
font-family: 'Proxima-Nova';
|
|
14
|
+
font-weight: 600;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
.action-buttons{
|
|
18
|
+
text-align: right;
|
|
19
|
+
padding-right: 0 !important;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
// import styled from 'styled-components';
|
|
4
|
+
|
|
5
|
+
import { Grid } from 'semantic-ui-react';
|
|
6
|
+
import './_pageHeader.scss';
|
|
7
|
+
|
|
8
|
+
// import { FormattedMessage } from 'react-intl';
|
|
9
|
+
// import messages from './messages';
|
|
10
|
+
|
|
11
|
+
class PageHeader extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
12
|
+
render() {
|
|
13
|
+
return (
|
|
14
|
+
<Grid className="pageHeader">
|
|
15
|
+
<Grid.Row className="pageHeader-wrapper">
|
|
16
|
+
<Grid.Column width={8} className="title-container">
|
|
17
|
+
<h2 className="title">{this.props.pageHeading}</h2>
|
|
18
|
+
</Grid.Column>
|
|
19
|
+
<Grid.Column className="action-buttons" width={8}>
|
|
20
|
+
{this.props.actionComponents}
|
|
21
|
+
</Grid.Column>
|
|
22
|
+
</Grid.Row>
|
|
23
|
+
</Grid>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
PageHeader.propTypes = {
|
|
29
|
+
// Need Formatted Message in pageHeading Props
|
|
30
|
+
pageHeading: PropTypes.oneOfType([
|
|
31
|
+
PropTypes.element,
|
|
32
|
+
PropTypes.string,
|
|
33
|
+
]),
|
|
34
|
+
actionComponents: PropTypes.element,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default PageHeader;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* PageHeader Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the PageHeader component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
export default defineMessages({
|
|
9
|
+
header: {
|
|
10
|
+
id: 'app.components.PageHeader.header',
|
|
11
|
+
defaultMessage: 'This is the PageHeader component !',
|
|
12
|
+
},
|
|
13
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#cap-sidebar{
|
|
2
|
+
padding: 8px 0 8px 0;
|
|
3
|
+
max-width: 200px;
|
|
4
|
+
min-width: 200px;
|
|
5
|
+
width: 16%;
|
|
6
|
+
overflow-y: hidden;
|
|
7
|
+
// height: 100%;
|
|
8
|
+
// display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
|
9
|
+
// display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
|
10
|
+
// display: -ms-flexbox; /* TWEENER - IE 10 */
|
|
11
|
+
// display: -webkit-flex; /* NEW - Chrome */
|
|
12
|
+
// display: flex;
|
|
13
|
+
overflow-x: hidden;
|
|
14
|
+
.header.item{
|
|
15
|
+
padding-left: 8px !important;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.sidebar-container {
|
|
20
|
+
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
|
21
|
+
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
|
22
|
+
display: -ms-flexbox; /* TWEENER - IE 10 */
|
|
23
|
+
display: -webkit-flex; /* NEW - Chrome */
|
|
24
|
+
display: flex;
|
|
25
|
+
flex: 1;
|
|
26
|
+
-webkit-box-flex: 1;
|
|
27
|
+
-webkit-flex: 1;
|
|
28
|
+
-ms-flex: 1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.sidebar-accordian .content .item.menu-item:hover{
|
|
32
|
+
margin-left: 0 !important;
|
|
33
|
+
text-indent: 0 !important;
|
|
34
|
+
}
|
|
35
|
+
.sidebar-accordian .content .item.menu-item.selected{
|
|
36
|
+
margin-left: 0 !important;
|
|
37
|
+
text-indent: 0 !important;
|
|
38
|
+
}
|
|
39
|
+
.ui.accordion.sidebar-accordian .content .item.selected{
|
|
40
|
+
background: #F2F3F7 !important;
|
|
41
|
+
padding-left: 40px !important;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.item.menu-item{
|
|
45
|
+
// margin-left: 0px;
|
|
46
|
+
padding-left: 40px !important;
|
|
47
|
+
border-left-width: 0 !important;
|
|
48
|
+
text-decoration: none;
|
|
49
|
+
}
|
|
50
|
+
.item.menu-item.selected{
|
|
51
|
+
border-left: 4px solid #2e89df !important;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.item.menu-item.assetItem{
|
|
55
|
+
padding-left: 28px !important;
|
|
56
|
+
line-height: 28px;
|
|
57
|
+
padding-top: 8px;
|
|
58
|
+
padding-bottom: 8px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.ui.accordion.sidebar-accordian {
|
|
62
|
+
padding-top: 8px !important;
|
|
63
|
+
margin-left: 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.ui.accordion.sidebar-accordian .title{
|
|
67
|
+
font-size: 12px !important;
|
|
68
|
+
line-height: 32px !important;
|
|
69
|
+
padding-top: 0 !important;
|
|
70
|
+
padding-bottom: 0 !important;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.sidebar-width {
|
|
74
|
+
// width: 200px !important;
|
|
75
|
+
max-width: 250px;
|
|
76
|
+
min-width: 190px;
|
|
77
|
+
width: 200px;
|
|
78
|
+
}
|
|
79
|
+
.module-menu-header {
|
|
80
|
+
padding-top: 8px!important;
|
|
81
|
+
line-height: 32px!important;
|
|
82
|
+
font-size: 16px!important;
|
|
83
|
+
margin-left: 0!important;
|
|
84
|
+
padding-left: 8px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// .searchbar {
|
|
88
|
+
// height: 32px;
|
|
89
|
+
// padding-left: 8px;
|
|
90
|
+
// }
|
|
91
|
+
|
|
92
|
+
.menu-header {
|
|
93
|
+
font-size: 12px!important;
|
|
94
|
+
line-height: 32px!important;
|
|
95
|
+
margin: 0!important;
|
|
96
|
+
padding: 0 0 0 8px!important;
|
|
97
|
+
width: 100%;
|
|
98
|
+
}
|
|
99
|
+
.menu-title {
|
|
100
|
+
flex: 0 0 90%!important;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.product-select-menu {
|
|
104
|
+
width: 100%;
|
|
105
|
+
padding-left: 2px;
|
|
106
|
+
background: #F2F3F7;
|
|
107
|
+
font-family: proxima-nova;
|
|
108
|
+
font-size: 16px !important;
|
|
109
|
+
font-weight: 600;
|
|
110
|
+
|
|
111
|
+
.ant-select-selection {
|
|
112
|
+
background: #F2F3F7;
|
|
113
|
+
border: none !important;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
// import styled from 'styled-components';
|
|
4
|
+
import { Accordion, Icon, Input, Button } from 'semantic-ui-react';
|
|
5
|
+
import { FormattedMessage } from 'react-intl';
|
|
6
|
+
import _ from 'lodash';
|
|
7
|
+
import { Link } from 'react-router';
|
|
8
|
+
import messages from './messages';
|
|
9
|
+
import './_sidebar.scss';
|
|
10
|
+
|
|
11
|
+
class Sidebar extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
12
|
+
constructor(props) {
|
|
13
|
+
super(props);
|
|
14
|
+
this.state = {
|
|
15
|
+
isOpen: false,
|
|
16
|
+
activeItem: '',
|
|
17
|
+
activeIndex: 0,
|
|
18
|
+
menuItems: this.props.menuData,
|
|
19
|
+
searchText: '',
|
|
20
|
+
visible: true,
|
|
21
|
+
};
|
|
22
|
+
this.handleItemClick = this.handleItemClick.bind(this);
|
|
23
|
+
this.handleTitleClick = this.handleTitleClick.bind(this);
|
|
24
|
+
this.handleSearch = this.handleSearch.bind(this);
|
|
25
|
+
this.toggleSideNav = this.toggleSideNav.bind(this);
|
|
26
|
+
this.getLinkElement = this.getLinkElement.bind(this);
|
|
27
|
+
this.selectActiveLinkFromUrl = this.selectActiveLinkFromUrl.bind(this);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
componentWillMount() {
|
|
31
|
+
this.selectActiveLinkFromUrl(this.props);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
componentWillReceiveProps(nextProp) {
|
|
35
|
+
this.selectActiveLinkFromUrl(nextProp);
|
|
36
|
+
this.setState({ menuItems: nextProp.menuData });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getAccordian(content, keyValue) {
|
|
40
|
+
return (<Accordion key={keyValue}>{content}</Accordion>);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getAccordionTitle(title) {
|
|
44
|
+
return (<Accordion.Title>
|
|
45
|
+
<div className="header item">
|
|
46
|
+
<Icon name="dropdown" /> {title}
|
|
47
|
+
</div>
|
|
48
|
+
</Accordion.Title>);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getAccordionContent(links, keyValue) {
|
|
52
|
+
return (<Accordion.Content key={keyValue}>{links}</Accordion.Content>);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getLinkElement(to, text, value, isExternal) {
|
|
56
|
+
const selectedItem = (value && value.trim().toLowerCase() === this.state.activeItem) ? 'selected' : '';
|
|
57
|
+
if (text.toLowerCase().includes(this.state.searchText.toLowerCase())) {
|
|
58
|
+
if (isExternal) {
|
|
59
|
+
return ((text.toLowerCase().includes(this.state.searchText.toLowerCase())) ? <a key={to} className={`item menu-item ${selectedItem}`} href={to}>{text}</a> : '');
|
|
60
|
+
}
|
|
61
|
+
return (
|
|
62
|
+
(text.toLowerCase().includes(this.state.searchText.toLowerCase())) ?
|
|
63
|
+
<Link to={to} className={`item menu-item ${selectedItem}`} onClick={this.handleItemClick} key={to} title={text}>{text}</Link>
|
|
64
|
+
: ''
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
selectActiveLinkFromUrl(props) {
|
|
71
|
+
const activeRoute = props.router.routes[props.router.routes.length - 1];
|
|
72
|
+
const activeRouteName = (activeRoute.name && activeRoute.name.trim().toLowerCase()) || '';
|
|
73
|
+
let selectedItem = '';
|
|
74
|
+
let selectedIndex = -1;
|
|
75
|
+
_.forEach(props.menuData, (menuItem, menuIndex) => {
|
|
76
|
+
if (menuItem.items && typeof menuItem.items === 'object') {
|
|
77
|
+
_.forEach(menuItem.items, (menuData) => {
|
|
78
|
+
// console.log('Menua Data ', menuData, activeRouteName, menuItem);
|
|
79
|
+
if ((menuItem.id && menuData.id.toLowerCase() === activeRouteName.toLowerCase()) || (menuData.value.toLowerCase() === activeRouteName.toLowerCase())) {
|
|
80
|
+
selectedIndex = menuIndex;
|
|
81
|
+
selectedItem = activeRouteName.toLowerCase();
|
|
82
|
+
} else if (activeRouteName === 'assets') {
|
|
83
|
+
selectedIndex = menuIndex;
|
|
84
|
+
selectedItem = 'gallery';
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
} else if (menuItem.value.toLowerCase() === activeRouteName.toLowerCase()) {
|
|
88
|
+
selectedIndex = menuIndex;
|
|
89
|
+
selectedItem = activeRouteName.toLowerCase();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
this.setState({ activeIndex: selectedIndex, activeItem: selectedItem });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
toggleSideNav(e) {
|
|
96
|
+
e.preventDefault();
|
|
97
|
+
this.setState({ visible: !this.state.visible }, () => {
|
|
98
|
+
window.dispatchEvent(new Event('resize'));
|
|
99
|
+
if (!this.state.visible) {
|
|
100
|
+
document.getElementById('cap-sidebar').classList.add('sidebar-collapse');
|
|
101
|
+
} else {
|
|
102
|
+
document.getElementById('cap-sidebar').classList.remove('sidebar-collapse');
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
createAccordianElements(title, contentItems) {
|
|
108
|
+
const accordian = [];
|
|
109
|
+
accordian.push(this.getAccordionTitle(title));
|
|
110
|
+
const contentLink = contentItems.map((key) =>
|
|
111
|
+
this.getLinkElement(key.link, key.text, key.value, key.external),
|
|
112
|
+
);
|
|
113
|
+
accordian.push(this.getAccordionContent(contentLink));
|
|
114
|
+
return accordian;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
createNavigationElement(menuItems) {
|
|
118
|
+
const navArray = [];
|
|
119
|
+
_.forEach(menuItems, (key, index) => {
|
|
120
|
+
const headerTitle = key.group;
|
|
121
|
+
const isCategory = Object.prototype.hasOwnProperty.call(key, 'categories');
|
|
122
|
+
if (isCategory) { // attach nested Accordion
|
|
123
|
+
const accordian = [];
|
|
124
|
+
const nestedAcordian = [];
|
|
125
|
+
accordian.push(this.getAccordionTitle(headerTitle));
|
|
126
|
+
const contentAccordian = this.getAccordian(this.createNavigationElement(key.categories), `nestedAccordian-${index}`);
|
|
127
|
+
nestedAcordian.push(contentAccordian);
|
|
128
|
+
const content = this.getAccordionContent(nestedAcordian, `content-${index}`);
|
|
129
|
+
accordian.push(content);
|
|
130
|
+
navArray.push(accordian);
|
|
131
|
+
} else { // attach items to existing accordian
|
|
132
|
+
const accordianElem = this.createAccordianElements(headerTitle, key.items);
|
|
133
|
+
navArray.push(accordianElem);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
// const selectedItem = (this.state.activeItem === 'gallery') ? 'selected' : '';
|
|
137
|
+
// navArray.push(
|
|
138
|
+
// <Link
|
|
139
|
+
// to={'/assets'}
|
|
140
|
+
// className={`item menu-item ${selectedItem} assetItem`}
|
|
141
|
+
// key={'assets'}
|
|
142
|
+
// title={'Gallery'}
|
|
143
|
+
// onClick={(e) => this.handleItemClick(e)}
|
|
144
|
+
// >Gallery</Link>
|
|
145
|
+
// );
|
|
146
|
+
return navArray;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
handleOpen() {
|
|
150
|
+
this.setState({ isOpen: true });
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
handleClose() {
|
|
154
|
+
this.setState({ isOpen: false });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
handleItemClick(e) {
|
|
158
|
+
this.setState({ activeItem: (e.target.text && e.target.text.trim().toLowerCase()) || '' });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
handleTitleClick(e, i) {
|
|
162
|
+
this.setState({ activeIndex: this.state.activeIndex === i ? -1 : i });
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
handleSearch(e) {
|
|
166
|
+
this.setState({ searchText: e.target.value });
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
render() {
|
|
171
|
+
const visible = this.state.visible;
|
|
172
|
+
const push = !visible ? 'push' : '';
|
|
173
|
+
const collapse = !visible ? 'collapse' : '';
|
|
174
|
+
const toggle = visible ? 'hide' : '';
|
|
175
|
+
|
|
176
|
+
// const types = [{ text: 'Creatives', value: 'Creatives' }];
|
|
177
|
+
return (
|
|
178
|
+
<div className="sidebar-container">
|
|
179
|
+
<div className={`sidebar sidebar-width ${collapse}`}>
|
|
180
|
+
<div className="searchbar">
|
|
181
|
+
<FormattedMessage {...messages.inputPlaceholder}>{(message) => <Input icon="search" className="sidebar-search" placeholder={message} fluid onChange={this.handleSearch} />}</FormattedMessage>
|
|
182
|
+
<a href="" onClick={this.toggleSideNav}><i className="material-icons control-arrow">arrow_back</i></a>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
<div className="menu-header">
|
|
186
|
+
<span className="menu-title"><FormattedMessage {...messages.menuTitle} /> </span>
|
|
187
|
+
{this.props.actionComponents}
|
|
188
|
+
</div>
|
|
189
|
+
<Accordion className="sidebar-accordian" activeIndex={this.state.activeIndex} onTitleClick={this.handleTitleClick}>
|
|
190
|
+
{this.props.menuData && this.createNavigationElement(this.props.menuData)}
|
|
191
|
+
</Accordion>
|
|
192
|
+
</div>
|
|
193
|
+
<div className={`togglebar ${toggle} ${push}`}>
|
|
194
|
+
<Button icon className="btn-toggle" onClick={this.toggleSideNav}>
|
|
195
|
+
<Icon name="bars" />
|
|
196
|
+
</Button>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
Sidebar.propTypes = {
|
|
204
|
+
menuData: PropTypes.array.isRequired,
|
|
205
|
+
actionComponents: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export default Sidebar;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Sidebar Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the Sidebar component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
export default defineMessages({
|
|
9
|
+
inputPlaceholder: {
|
|
10
|
+
id: 'app.components.Sidebar.input.placeholder',
|
|
11
|
+
defaultMessage: 'Search...',
|
|
12
|
+
},
|
|
13
|
+
menuTitle: {
|
|
14
|
+
id: 'app.components.Sidebar.menuTitle',
|
|
15
|
+
defaultMessage: 'Menu',
|
|
16
|
+
},
|
|
17
|
+
creatives: {
|
|
18
|
+
id: 'app.components.Sidebar.creatives',
|
|
19
|
+
defaultMessage: 'Creatives',
|
|
20
|
+
},
|
|
21
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* SmsEditor
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
|
|
9
|
+
import React from 'react';
|
|
10
|
+
// import styled from 'styled-components';
|
|
11
|
+
import {TextArea} from 'semantic-ui-react';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SmsEditor extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
15
|
+
constructor(props) {
|
|
16
|
+
super(props);
|
|
17
|
+
if (this.props.content) {
|
|
18
|
+
this.state = {
|
|
19
|
+
content: this.props.content,
|
|
20
|
+
};
|
|
21
|
+
} else {
|
|
22
|
+
this.state = {
|
|
23
|
+
content: '',
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
this.onContentChange = this.onContentChange.bind(this);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
onContentChange(e, data) {
|
|
30
|
+
this.props.onDataChange(data);
|
|
31
|
+
this.setState({
|
|
32
|
+
content: data,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
render() {
|
|
37
|
+
return (
|
|
38
|
+
<div>
|
|
39
|
+
<TextArea
|
|
40
|
+
autoHeight
|
|
41
|
+
style={{minHeight: 100}}
|
|
42
|
+
value={this.props.content}
|
|
43
|
+
onChange={(e, data) => { this.onContentChange(e, data); }}
|
|
44
|
+
/>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
SmsEditor.propTypes = {
|
|
51
|
+
content: PropTypes.string,
|
|
52
|
+
onDataChange: PropTypes.func,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default SmsEditor;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
.ui.navbar.menu {
|
|
2
|
+
height: 40px !important;
|
|
3
|
+
}
|
|
4
|
+
.ui.menu.navbar .item>img.logo{
|
|
5
|
+
height: 27px !important;
|
|
6
|
+
padding-left: 0!important;
|
|
7
|
+
margin: 0 auto;
|
|
8
|
+
max-width: 200px;
|
|
9
|
+
}
|
|
10
|
+
.ui.menu.navbar .ui.selection.dropdown{
|
|
11
|
+
height: 40px !important;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.ui.menu .ui.dropdown .menu>.selected.item {
|
|
15
|
+
background: #151821;
|
|
16
|
+
}
|
|
17
|
+
.org-list-drp-dwn .menu > .item{
|
|
18
|
+
height: 40px !important;
|
|
19
|
+
}
|
|
20
|
+
.ui.menu.navbar .ui.dropdown .menu>.item{
|
|
21
|
+
height: 40px !important;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ui.search.selection.dropdown>input.search{
|
|
25
|
+
padding-left: 12px !important;
|
|
26
|
+
padding-top: 8px !important;
|
|
27
|
+
padding-bottom: 8px !important;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ui.menu:not(.vertical) .right.item, .ui.menu:not(.vertical) .right.menu {
|
|
31
|
+
padding-right: 4px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.ui.menu .item {
|
|
35
|
+
padding-left: 12px !important;
|
|
36
|
+
padding-right: 12px !important;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.ui.secondary.vertical.menu>.item {
|
|
40
|
+
margin-bottom: 0 !important;
|
|
41
|
+
padding: 8px 16px !important;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.ui.menu.navbar .item.dropdownItem {
|
|
45
|
+
padding: 0px !important;
|
|
46
|
+
}
|
|
@@ -49,7 +49,7 @@ function SlideBoxContent(props) {
|
|
|
49
49
|
setIsLoadingContent,
|
|
50
50
|
showTemplateName,
|
|
51
51
|
onValidationFail,
|
|
52
|
-
|
|
52
|
+
channelsToHide,
|
|
53
53
|
} = props;
|
|
54
54
|
const type = messageDetails.type.toLowerCase(); // type is context in get tags values : outbound | dvs | referral | loyalty | coupons
|
|
55
55
|
const query = { type: !isFullMode && 'embedded', module: isFullMode ? 'defualt' : 'library'};
|
|
@@ -96,7 +96,7 @@ function SlideBoxContent(props) {
|
|
|
96
96
|
onChannelChange={onChannelChange}
|
|
97
97
|
onCallTaskSubmit={onCallTaskSubmit}
|
|
98
98
|
cap={cap}
|
|
99
|
-
|
|
99
|
+
channelsToHide={channelsToHide}
|
|
100
100
|
/>
|
|
101
101
|
)}
|
|
102
102
|
{isPreview && (
|
|
@@ -270,6 +270,6 @@ SlideBoxContent.propTypes = {
|
|
|
270
270
|
mobilePushCreateMode: PropTypes.string,
|
|
271
271
|
showTemplateName: PropTypes.func,
|
|
272
272
|
onValidationFail: PropTypes.func,
|
|
273
|
-
|
|
273
|
+
channelsToHide: PropTypes.array,
|
|
274
274
|
};
|
|
275
275
|
export default SlideBoxContent;
|