@capillarytech/creatives-library 7.17.46-alpha.0 → 7.17.47-alpha.0
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/components/CapTagList/index.js +2 -2
- package/components/CapTagList/messages.js +4 -0
- package/containers/App/constants.js +2 -1
- package/package.json +1 -1
- package/utils/common.js +6 -17
- package/v2Components/CapTagList/index.js +2 -2
- package/v2Components/CapTagList/style.scss +5 -0
- package/v2Components/FormBuilder/index.js +2 -2
- package/v2Containers/Email/index.js +1 -1
- package/v2Containers/TagList/index.js +16 -1
- package/v2Containers/Templates/actions.js +2 -2
- package/v2Containers/Templates/constants.js +2 -0
- package/v2Containers/Templates/index.js +6 -5
- package/v2Containers/Templates/sagas.js +8 -5
- package/v2Containers/Templates/tests/actions.test.js +2 -1
- package/v2Containers/Templates/tests/mockData.js +4 -0
- package/v2Containers/Templates/tests/sagas.test.js +25 -3
|
@@ -182,8 +182,8 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
182
182
|
visible={this.state.visible}
|
|
183
183
|
onVisibleChange={this.togglePopoverVisibility}
|
|
184
184
|
content={<div>
|
|
185
|
-
<Spin tip=
|
|
186
|
-
<Search style={{ marginBottom: 8, width: '250px'}} placeholder={this.props
|
|
185
|
+
<Spin tip={this.props?.intl?.formatMessage(messages.gettingTags)} spinning={this.props.loading}>
|
|
186
|
+
<Search style={{ marginBottom: 8, width: '250px'}} placeholder={this.props?.intl?.formatMessage(messages.searchText)} onChange={this.onChange} />
|
|
187
187
|
{this.props.moduleFilterEnabled ? <CapSelect getPopupContainer={(triggerNode) => triggerNode.parentNode} style={{width: '250px', marginBottom: '16px', minWidth: 'initial', display: 'inherit'}} onChange={this.props.onContextChange} defaultValue="All" options={options}>
|
|
188
188
|
</CapSelect> : ''}
|
|
189
189
|
<Tree
|
package/package.json
CHANGED
package/utils/common.js
CHANGED
|
@@ -15,8 +15,6 @@ import {
|
|
|
15
15
|
REGISTRATION_CUSTOM_FIELD,
|
|
16
16
|
JP_LOCALE_HIDE_FEATURE,
|
|
17
17
|
ENABLE_CUSTOMER_BARCODE_TAG,
|
|
18
|
-
PROMO_ENGINE_RELATED_TAGS,
|
|
19
|
-
GIFT_VOUCHER_RELATED_TAGS,
|
|
20
18
|
} from '../containers/App/constants';
|
|
21
19
|
import { apiMessageFormatHandler } from './commonUtils';
|
|
22
20
|
|
|
@@ -97,25 +95,16 @@ export const filterTags = (tagsToFilter, tagsList) => tagsList?.filter(
|
|
|
97
95
|
export function getTreeStructuredTags({tagsList, userLocale = 'en', offerDetails = [], disableTagsDetails = {}}) {
|
|
98
96
|
const mainTags = {};
|
|
99
97
|
const { disableRelatedTags, childTagsToDisable, parentTagstoDisable} = disableTagsDetails;
|
|
100
|
-
const excludedTagList = [];
|
|
101
98
|
|
|
99
|
+
let clonedTags = tagsList;
|
|
102
100
|
if (!hasCardBasedScope()) {
|
|
103
|
-
|
|
101
|
+
//filtering CARD_RELATED_TAGS if org does not have CARD_BASED_SCOPE feature enabled
|
|
102
|
+
clonedTags = filterTags(CARD_RELATED_TAGS, tagsList);
|
|
104
103
|
}
|
|
105
|
-
|
|
106
104
|
if (!hasHospitalityBasedScope()) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (!hasPromoFeature()) {
|
|
111
|
-
excludedTagList.push(PROMO_ENGINE_RELATED_TAGS);
|
|
105
|
+
//filtering HOSPITALITY_RELATED_TAGS if org does not have HOSPITALITY_BASED_SCOPE feature enabled
|
|
106
|
+
clonedTags = filterTags(HOSPITALITY_RELATED_TAGS, tagsList);
|
|
112
107
|
}
|
|
113
|
-
|
|
114
|
-
if (!hasGiftVoucherFeature()) {
|
|
115
|
-
excludedTagList.push(GIFT_VOUCHER_RELATED_TAGS);
|
|
116
|
-
}
|
|
117
|
-
const clonedTags = filterTags(excludedTagList, tagsList);
|
|
118
|
-
|
|
119
108
|
_.forEach(clonedTags, (temp) => {
|
|
120
109
|
const tag = temp.definition;
|
|
121
110
|
if (!tag['tag-header']) { //if tag doesn't have subtag(s), which means this tag itself is tag and not a tag header.
|
|
@@ -372,4 +361,4 @@ export const handleInjectedData = (data, scope) => {
|
|
|
372
361
|
|
|
373
362
|
export const handlePreviewInNewTab = (previewUrl) => {
|
|
374
363
|
window.open(previewUrl, '_blank');
|
|
375
|
-
}
|
|
364
|
+
}
|
|
@@ -11,7 +11,7 @@ import moment from 'moment';
|
|
|
11
11
|
import { FONT_COLOR_05 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
12
12
|
// import styled from 'styled-components';
|
|
13
13
|
import { CapSpin, CapModal, CapButton, CapPopover, CapInput, CapTree, CapSelect, CapTooltip, CapLink, CapIcon } from '@capillarytech/cap-ui-library';
|
|
14
|
-
|
|
14
|
+
import './style.scss';
|
|
15
15
|
import _ from 'lodash';
|
|
16
16
|
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
|
17
17
|
import { createStructuredSelector } from 'reselect';
|
|
@@ -287,6 +287,7 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
287
287
|
<CapIcon
|
|
288
288
|
type="help"
|
|
289
289
|
size="s"
|
|
290
|
+
svgProps={{ color: FONT_COLOR_05 }}
|
|
290
291
|
/>
|
|
291
292
|
<CapLink>
|
|
292
293
|
<CapButton id="translationtagfooter" type="flat" onClick={this.openTranslationLink} >
|
|
@@ -295,7 +296,6 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
295
296
|
<CapIcon
|
|
296
297
|
type="open-in-new-light"
|
|
297
298
|
size="s"
|
|
298
|
-
svgProps={{ color: FONT_COLOR_05 }}
|
|
299
299
|
/>
|
|
300
300
|
</div>
|
|
301
301
|
</CapButton>
|
|
@@ -54,7 +54,7 @@ import { convert } from 'html-to-text';
|
|
|
54
54
|
import { AI_SUGGESTION_API_URL } from './constants';
|
|
55
55
|
import { GET_TRANSLATION_MAPPED } from '../../containers/TagList/constants';
|
|
56
56
|
import moment from 'moment';
|
|
57
|
-
import { CUSTOMER_BARCODE_TAG } from '../../containers/App/constants';
|
|
57
|
+
import { CUSTOMER_BARCODE_TAG , COPY_OF} from '../../containers/App/constants';
|
|
58
58
|
const TabPane = Tabs.TabPane;
|
|
59
59
|
const {Column} = Table;
|
|
60
60
|
const {TextArea} = CapInput;
|
|
@@ -1669,7 +1669,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1669
1669
|
} else {
|
|
1670
1670
|
const tempTab = ifError ? currentTab : this.state.currentTab;
|
|
1671
1671
|
const version = `Version ${this.state.currentTab}`;
|
|
1672
|
-
formData[tabCount].name = `${
|
|
1672
|
+
formData[tabCount].name = `${COPY_OF} ${formData[tempTab - 1].name ? formData[tempTab - 1].name : version}`;
|
|
1673
1673
|
formData[tabCount].base = false;
|
|
1674
1674
|
const initialTab = this.state.currentTab;
|
|
1675
1675
|
this.setState({formData, tabCount: tabCount + 1, currentTab: tabCount + 1, tabKey: formData[tabCount].tabKey}, () => {
|
|
@@ -2554,7 +2554,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2554
2554
|
<CapInput
|
|
2555
2555
|
className="search-text"
|
|
2556
2556
|
style={{width: '210px'}}
|
|
2557
|
-
placeholder=
|
|
2557
|
+
placeholder={`${this.props.intl.formatMessage(messages.searchText)}`}
|
|
2558
2558
|
prefix={<i className="material-icons" style={{color: '#707070', fontSize: '16px'}}>search</i>}
|
|
2559
2559
|
value={this.state.searchText}
|
|
2560
2560
|
onChange={(e) => this.searchAsset(e.target.value)}
|
|
@@ -22,7 +22,8 @@ import './_tagList.scss';
|
|
|
22
22
|
import { selectCurrentOrgDetails } from '../Cap/selectors';
|
|
23
23
|
import { injectIntl } from 'react-intl';
|
|
24
24
|
import { scope } from './messages';
|
|
25
|
-
import { handleInjectedData } from '../../utils/common';
|
|
25
|
+
import { handleInjectedData, hasGiftVoucherFeature, hasPromoFeature } from '../../utils/common';
|
|
26
|
+
import { GIFT_VOUCHER_RELATED_TAGS, PROMO_ENGINE_RELATED_TAGS } from '../../containers/App/constants';
|
|
26
27
|
|
|
27
28
|
const TreeNode = Tree.TreeNode;
|
|
28
29
|
|
|
@@ -95,10 +96,24 @@ export class TagList extends React.Component { // eslint-disable-line react/pref
|
|
|
95
96
|
}
|
|
96
97
|
populateTags(tagsList) {
|
|
97
98
|
const mainTags = {};
|
|
99
|
+
const excludedTags = [];
|
|
100
|
+
if (!hasPromoFeature()) {
|
|
101
|
+
excludedTags.push(...PROMO_ENGINE_RELATED_TAGS);
|
|
102
|
+
//filtering PROMO_ENGINE_RELATED_TAGS if org does not have PROMO_ENGINE feature enabled
|
|
103
|
+
}
|
|
104
|
+
if (!hasGiftVoucherFeature()) {
|
|
105
|
+
//filtering GIFT_VOUCHER_RELATED_TAGS if org does not have GIFT_CARDS feature enabled
|
|
106
|
+
excludedTags.push(...GIFT_VOUCHER_RELATED_TAGS);
|
|
107
|
+
}
|
|
98
108
|
//Form tags object with tag headers
|
|
99
109
|
_.forEach(tagsList, (temp) => {
|
|
100
110
|
const tag = temp.definition;
|
|
101
111
|
const { locale: userLocale } = this.props?.intl || {};
|
|
112
|
+
|
|
113
|
+
// Check if the tag.value should be skipped based on feature control
|
|
114
|
+
if (_.includes(excludedTags, tag.value)) {
|
|
115
|
+
return; // Skip processing this tag
|
|
116
|
+
}
|
|
102
117
|
if (!tag['tag-header']) {
|
|
103
118
|
mainTags[tag.value] = {
|
|
104
119
|
"name": tag?.label[userLocale] ? tag?.label[userLocale] : tag?.label?.en,
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
import * as types from './constants';
|
|
8
8
|
import { LINE, WHATSAPP, RCS, ZALO } from '../CreativesContainer/constants';
|
|
9
9
|
|
|
10
|
-
export function getAllTemplates(channel, queryParams) {
|
|
10
|
+
export function getAllTemplates(channel, queryParams, intlCopyOf = '') {
|
|
11
11
|
return {
|
|
12
|
-
type: types.GET_ALL_TEMPLATES_REQUEST, channel, queryParams,
|
|
12
|
+
type: types.GET_ALL_TEMPLATES_REQUEST, channel, queryParams, intlCopyOf,
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -73,3 +73,5 @@ export const GET_SENDER_DETAILS_FAILURE =
|
|
|
73
73
|
export const GET_CDN_TRANSFORMATION_CONFIG_REQUEST = 'app/v2Containers/Templates/GET_CDN_TRANSFORMATION_CONFIG_REQUEST';
|
|
74
74
|
export const GET_CDN_TRANSFORMATION_CONFIG_SUCCESS = 'app/v2Containers/Templates/GET_CDN_TRANSFORMATION_CONFIG_SUCCESS';
|
|
75
75
|
export const GET_CDN_TRANSFORMATION_CONFIG_FAILURE = 'app/v2Containers/Templates/GET_CDN_TRANSFORMATION_CONFIG_FAILURE';
|
|
76
|
+
|
|
77
|
+
export const COPY_OF = 'Copy of';
|
|
@@ -93,7 +93,7 @@ import {
|
|
|
93
93
|
FACEBOOK as FACEBOOK_CHANNEL,
|
|
94
94
|
CREATE,
|
|
95
95
|
} from '../App/constants';
|
|
96
|
-
import { MAX_WHATSAPP_TEMPLATES, WARNING_WHATSAPP_TEMPLATES } from './constants';
|
|
96
|
+
import { COPY_OF, MAX_WHATSAPP_TEMPLATES, WARNING_WHATSAPP_TEMPLATES } from './constants';
|
|
97
97
|
import {
|
|
98
98
|
TWILIO_CATEGORY_OPTIONS,
|
|
99
99
|
KARIX_GUPSHUP_CATEGORY_OPTIONS,
|
|
@@ -309,6 +309,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
309
309
|
}
|
|
310
310
|
|
|
311
311
|
componentDidMount() {
|
|
312
|
+
const {formatMessage} =this.props?.intl || {};
|
|
312
313
|
if (this.props.location.query.type === 'embedded' && this.isEnabledInLibraryModule("setLocale")) {
|
|
313
314
|
this.setLocale();
|
|
314
315
|
}
|
|
@@ -334,7 +335,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
334
335
|
if ((this.state.channel || '').toLowerCase() === "sms" && isTraiDltFeature) {
|
|
335
336
|
queryParams.traiEnable = true;
|
|
336
337
|
}
|
|
337
|
-
this.props.actions.getAllTemplates(channel, queryParams);
|
|
338
|
+
this.props.actions.getAllTemplates(channel, queryParams,`${formatMessage(globalMessages.copyOf)}`);
|
|
338
339
|
}
|
|
339
340
|
|
|
340
341
|
window.addEventListener("message", this.handleFrameTasks);
|
|
@@ -770,7 +771,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
770
771
|
queryParams.originalId = this.props.Templates.selectedWeChatAccount.sourceAccountIdentifier;
|
|
771
772
|
}
|
|
772
773
|
const channel = this.state.channel;
|
|
773
|
-
this.props.actions.getAllTemplates(channel, queryParams);
|
|
774
|
+
this.props.actions.getAllTemplates(channel, queryParams,`${this.props?.intl?.formatMessage(globalMessages.copyOf)}`);
|
|
774
775
|
} else if ((resetPage || (page === 1 && this.state.templatesCount === 0) || page <= (this.state.templatesCount / this.state.perPageLimit))) {
|
|
775
776
|
if (getNextPage) {
|
|
776
777
|
page += 1;
|
|
@@ -812,7 +813,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
812
813
|
queryParams.page = page;
|
|
813
814
|
queryParams.perPage = this.state.perPageLimit;
|
|
814
815
|
const channel = this.state.channel;
|
|
815
|
-
this.props.actions.getAllTemplates(channel, queryParams);
|
|
816
|
+
this.props.actions.getAllTemplates(channel, queryParams, `${this.props?.intl?.formatMessage(globalMessages.copyOf)}`);
|
|
816
817
|
});
|
|
817
818
|
}
|
|
818
819
|
};
|
|
@@ -1756,7 +1757,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1756
1757
|
|
|
1757
1758
|
duplicateTemplate(template) {
|
|
1758
1759
|
const duplicateObj = cloneDeep(template);
|
|
1759
|
-
duplicateObj.name = `${
|
|
1760
|
+
duplicateObj.name = `${COPY_OF} ${template?.name} ${moment().format('MM-DD-YYYY HH:mm:ss')}`;
|
|
1760
1761
|
delete duplicateObj._id;
|
|
1761
1762
|
|
|
1762
1763
|
if (this.state.channel.toLowerCase() === "mobilepush") {
|
|
@@ -4,7 +4,6 @@ import { LOCATION_CHANGE } from 'react-router-redux';
|
|
|
4
4
|
import * as Api from '../../services/api';
|
|
5
5
|
import * as types from './constants';
|
|
6
6
|
import { saveCdnConfigs, removeAllCdnLocalStorageItems } from '../../utils/cdnTransformation';
|
|
7
|
-
|
|
8
7
|
// Individual exports for testing
|
|
9
8
|
export function* getAllTemplates(channel, queryParams) {
|
|
10
9
|
try {
|
|
@@ -20,6 +19,13 @@ export function* getAllTemplates(channel, queryParams) {
|
|
|
20
19
|
} else if (channel.channel === 'wechat' && channel.queryParams && channel.queryParams.sortBy && channel.queryParams.sortBy.toLocaleLowerCase() === ("Alphabetically").toLocaleLowerCase()) {
|
|
21
20
|
channelTemplates.templates.sort((a, b) => b.name - a.name);
|
|
22
21
|
}
|
|
22
|
+
// Update the "name" property in each template
|
|
23
|
+
if (channel.intlCopyOf && channelTemplates?.templates) {
|
|
24
|
+
channelTemplates.templates = channelTemplates.templates.map((template) => ({
|
|
25
|
+
...template,
|
|
26
|
+
name: template.name.replace(new RegExp(types.COPY_OF, 'g'), channel.intlCopyOf),
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
23
29
|
yield put({ type: types.GET_ALL_TEMPLATES_SUCCESS, data: channelTemplates, weCRMTemplate: result.response.unMapped, isReset: channel.queryParams.page === 1 });
|
|
24
30
|
} catch (error) {
|
|
25
31
|
yield put({ type: types.GET_ALL_TEMPLATES_FAILURE, error });
|
|
@@ -122,7 +128,7 @@ export function* sendZippedFile({selectedFile, errorHandler, successHandler}) {
|
|
|
122
128
|
yield errorHandler(errorMessage);
|
|
123
129
|
}
|
|
124
130
|
|
|
125
|
-
|
|
131
|
+
|
|
126
132
|
console.log("Got decoded result", decodeURIComponent(result.response.metaEntity.htmlContent));
|
|
127
133
|
yield [
|
|
128
134
|
put({
|
|
@@ -144,7 +150,6 @@ export function* sendZippedFile({selectedFile, errorHandler, successHandler}) {
|
|
|
144
150
|
|
|
145
151
|
export function* getDefaultBeeTemplates() {
|
|
146
152
|
try {
|
|
147
|
-
|
|
148
153
|
const result = yield call(Api.getDefaultBeeTemplates);
|
|
149
154
|
const edmTemplates = result.response;
|
|
150
155
|
yield put({ type: types.GET_DEAFULT_BEE_TEMPLATES_SUCCESS, data: edmTemplates });
|
|
@@ -155,7 +160,6 @@ export function* getDefaultBeeTemplates() {
|
|
|
155
160
|
|
|
156
161
|
export function* getTemplateDetails(id, channel) {
|
|
157
162
|
try {
|
|
158
|
-
|
|
159
163
|
const result = yield call(Api.getTemplateDetails, id, channel);
|
|
160
164
|
// const sidebar = result.response.sidebar;
|
|
161
165
|
yield put({ type: types.GET_TEMPLATE_DETAILS_SUCCESS, data: result.response });
|
|
@@ -208,7 +212,6 @@ function* watchGetUserList() {
|
|
|
208
212
|
}
|
|
209
213
|
|
|
210
214
|
function* watchFetchWeCrmAccounts() {
|
|
211
|
-
|
|
212
215
|
const watcher = yield takeLatest(types.GET_WECRM_ACCOUNTS_REQUEST, fetchWeCrmAccounts);
|
|
213
216
|
yield take(LOCATION_CHANGE);
|
|
214
217
|
yield cancel(watcher);
|
|
@@ -11,8 +11,9 @@ describe("Test zalo list actions", () => {
|
|
|
11
11
|
const expected = {
|
|
12
12
|
type: types.GET_ALL_TEMPLATES_REQUEST,
|
|
13
13
|
channel,
|
|
14
|
+
intlCopyOf: "test",
|
|
14
15
|
queryParams,
|
|
15
16
|
};
|
|
16
|
-
expect(getAllTemplates(channel, queryParams)).toEqual(expected);
|
|
17
|
+
expect(getAllTemplates(channel, queryParams, "test")).toEqual(expected);
|
|
17
18
|
});
|
|
18
19
|
});
|
|
@@ -80,14 +80,36 @@ describe('watchForGetJourneyList saga', () => {
|
|
|
80
80
|
describe('templateList saga', () => {
|
|
81
81
|
it('handle valid response from api', () => {
|
|
82
82
|
expectSaga(getAllTemplates, mockData.getAllTemplatesListSuccess)
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
.provide([
|
|
84
|
+
[
|
|
85
|
+
matchers.call.fn(api.getAllTemplates),
|
|
86
|
+
mockData.getAllTemplatesListSuccess,
|
|
87
|
+
],
|
|
88
|
+
]).put({
|
|
85
89
|
type: types.GET_ALL_TEMPLATES_SUCCESS,
|
|
86
|
-
|
|
90
|
+
data: mockData.getAllTemplatesListSuccess,
|
|
91
|
+
weCRMTemplate: mockData.getAllTemplatesListSuccess,
|
|
92
|
+
isReset: mockData.getAllTemplatesListSuccess?.queryParams?.page === 1,
|
|
87
93
|
})
|
|
88
94
|
.run();
|
|
89
95
|
});
|
|
90
96
|
|
|
97
|
+
it('handle valid response from api', () => {
|
|
98
|
+
mockData.getAllTemplatesListSuccess.intlCopyOf = '';
|
|
99
|
+
expectSaga(getAllTemplates, mockData.getAllTemplatesListSuccess)
|
|
100
|
+
.provide([
|
|
101
|
+
[
|
|
102
|
+
matchers.call.fn(api.getAllTemplates),
|
|
103
|
+
mockData.getAllTemplatesListSuccess,
|
|
104
|
+
],
|
|
105
|
+
]).put({
|
|
106
|
+
type: types.GET_ALL_TEMPLATES_SUCCESS,
|
|
107
|
+
data: mockData.getAllTemplatesListSuccess,
|
|
108
|
+
weCRMTemplate: mockData.getAllTemplatesListSuccess,
|
|
109
|
+
isReset: mockData.getAllTemplatesListSuccess?.queryParams?.page === 1,
|
|
110
|
+
})
|
|
111
|
+
.run();
|
|
112
|
+
});
|
|
91
113
|
it('handles error thrown from api', () => {
|
|
92
114
|
expectSaga(getAllTemplates, mockData.getAllTemplatesListFailure)
|
|
93
115
|
.provide([
|