@capillarytech/creatives-library 7.17.81 → 7.17.82-alpha.0

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "7.17.81",
4
+ "version": "7.17.82-alpha.0",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -25,6 +25,7 @@
25
25
  "jest-date-mock": "^1.0.8",
26
26
  "jquery": "^3.3.1",
27
27
  "load-script": "^1.0.0",
28
+ "ml-matrix": "6.10.8",
28
29
  "node-html-parser": "^5.4.2-0",
29
30
  "normalizr": "^3.2.3",
30
31
  "papaparse": "^5.3.1",
@@ -0,0 +1,230 @@
1
+ import React from "react";
2
+ import { injectIntl } from "react-intl";
3
+ import cloneDeep from "lodash/cloneDeep";
4
+ import CapRow from "@capillarytech/cap-ui-library/CapRow";
5
+ import CapHeader from "@capillarytech/cap-ui-library/CapHeader";
6
+ import CapHeading from "@capillarytech/cap-ui-library/CapHeading";
7
+ import CapTooltipWithInfo from "@capillarytech/cap-ui-library/CapTooltipWithInfo";
8
+ import CapInput from "@capillarytech/cap-ui-library/CapInput";
9
+ import CapError from "@capillarytech/cap-ui-library/CapError";
10
+ import CapTooltip from "@capillarytech/cap-ui-library/CapTooltip";
11
+ import CapButton from "@capillarytech/cap-ui-library/CapButton";
12
+ import CapColumn from "@capillarytech/cap-ui-library/CapColumn";
13
+ import CapIcon from "@capillarytech/cap-ui-library/CapIcon";
14
+ import CapLabel from "@capillarytech/cap-ui-library/CapLabel";
15
+ import { CAP_SPACE_04 } from "@capillarytech/cap-ui-library/styled/variables";
16
+ import messages from "./messages";
17
+ import "./index.scss";
18
+ import globalMessages from "../../v2Containers/Cap/messages";
19
+ import { INITIAL_QUICK_REPLY_DATA } from "../../v2Containers/Whatsapp/constants";
20
+ import ctaMessages from "../CapWhatsappCTA/messages";
21
+
22
+ const CapWhatsappQuickReply = ({
23
+ quickReplyData,
24
+ renderMessageLength,
25
+ setQuickReplyData,
26
+ isEditFlow,
27
+ intl,
28
+ }) => {
29
+ const { TextArea } = CapInput;
30
+ const { formatMessage } = intl;
31
+
32
+ const handleTextChange = (e, index) => {
33
+ let error = false;
34
+ const {
35
+ target: { value },
36
+ } = e;
37
+ if (value?.length > 20) {
38
+ error = formatMessage(messages.templateButtonTextLengthError);
39
+ }
40
+ setQuickReplyData(
41
+ quickReplyData.map((quickReply) => {
42
+ if (quickReply?.index === index) {
43
+ return {
44
+ ...quickReply,
45
+ text: value,
46
+ error: error,
47
+ };
48
+ } else return quickReply;
49
+ })
50
+ );
51
+ };
52
+
53
+ const handleSaveAndEditBtn = (index, value) => {
54
+ setQuickReplyData(
55
+ quickReplyData.map((quickReply) => {
56
+ if (quickReply?.index === index) {
57
+ return {
58
+ ...quickReply,
59
+ isSaved: value,
60
+ };
61
+ } else return quickReply;
62
+ })
63
+ );
64
+ };
65
+
66
+ const handleDelete = (index) => {
67
+ setQuickReplyData((prevState) => {
68
+ const clonedQuickReplyData = cloneDeep(prevState);
69
+ const filteredQuickReplyData = clonedQuickReplyData.filter(
70
+ (i) => i.index !== index
71
+ );
72
+ return filteredQuickReplyData.map((quickReply, index) => {
73
+ quickReply.index = index;
74
+ return quickReply;
75
+ });
76
+ });
77
+ };
78
+
79
+ const addQuickReply = () => {
80
+ INITIAL_QUICK_REPLY_DATA[0].index = quickReplyData?.length || 0;
81
+ const clonedQuickReplyData = [
82
+ ...quickReplyData,
83
+ ...INITIAL_QUICK_REPLY_DATA,
84
+ ];
85
+ setQuickReplyData(clonedQuickReplyData);
86
+ };
87
+
88
+ const quickReplyDisable =
89
+ quickReplyData?.length === 1 && !quickReplyData?.[0].isSaved;
90
+ return (
91
+ <>
92
+ {quickReplyData?.length > 0 && !isEditFlow && (
93
+ <CapRow>
94
+ {quickReplyData?.map(({ index, isSaved, text, error }) => {
95
+ if (!isSaved) {
96
+ return (
97
+ <CapRow className="cap-whatsapp-quick-reply">
98
+ <CapRow
99
+ className="whatsapp-button-text-container"
100
+ key={index}
101
+ >
102
+ <CapHeader
103
+ title={
104
+ <CapHeading
105
+ type="h4"
106
+ className="whatsapp-button-text-heading"
107
+ >
108
+ {formatMessage(messages.buttonText)}
109
+ <CapTooltipWithInfo
110
+ placement="right"
111
+ infoIconProps={{
112
+ style: { marginLeft: CAP_SPACE_04 },
113
+ }}
114
+ autoAdjustOverflow
115
+ />
116
+ </CapHeading>
117
+ }
118
+ />
119
+ <CapRow className="whatsapp-button-text-input">
120
+ <TextArea
121
+ autosize={{ minRows: 1, maxRows: 5 }}
122
+ placeholder={formatMessage(
123
+ messages.buttonTextPlaceholder
124
+ )}
125
+ onChange={(e) => handleTextChange(e, index)}
126
+ errorMessage={
127
+ error && (
128
+ <CapError className="whatsapp-template-message-error">
129
+ {error}
130
+ </CapError>
131
+ )
132
+ }
133
+ value={text || ""}
134
+ />
135
+ </CapRow>
136
+ {renderMessageLength("buttonText", text?.length || 0)}
137
+ <CapRow className="whatsapp-cta-save-delete-btn">
138
+ <CapTooltip
139
+ title={
140
+ text === "" || error
141
+ ? formatMessage(ctaMessages.ctaSaveDisabled)
142
+ : ""
143
+ }
144
+ placement={"bottom"}
145
+ >
146
+ <div className="button-disabled-tooltip-wrapper">
147
+ <CapButton
148
+ onClick={() => {
149
+ handleSaveAndEditBtn(index, true);
150
+ }}
151
+ disabled={text === "" || error}
152
+ className="whatsapp-cta-save-btn"
153
+ >
154
+ {formatMessage(globalMessages.save)}
155
+ </CapButton>
156
+ </div>
157
+ </CapTooltip>
158
+ <CapButton
159
+ onClick={() => {
160
+ handleDelete(index);
161
+ }}
162
+ className="whatsapp-cta-delete-btn whatsapp-quick-reply-delete-button"
163
+ type="secondary"
164
+ >
165
+ {formatMessage(globalMessages.delete)}
166
+ </CapButton>
167
+ </CapRow>
168
+ </CapRow>
169
+ </CapRow>
170
+ );
171
+ } else {
172
+ return (
173
+ <CapRow className="cap-whatsapp-quick-reply">
174
+ <CapRow className="whatsapp-quick-reply-save-container">
175
+ <CapColumn>
176
+ <CapIcon type="six-dots" />
177
+ </CapColumn>
178
+ <CapColumn className="text-conatiner">{text}</CapColumn>
179
+ <CapColumn className="quick-reply-icon">
180
+ <CapIcon
181
+ onClick={() => handleSaveAndEditBtn(index, false)}
182
+ type="edit"
183
+ />
184
+ <CapIcon
185
+ onClick={() => handleDelete(index)}
186
+ type="delete"
187
+ />
188
+ </CapColumn>
189
+ </CapRow>
190
+ </CapRow>
191
+ );
192
+ }
193
+ })}
194
+ </CapRow>
195
+ )}
196
+ {quickReplyData?.length > 0 && isEditFlow &&
197
+ quickReplyData.map(({text, index}) => (
198
+ <CapRow className='cap-whatsapp-quick-reply whatsapp-quick-reply-edit-container' key={index}>
199
+ <CapLabel type='label16'>{text}</CapLabel>
200
+ </CapRow>
201
+ ))
202
+ }
203
+ {quickReplyData?.length < 3 && !isEditFlow && (
204
+ <CapRow>
205
+ <CapTooltip
206
+ title={
207
+ quickReplyDisable ? formatMessage(ctaMessages.ctaAddDisabled) : ""
208
+ }
209
+ placement={"right"}
210
+ >
211
+ <div className="button-disabled-tooltip-wrapper">
212
+ <CapButton
213
+ type="flat"
214
+ id="whatsapp-quick-reply-add-button"
215
+ disabled={quickReplyDisable}
216
+ className="margin-t-12 margin-l-24"
217
+ isAddBtn
218
+ onClick={addQuickReply}
219
+ >
220
+ {formatMessage(ctaMessages.addButton)}
221
+ </CapButton>
222
+ </div>
223
+ </CapTooltip>
224
+ </CapRow>
225
+ )}
226
+ </>
227
+ );
228
+ };
229
+
230
+ export default injectIntl(CapWhatsappQuickReply);
@@ -0,0 +1,40 @@
1
+ @import "~@capillarytech/cap-ui-library/styles/_variables";
2
+
3
+ .cap-whatsapp-quick-reply {
4
+ border: solid 1px $CAP_G06;
5
+ margin-left: $CAP_SPACE_24;
6
+ margin-top: $CAP_SPACE_24;
7
+ border-radius: 0.285rem;
8
+ .whatsapp-button-text-container {
9
+ padding: $CAP_SPACE_16 $CAP_SPACE_24;
10
+ }
11
+ .whatsapp-button-text-heading {
12
+ display: flex;
13
+ text-align: center;
14
+ }
15
+ .whatsapp-quick-reply-delete-button {
16
+ margin-left: $CAP_SPACE_12;
17
+ }
18
+ .whatsapp-button-text-input {
19
+ margin-top: $CAP_SPACE_08;
20
+ margin-bottom: $CAP_SPACE_12;
21
+ }
22
+ .whatsapp-quick-reply-save-container {
23
+ display: flex;
24
+ align-items: center;
25
+ padding: $CAP_SPACE_08 $CAP_SPACE_12;
26
+ .text-conatiner {
27
+ padding-left: $CAP_SPACE_12;
28
+ }
29
+ .quick-reply-icon {
30
+ position: absolute;
31
+ right: $CAP_SPACE_12;
32
+ }
33
+ }
34
+ }
35
+
36
+ .whatsapp-quick-reply-edit-container {
37
+ padding: $CAP_SPACE_12;
38
+ margin-left: 0;
39
+ margin-top: $CAP_SPACE_16;
40
+ }
@@ -0,0 +1,20 @@
1
+ import { defineMessages } from 'react-intl';
2
+ const prefix = `creatives.componentsV2.CapWhatsappQuickReply`;
3
+ export default defineMessages({
4
+ buttonText: {
5
+ id: `${prefix}.buttonText`,
6
+ defaultMessage: 'Button text',
7
+ },
8
+ buttonTextPlaceholder: {
9
+ id: `${prefix}.buttonTextPlaceholder`,
10
+ defaultMessage: 'Enter button text',
11
+ },
12
+ templateButtonTextError: {
13
+ id: `${prefix}.templateButtonTextError`,
14
+ defaultMessage: 'Template footer length cannot exceed 20',
15
+ },
16
+ templateButtonTextLengthError: {
17
+ id: `${prefix}.templateButtonTextLengthError`,
18
+ defaultMessage: 'Text field length cannot exceed 20',
19
+ },
20
+ });
@@ -330,6 +330,33 @@ export class TemplatePreview extends React.Component { // eslint-disable-line re
330
330
  return renderArray;
331
331
  };
332
332
 
333
+ const renderQuickReplyPreview = () => {
334
+ const renderArray = [];
335
+ const { quickReplyData = [] } = content || {};
336
+ if (quickReplyData?.length) {
337
+ renderArray.push(<CapDivider className="whatsapp-divider" />);
338
+ quickReplyData.forEach((quickReply, index) => {
339
+ const { text } = quickReply || {};
340
+ if (text) {
341
+ renderArray.push(
342
+ <CapLabel type="label21" className="whatsapp-cta-preview">
343
+ <CapIcon
344
+ type='small-link'
345
+ size="xs"
346
+ svgProps={{ style: { marginRight: '4px' } }}
347
+ />
348
+ {text}
349
+ </CapLabel>
350
+ )
351
+ }
352
+ if (index < quickReplyData.length -1) {
353
+ renderArray.push(<CapDivider className="whatsapp-divider" />);
354
+ }
355
+ })
356
+ }
357
+ return renderArray;
358
+ }
359
+
333
360
  const handlePreview = () => {
334
361
  const {templatePreviewUrl = ''} = templateData;
335
362
  handlePreviewInNewTab(templatePreviewUrl);
@@ -772,8 +799,11 @@ export class TemplatePreview extends React.Component { // eslint-disable-line re
772
799
  {content?.docPreview}
773
800
  </div>
774
801
  )}
802
+ {content?.templateHeaderPreview || ''}
775
803
  {content?.templateMsg || ''}
804
+ {content?.templateFooterPreview || ''}
776
805
  {renderWhatsappCtaPreview()}
806
+ {renderQuickReplyPreview()}
777
807
  </div>
778
808
  </div>
779
809
  </div>
@@ -710,8 +710,7 @@ exports[`Test SlideBoxContent container Should render correct component for what
710
710
  charCounterEnabled={false}
711
711
  content={
712
712
  Object {
713
- "charCount": 151,
714
- "ctaData": Array [
713
+ "buttonsData": Array [
715
714
  Object {
716
715
  "index": 0,
717
716
  "phone_number": "+919738752617",
@@ -725,6 +724,9 @@ exports[`Test SlideBoxContent container Should render correct component for what
725
724
  "url": "https://docs.google.com/{{1}}",
726
725
  },
727
726
  ],
727
+ "charCount": 151,
728
+ "footerMsg": "",
729
+ "headerMsg": "",
728
730
  "templateMsg": <CapLabel
729
731
  type="label5"
730
732
  >
@@ -107,7 +107,7 @@ import {
107
107
  HOST_GUPSHUP,
108
108
  } from '../Whatsapp/constants';
109
109
  import { ZALO_STATUS_OPTIONS, ZALO_STATUSES } from '../Zalo/constants';
110
- import { getWhatsappContent, getWhatsappStatus, getWhatsappCategory, getWhatsappCta } from '../Whatsapp/utils';
110
+ import { getWhatsappContent, getWhatsappStatus, getWhatsappCategory, getWhatsappCta, getWhatsappQuickReply } from '../Whatsapp/utils';
111
111
  import { getRCSContent } from '../Rcs/utils';
112
112
  import zaloMessages from '../Zalo/messages';
113
113
  import globalMessages from '../../v2Containers/Cap/messages';
@@ -1174,7 +1174,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
1174
1174
  break;
1175
1175
  }
1176
1176
  case WHATSAPP: {
1177
- const { whatsappImageSrc = '', templateMsg, docPreview, whatsappVideoPreviewImg = ''} = getWhatsappContent(template);
1177
+ const { whatsappImageSrc = '', templateMsg, docPreview, whatsappVideoPreviewImg = '', headerMsg, footerMsg} = getWhatsappContent(template);
1178
1178
  templateData.title = (
1179
1179
  <CapRow>
1180
1180
  <CapLabel className="whatsapp-rcs-template-name">{template?.name}</CapLabel>
@@ -1205,9 +1205,12 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
1205
1205
  : 'whatsapp-message-without-media'
1206
1206
  }`}
1207
1207
  >
1208
+ {headerMsg}
1208
1209
  {templateMsg}
1210
+ {footerMsg}
1209
1211
  </span>
1210
1212
  {getWhatsappCta(template)}
1213
+ {getWhatsappQuickReply(template)}
1211
1214
  </>
1212
1215
  );
1213
1216
  break;
@@ -1389,12 +1389,14 @@ exports[`Test Templates container Test max templates exceeded 1`] = `
1389
1389
  <span
1390
1390
  className="whatsapp-message-with-media"
1391
1391
  >
1392
+
1392
1393
  <CapLabel
1393
1394
  type="label9"
1394
1395
  >
1395
1396
  Hey {{1}}, Easier implementation, tracking, reporting and planning of promotions is now live! Check it out at {{2}}
1396
1397
  Click {{unsubscribe}} to unsubscribe
1397
1398
  </CapLabel>
1399
+
1398
1400
  </span>
1399
1401
  <CapLabel
1400
1402
  style={
@@ -1830,12 +1832,14 @@ exports[`Test Templates container Test max templates not exceeded 1`] = `
1830
1832
  <span
1831
1833
  className="whatsapp-message-with-media"
1832
1834
  >
1835
+
1833
1836
  <CapLabel
1834
1837
  type="label9"
1835
1838
  >
1836
1839
  Hey {{1}}, Easier implementation, tracking, reporting and planning of promotions is now live! Check it out at {{2}}
1837
1840
  Click {{unsubscribe}} to unsubscribe
1838
1841
  </CapLabel>
1842
+
1839
1843
  </span>
1840
1844
  <CapLabel
1841
1845
  style={
@@ -2271,12 +2275,14 @@ exports[`Test Templates container Test max templates warning 1`] = `
2271
2275
  <span
2272
2276
  className="whatsapp-message-with-media"
2273
2277
  >
2278
+
2274
2279
  <CapLabel
2275
2280
  type="label9"
2276
2281
  >
2277
2282
  Hey {{1}}, Easier implementation, tracking, reporting and planning of promotions is now live! Check it out at {{2}}
2278
2283
  Click {{unsubscribe}} to unsubscribe
2279
2284
  </CapLabel>
2285
+
2280
2286
  </span>
2281
2287
  <CapLabel
2282
2288
  style={
@@ -12,6 +12,8 @@ import messages from './messages';
12
12
  export const UNSUBSCRIBE_TEXT_LENGTH = 36;
13
13
  export const TEMPLATE_MESSAGE_MAX_LENGTH = 1024;
14
14
  export const WHATSAPP = 'WHATSAPP';
15
+ export const TEMPLATE_HEADER_MAX_LENGTH = 60;
16
+ export const TEMPLATE_BUTTON_TEXT_MAX_LENGTH = 20;
15
17
 
16
18
  const prefix = 'app/v2Containers/Whatsapp';
17
19
  export const TEMPLATE_CREATE_REQUEST = `${prefix}/TEMPLATE_CREATE_REQUEST`;
@@ -178,6 +180,9 @@ export const WHATSAPP_MEDIA_TYPES = {
178
180
  export const NONE = 'NONE';
179
181
  export const CTA = 'CTA';
180
182
  export const QUICK_REPLY = 'QUICK_REPLY';
183
+ export const HEADER_TEXT = 'header';
184
+ export const FOOTER_TEXT = 'footer';
185
+ export const MESSAGE_TEXT = 'message';
181
186
  export const WHATSAPP_BUTTON_TYPES = {
182
187
  NONE,
183
188
  CTA,
@@ -197,6 +202,16 @@ export const INITIAL_CTA_DATA = [
197
202
  },
198
203
  ];
199
204
 
205
+ export const INITIAL_QUICK_REPLY_DATA = [
206
+ {
207
+ index: 0,
208
+ text: "",
209
+ type: "QUICK_REPLY",
210
+ isSaved: false,
211
+ error: "",
212
+ },
213
+ ];
214
+
200
215
  export const ALLOWED_IMAGE_EXTENSIONS_REGEX = /\.(jpe?g|png)$/i;
201
216
  export const ALLOWED_EXTENSIONS_VIDEO_REGEX = (/\.(mp4)$/i);
202
217
  export const ALLOWED_EXTENSIONS_DOCUMENT_REGEX = (/\.(pdf)$/i);