@capillarytech/creatives-library 8.0.346 → 8.0.348

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.346",
4
+ "version": "8.0.348",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -18,7 +18,7 @@ import CapRow from '@capillarytech/cap-ui-library/CapRow';
18
18
  import { ANDROID, IOS } from '../constants';
19
19
  import messages from '../messages';
20
20
  import { getWhatsappQuickReply, getWhatsappCarouselButtonView } from '../../../v2Containers/Whatsapp/utils';
21
- import { QUICK_REPLY, PHONE_NUMBER, WHATSAPP_CATEGORIES } from '../../../v2Containers/Whatsapp/constants';
21
+ import { QUICK_REPLY, PHONE_NUMBER, WHATSAPP_CATEGORIES, TEMPLATE_VARIABLE_REGEX } from '../../../v2Containers/Whatsapp/constants';
22
22
  import videoPlay from '../../../assets/videoPlay.svg';
23
23
  import whatsappImageEmptyPreview from '../../TemplatePreview/assets/images/empty_image_preview.svg';
24
24
  import whatsappVideoEmptyPreview from '../../TemplatePreview/assets/images/empty_video_preview.svg';
@@ -27,6 +27,8 @@ import whatsappVideoEmptyPreview from '../../TemplatePreview/assets/images/empty
27
27
  const whatsappMobileAndroid = require('../../../assets/whatsapp_android.png');
28
28
  const whatsappMobileIos = require('../../../assets/whatsapp_ios.png');
29
29
 
30
+ const { CapLabelInline } = CapLabel;
31
+
30
32
  const WhatsAppPreviewContent = ({
31
33
  content,
32
34
  device,
@@ -214,11 +216,21 @@ const WhatsAppPreviewContent = ({
214
216
 
215
217
  {/* Image Preview */}
216
218
  {content?.whatsappImageSrc && (
217
- <CapImage
218
- src={content.whatsappImageSrc}
219
- className="whatsapp-image"
220
- alt={formatMessage(messages.previewGenerated)}
221
- />
219
+ TEMPLATE_VARIABLE_REGEX.test(content.whatsappImageSrc) ? (
220
+ <CapRow className="whatsapp-image-url-placeholder">
221
+ <CapIcon type="picture" size="s" className="whatsapp-image-url-placeholder-icon" />
222
+ <CapLabelInline type="label2" className="whatsapp-image-url-placeholder-text">
223
+ {content.whatsappImageSrc}
224
+ </CapLabelInline>
225
+ </CapRow>
226
+ ) : (
227
+ <CapImage
228
+ src={content.whatsappImageSrc}
229
+ className="whatsapp-image"
230
+ alt={formatMessage(messages.previewGenerated)}
231
+ onError={(e) => { e.target.src = whatsappImageEmptyPreview; }}
232
+ />
233
+ )
222
234
  )}
223
235
 
224
236
  {/* Video Preview */}
@@ -940,6 +940,33 @@
940
940
  }
941
941
  }
942
942
 
943
+ .whatsapp-image-url-placeholder {
944
+ display: flex;
945
+ flex-direction: column;
946
+ align-items: center;
947
+ justify-content: center;
948
+ gap: $CAP_SPACE_08;
949
+ width: 100%;
950
+ min-height: 5rem;
951
+ max-height: 8.786rem;
952
+ margin-bottom: $CAP_SPACE_04;
953
+ background-color: $CAP_G09;
954
+ border-radius: $CAP_SPACE_04;
955
+ padding: $CAP_SPACE_08;
956
+
957
+ .whatsapp-image-url-placeholder-icon {
958
+ color: $CAP_G05;
959
+ font-size: 1.5rem;
960
+ }
961
+
962
+ .whatsapp-image-url-placeholder-text {
963
+ font-size: $FONT_SIZE_S;
964
+ color: $CAP_G04;
965
+ text-align: center;
966
+ word-break: break-all;
967
+ }
968
+ }
969
+
943
970
  .whatsapp-image {
944
971
  width: 100%;
945
972
  max-height: 8.786rem;
@@ -26,6 +26,7 @@ jest.mock('../../../../v2Containers/Whatsapp/constants', () => ({
26
26
  WHATSAPP_CATEGORIES: {
27
27
  authentication: 'authentication',
28
28
  },
29
+ TEMPLATE_VARIABLE_REGEX: /\{\{.*?\}\}/,
29
30
  }));
30
31
 
31
32
  // Convert messages object to format expected by IntlProvider
@@ -238,6 +239,53 @@ describe('WhatsAppPreviewContent', () => {
238
239
  expect(image.getAttribute('src')).toBe('https://image.url');
239
240
  });
240
241
 
242
+ it('should render placeholder when whatsappImageSrc is a template variable', () => {
243
+ const props = {
244
+ ...defaultProps,
245
+ content: {
246
+ templateMsg: 'Message',
247
+ whatsappImageSrc: '{{imageUrl}}',
248
+ },
249
+ };
250
+
251
+ const { container } = render(
252
+ <TestWrapper>
253
+ <ComponentToRender {...props} />
254
+ </TestWrapper>
255
+ );
256
+
257
+ expect(container.querySelector('.whatsapp-image-url-placeholder')).toBeTruthy();
258
+ expect(container.querySelector('.whatsapp-image-url-placeholder-icon')).toBeTruthy();
259
+ expect(container.querySelector('.whatsapp-image-url-placeholder-text').textContent).toBe('{{imageUrl}}');
260
+ expect(container.querySelector('img.whatsapp-image')).toBeFalsy();
261
+ });
262
+
263
+ it('should fall back to empty preview image when image fails to load', () => {
264
+ const props = {
265
+ ...defaultProps,
266
+ content: {
267
+ templateMsg: 'Message',
268
+ whatsappImageSrc: 'https://broken.url/image.jpg',
269
+ },
270
+ };
271
+
272
+ const { container } = render(
273
+ <TestWrapper>
274
+ <ComponentToRender {...props} />
275
+ </TestWrapper>
276
+ );
277
+
278
+ const image = container.querySelector('img.whatsapp-image');
279
+ expect(image).toBeTruthy();
280
+ expect(image.getAttribute('src')).toBe('https://broken.url/image.jpg');
281
+
282
+ // Trigger onError to swap src to fallback
283
+ const errorEvent = new Event('error');
284
+ image.dispatchEvent(errorEvent);
285
+
286
+ expect(image.getAttribute('src')).not.toBe('https://broken.url/image.jpg');
287
+ });
288
+
241
289
  it('should render video preview when whatsappVideoPreviewImg is present', () => {
242
290
  const props = {
243
291
  ...defaultProps,
@@ -816,6 +816,27 @@
816
816
  }
817
817
  }
818
818
 
819
+ .whatsapp-image-url-placeholder {
820
+ display: flex;
821
+ flex-direction: column;
822
+ align-items: center;
823
+ justify-content: center;
824
+ background-color: $CAP_G09;
825
+ border-radius: $CAP_SPACE_04;
826
+ width: 100%;
827
+ min-height: 5rem;
828
+ max-height: 8.786rem;
829
+ margin-bottom: $CAP_SPACE_04;
830
+ .whatsapp-image-url-placeholder-text {
831
+ font-size: 0.786rem;
832
+ color: $CAP_G04;
833
+ margin-top: $CAP_SPACE_04;
834
+ text-align: center;
835
+ word-break: break-all;
836
+ padding: 0 $CAP_SPACE_04;
837
+ }
838
+ }
839
+
819
840
  .msg-container-carousel {
820
841
  display: flex;
821
842
  flex-direction: column;
@@ -48,7 +48,7 @@ import { TEMPLATE, IMAGE_CAROUSEL, IMAGE, STICKER, TEXT, IMAGE_MAP, VIDEO } from
48
48
  import CapFacebookPreview from '../../v2Containers/CapFacebookPreview';
49
49
  import WhatsappStatusContainer from '../WhatsappStatusContainer';
50
50
  import { getWhatsappQuickReply, getWhatsappCarouselButtonView } from '../../v2Containers/Whatsapp/utils';
51
- import { QUICK_REPLY, WHATSAPP_CATEGORIES, PHONE_NUMBER } from '../../v2Containers/Whatsapp/constants';
51
+ import { QUICK_REPLY, WHATSAPP_CATEGORIES, PHONE_NUMBER, TEMPLATE_VARIABLE_REGEX } from '../../v2Containers/Whatsapp/constants';
52
52
  import { RCS_BUTTON_TYPES, LEFT, HORIZONTAL, VERTICAL, RIGHT} from '../../v2Containers/Rcs/constants';
53
53
  import { ANDROID, INAPP_MESSAGE_LAYOUT_TYPES } from '../../v2Containers/InApp/constants';
54
54
  import { CAROUSEL } from '../../v2Containers/MobilePushNew/constants';
@@ -66,6 +66,8 @@ const lineVideoPlaceholder = require('../../assets/rich-video-placeholder.svg');
66
66
  const androidPushMessagePhone = require('./assets/images/Android_With_date_and_time.svg');
67
67
  const iPhonePushMessagePhone = require('./assets/images/iOS_With_date_and_time.svg');
68
68
 
69
+ const { CapLabelInline } = CapLabel;
70
+
69
71
  export class TemplatePreview extends React.Component { // eslint-disable-line react/prefer-stateless-function
70
72
  onPreviewContentClicked = (channel) => {
71
73
  const IOSContent = (this.props.templateDataRaw && this.props.templateDataRaw.versions.base.IOS) ||
@@ -1194,11 +1196,21 @@ export class TemplatePreview extends React.Component { // eslint-disable-line re
1194
1196
  {content?.showUrlPreview
1195
1197
  && renderUrlPreview(content?.metaTagsDetails)}
1196
1198
  {content?.whatsappImageSrc && (
1197
- <CapImage
1198
- src={content.whatsappImageSrc}
1199
- className="whatsapp-image"
1200
- alt={formatMessage(messages.previewGenerated)}
1201
- />
1199
+ TEMPLATE_VARIABLE_REGEX.test(content.whatsappImageSrc) ? (
1200
+ <div className="whatsapp-image-url-placeholder">
1201
+ <CapIcon type="picture" size="s" className="whatsapp-image-url-placeholder-icon" />
1202
+ <CapLabelInline type="label2" className="whatsapp-image-url-placeholder-text">
1203
+ {content.whatsappImageSrc}
1204
+ </CapLabelInline>
1205
+ </div>
1206
+ ) : (
1207
+ <CapImage
1208
+ src={content.whatsappImageSrc}
1209
+ className="whatsapp-image"
1210
+ alt={formatMessage(messages.previewGenerated)}
1211
+ onError={(e) => { e.target.src = whatsappImageEmptyPreview; }}
1212
+ />
1213
+ )
1202
1214
  )}
1203
1215
  {content?.whatsappVideoPreviewImg && (
1204
1216
  <CapTooltip
@@ -43,6 +43,7 @@ exports[`Test Templates container Should render correct preview component for wh
43
43
  <CapImage
44
44
  alt="Preview is being generated"
45
45
  className="whatsapp-image"
46
+ onError={[Function]}
46
47
  src="https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/c9edc114-923b-4ac7-82d0-d6682213.jpg"
47
48
  />
48
49
  You have received {{1}} points
@@ -50,7 +50,7 @@ import { RCS_STATUSES } from '../Rcs/constants';
50
50
  import { CREATIVE } from '../Facebook/constants';
51
51
  import { LOYALTY } from '../App/constants';
52
52
  import {
53
- WHATSAPP_STATUSES, WHATSAPP_MEDIA_TYPES, PHONE_NUMBER, URL,
53
+ WHATSAPP_STATUSES, WHATSAPP_MEDIA_TYPES, PHONE_NUMBER, URL, ADD_IMAGE_URL_PREVIEW_MARKER,
54
54
  } from '../Whatsapp/constants';
55
55
  import { updateImagesInHtml } from '../../utils/cdnTransformation';
56
56
 
@@ -684,6 +684,8 @@ export class Creatives extends React.Component {
684
684
  switch (mediaType) {
685
685
  case (WHATSAPP_MEDIA_TYPES.IMAGE):
686
686
  mediaParams.imageUrl = url;
687
+ // Detect isAddImageUrl from previewUrl marker (previewUrl is unused for IMAGE type)
688
+ mediaParams.isAddImageUrl = previewUrl === ADD_IMAGE_URL_PREVIEW_MARKER;
687
689
  break;
688
690
  case (WHATSAPP_MEDIA_TYPES.VIDEO):
689
691
  mediaParams.videoUrl = url;
@@ -1142,6 +1144,7 @@ export class Creatives extends React.Component {
1142
1144
  headerTemplate = '',
1143
1145
  } = {},
1144
1146
  isPreviewUrl = false,
1147
+ isAddImageUrl = false,
1145
1148
  carouselData = [],
1146
1149
  } = cloneDeep(versions.base.content.whatsapp);
1147
1150
 
@@ -1178,6 +1181,11 @@ export class Creatives extends React.Component {
1178
1181
  switch (mediaType) {
1179
1182
  case (WHATSAPP_MEDIA_TYPES.IMAGE):
1180
1183
  whatsappMedia.url = imageUrl;
1184
+ // previewUrl is unused for IMAGE type — reuse it to persist isAddImageUrl flag
1185
+ // without adding any new field that the backend would reject
1186
+ if (isAddImageUrl) {
1187
+ whatsappMedia.previewUrl = ADD_IMAGE_URL_PREVIEW_MARKER;
1188
+ }
1181
1189
  break;
1182
1190
  case (WHATSAPP_MEDIA_TYPES.VIDEO):
1183
1191
  whatsappMedia.url = videoUrl;
@@ -319,6 +319,14 @@ export const WHATSAPP_MEDIA_TYPES = {
319
319
  DOCUMENT: 'DOCUMENT',
320
320
  CAROUSEL: 'CAROUSEL',
321
321
  };
322
+
323
+ export const WHATSAPP_IMAGE_SOURCE = {
324
+ UPLOAD: 'UPLOAD_IMAGE',
325
+ URL: 'ADD_IMAGE_URL',
326
+ };
327
+
328
+ export const ADD_IMAGE_URL_PREVIEW_MARKER = '__add_image_url__';
329
+ export const TEMPLATE_VARIABLE_REGEX = /\{\{.*?\}\}/;
322
330
  export const NONE = 'NONE';
323
331
  export const CTA = 'CTA';
324
332
  export const QUICK_REPLY = 'QUICK_REPLY';
@@ -104,7 +104,8 @@ import {
104
104
  VIDEO,
105
105
  URL,
106
106
  REQUEST,
107
- HOST_KARIX
107
+ HOST_KARIX,
108
+ WHATSAPP_IMAGE_SOURCE,
108
109
  } from './constants';
109
110
  import { transformAssetData, transformToVendorFormat, VENDOR_TYPES, resolveCarouselVideoUpdateFields } from '../../utils/vendorDataTransformers';
110
111
  import { validateCarouselCards } from '../../utils/commonUtils';
@@ -252,12 +253,15 @@ export const Whatsapp = (props) => {
252
253
  const [headerTextAreaId, setHeaderTextAreaId] = useState('');
253
254
  const [isHeaderTagValidationError, updateIsHeaderTagValidationError] =
254
255
  useState(false);
256
+ const [imageURLCursorPosition, setImageURLCursorPosition] = useState(0);
255
257
  const [showUrlPreview, setShowUrlPreview] = useState(false);
256
258
  const [previewUrl, setPreviewUrl] = useState('');
257
259
  const [carouselMediaType, setCarouselMediaType] = useState('image');
258
260
  const [carouselData, setCarouselData] = useState(CAROUSEL_INITIAL_DATA);
259
261
  const [activeIndex, setActiveIndex] = useState(defaultActiveIndex);
260
262
  const [carouselValidateTag, setCarouselValidateTag] = useState(false);
263
+ const [mediaTypeSelection, setMediaTypeSelection] = useState(WHATSAPP_IMAGE_SOURCE.UPLOAD);
264
+ const [imageURL, setImageURL] = useState('');
261
265
  // TestAndPreviewSlidebox state
262
266
  const [showTestAndPreviewSlidebox, setShowTestAndPreviewSlidebox] = useState(false);
263
267
  const [isTestAndPreviewMode, setIsTestAndPreviewMode] = useState(false);
@@ -364,6 +368,7 @@ export const Whatsapp = (props) => {
364
368
  whatsappMedia: { header = '', footer = '', headerVarMapped = [] } = {},
365
369
  isPreviewUrl = false,
366
370
  carouselData : editCarouselData = [],
371
+ isAddImageUrl = false,
367
372
  } = editContent;
368
373
  setTemplateCategory(category);
369
374
  setTemplateStatus(status);
@@ -378,6 +383,14 @@ export const Whatsapp = (props) => {
378
383
  });
379
384
  setWhatsappDocSource(documentUrl);
380
385
  setWhatsappDocParams(whatsappDocParams);
386
+ if (mediaType === WHATSAPP_MEDIA_TYPES.IMAGE) {
387
+ if (isAddImageUrl) {
388
+ setMediaTypeSelection(WHATSAPP_IMAGE_SOURCE.URL);
389
+ setImageURL(imageUrl);
390
+ } else {
391
+ setMediaTypeSelection(WHATSAPP_IMAGE_SOURCE.UPLOAD);
392
+ }
393
+ }
381
394
  if (host === HOST_HAPTIC) {
382
395
  updateAssetList(transformToVendorFormat({
383
396
  ...assetList,
@@ -800,6 +813,15 @@ export const Whatsapp = (props) => {
800
813
  });
801
814
  }
802
815
 
816
+ const onImageURLTagSelect = (data) => {
817
+ const currentURL = imageURL || '';
818
+ const tag = `{{${data}}}`;
819
+ const newURL = currentURL.slice(0, imageURLCursorPosition) + tag + currentURL.slice(imageURLCursorPosition);
820
+ setImageURL(newURL);
821
+ setWhatsappImageSrc(newURL);
822
+ setImageURLCursorPosition(imageURLCursorPosition + tag.length);
823
+ };
824
+
803
825
  //setting the id of currently selected text area, is used onTagSelect
804
826
  const setTextAreaId = ({ target: { id } }, type, carouselIndex) => {
805
827
  if (type === HEADER_TEXT) {
@@ -1151,6 +1173,9 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
1151
1173
  );
1152
1174
  } else {
1153
1175
  setWhatsappImageSrc(filePath);
1176
+ if (mediaTypeSelection !== WHATSAPP_IMAGE_SOURCE.URL) {
1177
+ setMediaTypeSelection(WHATSAPP_IMAGE_SOURCE.UPLOAD);
1178
+ }
1154
1179
  if (isHaptic) {
1155
1180
  setHapticFileHandle(fileHandle);
1156
1181
  } else {
@@ -1159,7 +1184,7 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
1159
1184
  }
1160
1185
  actions.clearWhatsappAsset(0);
1161
1186
  },
1162
- [whatsappImageSrc, isMediaTypeCarousel, activeIndex, carouselData, isHaptic],
1187
+ [whatsappImageSrc, isMediaTypeCarousel, activeIndex, carouselData, isHaptic, mediaTypeSelection],
1163
1188
  );
1164
1189
 
1165
1190
  const updateOnWhatsappImageReUpload = useCallback(() => {
@@ -1626,8 +1651,10 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
1626
1651
  const { whatsappVideoSrc = '', whatsappVideoPreviewImg = '' } = whatsappVideoSrcAndPreview;
1627
1652
  switch (templateMediaType) {
1628
1653
  case WHATSAPP_MEDIA_TYPES.IMAGE:
1654
+ const isImageUrlMode = mediaTypeSelection === WHATSAPP_IMAGE_SOURCE.URL;
1629
1655
  mediaParams = {
1630
1656
  imageUrl: getCdnUrl({ url: whatsappImageSrc, channelName: WHATSAPP }),
1657
+ ...(isImageUrlMode && { isAddImageUrl: true }),
1631
1658
  };
1632
1659
  break;
1633
1660
  case WHATSAPP_MEDIA_TYPES.VIDEO:
@@ -1646,7 +1673,6 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
1646
1673
  break;
1647
1674
  }
1648
1675
 
1649
- // Add the correct file handle based on host
1650
1676
  if (isHaptic && hapticFileHandle) {
1651
1677
  mediaParams.hapticFileHandle = hapticFileHandle;
1652
1678
  } else if (!isHaptic && karixFileHandle) {
@@ -1758,7 +1784,21 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
1758
1784
  type: WHATSAPP,
1759
1785
  });
1760
1786
  };
1761
- const isMediatypeValid =()=> ((isMediaTypeImage && whatsappImageSrc === "") || (isMediaTypeVideo && whatsappVideoSrcAndPreview?.whatsappVideoSrc === "") || (isMediaTypeDoc && whatsappDocSource === ""));
1787
+ const isMediatypeValid =()=> {
1788
+ if (isMediaTypeImage) {
1789
+ if (mediaTypeSelection === WHATSAPP_IMAGE_SOURCE.URL) {
1790
+ return isEditFlow ? !imageURL?.trim() : !whatsappImageSrc?.trim();
1791
+ }
1792
+ return !whatsappImageSrc?.trim();
1793
+ }
1794
+ if (isMediaTypeVideo) {
1795
+ return !whatsappVideoSrcAndPreview?.whatsappVideoSrc?.trim();
1796
+ }
1797
+ if (isMediaTypeDoc) {
1798
+ return !whatsappDocSource?.trim();
1799
+ }
1800
+ return false;
1801
+ };
1762
1802
 
1763
1803
  const isDisableDone = () => {
1764
1804
  // Snapshot removed
@@ -1835,9 +1875,106 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
1835
1875
  return false;
1836
1876
  };
1837
1877
 
1878
+ const renderImageURLComponent = () => (
1879
+ <>
1880
+ {templateStatus === WHATSAPP_STATUSES.approved && !isAuthenticationTemplate && (
1881
+ <CapRow className="whatsapp-render-heading">
1882
+ <CapHeader
1883
+ title={
1884
+ <CapHeading type="h4">
1885
+ {formatMessage(messages.mediaImage)}
1886
+ </CapHeading>
1887
+ }
1888
+ suffix={
1889
+ <TagList
1890
+ label={formatMessage(globalMessages.addLabels)}
1891
+ onTagSelect={onImageURLTagSelect}
1892
+ location={location}
1893
+ tags={tags || []}
1894
+ onContextChange={handleOnTagsContextChange}
1895
+ injectedTags={injectedTags || {}}
1896
+ selectedOfferDetails={selectedOfferDetails}
1897
+ eventContextTags={eventContextTags}
1898
+ />
1899
+ }
1900
+ />
1901
+ </CapRow>
1902
+ )}
1903
+ <CapRow className="whatsapp-image-url-container">
1904
+ <CapInput
1905
+ id="whatsapp-image-url-input"
1906
+ placeholder={formatMessage(messages.imageUrlInputPlaceholder)}
1907
+ value={imageURL}
1908
+ disabled={isEditFlow && isFullMode}
1909
+ onChange={e => {
1910
+ setImageURL(e.target.value);
1911
+ setWhatsappImageSrc(e.target.value);
1912
+ }}
1913
+ onFocus={(e) => {
1914
+ setImageURLCursorPosition(e.target.selectionStart || e.target.value.length);
1915
+ }}
1916
+ onSelect={(e) => {
1917
+ setImageURLCursorPosition(e.target.selectionStart || e.target.value.length);
1918
+ }}
1919
+ />
1920
+ </CapRow>
1921
+ </>
1922
+ );
1923
+
1924
+ const handleMediaChange = (e) => {
1925
+ if (templateStatus === WHATSAPP_STATUSES.approved || isEditFlow) {
1926
+ return;
1927
+ }
1928
+ setMediaTypeSelection(e.target.value);
1929
+ if (e.target.value === WHATSAPP_IMAGE_SOURCE.UPLOAD) {
1930
+ setImageURL('');
1931
+ } else if (e.target.value === WHATSAPP_IMAGE_SOURCE.URL) {
1932
+ setWhatsappImageSrc('');
1933
+ if (isHaptic) {
1934
+ setHapticFileHandle('');
1935
+ } else {
1936
+ setKarixFileHandle('');
1937
+ }
1938
+ }
1939
+ };
1940
+
1838
1941
  const renderMediaComponent = () => (
1839
1942
  <>
1840
- {isMediaTypeImage && renderImageComponent()}
1943
+ {isMediaTypeImage && (
1944
+ <CapRow className="whatsapp-dynamic-url-selection-container">
1945
+ <CapHeading type="h4" className="whatsapp-dynamic-url-selection-heading">
1946
+ {formatMessage(messages.mediaImage)}
1947
+ </CapHeading>
1948
+ <CapRadioGroup
1949
+ options={[
1950
+ {
1951
+ value: WHATSAPP_IMAGE_SOURCE.UPLOAD,
1952
+ label: formatMessage(messages.imageSourceUpload),
1953
+ },
1954
+ {
1955
+ value: WHATSAPP_IMAGE_SOURCE.URL,
1956
+ label: (
1957
+ <CapLabel.CapLabelInline type="label2">
1958
+ {formatMessage(messages.imageSourceUrl)}{' '}
1959
+ <CapTooltip
1960
+ placement="top"
1961
+ title={formatMessage(messages.imageSourceUrlTooltip)}
1962
+ >
1963
+ <CapIcon type="info-circle" size="s" style={{ cursor: 'pointer' }} />
1964
+ </CapTooltip>
1965
+ </CapLabel.CapLabelInline>
1966
+ ),
1967
+ },
1968
+ ]}
1969
+ value={mediaTypeSelection}
1970
+ onChange={handleMediaChange}
1971
+ className="whatsapp-media-radio"
1972
+ disabled={templateStatus === WHATSAPP_STATUSES.approved || isEditFlow}
1973
+ />
1974
+ </CapRow>
1975
+ )}
1976
+ {isMediaTypeImage && (mediaTypeSelection === WHATSAPP_IMAGE_SOURCE.UPLOAD || !isEditFlow) && renderImageComponent()}
1977
+ {isMediaTypeImage && mediaTypeSelection === WHATSAPP_IMAGE_SOURCE.URL && isEditFlow && renderImageURLComponent()}
1841
1978
  {isMediaTypeVideo && renderVideoComonent()}
1842
1979
  {isMediaTypeDoc && renderDocumentComponent()}
1843
1980
  </>
@@ -9,6 +9,14 @@
9
9
  margin-top: $CAP_SPACE_16;
10
10
  }
11
11
 
12
+ .whatsapp-dynamic-url-selection-container {
13
+ margin-bottom: $CAP_SPACE_08;
14
+ margin-top: $CAP_SPACE_32;
15
+ .whatsapp-dynamic-url-selection-heading {
16
+ margin-bottom: $CAP_SPACE_08;
17
+ }
18
+ }
19
+
12
20
  .whatsapp-render-heading {
13
21
  margin-top: $CAP_SPACE_16;
14
22
  margin-bottom: $CAP_SPACE_06;
@@ -138,6 +138,22 @@ export default defineMessages({
138
138
  id: `${prefix}.mediaCarousel`,
139
139
  defaultMessage: 'Carousel',
140
140
  },
141
+ imageSourceUpload: {
142
+ id: `${prefix}.imageSourceUpload`,
143
+ defaultMessage: 'Upload image',
144
+ },
145
+ imageSourceUrl: {
146
+ id: `${prefix}.imageSourceUrl`,
147
+ defaultMessage: 'Dynamic image',
148
+ },
149
+ imageSourceUrlTooltip: {
150
+ id: `${prefix}.imageSourceUrlTooltip`,
151
+ defaultMessage: 'Post template approval, the image placeholder is replaceable with image URL',
152
+ },
153
+ imageUrlInputPlaceholder: {
154
+ id: `${prefix}.imageUrlInputPlaceholder`,
155
+ defaultMessage: 'Enter image URL',
156
+ },
141
157
  disabledFeatureTooltip: {
142
158
  id: `${prefix}.disabledFeatureTooltip`,
143
159
  defaultMessage: 'Not yet enabled. Coming soon!',