@capillarytech/creatives-library 8.0.348 → 8.0.350
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 +1 -0
- package/package.json +1 -1
- package/services/api.js +20 -0
- package/services/tests/api.test.js +59 -0
- package/utils/common.js +6 -0
- package/utils/tests/v2Common.test.js +46 -1
- package/utils/v2common.js +18 -0
- package/v2Components/CapCustomSkeleton/index.js +1 -1
- package/v2Components/CapCustomSkeleton/tests/__snapshots__/index.test.js.snap +12 -12
- package/v2Components/CommonTestAndPreview/UnifiedPreview/WhatsAppPreviewContent.js +6 -18
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +0 -27
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/WhatsAppPreviewContent.test.js +0 -48
- package/v2Components/TemplatePreview/_templatePreview.scss +0 -21
- package/v2Components/TemplatePreview/index.js +6 -18
- package/v2Components/TemplatePreview/tests/__snapshots__/index.test.js.snap +0 -1
- package/v2Containers/Assets/images/archive_Empty_Illustration.svg +9 -0
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +3 -1
- package/v2Containers/CreativesContainer/index.js +6 -9
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +3 -0
- package/v2Containers/Templates/ChannelTypeIllustration.js +23 -6
- package/v2Containers/Templates/_templates.scss +180 -24
- package/v2Containers/Templates/actions.js +44 -0
- package/v2Containers/Templates/constants.js +31 -0
- package/v2Containers/Templates/index.js +364 -60
- package/v2Containers/Templates/messages.js +96 -0
- package/v2Containers/Templates/reducer.js +84 -1
- package/v2Containers/Templates/sagas.js +64 -0
- package/v2Containers/Templates/selectors.js +12 -0
- package/v2Containers/Templates/tests/ChannelTypeIllustration.test.js +12 -0
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1176 -1122
- package/v2Containers/Templates/tests/index.test.js +6 -0
- package/v2Containers/Templates/tests/reducer.test.js +178 -0
- package/v2Containers/Templates/tests/sagas.test.js +390 -8
- package/v2Containers/Templates/tests/selector.test.js +32 -0
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +1 -1
- package/v2Containers/Whatsapp/constants.js +0 -8
- package/v2Containers/Whatsapp/index.js +5 -142
- package/v2Containers/Whatsapp/index.scss +0 -8
- package/v2Containers/Whatsapp/messages.js +0 -16
|
@@ -50,9 +50,7 @@ import {
|
|
|
50
50
|
CapStatus,
|
|
51
51
|
CapColoredTag,
|
|
52
52
|
CapSpin,
|
|
53
|
-
|
|
54
|
-
CapColumn,
|
|
55
|
-
CapCarousel
|
|
53
|
+
CapCheckbox,
|
|
56
54
|
} from "@capillarytech/cap-ui-library";
|
|
57
55
|
import { makeSelectTemplates, makeSelectTemplatesResponse } from './selectors';
|
|
58
56
|
import { makeSelectCreate as makeSelectCreateSms } from '../Sms/Create/selectors';
|
|
@@ -83,7 +81,7 @@ import * as webpushActions from '../WebPush/actions';
|
|
|
83
81
|
import * as globalActions from '../Cap/actions';
|
|
84
82
|
import { makeSelectAuthenticated } from '../Cap/selectors';
|
|
85
83
|
import { UserIsAuthenticated } from '../../utils/authWrapper';
|
|
86
|
-
import { getObjFromQueryParams } from '../../utils/v2common';
|
|
84
|
+
import { getObjFromQueryParams, buildTemplateNameDescription } from '../../utils/v2common';
|
|
87
85
|
import messages from './messages';
|
|
88
86
|
import {checkUnicode} from '../../utils/smsCharCountV2';
|
|
89
87
|
import { containsBase64Images } from '../../utils/content';
|
|
@@ -107,8 +105,8 @@ import {
|
|
|
107
105
|
FACEBOOK as FACEBOOK_CHANNEL,
|
|
108
106
|
CREATE,
|
|
109
107
|
} from '../App/constants';
|
|
110
|
-
import {MAX_WHATSAPP_TEMPLATES, WARNING_WHATSAPP_TEMPLATES , ACCOUNT_MAPPING_ON_CHANNEL, noFilteredWhatsappZaloTemplatesTitle, noFilteredWhatsappZaloTemplatesDesc, noApprovedWhatsappZaloTemplatesTitle, noApprovedWhatsappTemplatesDesc, zaloDescIllustration, noApprovedRcsTemplatesTitle, noApprovedRcsTemplatesDesc} from './constants';
|
|
111
|
-
import { COPY_OF } from '../../constants/unified';
|
|
108
|
+
import {MAX_WHATSAPP_TEMPLATES, WARNING_WHATSAPP_TEMPLATES , ACCOUNT_MAPPING_ON_CHANNEL, noFilteredWhatsappZaloTemplatesTitle, noFilteredWhatsappZaloTemplatesDesc, noApprovedWhatsappZaloTemplatesTitle, noApprovedWhatsappTemplatesDesc, zaloDescIllustration, noApprovedRcsTemplatesTitle, noApprovedRcsTemplatesDesc, ARCHIVE_STATUS_ACTIVE, ARCHIVE_STATUS_ARCHIVED, ARCHIVE_REFRESH_TYPE_ARCHIVE, ARCHIVE_REFRESH_TYPE_UNARCHIVE} from './constants';
|
|
109
|
+
import { COPY_OF, EMBEDDED } from '../../constants/unified';
|
|
112
110
|
import {
|
|
113
111
|
STATUS_OPTIONS,
|
|
114
112
|
CATEGORY,
|
|
@@ -116,19 +114,11 @@ import {
|
|
|
116
114
|
STATUS as WHATSAPP_STATUS,
|
|
117
115
|
WHATSAPP_STATUSES,
|
|
118
116
|
HOST_GUPSHUP,
|
|
119
|
-
HOST_HAPTIC,
|
|
120
117
|
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,
|
|
127
118
|
IMAGE,
|
|
128
119
|
VIDEO,
|
|
129
|
-
GIF,
|
|
130
120
|
} from '../Whatsapp/constants';
|
|
131
|
-
import { INAPP_LAYOUT_DETAILS, INAPP_MESSAGE_LAYOUT_TYPES
|
|
121
|
+
import { INAPP_LAYOUT_DETAILS, INAPP_MESSAGE_LAYOUT_TYPES } from '../InApp/constants';
|
|
132
122
|
import { ZALO_STATUS_OPTIONS, ZALO_STATUSES } from '../Zalo/constants';
|
|
133
123
|
import { getWhatsappContent, getWhatsappStatus, getWhatsappCategory, getWhatsappCta, getWhatsappQuickReply, getWhatsappAutoFill, getWhatsappCarouselButtonView } from '../Whatsapp/utils';
|
|
134
124
|
import { getRCSContent } from '../Rcs/utils';
|
|
@@ -145,7 +135,7 @@ import {CREATIVE} from '../Facebook/constants';
|
|
|
145
135
|
import videoPlay from '../../assets/videoPlay.svg';
|
|
146
136
|
import whatsappImageEmptyPreview from '../../v2Components/TemplatePreview/assets/images/empty_image_preview.svg';
|
|
147
137
|
import whatsappVideoEmptyPreview from '../../v2Components/TemplatePreview/assets/images/empty_video_preview.svg';
|
|
148
|
-
import { CAP_SPACE_16 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
138
|
+
import { CAP_SPACE_16, CAP_G08, CAP_G05, CAP_SPACE_08, CAP_SPACE_12 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
149
139
|
import { GA } from '@capillarytech/cap-ui-utils';
|
|
150
140
|
import { MAPP_SDK } from '../InApp/constants';
|
|
151
141
|
import injectReducer from '../../utils/injectReducer';
|
|
@@ -154,7 +144,6 @@ import { compose } from 'redux';
|
|
|
154
144
|
import { v2TemplateSaga } from './sagas';
|
|
155
145
|
import injectSaga from '../../utils/injectSaga';
|
|
156
146
|
import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
|
|
157
|
-
import { Rcs } from '../Rcs';
|
|
158
147
|
import { makeSelectRcs } from '../Rcs/selectors';
|
|
159
148
|
import { getRcsStatusType } from '../Rcs/utils';
|
|
160
149
|
import { makeSelectWebPush } from '../WebPush/selectors';
|
|
@@ -437,6 +426,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
437
426
|
channel = '';
|
|
438
427
|
}
|
|
439
428
|
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();
|
|
440
432
|
// Clear templates when entering account selection mode to prevent showing old channel templates
|
|
441
433
|
if (activeMode === ACCOUNT_SELECTION_MODE) {
|
|
442
434
|
this.props.actions.resetTemplate();
|
|
@@ -827,6 +819,39 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
827
819
|
this.getAllTemplates({params, resetPage: true});
|
|
828
820
|
}
|
|
829
821
|
|
|
822
|
+
// Archive / Unarchive / Bulk Archive / Bulk Unarchive — detect completion and refresh listing
|
|
823
|
+
const wasArchiving = this.props.Templates.archiveInProgress;
|
|
824
|
+
const isArchiveDone = !nextProps.Templates.archiveInProgress && wasArchiving;
|
|
825
|
+
if (isArchiveDone && !nextProps.Templates.archiveError) {
|
|
826
|
+
const { successMessage, description } = nextProps.Templates.archiveSuccessPayload || {};
|
|
827
|
+
if (successMessage) CapNotification.success({ message: successMessage, description });
|
|
828
|
+
this.getAllTemplates({ params, resetPage: true });
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
const wasUnarchiving = this.props.Templates.unarchiveInProgress;
|
|
832
|
+
const isUnarchiveDone = !nextProps.Templates.unarchiveInProgress && wasUnarchiving;
|
|
833
|
+
if (isUnarchiveDone && !nextProps.Templates.unarchiveError) {
|
|
834
|
+
const { successMessage, description } = nextProps.Templates.unarchiveSuccessPayload || {};
|
|
835
|
+
if (successMessage) CapNotification.success({ message: successMessage, description });
|
|
836
|
+
this.getAllTemplates({ params, resetPage: true });
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
const wasBulkArchiving = this.props.Templates.bulkArchiveInProgress;
|
|
840
|
+
const isBulkArchiveDone = !nextProps.Templates.bulkArchiveInProgress && wasBulkArchiving;
|
|
841
|
+
if (isBulkArchiveDone && !nextProps.Templates.bulkArchiveError) {
|
|
842
|
+
const { count } = nextProps.Templates.bulkArchiveSuccessPayload || {};
|
|
843
|
+
CapNotification.success({ message: this.props.intl.formatMessage(messages.bulkArchiveSuccess, { count }) });
|
|
844
|
+
this.getAllTemplates({ params, resetPage: true });
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
const wasBulkUnarchiving = this.props.Templates.bulkUnarchiveInProgress;
|
|
848
|
+
const isBulkUnarchiveDone = !nextProps.Templates.bulkUnarchiveInProgress && wasBulkUnarchiving;
|
|
849
|
+
if (isBulkUnarchiveDone && !nextProps.Templates.bulkUnarchiveError) {
|
|
850
|
+
const { count } = nextProps.Templates.bulkUnarchiveSuccessPayload || {};
|
|
851
|
+
CapNotification.success({ message: this.props.intl.formatMessage(messages.bulkUnarchiveSuccess, { count }) });
|
|
852
|
+
this.getAllTemplates({ params, resetPage: true });
|
|
853
|
+
}
|
|
854
|
+
|
|
830
855
|
if (!nextProps.Templates.sendingFile && !isEqual(this.props.Templates.sendingFile, nextProps.Templates.sendingFile) && !nextProps.Templates.errorSendingFile) {
|
|
831
856
|
const module = this.props.location.query.module ? this.props.location.query.module : 'default';
|
|
832
857
|
const isLanguageSupport = (this.props.location.query.isLanguageSupport) ? this.props.location.query.isLanguageSupport : true;
|
|
@@ -1595,6 +1620,11 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1595
1620
|
let queryParams = params || {};
|
|
1596
1621
|
let page = this.state.page;
|
|
1597
1622
|
const { activeMode } = this.state;
|
|
1623
|
+
// Archive filter — use explicit param if provided (props may not have updated yet due to async dispatch)
|
|
1624
|
+
if (!queryParams.archiveStatus) {
|
|
1625
|
+
const archiveFilter = get(this.props, 'Templates.archiveFilter', 'active');
|
|
1626
|
+
queryParams.archiveStatus = archiveFilter;
|
|
1627
|
+
}
|
|
1598
1628
|
if (activeMode === ACCOUNT_SELECTION_MODE) {
|
|
1599
1629
|
this.setTemplatesMode();
|
|
1600
1630
|
}
|
|
@@ -1861,6 +1891,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1861
1891
|
const currentChannel = channel.toUpperCase();
|
|
1862
1892
|
const {channel: stateChannel} = this.state;
|
|
1863
1893
|
const channelLowerCase = stateChannel.toLowerCase();
|
|
1894
|
+
const _selectedIds = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
1895
|
+
const _selectedIdsArray = _selectedIds && typeof _selectedIds.toJS === 'function' ? _selectedIds.toJS() : (Array.isArray(_selectedIds) ? _selectedIds : []);
|
|
1896
|
+
const hasSelection = this.props.isFullMode && _selectedIdsArray.length > 0;
|
|
1864
1897
|
let filteredTemplates = templates;
|
|
1865
1898
|
let isTraiDltFeature = false;
|
|
1866
1899
|
switch (currentChannel) {
|
|
@@ -1900,47 +1933,59 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1900
1933
|
const iosBodyType = get(template, 'versions.base.content.IOS.bodyType');
|
|
1901
1934
|
const inappBodyType = androidBodyType || iosBodyType;
|
|
1902
1935
|
const isZaloPreviewLoading = previewTemplateId === template?._id;
|
|
1936
|
+
const selectedIdsForCard = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
1937
|
+
const selectedIdsArrayForCard = selectedIdsForCard.toJS ? selectedIdsForCard.toJS() : selectedIdsForCard;
|
|
1938
|
+
// Archive eligibility per template: Zalo never; WhatsApp/RCS not when pending/awaiting
|
|
1939
|
+
const cardWhatsappStatus = get(template, `versions.base.content.${WHATSAPP_LOWERCASE}.status`, '');
|
|
1940
|
+
const cardRcsStatus = get(template, 'versions.base.content.RCS.rcsContent.cardContent[0].Status', '');
|
|
1941
|
+
const isArchivalEnabled = commonUtil.hasCreativesArchivalEnabled();
|
|
1942
|
+
const isCardArchiveEligible = isArchivalEnabled && this.isChannelArchiveEligible(currentChannel, cardWhatsappStatus, cardRcsStatus);
|
|
1943
|
+
const isArchivedMode = isArchivalEnabled && get(this.props, 'Templates.isArchivedMode', false);
|
|
1944
|
+
const isAnyArchiveInProgress = isArchivalEnabled && !!(get(this.props, 'Templates.archiveInProgress') || get(this.props, 'Templates.unarchiveInProgress') || get(this.props, 'Templates.bulkArchiveInProgress') || get(this.props, 'Templates.bulkUnarchiveInProgress'));
|
|
1903
1945
|
const templateData = {
|
|
1904
1946
|
key: `${currentChannel}-card-${template?.name}`,
|
|
1905
1947
|
title: (
|
|
1906
|
-
<span
|
|
1907
|
-
{template
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
INAPP_LAYOUT_DETAILS[inappBodyType]?.
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1948
|
+
<span className="template-card-title">
|
|
1949
|
+
{isCardArchiveEligible && this.renderCardSelectionCheckbox({ templateId: template._id, selectedIds: selectedIdsArrayForCard, isDisabled: isAnyArchiveInProgress })}
|
|
1950
|
+
<CapLabel.CapLabelInline type="label1" title={template?.name} className="template-card-name">
|
|
1951
|
+
{template?.name}
|
|
1952
|
+
{currentChannel === INAPP && (
|
|
1953
|
+
<CapRow>
|
|
1954
|
+
<CapColoredTag
|
|
1955
|
+
tagColor={INAPP_LAYOUT_DETAILS[inappBodyType]?.tagColor}
|
|
1956
|
+
tagTextColor={
|
|
1957
|
+
INAPP_LAYOUT_DETAILS[inappBodyType]?.tagTextColor
|
|
1958
|
+
}
|
|
1959
|
+
tagHeight="1.25rem"
|
|
1960
|
+
tagFontSize="0.857rem"
|
|
1961
|
+
>
|
|
1962
|
+
{INAPP_LAYOUT_DETAILS[inappBodyType]?.text}
|
|
1963
|
+
</CapColoredTag>
|
|
1964
|
+
</CapRow>
|
|
1965
|
+
)}
|
|
1966
|
+
</CapLabel.CapLabelInline>
|
|
1922
1967
|
</span>
|
|
1923
1968
|
),
|
|
1924
|
-
extra: [
|
|
1969
|
+
extra: isArchivedMode ? [] : [
|
|
1925
1970
|
// Hide preview icon for channels that support Test and Preview
|
|
1926
1971
|
// Show preview icon only for channels that don't support Test and Preview
|
|
1927
1972
|
(() => {
|
|
1928
1973
|
// Channels that have Test and Preview integrated
|
|
1929
1974
|
const testAndPreviewChannels = [EMAIL, SMS, WHATSAPP, RCS, INAPP, MOBILE_PUSH, VIBER, ZALO];
|
|
1930
1975
|
const isTestAndPreviewSupported = testAndPreviewChannels.includes(currentChannel.toUpperCase());
|
|
1931
|
-
|
|
1976
|
+
|
|
1932
1977
|
// Don't show preview icon if channel supports Test and Preview
|
|
1933
1978
|
if (isTestAndPreviewSupported) {
|
|
1934
1979
|
return null;
|
|
1935
1980
|
}
|
|
1936
|
-
|
|
1981
|
+
|
|
1937
1982
|
// Show preview icon for other channels (e.g., WeChat, Line, Facebook, Ebill)
|
|
1938
1983
|
if (currentChannel === ZALO && isZaloPreviewLoading) {
|
|
1939
1984
|
return (
|
|
1940
1985
|
<CapSpin style={{ marginRight: "16px", position: "static", display: "inline" }} spinning />
|
|
1941
1986
|
);
|
|
1942
1987
|
}
|
|
1943
|
-
|
|
1988
|
+
|
|
1944
1989
|
return this.getHoverComponent(
|
|
1945
1990
|
<CapIcon
|
|
1946
1991
|
className={`view-${channelLowerCase}`}
|
|
@@ -1960,7 +2005,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1960
2005
|
);
|
|
1961
2006
|
})()
|
|
1962
2007
|
],
|
|
1963
|
-
hoverOption: (
|
|
2008
|
+
hoverOption: isArchivedMode ? null : (
|
|
1964
2009
|
<CapButton
|
|
1965
2010
|
className={
|
|
1966
2011
|
this.props.isFullMode
|
|
@@ -2000,8 +2045,8 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2000
2045
|
<CapDropdown
|
|
2001
2046
|
overlay={
|
|
2002
2047
|
<CapMenu>
|
|
2003
|
-
{/* Phase 16: Test and Preview menu item - Show for supported channels */}
|
|
2004
|
-
{(this.isTestAndPreviewSupported() ||
|
|
2048
|
+
{/* Phase 16: Test and Preview menu item - Show for supported channels, hide in archived mode */}
|
|
2049
|
+
{!isArchivedMode && (this.isTestAndPreviewSupported() ||
|
|
2005
2050
|
(this.state.channel.toUpperCase() === WHATSAPP &&
|
|
2006
2051
|
status === WHATSAPP_STATUSES.approved) || (this.state.channel.toUpperCase() === RCS &&
|
|
2007
2052
|
rcsStatus === RCS_STATUSES.approved)) && (
|
|
@@ -2024,7 +2069,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2024
2069
|
{![WECHAT, WHATSAPP, ZALO].includes(
|
|
2025
2070
|
this.state.channel.toUpperCase()
|
|
2026
2071
|
) &&
|
|
2027
|
-
!isTraiDltFeature && (
|
|
2072
|
+
!isTraiDltFeature && !template.isArchived && (
|
|
2028
2073
|
<CapMenu.Item
|
|
2029
2074
|
className={`duplicate-${channelLowerCase}`}
|
|
2030
2075
|
onClick={() => this.duplicateTemplate(template)}
|
|
@@ -2032,6 +2077,26 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2032
2077
|
<FormattedMessage {...messages.duplicateButton} />
|
|
2033
2078
|
</CapMenu.Item>
|
|
2034
2079
|
)}
|
|
2080
|
+
{/* Archive/Unarchive menu item (full mode only, not for Zalo, not for WhatsApp/RCS awaiting/pending) */}
|
|
2081
|
+
{commonUtil.hasCreativesArchivalEnabled() && (() => {
|
|
2082
|
+
const channelUp = this.state.channel.toUpperCase();
|
|
2083
|
+
if (!this.isChannelArchiveEligible(channelUp, status, rcsStatus)) return null;
|
|
2084
|
+
return !template?.isArchived ? (
|
|
2085
|
+
<CapMenu.Item
|
|
2086
|
+
className={`archive-${channelLowerCase}`}
|
|
2087
|
+
onClick={() => this.handleTemplateArchiveAction({ templateId: template._id, templateName: template.name })}
|
|
2088
|
+
>
|
|
2089
|
+
<FormattedMessage {...messages.archiveButton} />
|
|
2090
|
+
</CapMenu.Item>
|
|
2091
|
+
) : (
|
|
2092
|
+
<CapMenu.Item
|
|
2093
|
+
className={`unarchive-${channelLowerCase}`}
|
|
2094
|
+
onClick={() => this.handleTemplateArchiveAction({ templateId: template._id, templateName: template.name, isUnarchive: true })}
|
|
2095
|
+
>
|
|
2096
|
+
<FormattedMessage {...messages.unarchiveButton} />
|
|
2097
|
+
</CapMenu.Item>
|
|
2098
|
+
);
|
|
2099
|
+
})()}
|
|
2035
2100
|
{/* Delete/Unmap menu item */}
|
|
2036
2101
|
{(!(
|
|
2037
2102
|
this.state.channel.toUpperCase() === WHATSAPP &&
|
|
@@ -2312,7 +2377,8 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2312
2377
|
case WHATSAPP: {
|
|
2313
2378
|
const { whatsappImageSrc = '', templateMsg, docPreview, whatsappVideoPreviewImg = '', templateHeaderPreview, templateFooterPreview, carouselData = [] } = getWhatsappContent(template);
|
|
2314
2379
|
templateData.title = (
|
|
2315
|
-
<CapRow>
|
|
2380
|
+
<CapRow type="flex" align="middle">
|
|
2381
|
+
{isCardArchiveEligible && this.renderCardSelectionCheckbox({ templateId: template._id, selectedIds: selectedIdsArrayForCard, isDisabled: isAnyArchiveInProgress })}
|
|
2316
2382
|
<CapLabel className="whatsapp-rcs-template-name">{template?.name}</CapLabel>
|
|
2317
2383
|
<WhatsappStatusContainer template={template} />
|
|
2318
2384
|
</CapRow>
|
|
@@ -2405,7 +2471,8 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2405
2471
|
const name = get(template, "name", "");
|
|
2406
2472
|
const statusDisplay=getRcsStatusType(status);
|
|
2407
2473
|
templateData.title = (
|
|
2408
|
-
<CapRow>
|
|
2474
|
+
<CapRow type="flex" align="middle">
|
|
2475
|
+
{isCardArchiveEligible && this.renderCardSelectionCheckbox({ templateId: template._id, selectedIds: selectedIdsArrayForCard, isDisabled: isAnyArchiveInProgress })}
|
|
2409
2476
|
<CapLabel className="whatsapp-rcs-template-name">{name}</CapLabel>
|
|
2410
2477
|
<CapRow type="flex" align="middle" className="rcs-status-container zalo-status-color">
|
|
2411
2478
|
<CapStatus
|
|
@@ -2529,7 +2596,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2529
2596
|
|
|
2530
2597
|
//no templates available
|
|
2531
2598
|
const showIllustrationForChannel = (forChannel) => {
|
|
2532
|
-
return forChannel === channelLowerCase && isEmpty(templates) && isEmpty(this.state.searchText) && !isLoading;
|
|
2599
|
+
return forChannel === channelLowerCase && isEmpty(templates) && isEmpty(this.state.searchText) && !isLoading && !get(this.props, 'Templates.isArchivedMode', false);
|
|
2533
2600
|
}
|
|
2534
2601
|
//when filters applied not matching templates
|
|
2535
2602
|
const filteredEmptyAndFullModeAs = (fullModeValue) => {
|
|
@@ -2547,6 +2614,11 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2547
2614
|
const accountId = get(this.props, 'Templates.selectedWeChatAccount.uuid');
|
|
2548
2615
|
const accounts = get(this.props, 'Templates.weCrmAccounts');
|
|
2549
2616
|
const getAllTemplatesInProgress = get(this.props, 'Templates.getAllTemplatesInProgress');
|
|
2617
|
+
const archiveListingRefreshType = get(this.props, 'Templates.archiveListingRefreshType', null);
|
|
2618
|
+
const isArchiveOperationInProgress = get(this.props, 'Templates.archiveInProgress', false)
|
|
2619
|
+
|| get(this.props, 'Templates.unarchiveInProgress', false)
|
|
2620
|
+
|| get(this.props, 'Templates.bulkArchiveInProgress', false)
|
|
2621
|
+
|| get(this.props, 'Templates.bulkUnarchiveInProgress', false);
|
|
2550
2622
|
|
|
2551
2623
|
const noWhatsappZaloTemplates = this.isFullMode() && isEmpty(templates) || !this.state.hostName;
|
|
2552
2624
|
const noApprovedWhatsappZaloTemplates = filteredEmptyAndFullModeAs(false) && !isEmpty(this.state?.hostName);
|
|
@@ -2555,9 +2627,37 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2555
2627
|
|
|
2556
2628
|
const noLoaderAndSearchText = isEmpty(this.state.searchText) && !isLoading;
|
|
2557
2629
|
|
|
2558
|
-
|
|
2630
|
+
const isArchivalEnabledLocal = commonUtil.hasCreativesArchivalEnabled();
|
|
2631
|
+
const isArchivedModeLocal = isArchivalEnabledLocal && get(this.props, 'Templates.isArchivedMode', false);
|
|
2632
|
+
const selectedIdsLocal = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
2633
|
+
const selectedIdsArrayLocal = selectedIdsLocal && typeof selectedIdsLocal.toJS === 'function' ? selectedIdsLocal.toJS() : (Array.isArray(selectedIdsLocal) ? selectedIdsLocal : []);
|
|
2634
|
+
const selectedCountLocal = selectedIdsArrayLocal.length;
|
|
2635
|
+
const hasSelectionLocal = isArchivalEnabledLocal && this.props.isFullMode && selectedCountLocal > 0;
|
|
2636
|
+
|
|
2637
|
+
return (<div>
|
|
2559
2638
|
{[WECHAT, MOBILE_PUSH, WEBPUSH, INAPP, WHATSAPP, ZALO, RCS].includes(currentChannel) && this.showAccountName()}
|
|
2560
|
-
|
|
2639
|
+
<CapRow type="flex" align="middle" justify="space-between" className="filter-row">
|
|
2640
|
+
<div className="filter-row-content">{filterContent}</div>
|
|
2641
|
+
{hasSelectionLocal && (
|
|
2642
|
+
<CapRow type="flex" align="middle" className="bulk-selection-bar">
|
|
2643
|
+
<CapLabel type="label2">
|
|
2644
|
+
{this.props.intl.formatMessage(messages.templatesSelected, { count: selectedCountLocal })}
|
|
2645
|
+
</CapLabel>
|
|
2646
|
+
<CapButton
|
|
2647
|
+
type="primary"
|
|
2648
|
+
prefix={<CapIcon type="archive" size="l" />}
|
|
2649
|
+
onClick={() => this.handleBulkArchiveAction({ ids: selectedIdsArrayLocal, count: selectedCountLocal, isUnarchive: isArchivedModeLocal })}
|
|
2650
|
+
>
|
|
2651
|
+
<span className="archive-btn-label">
|
|
2652
|
+
<FormattedMessage {...(isArchivedModeLocal ? messages.unarchiveButton : messages.archiveButton)} />
|
|
2653
|
+
</span>
|
|
2654
|
+
</CapButton>
|
|
2655
|
+
<CapButton type="secondary" onClick={() => this.props.actions.clearTemplateSelection()}>
|
|
2656
|
+
<FormattedMessage {...messages.archiveConfirmCancel} />
|
|
2657
|
+
</CapButton>
|
|
2658
|
+
</CapRow>
|
|
2659
|
+
)}
|
|
2660
|
+
</CapRow>
|
|
2561
2661
|
{[WHATSAPP, ZALO, INAPP,RCS].includes(currentChannel) && this.selectedFilters()}
|
|
2562
2662
|
{<div>
|
|
2563
2663
|
{!isEmpty(filteredTemplates) || !isEmpty(this.state.searchText) || !isEmpty(this.props.Templates.templateError) ? (
|
|
@@ -2570,7 +2670,7 @@ return (<div>
|
|
|
2570
2670
|
fbType={"list"}
|
|
2571
2671
|
/>
|
|
2572
2672
|
</div>)
|
|
2573
|
-
: [SMS_LOWERCASE, EMAIL_LOWERCASE].includes(this.state.channel.toLowerCase()) && !isLoading && this.getSmsEmailIllustration()
|
|
2673
|
+
: [SMS_LOWERCASE, EMAIL_LOWERCASE].includes(this.state.channel.toLowerCase()) && !isLoading && !get(this.props, 'Templates.isArchivedMode', false) && this.getSmsEmailIllustration()
|
|
2574
2674
|
}
|
|
2575
2675
|
|
|
2576
2676
|
{(this.state.selectedAccount === '' && isEmpty(this.props.Templates.selectedWeChatAccount)) && ([WECHAT_LOWERCASE, MOBILE_PUSH_LOWERCASE, INAPP_LOWERCASE].includes(this.state.channel.toLowerCase())) &&
|
|
@@ -2594,7 +2694,7 @@ return (<div>
|
|
|
2594
2694
|
</div>
|
|
2595
2695
|
)
|
|
2596
2696
|
}
|
|
2597
|
-
{(showWhatsappIllustration || showZaloIllustration) && (
|
|
2697
|
+
{(showWhatsappIllustration || showZaloIllustration) && !get(this.props, 'Templates.isArchivedMode', false) && (
|
|
2598
2698
|
noLoaderAndSearchText &&
|
|
2599
2699
|
<div style={this.isFullMode() ? { height: "calc(100vh - 325px)", overflow: 'auto' } : {}}>
|
|
2600
2700
|
{noWhatsappZaloTemplates && <ChannelTypeIllustration isFullMode={this.props.isFullMode} createTemplate={this.createTemplate} currentChannel={currentChannel} hostName={this.state?.hostName}/>}
|
|
@@ -2635,8 +2735,27 @@ return (<div>
|
|
|
2635
2735
|
<ChannelTypeIllustration isFullMode={this.props.isFullMode} createTemplate={this.createTemplate} currentChannel={currentChannel} hostName={this.state?.hostName}/>
|
|
2636
2736
|
</div>
|
|
2637
2737
|
}
|
|
2738
|
+
{get(this.props, 'Templates.isArchivedMode', false) && isEmpty(templates) && !isLoading && !getAllTemplatesInProgress && isEmpty(this.state.searchText) && (
|
|
2739
|
+
<CapRow className={this.isFullMode() ? 'illustration-scroll-wrapper' : ''}>
|
|
2740
|
+
<ChannelTypeIllustration
|
|
2741
|
+
isFullMode={this.props.isFullMode}
|
|
2742
|
+
createTemplate={this.createTemplate}
|
|
2743
|
+
currentChannel={currentChannel}
|
|
2744
|
+
isArchivedMode
|
|
2745
|
+
/>
|
|
2746
|
+
</CapRow>
|
|
2747
|
+
)}
|
|
2638
2748
|
{<CapCustomSkeleton loader={isInitialLoading && (isLoading || getAllTemplatesInProgress)} />}
|
|
2639
|
-
{
|
|
2749
|
+
{!isInitialLoading && getAllTemplatesInProgress && archiveListingRefreshType ? (
|
|
2750
|
+
<div className="archive-listing-spinner">
|
|
2751
|
+
<CapSpin spinning />
|
|
2752
|
+
<CapLabel.CapLabelInline type="label1">
|
|
2753
|
+
{archiveListingRefreshType === ARCHIVE_REFRESH_TYPE_ARCHIVE ? this.props.intl.formatMessage(messages.archivalInProgress) : this.props.intl.formatMessage(messages.unarchivalInProgress)}
|
|
2754
|
+
</CapLabel.CapLabelInline>
|
|
2755
|
+
</div>
|
|
2756
|
+
) : (
|
|
2757
|
+
<CapPageSpinner spinning={!isInitialLoading && (isLoading || getAllTemplatesInProgress)} />
|
|
2758
|
+
)}
|
|
2640
2759
|
</div>
|
|
2641
2760
|
}
|
|
2642
2761
|
</div>);
|
|
@@ -3278,6 +3397,10 @@ return (<div>
|
|
|
3278
3397
|
};
|
|
3279
3398
|
|
|
3280
3399
|
handleEditClick(e, template, modeType, path, options) {
|
|
3400
|
+
if (template && template.isArchived) {
|
|
3401
|
+
CapNotification.error({ message: this.props.intl.formatMessage(messages.cannotEditArchivedTemplate) });
|
|
3402
|
+
return;
|
|
3403
|
+
}
|
|
3281
3404
|
if (modeType && modeType !== undefined) {
|
|
3282
3405
|
this.setState({modeType});
|
|
3283
3406
|
}
|
|
@@ -3459,6 +3582,87 @@ return (<div>
|
|
|
3459
3582
|
this.setState({showModal: false});
|
|
3460
3583
|
}
|
|
3461
3584
|
|
|
3585
|
+
renderCardSelectionCheckbox = ({ templateId, selectedIds, isDisabled }) => {
|
|
3586
|
+
if (!this.props.isFullMode || this.props.location.query.type === EMBEDDED) return null;
|
|
3587
|
+
return (
|
|
3588
|
+
<CapCheckbox
|
|
3589
|
+
checked={selectedIds.includes(templateId)}
|
|
3590
|
+
onChange={() => !isDisabled && this.props.actions.toggleTemplateSelection(templateId)}
|
|
3591
|
+
onClick={(e) => e.stopPropagation()}
|
|
3592
|
+
disabled={isDisabled}
|
|
3593
|
+
/>
|
|
3594
|
+
);
|
|
3595
|
+
}
|
|
3596
|
+
|
|
3597
|
+
handleBulkArchiveAction = ({ ids, count, isUnarchive = false }) => {
|
|
3598
|
+
const { intl, actions } = this.props;
|
|
3599
|
+
const { channel } = this.state;
|
|
3600
|
+
const title = isUnarchive
|
|
3601
|
+
? intl.formatMessage(messages.unarchiveTemplates)
|
|
3602
|
+
: intl.formatMessage(messages.archiveTemplates);
|
|
3603
|
+
const action = isUnarchive ? actions.bulkUnarchiveTemplates : actions.bulkArchiveTemplates;
|
|
3604
|
+
const successMessage = (c) => intl.formatMessage(
|
|
3605
|
+
isUnarchive ? messages.bulkUnarchiveSuccess : messages.bulkArchiveSuccess,
|
|
3606
|
+
{ count: c }
|
|
3607
|
+
);
|
|
3608
|
+
this.showArchiveConfirm({
|
|
3609
|
+
title,
|
|
3610
|
+
count,
|
|
3611
|
+
isUnarchive,
|
|
3612
|
+
onConfirm: () => action(channel, ids, successMessage),
|
|
3613
|
+
});
|
|
3614
|
+
};
|
|
3615
|
+
|
|
3616
|
+
handleTemplateArchiveAction = ({ templateId, templateName, isUnarchive = false }) => {
|
|
3617
|
+
const { intl, actions } = this.props;
|
|
3618
|
+
const { channel } = this.state;
|
|
3619
|
+
const title = isUnarchive
|
|
3620
|
+
? intl.formatMessage(messages.unarchiveTemplates)
|
|
3621
|
+
: intl.formatMessage(messages.archiveTemplates);
|
|
3622
|
+
const successMessage = isUnarchive
|
|
3623
|
+
? intl.formatMessage(messages.unarchiveTemplateSuccess)
|
|
3624
|
+
: intl.formatMessage(messages.archiveTemplateSuccess);
|
|
3625
|
+
const action = isUnarchive ? actions.unarchiveTemplate : actions.archiveTemplate;
|
|
3626
|
+
this.showArchiveConfirm({
|
|
3627
|
+
title,
|
|
3628
|
+
count: 1,
|
|
3629
|
+
isUnarchive,
|
|
3630
|
+
onConfirm: () => action(
|
|
3631
|
+
channel,
|
|
3632
|
+
templateId,
|
|
3633
|
+
successMessage,
|
|
3634
|
+
buildTemplateNameDescription(intl.formatMessage(messages.templateNameLabel), templateName)
|
|
3635
|
+
),
|
|
3636
|
+
});
|
|
3637
|
+
};
|
|
3638
|
+
|
|
3639
|
+
// Shared helper for archive/unarchive confirm modals:
|
|
3640
|
+
// - no icon, lighter overlay, Confirm button on left (primary), Cancel on right
|
|
3641
|
+
showArchiveConfirm = ({ title, content, onConfirm, count = 1, isUnarchive = false }) => {
|
|
3642
|
+
const { intl } = this.props;
|
|
3643
|
+
const confirmText = intl.formatMessage(messages.archiveConfirmOk);
|
|
3644
|
+
const cancelText = intl.formatMessage(messages.archiveConfirmCancel);
|
|
3645
|
+
// Derive content from count if not explicitly provided
|
|
3646
|
+
const resolvedContent = content || (isUnarchive
|
|
3647
|
+
? intl.formatMessage(count > 1 ? messages.unarchiveTemplateContent : messages.unarchiveTemplateSingleContent)
|
|
3648
|
+
: intl.formatMessage(count > 1 ? messages.archiveTemplateContent : messages.archiveTemplateSingleContent));
|
|
3649
|
+
// AntD v3 footer order is [cancelButton][okButton]. Swap text+handler so
|
|
3650
|
+
// "Confirm" (primary) appears on the left and "Cancel" (default) on the right.
|
|
3651
|
+
CapModal.confirm({
|
|
3652
|
+
title,
|
|
3653
|
+
content: resolvedContent,
|
|
3654
|
+
icon: ' ',
|
|
3655
|
+
className: 'archive-confirm-modal',
|
|
3656
|
+
maskStyle: { backgroundColor: 'rgba(0, 0, 0, 0.25)' },
|
|
3657
|
+
cancelText: confirmText,
|
|
3658
|
+
okText: cancelText,
|
|
3659
|
+
cancelButtonProps: { type: 'primary' },
|
|
3660
|
+
okButtonProps: { type: 'default' },
|
|
3661
|
+
onCancel: (close) => { onConfirm(); close(); },
|
|
3662
|
+
// onOk (the right "Cancel" button) just closes the modal — default behaviour
|
|
3663
|
+
});
|
|
3664
|
+
}
|
|
3665
|
+
|
|
3462
3666
|
populateTemplatesList = (data, blankTemplateRequired, layoutSelection) => {
|
|
3463
3667
|
if (!data) {
|
|
3464
3668
|
return [];
|
|
@@ -3608,22 +3812,71 @@ return (<div>
|
|
|
3608
3812
|
deleteOption = this.props.intl.formatMessage(messages.unMapButton);
|
|
3609
3813
|
}
|
|
3610
3814
|
if (!layoutSelection) {
|
|
3815
|
+
// Determine archive eligibility for this template:
|
|
3816
|
+
// - Zalo: never eligible
|
|
3817
|
+
// - WhatsApp: not eligible when status is awaitingApproval / pending / unsubmitted
|
|
3818
|
+
// - RCS: not eligible when status is awaitingApproval / pending
|
|
3819
|
+
const templateWhatsappStatus = get(template, `versions.base.content.${WHATSAPP_LOWERCASE}.status`, '');
|
|
3820
|
+
const templateRcsStatus = get(template, 'versions.base.content.RCS.rcsContent.cardContent[0].Status', '');
|
|
3821
|
+
const channelUpCase = this.state.channel.toUpperCase();
|
|
3822
|
+
const isTemplateArchiveEligible = this.isChannelArchiveEligible(channelUpCase, templateWhatsappStatus, templateRcsStatus);
|
|
3823
|
+
|
|
3824
|
+
// Checkbox on card header (full mode only, only for archive-eligible templates)
|
|
3825
|
+
if (this.props.isFullMode && this.props.location.query.type !== EMBEDDED && isTemplateArchiveEligible) {
|
|
3826
|
+
const selectedIds = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
3827
|
+
const selectedIdsArray = selectedIds.toJS ? selectedIds.toJS() : selectedIds;
|
|
3828
|
+
temp.cardTop = (
|
|
3829
|
+
<CapRow type="flex" align="middle" justify="space-between" className="template-card-top-bar">
|
|
3830
|
+
<CapCheckbox
|
|
3831
|
+
checked={selectedIdsArray.includes(template._id)}
|
|
3832
|
+
onChange={() => this.props.actions.toggleTemplateSelection(template._id)}
|
|
3833
|
+
onClick={(e) => e.stopPropagation()}
|
|
3834
|
+
/>
|
|
3835
|
+
</CapRow>
|
|
3836
|
+
);
|
|
3837
|
+
}
|
|
3838
|
+
|
|
3611
3839
|
temp.footer = (
|
|
3612
3840
|
<div className="footer-container">
|
|
3613
3841
|
<div className="card-title">
|
|
3614
3842
|
<span className="template-name" style={{ fontWeight: `${this.state.channel.toLowerCase() === 'wechat' ? '400' : '600'}` }}>
|
|
3615
3843
|
{ 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>}
|
|
3616
3844
|
{template?.name}
|
|
3845
|
+
{commonUtil.hasCreativesArchivalEnabled() && template.isArchived && <CapColoredTag tagColor={CAP_G08} tagTextColor={CAP_G05} className="archived-tag">{this.props.intl.formatMessage(messages.archivedTag)}</CapColoredTag>}
|
|
3617
3846
|
</span>
|
|
3618
|
-
{this.props.location.query.type !==
|
|
3847
|
+
{this.props.location.query.type !== EMBEDDED && <CapPopover
|
|
3619
3848
|
trigger="click"
|
|
3620
3849
|
content={
|
|
3621
3850
|
<div className="popover-content">
|
|
3622
|
-
{this.state.channel !== 'wechat' && <div className="popover-action-container">
|
|
3623
|
-
<
|
|
3851
|
+
{this.state.channel !== 'wechat' && !template.isArchived && <div className="popover-action-container">
|
|
3852
|
+
<CapButton type="link" onClick={() => this.duplicateTemplate(template)} className="popover-action">
|
|
3853
|
+
{this.props.intl.formatMessage(messages.duplicateButton)}
|
|
3854
|
+
</CapButton>
|
|
3855
|
+
</div>}
|
|
3856
|
+
{commonUtil.hasCreativesArchivalEnabled() && this.props.isFullMode && isTemplateArchiveEligible && !template.isArchived && <div className="popover-action-container">
|
|
3857
|
+
<CapButton
|
|
3858
|
+
type="link"
|
|
3859
|
+
onClick={() => this.handleTemplateArchiveAction({ templateId: template._id, templateName: template.name })}
|
|
3860
|
+
className="popover-action popover-archive-action"
|
|
3861
|
+
>
|
|
3862
|
+
<CapIcon type="archive" size="s" />
|
|
3863
|
+
<CapLabel.CapLabelInline type="label1">{this.props.intl.formatMessage(messages.archiveButton)}</CapLabel.CapLabelInline>
|
|
3864
|
+
</CapButton>
|
|
3865
|
+
</div>}
|
|
3866
|
+
{commonUtil.hasCreativesArchivalEnabled() && this.props.isFullMode && isTemplateArchiveEligible && template.isArchived && <div className="popover-action-container">
|
|
3867
|
+
<CapButton
|
|
3868
|
+
type="link"
|
|
3869
|
+
onClick={() => this.handleTemplateArchiveAction({ templateId: template._id, templateName: template.name, isUnarchive: true })}
|
|
3870
|
+
className="popover-action popover-archive-action"
|
|
3871
|
+
>
|
|
3872
|
+
<CapIcon type="archive" size="s" />
|
|
3873
|
+
<CapLabel.CapLabelInline type="label1">{this.props.intl.formatMessage(messages.unarchiveButton)}</CapLabel.CapLabelInline>
|
|
3874
|
+
</CapButton>
|
|
3624
3875
|
</div>}
|
|
3625
3876
|
<div className="popover-action-container">
|
|
3626
|
-
<
|
|
3877
|
+
<CapButton type="link" onClick={() => this.toggleDeleteTemplateModal(template)} className="popover-action">
|
|
3878
|
+
{deleteOption}
|
|
3879
|
+
</CapButton>
|
|
3627
3880
|
</div>
|
|
3628
3881
|
</div>
|
|
3629
3882
|
}
|
|
@@ -3676,7 +3929,20 @@ return (<div>
|
|
|
3676
3929
|
return false;
|
|
3677
3930
|
}
|
|
3678
3931
|
}
|
|
3679
|
-
isFullMode = () => this.props.location.query.type !==
|
|
3932
|
+
isFullMode = () => this.props.location.query.type !== EMBEDDED || this.props.isFullMode
|
|
3933
|
+
|
|
3934
|
+
isChannelArchiveEligible = (channel, whatsappStatus, rcsStatus) => (
|
|
3935
|
+
channel !== ZALO &&
|
|
3936
|
+
!(channel === WHATSAPP && [WHATSAPP_STATUSES.awaitingApproval, WHATSAPP_STATUSES.pending, WHATSAPP_STATUSES.unsubmitted].includes(whatsappStatus)) &&
|
|
3937
|
+
!(channel === RCS && [RCS_STATUSES.awaitingApproval, RCS_STATUSES.pending].includes(rcsStatus))
|
|
3938
|
+
)
|
|
3939
|
+
|
|
3940
|
+
setArchivedMode = (isArchived) => {
|
|
3941
|
+
this.props.actions.setArchivedMode(isArchived);
|
|
3942
|
+
this.setState({ searchText: '', page: 1 }, () => {
|
|
3943
|
+
this.getAllTemplates({ params: { name: '', sortBy: this.state.sortBy, archiveStatus: isArchived ? ARCHIVE_STATUS_ARCHIVED : ARCHIVE_STATUS_ACTIVE }, resetPage: true }, true);
|
|
3944
|
+
});
|
|
3945
|
+
}
|
|
3680
3946
|
isCreateDisabled = () => {
|
|
3681
3947
|
let isDisabled = this.isLoading();
|
|
3682
3948
|
const channel = this.state.channel.toUpperCase();
|
|
@@ -4214,11 +4480,17 @@ return (<div>
|
|
|
4214
4480
|
if (([WHATSAPP_LOWERCASE, ZALO_LOWERCASE, RCS_LOWERCASE].includes(this.state?.channel?.toLocaleLowerCase()) && isEmpty(this.state?.hostName))) {
|
|
4215
4481
|
isfilterContentVisisble = false;
|
|
4216
4482
|
}
|
|
4483
|
+
const _isArchivalEnabled = commonUtil.hasCreativesArchivalEnabled();
|
|
4484
|
+
const _isArchivedMode = _isArchivalEnabled && get(this.props, 'Templates.isArchivedMode', false);
|
|
4485
|
+
const _renderSelectedIds = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
4486
|
+
const _renderSelectedIdsArray = _renderSelectedIds && typeof _renderSelectedIds.toJS === 'function' ? _renderSelectedIds.toJS() : (Array.isArray(_renderSelectedIds) ? _renderSelectedIds : []);
|
|
4487
|
+
const _renderHasSelection = _isArchivalEnabled && this.props.isFullMode && _renderSelectedIdsArray.length > 0;
|
|
4488
|
+
|
|
4217
4489
|
const filterContent = (( isfilterContentVisisble || [WECHAT, MOBILE_PUSH, INAPP].includes(this.state.channel.toUpperCase())) && <div className="action-container">
|
|
4218
4490
|
{isfilterContentVisisble && <CapInput.Search
|
|
4219
4491
|
className="search-text"
|
|
4220
4492
|
style={{width: '210px'}}
|
|
4221
|
-
placeholder={this.props.intl.formatMessage(messages.searchText)}
|
|
4493
|
+
placeholder={_isArchivedMode ? this.props.intl.formatMessage(messages.searchArchivedTemplates) : this.props.intl.formatMessage(messages.searchText)}
|
|
4222
4494
|
value={this.state.searchText}
|
|
4223
4495
|
onChange={(e) => this.searchTemplate(e.target.value, this.state.channel)}
|
|
4224
4496
|
disabled={this.checkSearchDisabled()}
|
|
@@ -4370,9 +4642,9 @@ return (<div>
|
|
|
4370
4642
|
</div>
|
|
4371
4643
|
)
|
|
4372
4644
|
}
|
|
4373
|
-
<div
|
|
4374
|
-
{
|
|
4375
|
-
this.state?.channel?.toLowerCase() === WHATSAPP_LOWERCASE && (isWhatsappCountExeeded)? (
|
|
4645
|
+
<div className="template-listing-header-actions">
|
|
4646
|
+
{!_isArchivedMode && !_renderHasSelection && (
|
|
4647
|
+
this.state?.channel?.toLowerCase() === WHATSAPP_LOWERCASE && (isWhatsappCountExeeded) ? (
|
|
4376
4648
|
<CapTooltip title={whatsappCountExceedText}>
|
|
4377
4649
|
<div className="button-disabled-tooltip-wrapper">
|
|
4378
4650
|
{createButton}
|
|
@@ -4380,9 +4652,29 @@ return (<div>
|
|
|
4380
4652
|
</CapTooltip>
|
|
4381
4653
|
)
|
|
4382
4654
|
: isfilterContentVisisble && !isWechatEmbedded && !this.props.isDltFromRcs && createButton
|
|
4383
|
-
}
|
|
4655
|
+
)}
|
|
4656
|
+
{/* More (⋯) menu: full mode only, not archived mode, not Zalo (no archive support), not when selection active, archive flag enabled */}
|
|
4657
|
+
{commonUtil.hasCreativesArchivalEnabled() && !_isArchivedMode && !_renderHasSelection && this.props.isFullMode && this.props.location.query.type !== EMBEDDED && channelLowerCase !== ZALO_LOWERCASE && (
|
|
4658
|
+
<CapDropdown
|
|
4659
|
+
trigger={['click']}
|
|
4660
|
+
overlay={
|
|
4661
|
+
<CapMenu>
|
|
4662
|
+
<CapMenu.Item
|
|
4663
|
+
key="archived"
|
|
4664
|
+
onClick={() => this.setArchivedMode(true)}
|
|
4665
|
+
>
|
|
4666
|
+
<FormattedMessage {...messages.archivedTemplates} />
|
|
4667
|
+
</CapMenu.Item>
|
|
4668
|
+
</CapMenu>
|
|
4669
|
+
}
|
|
4670
|
+
placement="bottomRight"
|
|
4671
|
+
>
|
|
4672
|
+
<CapButton type="flat" className="template-listing-more-btn">
|
|
4673
|
+
<CapIcon type="more" />
|
|
4674
|
+
</CapButton>
|
|
4675
|
+
</CapDropdown>
|
|
4676
|
+
)}
|
|
4384
4677
|
</div>
|
|
4385
|
-
|
|
4386
4678
|
</div>);
|
|
4387
4679
|
let htmlPreviewContent = "";
|
|
4388
4680
|
if (this.state.channel.toLowerCase() === 'ebill') {
|
|
@@ -4431,6 +4723,18 @@ return (<div>
|
|
|
4431
4723
|
}
|
|
4432
4724
|
/>
|
|
4433
4725
|
|
|
4726
|
+
{/* Archived mode header with back arrow (full mode only, archive flag enabled) */}
|
|
4727
|
+
{commonUtil.hasCreativesArchivalEnabled() && this.props.isFullMode && get(this.props, 'Templates.isArchivedMode', false) && (
|
|
4728
|
+
<CapRow type="flex" align="middle" className="archived-mode-header">
|
|
4729
|
+
<CapIcon
|
|
4730
|
+
type="back"
|
|
4731
|
+
className="archived-mode-back-icon"
|
|
4732
|
+
onClick={() => this.setArchivedMode(false)}
|
|
4733
|
+
/>
|
|
4734
|
+
<CapHeading type="h3"><FormattedMessage {...messages.archivedTemplates} /></CapHeading>
|
|
4735
|
+
</CapRow>
|
|
4736
|
+
)}
|
|
4737
|
+
|
|
4434
4738
|
{channel.toLowerCase() === WHATSAPP_LOWERCASE &&
|
|
4435
4739
|
showWhatsappCountWarning ? (
|
|
4436
4740
|
<CapAlert message={whatsappCountExceedText} type="info" />
|