@capillarytech/creatives-library 8.0.348 → 8.0.349
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/services/api.js +20 -0
- package/services/tests/api.test.js +59 -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 +179 -24
- package/v2Containers/Templates/actions.js +44 -0
- package/v2Containers/Templates/constants.js +31 -0
- package/v2Containers/Templates/index.js +361 -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 +1300 -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,58 @@ 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 isCardArchiveEligible = this.isChannelArchiveEligible(currentChannel, cardWhatsappStatus, cardRcsStatus);
|
|
1942
|
+
const isArchivedMode = get(this.props, 'Templates.isArchivedMode', false);
|
|
1943
|
+
const isAnyArchiveInProgress = !!(get(this.props, 'Templates.archiveInProgress') || get(this.props, 'Templates.unarchiveInProgress') || get(this.props, 'Templates.bulkArchiveInProgress') || get(this.props, 'Templates.bulkUnarchiveInProgress'));
|
|
1903
1944
|
const templateData = {
|
|
1904
1945
|
key: `${currentChannel}-card-${template?.name}`,
|
|
1905
1946
|
title: (
|
|
1906
|
-
<span
|
|
1907
|
-
{template
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
INAPP_LAYOUT_DETAILS[inappBodyType]?.
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1947
|
+
<span className="template-card-title">
|
|
1948
|
+
{isCardArchiveEligible && this.renderCardSelectionCheckbox({ templateId: template._id, selectedIds: selectedIdsArrayForCard, isDisabled: isAnyArchiveInProgress })}
|
|
1949
|
+
<CapLabel.CapLabelInline type="label1" title={template?.name} className="template-card-name">
|
|
1950
|
+
{template?.name}
|
|
1951
|
+
{currentChannel === INAPP && (
|
|
1952
|
+
<CapRow>
|
|
1953
|
+
<CapColoredTag
|
|
1954
|
+
tagColor={INAPP_LAYOUT_DETAILS[inappBodyType]?.tagColor}
|
|
1955
|
+
tagTextColor={
|
|
1956
|
+
INAPP_LAYOUT_DETAILS[inappBodyType]?.tagTextColor
|
|
1957
|
+
}
|
|
1958
|
+
tagHeight="1.25rem"
|
|
1959
|
+
tagFontSize="0.857rem"
|
|
1960
|
+
>
|
|
1961
|
+
{INAPP_LAYOUT_DETAILS[inappBodyType]?.text}
|
|
1962
|
+
</CapColoredTag>
|
|
1963
|
+
</CapRow>
|
|
1964
|
+
)}
|
|
1965
|
+
</CapLabel.CapLabelInline>
|
|
1922
1966
|
</span>
|
|
1923
1967
|
),
|
|
1924
|
-
extra: [
|
|
1968
|
+
extra: isArchivedMode ? [] : [
|
|
1925
1969
|
// Hide preview icon for channels that support Test and Preview
|
|
1926
1970
|
// Show preview icon only for channels that don't support Test and Preview
|
|
1927
1971
|
(() => {
|
|
1928
1972
|
// Channels that have Test and Preview integrated
|
|
1929
1973
|
const testAndPreviewChannels = [EMAIL, SMS, WHATSAPP, RCS, INAPP, MOBILE_PUSH, VIBER, ZALO];
|
|
1930
1974
|
const isTestAndPreviewSupported = testAndPreviewChannels.includes(currentChannel.toUpperCase());
|
|
1931
|
-
|
|
1975
|
+
|
|
1932
1976
|
// Don't show preview icon if channel supports Test and Preview
|
|
1933
1977
|
if (isTestAndPreviewSupported) {
|
|
1934
1978
|
return null;
|
|
1935
1979
|
}
|
|
1936
|
-
|
|
1980
|
+
|
|
1937
1981
|
// Show preview icon for other channels (e.g., WeChat, Line, Facebook, Ebill)
|
|
1938
1982
|
if (currentChannel === ZALO && isZaloPreviewLoading) {
|
|
1939
1983
|
return (
|
|
1940
1984
|
<CapSpin style={{ marginRight: "16px", position: "static", display: "inline" }} spinning />
|
|
1941
1985
|
);
|
|
1942
1986
|
}
|
|
1943
|
-
|
|
1987
|
+
|
|
1944
1988
|
return this.getHoverComponent(
|
|
1945
1989
|
<CapIcon
|
|
1946
1990
|
className={`view-${channelLowerCase}`}
|
|
@@ -1960,7 +2004,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1960
2004
|
);
|
|
1961
2005
|
})()
|
|
1962
2006
|
],
|
|
1963
|
-
hoverOption: (
|
|
2007
|
+
hoverOption: isArchivedMode ? null : (
|
|
1964
2008
|
<CapButton
|
|
1965
2009
|
className={
|
|
1966
2010
|
this.props.isFullMode
|
|
@@ -2000,8 +2044,8 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2000
2044
|
<CapDropdown
|
|
2001
2045
|
overlay={
|
|
2002
2046
|
<CapMenu>
|
|
2003
|
-
{/* Phase 16: Test and Preview menu item - Show for supported channels */}
|
|
2004
|
-
{(this.isTestAndPreviewSupported() ||
|
|
2047
|
+
{/* Phase 16: Test and Preview menu item - Show for supported channels, hide in archived mode */}
|
|
2048
|
+
{!isArchivedMode && (this.isTestAndPreviewSupported() ||
|
|
2005
2049
|
(this.state.channel.toUpperCase() === WHATSAPP &&
|
|
2006
2050
|
status === WHATSAPP_STATUSES.approved) || (this.state.channel.toUpperCase() === RCS &&
|
|
2007
2051
|
rcsStatus === RCS_STATUSES.approved)) && (
|
|
@@ -2024,7 +2068,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2024
2068
|
{![WECHAT, WHATSAPP, ZALO].includes(
|
|
2025
2069
|
this.state.channel.toUpperCase()
|
|
2026
2070
|
) &&
|
|
2027
|
-
!isTraiDltFeature && (
|
|
2071
|
+
!isTraiDltFeature && !template.isArchived && (
|
|
2028
2072
|
<CapMenu.Item
|
|
2029
2073
|
className={`duplicate-${channelLowerCase}`}
|
|
2030
2074
|
onClick={() => this.duplicateTemplate(template)}
|
|
@@ -2032,6 +2076,26 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2032
2076
|
<FormattedMessage {...messages.duplicateButton} />
|
|
2033
2077
|
</CapMenu.Item>
|
|
2034
2078
|
)}
|
|
2079
|
+
{/* Archive/Unarchive menu item (full mode only, not for Zalo, not for WhatsApp/RCS awaiting/pending) */}
|
|
2080
|
+
{(() => {
|
|
2081
|
+
const channelUp = this.state.channel.toUpperCase();
|
|
2082
|
+
if (!this.isChannelArchiveEligible(channelUp, status, rcsStatus)) return null;
|
|
2083
|
+
return !template?.isArchived ? (
|
|
2084
|
+
<CapMenu.Item
|
|
2085
|
+
className={`archive-${channelLowerCase}`}
|
|
2086
|
+
onClick={() => this.handleTemplateArchiveAction({ templateId: template._id, templateName: template.name })}
|
|
2087
|
+
>
|
|
2088
|
+
<FormattedMessage {...messages.archiveButton} />
|
|
2089
|
+
</CapMenu.Item>
|
|
2090
|
+
) : (
|
|
2091
|
+
<CapMenu.Item
|
|
2092
|
+
className={`unarchive-${channelLowerCase}`}
|
|
2093
|
+
onClick={() => this.handleTemplateArchiveAction({ templateId: template._id, templateName: template.name, isUnarchive: true })}
|
|
2094
|
+
>
|
|
2095
|
+
<FormattedMessage {...messages.unarchiveButton} />
|
|
2096
|
+
</CapMenu.Item>
|
|
2097
|
+
);
|
|
2098
|
+
})()}
|
|
2035
2099
|
{/* Delete/Unmap menu item */}
|
|
2036
2100
|
{(!(
|
|
2037
2101
|
this.state.channel.toUpperCase() === WHATSAPP &&
|
|
@@ -2312,7 +2376,8 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2312
2376
|
case WHATSAPP: {
|
|
2313
2377
|
const { whatsappImageSrc = '', templateMsg, docPreview, whatsappVideoPreviewImg = '', templateHeaderPreview, templateFooterPreview, carouselData = [] } = getWhatsappContent(template);
|
|
2314
2378
|
templateData.title = (
|
|
2315
|
-
<CapRow>
|
|
2379
|
+
<CapRow type="flex" align="middle">
|
|
2380
|
+
{isCardArchiveEligible && this.renderCardSelectionCheckbox({ templateId: template._id, selectedIds: selectedIdsArrayForCard, isDisabled: isAnyArchiveInProgress })}
|
|
2316
2381
|
<CapLabel className="whatsapp-rcs-template-name">{template?.name}</CapLabel>
|
|
2317
2382
|
<WhatsappStatusContainer template={template} />
|
|
2318
2383
|
</CapRow>
|
|
@@ -2405,7 +2470,8 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2405
2470
|
const name = get(template, "name", "");
|
|
2406
2471
|
const statusDisplay=getRcsStatusType(status);
|
|
2407
2472
|
templateData.title = (
|
|
2408
|
-
<CapRow>
|
|
2473
|
+
<CapRow type="flex" align="middle">
|
|
2474
|
+
{isCardArchiveEligible && this.renderCardSelectionCheckbox({ templateId: template._id, selectedIds: selectedIdsArrayForCard, isDisabled: isAnyArchiveInProgress })}
|
|
2409
2475
|
<CapLabel className="whatsapp-rcs-template-name">{name}</CapLabel>
|
|
2410
2476
|
<CapRow type="flex" align="middle" className="rcs-status-container zalo-status-color">
|
|
2411
2477
|
<CapStatus
|
|
@@ -2529,7 +2595,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2529
2595
|
|
|
2530
2596
|
//no templates available
|
|
2531
2597
|
const showIllustrationForChannel = (forChannel) => {
|
|
2532
|
-
return forChannel === channelLowerCase && isEmpty(templates) && isEmpty(this.state.searchText) && !isLoading;
|
|
2598
|
+
return forChannel === channelLowerCase && isEmpty(templates) && isEmpty(this.state.searchText) && !isLoading && !get(this.props, 'Templates.isArchivedMode', false);
|
|
2533
2599
|
}
|
|
2534
2600
|
//when filters applied not matching templates
|
|
2535
2601
|
const filteredEmptyAndFullModeAs = (fullModeValue) => {
|
|
@@ -2547,6 +2613,11 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2547
2613
|
const accountId = get(this.props, 'Templates.selectedWeChatAccount.uuid');
|
|
2548
2614
|
const accounts = get(this.props, 'Templates.weCrmAccounts');
|
|
2549
2615
|
const getAllTemplatesInProgress = get(this.props, 'Templates.getAllTemplatesInProgress');
|
|
2616
|
+
const archiveListingRefreshType = get(this.props, 'Templates.archiveListingRefreshType', null);
|
|
2617
|
+
const isArchiveOperationInProgress = get(this.props, 'Templates.archiveInProgress', false)
|
|
2618
|
+
|| get(this.props, 'Templates.unarchiveInProgress', false)
|
|
2619
|
+
|| get(this.props, 'Templates.bulkArchiveInProgress', false)
|
|
2620
|
+
|| get(this.props, 'Templates.bulkUnarchiveInProgress', false);
|
|
2550
2621
|
|
|
2551
2622
|
const noWhatsappZaloTemplates = this.isFullMode() && isEmpty(templates) || !this.state.hostName;
|
|
2552
2623
|
const noApprovedWhatsappZaloTemplates = filteredEmptyAndFullModeAs(false) && !isEmpty(this.state?.hostName);
|
|
@@ -2555,9 +2626,36 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2555
2626
|
|
|
2556
2627
|
const noLoaderAndSearchText = isEmpty(this.state.searchText) && !isLoading;
|
|
2557
2628
|
|
|
2558
|
-
|
|
2629
|
+
const isArchivedModeLocal = get(this.props, 'Templates.isArchivedMode', false);
|
|
2630
|
+
const selectedIdsLocal = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
2631
|
+
const selectedIdsArrayLocal = selectedIdsLocal && typeof selectedIdsLocal.toJS === 'function' ? selectedIdsLocal.toJS() : (Array.isArray(selectedIdsLocal) ? selectedIdsLocal : []);
|
|
2632
|
+
const selectedCountLocal = selectedIdsArrayLocal.length;
|
|
2633
|
+
const hasSelectionLocal = this.props.isFullMode && selectedCountLocal > 0;
|
|
2634
|
+
|
|
2635
|
+
return (<div>
|
|
2559
2636
|
{[WECHAT, MOBILE_PUSH, WEBPUSH, INAPP, WHATSAPP, ZALO, RCS].includes(currentChannel) && this.showAccountName()}
|
|
2560
|
-
|
|
2637
|
+
<CapRow type="flex" align="middle" justify="space-between" className="filter-row">
|
|
2638
|
+
<div className="filter-row-content">{filterContent}</div>
|
|
2639
|
+
{hasSelectionLocal && (
|
|
2640
|
+
<CapRow type="flex" align="middle" className="bulk-selection-bar">
|
|
2641
|
+
<CapLabel type="label2">
|
|
2642
|
+
{this.props.intl.formatMessage(messages.templatesSelected, { count: selectedCountLocal })}
|
|
2643
|
+
</CapLabel>
|
|
2644
|
+
<CapButton
|
|
2645
|
+
type="primary"
|
|
2646
|
+
prefix={<CapIcon type="archive" size="l" />}
|
|
2647
|
+
onClick={() => this.handleBulkArchiveAction({ ids: selectedIdsArrayLocal, count: selectedCountLocal, isUnarchive: isArchivedModeLocal })}
|
|
2648
|
+
>
|
|
2649
|
+
<span className="archive-btn-label">
|
|
2650
|
+
<FormattedMessage {...(isArchivedModeLocal ? messages.unarchiveButton : messages.archiveButton)} />
|
|
2651
|
+
</span>
|
|
2652
|
+
</CapButton>
|
|
2653
|
+
<CapButton type="secondary" onClick={() => this.props.actions.clearTemplateSelection()}>
|
|
2654
|
+
<FormattedMessage {...messages.archiveConfirmCancel} />
|
|
2655
|
+
</CapButton>
|
|
2656
|
+
</CapRow>
|
|
2657
|
+
)}
|
|
2658
|
+
</CapRow>
|
|
2561
2659
|
{[WHATSAPP, ZALO, INAPP,RCS].includes(currentChannel) && this.selectedFilters()}
|
|
2562
2660
|
{<div>
|
|
2563
2661
|
{!isEmpty(filteredTemplates) || !isEmpty(this.state.searchText) || !isEmpty(this.props.Templates.templateError) ? (
|
|
@@ -2570,7 +2668,7 @@ return (<div>
|
|
|
2570
2668
|
fbType={"list"}
|
|
2571
2669
|
/>
|
|
2572
2670
|
</div>)
|
|
2573
|
-
: [SMS_LOWERCASE, EMAIL_LOWERCASE].includes(this.state.channel.toLowerCase()) && !isLoading && this.getSmsEmailIllustration()
|
|
2671
|
+
: [SMS_LOWERCASE, EMAIL_LOWERCASE].includes(this.state.channel.toLowerCase()) && !isLoading && !get(this.props, 'Templates.isArchivedMode', false) && this.getSmsEmailIllustration()
|
|
2574
2672
|
}
|
|
2575
2673
|
|
|
2576
2674
|
{(this.state.selectedAccount === '' && isEmpty(this.props.Templates.selectedWeChatAccount)) && ([WECHAT_LOWERCASE, MOBILE_PUSH_LOWERCASE, INAPP_LOWERCASE].includes(this.state.channel.toLowerCase())) &&
|
|
@@ -2594,7 +2692,7 @@ return (<div>
|
|
|
2594
2692
|
</div>
|
|
2595
2693
|
)
|
|
2596
2694
|
}
|
|
2597
|
-
{(showWhatsappIllustration || showZaloIllustration) && (
|
|
2695
|
+
{(showWhatsappIllustration || showZaloIllustration) && !get(this.props, 'Templates.isArchivedMode', false) && (
|
|
2598
2696
|
noLoaderAndSearchText &&
|
|
2599
2697
|
<div style={this.isFullMode() ? { height: "calc(100vh - 325px)", overflow: 'auto' } : {}}>
|
|
2600
2698
|
{noWhatsappZaloTemplates && <ChannelTypeIllustration isFullMode={this.props.isFullMode} createTemplate={this.createTemplate} currentChannel={currentChannel} hostName={this.state?.hostName}/>}
|
|
@@ -2635,8 +2733,27 @@ return (<div>
|
|
|
2635
2733
|
<ChannelTypeIllustration isFullMode={this.props.isFullMode} createTemplate={this.createTemplate} currentChannel={currentChannel} hostName={this.state?.hostName}/>
|
|
2636
2734
|
</div>
|
|
2637
2735
|
}
|
|
2736
|
+
{get(this.props, 'Templates.isArchivedMode', false) && isEmpty(templates) && !isLoading && !getAllTemplatesInProgress && isEmpty(this.state.searchText) && (
|
|
2737
|
+
<CapRow className={this.isFullMode() ? 'illustration-scroll-wrapper' : ''}>
|
|
2738
|
+
<ChannelTypeIllustration
|
|
2739
|
+
isFullMode={this.props.isFullMode}
|
|
2740
|
+
createTemplate={this.createTemplate}
|
|
2741
|
+
currentChannel={currentChannel}
|
|
2742
|
+
isArchivedMode
|
|
2743
|
+
/>
|
|
2744
|
+
</CapRow>
|
|
2745
|
+
)}
|
|
2638
2746
|
{<CapCustomSkeleton loader={isInitialLoading && (isLoading || getAllTemplatesInProgress)} />}
|
|
2639
|
-
{
|
|
2747
|
+
{!isInitialLoading && getAllTemplatesInProgress && archiveListingRefreshType ? (
|
|
2748
|
+
<div className="archive-listing-spinner">
|
|
2749
|
+
<CapSpin spinning />
|
|
2750
|
+
<CapLabel.CapLabelInline type="label1">
|
|
2751
|
+
{archiveListingRefreshType === ARCHIVE_REFRESH_TYPE_ARCHIVE ? this.props.intl.formatMessage(messages.archivalInProgress) : this.props.intl.formatMessage(messages.unarchivalInProgress)}
|
|
2752
|
+
</CapLabel.CapLabelInline>
|
|
2753
|
+
</div>
|
|
2754
|
+
) : (
|
|
2755
|
+
<CapPageSpinner spinning={!isInitialLoading && (isLoading || getAllTemplatesInProgress)} />
|
|
2756
|
+
)}
|
|
2640
2757
|
</div>
|
|
2641
2758
|
}
|
|
2642
2759
|
</div>);
|
|
@@ -3278,6 +3395,10 @@ return (<div>
|
|
|
3278
3395
|
};
|
|
3279
3396
|
|
|
3280
3397
|
handleEditClick(e, template, modeType, path, options) {
|
|
3398
|
+
if (template && template.isArchived) {
|
|
3399
|
+
CapNotification.error({ message: this.props.intl.formatMessage(messages.cannotEditArchivedTemplate) });
|
|
3400
|
+
return;
|
|
3401
|
+
}
|
|
3281
3402
|
if (modeType && modeType !== undefined) {
|
|
3282
3403
|
this.setState({modeType});
|
|
3283
3404
|
}
|
|
@@ -3459,6 +3580,87 @@ return (<div>
|
|
|
3459
3580
|
this.setState({showModal: false});
|
|
3460
3581
|
}
|
|
3461
3582
|
|
|
3583
|
+
renderCardSelectionCheckbox = ({ templateId, selectedIds, isDisabled }) => {
|
|
3584
|
+
if (!this.props.isFullMode || this.props.location.query.type === EMBEDDED) return null;
|
|
3585
|
+
return (
|
|
3586
|
+
<CapCheckbox
|
|
3587
|
+
checked={selectedIds.includes(templateId)}
|
|
3588
|
+
onChange={() => !isDisabled && this.props.actions.toggleTemplateSelection(templateId)}
|
|
3589
|
+
onClick={(e) => e.stopPropagation()}
|
|
3590
|
+
disabled={isDisabled}
|
|
3591
|
+
/>
|
|
3592
|
+
);
|
|
3593
|
+
}
|
|
3594
|
+
|
|
3595
|
+
handleBulkArchiveAction = ({ ids, count, isUnarchive = false }) => {
|
|
3596
|
+
const { intl, actions } = this.props;
|
|
3597
|
+
const { channel } = this.state;
|
|
3598
|
+
const title = isUnarchive
|
|
3599
|
+
? intl.formatMessage(messages.unarchiveTemplates)
|
|
3600
|
+
: intl.formatMessage(messages.archiveTemplates);
|
|
3601
|
+
const action = isUnarchive ? actions.bulkUnarchiveTemplates : actions.bulkArchiveTemplates;
|
|
3602
|
+
const successMessage = (c) => intl.formatMessage(
|
|
3603
|
+
isUnarchive ? messages.bulkUnarchiveSuccess : messages.bulkArchiveSuccess,
|
|
3604
|
+
{ count: c }
|
|
3605
|
+
);
|
|
3606
|
+
this.showArchiveConfirm({
|
|
3607
|
+
title,
|
|
3608
|
+
count,
|
|
3609
|
+
isUnarchive,
|
|
3610
|
+
onConfirm: () => action(channel, ids, successMessage),
|
|
3611
|
+
});
|
|
3612
|
+
};
|
|
3613
|
+
|
|
3614
|
+
handleTemplateArchiveAction = ({ templateId, templateName, isUnarchive = false }) => {
|
|
3615
|
+
const { intl, actions } = this.props;
|
|
3616
|
+
const { channel } = this.state;
|
|
3617
|
+
const title = isUnarchive
|
|
3618
|
+
? intl.formatMessage(messages.unarchiveTemplates)
|
|
3619
|
+
: intl.formatMessage(messages.archiveTemplates);
|
|
3620
|
+
const successMessage = isUnarchive
|
|
3621
|
+
? intl.formatMessage(messages.unarchiveTemplateSuccess)
|
|
3622
|
+
: intl.formatMessage(messages.archiveTemplateSuccess);
|
|
3623
|
+
const action = isUnarchive ? actions.unarchiveTemplate : actions.archiveTemplate;
|
|
3624
|
+
this.showArchiveConfirm({
|
|
3625
|
+
title,
|
|
3626
|
+
count: 1,
|
|
3627
|
+
isUnarchive,
|
|
3628
|
+
onConfirm: () => action(
|
|
3629
|
+
channel,
|
|
3630
|
+
templateId,
|
|
3631
|
+
successMessage,
|
|
3632
|
+
buildTemplateNameDescription(intl.formatMessage(messages.templateNameLabel), templateName)
|
|
3633
|
+
),
|
|
3634
|
+
});
|
|
3635
|
+
};
|
|
3636
|
+
|
|
3637
|
+
// Shared helper for archive/unarchive confirm modals:
|
|
3638
|
+
// - no icon, lighter overlay, Confirm button on left (primary), Cancel on right
|
|
3639
|
+
showArchiveConfirm = ({ title, content, onConfirm, count = 1, isUnarchive = false }) => {
|
|
3640
|
+
const { intl } = this.props;
|
|
3641
|
+
const confirmText = intl.formatMessage(messages.archiveConfirmOk);
|
|
3642
|
+
const cancelText = intl.formatMessage(messages.archiveConfirmCancel);
|
|
3643
|
+
// Derive content from count if not explicitly provided
|
|
3644
|
+
const resolvedContent = content || (isUnarchive
|
|
3645
|
+
? intl.formatMessage(count > 1 ? messages.unarchiveTemplateContent : messages.unarchiveTemplateSingleContent)
|
|
3646
|
+
: intl.formatMessage(count > 1 ? messages.archiveTemplateContent : messages.archiveTemplateSingleContent));
|
|
3647
|
+
// AntD v3 footer order is [cancelButton][okButton]. Swap text+handler so
|
|
3648
|
+
// "Confirm" (primary) appears on the left and "Cancel" (default) on the right.
|
|
3649
|
+
CapModal.confirm({
|
|
3650
|
+
title,
|
|
3651
|
+
content: resolvedContent,
|
|
3652
|
+
icon: ' ',
|
|
3653
|
+
className: 'archive-confirm-modal',
|
|
3654
|
+
maskStyle: { backgroundColor: 'rgba(0, 0, 0, 0.25)' },
|
|
3655
|
+
cancelText: confirmText,
|
|
3656
|
+
okText: cancelText,
|
|
3657
|
+
cancelButtonProps: { type: 'primary' },
|
|
3658
|
+
okButtonProps: { type: 'default' },
|
|
3659
|
+
onCancel: (close) => { onConfirm(); close(); },
|
|
3660
|
+
// onOk (the right "Cancel" button) just closes the modal — default behaviour
|
|
3661
|
+
});
|
|
3662
|
+
}
|
|
3663
|
+
|
|
3462
3664
|
populateTemplatesList = (data, blankTemplateRequired, layoutSelection) => {
|
|
3463
3665
|
if (!data) {
|
|
3464
3666
|
return [];
|
|
@@ -3608,22 +3810,71 @@ return (<div>
|
|
|
3608
3810
|
deleteOption = this.props.intl.formatMessage(messages.unMapButton);
|
|
3609
3811
|
}
|
|
3610
3812
|
if (!layoutSelection) {
|
|
3813
|
+
// Determine archive eligibility for this template:
|
|
3814
|
+
// - Zalo: never eligible
|
|
3815
|
+
// - WhatsApp: not eligible when status is awaitingApproval / pending / unsubmitted
|
|
3816
|
+
// - RCS: not eligible when status is awaitingApproval / pending
|
|
3817
|
+
const templateWhatsappStatus = get(template, `versions.base.content.${WHATSAPP_LOWERCASE}.status`, '');
|
|
3818
|
+
const templateRcsStatus = get(template, 'versions.base.content.RCS.rcsContent.cardContent[0].Status', '');
|
|
3819
|
+
const channelUpCase = this.state.channel.toUpperCase();
|
|
3820
|
+
const isTemplateArchiveEligible = this.isChannelArchiveEligible(channelUpCase, templateWhatsappStatus, templateRcsStatus);
|
|
3821
|
+
|
|
3822
|
+
// Checkbox on card header (full mode only, only for archive-eligible templates)
|
|
3823
|
+
if (this.props.isFullMode && this.props.location.query.type !== EMBEDDED && isTemplateArchiveEligible) {
|
|
3824
|
+
const selectedIds = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
3825
|
+
const selectedIdsArray = selectedIds.toJS ? selectedIds.toJS() : selectedIds;
|
|
3826
|
+
temp.cardTop = (
|
|
3827
|
+
<CapRow type="flex" align="middle" justify="space-between" className="template-card-top-bar">
|
|
3828
|
+
<CapCheckbox
|
|
3829
|
+
checked={selectedIdsArray.includes(template._id)}
|
|
3830
|
+
onChange={() => this.props.actions.toggleTemplateSelection(template._id)}
|
|
3831
|
+
onClick={(e) => e.stopPropagation()}
|
|
3832
|
+
/>
|
|
3833
|
+
</CapRow>
|
|
3834
|
+
);
|
|
3835
|
+
}
|
|
3836
|
+
|
|
3611
3837
|
temp.footer = (
|
|
3612
3838
|
<div className="footer-container">
|
|
3613
3839
|
<div className="card-title">
|
|
3614
3840
|
<span className="template-name" style={{ fontWeight: `${this.state.channel.toLowerCase() === 'wechat' ? '400' : '600'}` }}>
|
|
3615
3841
|
{ 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
3842
|
{template?.name}
|
|
3843
|
+
{template.isArchived && <CapColoredTag tagColor={CAP_G08} tagTextColor={CAP_G05} className="archived-tag">{this.props.intl.formatMessage(messages.archivedTag)}</CapColoredTag>}
|
|
3617
3844
|
</span>
|
|
3618
|
-
{this.props.location.query.type !==
|
|
3845
|
+
{this.props.location.query.type !== EMBEDDED && <CapPopover
|
|
3619
3846
|
trigger="click"
|
|
3620
3847
|
content={
|
|
3621
3848
|
<div className="popover-content">
|
|
3622
|
-
{this.state.channel !== 'wechat' && <div className="popover-action-container">
|
|
3623
|
-
<
|
|
3849
|
+
{this.state.channel !== 'wechat' && !template.isArchived && <div className="popover-action-container">
|
|
3850
|
+
<CapButton type="link" onClick={() => this.duplicateTemplate(template)} className="popover-action">
|
|
3851
|
+
{this.props.intl.formatMessage(messages.duplicateButton)}
|
|
3852
|
+
</CapButton>
|
|
3853
|
+
</div>}
|
|
3854
|
+
{this.props.isFullMode && isTemplateArchiveEligible && !template.isArchived && <div className="popover-action-container">
|
|
3855
|
+
<CapButton
|
|
3856
|
+
type="link"
|
|
3857
|
+
onClick={() => this.handleTemplateArchiveAction({ templateId: template._id, templateName: template.name })}
|
|
3858
|
+
className="popover-action popover-archive-action"
|
|
3859
|
+
>
|
|
3860
|
+
<CapIcon type="archive" size="s" />
|
|
3861
|
+
<CapLabel.CapLabelInline type="label1">{this.props.intl.formatMessage(messages.archiveButton)}</CapLabel.CapLabelInline>
|
|
3862
|
+
</CapButton>
|
|
3863
|
+
</div>}
|
|
3864
|
+
{this.props.isFullMode && isTemplateArchiveEligible && template.isArchived && <div className="popover-action-container">
|
|
3865
|
+
<CapButton
|
|
3866
|
+
type="link"
|
|
3867
|
+
onClick={() => this.handleTemplateArchiveAction({ templateId: template._id, templateName: template.name, isUnarchive: true })}
|
|
3868
|
+
className="popover-action popover-archive-action"
|
|
3869
|
+
>
|
|
3870
|
+
<CapIcon type="archive" size="s" />
|
|
3871
|
+
<CapLabel.CapLabelInline type="label1">{this.props.intl.formatMessage(messages.unarchiveButton)}</CapLabel.CapLabelInline>
|
|
3872
|
+
</CapButton>
|
|
3624
3873
|
</div>}
|
|
3625
3874
|
<div className="popover-action-container">
|
|
3626
|
-
<
|
|
3875
|
+
<CapButton type="link" onClick={() => this.toggleDeleteTemplateModal(template)} className="popover-action">
|
|
3876
|
+
{deleteOption}
|
|
3877
|
+
</CapButton>
|
|
3627
3878
|
</div>
|
|
3628
3879
|
</div>
|
|
3629
3880
|
}
|
|
@@ -3676,7 +3927,20 @@ return (<div>
|
|
|
3676
3927
|
return false;
|
|
3677
3928
|
}
|
|
3678
3929
|
}
|
|
3679
|
-
isFullMode = () => this.props.location.query.type !==
|
|
3930
|
+
isFullMode = () => this.props.location.query.type !== EMBEDDED || this.props.isFullMode
|
|
3931
|
+
|
|
3932
|
+
isChannelArchiveEligible = (channel, whatsappStatus, rcsStatus) => (
|
|
3933
|
+
channel !== ZALO &&
|
|
3934
|
+
!(channel === WHATSAPP && [WHATSAPP_STATUSES.awaitingApproval, WHATSAPP_STATUSES.pending, WHATSAPP_STATUSES.unsubmitted].includes(whatsappStatus)) &&
|
|
3935
|
+
!(channel === RCS && [RCS_STATUSES.awaitingApproval, RCS_STATUSES.pending].includes(rcsStatus))
|
|
3936
|
+
)
|
|
3937
|
+
|
|
3938
|
+
setArchivedMode = (isArchived) => {
|
|
3939
|
+
this.props.actions.setArchivedMode(isArchived);
|
|
3940
|
+
this.setState({ searchText: '', page: 1 }, () => {
|
|
3941
|
+
this.getAllTemplates({ params: { name: '', sortBy: this.state.sortBy, archiveStatus: isArchived ? ARCHIVE_STATUS_ARCHIVED : ARCHIVE_STATUS_ACTIVE }, resetPage: true }, true);
|
|
3942
|
+
});
|
|
3943
|
+
}
|
|
3680
3944
|
isCreateDisabled = () => {
|
|
3681
3945
|
let isDisabled = this.isLoading();
|
|
3682
3946
|
const channel = this.state.channel.toUpperCase();
|
|
@@ -4214,11 +4478,16 @@ return (<div>
|
|
|
4214
4478
|
if (([WHATSAPP_LOWERCASE, ZALO_LOWERCASE, RCS_LOWERCASE].includes(this.state?.channel?.toLocaleLowerCase()) && isEmpty(this.state?.hostName))) {
|
|
4215
4479
|
isfilterContentVisisble = false;
|
|
4216
4480
|
}
|
|
4481
|
+
const _isArchivedMode = get(this.props, 'Templates.isArchivedMode', false);
|
|
4482
|
+
const _renderSelectedIds = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
4483
|
+
const _renderSelectedIdsArray = _renderSelectedIds && typeof _renderSelectedIds.toJS === 'function' ? _renderSelectedIds.toJS() : (Array.isArray(_renderSelectedIds) ? _renderSelectedIds : []);
|
|
4484
|
+
const _renderHasSelection = this.props.isFullMode && _renderSelectedIdsArray.length > 0;
|
|
4485
|
+
|
|
4217
4486
|
const filterContent = (( isfilterContentVisisble || [WECHAT, MOBILE_PUSH, INAPP].includes(this.state.channel.toUpperCase())) && <div className="action-container">
|
|
4218
4487
|
{isfilterContentVisisble && <CapInput.Search
|
|
4219
4488
|
className="search-text"
|
|
4220
4489
|
style={{width: '210px'}}
|
|
4221
|
-
placeholder={this.props.intl.formatMessage(messages.searchText)}
|
|
4490
|
+
placeholder={_isArchivedMode ? this.props.intl.formatMessage(messages.searchArchivedTemplates) : this.props.intl.formatMessage(messages.searchText)}
|
|
4222
4491
|
value={this.state.searchText}
|
|
4223
4492
|
onChange={(e) => this.searchTemplate(e.target.value, this.state.channel)}
|
|
4224
4493
|
disabled={this.checkSearchDisabled()}
|
|
@@ -4370,9 +4639,9 @@ return (<div>
|
|
|
4370
4639
|
</div>
|
|
4371
4640
|
)
|
|
4372
4641
|
}
|
|
4373
|
-
<div
|
|
4374
|
-
{
|
|
4375
|
-
this.state?.channel?.toLowerCase() === WHATSAPP_LOWERCASE && (isWhatsappCountExeeded)? (
|
|
4642
|
+
<div className="template-listing-header-actions">
|
|
4643
|
+
{!_isArchivedMode && !_renderHasSelection && (
|
|
4644
|
+
this.state?.channel?.toLowerCase() === WHATSAPP_LOWERCASE && (isWhatsappCountExeeded) ? (
|
|
4376
4645
|
<CapTooltip title={whatsappCountExceedText}>
|
|
4377
4646
|
<div className="button-disabled-tooltip-wrapper">
|
|
4378
4647
|
{createButton}
|
|
@@ -4380,9 +4649,29 @@ return (<div>
|
|
|
4380
4649
|
</CapTooltip>
|
|
4381
4650
|
)
|
|
4382
4651
|
: isfilterContentVisisble && !isWechatEmbedded && !this.props.isDltFromRcs && createButton
|
|
4383
|
-
}
|
|
4652
|
+
)}
|
|
4653
|
+
{/* More (⋯) menu: full mode only, not archived mode, not Zalo (no archive support), not when selection active */}
|
|
4654
|
+
{!_isArchivedMode && !_renderHasSelection && this.props.isFullMode && this.props.location.query.type !== EMBEDDED && channelLowerCase !== ZALO_LOWERCASE && (
|
|
4655
|
+
<CapDropdown
|
|
4656
|
+
trigger={['click']}
|
|
4657
|
+
overlay={
|
|
4658
|
+
<CapMenu>
|
|
4659
|
+
<CapMenu.Item
|
|
4660
|
+
key="archived"
|
|
4661
|
+
onClick={() => this.setArchivedMode(true)}
|
|
4662
|
+
>
|
|
4663
|
+
<FormattedMessage {...messages.archivedTemplates} />
|
|
4664
|
+
</CapMenu.Item>
|
|
4665
|
+
</CapMenu>
|
|
4666
|
+
}
|
|
4667
|
+
placement="bottomRight"
|
|
4668
|
+
>
|
|
4669
|
+
<CapButton type="flat" className="template-listing-more-btn">
|
|
4670
|
+
<CapIcon type="more" />
|
|
4671
|
+
</CapButton>
|
|
4672
|
+
</CapDropdown>
|
|
4673
|
+
)}
|
|
4384
4674
|
</div>
|
|
4385
|
-
|
|
4386
4675
|
</div>);
|
|
4387
4676
|
let htmlPreviewContent = "";
|
|
4388
4677
|
if (this.state.channel.toLowerCase() === 'ebill') {
|
|
@@ -4431,6 +4720,18 @@ return (<div>
|
|
|
4431
4720
|
}
|
|
4432
4721
|
/>
|
|
4433
4722
|
|
|
4723
|
+
{/* Archived mode header with back arrow (full mode only) */}
|
|
4724
|
+
{this.props.isFullMode && get(this.props, 'Templates.isArchivedMode', false) && (
|
|
4725
|
+
<CapRow type="flex" align="middle" className="archived-mode-header">
|
|
4726
|
+
<CapIcon
|
|
4727
|
+
type="back"
|
|
4728
|
+
className="archived-mode-back-icon"
|
|
4729
|
+
onClick={() => this.setArchivedMode(false)}
|
|
4730
|
+
/>
|
|
4731
|
+
<CapHeading type="h3"><FormattedMessage {...messages.archivedTemplates} /></CapHeading>
|
|
4732
|
+
</CapRow>
|
|
4733
|
+
)}
|
|
4734
|
+
|
|
4434
4735
|
{channel.toLowerCase() === WHATSAPP_LOWERCASE &&
|
|
4435
4736
|
showWhatsappCountWarning ? (
|
|
4436
4737
|
<CapAlert message={whatsappCountExceedText} type="info" />
|