@capillarytech/creatives-library 8.0.123 → 8.0.125-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.
Files changed (67) hide show
  1. package/containers/App/constants.js +1 -0
  2. package/package.json +1 -1
  3. package/services/api.js +1 -1
  4. package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +8 -3
  5. package/tests/integration/TemplateCreation/api-response.js +5 -0
  6. package/tests/integration/TemplateCreation/msw-handler.js +42 -63
  7. package/utils/common.js +7 -0
  8. package/utils/commonUtils.js +2 -6
  9. package/utils/createPayload.js +240 -0
  10. package/utils/tests/createPayload.test.js +761 -0
  11. package/v2Components/CapDeviceContent/index.js +1 -0
  12. package/v2Components/CapImageUpload/index.js +51 -45
  13. package/v2Components/CapInAppCTA/index.js +1 -0
  14. package/v2Components/CapMpushCTA/constants.js +25 -0
  15. package/v2Components/CapMpushCTA/index.js +332 -0
  16. package/v2Components/CapMpushCTA/index.scss +95 -0
  17. package/v2Components/CapMpushCTA/messages.js +89 -0
  18. package/v2Components/CapTagList/index.js +177 -120
  19. package/v2Components/CapVideoUpload/constants.js +3 -0
  20. package/v2Components/CapVideoUpload/index.js +167 -110
  21. package/v2Components/CapVideoUpload/messages.js +16 -0
  22. package/v2Components/Carousel/index.js +15 -13
  23. package/v2Components/ErrorInfoNote/style.scss +1 -0
  24. package/v2Components/MobilePushPreviewV2/index.js +37 -5
  25. package/v2Components/TemplatePreview/_templatePreview.scss +114 -72
  26. package/v2Components/TemplatePreview/assets/images/Android _ With date and time.svg +29 -0
  27. package/v2Components/TemplatePreview/assets/images/android.svg +9 -0
  28. package/v2Components/TemplatePreview/assets/images/iOS _ With date and time.svg +26 -0
  29. package/v2Components/TemplatePreview/assets/images/ios.svg +9 -0
  30. package/v2Components/TemplatePreview/index.js +178 -50
  31. package/v2Components/TemplatePreview/messages.js +4 -0
  32. package/v2Containers/CreativesContainer/SlideBoxContent.js +7 -8
  33. package/v2Containers/CreativesContainer/index.js +194 -138
  34. package/v2Containers/InApp/constants.js +1 -1
  35. package/v2Containers/InApp/index.js +13 -13
  36. package/v2Containers/MobilePush/Create/index.js +1 -0
  37. package/v2Containers/MobilePushNew/actions.js +116 -0
  38. package/v2Containers/MobilePushNew/components/CtaButtons.js +170 -0
  39. package/v2Containers/MobilePushNew/components/MediaUploaders.js +686 -0
  40. package/v2Containers/MobilePushNew/components/PlatformContentFields.js +279 -0
  41. package/v2Containers/MobilePushNew/components/index.js +5 -0
  42. package/v2Containers/MobilePushNew/components/tests/CtaButtons.test.js +779 -0
  43. package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +2114 -0
  44. package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +343 -0
  45. package/v2Containers/MobilePushNew/constants.js +115 -0
  46. package/v2Containers/MobilePushNew/hooks/tests/usePlatformSync.test.js +1299 -0
  47. package/v2Containers/MobilePushNew/hooks/tests/useUpload.test.js +1223 -0
  48. package/v2Containers/MobilePushNew/hooks/usePlatformSync.js +246 -0
  49. package/v2Containers/MobilePushNew/hooks/useUpload.js +709 -0
  50. package/v2Containers/MobilePushNew/index.js +1937 -0
  51. package/v2Containers/MobilePushNew/index.scss +308 -0
  52. package/v2Containers/MobilePushNew/messages.js +226 -0
  53. package/v2Containers/MobilePushNew/reducer.js +160 -0
  54. package/v2Containers/MobilePushNew/sagas.js +198 -0
  55. package/v2Containers/MobilePushNew/selectors.js +55 -0
  56. package/v2Containers/MobilePushNew/tests/reducer.test.js +741 -0
  57. package/v2Containers/MobilePushNew/tests/sagas.test.js +863 -0
  58. package/v2Containers/MobilePushNew/tests/selectors.test.js +425 -0
  59. package/v2Containers/MobilePushNew/tests/utils.test.js +322 -0
  60. package/v2Containers/MobilePushNew/utils.js +33 -0
  61. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +5 -5
  62. package/v2Containers/TagList/index.js +56 -10
  63. package/v2Containers/Templates/_templates.scss +101 -1
  64. package/v2Containers/Templates/index.js +147 -35
  65. package/v2Containers/Templates/messages.js +8 -0
  66. package/v2Containers/Templates/sagas.js +2 -0
  67. package/v2Containers/Whatsapp/constants.js +1 -0
@@ -46,10 +46,12 @@ import {
46
46
  INITIAL_CTA_DATA,
47
47
  IOS,
48
48
  LAYOUT_RADIO_OPTIONS,
49
- AI_CONTENT_BOT_DISABLED
49
+ AI_CONTENT_BOT_DISABLED,
50
50
  } from "./constants";
51
51
  import { INAPP, SMS } from "../CreativesContainer/constants";
52
- import { ALL, TAG, EMBEDDED, DEFAULT, FULL, LIBRARY } from "../Whatsapp/constants";
52
+ import {
53
+ ALL, TAG, EMBEDDED, DEFAULT, FULL, LIBRARY,
54
+ } from "../Whatsapp/constants";
53
55
  import CapDeviceContent from "../../v2Components/CapDeviceContent";
54
56
  import { getCdnUrl } from "../../utils/cdnTransformation";
55
57
  import { getCtaObject, hasAnyErrors, getSingleTab } from "./utils";
@@ -297,14 +299,13 @@ export const InApp = (props) => {
297
299
 
298
300
  const templateDescErrorHandler = (value) => {
299
301
  let errorMessage = false;
300
- const { unsupportedTags, isBraceError } =
301
- validateTags({
302
- content: value,
303
- tagsParam: tags,
304
- injectedTagsParams: injectedTags,
305
- location,
306
- tagModule: getDefaultTags,
307
- }) || {};
302
+ const { unsupportedTags, isBraceError } = validateTags({
303
+ content: value,
304
+ tagsParam: tags,
305
+ injectedTagsParams: injectedTags,
306
+ location,
307
+ tagModule: getDefaultTags,
308
+ }) || {};
308
309
  if (value === '' && INAPP_MEDIA_TYPES.NONE) {
309
310
  errorMessage = formatMessage(messages.emptyTemplateDescErrorMessage);
310
311
  } else if (unsupportedTags?.length > 0) {
@@ -472,7 +473,7 @@ export const InApp = (props) => {
472
473
  placeholder={formatMessage(globalMessages.templateNamePlaceholder)}
473
474
  value={templateName}
474
475
  size="default"
475
- />
476
+ />
476
477
  </CapRow>
477
478
  );
478
479
  //create methods end
@@ -582,8 +583,7 @@ export const InApp = (props) => {
582
583
  return false;
583
584
  };
584
585
 
585
- const getCtaPayload = (type) =>
586
- (type === ANDROID ? ctaDataAndroid : ctaDataIos).map((cta) => {
586
+ const getCtaPayload = (type) => (type === ANDROID ? ctaDataAndroid : ctaDataIos).map((cta) => {
587
587
  const { text, urlType, url } = cta;
588
588
  return {
589
589
  type: urlType,
@@ -239,6 +239,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
239
239
  onLinkTypeChange = (eventTriggered, formData, field) => {
240
240
  let schema = cloneDeep(this.state.schema);
241
241
  const inputFields = get(schema, `containers[0].panes[${this.state.currentTab - 1}].sections[0].childSections[0].childSections[0].inputFields`);
242
+
242
243
  forEach(inputFields, (inputField, fieldIndex) => {
243
244
  if (inputField) {
244
245
  forEach(inputField.cols, (col) => {
@@ -0,0 +1,116 @@
1
+ /*
2
+ *
3
+ * Create actions
4
+ *
5
+ */
6
+
7
+ import * as types from './constants';
8
+
9
+ export function createTemplate(template, callback) {
10
+ return {
11
+ type: types.CREATE_TEMPLATE_REQUEST,
12
+ template,
13
+ callback,
14
+ };
15
+ }
16
+
17
+ export function clearCreateResponse() {
18
+ return {
19
+ type: types.CLEAR_CREATE_RESPONSE_REQUEST,
20
+ };
21
+ }
22
+
23
+ export function defaultAction() {
24
+ return {
25
+ type: types.DEFAULT_ACTION,
26
+ };
27
+ }
28
+
29
+ export function uploadAsset(file, assetType, fileParams, index = 0, mobilePushParams = {}) {
30
+ return {
31
+ type: types.UPLOAD_ASSET_REQUEST,
32
+ file,
33
+ assetType,
34
+ fileParams,
35
+ index,
36
+ mobilePushParams,
37
+ };
38
+ }
39
+
40
+ export function getIosCtas(licenseCode) {
41
+ return {
42
+ type: types.GET_IOS_CTAS, licenseCode,
43
+ };
44
+ }
45
+
46
+ export function clearAsset(index = undefined) {
47
+ return {
48
+ type: types.CLEAR_ASSET,
49
+ index,
50
+ };
51
+ }
52
+
53
+ export function resetStore() {
54
+ return {
55
+ type: types.RESET_STORE,
56
+ };
57
+ }
58
+
59
+ export function getTemplateDetails(id) {
60
+ return {
61
+ type: types.GET_TEMPLATE_DETAILS_REQUEST, id,
62
+ };
63
+ }
64
+
65
+ export function editTemplate(template, callback) {
66
+ return {
67
+ type: types.EDIT_TEMPLATE_REQUEST, template, callback,
68
+ };
69
+ }
70
+
71
+ export function clearEditResponse() {
72
+ return {
73
+ type: types.CLEAR_EDIT_RESPONSE_REQUEST,
74
+ };
75
+ }
76
+
77
+ export function clearData() {
78
+ return {
79
+ type: types.CLEAR_DATA,
80
+ };
81
+ }
82
+
83
+ export function getWeCrmAccounts(source) {
84
+ return {
85
+ type: types.GET_WECRM_ACCOUNTS_REQUEST, source,
86
+ };
87
+ }
88
+
89
+ export function setWeChatAccount(weChatAccount) {
90
+ return {
91
+ type: types.SET_WECHAT_ACCOUNT,
92
+ weChatAccount,
93
+ };
94
+ }
95
+
96
+ export function getMobilepushTemplatesList(channel, queryParams) {
97
+ return {
98
+ type: types.GET_MOBILEPUSH_TEMPLATES_LIST_REQUEST,
99
+ channel,
100
+ queryParams,
101
+ };
102
+ }
103
+
104
+ export function setSelectedTemplate(templateData) {
105
+ return {
106
+ type: types.SET_SELECTED_TEMPLATE,
107
+ data: templateData,
108
+ };
109
+ }
110
+
111
+ export function setTemplateDetails(templateDetails) {
112
+ return {
113
+ type: types.GET_TEMPLATE_DETAILS_SUCCESS,
114
+ data: templateDetails,
115
+ };
116
+ }
@@ -0,0 +1,170 @@
1
+ import React, { memo, useState } from "react";
2
+ import PropTypes from "prop-types";
3
+ import { FormattedMessage } from "react-intl";
4
+ import CapRow from "@capillarytech/cap-ui-library/CapRow";
5
+ import CapButton from "@capillarytech/cap-ui-library/CapButton";
6
+ import CapIcon from "@capillarytech/cap-ui-library/CapIcon";
7
+ import CapHeading from "@capillarytech/cap-ui-library/CapHeading";
8
+ import CapMpushCTA from "../../../v2Components/CapMpushCTA";
9
+ import { PRIMARY, SECONDARY, DEEP_LINK } from "../constants";
10
+ import messages from "../messages";
11
+
12
+ const CtaButtons = ({
13
+ primaryButton,
14
+ secondaryButton,
15
+ setPrimaryButton,
16
+ setSecondaryButton,
17
+ ctaData,
18
+ updateHandler,
19
+ deleteHandler,
20
+ deepLink,
21
+ }) => {
22
+ // Local state to control CTA form visibility
23
+ const [showPrimaryCTA, setShowPrimaryCTA] = useState(false);
24
+ const [showSecondaryCTA, setShowSecondaryCTA] = useState(false);
25
+
26
+ const handleAddPrimary = () => {
27
+ // Prevent multiple clicks if primary button is already being added or form is already showing
28
+ if (primaryButton && showPrimaryCTA) {
29
+ return;
30
+ }
31
+
32
+ // If ctaData is empty or doesn't have a primary button, initialize it
33
+ if (ctaData.length === 0 || !ctaData.find((cta) => cta.index === 0)) {
34
+ const newPrimaryButton = {
35
+ index: 0,
36
+ ctaType: PRIMARY,
37
+ text: "",
38
+ urlType: DEEP_LINK,
39
+ url: "",
40
+ isSaved: false,
41
+ };
42
+ updateHandler(newPrimaryButton, 0);
43
+ }
44
+
45
+ setPrimaryButton(true);
46
+ setShowPrimaryCTA(true);
47
+ };
48
+
49
+ const handleAddSecondary = () => {
50
+ // Prevent multiple clicks if secondary button is already being added or form is already showing
51
+ if (secondaryButton && showSecondaryCTA) {
52
+ return;
53
+ }
54
+
55
+ if (shouldShowSecondaryCTA) {
56
+ return;
57
+ }
58
+
59
+ // If ctaData doesn't have a secondary button, initialize it
60
+ if (ctaData.length < 2 || !ctaData.find((cta) => cta.index === 1)) {
61
+ const newSecondaryButton = {
62
+ index: 1,
63
+ ctaType: SECONDARY,
64
+ text: "",
65
+ urlType: DEEP_LINK,
66
+ url: "",
67
+ isSaved: false,
68
+ };
69
+ updateHandler(newSecondaryButton, 1);
70
+ }
71
+
72
+ setSecondaryButton(true);
73
+ setShowSecondaryCTA(true);
74
+ };
75
+
76
+ // Check if primary button exists (saved or being edited)
77
+ const primaryButtonExists = ctaData.length > 0 && ctaData[0]?.text;
78
+ const isPrimaryButtonSaved = primaryButtonExists && ctaData[0]?.isSaved;
79
+
80
+ // Check if secondary button exists (saved or being edited)
81
+ const secondaryButtonExists = ctaData.length > 1 && ctaData[1]?.text;
82
+ const isSecondaryButtonSaved = secondaryButtonExists && ctaData[1]?.isSaved;
83
+
84
+ // Show primary CTA if button is active and (form is showing OR button exists)
85
+ const shouldShowPrimaryCTA = primaryButton && (showPrimaryCTA || primaryButtonExists);
86
+
87
+ // Show secondary CTA if button is active and (form is showing OR button exists)
88
+ const shouldShowSecondaryCTA = secondaryButton && (showSecondaryCTA || secondaryButtonExists);
89
+
90
+ // Enhanced delete handler to hide forms when buttons are deleted
91
+ const handleDelete = (index) => {
92
+ if (index === 0) {
93
+ setShowPrimaryCTA(false);
94
+ setPrimaryButton(false);
95
+ } else if (index === 1) {
96
+ setShowSecondaryCTA(false);
97
+ setSecondaryButton(false);
98
+ }
99
+ deleteHandler(index);
100
+ };
101
+
102
+ return (
103
+ <>
104
+ <CapRow>
105
+ <CapHeading type="h4">
106
+ <FormattedMessage {...messages.buttons} />
107
+ </CapHeading>
108
+ {!isPrimaryButtonSaved && !shouldShowPrimaryCTA && (
109
+ <CapButton
110
+ type="flat"
111
+ id="add-primary-button"
112
+ onClick={handleAddPrimary}
113
+ >
114
+ <CapIcon type="plus" />
115
+ <CapHeading type="h5" id="add-primary-btn-heading">
116
+ <FormattedMessage {...messages.addPrimaryButton} />
117
+ </CapHeading>
118
+ </CapButton>
119
+ )}
120
+ </CapRow>
121
+ {shouldShowPrimaryCTA && (
122
+ <CapMpushCTA
123
+ ctaData={ctaData}
124
+ updateHandler={updateHandler}
125
+ deleteHandler={handleDelete}
126
+ deepLink={deepLink || []}
127
+ buttonType={PRIMARY}
128
+ />
129
+ )}
130
+ {isPrimaryButtonSaved && !isSecondaryButtonSaved && !shouldShowSecondaryCTA && (
131
+ <CapButton
132
+ type="flat"
133
+ id="add-secondary-button"
134
+ onClick={handleAddSecondary}
135
+ >
136
+ <CapIcon type="plus" />
137
+ <CapHeading type="h5" id="add-secondary-btn-heading">
138
+ <FormattedMessage {...messages.addSecondaryButton} />
139
+ </CapHeading>
140
+ </CapButton>
141
+ )}
142
+ {shouldShowSecondaryCTA && (
143
+ <CapMpushCTA
144
+ ctaData={ctaData}
145
+ updateHandler={updateHandler}
146
+ deleteHandler={handleDelete}
147
+ deepLink={deepLink || []}
148
+ buttonType={SECONDARY}
149
+ />
150
+ )}
151
+ </>
152
+ );
153
+ };
154
+
155
+ CtaButtons.propTypes = {
156
+ primaryButton: PropTypes.bool.isRequired,
157
+ secondaryButton: PropTypes.bool.isRequired,
158
+ setPrimaryButton: PropTypes.func.isRequired,
159
+ setSecondaryButton: PropTypes.func.isRequired,
160
+ ctaData: PropTypes.array.isRequired,
161
+ updateHandler: PropTypes.func.isRequired,
162
+ deleteHandler: PropTypes.func.isRequired,
163
+ deepLink: PropTypes.array,
164
+ };
165
+
166
+ CtaButtons.defaultProps = {
167
+ deepLink: [],
168
+ };
169
+
170
+ export default memo(CtaButtons);