@capillarytech/creatives-library 8.0.345-alpha.13 → 8.0.345-alpha.15
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/constants/unified.js +29 -0
- package/package.json +1 -1
- package/services/api.js +0 -20
- package/services/tests/api.test.js +13 -59
- package/utils/commonUtils.js +19 -1
- package/utils/rcsPayloadUtils.js +92 -0
- package/utils/templateVarUtils.js +201 -0
- package/utils/tests/templateVarUtils.test.js +204 -0
- package/v2Components/CapActionButton/constants.js +7 -0
- package/v2Components/CapActionButton/index.js +167 -109
- package/v2Components/CapActionButton/index.scss +157 -6
- package/v2Components/CapActionButton/messages.js +19 -3
- package/v2Components/CapActionButton/tests/index.test.js +41 -17
- package/v2Components/CapCustomSkeleton/index.js +1 -1
- package/v2Components/CapCustomSkeleton/tests/__snapshots__/index.test.js.snap +12 -12
- package/v2Components/CapTagList/index.js +10 -0
- package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
- package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
- package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +207 -21
- package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
- package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
- package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
- package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
- package/v2Components/CommonTestAndPreview/SendTestMessage.js +10 -5
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +160 -15
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js.rej +18 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +341 -76
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
- package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +11 -0
- package/v2Components/CommonTestAndPreview/constants.js +38 -2
- package/v2Components/CommonTestAndPreview/index.js +676 -186
- package/v2Components/CommonTestAndPreview/messages.js +49 -3
- package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
- package/v2Components/CommonTestAndPreview/sagas.js +15 -6
- package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +308 -284
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +231 -65
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
- package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
- package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +34 -13
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
- package/v2Components/CommonTestAndPreview/tests/index.test.js +132 -4
- package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
- package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
- package/v2Components/FormBuilder/index.js +8 -10
- package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
- package/v2Components/SmsFallback/constants.js +73 -0
- package/v2Components/SmsFallback/index.js +955 -0
- package/v2Components/SmsFallback/index.scss +265 -0
- package/v2Components/SmsFallback/messages.js +78 -0
- package/v2Components/SmsFallback/smsFallbackUtils.js +118 -0
- package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
- package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
- package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
- package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
- package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +277 -0
- package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
- package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
- package/v2Components/TemplatePreview/_templatePreview.scss +33 -23
- package/v2Components/TemplatePreview/constants.js +2 -0
- package/v2Components/TemplatePreview/index.js +143 -28
- package/v2Components/TemplatePreview/tests/index.test.js +142 -0
- package/v2Components/TestAndPreviewSlidebox/index.js +13 -1
- package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
- package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
- package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
- package/v2Components/VarSegmentMessageEditor/index.js +125 -0
- package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
- package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +36 -4
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +11 -4
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
- package/v2Containers/CreativesContainer/constants.js +9 -0
- package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
- package/v2Containers/CreativesContainer/index.js +300 -108
- package/v2Containers/CreativesContainer/index.scss +51 -1
- package/v2Containers/CreativesContainer/messages.js +0 -4
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +78 -34
- package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +79 -16
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +357 -98
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -18
- package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
- package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
- package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
- package/v2Containers/Rcs/constants.js +119 -8
- package/v2Containers/Rcs/index.js +2379 -807
- package/v2Containers/Rcs/index.js.rej +1336 -0
- package/v2Containers/Rcs/index.scss +276 -6
- package/v2Containers/Rcs/index.scss.rej +74 -0
- package/v2Containers/Rcs/messages.js +38 -3
- package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +225 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +98018 -70073
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap.rej +128 -0
- package/v2Containers/Rcs/tests/index.test.js +152 -121
- package/v2Containers/Rcs/tests/mockData.js +38 -0
- package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +318 -0
- package/v2Containers/Rcs/tests/utils.test.js +646 -30
- package/v2Containers/Rcs/utils.js +478 -11
- package/v2Containers/Sms/Create/index.js +100 -40
- package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
- package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
- package/v2Containers/SmsTrai/Create/index.js +9 -4
- package/v2Containers/SmsTrai/Edit/constants.js +2 -0
- package/v2Containers/SmsTrai/Edit/index.js +636 -130
- package/v2Containers/SmsTrai/Edit/index.scss +121 -0
- package/v2Containers/SmsTrai/Edit/messages.js +14 -4
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4328 -2375
- package/v2Containers/SmsWrapper/index.js +37 -8
- package/v2Containers/TagList/index.js +6 -0
- package/v2Containers/Templates/ChannelTypeIllustration.js +6 -23
- package/v2Containers/Templates/TemplatesActionBar.js +101 -0
- package/v2Containers/Templates/_templates.scss +181 -126
- package/v2Containers/Templates/actions.js +11 -36
- package/v2Containers/Templates/constants.js +2 -23
- package/v2Containers/Templates/index.js +142 -333
- package/v2Containers/Templates/messages.js +0 -68
- package/v2Containers/Templates/reducer.js +0 -68
- package/v2Containers/Templates/sagas.js +55 -98
- package/v2Containers/Templates/selectors.js +0 -12
- package/v2Containers/Templates/tests/ChannelTypeIllustration.test.js +0 -12
- package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1042 -1256
- package/v2Containers/Templates/tests/index.test.js +0 -6
- package/v2Containers/Templates/tests/reducer.test.js +0 -178
- package/v2Containers/Templates/tests/sagas.test.js +200 -436
- package/v2Containers/Templates/tests/selector.test.js +0 -32
- package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
- package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
- package/v2Containers/TemplatesV2/index.js +86 -23
- package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
- package/v2Containers/Whatsapp/index.js +3 -20
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
- package/v2Containers/Assets/images/archive_Empty_Illustration.svg +0 -9
|
@@ -50,7 +50,9 @@ import {
|
|
|
50
50
|
CapStatus,
|
|
51
51
|
CapColoredTag,
|
|
52
52
|
CapSpin,
|
|
53
|
-
|
|
53
|
+
CapCard,
|
|
54
|
+
CapColumn,
|
|
55
|
+
CapCarousel
|
|
54
56
|
} from "@capillarytech/cap-ui-library";
|
|
55
57
|
import { makeSelectTemplates, makeSelectTemplatesResponse } from './selectors';
|
|
56
58
|
import { makeSelectCreate as makeSelectCreateSms } from '../Sms/Create/selectors';
|
|
@@ -114,15 +116,23 @@ import {
|
|
|
114
116
|
STATUS as WHATSAPP_STATUS,
|
|
115
117
|
WHATSAPP_STATUSES,
|
|
116
118
|
HOST_GUPSHUP,
|
|
119
|
+
HOST_HAPTIC,
|
|
117
120
|
CATEGORY_OPTIONS_MAP,
|
|
121
|
+
HOST_TWILIO,
|
|
122
|
+
TWILIO_CATEGORY_OPTIONS,
|
|
123
|
+
KARIX_GUPSHUP_CATEGORY_OPTIONS,
|
|
124
|
+
ICS_CATEGORY_OPTIONS,
|
|
125
|
+
HAPTIC_CATEGORY_OPTIONS,
|
|
126
|
+
HOST_ICS,
|
|
118
127
|
IMAGE,
|
|
119
128
|
VIDEO,
|
|
129
|
+
GIF,
|
|
120
130
|
} from '../Whatsapp/constants';
|
|
121
|
-
import { INAPP_LAYOUT_DETAILS, INAPP_MESSAGE_LAYOUT_TYPES } from '../InApp/constants';
|
|
131
|
+
import { INAPP_LAYOUT_DETAILS, INAPP_MESSAGE_LAYOUT_TYPES, INAPP_MEDIA_TYPES, BIG_HTML, ANDROID, IOS } from '../InApp/constants';
|
|
122
132
|
import { ZALO_STATUS_OPTIONS, ZALO_STATUSES } from '../Zalo/constants';
|
|
123
133
|
import { getWhatsappContent, getWhatsappStatus, getWhatsappCategory, getWhatsappCta, getWhatsappQuickReply, getWhatsappAutoFill, getWhatsappCarouselButtonView } from '../Whatsapp/utils';
|
|
124
134
|
import { getRCSContent } from '../Rcs/utils';
|
|
125
|
-
import {RCS_STATUSES} from '../Rcs/constants';
|
|
135
|
+
import { RCS_STATUSES, HOST_INFOBIP } from '../Rcs/constants';
|
|
126
136
|
import zaloMessages from '../Zalo/messages';
|
|
127
137
|
import rcsMessages from '../Rcs/messages';
|
|
128
138
|
import inAppMessages from '../InApp/messages';
|
|
@@ -135,7 +145,7 @@ import {CREATIVE} from '../Facebook/constants';
|
|
|
135
145
|
import videoPlay from '../../assets/videoPlay.svg';
|
|
136
146
|
import whatsappImageEmptyPreview from '../../v2Components/TemplatePreview/assets/images/empty_image_preview.svg';
|
|
137
147
|
import whatsappVideoEmptyPreview from '../../v2Components/TemplatePreview/assets/images/empty_video_preview.svg';
|
|
138
|
-
import { CAP_SPACE_16
|
|
148
|
+
import { CAP_SPACE_16 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
139
149
|
import { GA } from '@capillarytech/cap-ui-utils';
|
|
140
150
|
import { MAPP_SDK } from '../InApp/constants';
|
|
141
151
|
import injectReducer from '../../utils/injectReducer';
|
|
@@ -144,6 +154,7 @@ import { compose } from 'redux';
|
|
|
144
154
|
import { v2TemplateSaga } from './sagas';
|
|
145
155
|
import injectSaga from '../../utils/injectSaga';
|
|
146
156
|
import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
|
|
157
|
+
import { Rcs } from '../Rcs';
|
|
147
158
|
import { makeSelectRcs } from '../Rcs/selectors';
|
|
148
159
|
import { getRcsStatusType } from '../Rcs/utils';
|
|
149
160
|
import { makeSelectWebPush } from '../WebPush/selectors';
|
|
@@ -426,9 +437,6 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
426
437
|
channel = '';
|
|
427
438
|
}
|
|
428
439
|
this.setState({ channel, activeMode });
|
|
429
|
-
// Always reset archive mode and selection when mounting a new channel
|
|
430
|
-
this.props.actions.setArchivedMode(false);
|
|
431
|
-
this.props.actions.clearTemplateSelection();
|
|
432
440
|
// Clear templates when entering account selection mode to prevent showing old channel templates
|
|
433
441
|
if (activeMode === ACCOUNT_SELECTION_MODE) {
|
|
434
442
|
this.props.actions.resetTemplate();
|
|
@@ -460,7 +468,13 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
460
468
|
if (this.props.location.query.type === 'embedded') {
|
|
461
469
|
this.props.actions.resetAccount();
|
|
462
470
|
}
|
|
463
|
-
|
|
471
|
+
// When using local templates (e.g. SMS fallback selector), do not fetch from API or we overwrite global store and break background RCS list
|
|
472
|
+
const useLocalTemplates = get(
|
|
473
|
+
this.props,
|
|
474
|
+
'localTemplatesConfig.useLocalTemplates',
|
|
475
|
+
get(this.props, 'useLocalTemplates', false),
|
|
476
|
+
);
|
|
477
|
+
if (!useLocalTemplates && ['line', VIBER_CHANNEL, FACEBOOK_CHANNEL, 'sms', 'email', 'ebill'].includes((this.state.channel || '').toLowerCase())) {
|
|
464
478
|
const queryParams = {
|
|
465
479
|
// name: this.state.searchText,
|
|
466
480
|
// sortBy: this.state.sortBy,
|
|
@@ -973,8 +987,16 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
973
987
|
|
|
974
988
|
componentWillUnmount() {
|
|
975
989
|
window.removeEventListener("message", this.handleFrameTasks);
|
|
976
|
-
|
|
977
|
-
|
|
990
|
+
// When using local templates (e.g. SMS fallback selector), do not clear global store or background RCS list is wiped
|
|
991
|
+
const useLocalTemplates = get(
|
|
992
|
+
this.props,
|
|
993
|
+
'localTemplatesConfig.useLocalTemplates',
|
|
994
|
+
get(this.props, 'useLocalTemplates', false),
|
|
995
|
+
);
|
|
996
|
+
if (!useLocalTemplates) {
|
|
997
|
+
this.props.actions.resetTemplateStoreData();
|
|
998
|
+
this.props.globalActions.clearMetaEntities();
|
|
999
|
+
}
|
|
978
1000
|
// Clear any pending timeouts to prevent memory leaks
|
|
979
1001
|
if (this._clearEditTimeout) {
|
|
980
1002
|
clearTimeout(this._clearEditTimeout);
|
|
@@ -1587,11 +1609,6 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1587
1609
|
let queryParams = params || {};
|
|
1588
1610
|
let page = this.state.page;
|
|
1589
1611
|
const { activeMode } = this.state;
|
|
1590
|
-
// Archive filter — use explicit param if provided (props may not have updated yet due to async dispatch)
|
|
1591
|
-
if (!queryParams.archiveStatus) {
|
|
1592
|
-
const archiveFilter = get(this.props, 'Templates.archiveFilter', 'active');
|
|
1593
|
-
queryParams.archiveStatus = archiveFilter;
|
|
1594
|
-
}
|
|
1595
1612
|
if (activeMode === ACCOUNT_SELECTION_MODE) {
|
|
1596
1613
|
this.setTemplatesMode();
|
|
1597
1614
|
}
|
|
@@ -1764,12 +1781,20 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1764
1781
|
}
|
|
1765
1782
|
|
|
1766
1783
|
filterRcsTemplates = (templates) => {
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1784
|
+
const selectedRcsAccountName = this.props?.Templates?.selectedRcsAccount?.name || '';
|
|
1785
|
+
const hostName = this.state?.hostName;
|
|
1786
|
+
let nextTemplates = templates || [];
|
|
1787
|
+
if (selectedRcsAccountName) {
|
|
1788
|
+
nextTemplates = nextTemplates.filter(
|
|
1789
|
+
(t) => get(t, 'versions.base.content.RCS.rcsContent.accountName', '') === selectedRcsAccountName
|
|
1790
|
+
);
|
|
1771
1791
|
}
|
|
1772
|
-
|
|
1792
|
+
if (!this.props.isFullMode && hostName !== HOST_INFOBIP) {
|
|
1793
|
+
return nextTemplates.filter(
|
|
1794
|
+
(t) => get(t, 'versions.base.content.RCS.rcsContent.cardContent[0].Status', 'unavailable') === RCS_STATUSES.approved
|
|
1795
|
+
);
|
|
1796
|
+
}
|
|
1797
|
+
return nextTemplates;
|
|
1773
1798
|
}
|
|
1774
1799
|
|
|
1775
1800
|
filterZaloTemplates = (templates) => {
|
|
@@ -1858,9 +1883,6 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1858
1883
|
const currentChannel = channel.toUpperCase();
|
|
1859
1884
|
const {channel: stateChannel} = this.state;
|
|
1860
1885
|
const channelLowerCase = stateChannel.toLowerCase();
|
|
1861
|
-
const _selectedIds = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
1862
|
-
const _selectedIdsArray = _selectedIds && typeof _selectedIds.toJS === 'function' ? _selectedIds.toJS() : (Array.isArray(_selectedIds) ? _selectedIds : []);
|
|
1863
|
-
const hasSelection = this.props.isFullMode && _selectedIdsArray.length > 0;
|
|
1864
1886
|
let filteredTemplates = templates;
|
|
1865
1887
|
let isTraiDltFeature = false;
|
|
1866
1888
|
switch (currentChannel) {
|
|
@@ -1900,26 +1922,10 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1900
1922
|
const iosBodyType = get(template, 'versions.base.content.IOS.bodyType');
|
|
1901
1923
|
const inappBodyType = androidBodyType || iosBodyType;
|
|
1902
1924
|
const isZaloPreviewLoading = previewTemplateId === template?._id;
|
|
1903
|
-
const selectedIdsForCard = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
1904
|
-
const selectedIdsArrayForCard = selectedIdsForCard.toJS ? selectedIdsForCard.toJS() : selectedIdsForCard;
|
|
1905
|
-
// Archive eligibility per template: Zalo never; WhatsApp/RCS not when pending/awaiting
|
|
1906
|
-
const cardWhatsappStatus = get(template, `versions.base.content.${WHATSAPP_LOWERCASE}.status`, '');
|
|
1907
|
-
const cardRcsStatus = get(template, 'versions.base.content.RCS.rcsContent.cardContent[0].Status', '');
|
|
1908
|
-
const isCardArchiveEligible = currentChannel !== ZALO &&
|
|
1909
|
-
!(currentChannel === WHATSAPP && [WHATSAPP_STATUSES.awaitingApproval, WHATSAPP_STATUSES.pending, WHATSAPP_STATUSES.unsubmitted].includes(cardWhatsappStatus)) &&
|
|
1910
|
-
!(currentChannel === RCS && [RCS_STATUSES.awaitingApproval, RCS_STATUSES.pending].includes(cardRcsStatus));
|
|
1911
1925
|
const templateData = {
|
|
1912
1926
|
key: `${currentChannel}-card-${template?.name}`,
|
|
1913
1927
|
title: (
|
|
1914
|
-
<span title={template?.name}
|
|
1915
|
-
{this.props.isFullMode && this.props.location.query.type !== 'embedded' && isCardArchiveEligible && (
|
|
1916
|
-
<CapCheckbox
|
|
1917
|
-
checked={selectedIdsArrayForCard.includes(template._id)}
|
|
1918
|
-
onChange={() => this.props.actions.toggleTemplateSelection(template._id)}
|
|
1919
|
-
onClick={(e) => e.stopPropagation()}
|
|
1920
|
-
style={{ marginRight: CAP_SPACE_08, flexShrink: 0 }}
|
|
1921
|
-
/>
|
|
1922
|
-
)}
|
|
1928
|
+
<span title={template?.name}>
|
|
1923
1929
|
{template?.name}
|
|
1924
1930
|
{currentChannel === INAPP && (
|
|
1925
1931
|
<CapRow>
|
|
@@ -1963,7 +1969,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1963
1969
|
style={{ marginRight: "16px" }}
|
|
1964
1970
|
type="eye"
|
|
1965
1971
|
onClick={() => {
|
|
1966
|
-
if (!this.props.isFullMode || this.props.isDltFromRcs) {
|
|
1972
|
+
if (!this.props.isFullMode || this.props.isDltFromRcs || this.props.isSmsFallbackFromRcs) {
|
|
1967
1973
|
if (!get(template, "versions.base.content.zalo.previewUrl", "")) {
|
|
1968
1974
|
this.setState({ zaloPreviewItemId: template?._id });
|
|
1969
1975
|
}
|
|
@@ -2040,7 +2046,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2040
2046
|
{![WECHAT, WHATSAPP, ZALO].includes(
|
|
2041
2047
|
this.state.channel.toUpperCase()
|
|
2042
2048
|
) &&
|
|
2043
|
-
!isTraiDltFeature &&
|
|
2049
|
+
!isTraiDltFeature && (
|
|
2044
2050
|
<CapMenu.Item
|
|
2045
2051
|
className={`duplicate-${channelLowerCase}`}
|
|
2046
2052
|
onClick={() => this.duplicateTemplate(template)}
|
|
@@ -2048,42 +2054,6 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2048
2054
|
<FormattedMessage {...messages.duplicateButton} />
|
|
2049
2055
|
</CapMenu.Item>
|
|
2050
2056
|
)}
|
|
2051
|
-
{/* Archive/Unarchive menu item (full mode only, not for Zalo, not for WhatsApp/RCS awaiting/pending) */}
|
|
2052
|
-
{(() => {
|
|
2053
|
-
const channelUp = this.state.channel.toUpperCase();
|
|
2054
|
-
const isArchiveEligible = channelUp !== ZALO &&
|
|
2055
|
-
!(channelUp === WHATSAPP && [WHATSAPP_STATUSES.awaitingApproval, WHATSAPP_STATUSES.pending, WHATSAPP_STATUSES.unsubmitted].includes(status)) &&
|
|
2056
|
-
!(channelUp === RCS && [RCS_STATUSES.awaitingApproval, RCS_STATUSES.pending].includes(rcsStatus));
|
|
2057
|
-
if (!isArchiveEligible) return null;
|
|
2058
|
-
return !template.isArchived ? (
|
|
2059
|
-
<CapMenu.Item
|
|
2060
|
-
className={`archive-${channelLowerCase}`}
|
|
2061
|
-
onClick={() => {
|
|
2062
|
-
this.showArchiveConfirm({
|
|
2063
|
-
title: this.props.intl.formatMessage(messages.archiveTemplates),
|
|
2064
|
-
onConfirm: () => this.props.actions.archiveTemplate(this.state.channel, template._id, template.name),
|
|
2065
|
-
count: 1,
|
|
2066
|
-
});
|
|
2067
|
-
}}
|
|
2068
|
-
>
|
|
2069
|
-
<FormattedMessage {...messages.archiveButton} />
|
|
2070
|
-
</CapMenu.Item>
|
|
2071
|
-
) : (
|
|
2072
|
-
<CapMenu.Item
|
|
2073
|
-
className={`unarchive-${channelLowerCase}`}
|
|
2074
|
-
onClick={() => {
|
|
2075
|
-
this.showArchiveConfirm({
|
|
2076
|
-
title: this.props.intl.formatMessage(messages.unarchiveTemplates),
|
|
2077
|
-
onConfirm: () => this.props.actions.unarchiveTemplate(this.state.channel, template._id, template.name),
|
|
2078
|
-
count: 1,
|
|
2079
|
-
isUnarchive: true,
|
|
2080
|
-
});
|
|
2081
|
-
}}
|
|
2082
|
-
>
|
|
2083
|
-
<FormattedMessage {...messages.unarchiveButton} />
|
|
2084
|
-
</CapMenu.Item>
|
|
2085
|
-
);
|
|
2086
|
-
})()}
|
|
2087
2057
|
{/* Delete/Unmap menu item */}
|
|
2088
2058
|
{(!(
|
|
2089
2059
|
this.state.channel.toUpperCase() === WHATSAPP &&
|
|
@@ -2364,15 +2334,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2364
2334
|
case WHATSAPP: {
|
|
2365
2335
|
const { whatsappImageSrc = '', templateMsg, docPreview, whatsappVideoPreviewImg = '', templateHeaderPreview, templateFooterPreview, carouselData = [] } = getWhatsappContent(template);
|
|
2366
2336
|
templateData.title = (
|
|
2367
|
-
<CapRow
|
|
2368
|
-
{this.props.isFullMode && this.props.location.query.type !== 'embedded' && isCardArchiveEligible && (
|
|
2369
|
-
<CapCheckbox
|
|
2370
|
-
checked={selectedIdsArrayForCard.includes(template._id)}
|
|
2371
|
-
onChange={() => this.props.actions.toggleTemplateSelection(template._id)}
|
|
2372
|
-
onClick={(e) => e.stopPropagation()}
|
|
2373
|
-
style={{ marginRight: CAP_SPACE_08, flexShrink: 0 }}
|
|
2374
|
-
/>
|
|
2375
|
-
)}
|
|
2337
|
+
<CapRow>
|
|
2376
2338
|
<CapLabel className="whatsapp-rcs-template-name">{template?.name}</CapLabel>
|
|
2377
2339
|
<WhatsappStatusContainer template={template} />
|
|
2378
2340
|
</CapRow>
|
|
@@ -2465,23 +2427,16 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2465
2427
|
const name = get(template, "name", "");
|
|
2466
2428
|
const statusDisplay=getRcsStatusType(status);
|
|
2467
2429
|
templateData.title = (
|
|
2468
|
-
<CapRow
|
|
2469
|
-
{this.props.isFullMode && this.props.location.query.type !== 'embedded' && isCardArchiveEligible && (
|
|
2470
|
-
<CapCheckbox
|
|
2471
|
-
checked={selectedIdsArrayForCard.includes(template._id)}
|
|
2472
|
-
onChange={() => this.props.actions.toggleTemplateSelection(template._id)}
|
|
2473
|
-
onClick={(e) => e.stopPropagation()}
|
|
2474
|
-
style={{ marginRight: CAP_SPACE_08, flexShrink: 0 }}
|
|
2475
|
-
/>
|
|
2476
|
-
)}
|
|
2430
|
+
<CapRow>
|
|
2477
2431
|
<CapLabel className="whatsapp-rcs-template-name">{name}</CapLabel>
|
|
2478
|
-
<CapRow type="flex" align="middle" className="rcs-status-container zalo-status-color">
|
|
2432
|
+
{this.state.hostName !== HOST_INFOBIP && <CapRow type="flex" align="middle" className="rcs-status-container zalo-status-color">
|
|
2479
2433
|
<CapStatus
|
|
2480
2434
|
type={statusDisplay}
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2435
|
+
text={statusDisplay && this.props.intl.formatMessage(rcsMessages?.[`${statusDisplay}_STATUS`])}
|
|
2436
|
+
labelType="label3"
|
|
2437
|
+
/>
|
|
2438
|
+
</CapRow>
|
|
2439
|
+
}
|
|
2485
2440
|
</CapRow>
|
|
2486
2441
|
);
|
|
2487
2442
|
|
|
@@ -2597,7 +2552,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2597
2552
|
|
|
2598
2553
|
//no templates available
|
|
2599
2554
|
const showIllustrationForChannel = (forChannel) => {
|
|
2600
|
-
return forChannel === channelLowerCase && isEmpty(templates) && isEmpty(this.state.searchText) && !isLoading
|
|
2555
|
+
return forChannel === channelLowerCase && isEmpty(templates) && isEmpty(this.state.searchText) && !isLoading;
|
|
2601
2556
|
}
|
|
2602
2557
|
//when filters applied not matching templates
|
|
2603
2558
|
const filteredEmptyAndFullModeAs = (fullModeValue) => {
|
|
@@ -2623,49 +2578,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2623
2578
|
|
|
2624
2579
|
const noLoaderAndSearchText = isEmpty(this.state.searchText) && !isLoading;
|
|
2625
2580
|
|
|
2626
|
-
|
|
2627
|
-
const selectedIdsLocal = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
2628
|
-
const selectedIdsArrayLocal = selectedIdsLocal && typeof selectedIdsLocal.toJS === 'function' ? selectedIdsLocal.toJS() : (Array.isArray(selectedIdsLocal) ? selectedIdsLocal : []);
|
|
2629
|
-
const selectedCountLocal = selectedIdsArrayLocal.length;
|
|
2630
|
-
const hasSelectionLocal = this.props.isFullMode && selectedCountLocal > 0;
|
|
2631
|
-
|
|
2632
|
-
return (<div>
|
|
2581
|
+
return (<div>
|
|
2633
2582
|
{[WECHAT, MOBILE_PUSH, WEBPUSH, INAPP, WHATSAPP, ZALO, RCS].includes(currentChannel) && this.showAccountName()}
|
|
2634
|
-
|
|
2635
|
-
<div className="filter-row-content">{filterContent}</div>
|
|
2636
|
-
{hasSelectionLocal && (
|
|
2637
|
-
<CapRow type="flex" align="middle" className="bulk-selection-bar">
|
|
2638
|
-
<CapLabel type="label2">
|
|
2639
|
-
{this.props.intl.formatMessage(messages.templatesSelected, { count: selectedCountLocal })}
|
|
2640
|
-
</CapLabel>
|
|
2641
|
-
<CapButton
|
|
2642
|
-
type="primary"
|
|
2643
|
-
prefix={<CapIcon type="archive" size="l" />}
|
|
2644
|
-
onClick={() => {
|
|
2645
|
-
this.showArchiveConfirm({
|
|
2646
|
-
title: this.props.intl.formatMessage(isArchivedModeLocal ? messages.unarchiveTemplates : messages.archiveTemplates),
|
|
2647
|
-
onConfirm: () => {
|
|
2648
|
-
if (isArchivedModeLocal) {
|
|
2649
|
-
this.props.actions.bulkUnarchiveTemplates(this.state.channel, selectedIdsArrayLocal);
|
|
2650
|
-
} else {
|
|
2651
|
-
this.props.actions.bulkArchiveTemplates(this.state.channel, selectedIdsArrayLocal);
|
|
2652
|
-
}
|
|
2653
|
-
},
|
|
2654
|
-
count: selectedCountLocal,
|
|
2655
|
-
isUnarchive: isArchivedModeLocal,
|
|
2656
|
-
});
|
|
2657
|
-
}}
|
|
2658
|
-
>
|
|
2659
|
-
<span className="archive-btn-label">
|
|
2660
|
-
<FormattedMessage {...(isArchivedModeLocal ? messages.unarchiveButton : messages.archiveButton)} />
|
|
2661
|
-
</span>
|
|
2662
|
-
</CapButton>
|
|
2663
|
-
<CapButton type="secondary" onClick={() => this.props.actions.clearTemplateSelection()}>
|
|
2664
|
-
<FormattedMessage {...messages.archiveConfirmCancel} />
|
|
2665
|
-
</CapButton>
|
|
2666
|
-
</CapRow>
|
|
2667
|
-
)}
|
|
2668
|
-
</CapRow>
|
|
2583
|
+
{filterContent}
|
|
2669
2584
|
{[WHATSAPP, ZALO, INAPP,RCS].includes(currentChannel) && this.selectedFilters()}
|
|
2670
2585
|
{<div>
|
|
2671
2586
|
{!isEmpty(filteredTemplates) || !isEmpty(this.state.searchText) || !isEmpty(this.props.Templates.templateError) ? (
|
|
@@ -2678,7 +2593,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2678
2593
|
fbType={"list"}
|
|
2679
2594
|
/>
|
|
2680
2595
|
</div>)
|
|
2681
|
-
: [SMS_LOWERCASE, EMAIL_LOWERCASE].includes(this.state.channel.toLowerCase()) && !isLoading &&
|
|
2596
|
+
: [SMS_LOWERCASE, EMAIL_LOWERCASE].includes(this.state.channel.toLowerCase()) && !isLoading && this.getSmsEmailIllustration()
|
|
2682
2597
|
}
|
|
2683
2598
|
|
|
2684
2599
|
{(this.state.selectedAccount === '' && isEmpty(this.props.Templates.selectedWeChatAccount)) && ([WECHAT_LOWERCASE, MOBILE_PUSH_LOWERCASE, INAPP_LOWERCASE].includes(this.state.channel.toLowerCase())) &&
|
|
@@ -2702,7 +2617,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2702
2617
|
</div>
|
|
2703
2618
|
)
|
|
2704
2619
|
}
|
|
2705
|
-
{(showWhatsappIllustration || showZaloIllustration) &&
|
|
2620
|
+
{(showWhatsappIllustration || showZaloIllustration) && (
|
|
2706
2621
|
noLoaderAndSearchText &&
|
|
2707
2622
|
<div style={this.isFullMode() ? { height: "calc(100vh - 325px)", overflow: 'auto' } : {}}>
|
|
2708
2623
|
{noWhatsappZaloTemplates && <ChannelTypeIllustration isFullMode={this.props.isFullMode} createTemplate={this.createTemplate} currentChannel={currentChannel} hostName={this.state?.hostName}/>}
|
|
@@ -2743,16 +2658,6 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2743
2658
|
<ChannelTypeIllustration isFullMode={this.props.isFullMode} createTemplate={this.createTemplate} currentChannel={currentChannel} hostName={this.state?.hostName}/>
|
|
2744
2659
|
</div>
|
|
2745
2660
|
}
|
|
2746
|
-
{get(this.props, 'Templates.isArchivedMode', false) && isEmpty(templates) && !isLoading && !getAllTemplatesInProgress && isEmpty(this.state.searchText) && (
|
|
2747
|
-
<div className={this.isFullMode() ? 'illustration-scroll-wrapper' : ''}>
|
|
2748
|
-
<ChannelTypeIllustration
|
|
2749
|
-
isFullMode={this.props.isFullMode}
|
|
2750
|
-
createTemplate={this.createTemplate}
|
|
2751
|
-
currentChannel={currentChannel}
|
|
2752
|
-
isArchivedMode
|
|
2753
|
-
/>
|
|
2754
|
-
</div>
|
|
2755
|
-
)}
|
|
2756
2661
|
{<CapCustomSkeleton loader={isInitialLoading && (isLoading || getAllTemplatesInProgress)} />}
|
|
2757
2662
|
{<CapPageSpinner spinning={!isInitialLoading && (isLoading || getAllTemplatesInProgress)} />}
|
|
2758
2663
|
</div>
|
|
@@ -3055,6 +2960,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
3055
2960
|
let routeParams = {};
|
|
3056
2961
|
const {fbAdManager} = this.props;
|
|
3057
2962
|
const isLibraryMode = this.isEnabledInLibraryModule("callCreateFromProps");
|
|
2963
|
+
|
|
3058
2964
|
if (!isLibraryMode) {
|
|
3059
2965
|
timeTracker.startTimer(CHANNEL_CREATE_TRACK_MAPPING[channel]);
|
|
3060
2966
|
}
|
|
@@ -3396,14 +3302,17 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
3396
3302
|
};
|
|
3397
3303
|
|
|
3398
3304
|
handleEditClick(e, template, modeType, path, options) {
|
|
3399
|
-
if (template && template.isArchived) {
|
|
3400
|
-
CapNotification.error({ message: this.props.intl.formatMessage(messages.cannotEditArchivedTemplate) });
|
|
3401
|
-
return;
|
|
3402
|
-
}
|
|
3403
3305
|
if (modeType && modeType !== undefined) {
|
|
3404
3306
|
this.setState({modeType});
|
|
3405
3307
|
}
|
|
3406
3308
|
const { _id: id } = template;
|
|
3309
|
+
const {
|
|
3310
|
+
localTemplatesConfig,
|
|
3311
|
+
fbAdManager,
|
|
3312
|
+
isDltFromRcs,
|
|
3313
|
+
isSmsFallbackFromRcs,
|
|
3314
|
+
onSelectTemplate,
|
|
3315
|
+
} = this.props;
|
|
3407
3316
|
const type = this.props.location.query.type;
|
|
3408
3317
|
const module = this.props.location.query.module;
|
|
3409
3318
|
const isLanguageSupport = (this.props.location.query.isLanguageSupport) ? this.props.location.query.isLanguageSupport : false;
|
|
@@ -3489,10 +3398,12 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
3489
3398
|
}
|
|
3490
3399
|
if (this.isEnabledInLibraryModule("callSelectFromProps")) {
|
|
3491
3400
|
let data = id;
|
|
3492
|
-
if (
|
|
3401
|
+
if (localTemplatesConfig?.useLocalTemplates) {
|
|
3402
|
+
data = template;
|
|
3403
|
+
} else if (fbAdManager || isDltFromRcs || isSmsFallbackFromRcs) {
|
|
3493
3404
|
data = this.selectTemplate(id);
|
|
3494
3405
|
}
|
|
3495
|
-
|
|
3406
|
+
onSelectTemplate(data, fbAdManager);
|
|
3496
3407
|
} else {
|
|
3497
3408
|
timeTracker.startTimer(CHANNEL_EDIT_TRACK_MAPPING[this.state.channel.toLowerCase()]);
|
|
3498
3409
|
if (this.state.channel.toLowerCase() === 'ebill') {
|
|
@@ -3581,33 +3492,6 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
3581
3492
|
this.setState({showModal: false});
|
|
3582
3493
|
}
|
|
3583
3494
|
|
|
3584
|
-
// Shared helper for archive/unarchive confirm modals:
|
|
3585
|
-
// - no icon, lighter overlay, Confirm button on left (primary), Cancel on right
|
|
3586
|
-
showArchiveConfirm = ({ title, content, onConfirm, count = 1, isUnarchive = false }) => {
|
|
3587
|
-
const { intl } = this.props;
|
|
3588
|
-
const confirmText = intl.formatMessage(messages.archiveConfirmOk);
|
|
3589
|
-
const cancelText = intl.formatMessage(messages.archiveConfirmCancel);
|
|
3590
|
-
// Derive content from count if not explicitly provided
|
|
3591
|
-
const resolvedContent = content || (isUnarchive
|
|
3592
|
-
? intl.formatMessage(count > 1 ? messages.unarchiveTemplateContent : messages.unarchiveTemplateSingleContent)
|
|
3593
|
-
: intl.formatMessage(count > 1 ? messages.archiveTemplateContent : messages.archiveTemplateSingleContent));
|
|
3594
|
-
// AntD v3 footer order is [cancelButton][okButton]. Swap text+handler so
|
|
3595
|
-
// "Confirm" (primary) appears on the left and "Cancel" (default) on the right.
|
|
3596
|
-
CapModal.confirm({
|
|
3597
|
-
title,
|
|
3598
|
-
content: resolvedContent,
|
|
3599
|
-
icon: ' ',
|
|
3600
|
-
className: 'archive-confirm-modal',
|
|
3601
|
-
maskStyle: { backgroundColor: 'rgba(0, 0, 0, 0.25)' },
|
|
3602
|
-
cancelText: confirmText,
|
|
3603
|
-
okText: cancelText,
|
|
3604
|
-
cancelButtonProps: { type: 'primary' },
|
|
3605
|
-
okButtonProps: { type: 'default' },
|
|
3606
|
-
onCancel: (close) => { onConfirm(); close(); },
|
|
3607
|
-
// onOk (the right "Cancel" button) just closes the modal — default behaviour
|
|
3608
|
-
});
|
|
3609
|
-
}
|
|
3610
|
-
|
|
3611
3495
|
populateTemplatesList = (data, blankTemplateRequired, layoutSelection) => {
|
|
3612
3496
|
if (!data) {
|
|
3613
3497
|
return [];
|
|
@@ -3757,78 +3641,20 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
3757
3641
|
deleteOption = this.props.intl.formatMessage(messages.unMapButton);
|
|
3758
3642
|
}
|
|
3759
3643
|
if (!layoutSelection) {
|
|
3760
|
-
// Determine archive eligibility for this template:
|
|
3761
|
-
// - Zalo: never eligible
|
|
3762
|
-
// - WhatsApp: not eligible when status is awaitingApproval / pending / unsubmitted
|
|
3763
|
-
// - RCS: not eligible when status is awaitingApproval / pending
|
|
3764
|
-
const templateWhatsappStatus = get(template, `versions.base.content.${WHATSAPP_LOWERCASE}.status`, '');
|
|
3765
|
-
const templateRcsStatus = get(template, 'versions.base.content.RCS.rcsContent.cardContent[0].Status', '');
|
|
3766
|
-
const channelUpCase = this.state.channel.toUpperCase();
|
|
3767
|
-
const isTemplateArchiveEligible = channelUpCase !== ZALO &&
|
|
3768
|
-
!(channelUpCase === WHATSAPP && [WHATSAPP_STATUSES.awaitingApproval, WHATSAPP_STATUSES.pending, WHATSAPP_STATUSES.unsubmitted].includes(templateWhatsappStatus)) &&
|
|
3769
|
-
!(channelUpCase === RCS && [RCS_STATUSES.awaitingApproval, RCS_STATUSES.pending].includes(templateRcsStatus));
|
|
3770
|
-
|
|
3771
|
-
// Checkbox on card header (full mode only, only for archive-eligible templates)
|
|
3772
|
-
if (this.props.isFullMode && this.props.location.query.type !== 'embedded' && isTemplateArchiveEligible) {
|
|
3773
|
-
const selectedIds = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
3774
|
-
const selectedIdsArray = selectedIds.toJS ? selectedIds.toJS() : selectedIds;
|
|
3775
|
-
temp.cardTop = (
|
|
3776
|
-
<div className="template-card-top-bar">
|
|
3777
|
-
<CapCheckbox
|
|
3778
|
-
checked={selectedIdsArray.includes(template._id)}
|
|
3779
|
-
onChange={() => this.props.actions.toggleTemplateSelection(template._id)}
|
|
3780
|
-
onClick={(e) => e.stopPropagation()}
|
|
3781
|
-
/>
|
|
3782
|
-
</div>
|
|
3783
|
-
);
|
|
3784
|
-
}
|
|
3785
|
-
|
|
3786
3644
|
temp.footer = (
|
|
3787
3645
|
<div className="footer-container">
|
|
3788
3646
|
<div className="card-title">
|
|
3789
3647
|
<span className="template-name" style={{ fontWeight: `${this.state.channel.toLowerCase() === 'wechat' ? '400' : '600'}` }}>
|
|
3790
3648
|
{ template && template.versions && template.versions.history && template.versions.history.length > 1 && this.state.channel.toLowerCase() !== 'mobilepush' && <i style={{fontSize: '16px', margin: '0 8px 0 0', verticalAlign: 'middle'}} className="material-icons">filter_none</i>}
|
|
3791
3649
|
{template?.name}
|
|
3792
|
-
{template.isArchived && <CapColoredTag tagColor={CAP_G08} tagTextColor={CAP_G05} className="archived-tag">{this.props.intl.formatMessage(messages.archivedTag)}</CapColoredTag>}
|
|
3793
3650
|
</span>
|
|
3794
3651
|
{this.props.location.query.type !== 'embedded' && <CapPopover
|
|
3795
3652
|
trigger="click"
|
|
3796
3653
|
content={
|
|
3797
3654
|
<div className="popover-content">
|
|
3798
|
-
{this.state.channel !== 'wechat' &&
|
|
3655
|
+
{this.state.channel !== 'wechat' && <div className="popover-action-container">
|
|
3799
3656
|
<span onClick={() => this.duplicateTemplate(template)} className="popover-action" style={{cursor: 'pointer', padding: '8px 0px'}}>{this.props.intl.formatMessage(messages.duplicateButton)}</span>
|
|
3800
3657
|
</div>}
|
|
3801
|
-
{this.props.isFullMode && isTemplateArchiveEligible && !template.isArchived && <div className="popover-action-container">
|
|
3802
|
-
<span
|
|
3803
|
-
onClick={() => {
|
|
3804
|
-
this.showArchiveConfirm({
|
|
3805
|
-
title: this.props.intl.formatMessage(messages.archiveTemplates),
|
|
3806
|
-
onConfirm: () => this.props.actions.archiveTemplate(this.state.channel, template._id, template.name),
|
|
3807
|
-
count: 1,
|
|
3808
|
-
});
|
|
3809
|
-
}}
|
|
3810
|
-
className="popover-action popover-archive-action"
|
|
3811
|
-
>
|
|
3812
|
-
<CapIcon type="archive" size="l" />
|
|
3813
|
-
{this.props.intl.formatMessage(messages.archiveButton)}
|
|
3814
|
-
</span>
|
|
3815
|
-
</div>}
|
|
3816
|
-
{this.props.isFullMode && isTemplateArchiveEligible && template.isArchived && <div className="popover-action-container">
|
|
3817
|
-
<span
|
|
3818
|
-
onClick={() => {
|
|
3819
|
-
this.showArchiveConfirm({
|
|
3820
|
-
title: this.props.intl.formatMessage(messages.unarchiveTemplates),
|
|
3821
|
-
onConfirm: () => this.props.actions.unarchiveTemplate(this.state.channel, template._id, template.name),
|
|
3822
|
-
count: 1,
|
|
3823
|
-
isUnarchive: true,
|
|
3824
|
-
});
|
|
3825
|
-
}}
|
|
3826
|
-
className="popover-action popover-archive-action"
|
|
3827
|
-
>
|
|
3828
|
-
<CapIcon type="archive" size="l" />
|
|
3829
|
-
{this.props.intl.formatMessage(messages.unarchiveButton)}
|
|
3830
|
-
</span>
|
|
3831
|
-
</div>}
|
|
3832
3658
|
<div className="popover-action-container">
|
|
3833
3659
|
<span onClick={() => this.toggleDeleteTemplateModal(template)} className="popover-action" style={{cursor: 'pointer', padding: '8px 0px'}}>{deleteOption}</span>
|
|
3834
3660
|
</div>
|
|
@@ -4393,9 +4219,14 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
4393
4219
|
const isWechatEmbedded = !this.props.isFullMode && channel.toUpperCase() === WECHAT;
|
|
4394
4220
|
const channelLowerCase = (channel || '').toLowerCase();
|
|
4395
4221
|
const isTraiDltFeature = this.checkDLTfeatureEnable();
|
|
4396
|
-
|
|
4397
4222
|
const createButton =
|
|
4398
|
-
(
|
|
4223
|
+
(
|
|
4224
|
+
(
|
|
4225
|
+
channelLowerCase === WHATSAPP_LOWERCASE
|
|
4226
|
+
|| channelLowerCase === RCS_LOWERCASE
|
|
4227
|
+
)
|
|
4228
|
+
&& !this.props.isFullMode
|
|
4229
|
+
)
|
|
4399
4230
|
? (
|
|
4400
4231
|
<CapLink
|
|
4401
4232
|
onClick={this.openCreativesFullMode}
|
|
@@ -4421,22 +4252,23 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
4421
4252
|
if (([WHATSAPP_LOWERCASE, ZALO_LOWERCASE, RCS_LOWERCASE].includes(this.state?.channel?.toLocaleLowerCase()) && isEmpty(this.state?.hostName))) {
|
|
4422
4253
|
isfilterContentVisisble = false;
|
|
4423
4254
|
}
|
|
4424
|
-
|
|
4425
|
-
const
|
|
4426
|
-
const
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4255
|
+
|
|
4256
|
+
const useLocalTemplates = this.props.localTemplatesConfig?.useLocalTemplates;
|
|
4257
|
+
const builtFilterContent = ((isfilterContentVisisble || [WECHAT, MOBILE_PUSH, INAPP].includes(this.state.channel.toUpperCase())) && (
|
|
4258
|
+
<div className="action-container">
|
|
4259
|
+
<div className="action-container__toolbar-row">
|
|
4260
|
+
{isfilterContentVisisble ? (
|
|
4261
|
+
<CapInput.Search
|
|
4262
|
+
className="search-text"
|
|
4263
|
+
placeholder={this.props.intl.formatMessage(messages.searchText)}
|
|
4264
|
+
value={this.state.searchText}
|
|
4265
|
+
onChange={(e) => this.searchTemplate(e.target.value, this.state.channel)}
|
|
4266
|
+
onSearch={() => this.searchTemplate(this.state.searchText, this.state.channel)}
|
|
4267
|
+
onClear={() => this.searchTemplate('', this.state.channel)}
|
|
4268
|
+
onScroll={(e) => e.stopPropagation()}
|
|
4269
|
+
disabled={this.checkSearchDisabled()}
|
|
4270
|
+
/>
|
|
4271
|
+
) : null}
|
|
4440
4272
|
{
|
|
4441
4273
|
channel.toUpperCase() === WECHAT && <CapRadio.CapRadioGroup className="wechat-filters" defaultValue={wechatFilter} onChange={this.setWechatFilter}>
|
|
4442
4274
|
<CapRadio.Button value={WECHAT_FILTERS.ALL}><CapLabel type="label2">
|
|
@@ -4582,46 +4414,27 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
4582
4414
|
</div>
|
|
4583
4415
|
)
|
|
4584
4416
|
}
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
{
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
{!_isArchivedMode && !_renderHasSelection && this.props.isFullMode && this.props.location.query.type !== 'embedded' && channelLowerCase !== ZALO_LOWERCASE && (
|
|
4598
|
-
<CapDropdown
|
|
4599
|
-
trigger={['click']}
|
|
4600
|
-
overlay={
|
|
4601
|
-
<CapMenu>
|
|
4602
|
-
<CapMenu.Item
|
|
4603
|
-
key="archived"
|
|
4604
|
-
onClick={() => {
|
|
4605
|
-
this.props.actions.setArchivedMode(true);
|
|
4606
|
-
this.setState({ searchText: '', page: 1 }, () => {
|
|
4607
|
-
const params = { name: '', sortBy: this.state.sortBy, archiveStatus: 'archived' };
|
|
4608
|
-
this.getAllTemplates({ params, resetPage: true }, true);
|
|
4609
|
-
});
|
|
4610
|
-
}}
|
|
4611
|
-
>
|
|
4612
|
-
<FormattedMessage {...messages.archivedTemplates} />
|
|
4613
|
-
</CapMenu.Item>
|
|
4614
|
-
</CapMenu>
|
|
4417
|
+
</div>
|
|
4418
|
+
<div>
|
|
4419
|
+
<div className="action-container__create-row">
|
|
4420
|
+
{
|
|
4421
|
+
this.state?.channel?.toLowerCase() === WHATSAPP_LOWERCASE && (isWhatsappCountExeeded) ? (
|
|
4422
|
+
<CapTooltip title={whatsappCountExceedText}>
|
|
4423
|
+
<div className="button-disabled-tooltip-wrapper">
|
|
4424
|
+
{createButton}
|
|
4425
|
+
</div>
|
|
4426
|
+
</CapTooltip>
|
|
4427
|
+
)
|
|
4428
|
+
: isfilterContentVisisble && !isWechatEmbedded && !this.props.isDltFromRcs && !this.props.isSmsFallbackFromRcs && createButton
|
|
4615
4429
|
}
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
<CapButton type="flat" className="template-listing-more-btn">
|
|
4619
|
-
<CapIcon type="more" />
|
|
4620
|
-
</CapButton>
|
|
4621
|
-
</CapDropdown>
|
|
4622
|
-
)}
|
|
4430
|
+
</div>
|
|
4431
|
+
</div>
|
|
4623
4432
|
</div>
|
|
4624
|
-
|
|
4433
|
+
));
|
|
4434
|
+
const localTemplatesFilterContent = get(this.props, 'localTemplatesConfig.localTemplatesFilterContent', null);
|
|
4435
|
+
const filterContent = (useLocalTemplates && localTemplatesFilterContent) != null
|
|
4436
|
+
? localTemplatesFilterContent
|
|
4437
|
+
: builtFilterContent;
|
|
4625
4438
|
let htmlPreviewContent = "";
|
|
4626
4439
|
if (this.state.channel.toLowerCase() === 'ebill') {
|
|
4627
4440
|
htmlPreviewContent = this.state.previewTemplate && this.state.previewTemplate.versions && this.state.previewTemplate.versions.base && this.state.previewTemplate.versions.base['ebill-editor'];
|
|
@@ -4631,7 +4444,10 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
4631
4444
|
|
|
4632
4445
|
|
|
4633
4446
|
const creativesParams = this.getCreativesParams();
|
|
4634
|
-
const templates =
|
|
4447
|
+
const templates = useLocalTemplates
|
|
4448
|
+
? (this.props.localTemplatesConfig?.localTemplates || [])
|
|
4449
|
+
: (this.props.TemplatesList || []);
|
|
4450
|
+
const isLoadingWhenLocal = useLocalTemplates && !!this.props.localTemplatesConfig?.localTemplatesLoading;
|
|
4635
4451
|
const {route} = this.props;
|
|
4636
4452
|
const loadingTipMap = {
|
|
4637
4453
|
sendingFile: 'uploadingFile',
|
|
@@ -4646,9 +4462,11 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
4646
4462
|
(deleteRcsTemplateInProgress && 'deletingTemplate') ||
|
|
4647
4463
|
(this.props.EmailCreate.duplicateTemplateInProgress && 'duplicatingTemplate');
|
|
4648
4464
|
|
|
4649
|
-
const loadingTip =
|
|
4465
|
+
const loadingTip = useLocalTemplates && this.props.localTemplatesConfig?.localTemplatesLoadingTip
|
|
4466
|
+
? this.props.localTemplatesConfig.localTemplatesLoadingTip
|
|
4467
|
+
: (messages[loadingTipIntl] ? this.props.intl.formatMessage(messages[loadingTipIntl]) : this.props.intl.formatMessage(messages.gettingAllTemplates));
|
|
4650
4468
|
const showNoTemplatesFoundZalo = this.state.channel.toUpperCase() === ZALO && isEmpty(this.state.searchedZaloTemplates) && this.state.searchingZaloTemplate;
|
|
4651
|
-
const showNoTemplatesFoundOther = ![ZALO].includes(this.state.channel.toUpperCase()) && isEmpty(
|
|
4469
|
+
const showNoTemplatesFoundOther = ![ZALO].includes(this.state.channel.toUpperCase()) && isEmpty(templates) && (useLocalTemplates ? !isLoadingWhenLocal : !this.props.Templates.getAllTemplatesInProgress) && (useLocalTemplates || !isEmpty(this.state.searchText));
|
|
4652
4470
|
const showNoTemplatesFound = showNoTemplatesFoundZalo || showNoTemplatesFoundOther;
|
|
4653
4471
|
|
|
4654
4472
|
return (
|
|
@@ -4669,24 +4487,6 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
4669
4487
|
}
|
|
4670
4488
|
/>
|
|
4671
4489
|
|
|
4672
|
-
{/* Archived mode header with back arrow (full mode only) */}
|
|
4673
|
-
{this.props.isFullMode && get(this.props, 'Templates.isArchivedMode', false) && (
|
|
4674
|
-
<CapRow type="flex" align="middle" className="archived-mode-header">
|
|
4675
|
-
<CapIcon
|
|
4676
|
-
type="back"
|
|
4677
|
-
className="archived-mode-back-icon"
|
|
4678
|
-
onClick={() => {
|
|
4679
|
-
this.props.actions.setArchivedMode(false);
|
|
4680
|
-
this.setState({ searchText: '', page: 1 }, () => {
|
|
4681
|
-
const params = { name: '', sortBy: this.state.sortBy, archiveStatus: 'active' };
|
|
4682
|
-
this.getAllTemplates({ params, resetPage: true }, true);
|
|
4683
|
-
});
|
|
4684
|
-
}}
|
|
4685
|
-
/>
|
|
4686
|
-
<CapHeading type="h3"><FormattedMessage {...messages.archivedTemplates} /></CapHeading>
|
|
4687
|
-
</CapRow>
|
|
4688
|
-
)}
|
|
4689
|
-
|
|
4690
4490
|
{channel.toLowerCase() === WHATSAPP_LOWERCASE &&
|
|
4691
4491
|
showWhatsappCountWarning ? (
|
|
4692
4492
|
<CapAlert message={whatsappCountExceedText} type="info" />
|
|
@@ -4698,7 +4498,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
4698
4498
|
/>
|
|
4699
4499
|
) : null}
|
|
4700
4500
|
|
|
4701
|
-
{channel.toLowerCase() === RCS_LOWERCASE && !isFullMode ? (
|
|
4501
|
+
{channel.toLowerCase() === RCS_LOWERCASE && !isFullMode && this.state?.hostName !== HOST_INFOBIP ? (
|
|
4702
4502
|
<CapInfoNote
|
|
4703
4503
|
message={formatMessage(messages.rcsOnlyApprovedTemplates)}
|
|
4704
4504
|
/>
|
|
@@ -4711,22 +4511,22 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
4711
4511
|
) : null}
|
|
4712
4512
|
<CapRow>
|
|
4713
4513
|
<Pagination
|
|
4714
|
-
templateInProgress={
|
|
4715
|
-
this.props.Templates.getAllTemplatesInProgress
|
|
4716
|
-
}
|
|
4514
|
+
templateInProgress={useLocalTemplates ? isLoadingWhenLocal : this.props.Templates.getAllTemplatesInProgress}
|
|
4717
4515
|
onPageChange={
|
|
4718
|
-
templates.length
|
|
4516
|
+
templates.length
|
|
4517
|
+
? (useLocalTemplates ? (this.props.localTemplatesConfig?.localTemplatesOnPageChange || (() => {})) : this.onPaginationChange)
|
|
4518
|
+
: () => {}
|
|
4719
4519
|
}
|
|
4720
4520
|
>
|
|
4721
4521
|
{this.getTemplateDataForGrid({
|
|
4722
4522
|
previewTemplateId: this.state.zaloPreviewItemId,
|
|
4723
|
-
isLoading,
|
|
4724
|
-
isInitialLoading,
|
|
4523
|
+
isLoading: useLocalTemplates ? isLoadingWhenLocal : isLoading,
|
|
4524
|
+
isInitialLoading: useLocalTemplates ? isLoadingWhenLocal && templates.length === 0 : isInitialLoading,
|
|
4725
4525
|
loadingTip,
|
|
4726
4526
|
channel: this.state.channel,
|
|
4727
4527
|
templates: this.state.searchingZaloTemplate
|
|
4728
4528
|
? this.state.searchedZaloTemplates
|
|
4729
|
-
:
|
|
4529
|
+
: templates,
|
|
4730
4530
|
filterContent,
|
|
4731
4531
|
handlers: {
|
|
4732
4532
|
handlePreviewClick: this.handlePreviewClick,
|
|
@@ -4909,6 +4709,15 @@ Templates.propTypes = {
|
|
|
4909
4709
|
WebPush: PropTypes.object,
|
|
4910
4710
|
smsRegister: PropTypes.any,
|
|
4911
4711
|
isDltFromRcs: PropTypes.bool,
|
|
4712
|
+
isSmsFallbackFromRcs: PropTypes.bool,
|
|
4713
|
+
localTemplatesConfig: PropTypes.shape({
|
|
4714
|
+
useLocalTemplates: PropTypes.bool,
|
|
4715
|
+
localTemplates: PropTypes.arrayOf(PropTypes.object),
|
|
4716
|
+
localTemplatesLoading: PropTypes.bool,
|
|
4717
|
+
localTemplatesLoadingTip: PropTypes.string,
|
|
4718
|
+
localTemplatesFilterContent: PropTypes.node,
|
|
4719
|
+
localTemplatesOnPageChange: PropTypes.func,
|
|
4720
|
+
}),
|
|
4912
4721
|
};
|
|
4913
4722
|
|
|
4914
4723
|
const mapStateToProps = createStructuredSelector({
|