@capillarytech/creatives-library 7.17.35 → 7.17.36

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.
Files changed (46) hide show
  1. package/containers/Templates/actions.js +0 -5
  2. package/index.js +6 -0
  3. package/package.json +1 -1
  4. package/routes.js +5 -0
  5. package/services/api.js +6 -1
  6. package/v2Components/WhatsappStatusContainer/_whatsappStatusContainer.scss +2 -1
  7. package/v2Containers/App/constants.js +1 -0
  8. package/v2Containers/CreativesContainer/SlideBoxContent.js +13 -0
  9. package/v2Containers/CreativesContainer/SlideBoxHeader.js +9 -6
  10. package/v2Containers/CreativesContainer/constants.js +1 -0
  11. package/v2Containers/CreativesContainer/index.scss +3 -0
  12. package/v2Containers/CreativesContainer/messages.js +8 -0
  13. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +6 -1
  14. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +58 -0
  15. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +18114 -88
  16. package/v2Containers/Templates/_templates.scss +20 -2
  17. package/v2Containers/Templates/actions.js +4 -3
  18. package/v2Containers/Templates/constants.js +2 -1
  19. package/v2Containers/Templates/index.js +319 -120
  20. package/v2Containers/Templates/messages.js +28 -8
  21. package/v2Containers/Templates/reducer.js +3 -1
  22. package/v2Containers/Templates/sagas.js +2 -2
  23. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +724 -43
  24. package/v2Containers/Templates/tests/actions.test.js +18 -0
  25. package/v2Containers/Templates/tests/index.test.js +52 -1
  26. package/v2Containers/Templates/tests/mockData.js +41 -1
  27. package/v2Containers/Templates/tests/reducer.test.js +50 -0
  28. package/v2Containers/Templates/tests/sagas.test.js +40 -2
  29. package/v2Containers/Templates/tests/selector.test.js +17 -0
  30. package/v2Containers/TemplatesV2/index.js +2 -2
  31. package/v2Containers/TemplatesV2/messages.js +4 -0
  32. package/v2Containers/Zalo/actions.js +17 -0
  33. package/v2Containers/Zalo/constants.js +57 -0
  34. package/v2Containers/Zalo/index.js +391 -0
  35. package/v2Containers/Zalo/index.scss +76 -0
  36. package/v2Containers/Zalo/messages.js +74 -0
  37. package/v2Containers/Zalo/reducer.js +57 -0
  38. package/v2Containers/Zalo/saga.js +35 -0
  39. package/v2Containers/Zalo/selectors.js +14 -0
  40. package/v2Containers/Zalo/tests/actions.test.js +20 -0
  41. package/v2Containers/Zalo/tests/index.test.js +127 -0
  42. package/v2Containers/Zalo/tests/mockData.js +11470 -0
  43. package/v2Containers/Zalo/tests/reducer.test.js +85 -0
  44. package/v2Containers/Zalo/tests/saga.test.js +115 -0
  45. package/v2Containers/Zalo/tests/selectors.test.js +52 -0
  46. package/v2Containers/mockdata.js +817 -680
@@ -0,0 +1,391 @@
1
+ /* eslint-disable react/prop-types */
2
+ import React, { useState, useEffect } from "react";
3
+ import { injectIntl } from "react-intl";
4
+ import { createStructuredSelector } from "reselect";
5
+ import { bindActionCreators } from "redux";
6
+ import { get } from "lodash";
7
+ import styled from 'styled-components';
8
+ import {
9
+ CapSpin,
10
+ CapRow,
11
+ CapColumn,
12
+ CapLabel,
13
+ CapAlert,
14
+ CapInput,
15
+ CapHeading,
16
+ CapHeader,
17
+ CapIcon,
18
+ } from "@capillarytech/cap-ui-library";
19
+ import {
20
+ CAP_SPACE_16,
21
+ CAP_SPACE_24,
22
+ CAP_SPACE_32,
23
+ CAP_WHITE,
24
+ } from '@capillarytech/cap-ui-library/styled/variables';
25
+ import messages from "./messages";
26
+ import withCreatives from "../../hoc/withCreatives";
27
+ import {
28
+ SUCCESS_ALERT,
29
+ REQUEST,
30
+ EMBEDDED,
31
+ DEFAULT,
32
+ TAG,
33
+ FULL,
34
+ ALL,
35
+ LIBRARY,
36
+ ERROR_ALERT,
37
+ WARNING_ALERT,
38
+ ZALO_STATUSES,
39
+ ENABLE,
40
+ } from "./constants";
41
+ import "./index.scss";
42
+ import { makeSelectZalo } from "./selectors";
43
+ import * as zaloActions from "./actions";
44
+ import * as templateActions from "../Templates/actions";
45
+ import { makeSelectTemplates } from "../Templates/selectors";
46
+ import TagList from "../TagList";
47
+ import globalMessages from "../Cap/messages";
48
+ import { makeSelectMetaEntities, setInjectedTags } from "../Cap/selectors";
49
+ import * as globalActions from "../Cap/actions";
50
+ import { validateTags } from "../../utils/tagValidations";
51
+
52
+
53
+ export const Zalo = ({
54
+ intl,
55
+ actions,
56
+ zaloTemplateInfoData,
57
+ templateData,
58
+ location,
59
+ metaEntities,
60
+ getDefaultTags,
61
+ supportedTags,
62
+ injectedTags,
63
+ selectedOfferDetails,
64
+ template,
65
+ }) => {
66
+ const { formatMessage } = intl;
67
+ const [zaloTemplateListParams, setZaloTemplateListParams] = useState([]);
68
+ const [templatePreviewUrl, setTemplatePreviewUrl] = useState("");
69
+ const [tags, updateTags] = useState([]);
70
+ const [textAreaId, updateTextAreaId] = useState("");
71
+ const [templateStatus, setZaloTemplateStatus] = useState(ENABLE);
72
+
73
+ const ZaloFooter = styled.div`
74
+ background-color: ${CAP_WHITE};
75
+ position: fixed;
76
+ bottom: 0;
77
+ width: 100%;
78
+ margin-left: -32px;
79
+ padding: ${CAP_SPACE_32} ${CAP_SPACE_24};
80
+ z-index: 1;
81
+
82
+ .ant-btn {
83
+ margin-right: ${CAP_SPACE_16};
84
+ }
85
+ }
86
+ `;
87
+
88
+ const { zaloTemplateInfoStatus, zaloTemplateInfoValue } =
89
+ zaloTemplateInfoData;
90
+
91
+ // here listParams and previewUrl data will be setting in respective states. We got that data by destructring
92
+ useEffect(() => {
93
+ if (zaloTemplateInfoValue) {
94
+ const {
95
+ versions: {
96
+ base: {
97
+ content: {
98
+ zalo: { listParams = [], previewUrl = "", status = "" } = {},
99
+ } = {},
100
+ } = {},
101
+ } = {},
102
+ } = zaloTemplateInfoValue;
103
+ setZaloTemplateListParams(listParams);
104
+ setTemplatePreviewUrl(previewUrl);
105
+ setZaloTemplateStatus(status);
106
+ updateTextAreaId(listParams[0]?.name);
107
+ }
108
+ }, [zaloTemplateInfoValue]);
109
+
110
+ useEffect(() => {
111
+ const {
112
+ weCrmAccounts: [
113
+ {
114
+ name,
115
+ sourceAccountIdentifier,
116
+ configs: { token },
117
+ },
118
+ ],
119
+ } = template;
120
+ const { _id: id } = templateData;
121
+ actions.getTemplateInfoById({
122
+ username: name,
123
+ oa_id: sourceAccountIdentifier,
124
+ token,
125
+ id,
126
+ });
127
+ }, []);
128
+
129
+ useEffect(() => {
130
+ let tag = get(metaEntities, `tags.standard`, []);
131
+ const { type, module } = location?.query || {};
132
+ if (type === EMBEDDED && module === LIBRARY && !getDefaultTags) {
133
+ tag = supportedTags;
134
+ }
135
+ updateTags(tag);
136
+ }, [metaEntities]);
137
+
138
+ useEffect(() => {
139
+ //fetching tags
140
+ const { type, module } = location?.query || {};
141
+ const isEmbedded = type === EMBEDDED;
142
+ const query = {
143
+ layout: "SMS",
144
+ type: TAG,
145
+ context: isEmbedded ? module : DEFAULT,
146
+ embedded: isEmbedded ? type : FULL,
147
+ };
148
+ if (getDefaultTags) {
149
+ query.context = getDefaultTags;
150
+ }
151
+ actions.fetchSchemaForEntity(query);
152
+ }, []);
153
+
154
+ const handleOnTagsContextChange = (data) => {
155
+ const { type } = location?.query || {};
156
+ const isEmbedded = type === EMBEDDED;
157
+ const query = {
158
+ layout: "SMS",
159
+ type: TAG,
160
+ context:
161
+ (data || "").toLowerCase() === ALL
162
+ ? DEFAULT
163
+ : (data || "").toLowerCase(),
164
+ embedded: isEmbedded ? type : FULL,
165
+ };
166
+ actions.fetchSchemaForEntity(query);
167
+ };
168
+
169
+ const onTagSelect = (data) => {
170
+ if (data && textAreaId) {
171
+ const updatedZaloTemplateInfo = zaloTemplateListParams.map((item) => {
172
+ if (item?.name === textAreaId) {
173
+ const text = `${item?.value ? item?.value : ""}{{${data}}}`;
174
+ return {
175
+ ...item,
176
+ value: text,
177
+ error:
178
+ text.length <= item?.minLength || text.length > item?.maxLength
179
+ ? formatMessage(messages.maxMinLengthMessage, {
180
+ minLength: item?.minLength,
181
+ maxLength: item?.maxLength,
182
+ })
183
+ : "",
184
+ };
185
+ }
186
+ return item;
187
+ });
188
+ setZaloTemplateListParams(updatedZaloTemplateInfo);
189
+ }
190
+ };
191
+
192
+ const tagValidationErrorMessage = (message) => {
193
+ const tagValidationResponse =
194
+ validateTags({
195
+ content: message,
196
+ tagsParam: tags,
197
+ injectedTagsParams: injectedTags,
198
+ location,
199
+ tagModule: getDefaultTags,
200
+ }) || {};
201
+ const { unsupportedTags = [], isBraceError } = tagValidationResponse;
202
+ let tagError = "";
203
+ if (unsupportedTags.length > 0) {
204
+ tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
205
+ unsupportedTags,
206
+ });
207
+ }
208
+ if (isBraceError) {
209
+ tagError = formatMessage(globalMessages.unbalanacedCurlyBraces);
210
+ }
211
+ return tagError;
212
+ };
213
+
214
+ // this function is used for handle form data change in this also handle error validtion on change of value
215
+ const handleFormDataChange = (e, field) => {
216
+ const {
217
+ target: { value },
218
+ } = e;
219
+ const updatedZaloTemplateInfo = zaloTemplateListParams?.map((item) => {
220
+ if (item?.name === field?.name) {
221
+ const error = handleErrorValidation(value, field);
222
+ return {
223
+ ...item,
224
+ value,
225
+ error,
226
+ };
227
+ }
228
+ return item;
229
+ });
230
+ setZaloTemplateListParams(updatedZaloTemplateInfo);
231
+ };
232
+
233
+ //this function is used for checking errror validation in this it validate tags error and length error
234
+ const handleErrorValidation = (e, field) => {
235
+ const { minLength, maxLength } = field;
236
+ let error = tagValidationErrorMessage(e);
237
+
238
+ if (e.length <= minLength || e.length > maxLength) {
239
+ error = formatMessage(messages.maxMinLengthMessage, {
240
+ minLength,
241
+ maxLength,
242
+ });
243
+ }
244
+
245
+ return error;
246
+ };
247
+
248
+ const renderTextBoxesForListParams = (listParam) => {
249
+ const { name, error, value } = listParam;
250
+ return (
251
+ <CapInput
252
+ id={`zalo-${name}`}
253
+ onChange={(e) => handleFormDataChange(e, listParam)}
254
+ errorMessage={error}
255
+ placeholder={formatMessage(messages.addVariableWithMessage)}
256
+ defaultValue={value || ""}
257
+ value={value || ""}
258
+ size="default"
259
+ onFocus={() => setTextAreaId(name)}
260
+ />
261
+ );
262
+ };
263
+
264
+ const setTextAreaId = (fieldName) => {
265
+ updateTextAreaId(fieldName);
266
+ };
267
+
268
+ const handlePreview = () => {
269
+ window.open(templatePreviewUrl, "_blank");
270
+ };
271
+
272
+ const getTemplateStatusType = () => {
273
+ switch (templateStatus) {
274
+ case ZALO_STATUSES.ENABLE:
275
+ return SUCCESS_ALERT;
276
+ case ZALO_STATUSES.REJECT:
277
+ return ERROR_ALERT;
278
+ default:
279
+ return WARNING_ALERT;
280
+ }
281
+ };
282
+
283
+ return (
284
+ <CapSpin spinning={zaloTemplateInfoStatus === REQUEST}>
285
+ <CapRow type="flex" className="cap-zalo-creatives">
286
+ <CapColumn span={14}>
287
+ <CapAlert
288
+ message={
289
+ <CapLabel type="label2">
290
+ {formatMessage(messages.approvedStatusMsg, {
291
+ status: formatMessage(messages?.[templateStatus]),
292
+ })}
293
+ </CapLabel>
294
+ }
295
+ type={getTemplateStatusType()}
296
+ />
297
+ <CapRow>
298
+ <CapRow className="whatsapp-render-heading">
299
+ <CapHeader
300
+ className="zalo-variable-heading"
301
+ title={
302
+ <CapHeading type="h4">
303
+ {formatMessage(messages.variables)}
304
+ </CapHeading>
305
+ }
306
+ suffix={
307
+ <TagList
308
+ label={formatMessage(globalMessages.addLabels)}
309
+ onTagSelect={onTagSelect}
310
+ location={location}
311
+ tags={tags || []}
312
+ onContextChange={handleOnTagsContextChange}
313
+ injectedTags={injectedTags || {}}
314
+ selectedOfferDetails={selectedOfferDetails}
315
+ />
316
+ }
317
+ />
318
+ </CapRow>
319
+ <CapRow className="zalo-variable-list">
320
+ {zaloTemplateListParams?.map((listParam) => {
321
+ const { name = "", maxLength, value = "" } = listParam;
322
+ return (
323
+ <>
324
+ {renderTextBoxesForListParams(listParam)}
325
+ <CapRow className="variable-field-container">
326
+ <CapLabel className="variable-field-name">
327
+ {formatMessage(messages.variableType, {
328
+ fieldName: name,
329
+ })}
330
+ </CapLabel>
331
+ <CapLabel className="variable-field-length">
332
+ {formatMessage(messages.charactersCount, {
333
+ variableLength: value?.length,
334
+ fixedLength: maxLength,
335
+ })}
336
+ </CapLabel>
337
+ </CapRow>
338
+ </>
339
+ );
340
+ })}
341
+ </CapRow>
342
+ </CapRow>
343
+ </CapColumn>
344
+ <CapColumn type="flex" span={10} className="zalo-preview-container">
345
+ <CapRow>
346
+ <CapLabel className="preview-head">
347
+ {formatMessage(messages.previewHead)}
348
+ </CapLabel>
349
+ </CapRow>
350
+ <CapRow>
351
+ <CapLabel className="preview-text">
352
+ {formatMessage(messages.previewText)}
353
+ </CapLabel>
354
+ </CapRow>
355
+ <CapRow>
356
+ <CapLabel
357
+ data-testid="preview-link-button"
358
+ onClick={handlePreview}
359
+ className="preview-link"
360
+ >
361
+ {formatMessage(messages.openPreview)}{" "}
362
+ <CapIcon type="open-in-new-light"></CapIcon>
363
+ </CapLabel>
364
+ </CapRow>
365
+ </CapColumn>
366
+ </CapRow>
367
+ <ZaloFooter></ZaloFooter>
368
+ </CapSpin>
369
+ );
370
+ };
371
+
372
+ const mapStateToProps = createStructuredSelector({
373
+ zaloTemplateInfoData: makeSelectZalo(),
374
+ template: makeSelectTemplates(),
375
+ metaEntities: makeSelectMetaEntities(),
376
+ injectedTags: setInjectedTags(),
377
+ });
378
+
379
+ const mapDispatchToProps = (dispatch) => ({
380
+ actions: bindActionCreators(
381
+ { ...zaloActions, ...templateActions, ...globalActions },
382
+ dispatch
383
+ ),
384
+ });
385
+
386
+ export default withCreatives({
387
+ WrappedComponent: injectIntl(Zalo),
388
+ mapStateToProps,
389
+ mapDispatchToProps,
390
+ userAuth: true,
391
+ });
@@ -0,0 +1,76 @@
1
+ @import '~@capillarytech/cap-ui-library/styles/_variables.scss';
2
+
3
+
4
+ .cap-zalo-creatives {
5
+ .zalo-variable-heading {
6
+ margin-top: $CAP_SPACE_24;
7
+ }
8
+
9
+ .zalo-variable-list {
10
+ margin: 0px 0px 200px;
11
+
12
+ input {
13
+ height: $CAP_SPACE_40;
14
+ margin-top: $CAP_SPACE_16;
15
+ }
16
+
17
+ .ant-calendar-picker {
18
+ width: 100%;
19
+
20
+ .ant-calendar-picker-icon {
21
+ top: 50%;
22
+ }
23
+ }
24
+
25
+ .ant-input-suffix {
26
+ top: 62%;
27
+ }
28
+ }
29
+
30
+ .variable-field-container {
31
+ display: flex;
32
+ margin-top: $CAP_SPACE_08;
33
+
34
+ div {
35
+ font-weight: 400;
36
+ }
37
+
38
+ .variable-field-length {
39
+ position: absolute;
40
+ right: 0;
41
+ }
42
+ }
43
+
44
+ .zalo-preview-container {
45
+ text-align: center;
46
+ position: fixed;
47
+ right: 0;
48
+ padding-left: 194px;
49
+ padding-right: 116px;
50
+
51
+ .preview-head {
52
+ font-weight: 500;
53
+ font-size: $FONT_SIZE_M;
54
+ color: $FONT_COLOR_01;
55
+ }
56
+
57
+ .preview-text {
58
+ font-weight: 400;
59
+ font-size: $FONT_SIZE_S;
60
+ padding-top: $CAP_SPACE_08;
61
+ }
62
+
63
+ .preview-link {
64
+ font-weight: 500;
65
+ font-size: $FONT_SIZE_M;
66
+ color: $FONT_COLOR_05;
67
+ margin-top: $CAP_SPACE_19;
68
+ cursor: pointer;
69
+
70
+ svg {
71
+ height: $CAP_SPACE_16;
72
+ width: $CAP_SPACE_16;
73
+ }
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,74 @@
1
+ import { defineMessages } from "react-intl";
2
+ const prefix = `creatives.containersV2.zalo`;
3
+
4
+ export default defineMessages({
5
+ approvedStatusMsg: {
6
+ id: `${prefix}.approvedStatusMsg`,
7
+ defaultMessage: "This template has been {status}",
8
+ },
9
+ variables: {
10
+ id: `${prefix}.variables`,
11
+ defaultMessage: "Variables",
12
+ },
13
+ addVariableWithMessage: {
14
+ id: `${prefix}.addVariableWithMessage`,
15
+ defaultMessage: "Add labels or text or combination of both",
16
+ },
17
+ variableType: {
18
+ id: `${prefix}.variableType`,
19
+ defaultMessage: "Variable type: <{fieldName}>",
20
+ },
21
+ charactersCount: {
22
+ id: `${prefix}.charactersCount`,
23
+ defaultMessage: "Characters count {variableLength}/{fixedLength}",
24
+ },
25
+ maxMinLengthMessage: {
26
+ id: `${prefix}.maxLengthMessage`,
27
+ defaultMessage:
28
+ "Character count for this variable should be in between {minLength} to {maxLength}",
29
+ },
30
+ previewHead: {
31
+ id: `${prefix}.previewText`,
32
+ defaultMessage: "Preview",
33
+ },
34
+ previewText: {
35
+ id: `${prefix}.previewText`,
36
+ defaultMessage: `Preview of the template is generated on the Zalo platform. Click on ‘Open preview’ to view it in a new tab`,
37
+ },
38
+ openPreview: {
39
+ id: `${prefix}.openPreview`,
40
+ defaultMessage: "Open Preview",
41
+ },
42
+ ENABLE_STATUS: {
43
+ id: `${prefix}.ENABLE_STATUS`,
44
+ defaultMessage: 'Enable',
45
+ },
46
+ REJECT_STATUS: {
47
+ id: `${prefix}.REJECT_STATUS`,
48
+ defaultMessage: 'Reject',
49
+ },
50
+ DISABLE_STATUS: {
51
+ id: `${prefix}.DISABLE_STATUS`,
52
+ defaultMessage: 'Disable',
53
+ },
54
+ PENDING_REVIEW_STATUS: {
55
+ id: `${prefix}.PENDING_REVIEW_STATUS`,
56
+ defaultMessage: 'Review Pending',
57
+ },
58
+ ENABLE: {
59
+ id: `${prefix}.ENABLE`,
60
+ defaultMessage: 'enabled',
61
+ },
62
+ REJECT: {
63
+ id: `${prefix}.REJECT`,
64
+ defaultMessage: 'rejected',
65
+ },
66
+ DISABLE: {
67
+ id: `${prefix}.DISABLE`,
68
+ defaultMessage: 'disabled',
69
+ },
70
+ PENDING_REVIEW: {
71
+ id: `${prefix}.PENDING_REVIEW`,
72
+ defaultMessage: 'pending review',
73
+ }
74
+ });
@@ -0,0 +1,57 @@
1
+ import { fromJS } from "immutable";
2
+ import {
3
+ ZALO_TEMPLATE_INFO_ERROR,
4
+ ZALO_TEMPLATE_INFO_SUCCESS,
5
+ ZALO_TEMPLATE_INFO_REQUEST,
6
+ ZALO_TEMPLATE_PREVIEW_RESET,
7
+ ZALO_TEMPLATE_PREVIEW_INFO,
8
+ SUCCESS,
9
+ REQUEST,
10
+ ERROR,
11
+ } from "./constants";
12
+
13
+ const initialState = fromJS({
14
+ zaloTemplateInfoStatus: "",
15
+ zaloTemplateInfoValue: "",
16
+ zaloTemplateInfoError: "",
17
+ zaloTemplatePreviewData: "",
18
+ });
19
+
20
+ const zaloReducer = (state = initialState, action) => {
21
+ switch (action.type) {
22
+ case ZALO_TEMPLATE_INFO_REQUEST:
23
+ return state
24
+ .set("zaloTemplateInfoStatus", REQUEST)
25
+ .set("zaloTemplateInfoValue", "")
26
+ .set("zaloTemplateInfoError", null);
27
+
28
+ case ZALO_TEMPLATE_INFO_SUCCESS:
29
+ return state
30
+ .set("zaloTemplateInfoStatus", SUCCESS)
31
+ .set("zaloTemplateInfoValue", action.result)
32
+ .set("zaloTemplateInfoError", null);
33
+
34
+ case ZALO_TEMPLATE_INFO_ERROR:
35
+ return state
36
+ .set("zaloTemplateInfoStatus", ERROR)
37
+ .set("zaloTemplateInfoValue", "")
38
+ .set("zaloTemplateInfoError", action.error);
39
+
40
+ case ZALO_TEMPLATE_PREVIEW_INFO:
41
+ return state
42
+ .set("zaloTemplateInfoStatus", SUCCESS)
43
+ .set("zaloTemplatePreviewData", action.result)
44
+ .set("zaloTemplateInfoError", null);
45
+
46
+ case ZALO_TEMPLATE_PREVIEW_RESET:
47
+ return state
48
+ .set("zaloTemplateInfoStatus", REQUEST)
49
+ .set("zaloTemplatePreviewData", "")
50
+ .set("zaloTemplateInfoError", null);
51
+
52
+ default:
53
+ return state;
54
+ }
55
+ };
56
+
57
+ export default zaloReducer;
@@ -0,0 +1,35 @@
1
+ import { call, put, takeLatest } from "redux-saga/effects";
2
+ import * as Api from "../../services/api";
3
+ import {
4
+ ZALO_TEMPLATE_INFO_REQUEST,
5
+ ZALO_TEMPLATE_INFO_SUCCESS,
6
+ ZALO_TEMPLATE_INFO_ERROR,
7
+ ZALO_TEMPLATE_PREVIEW_INFO,
8
+ } from "./constants";
9
+
10
+ export function* getTemplateInfoById({ payload }) {
11
+ try {
12
+ const res = yield call(Api.getTemplateInfoById, payload);
13
+ if (res?.success) {
14
+ yield put({
15
+ type: payload?.preview
16
+ ? ZALO_TEMPLATE_PREVIEW_INFO
17
+ : ZALO_TEMPLATE_INFO_SUCCESS,
18
+ result: res?.response || {},
19
+ });
20
+ } else {
21
+ yield put({
22
+ type: ZALO_TEMPLATE_INFO_ERROR,
23
+ error: res?.error || res?.message,
24
+ });
25
+ }
26
+ } catch (error) {
27
+ yield put({ type: ZALO_TEMPLATE_INFO_ERROR, error });
28
+ }
29
+ }
30
+
31
+ export function* watchForGetTemplateInfoById() {
32
+ yield takeLatest(ZALO_TEMPLATE_INFO_REQUEST, getTemplateInfoById);
33
+ }
34
+
35
+ export default [watchForGetTemplateInfoById];
@@ -0,0 +1,14 @@
1
+ import { createSelector } from "reselect";
2
+ import { fromJS } from "immutable";
3
+
4
+ const selectZaloDomain = (state = fromJS({})) => state.get("zalo");
5
+
6
+ const makeSelectZalo = () =>
7
+ createSelector(selectZaloDomain, (substate = fromJS({})) => ({
8
+ zaloTemplateInfoStatus: substate.get("zaloTemplateInfoStatus"),
9
+ zaloTemplateInfoValue: substate.get("zaloTemplateInfoValue"),
10
+ zaloTemplateInfoError: substate.get("zaloTemplateInfoError"),
11
+ zaloTemplatePreviewData: substate.get("zaloTemplatePreviewData"),
12
+ }));
13
+
14
+ export { makeSelectZalo, selectZaloDomain };
@@ -0,0 +1,20 @@
1
+ import * as types from "../constants";
2
+ import * as actions from "../actions";
3
+
4
+ describe("Test zalo actions", () => {
5
+ it("has a type of ZALO_TEMPLATE_INFO_REQUEST action", () => {
6
+ const payload = {};
7
+ const expected = {
8
+ type: types.ZALO_TEMPLATE_INFO_REQUEST,
9
+ payload,
10
+ };
11
+ expect(actions.getTemplateInfoById(payload)).toEqual(expected);
12
+ });
13
+
14
+ it("has a type of ZALO_TEMPLATE_PREVIEW_RESET action", () => {
15
+ const expected = {
16
+ type: types.ZALO_TEMPLATE_PREVIEW_RESET,
17
+ };
18
+ expect(actions.resetTemplateInfoData()).toEqual(expected);
19
+ });
20
+ });