@capillarytech/creatives-library 8.0.345-alpha.8 → 8.0.345
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/v2Components/CapCustomSkeleton/index.js +1 -1
- package/v2Components/CapCustomSkeleton/tests/__snapshots__/index.test.js.snap +12 -12
- package/v2Containers/Assets/images/archive_Empty_Illustration.svg +9 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +1 -20
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +3 -1
- package/v2Containers/CreativesContainer/index.js +6 -4
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +3 -0
- package/v2Containers/Email/index.js +0 -17
- package/v2Containers/Templates/ChannelTypeIllustration.js +23 -6
- package/v2Containers/Templates/_templates.scss +130 -24
- package/v2Containers/Templates/actions.js +36 -0
- package/v2Containers/Templates/constants.js +23 -0
- package/v2Containers/Templates/index.js +286 -30
- package/v2Containers/Templates/messages.js +68 -0
- package/v2Containers/Templates/reducer.js +68 -0
- package/v2Containers/Templates/sagas.js +89 -1
- 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 +314 -8
- package/v2Containers/Templates/tests/selector.test.js +32 -0
|
@@ -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';
|
|
@@ -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();
|
|
@@ -1595,6 +1587,11 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1595
1587
|
let queryParams = params || {};
|
|
1596
1588
|
let page = this.state.page;
|
|
1597
1589
|
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
|
+
}
|
|
1598
1595
|
if (activeMode === ACCOUNT_SELECTION_MODE) {
|
|
1599
1596
|
this.setTemplatesMode();
|
|
1600
1597
|
}
|
|
@@ -1861,6 +1858,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1861
1858
|
const currentChannel = channel.toUpperCase();
|
|
1862
1859
|
const {channel: stateChannel} = this.state;
|
|
1863
1860
|
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
1864
|
let filteredTemplates = templates;
|
|
1865
1865
|
let isTraiDltFeature = false;
|
|
1866
1866
|
switch (currentChannel) {
|
|
@@ -1900,10 +1900,26 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1900
1900
|
const iosBodyType = get(template, 'versions.base.content.IOS.bodyType');
|
|
1901
1901
|
const inappBodyType = androidBodyType || iosBodyType;
|
|
1902
1902
|
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));
|
|
1903
1911
|
const templateData = {
|
|
1904
1912
|
key: `${currentChannel}-card-${template?.name}`,
|
|
1905
1913
|
title: (
|
|
1906
|
-
<span title={template?.name}>
|
|
1914
|
+
<span title={template?.name} style={{ display: 'flex', alignItems: 'center' }}>
|
|
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
|
+
)}
|
|
1907
1923
|
{template?.name}
|
|
1908
1924
|
{currentChannel === INAPP && (
|
|
1909
1925
|
<CapRow>
|
|
@@ -2024,7 +2040,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2024
2040
|
{![WECHAT, WHATSAPP, ZALO].includes(
|
|
2025
2041
|
this.state.channel.toUpperCase()
|
|
2026
2042
|
) &&
|
|
2027
|
-
!isTraiDltFeature && (
|
|
2043
|
+
!isTraiDltFeature && !template.isArchived && (
|
|
2028
2044
|
<CapMenu.Item
|
|
2029
2045
|
className={`duplicate-${channelLowerCase}`}
|
|
2030
2046
|
onClick={() => this.duplicateTemplate(template)}
|
|
@@ -2032,6 +2048,42 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2032
2048
|
<FormattedMessage {...messages.duplicateButton} />
|
|
2033
2049
|
</CapMenu.Item>
|
|
2034
2050
|
)}
|
|
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
|
+
})()}
|
|
2035
2087
|
{/* Delete/Unmap menu item */}
|
|
2036
2088
|
{(!(
|
|
2037
2089
|
this.state.channel.toUpperCase() === WHATSAPP &&
|
|
@@ -2312,7 +2364,15 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2312
2364
|
case WHATSAPP: {
|
|
2313
2365
|
const { whatsappImageSrc = '', templateMsg, docPreview, whatsappVideoPreviewImg = '', templateHeaderPreview, templateFooterPreview, carouselData = [] } = getWhatsappContent(template);
|
|
2314
2366
|
templateData.title = (
|
|
2315
|
-
<CapRow>
|
|
2367
|
+
<CapRow type="flex" align="middle">
|
|
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
|
+
)}
|
|
2316
2376
|
<CapLabel className="whatsapp-rcs-template-name">{template?.name}</CapLabel>
|
|
2317
2377
|
<WhatsappStatusContainer template={template} />
|
|
2318
2378
|
</CapRow>
|
|
@@ -2405,7 +2465,15 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2405
2465
|
const name = get(template, "name", "");
|
|
2406
2466
|
const statusDisplay=getRcsStatusType(status);
|
|
2407
2467
|
templateData.title = (
|
|
2408
|
-
<CapRow>
|
|
2468
|
+
<CapRow type="flex" align="middle">
|
|
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
|
+
)}
|
|
2409
2477
|
<CapLabel className="whatsapp-rcs-template-name">{name}</CapLabel>
|
|
2410
2478
|
<CapRow type="flex" align="middle" className="rcs-status-container zalo-status-color">
|
|
2411
2479
|
<CapStatus
|
|
@@ -2529,7 +2597,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2529
2597
|
|
|
2530
2598
|
//no templates available
|
|
2531
2599
|
const showIllustrationForChannel = (forChannel) => {
|
|
2532
|
-
return forChannel === channelLowerCase && isEmpty(templates) && isEmpty(this.state.searchText) && !isLoading;
|
|
2600
|
+
return forChannel === channelLowerCase && isEmpty(templates) && isEmpty(this.state.searchText) && !isLoading && !get(this.props, 'Templates.isArchivedMode', false);
|
|
2533
2601
|
}
|
|
2534
2602
|
//when filters applied not matching templates
|
|
2535
2603
|
const filteredEmptyAndFullModeAs = (fullModeValue) => {
|
|
@@ -2555,9 +2623,49 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
2555
2623
|
|
|
2556
2624
|
const noLoaderAndSearchText = isEmpty(this.state.searchText) && !isLoading;
|
|
2557
2625
|
|
|
2558
|
-
|
|
2626
|
+
const isArchivedModeLocal = get(this.props, 'Templates.isArchivedMode', false);
|
|
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>
|
|
2559
2633
|
{[WECHAT, MOBILE_PUSH, WEBPUSH, INAPP, WHATSAPP, ZALO, RCS].includes(currentChannel) && this.showAccountName()}
|
|
2560
|
-
|
|
2634
|
+
<CapRow type="flex" align="middle" justify="space-between" className="filter-row">
|
|
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>
|
|
2561
2669
|
{[WHATSAPP, ZALO, INAPP,RCS].includes(currentChannel) && this.selectedFilters()}
|
|
2562
2670
|
{<div>
|
|
2563
2671
|
{!isEmpty(filteredTemplates) || !isEmpty(this.state.searchText) || !isEmpty(this.props.Templates.templateError) ? (
|
|
@@ -2570,7 +2678,7 @@ return (<div>
|
|
|
2570
2678
|
fbType={"list"}
|
|
2571
2679
|
/>
|
|
2572
2680
|
</div>)
|
|
2573
|
-
: [SMS_LOWERCASE, EMAIL_LOWERCASE].includes(this.state.channel.toLowerCase()) && !isLoading && this.getSmsEmailIllustration()
|
|
2681
|
+
: [SMS_LOWERCASE, EMAIL_LOWERCASE].includes(this.state.channel.toLowerCase()) && !isLoading && !get(this.props, 'Templates.isArchivedMode', false) && this.getSmsEmailIllustration()
|
|
2574
2682
|
}
|
|
2575
2683
|
|
|
2576
2684
|
{(this.state.selectedAccount === '' && isEmpty(this.props.Templates.selectedWeChatAccount)) && ([WECHAT_LOWERCASE, MOBILE_PUSH_LOWERCASE, INAPP_LOWERCASE].includes(this.state.channel.toLowerCase())) &&
|
|
@@ -2594,7 +2702,7 @@ return (<div>
|
|
|
2594
2702
|
</div>
|
|
2595
2703
|
)
|
|
2596
2704
|
}
|
|
2597
|
-
{(showWhatsappIllustration || showZaloIllustration) && (
|
|
2705
|
+
{(showWhatsappIllustration || showZaloIllustration) && !get(this.props, 'Templates.isArchivedMode', false) && (
|
|
2598
2706
|
noLoaderAndSearchText &&
|
|
2599
2707
|
<div style={this.isFullMode() ? { height: "calc(100vh - 325px)", overflow: 'auto' } : {}}>
|
|
2600
2708
|
{noWhatsappZaloTemplates && <ChannelTypeIllustration isFullMode={this.props.isFullMode} createTemplate={this.createTemplate} currentChannel={currentChannel} hostName={this.state?.hostName}/>}
|
|
@@ -2635,6 +2743,16 @@ return (<div>
|
|
|
2635
2743
|
<ChannelTypeIllustration isFullMode={this.props.isFullMode} createTemplate={this.createTemplate} currentChannel={currentChannel} hostName={this.state?.hostName}/>
|
|
2636
2744
|
</div>
|
|
2637
2745
|
}
|
|
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
|
+
)}
|
|
2638
2756
|
{<CapCustomSkeleton loader={isInitialLoading && (isLoading || getAllTemplatesInProgress)} />}
|
|
2639
2757
|
{<CapPageSpinner spinning={!isInitialLoading && (isLoading || getAllTemplatesInProgress)} />}
|
|
2640
2758
|
</div>
|
|
@@ -3278,6 +3396,10 @@ return (<div>
|
|
|
3278
3396
|
};
|
|
3279
3397
|
|
|
3280
3398
|
handleEditClick(e, template, modeType, path, options) {
|
|
3399
|
+
if (template && template.isArchived) {
|
|
3400
|
+
CapNotification.error({ message: this.props.intl.formatMessage(messages.cannotEditArchivedTemplate) });
|
|
3401
|
+
return;
|
|
3402
|
+
}
|
|
3281
3403
|
if (modeType && modeType !== undefined) {
|
|
3282
3404
|
this.setState({modeType});
|
|
3283
3405
|
}
|
|
@@ -3459,6 +3581,33 @@ return (<div>
|
|
|
3459
3581
|
this.setState({showModal: false});
|
|
3460
3582
|
}
|
|
3461
3583
|
|
|
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
|
+
|
|
3462
3611
|
populateTemplatesList = (data, blankTemplateRequired, layoutSelection) => {
|
|
3463
3612
|
if (!data) {
|
|
3464
3613
|
return [];
|
|
@@ -3608,20 +3757,78 @@ return (<div>
|
|
|
3608
3757
|
deleteOption = this.props.intl.formatMessage(messages.unMapButton);
|
|
3609
3758
|
}
|
|
3610
3759
|
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
|
+
|
|
3611
3786
|
temp.footer = (
|
|
3612
3787
|
<div className="footer-container">
|
|
3613
3788
|
<div className="card-title">
|
|
3614
3789
|
<span className="template-name" style={{ fontWeight: `${this.state.channel.toLowerCase() === 'wechat' ? '400' : '600'}` }}>
|
|
3615
3790
|
{ 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
3791
|
{template?.name}
|
|
3792
|
+
{template.isArchived && <CapColoredTag tagColor={CAP_G08} tagTextColor={CAP_G05} className="archived-tag">{this.props.intl.formatMessage(messages.archivedTag)}</CapColoredTag>}
|
|
3617
3793
|
</span>
|
|
3618
3794
|
{this.props.location.query.type !== 'embedded' && <CapPopover
|
|
3619
3795
|
trigger="click"
|
|
3620
3796
|
content={
|
|
3621
3797
|
<div className="popover-content">
|
|
3622
|
-
{this.state.channel !== 'wechat' && <div className="popover-action-container">
|
|
3798
|
+
{this.state.channel !== 'wechat' && !template.isArchived && <div className="popover-action-container">
|
|
3623
3799
|
<span onClick={() => this.duplicateTemplate(template)} className="popover-action" style={{cursor: 'pointer', padding: '8px 0px'}}>{this.props.intl.formatMessage(messages.duplicateButton)}</span>
|
|
3624
3800
|
</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>}
|
|
3625
3832
|
<div className="popover-action-container">
|
|
3626
3833
|
<span onClick={() => this.toggleDeleteTemplateModal(template)} className="popover-action" style={{cursor: 'pointer', padding: '8px 0px'}}>{deleteOption}</span>
|
|
3627
3834
|
</div>
|
|
@@ -4214,11 +4421,16 @@ return (<div>
|
|
|
4214
4421
|
if (([WHATSAPP_LOWERCASE, ZALO_LOWERCASE, RCS_LOWERCASE].includes(this.state?.channel?.toLocaleLowerCase()) && isEmpty(this.state?.hostName))) {
|
|
4215
4422
|
isfilterContentVisisble = false;
|
|
4216
4423
|
}
|
|
4424
|
+
const _isArchivedMode = get(this.props, 'Templates.isArchivedMode', false);
|
|
4425
|
+
const _renderSelectedIds = get(this.props, 'Templates.selectedTemplateIds', []);
|
|
4426
|
+
const _renderSelectedIdsArray = _renderSelectedIds && typeof _renderSelectedIds.toJS === 'function' ? _renderSelectedIds.toJS() : (Array.isArray(_renderSelectedIds) ? _renderSelectedIds : []);
|
|
4427
|
+
const _renderHasSelection = this.props.isFullMode && _renderSelectedIdsArray.length > 0;
|
|
4428
|
+
|
|
4217
4429
|
const filterContent = (( isfilterContentVisisble || [WECHAT, MOBILE_PUSH, INAPP].includes(this.state.channel.toUpperCase())) && <div className="action-container">
|
|
4218
4430
|
{isfilterContentVisisble && <CapInput.Search
|
|
4219
4431
|
className="search-text"
|
|
4220
4432
|
style={{width: '210px'}}
|
|
4221
|
-
placeholder={this.props.intl.formatMessage(messages.searchText)}
|
|
4433
|
+
placeholder={_isArchivedMode ? this.props.intl.formatMessage(messages.searchArchivedTemplates) : this.props.intl.formatMessage(messages.searchText)}
|
|
4222
4434
|
value={this.state.searchText}
|
|
4223
4435
|
onChange={(e) => this.searchTemplate(e.target.value, this.state.channel)}
|
|
4224
4436
|
disabled={this.checkSearchDisabled()}
|
|
@@ -4370,9 +4582,9 @@ return (<div>
|
|
|
4370
4582
|
</div>
|
|
4371
4583
|
)
|
|
4372
4584
|
}
|
|
4373
|
-
<div
|
|
4374
|
-
{
|
|
4375
|
-
this.state?.channel?.toLowerCase() === WHATSAPP_LOWERCASE && (isWhatsappCountExeeded)? (
|
|
4585
|
+
<div className="template-listing-header-actions">
|
|
4586
|
+
{!_isArchivedMode && !_renderHasSelection && (
|
|
4587
|
+
this.state?.channel?.toLowerCase() === WHATSAPP_LOWERCASE && (isWhatsappCountExeeded) ? (
|
|
4376
4588
|
<CapTooltip title={whatsappCountExceedText}>
|
|
4377
4589
|
<div className="button-disabled-tooltip-wrapper">
|
|
4378
4590
|
{createButton}
|
|
@@ -4380,9 +4592,35 @@ return (<div>
|
|
|
4380
4592
|
</CapTooltip>
|
|
4381
4593
|
)
|
|
4382
4594
|
: isfilterContentVisisble && !isWechatEmbedded && !this.props.isDltFromRcs && createButton
|
|
4383
|
-
}
|
|
4595
|
+
)}
|
|
4596
|
+
{/* More (⋯) menu: full mode only, not archived mode, not Zalo (no archive support), not when selection active */}
|
|
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>
|
|
4615
|
+
}
|
|
4616
|
+
placement="bottomRight"
|
|
4617
|
+
>
|
|
4618
|
+
<CapButton type="flat" className="template-listing-more-btn">
|
|
4619
|
+
<CapIcon type="more" />
|
|
4620
|
+
</CapButton>
|
|
4621
|
+
</CapDropdown>
|
|
4622
|
+
)}
|
|
4384
4623
|
</div>
|
|
4385
|
-
|
|
4386
4624
|
</div>);
|
|
4387
4625
|
let htmlPreviewContent = "";
|
|
4388
4626
|
if (this.state.channel.toLowerCase() === 'ebill') {
|
|
@@ -4431,6 +4669,24 @@ return (<div>
|
|
|
4431
4669
|
}
|
|
4432
4670
|
/>
|
|
4433
4671
|
|
|
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
|
+
|
|
4434
4690
|
{channel.toLowerCase() === WHATSAPP_LOWERCASE &&
|
|
4435
4691
|
showWhatsappCountWarning ? (
|
|
4436
4692
|
<CapAlert message={whatsappCountExceedText} type="info" />
|
|
@@ -618,4 +618,72 @@ export default defineMessages({
|
|
|
618
618
|
id: `${scope}.templateUpdateSuccess`,
|
|
619
619
|
defaultMessage: 'Template updated successfully',
|
|
620
620
|
},
|
|
621
|
+
"archiveTemplates": {
|
|
622
|
+
id: `${scope}.archiveTemplates`,
|
|
623
|
+
defaultMessage: 'Archive templates',
|
|
624
|
+
},
|
|
625
|
+
"archiveTemplateContent": {
|
|
626
|
+
id: `${scope}.archiveTemplateContent`,
|
|
627
|
+
defaultMessage: 'These templates will be archived and unavailable for use. You can restore them anytime.',
|
|
628
|
+
},
|
|
629
|
+
"archiveTemplateSingleContent": {
|
|
630
|
+
id: `${scope}.archiveTemplateSingleContent`,
|
|
631
|
+
defaultMessage: 'This template will be archived and unavailable for use. You can restore it anytime.',
|
|
632
|
+
},
|
|
633
|
+
"unarchiveTemplates": {
|
|
634
|
+
id: `${scope}.unarchiveTemplates`,
|
|
635
|
+
defaultMessage: 'Unarchive templates',
|
|
636
|
+
},
|
|
637
|
+
"unarchiveTemplateContent": {
|
|
638
|
+
id: `${scope}.unarchiveTemplateContent`,
|
|
639
|
+
defaultMessage: 'These templates will be unarchived and available for use again.',
|
|
640
|
+
},
|
|
641
|
+
"unarchiveTemplateSingleContent": {
|
|
642
|
+
id: `${scope}.unarchiveTemplateSingleContent`,
|
|
643
|
+
defaultMessage: 'This template will be unarchived and available for use again.',
|
|
644
|
+
},
|
|
645
|
+
"archiveConfirmOk": {
|
|
646
|
+
id: `${scope}.archiveConfirmOk`,
|
|
647
|
+
defaultMessage: 'Confirm',
|
|
648
|
+
},
|
|
649
|
+
"archiveConfirmCancel": {
|
|
650
|
+
id: `${scope}.archiveConfirmCancel`,
|
|
651
|
+
defaultMessage: 'Cancel',
|
|
652
|
+
},
|
|
653
|
+
"archiveButton": {
|
|
654
|
+
id: `${scope}.archiveButton`,
|
|
655
|
+
defaultMessage: 'Archive',
|
|
656
|
+
},
|
|
657
|
+
"unarchiveButton": {
|
|
658
|
+
id: `${scope}.unarchiveButton`,
|
|
659
|
+
defaultMessage: 'Unarchive',
|
|
660
|
+
},
|
|
661
|
+
"archivedTag": {
|
|
662
|
+
id: `${scope}.archivedTag`,
|
|
663
|
+
defaultMessage: 'Archived',
|
|
664
|
+
},
|
|
665
|
+
"archivedTemplates": {
|
|
666
|
+
id: `${scope}.archivedTemplates`,
|
|
667
|
+
defaultMessage: 'Archived templates',
|
|
668
|
+
},
|
|
669
|
+
"searchArchivedTemplates": {
|
|
670
|
+
id: `${scope}.searchArchivedTemplates`,
|
|
671
|
+
defaultMessage: 'Search archived templates...',
|
|
672
|
+
},
|
|
673
|
+
"templatesSelected": {
|
|
674
|
+
id: `${scope}.templatesSelected`,
|
|
675
|
+
defaultMessage: '{count} {count, plural, one {template} other {templates}} selected',
|
|
676
|
+
},
|
|
677
|
+
"cannotEditArchivedTemplate": {
|
|
678
|
+
id: `${scope}.cannotEditArchivedTemplate`,
|
|
679
|
+
defaultMessage: 'Cannot edit an archived template. Please unarchive it first.',
|
|
680
|
+
},
|
|
681
|
+
"noArchivedCreatives": {
|
|
682
|
+
id: `${scope}.noArchivedCreatives`,
|
|
683
|
+
defaultMessage: 'No archived creatives',
|
|
684
|
+
},
|
|
685
|
+
"noArchivedCreativesDesc": {
|
|
686
|
+
id: `${scope}.noArchivedCreativesDesc`,
|
|
687
|
+
defaultMessage: 'Creatives you archive will appear here',
|
|
688
|
+
},
|
|
621
689
|
});
|
|
@@ -26,6 +26,13 @@ export const initialState = fromJS({
|
|
|
26
26
|
reportsSettings: {},
|
|
27
27
|
},
|
|
28
28
|
senderDetails: {},
|
|
29
|
+
archiveFilter: 'active',
|
|
30
|
+
isArchivedMode: false,
|
|
31
|
+
selectedTemplateIds: fromJS([]),
|
|
32
|
+
archiveInProgress: false,
|
|
33
|
+
unarchiveInProgress: false,
|
|
34
|
+
bulkArchiveInProgress: false,
|
|
35
|
+
bulkUnarchiveInProgress: false,
|
|
29
36
|
});
|
|
30
37
|
|
|
31
38
|
function templatesReducer(state = initialState, action) {
|
|
@@ -231,6 +238,67 @@ function templatesReducer(state = initialState, action) {
|
|
|
231
238
|
hostName: '',
|
|
232
239
|
errors: action.payload,
|
|
233
240
|
});
|
|
241
|
+
case types.SET_ARCHIVE_FILTER:
|
|
242
|
+
return state
|
|
243
|
+
.set('archiveFilter', action.filter)
|
|
244
|
+
.set('templates', [])
|
|
245
|
+
.set('selectedTemplateIds', fromJS([]));
|
|
246
|
+
case types.SET_ARCHIVED_MODE:
|
|
247
|
+
return state
|
|
248
|
+
.set('isArchivedMode', action.isArchived)
|
|
249
|
+
.set('archiveFilter', action.isArchived ? 'archived' : 'active')
|
|
250
|
+
.set('templates', [])
|
|
251
|
+
.set('selectedTemplateIds', fromJS([]));
|
|
252
|
+
case types.TOGGLE_TEMPLATE_SELECTION: {
|
|
253
|
+
const rawSelected = state.get('selectedTemplateIds');
|
|
254
|
+
// Defensive: handle undefined (stale persisted state) or plain array (pre-fromJS migration)
|
|
255
|
+
const currentSelected = rawSelected && typeof rawSelected.toJS === 'function'
|
|
256
|
+
? rawSelected.toJS()
|
|
257
|
+
: (Array.isArray(rawSelected) ? rawSelected : []);
|
|
258
|
+
const idx = currentSelected.indexOf(action.id);
|
|
259
|
+
const newSelected = idx === -1
|
|
260
|
+
? [...currentSelected, action.id]
|
|
261
|
+
: currentSelected.filter((id) => id !== action.id);
|
|
262
|
+
return state.set('selectedTemplateIds', fromJS(newSelected));
|
|
263
|
+
}
|
|
264
|
+
case types.SELECT_ALL_TEMPLATES:
|
|
265
|
+
return state.set('selectedTemplateIds', fromJS(action.ids));
|
|
266
|
+
case types.CLEAR_TEMPLATE_SELECTION:
|
|
267
|
+
return state.set('selectedTemplateIds', fromJS([]));
|
|
268
|
+
case types.ARCHIVE_TEMPLATE_REQUEST:
|
|
269
|
+
return state.set('archiveInProgress', true);
|
|
270
|
+
case types.ARCHIVE_TEMPLATE_SUCCESS: {
|
|
271
|
+
const afterArchive = state.get('selectedTemplateIds');
|
|
272
|
+
const archiveSelected = afterArchive && typeof afterArchive.toJS === 'function' ? afterArchive.toJS() : [];
|
|
273
|
+
return state
|
|
274
|
+
.set('archiveInProgress', false)
|
|
275
|
+
.set('selectedTemplateIds', fromJS(archiveSelected.filter((sid) => sid !== action.id)));
|
|
276
|
+
}
|
|
277
|
+
case types.ARCHIVE_TEMPLATE_FAILURE:
|
|
278
|
+
return state.set('archiveInProgress', false);
|
|
279
|
+
case types.UNARCHIVE_TEMPLATE_REQUEST:
|
|
280
|
+
return state.set('unarchiveInProgress', true);
|
|
281
|
+
case types.UNARCHIVE_TEMPLATE_SUCCESS: {
|
|
282
|
+
const afterUnarchive = state.get('selectedTemplateIds');
|
|
283
|
+
const unarchiveSelected = afterUnarchive && typeof afterUnarchive.toJS === 'function' ? afterUnarchive.toJS() : [];
|
|
284
|
+
return state
|
|
285
|
+
.set('unarchiveInProgress', false)
|
|
286
|
+
.set('selectedTemplateIds', fromJS(unarchiveSelected.filter((sid) => sid !== action.id)));
|
|
287
|
+
}
|
|
288
|
+
case types.UNARCHIVE_TEMPLATE_FAILURE:
|
|
289
|
+
return state.set('unarchiveInProgress', false);
|
|
290
|
+
case types.BULK_ARCHIVE_REQUEST:
|
|
291
|
+
return state.set('bulkArchiveInProgress', true);
|
|
292
|
+
case types.BULK_ARCHIVE_SUCCESS:
|
|
293
|
+
return state.set('bulkArchiveInProgress', false).set('selectedTemplateIds', fromJS([]));
|
|
294
|
+
case types.BULK_ARCHIVE_FAILURE:
|
|
295
|
+
return state.set('bulkArchiveInProgress', false);
|
|
296
|
+
case types.BULK_UNARCHIVE_REQUEST:
|
|
297
|
+
return state.set('bulkUnarchiveInProgress', true);
|
|
298
|
+
case types.BULK_UNARCHIVE_SUCCESS:
|
|
299
|
+
return state.set('bulkUnarchiveInProgress', false).set('selectedTemplateIds', fromJS([]));
|
|
300
|
+
case types.BULK_UNARCHIVE_FAILURE:
|
|
301
|
+
return state.set('bulkUnarchiveInProgress', false);
|
|
234
302
|
default:
|
|
235
303
|
return state;
|
|
236
304
|
}
|