@capillarytech/creatives-library 7.9.13 → 7.9.15
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/assets/group.png +0 -0
- package/components/Card/index.js +1 -1
- package/components/Card/tests/__snapshots__/index.test.js.snap +22 -0
- package/components/Card/tests/index.test.js +19 -7
- package/containers/App/constants.js +2 -1
- package/helpers/intl-enzym-test-helpers.js +40 -0
- package/index.js +6 -0
- package/package.json +3 -2
- package/routes.js +5 -0
- package/services/api.js +9 -15
- package/utils/common.js +17 -4
- package/v2Components/CapTagList/index.js +38 -9
- package/v2Components/CapTagList/messages.js +4 -0
- package/v2Containers/Cap/constants.js +2 -0
- package/v2Containers/Cap/index.js +9 -2
- package/v2Containers/Cap/reducer.js +5 -1
- package/v2Containers/Cap/selectors.js +10 -1
- package/v2Containers/CreativesContainer/SlideBoxContent.js +10 -4
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +6 -1
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/FTP/index.js +14 -4
- package/v2Containers/Sms/Create/index.js +5 -6
- package/v2Containers/Sms/Edit/sagas.js +1 -1
- package/v2Containers/SmsTrai/Create/actions.js +25 -0
- package/v2Containers/SmsTrai/Create/constants.js +74 -0
- package/v2Containers/SmsTrai/Create/index.js +681 -0
- package/v2Containers/SmsTrai/Create/index.scss +92 -0
- package/v2Containers/SmsTrai/Create/messages.js +116 -0
- package/v2Containers/SmsTrai/Create/reducer.js +43 -0
- package/v2Containers/SmsTrai/Create/sagas.js +36 -0
- package/v2Containers/SmsTrai/Create/selectors.js +26 -0
- package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +10351 -0
- package/v2Containers/SmsTrai/Create/tests/index.test.js +77 -0
- package/v2Containers/SmsTrai/Create/tests/mockData.js +58 -0
- package/v2Containers/SmsTrai/Edit/constants.js +16 -0
- package/v2Containers/SmsTrai/Edit/index.js +483 -0
- package/v2Containers/SmsTrai/Edit/messages.js +58 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +16103 -0
- package/v2Containers/SmsTrai/Edit/tests/index.test.js +61 -0
- package/v2Containers/SmsTrai/Edit/tests/mockData.js +36 -0
- package/v2Containers/SmsWrapper/index.js +75 -0
- package/v2Containers/SmsWrapper/tests/index.test.js +10 -0
- package/v2Containers/Templates/_templates.scss +2 -0
- package/v2Containers/Templates/index.js +89 -27
- package/v2Containers/Templates/messages.js +16 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { mountWithIntl } from '../../../../../app/helpers/intl-enzym-test-helpers';
|
|
3
|
+
import { SmsTraiCreate } from '../index';
|
|
4
|
+
import { SAMPLE_CSV, DOWNLOAD_ISSUES_CSV } from '../constants';
|
|
5
|
+
import { mockData } from './mockData';
|
|
6
|
+
|
|
7
|
+
let file = [];
|
|
8
|
+
const renderHelper = (fileData) => {
|
|
9
|
+
file = new File(mockData.contents, fileData.name, {
|
|
10
|
+
type: fileData.type,
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
jest.mock('papaparse', () => ({
|
|
15
|
+
parse: (file, response) => {
|
|
16
|
+
response.complete({ data: mockData.contents }, file);
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
describe('Creatives SmsTraiCreate test/>', () => {
|
|
21
|
+
let renderedComponent;
|
|
22
|
+
const clearCreateResponse = jest.fn();
|
|
23
|
+
const createSMSTRAITemplates = jest.fn();
|
|
24
|
+
const onCreateComplete = jest.fn();
|
|
25
|
+
const setAttribute = jest.fn();
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
renderedComponent = mountWithIntl(
|
|
28
|
+
<SmsTraiCreate
|
|
29
|
+
actions={{ clearCreateResponse, createSMSTRAITemplates }}
|
|
30
|
+
onCreateComplete={onCreateComplete}
|
|
31
|
+
/>,
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('renders UI', () => {
|
|
36
|
+
expect(renderedComponent).toMatchSnapshot();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('clicking on Sample CSV should download sample CSV file', () => {
|
|
40
|
+
const event = { target: { setAttribute } };
|
|
41
|
+
renderedComponent.find('.download-sample-link').props().onClick(event);
|
|
42
|
+
expect(setAttribute).toHaveBeenCalledWith('download', SAMPLE_CSV);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('done button should be disabled initially', () => {
|
|
46
|
+
const buttonProps = renderedComponent.find('button.done-button').props();
|
|
47
|
+
expect(buttonProps.disabled).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('invalid file drop', async () => {
|
|
51
|
+
renderHelper(mockData.invalidFile);
|
|
52
|
+
const dropZone = renderedComponent.find('Dropzone').props();
|
|
53
|
+
await dropZone.onDrop([file]);
|
|
54
|
+
renderedComponent.update();
|
|
55
|
+
expect(renderedComponent).toMatchSnapshot();
|
|
56
|
+
expect(renderedComponent.find('button.done-button').props().disabled).toBe(
|
|
57
|
+
true,
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('valid file drop', async () => {
|
|
62
|
+
const event = { target: { setAttribute } };
|
|
63
|
+
renderHelper(mockData.validFile);
|
|
64
|
+
const dropZone = renderedComponent.find('Dropzone').props();
|
|
65
|
+
await dropZone.onDrop([file]);
|
|
66
|
+
renderedComponent.update();
|
|
67
|
+
expect(renderedComponent).toMatchSnapshot();
|
|
68
|
+
expect(renderedComponent.find('button.done-button').props().disabled).toBe(
|
|
69
|
+
false,
|
|
70
|
+
);
|
|
71
|
+
renderedComponent.find('a.download-issues-csv-link').props().onClick(event);
|
|
72
|
+
expect(setAttribute).toHaveBeenCalledWith('download', DOWNLOAD_ISSUES_CSV);
|
|
73
|
+
renderedComponent.find('button.done-button').props().onClick();
|
|
74
|
+
renderedComponent.update();
|
|
75
|
+
expect(renderedComponent).toMatchSnapshot();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export const mockData = {
|
|
2
|
+
invalidFile: {
|
|
3
|
+
type: 'application/json',
|
|
4
|
+
name: 'test.json',
|
|
5
|
+
},
|
|
6
|
+
validFile: {
|
|
7
|
+
type: 'text/csv',
|
|
8
|
+
name: 'test.csv',
|
|
9
|
+
},
|
|
10
|
+
contents: [
|
|
11
|
+
[
|
|
12
|
+
'TEMPLATE ID',
|
|
13
|
+
'TELEMARKETER',
|
|
14
|
+
'TEMPLATE NAME',
|
|
15
|
+
'TYPE',
|
|
16
|
+
'SENDER ID',
|
|
17
|
+
'CATEGORY',
|
|
18
|
+
'REGISTERED DLT',
|
|
19
|
+
'REQUESTED ON',
|
|
20
|
+
'STATUS DATE',
|
|
21
|
+
'APPROVAL STATUS',
|
|
22
|
+
'STATUS',
|
|
23
|
+
'TEMPLATE MESSAGE',
|
|
24
|
+
'CONSENT TYPE',
|
|
25
|
+
],
|
|
26
|
+
[
|
|
27
|
+
"'1107160277332377515'",
|
|
28
|
+
'--',
|
|
29
|
+
'CAP71871_12',
|
|
30
|
+
'Service-Explicit',
|
|
31
|
+
'VISHMM',
|
|
32
|
+
'--',
|
|
33
|
+
'Vodafone Idea',
|
|
34
|
+
'07/10/20 17:52',
|
|
35
|
+
'13/10/20 21:55',
|
|
36
|
+
'Approved',
|
|
37
|
+
'Active',
|
|
38
|
+
'DUSSEHRA DEALS@VISHAL\n\nBUY1GET1 FREE\n{#var#}\n{#var#}\n{#var#}\n{#var#}\n+\n{#var#}\n{#var#}\n{#var#}\nTC',
|
|
39
|
+
'Explicit',
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
"'1107160277332377515'",
|
|
43
|
+
'--',
|
|
44
|
+
'',
|
|
45
|
+
'Service-Explicit',
|
|
46
|
+
'',
|
|
47
|
+
'--',
|
|
48
|
+
'Vodafone Idea',
|
|
49
|
+
'07/10/20 17:52',
|
|
50
|
+
'13/10/20 21:55',
|
|
51
|
+
'',
|
|
52
|
+
'Active',
|
|
53
|
+
'DUSSEHRA DEALS@VISHAL\n\nBUY1GET1 FREE\n{#var#}\n{#var#}\n{#var#}\n{#var#}\n+\n{#var#}\n{#var#}\n{#var#}\nTC',
|
|
54
|
+
'Explicit',
|
|
55
|
+
],
|
|
56
|
+
[''],
|
|
57
|
+
],
|
|
58
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* SmsTrai constants
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const DEFAULT_ACTION = 'app/SmsTrai/DEFAULT_ACTION';
|
|
8
|
+
export const CHARLIMIT = 30;
|
|
9
|
+
export const SMS = 'SMS';
|
|
10
|
+
export const SMS_TRAI_VAR = '{#var#}';
|
|
11
|
+
export const TAG = 'TAG';
|
|
12
|
+
export const EMBEDDED = 'embedded';
|
|
13
|
+
export const DEFAULT = 'default';
|
|
14
|
+
export const FULL = 'full';
|
|
15
|
+
export const ALL = 'all';
|
|
16
|
+
export const LIBRARY = 'library';
|
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { createStructuredSelector } from 'reselect';
|
|
3
|
+
import { bindActionCreators } from 'redux';
|
|
4
|
+
import { FormattedMessage, injectIntl } from 'react-intl';
|
|
5
|
+
import { get, cloneDeep, isEmpty } from 'lodash';
|
|
6
|
+
import styled from 'styled-components';
|
|
7
|
+
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
8
|
+
import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
|
|
9
|
+
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
10
|
+
import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
|
|
11
|
+
import CapInput from '@capillarytech/cap-ui-library/CapInput';
|
|
12
|
+
import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
|
|
13
|
+
import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
|
|
14
|
+
import CapSpin from '@capillarytech/cap-ui-library/CapSpin';
|
|
15
|
+
import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
|
|
16
|
+
import {
|
|
17
|
+
CAP_SPACE_16,
|
|
18
|
+
CAP_SPACE_12,
|
|
19
|
+
CAP_SPACE_24,
|
|
20
|
+
CAP_SPACE_32,
|
|
21
|
+
CAP_SPACE_04,
|
|
22
|
+
CAP_WHITE,
|
|
23
|
+
CAP_G10,
|
|
24
|
+
} from '@capillarytech/cap-ui-library/styled/variables';
|
|
25
|
+
import { makeSelectTemplateDetailsResponse } from '../../Sms/Edit/selectors';
|
|
26
|
+
import { makeSelectMetaEntities, setInjectedTags } from '../../Cap/selectors';
|
|
27
|
+
import * as actions from '../../Sms/Edit/actions';
|
|
28
|
+
import messages from './messages';
|
|
29
|
+
import TagList from '../../TagList';
|
|
30
|
+
import TemplatePreview from '../../../v2Components/TemplatePreview';
|
|
31
|
+
import withCreatives from '../../../hoc/withCreatives';
|
|
32
|
+
|
|
33
|
+
import {
|
|
34
|
+
CHARLIMIT,
|
|
35
|
+
SMS,
|
|
36
|
+
SMS_TRAI_VAR,
|
|
37
|
+
TAG,
|
|
38
|
+
EMBEDDED,
|
|
39
|
+
DEFAULT,
|
|
40
|
+
FULL,
|
|
41
|
+
ALL,
|
|
42
|
+
LIBRARY,
|
|
43
|
+
} from './constants';
|
|
44
|
+
let varMap = {};
|
|
45
|
+
const { TextArea } = CapInput;
|
|
46
|
+
const { CapLabelInline } = CapLabel;
|
|
47
|
+
export const SmsTraiEdit = (props) => {
|
|
48
|
+
const {
|
|
49
|
+
intl,
|
|
50
|
+
handleClose,
|
|
51
|
+
params,
|
|
52
|
+
actions,
|
|
53
|
+
templateDetails,
|
|
54
|
+
globalActions,
|
|
55
|
+
location,
|
|
56
|
+
getDefaultTags,
|
|
57
|
+
supportedTags,
|
|
58
|
+
metaEntities,
|
|
59
|
+
injectedTags,
|
|
60
|
+
onCreateComplete,
|
|
61
|
+
} = props || {};
|
|
62
|
+
const { formatMessage } = intl;
|
|
63
|
+
const [loading, updateLoading] = useState(true);
|
|
64
|
+
const [tempMsgArray, updateTempMsgArray] = useState([]);
|
|
65
|
+
const [updatedSmsEditor, setUpdatedSmsEditor] = useState([]);
|
|
66
|
+
const [tags, updateTags] = useState([]);
|
|
67
|
+
const [textAreaId, updateTextAreaId] = useState();
|
|
68
|
+
const [isValidationError, updateIsValidationError] = useState(false);
|
|
69
|
+
let totalVarCount = 0;
|
|
70
|
+
const SMSTraiFooter = styled.div`
|
|
71
|
+
background-color: ${CAP_WHITE};
|
|
72
|
+
position: fixed;
|
|
73
|
+
bottom: 0;
|
|
74
|
+
width: 100%;
|
|
75
|
+
margin-left: -32px;
|
|
76
|
+
padding: ${CAP_SPACE_32} ${CAP_SPACE_24};
|
|
77
|
+
.ant-btn {
|
|
78
|
+
margin-right: ${CAP_SPACE_16};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
const TraiEditTemplateDetails = styled.div`
|
|
83
|
+
margin-bottom: ${CAP_SPACE_16};
|
|
84
|
+
${CapLabelInline} {
|
|
85
|
+
margin-right: ${CAP_SPACE_12};
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
const { id } = params || {};
|
|
90
|
+
if (id) {
|
|
91
|
+
actions.getTemplateDetails(id);
|
|
92
|
+
//fetching tags
|
|
93
|
+
const query = {
|
|
94
|
+
layout: SMS,
|
|
95
|
+
type: TAG,
|
|
96
|
+
context:
|
|
97
|
+
location.query.type === EMBEDDED ? location.query.module : DEFAULT,
|
|
98
|
+
embedded: location.query.type === EMBEDDED ? location.query.type : FULL,
|
|
99
|
+
};
|
|
100
|
+
if (getDefaultTags) {
|
|
101
|
+
query.context = getDefaultTags;
|
|
102
|
+
}
|
|
103
|
+
globalActions.fetchSchemaForEntity(query);
|
|
104
|
+
}
|
|
105
|
+
return () => {
|
|
106
|
+
actions.resetEditTemplate();
|
|
107
|
+
};
|
|
108
|
+
}, []);
|
|
109
|
+
|
|
110
|
+
//computing placeholder array for mapping values and rendering dynamic form
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (templateDetails && !isEmpty(templateDetails)) {
|
|
113
|
+
let msg = get(templateDetails, `versions.base.sms-editor`);
|
|
114
|
+
const templateMessageArray = [];
|
|
115
|
+
//converting sms-editor string to an array split at '{#var#}'
|
|
116
|
+
//split and push string before '{#var#}[0 to index]', push '{#var#}',
|
|
117
|
+
//split and repeat for remaining string[index+7 to length]
|
|
118
|
+
while (msg.length !== 0) {
|
|
119
|
+
const index = msg.search(SMS_TRAI_VAR);
|
|
120
|
+
if (index !== -1) {
|
|
121
|
+
templateMessageArray.push(msg.substring(0, index));
|
|
122
|
+
templateMessageArray.push(SMS_TRAI_VAR);
|
|
123
|
+
msg = msg.substring(index + 7, msg.length);
|
|
124
|
+
} else {
|
|
125
|
+
templateMessageArray.push(msg);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const filteredTemplateMessageArray = templateMessageArray.filter(
|
|
131
|
+
(i) => i.trim() !== '',
|
|
132
|
+
);
|
|
133
|
+
updateTempMsgArray(filteredTemplateMessageArray);
|
|
134
|
+
//stop spinner
|
|
135
|
+
updateLoading(false);
|
|
136
|
+
}
|
|
137
|
+
}, [templateDetails]);
|
|
138
|
+
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
if (tempMsgArray.length !== 0) {
|
|
141
|
+
//if varMapped and updated-sms-editor is already present on non first edits
|
|
142
|
+
if (!isEmpty(get(templateDetails, `versions.base.var-mapped`))) {
|
|
143
|
+
varMap = cloneDeep(get(templateDetails, `versions.base.var-mapped`));
|
|
144
|
+
setUpdatedSmsEditor(
|
|
145
|
+
get(templateDetails, `versions.base.updated-sms-editor`),
|
|
146
|
+
);
|
|
147
|
+
} else {
|
|
148
|
+
//computing varMap for first edit
|
|
149
|
+
let counter = 1;
|
|
150
|
+
for (let i = 0; i < tempMsgArray.length; i++) {
|
|
151
|
+
if (tempMsgArray[i] === SMS_TRAI_VAR) {
|
|
152
|
+
const nextElem =
|
|
153
|
+
tempMsgArray[i === tempMsgArray.length - 1 ? 0 : i + 1];
|
|
154
|
+
if (tempMsgArray[i] !== nextElem) {
|
|
155
|
+
varMap[`${tempMsgArray[i]}_${i - counter + 1}`] = {
|
|
156
|
+
data: '',
|
|
157
|
+
count: counter,
|
|
158
|
+
};
|
|
159
|
+
counter = 1;
|
|
160
|
+
} else {
|
|
161
|
+
counter++;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
setUpdatedSmsEditor(tempMsgArray);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}, [tempMsgArray]);
|
|
169
|
+
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
const previewCountElem = document.getElementsByClassName(
|
|
172
|
+
'character-count-col',
|
|
173
|
+
);
|
|
174
|
+
if (previewCountElem.length === 1) {
|
|
175
|
+
previewCountElem[0].style.visibility = 'hidden';
|
|
176
|
+
}
|
|
177
|
+
}, []);
|
|
178
|
+
|
|
179
|
+
//Saving on done start
|
|
180
|
+
const onUpdateTemplateComplete = (editResponse, errorMsg) => {
|
|
181
|
+
if (editResponse?.templateId) {
|
|
182
|
+
CapNotification.success({
|
|
183
|
+
message: formatMessage(messages.smsEditNotification),
|
|
184
|
+
});
|
|
185
|
+
actions.clearEditResponse();
|
|
186
|
+
onCreateComplete();
|
|
187
|
+
} else if (errorMsg) {
|
|
188
|
+
CapNotification.error({
|
|
189
|
+
message: errorMsg,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
const onDoneCallback = () => {
|
|
194
|
+
if (updatedSmsEditor.includes(SMS_TRAI_VAR)) {
|
|
195
|
+
//during save textbox should not be empty
|
|
196
|
+
updateIsValidationError(true);
|
|
197
|
+
} else {
|
|
198
|
+
//start spinner
|
|
199
|
+
updateLoading(true);
|
|
200
|
+
templateDetails.versions.base['var-mapped'] = varMap;
|
|
201
|
+
templateDetails.versions.base['updated-sms-editor'] = updatedSmsEditor;
|
|
202
|
+
templateDetails.versions.history = [templateDetails.versions.base];
|
|
203
|
+
actions.editTemplate(templateDetails, onUpdateTemplateComplete);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
//Saving on done end
|
|
207
|
+
|
|
208
|
+
// tag code start
|
|
209
|
+
useEffect(() => {
|
|
210
|
+
let tag =
|
|
211
|
+
metaEntities && metaEntities.tags ? metaEntities.tags.standard : [];
|
|
212
|
+
if (
|
|
213
|
+
location.query.type === EMBEDDED &&
|
|
214
|
+
location.query.module === LIBRARY &&
|
|
215
|
+
!getDefaultTags
|
|
216
|
+
) {
|
|
217
|
+
tag = supportedTags;
|
|
218
|
+
}
|
|
219
|
+
updateTags(tag);
|
|
220
|
+
}, [metaEntities]);
|
|
221
|
+
|
|
222
|
+
const handleOnTagsContextChange = (data) => {
|
|
223
|
+
const query = {
|
|
224
|
+
layout: SMS,
|
|
225
|
+
type: TAG,
|
|
226
|
+
context:
|
|
227
|
+
(data || '').toLowerCase() === ALL
|
|
228
|
+
? DEFAULT
|
|
229
|
+
: (data || '').toLowerCase(),
|
|
230
|
+
embedded: location.query.type === EMBEDDED ? location.query.type : FULL,
|
|
231
|
+
};
|
|
232
|
+
globalActions.fetchSchemaForEntity(query);
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const onTagSelect = (data) => {
|
|
236
|
+
if (textAreaId && varMap && updatedSmsEditor) {
|
|
237
|
+
const tempArr = [...updatedSmsEditor];
|
|
238
|
+
//when trying to insert tag in empty textarea,{#var#} is replaced with "" and then tag is added
|
|
239
|
+
if (tempArr[textAreaId] === SMS_TRAI_VAR) {
|
|
240
|
+
for (
|
|
241
|
+
let i = 0;
|
|
242
|
+
i < varMap[`${SMS_TRAI_VAR}_${textAreaId}`].count;
|
|
243
|
+
i++
|
|
244
|
+
) {
|
|
245
|
+
tempArr[textAreaId + i] = '';
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const messageData = `${tempArr[textAreaId]} {{${data}}}`;
|
|
249
|
+
tempArr[textAreaId] = messageData;
|
|
250
|
+
varMap[`${SMS_TRAI_VAR}_${textAreaId}`].data = messageData;
|
|
251
|
+
setUpdatedSmsEditor(tempArr);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
//setting the id of currently selected text area, is used onTagSelect
|
|
255
|
+
const setTextAreaId = (event) => {
|
|
256
|
+
updateTextAreaId(Number(event.target.id));
|
|
257
|
+
};
|
|
258
|
+
// tag code end
|
|
259
|
+
|
|
260
|
+
// on change event of Text Area
|
|
261
|
+
const textAreaValueChange = ({ target: { value, id } }) => {
|
|
262
|
+
id = Number(id);
|
|
263
|
+
const arr = [...updatedSmsEditor];
|
|
264
|
+
varMap[`${SMS_TRAI_VAR}_${id}`].data = value;
|
|
265
|
+
if (value === '') {
|
|
266
|
+
for (let i = 0; i < varMap[`${SMS_TRAI_VAR}_${id}`].count; i++) {
|
|
267
|
+
arr[id + i] = SMS_TRAI_VAR;
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
for (let i = 0; i < varMap[`${SMS_TRAI_VAR}_${id}`].count; i++) {
|
|
271
|
+
if (i === 0) {
|
|
272
|
+
arr[id] = varMap[`${SMS_TRAI_VAR}_${id}`].data;
|
|
273
|
+
} else {
|
|
274
|
+
arr[id + i] = '';
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
setUpdatedSmsEditor(arr);
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const textAreaValue = (idValue) => {
|
|
282
|
+
if (idValue && updatedSmsEditor) {
|
|
283
|
+
if (
|
|
284
|
+
updatedSmsEditor[idValue] &&
|
|
285
|
+
updatedSmsEditor[idValue] !== SMS_TRAI_VAR
|
|
286
|
+
) {
|
|
287
|
+
return updatedSmsEditor[idValue];
|
|
288
|
+
} else {
|
|
289
|
+
return '';
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return '';
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const capHeading = (index, varCount) => {
|
|
296
|
+
if ((index, varCount)) {
|
|
297
|
+
return (
|
|
298
|
+
<CapHeading
|
|
299
|
+
key={`label${index}`}
|
|
300
|
+
type="h6"
|
|
301
|
+
style={{ margin: `${CAP_SPACE_04} 0`, float: 'right' }}
|
|
302
|
+
>
|
|
303
|
+
{formatMessage(messages.textAreaCounts, {
|
|
304
|
+
varCounts: varCount,
|
|
305
|
+
var: SMS_TRAI_VAR,
|
|
306
|
+
charCounts: varCount * CHARLIMIT,
|
|
307
|
+
})}
|
|
308
|
+
</CapHeading>
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const renderedContent = () => {
|
|
314
|
+
const renderArray = [];
|
|
315
|
+
if (tempMsgArray?.length !== 0) {
|
|
316
|
+
let varCount = 0;
|
|
317
|
+
tempMsgArray.map((elem, index) => {
|
|
318
|
+
let prevElem = '';
|
|
319
|
+
if (elem.includes(SMS_TRAI_VAR)) {
|
|
320
|
+
prevElem =
|
|
321
|
+
tempMsgArray[[index === 0 ? tempMsgArray.length - 1 : index - 1]];
|
|
322
|
+
varCount++;
|
|
323
|
+
totalVarCount++;
|
|
324
|
+
if (prevElem !== SMS_TRAI_VAR) {
|
|
325
|
+
renderArray.push(
|
|
326
|
+
<TextArea
|
|
327
|
+
id={index}
|
|
328
|
+
key={`${elem}${index}`}
|
|
329
|
+
placeholder={props.intl.formatMessage(
|
|
330
|
+
messages.inputplaceHolderText,
|
|
331
|
+
)}
|
|
332
|
+
autosize={{ minRows: 1, maxRows: 3 }}
|
|
333
|
+
onChange={textAreaValueChange}
|
|
334
|
+
value={textAreaValue(index)}
|
|
335
|
+
onFocus={setTextAreaId}
|
|
336
|
+
errorMessage={
|
|
337
|
+
isValidationError &&
|
|
338
|
+
updatedSmsEditor[index] === SMS_TRAI_VAR &&
|
|
339
|
+
formatMessage(messages.textAreaError)
|
|
340
|
+
}
|
|
341
|
+
/>,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
if (index === tempMsgArray.length - 1) {
|
|
345
|
+
renderArray.push(capHeading(index, varCount));
|
|
346
|
+
varCount = 0;
|
|
347
|
+
}
|
|
348
|
+
} else if (varCount > 0) {
|
|
349
|
+
renderArray.push(
|
|
350
|
+
capHeading(index, varCount),
|
|
351
|
+
<CapHeading
|
|
352
|
+
key={`${elem}${index}`}
|
|
353
|
+
style={{ margin: `${CAP_SPACE_16} 0` }}
|
|
354
|
+
>
|
|
355
|
+
{elem}
|
|
356
|
+
</CapHeading>,
|
|
357
|
+
);
|
|
358
|
+
varCount = 0;
|
|
359
|
+
} else {
|
|
360
|
+
renderArray.push(
|
|
361
|
+
<CapHeading
|
|
362
|
+
key={`${elem}${index}`}
|
|
363
|
+
style={{ margin: `${CAP_SPACE_16} 0` }}
|
|
364
|
+
>
|
|
365
|
+
{elem}
|
|
366
|
+
</CapHeading>,
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
return renderArray;
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
// to compute the length of the message
|
|
375
|
+
//30 characters is blocked per'{#var#}' and the remaining string length is added to it
|
|
376
|
+
const smsLengthForVar = () => {
|
|
377
|
+
const msgLenWithoutVar =
|
|
378
|
+
tempMsgArray?.filter((i) => i !== SMS_TRAI_VAR)?.join('').length || 0;
|
|
379
|
+
const totalMessageLength = msgLenWithoutVar + totalVarCount * CHARLIMIT;
|
|
380
|
+
return (
|
|
381
|
+
<CapHeading type="h5" style={{ marginTop: CAP_SPACE_04, float: 'right' }}>
|
|
382
|
+
{formatMessage(messages.totalCharacters, {
|
|
383
|
+
smsCount: Math.ceil(totalMessageLength / 160),
|
|
384
|
+
number: totalMessageLength,
|
|
385
|
+
})}
|
|
386
|
+
</CapHeading>
|
|
387
|
+
);
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
return (
|
|
391
|
+
<>
|
|
392
|
+
<CapSpin spinning={loading}>
|
|
393
|
+
<CapRow>
|
|
394
|
+
{templateDetails && !isEmpty(templateDetails) && (
|
|
395
|
+
<TraiEditTemplateDetails>
|
|
396
|
+
<CapLabelInline type="label1">
|
|
397
|
+
{formatMessage(messages.templateLabel)}
|
|
398
|
+
</CapLabelInline>
|
|
399
|
+
<CapLabelInline type="label2">
|
|
400
|
+
{templateDetails.versions.base.template_name}
|
|
401
|
+
</CapLabelInline>
|
|
402
|
+
<CapLabelInline type="label1">
|
|
403
|
+
{formatMessage(messages.traiEditSeperator)}
|
|
404
|
+
</CapLabelInline>
|
|
405
|
+
<CapLabelInline type="label1">
|
|
406
|
+
{formatMessage(messages.senderIdlabel)}
|
|
407
|
+
</CapLabelInline>
|
|
408
|
+
<CapLabelInline type="label2">
|
|
409
|
+
{templateDetails.versions.base.header}
|
|
410
|
+
</CapLabelInline>
|
|
411
|
+
</TraiEditTemplateDetails>
|
|
412
|
+
)}
|
|
413
|
+
<CapColumn span={14}>
|
|
414
|
+
<CapRow>
|
|
415
|
+
<CapHeader
|
|
416
|
+
title={formatMessage(messages.traiEditTitle)}
|
|
417
|
+
size="regular"
|
|
418
|
+
suffix={
|
|
419
|
+
<TagList
|
|
420
|
+
label={formatMessage(messages.addLabels)}
|
|
421
|
+
onTagSelect={onTagSelect}
|
|
422
|
+
location={location}
|
|
423
|
+
tags={tags || []}
|
|
424
|
+
onContextChange={handleOnTagsContextChange}
|
|
425
|
+
injectedTags={injectedTags || {}}
|
|
426
|
+
/>
|
|
427
|
+
}
|
|
428
|
+
/>
|
|
429
|
+
</CapRow>
|
|
430
|
+
|
|
431
|
+
<CapRow
|
|
432
|
+
style={{
|
|
433
|
+
backgroundColor: CAP_G10,
|
|
434
|
+
padding: CAP_SPACE_16,
|
|
435
|
+
}}
|
|
436
|
+
>
|
|
437
|
+
{renderedContent()}
|
|
438
|
+
</CapRow>
|
|
439
|
+
<CapRow>{smsLengthForVar()}</CapRow>
|
|
440
|
+
<div style={{ marginBottom: '100px' }} />
|
|
441
|
+
</CapColumn>
|
|
442
|
+
<CapColumn span={10}>
|
|
443
|
+
<TemplatePreview
|
|
444
|
+
channel={SMS}
|
|
445
|
+
content={[updatedSmsEditor.join('')]}
|
|
446
|
+
/>
|
|
447
|
+
</CapColumn>
|
|
448
|
+
</CapRow>
|
|
449
|
+
<SMSTraiFooter>
|
|
450
|
+
<CapButton onClick={onDoneCallback} className="create-msg">
|
|
451
|
+
<FormattedMessage {...messages.saveButtonLabel} />
|
|
452
|
+
</CapButton>
|
|
453
|
+
<CapButton
|
|
454
|
+
onClick={handleClose}
|
|
455
|
+
className="cancel-msg"
|
|
456
|
+
type="secondary"
|
|
457
|
+
>
|
|
458
|
+
<FormattedMessage {...messages.cancelButtonLabel} />
|
|
459
|
+
</CapButton>
|
|
460
|
+
</SMSTraiFooter>
|
|
461
|
+
</CapSpin>
|
|
462
|
+
</>
|
|
463
|
+
);
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
const mapStateToProps = createStructuredSelector({
|
|
467
|
+
templateDetails: makeSelectTemplateDetailsResponse(),
|
|
468
|
+
metaEntities: makeSelectMetaEntities(),
|
|
469
|
+
injectedTags: setInjectedTags(),
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
const mapDispatchToProps = (dispatch) => {
|
|
473
|
+
return {
|
|
474
|
+
actions: bindActionCreators(actions, dispatch),
|
|
475
|
+
};
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
export default withCreatives({
|
|
479
|
+
WrappedComponent: injectIntl(SmsTraiEdit),
|
|
480
|
+
mapStateToProps,
|
|
481
|
+
mapDispatchToProps,
|
|
482
|
+
userAuth: true,
|
|
483
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SmsTrai Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the SmsTrai component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
const prefix = 'app.v2containers.SmsTrai.Edit';
|
|
8
|
+
|
|
9
|
+
export default defineMessages({
|
|
10
|
+
saveButtonLabel: {
|
|
11
|
+
id: `${prefix}.saveButtonLabel`,
|
|
12
|
+
defaultMessage: 'Save',
|
|
13
|
+
},
|
|
14
|
+
cancelButtonLabel: {
|
|
15
|
+
id: `${prefix}.cancelButtonLabel`,
|
|
16
|
+
defaultMessage: 'Cancel',
|
|
17
|
+
},
|
|
18
|
+
traiEditTitle: {
|
|
19
|
+
id: `${prefix}.traiEditTitle`,
|
|
20
|
+
defaultMessage: 'Message',
|
|
21
|
+
},
|
|
22
|
+
addLabels: {
|
|
23
|
+
id: `${prefix}.addLabels`,
|
|
24
|
+
defaultMessage: 'Add labels',
|
|
25
|
+
},
|
|
26
|
+
inputplaceHolderText: {
|
|
27
|
+
id: `${prefix}.inputplaceHolderText`,
|
|
28
|
+
defaultMessage: 'Add labels or text or combination of both',
|
|
29
|
+
},
|
|
30
|
+
textAreaCounts: {
|
|
31
|
+
id: `${prefix}.textAreaCounts`,
|
|
32
|
+
defaultMessage: '{varCounts} Variables {var}: max. {charCounts} characters',
|
|
33
|
+
},
|
|
34
|
+
totalCharacters: {
|
|
35
|
+
id: `${prefix}.totalCharacters`,
|
|
36
|
+
defaultMessage: '{smsCount} SMS ({number} characters)',
|
|
37
|
+
},
|
|
38
|
+
smsEditNotification: {
|
|
39
|
+
id: `${prefix}.smsEditNotification`,
|
|
40
|
+
defaultMessage: 'Trai SMS template updated successfully',
|
|
41
|
+
},
|
|
42
|
+
textAreaError: {
|
|
43
|
+
id: `${prefix}.textAreaError`,
|
|
44
|
+
defaultMessage: 'Template cannot be empty',
|
|
45
|
+
},
|
|
46
|
+
templateLabel: {
|
|
47
|
+
id: `${prefix}.templateLabel`,
|
|
48
|
+
defaultMessage: 'Template',
|
|
49
|
+
},
|
|
50
|
+
traiEditSeperator: {
|
|
51
|
+
id: `${prefix}.traiEditSeperator`,
|
|
52
|
+
defaultMessage: '|',
|
|
53
|
+
},
|
|
54
|
+
senderIdlabel: {
|
|
55
|
+
id: `${prefix}.senderIdlabel`,
|
|
56
|
+
defaultMessage: 'Sender ID',
|
|
57
|
+
},
|
|
58
|
+
});
|