@capillarytech/creatives-library 8.0.60-alpha.7 → 8.0.61-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.
@@ -8,14 +8,14 @@
8
8
  .action-text-reply{
9
9
  position: absolute;
10
10
  left: 34%;
11
- top: 59%;
11
+ top: 43% !important;
12
12
  color: #3861ca;
13
13
  font-weight: $FONT_WEIGHT_MEDIUM;
14
14
  }
15
15
  .action-text-cancel{
16
16
  position: absolute;
17
17
  left: 33.5%;
18
- top: 66%;
18
+ top: 48% !important;
19
19
  color: #3861ca;
20
20
  font-weight: $FONT_WEIGHT_MEDIUM;
21
21
  }
@@ -25,7 +25,7 @@
25
25
  }
26
26
  .lock-screen-preview .lock-msgContainer{
27
27
  position: absolute;
28
- top: 40%;
28
+ top: 30% !important;
29
29
  left: 25.9%;
30
30
  width: 21.5%;
31
31
  height: 60px;
@@ -55,7 +55,7 @@
55
55
  }
56
56
  .main-screen-preview .msgContainer{
57
57
  position: absolute;
58
- top: 30%;
58
+ top: 30% !important;
59
59
  left: 53%;
60
60
  width: 42%;
61
61
  height: 336px;
@@ -138,8 +138,8 @@
138
138
  margin: 0 20px 0 auto;
139
139
  .action-text{
140
140
  position: absolute;
141
- left: 27.5%;
142
- top: 54%;
141
+ left: 28.5%;
142
+ top: 39% !important;
143
143
  font-size: $FONT_SIZE_VS;
144
144
  color: #3861ca;
145
145
  font-weight: $FONT_WEIGHT_MEDIUM;
@@ -150,8 +150,8 @@
150
150
  }
151
151
  .lock-screen-preview .lock-msgContainer{
152
152
  position: absolute;
153
- top: 43%;
154
- left: 25.9%;
153
+ top: 32% !important;
154
+ left: 26.9%;
155
155
  width: 21.5%;
156
156
  height: 52px;
157
157
  display: -webkit-box;
@@ -181,7 +181,7 @@
181
181
 
182
182
  .main-screen-preview .msgContainer{
183
183
  position: absolute;
184
- top: 30%;
184
+ top: 30% !important;
185
185
  left: 53%;
186
186
  width: 42%;
187
187
  height: 336px;
package/config/app.js CHANGED
@@ -17,7 +17,6 @@ const config = {
17
17
  accountConfig: (strs, accountId) => `${window.location.origin}/org/config/AccountAdd?q=a&channelId=2&accountId=${accountId}&edit=1`,
18
18
  },
19
19
  development: {
20
- // api_endpoint: 'http://localhost:2022/arya/api/v1/creatives',
21
20
  api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/creatives',
22
21
  campaigns_api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/campaigns',
23
22
  campaigns_api_org_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/org/campaign',
@@ -5,6 +5,9 @@ import { injectIntl } from 'react-intl';
5
5
  import * as globalActions from '../v2Containers/Cap/actions';
6
6
  import * as creativesContainerActions from '../v2Containers/CreativesContainer/actions';
7
7
  import { UserIsAuthenticated } from '../utils/authWrapper';
8
+ import { v2ZaloSagas } from '../v2Containers/Zalo/saga';
9
+ import { injectSaga } from '@capillarytech/vulcan-react-sdk/utils';
10
+ import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
8
11
 
9
12
  /**
10
13
  * Higher Order Component to common out creatives channel logic
@@ -18,6 +21,7 @@ export default ({
18
21
  userAuth,
19
22
  sagas = [],
20
23
  reducers = [],
24
+ zaloSaga = false,
21
25
  }) => {
22
26
  const CreativesCommon = (props) => {
23
27
  useEffect(() => {
@@ -44,7 +48,9 @@ export default ({
44
48
  };
45
49
 
46
50
  const withConnect = connect(mapStateToProps, hocMapDispatchToProps);
51
+ const withZaloSaga = injectSaga({ key: 'zalo', saga: v2ZaloSagas,mode: DAEMON });
47
52
  return compose(
53
+ withZaloSaga,
48
54
  ...sagas,
49
55
  ...reducers,
50
56
  withConnect,
package/index.js CHANGED
@@ -93,7 +93,7 @@ import whatsappSaga from './v2Containers/Whatsapp/sagas';
93
93
 
94
94
  import Zalo from './v2Containers/Zalo';
95
95
  import zaloReducer from './v2Containers/Zalo/reducer';
96
- import zaloSaga from './v2Containers/Zalo/saga';
96
+ import { v2ZaloSagas } from './v2Containers/Zalo/sagas';
97
97
 
98
98
  import InApp from './v2Containers/InApp';
99
99
  import inAppReducer from './v2Containers/InApp/reducer';
@@ -129,7 +129,7 @@ const FacebookPreviewContainer = { FacebookPreview, facebookPreviewReducer, face
129
129
  const SmsTraiContainer = {SmsTraiCreate, SmsTraiCreateReducer, SmsTraiCreateSaga};
130
130
  const WhatsappContainer = { Whatsapp, whatsappReducer, whatsappSaga };
131
131
  const RcsContainer = { Rcs, rcsReducer, rcsSaga };
132
- const ZaloContainer = { Zalo, zaloReducer, zaloSaga };
132
+ const ZaloContainer = { Zalo, zaloReducer, v2ZaloSagas };
133
133
  const InAppContainer = { InApp, inAppReducer, inAppSaga };
134
134
 
135
135
  const GalleryContainer = {Gallery, galleryReducer, gallerySagas};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.60-alpha.7",
4
+ "version": "8.0.61-alpha.0",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -294,4 +294,36 @@ export const getTagMapValue = (object = {}) => {
294
294
  ).reduce((acc, current) => {
295
295
  return { ...acc?.subtags ?? {}, ...current?.subtags ?? {} };
296
296
  }, {});
297
+ };
298
+
299
+
300
+ /**
301
+ * Extracts and merges all subtags and top-level keys from the provided object into a single flat map.
302
+ *
303
+ * @param {Object} object - The input object containing top-level keys with optional subtags.
304
+ * @returns {Object} - A flat map containing all top-level keys and their subtags.
305
+ */
306
+ export const getForwardedMapValues = (object = {}) => {
307
+ return Object?.entries(object)?.reduce((acc, [key, current]) => {
308
+ // Check if current has 'subtags' and it's an object
309
+ if (current && current?.subtags && typeof current?.subtags === 'object') {
310
+ // Add the top-level key with its 'name' and 'desc'
311
+ acc[key] = {
312
+ name: current?.name,
313
+ desc: current?.desc,
314
+ };
315
+
316
+ // Merge the subtags into the accumulator
317
+ acc = { ...acc, ...current?.subtags };
318
+ } else if (current && typeof current === 'object') {
319
+ // If no 'subtags', add the top-level key with its 'name' and 'desc'
320
+ acc[key] = {
321
+ name: current?.name,
322
+ desc: current?.desc,
323
+ };
324
+ }
325
+
326
+ // If the current entry is not an object or lacks 'name'/'desc', skip it
327
+ return acc;
328
+ }, {});
297
329
  };
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import '@testing-library/jest-dom';
3
- import { checkSupport, extractNames, getTagMapValue, preprocessHtml, validateIfTagClosed,validateTags, skipTags } from '../tagValidations';
3
+ import { checkSupport, extractNames, getTagMapValue,getForwardedMapValues, preprocessHtml, validateIfTagClosed,validateTags, skipTags } from '../tagValidations';
4
4
  import { eventContextTags } from '../../v2Containers/TagList/tests/mockdata';
5
5
 
6
6
  describe("check if curly brackets are balanced", () => {
@@ -496,4 +496,273 @@ describe("skipTags", () => {
496
496
  const result = skipTags(tag);
497
497
  expect(result).toEqual(true);
498
498
  });
499
+ });
500
+
501
+
502
+ describe('getForwardedMapValues', () => {
503
+ test('should return an empty object when input is empty', () => {
504
+ const input = {};
505
+ const expected = {};
506
+ expect(getForwardedMapValues(input)).toEqual(expected);
507
+ });
508
+
509
+ test('should correctly process objects with subtags', () => {
510
+ const input = {
511
+ customer: {
512
+ name: 'Customer',
513
+ desc: 'Customer Description',
514
+ subtags: {
515
+ cumulative_points_currency: {
516
+ name: 'Lifetime Points (in ₹)',
517
+ desc: 'Lifetime Points in ₹ Description',
518
+ },
519
+ mobile_number: {
520
+ name: 'Mobile Number',
521
+ desc: 'Mobile Number Description',
522
+ },
523
+ },
524
+ },
525
+ store: {
526
+ name: 'Store',
527
+ desc: 'Store Description',
528
+ subtags: {
529
+ store_name: {
530
+ name: 'Store Name',
531
+ desc: 'Store Name Description',
532
+ },
533
+ store_address: {
534
+ name: 'Store Address',
535
+ desc: 'Store Address Description',
536
+ },
537
+ },
538
+ },
539
+ };
540
+
541
+ const expected = {
542
+ customer: {
543
+ name: 'Customer',
544
+ desc: 'Customer Description',
545
+ },
546
+ cumulative_points_currency: {
547
+ name: 'Lifetime Points (in ₹)',
548
+ desc: 'Lifetime Points in ₹ Description',
549
+ },
550
+ mobile_number: {
551
+ name: 'Mobile Number',
552
+ desc: 'Mobile Number Description',
553
+ },
554
+ store: {
555
+ name: 'Store',
556
+ desc: 'Store Description',
557
+ },
558
+ store_name: {
559
+ name: 'Store Name',
560
+ desc: 'Store Name Description',
561
+ },
562
+ store_address: {
563
+ name: 'Store Address',
564
+ desc: 'Store Address Description',
565
+ },
566
+ };
567
+
568
+ expect(getForwardedMapValues(input)).toEqual(expected);
569
+ });
570
+
571
+ test('should correctly process objects without subtags', () => {
572
+ const input = {
573
+ points_on_event: {
574
+ name: 'Points on event',
575
+ desc: 'Points on event Description',
576
+ },
577
+ unsubscribe: {
578
+ name: 'Unsubscribe',
579
+ desc: 'Unsubscribe Description',
580
+ },
581
+ };
582
+
583
+ const expected = {
584
+ points_on_event: {
585
+ name: 'Points on event',
586
+ desc: 'Points on event Description',
587
+ },
588
+ unsubscribe: {
589
+ name: 'Unsubscribe',
590
+ desc: 'Unsubscribe Description',
591
+ },
592
+ };
593
+
594
+ expect(getForwardedMapValues(input)).toEqual(expected);
595
+ });
596
+
597
+ test('should handle a mix of entries with and without subtags', () => {
598
+ const input = {
599
+ customer: {
600
+ name: 'Customer',
601
+ desc: 'Customer Description',
602
+ subtags: {
603
+ cumulative_points_currency: {
604
+ name: 'Lifetime Points (in ₹)',
605
+ desc: 'Lifetime Points in ₹ Description',
606
+ },
607
+ },
608
+ },
609
+ points_on_event: {
610
+ name: 'Points on event',
611
+ desc: 'Points on event Description',
612
+ },
613
+ store: {
614
+ name: 'Store',
615
+ desc: 'Store Description',
616
+ subtags: {
617
+ store_name: {
618
+ name: 'Store Name',
619
+ desc: 'Store Name Description',
620
+ },
621
+ },
622
+ },
623
+ };
624
+
625
+ const expected = {
626
+ customer: {
627
+ name: 'Customer',
628
+ desc: 'Customer Description',
629
+ },
630
+ cumulative_points_currency: {
631
+ name: 'Lifetime Points (in ₹)',
632
+ desc: 'Lifetime Points in ₹ Description',
633
+ },
634
+ points_on_event: {
635
+ name: 'Points on event',
636
+ desc: 'Points on event Description',
637
+ },
638
+ store: {
639
+ name: 'Store',
640
+ desc: 'Store Description',
641
+ },
642
+ store_name: {
643
+ name: 'Store Name',
644
+ desc: 'Store Name Description',
645
+ },
646
+ };
647
+
648
+ expect(getForwardedMapValues(input)).toEqual(expected);
649
+ });
650
+
651
+ test('should ignore entries that are not objects', () => {
652
+ const input = {
653
+ valid_entry: {
654
+ name: 'Valid Entry',
655
+ desc: 'Valid Entry Description',
656
+ },
657
+ invalid_entry: 'This is a string, not an object',
658
+ another_invalid_entry: null,
659
+ };
660
+
661
+ const expected = {
662
+ valid_entry: {
663
+ name: 'Valid Entry',
664
+ desc: 'Valid Entry Description',
665
+ },
666
+ };
667
+
668
+ expect(getForwardedMapValues(input)).toEqual(expected);
669
+ });
670
+
671
+ test('should handle entries missing name or desc', () => {
672
+ const input = {
673
+ incomplete_entry1: {
674
+ name: 'Incomplete Entry 1',
675
+ // desc is missing
676
+ subtags: {
677
+ subtag1: {
678
+ name: 'Subtag 1',
679
+ desc: 'Subtag 1 Description',
680
+ },
681
+ },
682
+ },
683
+ incomplete_entry2: {
684
+ // name is missing
685
+ desc: 'Incomplete Entry 2 Description',
686
+ },
687
+ };
688
+
689
+ const expected = {
690
+ incomplete_entry1: {
691
+ name: 'Incomplete Entry 1',
692
+ desc: undefined,
693
+ },
694
+ subtag1: {
695
+ name: 'Subtag 1',
696
+ desc: 'Subtag 1 Description',
697
+ },
698
+ incomplete_entry2: {
699
+ name: undefined,
700
+ desc: 'Incomplete Entry 2 Description',
701
+ },
702
+ };
703
+
704
+ expect(getForwardedMapValues(input)).toEqual(expected);
705
+ });
706
+
707
+ test('should handle deeply nested subtags by only flattening one level', () => {
708
+ const input = {
709
+ parent: {
710
+ name: 'Parent',
711
+ desc: 'Parent Description',
712
+ subtags: {
713
+ child: {
714
+ name: 'Child',
715
+ desc: 'Child Description',
716
+ subtags: {
717
+ grandchild: {
718
+ name: 'Grandchild',
719
+ desc: 'Grandchild Description',
720
+ },
721
+ },
722
+ },
723
+ },
724
+ },
725
+ };
726
+
727
+ const expected = {
728
+ parent: {
729
+ name: 'Parent',
730
+ desc: 'Parent Description',
731
+ },
732
+ child: {
733
+ name: 'Child',
734
+ desc: 'Child Description',
735
+ subtags: {
736
+ grandchild: {
737
+ name: 'Grandchild',
738
+ desc: 'Grandchild Description',
739
+ },
740
+ },
741
+ },
742
+ };
743
+
744
+ expect(getForwardedMapValues(input)).toEqual(expected);
745
+ });
746
+
747
+
748
+ test('should not mutate the original input object', () => {
749
+ const input = {
750
+ customer: {
751
+ name: 'Customer',
752
+ desc: 'Customer Description',
753
+ subtags: {
754
+ cumulative_points_currency: {
755
+ name: 'Lifetime Points (in ₹)',
756
+ desc: 'Lifetime Points in ₹ Description',
757
+ },
758
+ },
759
+ },
760
+ };
761
+
762
+ const inputCopy = JSON.parse(JSON.stringify(input)); // Deep copy
763
+
764
+ getForwardedMapValues(input);
765
+
766
+ expect(input).toEqual(inputCopy);
767
+ });
499
768
  });
@@ -54,6 +54,8 @@ import { v2ViberSagas } from '../Viber/sagas';
54
54
  import { v2FacebookSagas } from '../Facebook/sagas';
55
55
  import createReducer from '../Line/Container/reducer';
56
56
  import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
57
+ import { v2ZaloSagas } from '../Zalo/saga';
58
+
57
59
  const gtm = window.dataLayer || [];
58
60
  const {
59
61
  logNewTab,
@@ -609,6 +611,7 @@ function mapDispatchToProps(dispatch) {
609
611
  const withConnect = connect(mapStateToProps, mapDispatchToProps);
610
612
  const withReducer = injectReducer({ key: 'cap', reducer });
611
613
  const withZaloReducer = injectReducer({ key: 'zalo', reducer: zaloReducer });
614
+ const withZaloSagas = injectSaga({ key: 'zalo', saga: v2ZaloSagas });
612
615
  const withSaga = injectSaga({ key: 'cap', saga: v2CapSagas });
613
616
  const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity, mode : DAEMON });
614
617
  const withSmsCreateSaga = injectSaga({ key: 'create', saga: v2SmsCreateSagas });
@@ -638,6 +641,7 @@ export default compose(
638
641
  withFacebookSaga,
639
642
  withReducer,
640
643
  withZaloReducer,
644
+ withZaloSagas,
641
645
  withLineReducer,
642
646
  withConnect,
643
647
  )(injectIntl(Cap));
@@ -71,4 +71,20 @@ export const expectedStateGetLiquidTagsRequest = {
71
71
  },
72
72
  orgID: "",
73
73
  token: ""
74
+ };
75
+
76
+ export const expectedForwardedTags = {
77
+ fetchingLiquidTags: false,
78
+ fetchingSchema: true,
79
+ fetchingSchemaError: '',
80
+ injectedTags: undefined,
81
+ liquidTags: [],
82
+ messages: [],
83
+ metaEntities: {
84
+ layouts: [],
85
+ tagLookupMap: {},
86
+ tags: []
87
+ },
88
+ orgID: "",
89
+ token: ""
74
90
  };
@@ -7,7 +7,7 @@ import * as types from './constants';
7
7
  import initialState from '../../initialState';
8
8
  import { FAILURE } from '../App/constants';
9
9
  import { TAG } from '../Whatsapp/constants';
10
- import { getTagMapValue } from '../../utils/tagValidations';
10
+ import { getTagMapValue, getForwardedMapValues } from '../../utils/tagValidations';
11
11
 
12
12
  function capReducer(state = fromJS(initialState.cap), action) {
13
13
  switch (action.type) {
@@ -117,7 +117,8 @@ function capReducer(state = fromJS(initialState.cap), action) {
117
117
  const combinedTagMap = {
118
118
  ...standardTagMap,
119
119
  ...customSubtags,
120
- ...extendedSubtags
120
+ ...extendedSubtags,
121
+ ...state.getIn(['metaEntities', 'tagLookupMap'])?.toJS(),
121
122
  };
122
123
  const stateMeta = state.get("metaEntities");
123
124
  return state
@@ -142,7 +143,18 @@ function capReducer(state = fromJS(initialState.cap), action) {
142
143
  metaEntities.tags.custom = _.filter(state.get('metaEntities').tags.custom, (tag) => action.tagList.indexOf(tag.name) === -1);
143
144
  return state.setIn(['metaEntities'], metaEntities);
144
145
  case types.SET_INJECTED_TAGS:
145
- return state.set('injectedTags', action.injectedTags);
146
+
147
+ // Deep clone the tagLookupMap to avoid direct mutations
148
+ let updatedMetaEntitiesTagLookUp = _.cloneDeep(state.getIn(['metaEntities', 'tagLookupMap']));
149
+ const formattedInjectedTags = getForwardedMapValues(action?.injectedTags);
150
+ // Merge the injectedTags with the existing tagLookupMap
151
+ updatedMetaEntitiesTagLookUp = {
152
+ ...formattedInjectedTags || {},
153
+ ...updatedMetaEntitiesTagLookUp || {},
154
+ };
155
+ return state
156
+ .set('injectedTags', action.injectedTags)
157
+ .setIn(['metaEntities', 'tagLookupMap'], fromJS(updatedMetaEntitiesTagLookUp));
146
158
  case types.GET_TOPBAR_MENU_DATA_REQUEST:
147
159
  return state.set('topbarMenuData', fromJS({ status: 'request' }));
148
160
  case types.GET_TOPBAR_MENU_DATA_SUCCESS:
@@ -10,6 +10,7 @@ import {
10
10
  GET_LIQUID_TAGS_FAILURE,
11
11
  GET_LIQUID_TAGS_REQUEST,
12
12
  GET_SCHEMA_FOR_ENTITY_SUCCESS,
13
+ SET_INJECTED_TAGS,
13
14
  } from '../constants';
14
15
  import reducer from '../reducer';
15
16
  import initialState from '../../../initialState';
@@ -18,7 +19,8 @@ import {
18
19
  expectedStateGetLiquidTagsFailure,
19
20
  expectedStateGetLiquidTagsSuccess,
20
21
  expectedStateGetSchemaForEntitySuccessTAG,
21
- expectedStateGetSchemaForEntitySuccess
22
+ expectedStateGetSchemaForEntitySuccess,
23
+ expectedForwardedTags
22
24
  } from '../mockData';
23
25
 
24
26
  const mockedInitialState = fromJS(initialState.cap);
@@ -106,4 +108,12 @@ describe('should handle GET_SUPPORT_VIDEOS_CONFIG', () => {
106
108
 
107
109
  expect(reducer(mockedInitialState, action).toJS()).toEqual(expectedStateGetSchemaForEntitySuccess);
108
110
  });
111
+ it('handles the GET_SCHEMA_FOR_ENTITY_SUCCESS action', () => {
112
+ const action = {
113
+ type: SET_INJECTED_TAGS,
114
+ data: {},
115
+ };
116
+
117
+ expect(reducer(mockedInitialState, action).toJS())?.fetchingSchema?.toEqual(true);
118
+ });
109
119
  });
@@ -73,8 +73,3 @@ export const GET_SENDER_DETAILS_FAILURE =
73
73
  export const GET_CDN_TRANSFORMATION_CONFIG_REQUEST = 'app/v2Containers/Templates/GET_CDN_TRANSFORMATION_CONFIG_REQUEST';
74
74
  export const GET_CDN_TRANSFORMATION_CONFIG_SUCCESS = 'app/v2Containers/Templates/GET_CDN_TRANSFORMATION_CONFIG_SUCCESS';
75
75
  export const GET_CDN_TRANSFORMATION_CONFIG_FAILURE = 'app/v2Containers/Templates/GET_CDN_TRANSFORMATION_CONFIG_FAILURE';
76
-
77
- export const ACCOUNT_MAPPING_ON_CHANNEL = {
78
- whatsapp: 'selectedWhatsappAccount',
79
- zalo: 'selectedZaloAccount',
80
- };