@capillarytech/creatives-library 8.0.236-beta.0 → 8.0.237

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 (54) hide show
  1. package/config/app.js +1 -1
  2. package/constants/unified.js +0 -1
  3. package/package.json +1 -1
  4. package/services/api.js +0 -5
  5. package/utils/common.js +1 -6
  6. package/v2Components/CapTagList/index.js +1 -2
  7. package/v2Components/CapTagListWithInput/index.js +1 -5
  8. package/v2Components/CapTagListWithInput/messages.js +1 -1
  9. package/v2Components/ErrorInfoNote/style.scss +1 -1
  10. package/v2Components/HtmlEditor/HTMLEditor.js +14 -86
  11. package/v2Components/HtmlEditor/_htmlEditor.scss +4 -0
  12. package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
  13. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +98 -11
  14. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +115 -174
  15. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  16. package/v2Components/HtmlEditor/hooks/useEditorContent.js +2 -5
  17. package/v2Components/TestAndPreviewSlidebox/index.js +25 -31
  18. package/v2Containers/CreativesContainer/SlideBoxContent.js +35 -83
  19. package/v2Containers/CreativesContainer/SlideBoxFooter.js +3 -9
  20. package/v2Containers/CreativesContainer/index.js +11 -83
  21. package/v2Containers/CreativesContainer/messages.js +0 -4
  22. package/v2Containers/Email/actions.js +0 -7
  23. package/v2Containers/Email/constants.js +1 -5
  24. package/v2Containers/Email/index.js +0 -13
  25. package/v2Containers/Email/messages.js +0 -32
  26. package/v2Containers/Email/reducer.js +1 -12
  27. package/v2Containers/Email/sagas.js +0 -17
  28. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +7 -193
  29. package/v2Containers/EmailWrapper/constants.js +0 -2
  30. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +67 -436
  31. package/v2Containers/EmailWrapper/index.js +23 -99
  32. package/v2Containers/EmailWrapper/messages.js +1 -61
  33. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +49 -49
  34. package/v2Containers/Rcs/index.js +5 -3
  35. package/v2Containers/Rcs/sagas.js +4 -4
  36. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +0 -16
  37. package/v2Containers/Rcs/tests/index.test.js +139 -2
  38. package/v2Containers/Rcs/tests/mockData.js +6 -3
  39. package/v2Containers/Rcs/tests/saga.test.js +88 -0
  40. package/v2Containers/TagList/index.js +0 -2
  41. package/v2Containers/Templates/actions.js +2 -6
  42. package/v2Containers/Templates/constants.js +1 -0
  43. package/v2Containers/Templates/index.js +66 -39
  44. package/v2Containers/Templates/messages.js +8 -0
  45. package/v2Containers/Templates/reducer.js +3 -3
  46. package/v2Containers/Templates/sagas.js +1 -1
  47. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +8 -8
  48. package/v2Containers/Templates/tests/actions.test.js +36 -1
  49. package/v2Containers/Templates/tests/reducer.test.js +9 -2
  50. package/v2Containers/Templates/tests/sagas.test.js +262 -9
  51. package/HOW_BEE_EDITOR_WORKS.md +0 -375
  52. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +0 -1034
  53. package/v2Containers/EmailWrapper/tests/EmailHTMLEditor.test.js +0 -177
  54. package/v2Containers/EmailWrapper/tests/EmailHTMLEditorValidation.test.js +0 -90
package/config/app.js CHANGED
@@ -20,7 +20,7 @@ const config = {
20
20
  accountConfig: (strs, accountId) => `${window.location.origin}/org/config/AccountAdd?q=a&channelId=2&accountId=${accountId}&edit=1`,
21
21
  },
22
22
  development: {
23
- api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/creatives',
23
+ api_endpoint: 'http://localhost:2022/arya/api/v1/creatives',
24
24
  campaigns_api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/campaigns',
25
25
  campaigns_api_org_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/org/campaign',
26
26
  auth_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/auth',
@@ -45,7 +45,6 @@ export const GIFT_CARDS = 'GIFT_CARDS';
45
45
  export const PROMO_ENGINE = 'PROMO_ENGINE';
46
46
  export const LIQUID_SUPPORT = 'ENABLE_LIQUID_SUPPORT';
47
47
  export const ENABLE_NEW_MPUSH = 'ENABLE_NEW_MPUSH';
48
- export const SUPPORT_CK_EDITOR = 'SUPPORT_CK_EDITOR';
49
48
  export const CUSTOM_TAG = 'CustomTagMessage';
50
49
  export const CUSTOMER_EXTENDED_FIELD = 'Customer extended fields';
51
50
  export const EXTENDED_TAG = 'ExtendedTagMessage';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.236-beta.0",
4
+ "version": "8.0.237",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
package/services/api.js CHANGED
@@ -465,11 +465,6 @@ export const getCmsTemplateSettingsV2 = (cmsType, projectId, cmsMode, langId, is
465
465
  return API.get(url);
466
466
  };
467
467
 
468
- export const getCmsAccounts = (cmsType) => {
469
- const url = `${API_ENDPOINT}/cms/accounts?type=${cmsType}`;
470
- return API.get(url);
471
- };
472
-
473
468
  export const getCmsTemplateData = (cmsType, projectId, langId) => {
474
469
  const url = `${API_ENDPOINT}/cms/getContent?type=${cmsType}&projectId=${projectId}&langId=${langId}`;
475
470
  return API.get(url);
package/utils/common.js CHANGED
@@ -22,8 +22,7 @@ import {
22
22
  BADGES_ISSUE,
23
23
  ENABLE_WECHAT,
24
24
  LIQUID_SUPPORT,
25
- ENABLE_NEW_MPUSH,
26
- SUPPORT_CK_EDITOR
25
+ ENABLE_NEW_MPUSH
27
26
  } from '../constants/unified';
28
27
  import { apiMessageFormatHandler } from './commonUtils';
29
28
 
@@ -96,10 +95,6 @@ export const hasLiquidSupportFeature = Auth.hasFeatureAccess.bind(
96
95
  LIQUID_SUPPORT,
97
96
  );
98
97
 
99
- export const hasSupportCKEditor = Auth.hasFeatureAccess.bind(
100
- null,
101
- SUPPORT_CK_EDITOR,
102
- );
103
98
 
104
99
  export const hasGiftVoucherFeature = Auth.hasFeatureAccess.bind(
105
100
  null,
@@ -468,7 +468,7 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
468
468
  onVisibleChange={this.togglePopoverVisibility}
469
469
  content={contentSection}
470
470
  trigger="click"
471
- placement={this.props.popoverPlacement || (channel === EMAIL.toUpperCase() ? "leftTop" : "rightTop")}
471
+ placement={channel === EMAIL.toUpperCase() ? "leftTop" : "rightTop"}
472
472
  >
473
473
  <CapTooltip
474
474
  title={
@@ -535,7 +535,6 @@ CapTagList.propTypes = {
535
535
  channel: PropTypes.string,
536
536
  disabled: PropTypes.bool,
537
537
  fetchingSchemaError: PropTypes.bool,
538
- popoverPlacement: PropTypes.string,
539
538
  };
540
539
 
541
540
  CapTagList.defaultValue = {
@@ -48,14 +48,13 @@ export const CapTagListWithInput = (props) => {
48
48
  showTagList = true,
49
49
  showInput = true,
50
50
  inputProps = {},
51
- popoverPlacement,
52
51
  } = props;
53
52
 
54
53
  const { formatMessage } = intl;
55
54
 
56
55
  return (
57
56
  <CapColumn style={containerStyle}>
58
- <CapRow align="middle" type="flex">
57
+ <CapRow style={{display: 'flex', flexDirection: 'row'}}>
59
58
  {showHeading && headingText && (
60
59
  <CapHeading type={headingType} style={headingStyle}>
61
60
  {headingText}
@@ -77,7 +76,6 @@ export const CapTagListWithInput = (props) => {
77
76
  selectedOfferDetails={selectedOfferDetails}
78
77
  eventContextTags={eventContextTags}
79
78
  style={tagListStyle}
80
- popoverPlacement={popoverPlacement}
81
79
  />
82
80
  )}
83
81
  </CapRow>
@@ -138,7 +136,6 @@ CapTagListWithInput.propTypes = {
138
136
  showHeading: PropTypes.bool,
139
137
  showTagList: PropTypes.bool,
140
138
  showInput: PropTypes.bool,
141
- popoverPlacement: PropTypes.string,
142
139
  };
143
140
 
144
141
  CapTagListWithInput.defaultProps = {
@@ -167,7 +164,6 @@ CapTagListWithInput.defaultProps = {
167
164
  showTagList: true,
168
165
  showInput: true,
169
166
  inputProps: {},
170
- popoverPlacement: undefined,
171
167
  };
172
168
 
173
169
  export default injectIntl(CapTagListWithInput);
@@ -5,6 +5,6 @@ const prefix = 'creatives.componentsV2.CapTagListWithInput';
5
5
  export default defineMessages({
6
6
  addLabels: {
7
7
  id: `${prefix}.addLabels`,
8
- defaultMessage: 'Add label',
8
+ defaultMessage: 'Add labels',
9
9
  },
10
10
  });
@@ -1,7 +1,7 @@
1
1
  @import "~@capillarytech/cap-ui-library/styles/_variables.scss";
2
2
 
3
3
  .error-container {
4
- width: 100%;
4
+ width: max-content;
5
5
  margin-bottom: $CAP_SPACE_08;
6
6
  margin-top: $CAP_SPACE_12;
7
7
  background-color: $CAP_COLOR_05;
@@ -12,7 +12,7 @@
12
12
  * Note: Uses injectIntl with forwardRef to provide direct access to CodeEditorPane via ref
13
13
  */
14
14
 
15
- import React, { useRef, useCallback, useMemo, useState, useEffect } from 'react';
15
+ import React, { useRef, useCallback, useMemo, useState } from 'react';
16
16
  import PropTypes from 'prop-types';
17
17
  import { Layout } from 'antd'; // Fallback - no Cap UI equivalent
18
18
  import { injectIntl, intlShape } from 'react-intl';
@@ -61,16 +61,6 @@ const HTMLEditor = ({
61
61
  showFullscreenButton = true,
62
62
  autoSave = true,
63
63
  autoSaveInterval = 30000, // 30 seconds
64
- // Tag-related props - tags are fetched and managed by parent component (EmailHTMLEditor, INAPP, etc.)
65
- tags = [],
66
- injectedTags = {},
67
- location,
68
- eventContextTags = [],
69
- selectedOfferDetails = [],
70
- channel,
71
- userLocale = 'en',
72
- moduleFilterEnabled = true,
73
- onTagContextChange, // Parent component handles tag fetching
74
64
  ...props
75
65
  }) => {
76
66
  // Separate refs for main and modal editors to avoid conflicts
@@ -127,29 +117,6 @@ const HTMLEditor = ({
127
117
  // Use appropriate content hook based on variant
128
118
  const content = variant === HTML_EDITOR_VARIANTS.EMAIL ? emailContent : inAppContent;
129
119
 
130
- // Update content when initialContent prop changes (for edit mode)
131
- // This ensures the editor updates when template data loads
132
- useEffect(() => {
133
- if (isEmailVariant && emailContent && initialContent !== undefined && initialContent !== null) {
134
- // Only update if content is different to avoid unnecessary updates
135
- if (emailContent.content !== initialContent) {
136
- emailContent.updateContent(initialContent, true); // immediate update
137
- }
138
- } else if (isInAppVariant && inAppContent && initialContent !== undefined && initialContent !== null) {
139
- // Handle InApp variant updates
140
- const contentToUpdate = typeof initialContent === 'string'
141
- ? { [DEVICE_TYPES.ANDROID]: initialContent, [DEVICE_TYPES.IOS]: initialContent }
142
- : initialContent;
143
- if (inAppContent.updateContent) {
144
- const currentContent = inAppContent.getDeviceContent?.(inAppContent.activeDevice);
145
- const newContent = contentToUpdate[inAppContent.activeDevice] || contentToUpdate[DEVICE_TYPES.ANDROID] || '';
146
- if (currentContent !== newContent) {
147
- inAppContent.updateContent(newContent, true);
148
- }
149
- }
150
- }
151
- }, [initialContent, isEmailVariant, isInAppVariant]);
152
-
153
120
  // Destructure content properties for cleaner access throughout component
154
121
  const {
155
122
  activeDevice,
@@ -420,15 +387,6 @@ const HTMLEditor = ({
420
387
  ref={mainEditorRef}
421
388
  readOnly={readOnly}
422
389
  onLabelInsert={handleLabelInsert}
423
- tags={tags}
424
- injectedTags={injectedTags}
425
- location={location}
426
- eventContextTags={eventContextTags}
427
- selectedOfferDetails={selectedOfferDetails}
428
- channel={channel}
429
- userLocale={userLocale}
430
- moduleFilterEnabled={moduleFilterEnabled}
431
- onTagContextChange={onTagContextChange}
432
390
  />
433
391
 
434
392
  {/* Preview Pane */}
@@ -496,28 +454,19 @@ const HTMLEditor = ({
496
454
  readOnly={readOnly}
497
455
  isFullscreenMode={true}
498
456
  onLabelInsert={handleLabelInsert}
499
- tags={tags}
500
- injectedTags={injectedTags}
501
- location={location}
502
- eventContextTags={eventContextTags}
503
- selectedOfferDetails={selectedOfferDetails}
504
- channel={channel}
505
- userLocale={userLocale}
506
- moduleFilterEnabled={moduleFilterEnabled}
507
- onTagContextChange={onTagContextChange}
508
457
  />
509
458
 
510
- {/* Preview Pane */}
511
- <PreviewPane isFullscreenMode={true} isModalContext={true} />
512
- </SplitContainer>
459
+ {/* Preview Pane */}
460
+ <PreviewPane isFullscreenMode={true} isModalContext={true} />
461
+ </SplitContainer>
513
462
 
514
- {/* Validation Display in Modal */}
515
- <ValidationErrorDisplay
516
- validation={validation}
517
- onErrorClick={handleValidationErrorClick}
518
- variant={variant}
519
- className="html-editor-validation"
520
- />
463
+ {/* Validation Display in Modal */}
464
+ <ValidationErrorDisplay
465
+ validation={validation}
466
+ onErrorClick={handleValidationErrorClick}
467
+ variant={variant}
468
+ className="html-editor-validation"
469
+ />
521
470
  </CapRow>
522
471
  </CapRow>
523
472
  </CapModal>
@@ -532,7 +481,7 @@ HTMLEditor.propTypes = {
532
481
  layoutType: PropTypes.string, // Layout type for InApp variant
533
482
  initialContent: PropTypes.oneOfType([
534
483
  PropTypes.string,
535
- PropTypes.objectOf(PropTypes.string), // Per-device content for INAPP variant
484
+ PropTypes.objectOf(PropTypes.string) // Per-device content for INAPP variant
536
485
  ]),
537
486
  onSave: PropTypes.func,
538
487
  onContentChange: PropTypes.func,
@@ -540,22 +489,11 @@ HTMLEditor.propTypes = {
540
489
  readOnly: PropTypes.bool,
541
490
  showFullscreenButton: PropTypes.bool,
542
491
  autoSave: PropTypes.bool,
543
- autoSaveInterval: PropTypes.number,
544
- // Tag-related props - tags are fetched and managed by parent component
545
- tags: PropTypes.array,
546
- injectedTags: PropTypes.object,
547
- location: PropTypes.object,
548
- eventContextTags: PropTypes.array,
549
- selectedOfferDetails: PropTypes.array,
550
- channel: PropTypes.string,
551
- userLocale: PropTypes.string,
552
- moduleFilterEnabled: PropTypes.bool,
553
- onTagContextChange: PropTypes.func, // Required - parent must handle tag fetching
492
+ autoSaveInterval: PropTypes.number
554
493
  };
555
494
 
556
495
  HTMLEditor.defaultProps = {
557
496
  variant: HTML_EDITOR_VARIANTS.EMAIL, // Default to email variant
558
- layoutType: null,
559
497
  initialContent: null, // Will use default from useEditorContent hook
560
498
  onSave: null,
561
499
  onContentChange: null,
@@ -563,17 +501,7 @@ HTMLEditor.defaultProps = {
563
501
  readOnly: false,
564
502
  showFullscreenButton: true,
565
503
  autoSave: true,
566
- autoSaveInterval: 30000,
567
- // Tag-related defaults - tags are fetched and managed by parent component
568
- tags: [],
569
- injectedTags: {},
570
- location: null,
571
- eventContextTags: [],
572
- selectedOfferDetails: [],
573
- channel: null,
574
- userLocale: 'en',
575
- moduleFilterEnabled: true,
576
- onTagContextChange: null, // Parent component should provide this
504
+ autoSaveInterval: 30000
577
505
  };
578
506
 
579
507
  // Export with forwardRef to allow direct access to CodeEditorPane via ref
@@ -267,6 +267,10 @@
267
267
 
268
268
  // Focus states and accessibility
269
269
  .html-editor {
270
+ &:focus-within {
271
+ outline: 0.125rem solid map-get($CAP_PRIMARY, base); // 2px = 0.125rem
272
+ outline-offset: -0.125rem; // -2px = -0.125rem
273
+ }
270
274
 
271
275
  // High contrast mode support
272
276
  @media (prefers-contrast: high) {
@@ -13,7 +13,7 @@
13
13
  align-items: center;
14
14
  min-height: 25rem; // 400px = 25rem
15
15
  background: $CAP_G11; // Light background similar to #fafbfc
16
- // border: 0.0625rem solid $CAP_G07; // 1px border similar to #dfe2e7
16
+ border: 0.0625rem solid $CAP_G07; // 1px border similar to #dfe2e7
17
17
  border-radius: 0.5rem; // 8px = 0.5rem
18
18
  flex-direction: column;
19
19
  gap: 1rem; // 16px = 1rem
@@ -31,6 +31,79 @@
31
31
  display: flex;
32
32
  align-items: center;
33
33
  gap: 0.5rem;
34
+
35
+ .cap-button,
36
+ .ant-btn,
37
+ button {
38
+ color: map-get($CAP_PRIMARY, base);
39
+ border: none;
40
+ background: $CAP_WHITE;
41
+ border-radius: 0.25rem;
42
+ padding: 0.375rem 0.5rem;
43
+ font-size: 0.875rem;
44
+ font-family: $FONT_FAMILY;
45
+ font-weight: 500;
46
+ height: auto;
47
+ min-width: 5.9375rem;
48
+ display: flex;
49
+ align-items: center;
50
+ gap: 0.25rem;
51
+ box-shadow: 0 0 0.0625rem 0 rgba(9, 30, 66, 0.31), 0 0.25rem 0.5rem -0.125rem rgba(9, 30, 66, 0.25);
52
+ line-height: 1.25rem;
53
+ text-align: left;
54
+
55
+ &:hover {
56
+ background: $CAP_G09;
57
+ box-shadow: 0 0 0.0625rem 0 rgba(9, 30, 66, 0.31), 0 0.375rem 0.75rem -0.125rem rgba(9, 30, 66, 0.25);
58
+ color: map-get($CAP_PRIMARY, base);
59
+ border: none;
60
+ }
61
+
62
+ &:active,
63
+ &:focus {
64
+ background: $CAP_G08;
65
+ box-shadow: 0 0 0.0625rem 0 rgba(9, 30, 66, 0.31), 0 0.125rem 0.25rem -0.125rem rgba(9, 30, 66, 0.25);
66
+ color: map-get($CAP_PRIMARY, base);
67
+ border: none;
68
+ }
69
+
70
+ .anticon,
71
+ .cap-icon {
72
+ font-size: 1rem;
73
+ color: map-get($CAP_PRIMARY, base);
74
+ }
75
+
76
+ span {
77
+ font-size: 0.875rem;
78
+ font-weight: 500;
79
+ line-height: 1.25rem;
80
+ color: map-get($CAP_PRIMARY, base);
81
+ white-space: nowrap;
82
+ }
83
+
84
+ &:before,
85
+ &:after {
86
+ display: none;
87
+ }
88
+ }
89
+
90
+ .tooltip-add-label-container {
91
+
92
+ .cap-button,
93
+ .ant-btn {
94
+ color: map-get($CAP_PRIMARY, base);
95
+ background: $CAP_WHITE;
96
+ border: none;
97
+ box-shadow: 0 0 0.0625rem 0 rgba(9, 30, 66, 0.31), 0 0.25rem 0.5rem -0.125rem rgba(9, 30, 66, 0.25);
98
+ }
99
+ }
100
+
101
+ .cap-button-flat,
102
+ .cap-button-add {
103
+ background: $CAP_WHITE;
104
+ color: map-get($CAP_PRIMARY, base);
105
+ border: none;
106
+ }
34
107
  }
35
108
 
36
109
  &__content {
@@ -57,17 +130,6 @@
57
130
  }
58
131
  }
59
132
 
60
- .code-editor-pane__actions {
61
- opacity: 0;
62
- pointer-events: none;
63
- transition: opacity 0.2s ease;
64
- }
65
-
66
- .code-editor-pane__content:hover .code-editor-pane__actions {
67
- opacity: 1;
68
- pointer-events: auto;
69
- }
70
-
71
133
  .cm-foldGutter {
72
134
  width: 1rem;
73
135
 
@@ -172,6 +234,31 @@
172
234
  top: 0.5rem;
173
235
  right: 0.5rem;
174
236
  z-index: 20;
237
+
238
+ .cap-button,
239
+ .ant-btn,
240
+ button {
241
+ background: $CAP_WHITE;
242
+ color: map-get($CAP_PRIMARY, base);
243
+ border: none;
244
+ border-radius: 0.25rem;
245
+ padding: 0.375rem 0.5rem;
246
+ font-size: 0.875rem;
247
+ font-family: $FONT_FAMILY;
248
+ font-weight: 500;
249
+ min-width: 5.9375rem;
250
+ box-shadow: 0 0 0.0625rem 0 rgba(9, 30, 66, 0.31), 0 0.25rem 0.5rem -0.125rem rgba(9, 30, 66, 0.25);
251
+
252
+ &:hover {
253
+ background: $CAP_G09;
254
+ color: map-get($CAP_PRIMARY, base);
255
+ }
256
+
257
+ &:active {
258
+ background: $CAP_G08;
259
+ color: map-get($CAP_PRIMARY, base);
260
+ }
261
+ }
175
262
  }
176
263
 
177
264
  .codemirror-editor {