@capillarytech/creatives-library 8.0.79 → 8.0.81

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": "8.0.79",
4
+ "version": "8.0.81",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
package/services/api.js CHANGED
@@ -2,13 +2,12 @@
2
2
  * Created by vivek on 3/5/17.
3
3
  */
4
4
  import 'whatwg-fetch';
5
- import { GA, decompressJsonObject } from '@capillarytech/cap-ui-utils';
6
- import { get } from 'lodash';
7
5
  import { loadItem, clearItem } from './localStorageApi';
8
6
  import config from '../config/app';
9
7
  import pathConfig from '../config/path';
10
8
  import getSchema from './getSchema';
11
9
  import * as API from '../utils/ApiCaller';
10
+ import { GA, decompressJsonObject } from '@capillarytech/cap-ui-utils';
12
11
  import { addBaseToTemplate } from '../utils/commonUtils';
13
12
  import { EMAIL, SMS } from '../v2Containers/CreativesContainer/constants';
14
13
  let API_ENDPOINT = config.development.api_endpoint;
@@ -301,17 +300,15 @@ export const getAllAssets = ({assetType, queryParams = {}}) => {
301
300
  });
302
301
  // const url = `https://nightly.capillary.in/arya/api/v1/creatives/assets/${assetType}?query=${JSON.stringify(queryParams)}`;
303
302
  return request(url, getAPICallObject('GET'));
304
- };
305
-
303
+ }
304
+ ;
306
305
  export const deleteAssetById = ({assetId, assetType}) => {
307
306
  const url = `${API_ENDPOINT}/assets/${assetId}/${assetType}`;
308
307
  return request(url, getAPICallObject('DELETE'));
309
308
  // return API.deleteResource(url);
310
309
  };
311
310
 
312
- export const uploadFile = ({
313
- file, assetType, fileParams, mode, wechatParams, whatsappParams,
314
- }) => {
311
+ export const uploadFile = ({file, assetType, fileParams, mode, wechatParams, whatsappParams}) => {
315
312
  const data = new FormData();
316
313
  let fileName = '';
317
314
  try {
@@ -406,20 +403,14 @@ export const getCmsData = (cmsType, projectId, langId) => {
406
403
  return API.get(url);
407
404
  };
408
405
 
409
- export const getEdmTemplates = async () => {
406
+ export const getEdmTemplates = () => {
410
407
  const url = `${API_ENDPOINT}/templates/email/default`;
411
- const compressedEdmTemplates = await request(url, getAPICallObject('GET'));
412
- const response = get(compressedEdmTemplates, 'response', '');
413
- const decompressedEdmTemplates = decompressJsonObject(response);
414
- return { ...compressedEdmTemplates, response: addBaseToTemplate(decompressedEdmTemplates) };
408
+ return request(url, getAPICallObject('GET'));
415
409
  };
416
410
 
417
- export const getDefaultBeeTemplates = async () => {
411
+ export const getDefaultBeeTemplates = () => {
418
412
  const url = `${API_ENDPOINT}/templates/v2/email/default`;
419
- const compressedDefaultBeeTemplates = await request(url, getAPICallObject('GET'));
420
- const response = get(compressedDefaultBeeTemplates, 'response', '');
421
- const decompressedBeeTemplates = decompressJsonObject(response);
422
- return { ...compressedDefaultBeeTemplates, response: addBaseToTemplate(decompressedBeeTemplates) };
413
+ return request(url, getAPICallObject('GET'));
423
414
  };
424
415
 
425
416
  // All about line
@@ -12,22 +12,17 @@ import {
12
12
  askAiraForLiquid,
13
13
  getLiquidTags,
14
14
  fetchSchemaForEntity,
15
- getDefaultBeeTemplates,
16
- getEdmTemplates,
17
15
  } from '../api';
18
16
  import { mockData } from './mockData';
19
17
  import getSchema from '../getSchema';
20
18
  const sampleFile = require('../../assets/line.png');
21
19
 
22
20
  let mockDecompressJsonObject;
23
- let mockAddBaseToTemplate;
24
21
  jest.mock('@capillarytech/cap-ui-utils', () => {
25
22
  mockDecompressJsonObject = jest.fn();
26
- mockAddBaseToTemplate = jest.fn();
27
23
  return {
28
24
  ...jest.requireActual('@capillarytech/cap-ui-utils'),
29
25
  decompressJsonObject: mockDecompressJsonObject,
30
- addBaseToTemplate: mockAddBaseToTemplate,
31
26
  };
32
27
  });
33
28
 
@@ -141,7 +136,7 @@ describe('getAllTemplates -- Test with valid responses', () => {
141
136
  global.fetch.mockReturnValue(Promise.resolve({json: () => Promise.resolve(),}));
142
137
  mockDecompressJsonObject.mockReturnValue();
143
138
  expect(await getAllTemplates({channel: 'email'})).toEqual({
144
- response: undefined,
139
+ "response": undefined,
145
140
  });
146
141
  });
147
142
 
@@ -498,114 +493,3 @@ describe('fetchSchemaForEntity', () => {
498
493
  expect(console.error).toHaveBeenCalledWith(mockError);
499
494
  });
500
495
  });
501
-
502
- describe('Email Template APIs', () => {
503
- beforeEach(() => {
504
- global.fetch = jest.fn();
505
- });
506
-
507
- afterEach(() => {
508
- jest.restoreAllMocks();
509
- });
510
-
511
- const sharedTests = (apiFunction, functionName) => {
512
- it('should handle successful response', async () => {
513
- const mockResponse = { response: 'compressed-data' };
514
- const mockDecompressed = { template: 'decompressed-data' };
515
- const mockWithBase = { template: 'data-with-base' };
516
-
517
- global.fetch.mockReturnValue(Promise.resolve({
518
- status: 200,
519
- json: () => Promise.resolve(mockResponse),
520
- }));
521
- mockDecompressJsonObject.mockReturnValue(mockDecompressed);
522
- mockAddBaseToTemplate.mockReturnValue(mockWithBase);
523
-
524
- const result = await apiFunction();
525
- expect(result).toEqual({
526
- ...mockResponse,
527
- response: mockDecompressed,
528
- });
529
- });
530
-
531
- it('should handle response property as empty object', async () => {
532
- const mockResponse = { response: {} };
533
-
534
- global.fetch.mockReturnValue(Promise.resolve({
535
- status: 200,
536
- json: () => Promise.resolve(mockResponse),
537
- }));
538
- mockDecompressJsonObject.mockReturnValue({});
539
- mockAddBaseToTemplate.mockReturnValue({});
540
-
541
- const result = await apiFunction();
542
- expect(result).toEqual({
543
- ...mockResponse,
544
- response: {},
545
- });
546
- });
547
-
548
- it('should handle missing response property', async () => {
549
- const mockResponse = {};
550
-
551
- global.fetch.mockReturnValue(Promise.resolve({
552
- status: 200,
553
- json: () => Promise.resolve(mockResponse),
554
- }));
555
- mockDecompressJsonObject.mockReturnValue('');
556
- mockAddBaseToTemplate.mockReturnValue('');
557
-
558
- const result = await apiFunction();
559
- expect(result).toEqual({
560
- response: '',
561
- });
562
- });
563
-
564
- it('should handle null response', async () => {
565
- global.fetch.mockReturnValue(Promise.resolve({
566
- json: () => Promise.resolve(null),
567
- }));
568
- mockDecompressJsonObject.mockReturnValue('');
569
- mockAddBaseToTemplate.mockReturnValue('');
570
-
571
- const result = await apiFunction();
572
- expect(result).toEqual({
573
- response: '',
574
- });
575
- });
576
-
577
- it('should handle undefined response', async () => {
578
- global.fetch.mockReturnValue(Promise.resolve({
579
- json: () => Promise.resolve(undefined),
580
- }));
581
- mockDecompressJsonObject.mockReturnValue('');
582
- mockAddBaseToTemplate.mockReturnValue('');
583
-
584
- const result = await apiFunction();
585
- expect(result).toEqual({
586
- response: '',
587
- });
588
- });
589
-
590
- it('should handle fetch failure', async () => {
591
- global.fetch.mockRejectedValue(new Error('Network error'));
592
- mockDecompressJsonObject.mockReturnValue(undefined);
593
- mockAddBaseToTemplate.mockReturnValue(undefined);
594
- console.error = jest.fn();
595
-
596
- const result = await apiFunction();
597
-
598
- expect(result).toEqual({
599
- response: undefined,
600
- });
601
- });
602
- };
603
-
604
- describe('getEdmTemplates', () => {
605
- sharedTests(getEdmTemplates, 'getEdmTemplates');
606
- });
607
-
608
- describe('getDefaultBeeTemplates', () => {
609
- sharedTests(getDefaultBeeTemplates, 'getDefaultBeeTemplates');
610
- });
611
- });
@@ -998,7 +998,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
998
998
  if (tagValidationResponse?.isContentEmpty) {
999
999
  errorString += this.props.intl.formatMessage(messages.emailBodyEmptyError);
1000
1000
  // Adds a bypass for cases where content is initially empty in the creation flow.
1001
- if(this.liquidFlow && !this.props.isEdit){
1001
+ if(this.liquidFlow){
1002
1002
  errorString = "";
1003
1003
  isLiquidValid = true;
1004
1004
  }
@@ -1102,13 +1102,16 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
1102
1102
  const handleResult = (result) => {
1103
1103
  const {formatMessage} = this.props.intl;
1104
1104
  // Checks for errors in the result and displays them if any are found.
1105
- if (result?.errors?.length > 0) {
1105
+ const validString = /\S/.test(content);
1106
+ // If the content is empty or there are errors in the result, display the necessary validation messages.
1107
+ if (result?.errors?.length > 0 || !validString) {
1106
1108
  this.setState((prevState) => ({
1107
1109
  liquidErrorMessage: {
1108
1110
  ...prevState.liquidErrorMessage,
1111
+ STANDARD_ERROR_MSG: !validString ? [...(prevState.liquidErrorMessage?.STANDARD_ERROR_MSG || []), formatMessage(messages.emailBodyEmptyError)] : prevState.liquidErrorMessage?.STANDARD_ERROR_MSG,
1109
1112
  LIQUID_ERROR_MSG: result?.errors?.map(error => error?.message) ?? [formatMessage(messages.somethingWentWrong)],
1110
- },
1111
- }) , () => {
1113
+ }
1114
+ }), () => {
1112
1115
  this.props.showLiquidErrorInFooter(this.state.liquidErrorMessage);
1113
1116
  });
1114
1117
  this.props.stopValidation();
@@ -199,9 +199,9 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
199
199
  this.setState({isDragDrop: true});
200
200
  }
201
201
  if (this.props.params.id) {
202
- this.props.actions.getCmsSetting(BEE_PLUGIN, _.get(this.props.Templates.BEETemplate, 'versions.base.drag_drop_id', this.props.Templates.BEETemplate?._id), 'open', undefined, isBEESupport, isBEEAppEnable);
202
+ this.props.actions.getCmsSetting(BEE_PLUGIN, this.props.Templates.BEETemplate._id, 'open', undefined, isBEESupport, isBEEAppEnable);
203
203
  } else if (this.props.location.query.module !== "library" || (this.props.location.query.module === "library" && !this.props.templateData)) {
204
- this.props.actions.getCmsSetting(BEE_PLUGIN, _.get(this.props.Templates.BEETemplate, 'versions.base.drag_drop_id', this.props.Templates.BEETemplate?._id), 'create', undefined, isBEESupport, isBEEAppEnable);
204
+ this.props.actions.getCmsSetting(BEE_PLUGIN, this.props.Templates.BEETemplate._id, 'create', undefined, isBEESupport, isBEEAppEnable);
205
205
  }
206
206
  }
207
207
  this.setState({ content: (this.props.Templates.selectedEmailLayout ? this.props.Templates.selectedEmailLayout : ''), formData});
@@ -0,0 +1,103 @@
1
+ export const emptyInputs = {
2
+ emptyObject: {},
3
+ nullInput: null,
4
+ undefinedInput: undefined,
5
+ expectedOutput: {}
6
+ };
7
+
8
+ export const noValidPackageIdsInput = {
9
+ input: {
10
+ standard: [
11
+ { _id: '1', definition: { stickerUrl: 'url1' } },
12
+ { _id: '2', definition: {} }
13
+ ],
14
+ custom: [
15
+ { _id: '3', definition: null },
16
+ { _id: '4' }
17
+ ]
18
+ },
19
+ expectedOutput: {}
20
+ };
21
+
22
+ export const singleCategoryInput = {
23
+ input: {
24
+ standard: [
25
+ { _id: '1', definition: { packageId: 'pkg1', stickerUrl: 'url1' } },
26
+ { _id: '2', definition: { packageId: 'pkg1', stickerUrl: 'url2' } },
27
+ { _id: '3', definition: { packageId: 'pkg2', stickerUrl: 'url3' } }
28
+ ]
29
+ },
30
+ expectedOutput: {
31
+ pkg1: [
32
+ { _id: '1', definition: { packageId: 'pkg1', stickerUrl: 'url1' } },
33
+ { _id: '2', definition: { packageId: 'pkg1', stickerUrl: 'url2' } }
34
+ ],
35
+ pkg2: [
36
+ { _id: '3', definition: { packageId: 'pkg2', stickerUrl: 'url3' } }
37
+ ]
38
+ }
39
+ };
40
+
41
+ export const multipleCategoriesInput = {
42
+ input: {
43
+ standard: [
44
+ { _id: '1', definition: { packageId: 'pkg1', stickerUrl: 'url1' } },
45
+ { _id: '2', definition: { packageId: 'pkg2', stickerUrl: 'url2' } }
46
+ ],
47
+ custom: [
48
+ { _id: '3', definition: { packageId: 'pkg1', stickerUrl: 'url3' } },
49
+ { _id: '4', definition: { packageId: 'pkg3', stickerUrl: 'url4' } }
50
+ ],
51
+ extended: [
52
+ { _id: '5', definition: { packageId: 'pkg2', stickerUrl: 'url5' } }
53
+ ]
54
+ },
55
+ expectedOutput: {
56
+ pkg1: [
57
+ { _id: '1', definition: { packageId: 'pkg1', stickerUrl: 'url1' } },
58
+ { _id: '3', definition: { packageId: 'pkg1', stickerUrl: 'url3' } }
59
+ ],
60
+ pkg2: [
61
+ { _id: '2', definition: { packageId: 'pkg2', stickerUrl: 'url2' } },
62
+ { _id: '5', definition: { packageId: 'pkg2', stickerUrl: 'url5' } }
63
+ ],
64
+ pkg3: [
65
+ { _id: '4', definition: { packageId: 'pkg3', stickerUrl: 'url4' } }
66
+ ]
67
+ }
68
+ };
69
+
70
+ export const nonArrayCategoriesInput = {
71
+ input: {
72
+ standard: [
73
+ { _id: '1', definition: { packageId: 'pkg1', stickerUrl: 'url1' } }
74
+ ],
75
+ custom: 'not an array',
76
+ extended: null
77
+ },
78
+ expectedOutput: {
79
+ pkg1: [
80
+ { _id: '1', definition: { packageId: 'pkg1', stickerUrl: 'url1' } }
81
+ ]
82
+ }
83
+ };
84
+
85
+ export const mixedStickerDataInput = {
86
+ input: {
87
+ standard: [
88
+ { _id: '1', definition: { packageId: 'pkg1', stickerUrl: 'url1' } },
89
+ { _id: '2', definition: { stickerUrl: 'url2' } },
90
+ { _id: '3' }
91
+ ],
92
+ custom: [
93
+ { _id: '4', definition: { packageId: 'pkg1', stickerUrl: 'url4' } },
94
+ { _id: '5', definition: { packageId: null, stickerUrl: 'url5' } }
95
+ ]
96
+ },
97
+ expectedOutput: {
98
+ pkg1: [
99
+ { _id: '1', definition: { packageId: 'pkg1', stickerUrl: 'url1' } },
100
+ { _id: '4', definition: { packageId: 'pkg1', stickerUrl: 'url4' } }
101
+ ]
102
+ }
103
+ };
@@ -0,0 +1,37 @@
1
+ import { groupLineStickers } from '../utils';
2
+ import {
3
+ emptyInputs,
4
+ noValidPackageIdsInput,
5
+ singleCategoryInput,
6
+ multipleCategoriesInput,
7
+ nonArrayCategoriesInput,
8
+ mixedStickerDataInput
9
+ } from './mockData';
10
+
11
+ describe('groupLineStickers', () => {
12
+ it('should return empty object when input is empty', () => {
13
+ expect(groupLineStickers(emptyInputs.emptyObject)).toEqual(emptyInputs.expectedOutput);
14
+ expect(groupLineStickers(emptyInputs.nullInput)).toEqual(emptyInputs.expectedOutput);
15
+ expect(groupLineStickers(emptyInputs.undefinedInput)).toEqual(emptyInputs.expectedOutput);
16
+ });
17
+
18
+ it('should handle input with no valid packageIds', () => {
19
+ expect(groupLineStickers(noValidPackageIdsInput.input)).toEqual(noValidPackageIdsInput.expectedOutput);
20
+ });
21
+
22
+ it('should group stickers by packageId within single category', () => {
23
+ expect(groupLineStickers(singleCategoryInput.input)).toEqual(singleCategoryInput.expectedOutput);
24
+ });
25
+
26
+ it('should group stickers by packageId across multiple categories', () => {
27
+ expect(groupLineStickers(multipleCategoriesInput.input)).toEqual(multipleCategoriesInput.expectedOutput);
28
+ });
29
+
30
+ it('should skip non-array categories', () => {
31
+ expect(groupLineStickers(nonArrayCategoriesInput.input)).toEqual(nonArrayCategoriesInput.expectedOutput);
32
+ });
33
+
34
+ it('should handle mixed valid and invalid sticker data', () => {
35
+ expect(groupLineStickers(mixedStickerDataInput.input)).toEqual(mixedStickerDataInput.expectedOutput);
36
+ });
37
+ });
@@ -6,15 +6,26 @@ import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
6
6
 
7
7
  export const groupLineStickers = (lineStickers) => {
8
8
  const stickerGroup = {};
9
- lineStickers.forEach((lineSticker) => {
10
- const packageId = get(lineSticker, 'definition.packageId');
11
- if (packageId) {
12
- const stickerGroupPackageId = stickerGroup[packageId];
13
- if (stickerGroupPackageId && Array.isArray(stickerGroupPackageId)) {
14
- stickerGroup[packageId].push(lineSticker);
15
- } else {
16
- stickerGroup[packageId] = [];
17
- }
9
+ // Return early if lineStickers is null or undefined
10
+ if (!lineStickers) return stickerGroup;
11
+
12
+ // Now we can safely iterate as lineStickers is defined
13
+ Object?.keys(lineStickers)?.forEach((key) => {
14
+ const category = lineStickers[key];
15
+ if (Array.isArray(category)) {
16
+ //iterating over each category [standard, custom, extended]
17
+ category?.forEach((lineSticker) => {
18
+ const packageId = get(lineSticker, 'definition.packageId');
19
+ if (packageId) {
20
+ const stickerGroupPackageId = stickerGroup[packageId];
21
+ if (stickerGroupPackageId && Array.isArray(stickerGroupPackageId)) {
22
+ stickerGroup[packageId].push(lineSticker);
23
+ } else {
24
+ //initialising with first sticker for each package ID
25
+ stickerGroup[packageId] = [lineSticker];
26
+ }
27
+ }
28
+ });
18
29
  }
19
30
  });
20
31
  return stickerGroup;
@@ -35,7 +46,7 @@ export const getContent = ({ lineStickers, onStickerSelect }) => (
35
46
  >
36
47
  <CapImage
37
48
  src={definition.stickerUrl}
38
- rest={{ height: 70 }}
49
+ rest = {{ height: 70 }}
39
50
  rest={{
40
51
  height: 70,
41
52
  onMouseOut: e => (e.currentTarget.src = definition.stickerUrl),