@capillarytech/creatives-library 7.5.6 → 7.5.8

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.5.6",
4
+ "version": "7.5.8",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -274,6 +274,11 @@ function CapVideoUpload(props) {
274
274
  <CapHeading.CapHeadingSpan type="h6" className="video-description">
275
275
  <FormattedMessage {...messages.videoRatioDescription} />
276
276
 
277
+ </CapHeading.CapHeadingSpan>
278
+ {' '}
279
+ <CapHeading.CapHeadingSpan type="h6" className="video-description file-format">
280
+ <FormattedMessage {...messages.fileFormat} />
281
+
277
282
  </CapHeading.CapHeadingSpan>
278
283
  <CapHeading.CapHeadingSpan type="h6" className="video-description video-details">
279
284
  <FormattedMessage {...messages.videoSizeDescription} values={{size: bytes2Size(videoSize)}} />
@@ -24,6 +24,9 @@ $classPrefix: cap-custom-video-upload;
24
24
  .video-details{
25
25
  float: right;
26
26
  position: absolute;
27
- right: 40px;
27
+ right: 55px;
28
+ }
29
+ .file-format{
30
+ padding-left:9%;
28
31
  }
29
32
  }
@@ -51,4 +51,8 @@ export default defineMessages({
51
51
  id: `${scope}.imageReUpload`,
52
52
  defaultMessage: 'Re upload',
53
53
  },
54
+ fileFormat: {
55
+ id: `${scope}.fileFormat`,
56
+ defaultMessage: 'File formats: MP4',
57
+ },
54
58
  });
@@ -20,15 +20,17 @@ import {
20
20
  CapImage,
21
21
  CapSpin,
22
22
  CapIcon,
23
+ CapNotification,
24
+ CapTooltip,
23
25
  } from "@capillarytech/cap-ui-library";
24
26
  import facebookEmptyPlaceholder from '../../assets/facebookEmptyPlaceholder.png';
25
27
  import {
26
28
  IMAGE,
27
29
  VIDEO,
28
30
  CAROUSEL,
31
+ NO_CALL_TO_ACTION,
29
32
  } from '../../v2Containers/Facebook/Advertisement/constant';
30
33
 
31
- const NO_CALL_TO_ACTION = 'NO_CALL_TO_ACTION';
32
34
 
33
35
  export const CapFacebookPreview = (props) => {
34
36
  const {
@@ -48,9 +50,10 @@ export const CapFacebookPreview = (props) => {
48
50
  formatMessage,
49
51
  } = intl || {};
50
52
  const [adPreviewFormat, setAdPreviewFormat] = useState("DESKTOP_FEED_STANDARD");
53
+ const [disableAfterPreviewGenerate, setDisableAfterPreviewGenerate] = useState(false);
51
54
  const [random, setRandom] = useState(0);
52
55
  const {pageAccessToken, pageId} = orgUnitFacebookPageSettingsMap;
53
- const {previewIframe = "", isFetchingPreview = false} = facebookPreviewData;
56
+ const {previewIframe = "", isFetchingPreview = false, previewIframeError = ""} = facebookPreviewData;
54
57
  const facebookAdOptions = [
55
58
  {
56
59
  value: "DESKTOP_FEED_STANDARD",
@@ -271,11 +274,14 @@ export const CapFacebookPreview = (props) => {
271
274
  };
272
275
  facebookPreviewActions.getCarouselPreview(data);
273
276
  }
277
+ setDisableAfterPreviewGenerate(true);
274
278
  };
279
+
275
280
  const resetIframe = () => {
276
281
  const r = random + 1;
277
282
  setRandom(r);
278
283
  };
284
+
279
285
  const getIframe = (iframe) => {
280
286
  const divTag = document.createElement('div');
281
287
  divTag.innerHTML = iframe;
@@ -294,6 +300,7 @@ export const CapFacebookPreview = (props) => {
294
300
  />
295
301
  </>);
296
302
  };
303
+
297
304
  const showRefreshButton = () => {
298
305
  let isRefresh = false;
299
306
  props.previewData.forEach((obj) => {
@@ -305,9 +312,28 @@ export const CapFacebookPreview = (props) => {
305
312
  return isRefresh && previewIframe !== "";
306
313
  };
307
314
  const isRefreshButton = showRefreshButton();
315
+
308
316
  useEffect(() => {
309
317
  facebookPreviewActions.clearPreview();
310
318
  }, []);
319
+
320
+ useEffect(() => {
321
+ if (disableAfterPreviewGenerate) {
322
+ setDisableAfterPreviewGenerate(false);
323
+ }
324
+ }, [previewData,
325
+ primaryText,
326
+ callToAction]);
327
+
328
+ useEffect(() => {
329
+ if (previewIframeError) {
330
+ CapNotification.error({
331
+ message: formatMessage(messages.generatePreviewError),
332
+ });
333
+ setDisableAfterPreviewGenerate(false);
334
+ }
335
+ }, [previewIframeError]);
336
+
311
337
  return (
312
338
  <CapSpin spinning={isFetchingPreview}>
313
339
  <div style={{display: 'inline-block'}}>
@@ -328,13 +354,23 @@ export const CapFacebookPreview = (props) => {
328
354
  {formatMessage(messages.previewAdDesc)}
329
355
  </CapLabel>
330
356
  <div style={{marginBottom: 16}}>
331
- <CapButton
332
- type="secondary"
333
- disabled={disablePreviewButton}
334
- onClick={generatePreview}
335
- >
336
- <FormattedMessage {...messages.generatePreview} />
337
- </CapButton>
357
+ {(disablePreviewButton || disableAfterPreviewGenerate) ?
358
+ <CapTooltip title={formatMessage(messages.generatePreviewDisableToolTip)}>
359
+ <div className="button-disabled-tooltip-wrapper">
360
+ <CapButton
361
+ type="secondary"
362
+ disabled
363
+ >
364
+ <FormattedMessage {...messages.generatePreview} />
365
+ </CapButton>
366
+ </div>
367
+ </CapTooltip> :
368
+ <CapButton
369
+ type="secondary"
370
+ onClick={generatePreview}
371
+ >
372
+ <FormattedMessage {...messages.generatePreview} />
373
+ </CapButton>}
338
374
  {isRefreshButton && (<CapButton
339
375
  onClick={resetIframe}
340
376
  type="secondary"
@@ -135,4 +135,12 @@ export default defineMessages({
135
135
  id: `${messagePrefix}.videoNotePreview`,
136
136
  defaultMessage: 'Facebook may take time to upload the video. Please try Refreshing.',
137
137
  },
138
+ generatePreviewError: {
139
+ id: `${messagePrefix}.generatePreviewError`,
140
+ defaultMessage: 'Error in generating preview',
141
+ },
142
+ generatePreviewDisableToolTip: {
143
+ id: `${messagePrefix}.generatePreviewDisableToolTip`,
144
+ defaultMessage: 'Looks like either all the mandatory fields are not filled or there is no new change',
145
+ },
138
146
  });
@@ -11,6 +11,7 @@ import * as types from './constants';
11
11
  const initialState = fromJS({
12
12
  isFetchingPreview: false,
13
13
  previewIframe: "",
14
+ previewIframeError: "",
14
15
  });
15
16
 
16
17
  function capFacebookPreviewReducer(state = initialState, action) {
@@ -18,17 +19,24 @@ function capFacebookPreviewReducer(state = initialState, action) {
18
19
  case types.GENERATE_IMAGE_PREVIEW_REQUEST:
19
20
  case types.GENERATE_VIDEO_PREVIEW_REQUEST:
20
21
  case types.GENERATE_CAROUSEL_PREVIEW_REQUEST:
21
- return state.set('isFetchingPreview', true).set('previewIframe', "");
22
+ return state.set('isFetchingPreview', true)
23
+ .set('previewIframe', "")
24
+ .set("previewIframeError", "");
22
25
  case types.GENERATE_IMAGE_PREVIEW_SUCCESS:
23
26
  case types.GENERATE_VIDEO_PREVIEW_SUCCESS:
24
27
  case types.GENERATE_CAROUSEL_PREVIEW_SUCCESS:
25
- return state.set('isFetchingPreview', false).set('previewIframe', get(action, 'payload.fbPreview[0].body', ""));
28
+ return state.set('isFetchingPreview', false)
29
+ .set('previewIframe', get(action, 'payload.fbPreview[0].body', ""));
26
30
  case types.GENERATE_IMAGE_PREVIEW_FAILURE:
27
31
  case types.GENERATE_VIDEO_PREVIEW_FAILURE:
28
32
  case types.GENERATE_CAROUSEL_PREVIEW_FAILURE:
29
- return state.set('isFetchingPreview', false).set('previewIframe', "");
33
+ return state.set('isFetchingPreview', false)
34
+ .set('previewIframe', "")
35
+ .set("previewIframeError", get(action, 'payload.message', ""));
30
36
  case types.CLEAR_PREVIEW:
31
- return state.set('isFetchingPreview', false).set('previewIframe', "");
37
+ return state.set('isFetchingPreview', false)
38
+ .set('previewIframe', "")
39
+ .set("previewIframeError", "");
32
40
  default:
33
41
  return state;
34
42
  }
@@ -6,11 +6,11 @@ import * as type from './constants';
6
6
  export function* getImageFacebookPreview(previewData) {
7
7
  try {
8
8
  const response = yield call(Api.getImageFacebookPreview, previewData );
9
- const { errors, response: responsePreview } = response;
10
- if (errors && errors.length) {
9
+ const { status, response: responsePreview } = response;
10
+ if (status && status.isError) {
11
11
  yield put({
12
12
  type: type.GENERATE_IMAGE_PREVIEW_FAILURE,
13
- payload: errors,
13
+ payload: status,
14
14
  });
15
15
  } else {
16
16
  yield put({
@@ -29,11 +29,11 @@ export function* getImageFacebookPreview(previewData) {
29
29
  export function* getVideoFacebookPreview(previewData) {
30
30
  try {
31
31
  const response = yield call(Api.getVideoFacebookPreview, previewData);
32
- const { errors, response: responsePreview } = response;
33
- if (errors && errors.length) {
32
+ const { status, response: responsePreview } = response;
33
+ if (status && status.isError) {
34
34
  yield put({
35
35
  type: type.GENERATE_VIDEO_PREVIEW_FAILURE,
36
- payload: errors,
36
+ payload: status,
37
37
  });
38
38
  } else {
39
39
  yield put({
@@ -52,11 +52,11 @@ export function* getVideoFacebookPreview(previewData) {
52
52
  export function* getCarouselFacebookPreview(previewData) {
53
53
  try {
54
54
  const response = yield call(Api.getCarouselFacebookPreview, previewData);
55
- const { errors, response: responsePreview } = response;
56
- if (errors && errors.length) {
55
+ const { status, response: responsePreview } = response;
56
+ if (status && status.isError) {
57
57
  yield put({
58
58
  type: type.GENERATE_CAROUSEL_PREVIEW_FAILURE,
59
- payload: errors,
59
+ payload: status,
60
60
  });
61
61
  } else {
62
62
  yield put({
@@ -10,3 +10,4 @@ export const IMAGE = 'IMAGE';
10
10
  export const VIDEO = 'VIDEO';
11
11
  export const CAROUSEL = 'CAROUSEL';
12
12
  export const IMAGE_VIDEO = 'imageVideo';
13
+ export const NO_CALL_TO_ACTION = 'NO_CALL_TO_ACTION';
@@ -52,6 +52,7 @@ import {
52
52
  VIDEO,
53
53
  CAROUSEL,
54
54
  IMAGE_VIDEO,
55
+ NO_CALL_TO_ACTION,
55
56
  } from './constant';
56
57
 
57
58
  export const Advertisement = (props) => {
@@ -105,9 +106,8 @@ export const Advertisement = (props) => {
105
106
  const [primaryText, setPrimaryText] = useState('');
106
107
  const [pageId, setPageId] = useState(false);
107
108
  const [displayLink, setDisplayLink] = useState('');
108
- const [callToAction, setCallToAction] = useState("NO_CALL_TO_ACTION");
109
+ const [callToAction, setCallToAction] = useState(NO_CALL_TO_ACTION);
109
110
  const [callToActionError, setCallToActionError] = useState(false);
110
-
111
111
  const [messageTitle, updateMessageTitle] = useState('');
112
112
  const [step, updateStep] = useState('modeSelection');
113
113
  const [activeIndex, updateActiveIndex] = useState(`${defaultActiveIndex}`);
@@ -116,7 +116,6 @@ export const Advertisement = (props) => {
116
116
  const [editNameState, setEditNameState] = useState(false);
117
117
  const isCarouselSelectedAd = selectedAd === CAROUSEL;
118
118
  const isImgVideoSelectedAd = selectedAd === IMAGE_VIDEO;
119
-
120
119
  const activeCarouselData = carouselData[activeIndex];
121
120
 
122
121
  const uploadFbAdAsset = useCallback(( file,
@@ -430,6 +429,7 @@ export const Advertisement = (props) => {
430
429
  flag = true;
431
430
  return flag;
432
431
  }
432
+ const subTypes = [];
433
433
  carouselData.forEach((obj) => {
434
434
  const {
435
435
  webSiteLink,
@@ -446,17 +446,19 @@ export const Advertisement = (props) => {
446
446
  } else if (Object.keys(videoData).length === 0 && subType === VIDEO) {
447
447
  flag = true;
448
448
  }
449
- if (subType === VIDEO) {
450
- if (callToAction === "NO_CALL_TO_ACTION" && !callToActionError) {
451
- setCallToActionError(messages.callToActionMandatoryError);
452
- flag = true;
453
- } else if (callToAction !== "NO_CALL_TO_ACTION" && callToActionError) {
454
- setCallToActionError(false);
455
- }
456
- }
449
+ subTypes.push(subType);
457
450
  });
458
- if (callToAction === "NO_CALL_TO_ACTION" && callToActionError) {
459
- flag = true;
451
+ if (subTypes.includes(VIDEO) ) {
452
+ if (callToAction === NO_CALL_TO_ACTION && !callToActionError) {
453
+ setCallToActionError(messages.callToActionMandatoryError);
454
+ flag = true;
455
+ } else if (callToAction !== NO_CALL_TO_ACTION && callToActionError) {
456
+ setCallToActionError(false);
457
+ flag = false;
458
+ }
459
+ } else if (callToActionError) {
460
+ setCallToActionError(false);
461
+ flag = false;
460
462
  }
461
463
  return flag;
462
464
  }, [
@@ -549,6 +551,7 @@ export const Advertisement = (props) => {
549
551
  onChange={onChangePrimaryText}
550
552
  defaultValue={primaryText || ''}
551
553
  value={primaryText || ''}
554
+ maxLength={125}
552
555
  rows={3}
553
556
  cols={2}
554
557
  placeholder={formatMessage(messages.primaryTextPlaceholder)}
@@ -858,7 +861,7 @@ export const Advertisement = (props) => {
858
861
  <div className="cap-header-facebook-ad">
859
862
  <CapHeading
860
863
  type="h2"
861
- style={{display: 'inline'}}
864
+ className="truncate-text"
862
865
  >
863
866
  {editNameState ? <CapInput
864
867
  type="input"
@@ -12,6 +12,13 @@ $classPrefix: add-facebook-ad-section;
12
12
  padding: 0;
13
13
  }
14
14
  }
15
+ .truncate-text{
16
+ overflow: hidden;
17
+ text-overflow: ellipsis;
18
+ white-space: nowrap;
19
+ min-width: 112px;
20
+ max-width: 920px;
21
+ }
15
22
  .cap-header-facebook-ad{
16
23
  position: fixed;
17
24
  top: 27px;
@@ -29,15 +36,22 @@ $classPrefix: add-facebook-ad-section;
29
36
  margin-left: 6px;
30
37
  }
31
38
  }
32
- .cap-image-upload-CAROUSEL{
39
+ .cap-custom-image-upload{
33
40
  .dragger-button.re-upload{
34
- margin-top: 90px;
35
- top: 0;
41
+ margin-top: 50px;
42
+ top: 0px;
36
43
  position: absolute;
37
- right: 80;
44
+ right: 60px;
38
45
  color: $FONT_COLOR_05;
39
46
  }
47
+ .cap-image-upload-CAROUSEL{
48
+ .dragger-button.re-upload{
49
+ margin-top: 90px;
50
+ right: 0px;
51
+ }
52
+ }
40
53
  }
54
+
41
55
  .facebook-ad-type-card{
42
56
  .ant-card-body {
43
57
  display:flex;
@@ -358,6 +358,7 @@ Facebook.propTypes = {
358
358
  templateData: PropTypes.object,
359
359
  cap: PropTypes.object,
360
360
  messageDetails: PropTypes.object,
361
+ params: PropTypes.object,
361
362
  onFacebookSubmit: PropTypes.func,
362
363
  marketingObjectiveList: PropTypes.arrayOf(PropTypes.string),
363
364
  facebookActions: PropTypes.func,
@@ -365,6 +366,7 @@ Facebook.propTypes = {
365
366
  isFullMode: PropTypes.boolean,
366
367
  fbADData: PropTypes.object,
367
368
  onCreateComplete: PropTypes.func,
369
+ facebookTemplateData: PropTypes.object,
368
370
  };
369
371
 
370
372
  Facebook.defaultProps = {
@@ -422,7 +422,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
422
422
  }
423
423
  if (!nextProps.Templates.deleteTemplateInProgress && !isEqual(nextProps.Templates.deleteTemplateInProgress, this.props.Templates.deleteTemplateInProgress) &&
424
424
  nextProps.Templates.deleteResponse) {
425
- const message = `${this.state.channel.toUpperCase()} ${this.props.intl.formatMessage(messages['Template deleted successfully'])}`;
425
+ const message = `${this.state.channel} ${this.props.intl.formatMessage(messages['Template deleted successfully'])}`;
426
426
  CapNotification.success({key: 'deleteSucess', message});
427
427
  this.getAllTemplates({params, resetPage: true});
428
428
  }
@@ -1802,7 +1802,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
1802
1802
  const isMobilePushChannel = channel === MOBILE_PUSH;
1803
1803
  const isLineChannel = channel === LINE;
1804
1804
 
1805
-
1805
+
1806
1806
  if ((isWechatChannel || isMobilePushChannel || isLineChannel) && !isEmpty(weCrmAccounts)) {
1807
1807
  forEach(weCrmAccounts, (account) => {
1808
1808
  if ((isWechatChannel && account.configs && account.configs.is_wecrm_enabled) || isMobilePushChannel || isLineChannel) {