@capillarytech/creatives-library 2.0.54 → 2.0.57
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/components/CallTaskPreview/_callTaskPreview.scss +17 -0
- package/components/CallTaskPreview/images/Footer.png +0 -0
- package/components/CallTaskPreview/images/Header.png +0 -0
- package/components/CallTaskPreview/index.js +37 -0
- package/components/CallTaskPreview/messages.js +13 -0
- package/components/CallTaskPreview/tests/index.test.js +15 -0
- package/components/CapTagList/index.js +1 -1
- package/components/EmailPreviewV2/index.js +3 -1
- package/components/FormBuilder/index.js +10 -7
- package/components/NewCallTask/_newCallTask.scss +9 -0
- package/components/NewCallTask/index.js +152 -0
- package/components/NewCallTask/messages.js +29 -0
- package/components/NewCallTask/tests/index.test.js +10 -0
- package/containers/CallTask/_callTask.scss +5 -0
- package/containers/CallTask/actions.js +15 -0
- package/containers/CallTask/constants.js +7 -0
- package/containers/CallTask/index.js +141 -0
- package/containers/CallTask/messages.js +21 -0
- package/containers/CallTask/reducer.js +23 -0
- package/containers/CallTask/sagas.js +11 -0
- package/containers/CallTask/selectors.js +25 -0
- package/containers/CallTask/tests/actions.test.js +18 -0
- package/containers/CallTask/tests/index.test.js +10 -0
- package/containers/CallTask/tests/reducer.test.js +9 -0
- package/containers/CallTask/tests/sagas.test.js +15 -0
- package/containers/CallTask/tests/selectors.test.js +10 -0
- package/containers/CreativesContainer/SlideBoxContent.js +66 -3
- package/containers/CreativesContainer/SlideBoxFooter.js +3 -3
- package/containers/CreativesContainer/constants.js +2 -0
- package/containers/CreativesContainer/index.js +105 -21
- package/containers/Email/_email.scss +0 -1
- package/containers/Email/index.js +2 -0
- package/containers/Line/Edit/_lineEdit.scss +0 -4
- package/containers/MobilePush/Create/_mobilePushCreate.scss +0 -4
- package/containers/MobilePush/Create/index.js +4 -2
- package/containers/MobilePush/Edit/_mobilePushCreate.scss +0 -4
- package/containers/MobilePush/Edit/index.js +11 -8
- package/containers/MobilePush/Edit/selectors.js +2 -1
- package/containers/MobilepushWrapper/index.js +92 -0
- package/containers/MobilepushWrapper/messages.js +25 -0
- package/containers/MobilepushWrapper/tests/index.test.js +10 -0
- package/containers/Sms/Create/_smsCreate.scss +0 -1
- package/containers/Sms/Edit/actions.js +6 -0
- package/containers/Sms/Edit/constants.js +1 -0
- package/containers/Sms/Edit/index.js +1 -0
- package/containers/Sms/Edit/reducer.js +2 -0
- package/containers/TagList/index.js +3 -3
- package/containers/Templates/index.js +35 -17
- package/containers/TemplatesV2/index.js +22 -11
- package/index.js +7 -0
- package/package.json +2 -2
- package/routes.js +7 -2
- package/styles/containers/layout/_layoutPage.scss +1 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.call-task-preview {
|
|
2
|
+
.call-task-subject-container {
|
|
3
|
+
padding: 8px;
|
|
4
|
+
background: #444;
|
|
5
|
+
color: white;
|
|
6
|
+
font-size: 12px;
|
|
7
|
+
font-weight: 500;
|
|
8
|
+
}
|
|
9
|
+
.call-task-message-container {
|
|
10
|
+
overflow-y: auto;
|
|
11
|
+
height: 150px;
|
|
12
|
+
width: 100%;
|
|
13
|
+
font-size: 12px;
|
|
14
|
+
background: #eee;
|
|
15
|
+
padding: 8px;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* CallTaskPreview
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import HeaderPng from './images/Header.png';
|
|
10
|
+
import FooterPng from './images/Footer.png';
|
|
11
|
+
|
|
12
|
+
import './_callTaskPreview.scss';
|
|
13
|
+
|
|
14
|
+
class CallTaskPreview extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
15
|
+
render() {
|
|
16
|
+
const { subject, messageBody } = this.props;
|
|
17
|
+
return (
|
|
18
|
+
<div className="call-task-preview">
|
|
19
|
+
<img style={{ width: '100%' }} src={HeaderPng} alt="header" />
|
|
20
|
+
<div className="call-task-subject-container">
|
|
21
|
+
{subject}
|
|
22
|
+
</div>
|
|
23
|
+
<div className="call-task-message-container">
|
|
24
|
+
{messageBody}
|
|
25
|
+
</div>
|
|
26
|
+
<img style={{ width: '100%' }} src={FooterPng} alt="footer" />
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
CallTaskPreview.propTypes = {
|
|
33
|
+
subject: PropTypes.string,
|
|
34
|
+
messageBody: PropTypes.string,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default CallTaskPreview;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* CallTaskPreview Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the CallTaskPreview component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
export default defineMessages({
|
|
9
|
+
header: {
|
|
10
|
+
id: 'app.components.CallTaskPreview.header',
|
|
11
|
+
defaultMessage: 'This is the CallTaskPreview component !',
|
|
12
|
+
},
|
|
13
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { shallow } from "enzyme";
|
|
3
|
+
import CallTaskPreview from "../index";
|
|
4
|
+
|
|
5
|
+
describe("<CallTaskPreview />", () => {
|
|
6
|
+
it("Test if Call task component renders", () => {
|
|
7
|
+
const component = shallow(
|
|
8
|
+
<CallTaskPreview
|
|
9
|
+
subject="this is test"
|
|
10
|
+
body="this is test message body"
|
|
11
|
+
/>
|
|
12
|
+
);
|
|
13
|
+
expect(component).toMatchSnapshot();
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -81,8 +81,8 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
81
81
|
tagValue = tagValue.replace("(N)", `${days}`);
|
|
82
82
|
const resultArray = [];
|
|
83
83
|
resultArray.push(tagValue);
|
|
84
|
-
this.props.onSelect(resultArray);
|
|
85
84
|
this.setState({showModal: false, dynamicDateValue: ''});
|
|
85
|
+
this.props.onSelect(resultArray);
|
|
86
86
|
};
|
|
87
87
|
|
|
88
88
|
handleCancel = () => {
|
|
@@ -54,7 +54,9 @@ class EmailPreviewV2 extends React.Component {
|
|
|
54
54
|
this.props.templateActions.getTemplateDetails(templateData._id); // templateContent: html data to be shown in iframe
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
|
|
57
|
+
componentWillUnmount() {
|
|
58
|
+
this.props.templateActions.resetTemplateData();
|
|
59
|
+
}
|
|
58
60
|
changePreviewDevice = (ev) => {
|
|
59
61
|
this.setState({currentDevice: ev.currentTarget.id});
|
|
60
62
|
}
|
|
@@ -556,7 +556,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
556
556
|
_.forEach(this.state.formData, (tab, index) => {
|
|
557
557
|
let isCurrentTabValid = true;
|
|
558
558
|
let skipValidation = false;
|
|
559
|
-
if (type.toLowerCase() === 'embedded' && ((isOnlyAndroid && parseInt(index) === 1) || (isOnlyIos && parseInt(index) === 0))) {
|
|
559
|
+
if (type.toLowerCase() === 'embedded' && ((isOnlyAndroid && parseInt(index) === 1) || (isOnlyIos && parseInt(index) === 0)) && isOnlyAndroid !== isOnlyIos) {
|
|
560
|
+
// skip validation of the tab which is not open in embedded mode
|
|
560
561
|
skipValidation = true;
|
|
561
562
|
}
|
|
562
563
|
if (!isNaN(index) && tab && !skipValidation) {
|
|
@@ -2161,7 +2162,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2161
2162
|
case "input":
|
|
2162
2163
|
if (styling === 'semantic') {
|
|
2163
2164
|
ifError = this.state.checkValidation && (isVersionEnable ? this.state.errorData[`${this.state.currentTab - 1}`][val.id] : this.state.errorData[val.id]);
|
|
2164
|
-
|
|
2165
|
+
const value = isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id];
|
|
2165
2166
|
columns.push(
|
|
2166
2167
|
<CapColumn key={val.id} span={val.width}>
|
|
2167
2168
|
<CapInput
|
|
@@ -2173,7 +2174,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2173
2174
|
placeholder={val.placeholder}
|
|
2174
2175
|
onChange={(e) => this.updateFormData(e.target.value, val)}
|
|
2175
2176
|
defaultValue={isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id]}
|
|
2176
|
-
value={
|
|
2177
|
+
value={value || ""}
|
|
2177
2178
|
disabled={val.disabled}
|
|
2178
2179
|
/>
|
|
2179
2180
|
</CapColumn>
|
|
@@ -2193,6 +2194,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2193
2194
|
break;
|
|
2194
2195
|
case "textarea":
|
|
2195
2196
|
ifError = this.state.checkValidation && (isVersionEnable ? this.state.errorData[`${this.state.currentTab - 1}`][val.id] : this.state.errorData[val.id]);
|
|
2197
|
+
const value = isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id];
|
|
2196
2198
|
if (styling === 'semantic') {
|
|
2197
2199
|
columns.push(
|
|
2198
2200
|
<CapColumn key="input" span={val.width}>
|
|
@@ -2204,7 +2206,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2204
2206
|
onChange={(e) => this.updateFormData(e.target.value, val)}
|
|
2205
2207
|
style={val.style ? val.style : {}}
|
|
2206
2208
|
defaultValue={isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id]}
|
|
2207
|
-
value={
|
|
2209
|
+
value={value || ""}
|
|
2208
2210
|
rows={20}
|
|
2209
2211
|
disabled={val.disabled}
|
|
2210
2212
|
cols={20}
|
|
@@ -2518,7 +2520,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2518
2520
|
switch (type) {
|
|
2519
2521
|
case "input":
|
|
2520
2522
|
ifError = this.state.checkValidation && (isVersionEnable ? this.state.errorData[`${this.state.currentTab - 1}`][val.id] : this.state.errorData[val.id]);
|
|
2521
|
-
|
|
2523
|
+
const value = isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id];
|
|
2522
2524
|
if (styling === 'semantic') {
|
|
2523
2525
|
columns.push(
|
|
2524
2526
|
<CapColumn key={val.id} span={val.width}>
|
|
@@ -2530,7 +2532,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2530
2532
|
style={val.style ? val.style : {}}
|
|
2531
2533
|
placeholder={val.placeholder}
|
|
2532
2534
|
onChange={(e) => this.updateFormData(e.target.value, val)}
|
|
2533
|
-
value={
|
|
2535
|
+
value={value || ""}
|
|
2534
2536
|
defaultValue={isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id]}
|
|
2535
2537
|
disabled={val.disabled}
|
|
2536
2538
|
/>
|
|
@@ -2551,6 +2553,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2551
2553
|
break;
|
|
2552
2554
|
case "textarea":
|
|
2553
2555
|
ifError = this.state.checkValidation && (isVersionEnable ? this.state.errorData[`${this.state.currentTab - 1}`][val.id] : this.state.errorData[val.id]);
|
|
2556
|
+
const textValue = isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id];
|
|
2554
2557
|
if (styling === 'semantic') {
|
|
2555
2558
|
columns.push(
|
|
2556
2559
|
<CapColumn key="input" span={val.width} offset={val.offset}>
|
|
@@ -2564,7 +2567,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2564
2567
|
onChange={(e) => this.updateFormData(e.target.value, val)}
|
|
2565
2568
|
style={val.style ? val.style : {}}
|
|
2566
2569
|
defaultValue={isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id]}
|
|
2567
|
-
value={
|
|
2570
|
+
value={textValue || ""}
|
|
2568
2571
|
rows={10}
|
|
2569
2572
|
cols={2}
|
|
2570
2573
|
/>
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* NewCallTask
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { CapRow, CapColumn, CapInput, CapButton, CapSpin } from '@capillarytech/cap-ui-library';
|
|
10
|
+
import { injectIntl, intlShape } from 'react-intl';
|
|
11
|
+
import TagList from '../../containers/TagList';
|
|
12
|
+
import CallTaskPreview from '../CallTaskPreview';
|
|
13
|
+
import messages from './messages';
|
|
14
|
+
import './_newCallTask.scss';
|
|
15
|
+
|
|
16
|
+
class NewCallTask extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
17
|
+
constructor(props) {
|
|
18
|
+
super(props);
|
|
19
|
+
this.state = this.getInitialState();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getInitialState = () => {
|
|
23
|
+
const { templateData } = this.props;
|
|
24
|
+
return {
|
|
25
|
+
subject: templateData && templateData.subject ? templateData.subject : '',
|
|
26
|
+
messageBody: templateData && templateData.messageBody ? templateData.messageBody : '',
|
|
27
|
+
description: templateData && templateData.description ? templateData.description : '',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onTagSelect = (data) => {
|
|
32
|
+
this.insertAtCursor(`{{${data}}}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setInputRef = (textarea) => {
|
|
36
|
+
this.textArea = textarea;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
insertAtCursor = (myValue) => {
|
|
40
|
+
this.textArea.focus();
|
|
41
|
+
const textAreaRef = this.textArea.textAreaRef;
|
|
42
|
+
let pos = textAreaRef.selectionEnd + myValue.length;
|
|
43
|
+
//IE support
|
|
44
|
+
let newMessage = textAreaRef.value + myValue;
|
|
45
|
+
if (document.selection) {
|
|
46
|
+
this.textArea.focus();
|
|
47
|
+
const sel = document.selection.createRange();
|
|
48
|
+
sel.text = myValue;
|
|
49
|
+
} else if (textAreaRef.selectionStart || textAreaRef.selectionStart === '0') { //MOZILLA and others
|
|
50
|
+
const startPos = textAreaRef.selectionStart;
|
|
51
|
+
const endPos = textAreaRef.selectionEnd;
|
|
52
|
+
newMessage = textAreaRef.value.substring(0, startPos) + myValue + textAreaRef.value.substring(endPos, textAreaRef.value.length);
|
|
53
|
+
pos = startPos + myValue.length;
|
|
54
|
+
}
|
|
55
|
+
this.setState({
|
|
56
|
+
messageBody: newMessage,
|
|
57
|
+
}, () => {
|
|
58
|
+
textAreaRef.selectionStart = pos;
|
|
59
|
+
textAreaRef.selectionEnd = pos;
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
updateSubject = (e) => {
|
|
64
|
+
this.setState({
|
|
65
|
+
subject: e.target.value,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
updateMessageBody = (e) => {
|
|
70
|
+
this.setState({
|
|
71
|
+
messageBody: e.target.value,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
updateDescription = (e) => {
|
|
76
|
+
this.setState({
|
|
77
|
+
description: e.target.value,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
submitForm = () => {
|
|
82
|
+
this.props.onCallTaskSubmit(this.state);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
render() {
|
|
86
|
+
const { intl, isLoading, metaEntities } = this.props;
|
|
87
|
+
const { formatMessage } = intl;
|
|
88
|
+
const { subject, messageBody, description } = this.state;
|
|
89
|
+
const tags = metaEntities && metaEntities.tags ? metaEntities.tags.standard : [];
|
|
90
|
+
return (
|
|
91
|
+
<CapSpin spinning={isLoading}>
|
|
92
|
+
<CapRow gutter={16}>
|
|
93
|
+
<CapColumn span={12}>
|
|
94
|
+
<div style={{ height: 'calc(100vh - 187px)', overflowY: 'auto', paddingRight: "8px" }}>
|
|
95
|
+
<div style={{ marginBottom: '34px' }}>
|
|
96
|
+
<CapInput
|
|
97
|
+
label={formatMessage(messages.callTaskTitle)}
|
|
98
|
+
onChange={this.updateSubject}
|
|
99
|
+
value={subject}
|
|
100
|
+
isRequired
|
|
101
|
+
/>
|
|
102
|
+
</div>
|
|
103
|
+
<div style={{ position: 'relative', marginBottom: '34px' }}>
|
|
104
|
+
<TagList
|
|
105
|
+
className="new-call-task-tagList"
|
|
106
|
+
label={formatMessage(messages.personalisationTags)}
|
|
107
|
+
tags={tags}
|
|
108
|
+
onTagSelect={this.onTagSelect}
|
|
109
|
+
/>
|
|
110
|
+
<CapInput.TextArea
|
|
111
|
+
setInputRef={this.setInputRef}
|
|
112
|
+
label={formatMessage(messages.messageHeader)}
|
|
113
|
+
onChange={this.updateMessageBody}
|
|
114
|
+
value={messageBody}
|
|
115
|
+
isRequired
|
|
116
|
+
/>
|
|
117
|
+
</div>
|
|
118
|
+
<CapInput.TextArea
|
|
119
|
+
label={formatMessage(messages.description)}
|
|
120
|
+
onChange={this.updateDescription}
|
|
121
|
+
value={description}
|
|
122
|
+
isRequired
|
|
123
|
+
/>
|
|
124
|
+
</div>
|
|
125
|
+
<CapButton
|
|
126
|
+
disabled={!subject || !messageBody || !description}
|
|
127
|
+
className="new-call-task-done-button"
|
|
128
|
+
onClick={this.submitForm}>
|
|
129
|
+
{formatMessage(messages.done)}
|
|
130
|
+
</CapButton>
|
|
131
|
+
</CapColumn>
|
|
132
|
+
<CapColumn span={12}>
|
|
133
|
+
<CallTaskPreview
|
|
134
|
+
subject={subject}
|
|
135
|
+
messageBody={messageBody}
|
|
136
|
+
/>
|
|
137
|
+
</CapColumn>
|
|
138
|
+
</CapRow>
|
|
139
|
+
</CapSpin>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
NewCallTask.propTypes = {
|
|
145
|
+
intl: intlShape.isRequired,
|
|
146
|
+
onCallTaskSubmit: PropTypes.func,
|
|
147
|
+
templateData: PropTypes.object,
|
|
148
|
+
isLoading: PropTypes.bool,
|
|
149
|
+
metaEntities: PropTypes.object,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export default injectIntl(NewCallTask);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* NewCallTask Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the NewCallTask component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
export default defineMessages({
|
|
9
|
+
callTaskTitle: {
|
|
10
|
+
id: 'app.components.NewCallTask.callTaskTitle',
|
|
11
|
+
defaultMessage: 'Call Task title',
|
|
12
|
+
},
|
|
13
|
+
messageHeader: {
|
|
14
|
+
id: 'app.components.NewCallTask.messageHeader',
|
|
15
|
+
defaultMessage: 'Message',
|
|
16
|
+
},
|
|
17
|
+
description: {
|
|
18
|
+
id: 'app.components.NewCallTask.description',
|
|
19
|
+
defaultMessage: 'Description',
|
|
20
|
+
},
|
|
21
|
+
done: {
|
|
22
|
+
id: 'app.components.NewCallTask.done',
|
|
23
|
+
defaultMessage: 'Done',
|
|
24
|
+
},
|
|
25
|
+
personalisationTags: {
|
|
26
|
+
id: 'app.components.NewCallTask.personalisationTags',
|
|
27
|
+
defaultMessage: 'Personalisation tags',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* CallTask
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
import PropTypes from 'prop-types';
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { bindActionCreators } from "redux";
|
|
9
|
+
import { connect } from 'react-redux';
|
|
10
|
+
import {
|
|
11
|
+
//CapSlideBox,
|
|
12
|
+
CapButton,
|
|
13
|
+
//CapIcon,
|
|
14
|
+
//CapHeader,
|
|
15
|
+
CapLabel,
|
|
16
|
+
} from '@capillarytech/cap-ui-library';
|
|
17
|
+
import { injectIntl, intlShape } from 'react-intl';
|
|
18
|
+
import { createStructuredSelector } from 'reselect';
|
|
19
|
+
import { makeSelectMetaEntities, isLoadingMetaEntities } from '../Cap/selectors';
|
|
20
|
+
import * as globalActions from '../../containers/Cap/actions';
|
|
21
|
+
import * as actions from "./actions";
|
|
22
|
+
import makeSelectCallTask from './selectors';
|
|
23
|
+
import NewCallTask from '../../components/NewCallTask';
|
|
24
|
+
import messages from './messages';
|
|
25
|
+
import './_callTask.scss';
|
|
26
|
+
|
|
27
|
+
export class CallTask extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
28
|
+
constructor(props) {
|
|
29
|
+
super(props);
|
|
30
|
+
this.state = {
|
|
31
|
+
showCallTaskSlidebox: false,
|
|
32
|
+
mode: props.mode || '', // supported modes are create | edit
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
componentDidMount() {
|
|
37
|
+
const query = {
|
|
38
|
+
layout: 'SMS',
|
|
39
|
+
type: 'TAG',
|
|
40
|
+
context: 'outbound',
|
|
41
|
+
embedded: 'embedded',
|
|
42
|
+
};
|
|
43
|
+
this.props.globalActions.fetchSchemaForEntity(query);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
showNewCallTask = () => {
|
|
47
|
+
this.setState({
|
|
48
|
+
showCallTaskSlidebox: true,
|
|
49
|
+
mode: 'create',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
closeSlideBox = () => {
|
|
54
|
+
this.setState({
|
|
55
|
+
showCallTaskSlidebox: false,
|
|
56
|
+
mode: '',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
render() {
|
|
61
|
+
const { intl, onCallTaskSubmit, templateData, loadingMetaEntities, metaEntities, showContentInSlidebox, onCreateNew } = this.props;
|
|
62
|
+
const { formatMessage } = intl;
|
|
63
|
+
const { mode } = this.state;
|
|
64
|
+
return (
|
|
65
|
+
<div>
|
|
66
|
+
{mode ?
|
|
67
|
+
<NewCallTask
|
|
68
|
+
metaEntities={metaEntities}
|
|
69
|
+
isLoading={loadingMetaEntities}
|
|
70
|
+
mode={mode}
|
|
71
|
+
templateData={templateData}
|
|
72
|
+
onCallTaskSubmit={onCallTaskSubmit}
|
|
73
|
+
/>
|
|
74
|
+
:
|
|
75
|
+
<div>
|
|
76
|
+
<CapLabel type="label1">
|
|
77
|
+
{formatMessage(messages.callTaskInfo)}
|
|
78
|
+
</CapLabel>
|
|
79
|
+
<div className="call-task-action-button">
|
|
80
|
+
<CapButton onClick={showContentInSlidebox ? this.showNewCallTask : onCreateNew}>
|
|
81
|
+
{formatMessage(messages.addNewCallTask)}
|
|
82
|
+
</CapButton>
|
|
83
|
+
</div>
|
|
84
|
+
{/* {
|
|
85
|
+
showCallTaskSlidebox && showContentInSlidebox &&
|
|
86
|
+
<CapSlideBox
|
|
87
|
+
header={
|
|
88
|
+
<CapHeader
|
|
89
|
+
title={formatMessage(messages.newMessage)}
|
|
90
|
+
prefix={
|
|
91
|
+
<CapIcon style={{ marginRight: '16px' }} type={"back"} onClick={this.closeSlideBox} />
|
|
92
|
+
} />
|
|
93
|
+
}
|
|
94
|
+
show={showCallTaskSlidebox}
|
|
95
|
+
size="size-l"
|
|
96
|
+
handleClose={this.closeSlideBox}
|
|
97
|
+
content={
|
|
98
|
+
<NewCallTask
|
|
99
|
+
metaEntities={metaEntities}
|
|
100
|
+
isLoading={loadingMetaEntities}
|
|
101
|
+
mode={mode}
|
|
102
|
+
onCallTaskSubmit={onCallTaskSubmit}
|
|
103
|
+
/>
|
|
104
|
+
}
|
|
105
|
+
/>
|
|
106
|
+
} */}
|
|
107
|
+
</div>
|
|
108
|
+
}
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
CallTask.propTypes = {
|
|
115
|
+
intl: intlShape.isRequired,
|
|
116
|
+
onCallTaskSubmit: PropTypes.func,
|
|
117
|
+
mode: PropTypes.string,
|
|
118
|
+
templateData: PropTypes.object,
|
|
119
|
+
globalActions: PropTypes.object,
|
|
120
|
+
metaEntities: PropTypes.object,
|
|
121
|
+
loadingMetaEntities: PropTypes.bool,
|
|
122
|
+
showContentInSlidebox: PropTypes.bool,
|
|
123
|
+
onCreateNew: PropTypes.func,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
const mapStateToProps = createStructuredSelector({
|
|
128
|
+
CallTask: makeSelectCallTask(),
|
|
129
|
+
metaEntities: makeSelectMetaEntities(),
|
|
130
|
+
loadingMetaEntities: isLoadingMetaEntities(),
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
function mapDispatchToProps(dispatch) {
|
|
134
|
+
return {
|
|
135
|
+
globalActions: bindActionCreators(globalActions, dispatch),
|
|
136
|
+
actions: bindActionCreators(actions, dispatch),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(CallTask));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* CallTask Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the CallTask component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
export default defineMessages({
|
|
9
|
+
addNewCallTask: {
|
|
10
|
+
id: 'app.containers.CallTask.addNewCallTask',
|
|
11
|
+
defaultMessage: 'Add New Call Task',
|
|
12
|
+
},
|
|
13
|
+
newMessage: {
|
|
14
|
+
id: 'app.containers.CallTask.newMessage',
|
|
15
|
+
defaultMessage: 'New Message',
|
|
16
|
+
},
|
|
17
|
+
callTaskInfo: {
|
|
18
|
+
id: 'app.containers.CallTask.callTaskInfo',
|
|
19
|
+
defaultMessage: 'Call Tasks are message sent to store staff. The messages are displayed on the Point of Sale (POS) machines for store staff to take action.',
|
|
20
|
+
},
|
|
21
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* CallTask reducer
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { fromJS } from 'immutable';
|
|
8
|
+
import {
|
|
9
|
+
DEFAULT_ACTION,
|
|
10
|
+
} from './constants';
|
|
11
|
+
|
|
12
|
+
const initialState = fromJS({});
|
|
13
|
+
|
|
14
|
+
function callTaskReducer(state = initialState, action) {
|
|
15
|
+
switch (action.type) {
|
|
16
|
+
case DEFAULT_ACTION:
|
|
17
|
+
return state;
|
|
18
|
+
default:
|
|
19
|
+
return state;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default callTaskReducer;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// import { take, call, put, select } from 'redux-saga/effects';
|
|
2
|
+
|
|
3
|
+
// Individual exports for testing
|
|
4
|
+
export function* defaultSaga() {
|
|
5
|
+
// See example in containers/HomePage/sagas.js
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// All sagas to be loaded
|
|
9
|
+
export default [
|
|
10
|
+
defaultSaga,
|
|
11
|
+
];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createSelector } from 'reselect';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Direct selector to the callTask state domain
|
|
5
|
+
*/
|
|
6
|
+
const selectCallTaskDomain = () => (state) => state.get('callTask');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Other specific selectors
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Default selector used by CallTask
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const makeSelectCallTask = () => createSelector(
|
|
18
|
+
selectCallTaskDomain(),
|
|
19
|
+
(substate) => substate.toJS()
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export default makeSelectCallTask;
|
|
23
|
+
export {
|
|
24
|
+
selectCallTaskDomain,
|
|
25
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import {
|
|
3
|
+
defaultAction,
|
|
4
|
+
} from '../actions';
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_ACTION,
|
|
7
|
+
} from '../constants';
|
|
8
|
+
|
|
9
|
+
describe('CallTask actions', () => {
|
|
10
|
+
describe('Default Action', () => {
|
|
11
|
+
it('has a type of DEFAULT_ACTION', () => {
|
|
12
|
+
const expected = {
|
|
13
|
+
type: DEFAULT_ACTION,
|
|
14
|
+
};
|
|
15
|
+
expect(defaultAction()).toEqual(expected);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
});
|