@capillarytech/creatives-library 7.9.13 → 7.9.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/group.png +0 -0
- package/components/Card/index.js +1 -1
- package/components/Card/tests/__snapshots__/index.test.js.snap +22 -0
- package/components/Card/tests/index.test.js +19 -7
- package/containers/App/constants.js +2 -1
- package/helpers/intl-enzym-test-helpers.js +40 -0
- package/index.js +6 -0
- package/package.json +3 -2
- package/routes.js +5 -0
- package/services/api.js +9 -15
- package/utils/common.js +17 -4
- package/v2Components/CapTagList/index.js +38 -9
- package/v2Components/CapTagList/messages.js +4 -0
- package/v2Containers/Cap/constants.js +2 -0
- package/v2Containers/Cap/index.js +9 -2
- package/v2Containers/Cap/reducer.js +5 -1
- package/v2Containers/Cap/selectors.js +10 -1
- package/v2Containers/CreativesContainer/SlideBoxContent.js +10 -4
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +6 -1
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/FTP/index.js +14 -4
- package/v2Containers/Sms/Create/index.js +5 -6
- package/v2Containers/Sms/Edit/sagas.js +1 -1
- package/v2Containers/SmsTrai/Create/actions.js +25 -0
- package/v2Containers/SmsTrai/Create/constants.js +74 -0
- package/v2Containers/SmsTrai/Create/index.js +681 -0
- package/v2Containers/SmsTrai/Create/index.scss +92 -0
- package/v2Containers/SmsTrai/Create/messages.js +116 -0
- package/v2Containers/SmsTrai/Create/reducer.js +43 -0
- package/v2Containers/SmsTrai/Create/sagas.js +36 -0
- package/v2Containers/SmsTrai/Create/selectors.js +26 -0
- package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +10351 -0
- package/v2Containers/SmsTrai/Create/tests/index.test.js +77 -0
- package/v2Containers/SmsTrai/Create/tests/mockData.js +58 -0
- package/v2Containers/SmsTrai/Edit/constants.js +16 -0
- package/v2Containers/SmsTrai/Edit/index.js +483 -0
- package/v2Containers/SmsTrai/Edit/messages.js +58 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +16103 -0
- package/v2Containers/SmsTrai/Edit/tests/index.test.js +61 -0
- package/v2Containers/SmsTrai/Edit/tests/mockData.js +36 -0
- package/v2Containers/SmsWrapper/index.js +75 -0
- package/v2Containers/SmsWrapper/tests/index.test.js +10 -0
- package/v2Containers/Templates/_templates.scss +2 -0
- package/v2Containers/Templates/index.js +89 -27
- package/v2Containers/Templates/messages.js +16 -0
package/assets/group.png
ADDED
|
Binary file
|
package/components/Card/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import React from 'react';
|
|
|
10
10
|
import { Card } from 'antd';
|
|
11
11
|
import './_customCard.scss';
|
|
12
12
|
|
|
13
|
-
class CustomCard extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
13
|
+
export class CustomCard extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
14
14
|
constructor(props) {
|
|
15
15
|
super(props);
|
|
16
16
|
this.handleMouseHover = this.handleMouseHover.bind(this);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`RestrictionPlainInput test Test 1 should render default component when a retriction constant is passed 1`] = `
|
|
4
|
+
<Card
|
|
5
|
+
className="custom-card"
|
|
6
|
+
onClick={[Function]}
|
|
7
|
+
onMouseEnter={[Function]}
|
|
8
|
+
onMouseLeave={[Function]}
|
|
9
|
+
style={
|
|
10
|
+
Object {
|
|
11
|
+
"height": undefined,
|
|
12
|
+
"width": undefined,
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
>
|
|
16
|
+
<div>
|
|
17
|
+
<div
|
|
18
|
+
className="content-wrapper"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
</Card>
|
|
22
|
+
`;
|
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallowWithIntl } from '../../../helpers/intl-enzym-test-helpers';
|
|
3
|
+
import { CustomCard } from '../index';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
describe('RestrictionPlainInput test', () => {
|
|
6
|
+
|
|
7
|
+
let renderedComponent;
|
|
8
|
+
|
|
9
|
+
const renderFunc = () => {
|
|
10
|
+
renderedComponent = shallowWithIntl(
|
|
11
|
+
<CustomCard />
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
describe('Test 1', () => {
|
|
16
|
+
it('should render default component when a retriction constant is passed', () => {
|
|
17
|
+
renderFunc();
|
|
18
|
+
expect(renderedComponent).toMatchSnapshot();
|
|
19
|
+
})
|
|
20
|
+
});
|
|
5
21
|
|
|
6
|
-
describe('<Card />', () => {
|
|
7
|
-
it('Expect to have unit tests specified', () => {
|
|
8
|
-
expect(true).toEqual(false);
|
|
9
|
-
});
|
|
10
22
|
});
|
|
@@ -2,4 +2,5 @@ export const GET_SIDEBAR_REQUEST = 'app/App/GET_SIDEBAR_REQUEST';
|
|
|
2
2
|
export const GET_SIDEBAR_SUCCESS = 'app/App/GET_SIDEBAR_SUCCESS';
|
|
3
3
|
export const GET_SIDEBAR_FAILURE = 'app/App/GET_SIDEBAR_FAILURE';
|
|
4
4
|
|
|
5
|
-
export const STORE2DOOR_PLUS_ENABLED = 'STORE2DOOR_PLUS_ENABLED';
|
|
5
|
+
export const STORE2DOOR_PLUS_ENABLED = 'STORE2DOOR_PLUS_ENABLED';
|
|
6
|
+
export const TRAI_DLT = 'TRAI_DLT';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Components using the react-intl module require access to the intl context.
|
|
3
|
+
* This is not available when mounting single components in Enzyme.
|
|
4
|
+
* These helper functions aim to address that and wrap a valid,
|
|
5
|
+
* English-locale intl context around them.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import { IntlProvider, intlShape } from 'react-intl';
|
|
10
|
+
import { mount, shallow, configure } from 'enzyme';
|
|
11
|
+
import Adapter from 'enzyme-adapter-react-16';
|
|
12
|
+
|
|
13
|
+
configure({ adapter: new Adapter() });
|
|
14
|
+
// You can pass your messages to the IntlProvider. Optional: remove if unneeded.
|
|
15
|
+
const messages = require('../translations/en.json'); // en.json
|
|
16
|
+
|
|
17
|
+
// Create the IntlProvider to retrieve context for wrapping around.
|
|
18
|
+
const intlProvider = new IntlProvider({ locale: 'en', messages }, {});
|
|
19
|
+
const { intl } = intlProvider.getChildContext();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* When using React-Intl `injectIntl` on components, props.intl is required.
|
|
23
|
+
*/
|
|
24
|
+
function nodeWithIntlProp(node) {
|
|
25
|
+
return React.cloneElement(node, { intl });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Export these methods.
|
|
30
|
+
*/
|
|
31
|
+
export function shallowWithIntl(node) {
|
|
32
|
+
return shallow(nodeWithIntlProp(node), { context: { intl } });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function mountWithIntl(node) {
|
|
36
|
+
return mount(nodeWithIntlProp(node), {
|
|
37
|
+
context: { intl },
|
|
38
|
+
childContextTypes: { intl: intlShape },
|
|
39
|
+
});
|
|
40
|
+
}
|
package/index.js
CHANGED
|
@@ -83,6 +83,10 @@ import CreativesContainer from './v2Containers/CreativesContainer';
|
|
|
83
83
|
import CreativesContainerReducer from './v2Containers/CreativesContainer/reducer';
|
|
84
84
|
import { updateCharCount } from './utils/smsCharCountV2';
|
|
85
85
|
|
|
86
|
+
import SmsTraiCreate from './v2Containers/SmsTrai/Create';
|
|
87
|
+
import SmsTraiCreateReducer from './v2Containers/SmsTrai/Create/reducer';
|
|
88
|
+
import SmsTraiCreateSaga from './v2Containers/SmsTrai/Create/sagas';
|
|
89
|
+
|
|
86
90
|
export {default as Ebill} from './v2Containers/Ebill';
|
|
87
91
|
export {default as EbillReducer} from './v2Containers/Ebill/reducer';
|
|
88
92
|
export {default as EbillSaga} from './v2Containers/Ebill/sagas';
|
|
@@ -106,6 +110,7 @@ const TemplatesV2Container = {TemplatesV2, templateReducer, templateSaga};
|
|
|
106
110
|
const FacebookContainer = {Facebook, facebookReducer, facebookSaga};
|
|
107
111
|
const ViberContainer = {Viber, viberReducer, viberSaga};
|
|
108
112
|
const FacebookPreviewContainer = { FacebookPreview, facebookPreviewReducer, facebookPreviewSaga };
|
|
113
|
+
const SmsTraiContainer = {SmsTraiCreate, SmsTraiCreateReducer, SmsTraiCreateSaga};
|
|
109
114
|
|
|
110
115
|
const GalleryContainer = {Gallery, galleryReducer, gallerySagas};
|
|
111
116
|
const FTPContainer = {FTP, FTPReducer, FTPSagas};
|
|
@@ -151,4 +156,5 @@ export { CapContainer,
|
|
|
151
156
|
FTPContainer,
|
|
152
157
|
ViberContainer,
|
|
153
158
|
FacebookPreviewContainer,
|
|
159
|
+
SmsTraiContainer,
|
|
154
160
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capillarytech/creatives-library",
|
|
3
3
|
"author": "meharaj",
|
|
4
|
-
"version": "7.9.
|
|
4
|
+
"version": "7.9.15",
|
|
5
5
|
"description": "Capillary creatives ui",
|
|
6
6
|
"main": "./index.js",
|
|
7
7
|
"module": "./index.es.js",
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
},
|
|
13
13
|
"license": "LicenseRef-LICENSE",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@babel/polyfill": "7.4.3",
|
|
16
15
|
"@bugsnag/js": "^7.2.1",
|
|
17
16
|
"@bugsnag/plugin-react": "^7.2.1",
|
|
18
17
|
"@capillarytech/cap-ui-utils": "1.4.0",
|
|
@@ -24,7 +23,9 @@
|
|
|
24
23
|
"jquery": "^3.3.1",
|
|
25
24
|
"load-script": "^1.0.0",
|
|
26
25
|
"normalizr": "^3.2.3",
|
|
26
|
+
"papaparse": "^5.3.1",
|
|
27
27
|
"react-datepicker": "^0.46.0",
|
|
28
|
+
"react-dropzone": "^11.3.4",
|
|
28
29
|
"react-router": "^3.2.0",
|
|
29
30
|
"react-router-dom": "^4.2.2",
|
|
30
31
|
"redux": "3.6.0",
|
package/routes.js
CHANGED
|
@@ -639,6 +639,8 @@ export default function createRoutes(store) {
|
|
|
639
639
|
import('v2Containers/Viber/reducer'),
|
|
640
640
|
import('v2Containers/CapFacebookPreview/sagas'),
|
|
641
641
|
import('v2Containers/CapFacebookPreview/reducer'),
|
|
642
|
+
import('v2Containers/SmsTrai/Create/sagas'),
|
|
643
|
+
import('v2Containers/SmsTrai/Create/reducer'),
|
|
642
644
|
]);
|
|
643
645
|
|
|
644
646
|
const renderRoute = loadModule(cb);
|
|
@@ -661,6 +663,7 @@ export default function createRoutes(store) {
|
|
|
661
663
|
lineCreateSagas, lineCreateReducer,
|
|
662
664
|
viberSagas, viberReducer,
|
|
663
665
|
capFacebookPreviewSagas, capFacebookPreviewReducer,
|
|
666
|
+
smsTraiSagas, smsTraiReducer,
|
|
664
667
|
]) => {
|
|
665
668
|
injectReducer('templates', reducer.default);
|
|
666
669
|
injectReducer('cap', capReducer.default);
|
|
@@ -679,6 +682,7 @@ export default function createRoutes(store) {
|
|
|
679
682
|
injectReducer('lineCreate', lineCreateReducer.default);
|
|
680
683
|
injectReducer('viber', viberReducer.default);
|
|
681
684
|
injectReducer('facebookPreview', capFacebookPreviewReducer.default);
|
|
685
|
+
injectReducer('smsTrai', smsTraiReducer.default);
|
|
682
686
|
injectSagas(gallerySagas.default);
|
|
683
687
|
injectSagas(sagas.default);
|
|
684
688
|
injectSagas(capSagas.default);
|
|
@@ -696,6 +700,7 @@ export default function createRoutes(store) {
|
|
|
696
700
|
injectSagas(lineCreateSagas.default);
|
|
697
701
|
injectSagas(viberSagas.default);
|
|
698
702
|
injectSagas(capFacebookPreviewSagas.default);
|
|
703
|
+
injectSagas(smsTraiSagas.default);
|
|
699
704
|
renderRoute(component);
|
|
700
705
|
});
|
|
701
706
|
importModules.catch(errorLoading);
|
package/services/api.js
CHANGED
|
@@ -40,7 +40,7 @@ function getUrlWithQueryParams({url, queryParams}) {
|
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
return updatedUrl;
|
|
43
|
-
}
|
|
43
|
+
}
|
|
44
44
|
|
|
45
45
|
// const loginUrl = (process.env.NODE_ENV === 'production') ?
|
|
46
46
|
// config.production.login_url : config.development.login_url;
|
|
@@ -81,7 +81,7 @@ function checkStatus(response) {
|
|
|
81
81
|
description: `API Error ${requestCallerName} returned ${status}`,
|
|
82
82
|
fatal: true,
|
|
83
83
|
apiError: true,
|
|
84
|
-
statusCode: status
|
|
84
|
+
statusCode: status,
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
if ((status >= 200 && status < 300) || [500, 409, 413].includes(response.status)) {
|
|
@@ -99,7 +99,7 @@ function request(url, options) {
|
|
|
99
99
|
try {
|
|
100
100
|
requestCallerName = getCallerName();
|
|
101
101
|
} catch (e) {
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
}
|
|
104
104
|
const fetchUrl = url.indexOf('?') !== -1 ? `${url}&time=${Date.now()}` : `${url}?time=${Date.now()}`;
|
|
105
105
|
return fetch(fetchUrl, options)
|
|
@@ -197,36 +197,31 @@ export const getSidebar = () => {
|
|
|
197
197
|
};
|
|
198
198
|
|
|
199
199
|
export const getUserData = () => {
|
|
200
|
-
const url = `${API_AUTH_ENDPOINT}/user`;
|
|
200
|
+
const url = `${API_AUTH_ENDPOINT}/user?include_features=1`;
|
|
201
201
|
return request(url, getAPICallObject('GET'));
|
|
202
202
|
};
|
|
203
203
|
|
|
204
204
|
export const createTemplate = ({template}) => {
|
|
205
|
-
|
|
206
205
|
const url = `${API_ENDPOINT}/templates/SMS`;
|
|
207
206
|
return request(url, getAPICallObject('POST', template));
|
|
208
207
|
};
|
|
209
208
|
|
|
210
209
|
export const editTemplate = ({template}) => {
|
|
211
|
-
|
|
212
210
|
const url = `${API_ENDPOINT}/templates/SMS`;
|
|
213
211
|
return request(url, getAPICallObject('POST', template));
|
|
214
212
|
};
|
|
215
213
|
|
|
216
214
|
export const createWeChatTemplate = ({template}) => {
|
|
217
|
-
|
|
218
215
|
const url = `${API_ENDPOINT}/templates/WECHAT`;
|
|
219
216
|
return request(url, getAPICallObject('POST', template));
|
|
220
217
|
};
|
|
221
218
|
|
|
222
219
|
export const createMobilePushTemplate = ({template}) => {
|
|
223
|
-
|
|
224
220
|
const url = `${API_ENDPOINT}/templates/MOBILEPUSH`;
|
|
225
221
|
return request(url, getAPICallObject('POST', template));
|
|
226
222
|
};
|
|
227
223
|
|
|
228
224
|
export const duplicateTemplate = ({id, channel}) => {
|
|
229
|
-
|
|
230
225
|
const url = `${API_ENDPOINT}/templates/duplicate/${id}/${channel}`;
|
|
231
226
|
return request(url, getAPICallObject('GET'));
|
|
232
227
|
};
|
|
@@ -237,25 +232,21 @@ export const getFTPServers = () => {
|
|
|
237
232
|
};
|
|
238
233
|
|
|
239
234
|
export const editWeChatTemplate = ({template}) => {
|
|
240
|
-
|
|
241
235
|
const url = `${API_ENDPOINT}/templates/WECHAT`;
|
|
242
236
|
return request(url, getAPICallObject('POST', template));
|
|
243
237
|
};
|
|
244
238
|
|
|
245
239
|
export const createEmailTemplate = ({template}) => {
|
|
246
|
-
|
|
247
240
|
const url = `${API_ENDPOINT}/templates/EMAIL`;
|
|
248
241
|
return request(url, getAPICallObject('POST', template));
|
|
249
242
|
};
|
|
250
243
|
|
|
251
244
|
export const createEbillTemplate = ({template}) => {
|
|
252
|
-
|
|
253
245
|
const url = `${API_ENDPOINT}/templates/EBILL`;
|
|
254
246
|
return request(url, getAPICallObject('POST', template));
|
|
255
247
|
};
|
|
256
248
|
|
|
257
249
|
export const getTemplateDetails = ({id, channel}) => {
|
|
258
|
-
|
|
259
250
|
const url = `${API_ENDPOINT}/templates/${id}/${channel ? channel.toUpperCase() : 'SMS'}`;
|
|
260
251
|
return request(url, getAPICallObject('GET'));
|
|
261
252
|
};
|
|
@@ -367,7 +358,6 @@ export const getCmsData = (cmsType, projectId, langId) => {
|
|
|
367
358
|
};
|
|
368
359
|
|
|
369
360
|
export const getEdmTemplates = () => {
|
|
370
|
-
|
|
371
361
|
const url = `${API_ENDPOINT}/templates/email/default`;
|
|
372
362
|
return request(url, getAPICallObject('GET'));
|
|
373
363
|
};
|
|
@@ -380,7 +370,6 @@ export const getDefaultBeeTemplates = () => {
|
|
|
380
370
|
// All about line
|
|
381
371
|
|
|
382
372
|
export const createLineTemplate = ({template}) => {
|
|
383
|
-
|
|
384
373
|
const url = `${API_ENDPOINT}/templates/LINE`;
|
|
385
374
|
return request(url, getAPICallObject('POST', template));
|
|
386
375
|
};
|
|
@@ -449,3 +438,8 @@ export const getFacebookVideoId = ({videoUrl, accessToken, actId, pageAccessToke
|
|
|
449
438
|
const url = `${API_ENDPOINT}/facebook/getFacebookVideoId`;
|
|
450
439
|
return request(url, getAPICallObject('POST', {videoUrl, accessToken, actId, pageAccessToken, pageId}));
|
|
451
440
|
};
|
|
441
|
+
|
|
442
|
+
export const createBulkSMSTemplate = ({templates}) => {
|
|
443
|
+
const url = `${API_ENDPOINT}/templates/bulk/sms`;
|
|
444
|
+
return request(url, getAPICallObject('POST', templates));
|
|
445
|
+
};
|
package/utils/common.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import { Auth } from '@capillarytech/cap-ui-utils';
|
|
3
|
-
import { STORE2DOOR_PLUS_ENABLED } from '../containers/App/constants';
|
|
3
|
+
import { STORE2DOOR_PLUS_ENABLED, TRAI_DLT } from '../containers/App/constants';
|
|
4
4
|
|
|
5
5
|
export function getUserNameById(userId, allUserList) {
|
|
6
6
|
let userName = "";
|
|
@@ -38,9 +38,16 @@ export const hasStore2DoorFeature = Auth.hasFeatureAccess.bind(
|
|
|
38
38
|
STORE2DOOR_PLUS_ENABLED,
|
|
39
39
|
);
|
|
40
40
|
|
|
41
|
-
export
|
|
41
|
+
export const hasTraiDltFeature = Auth.hasFeatureAccess.bind(
|
|
42
|
+
null,
|
|
43
|
+
TRAI_DLT,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
export function getTreeStructuredTags({tagsList, userLocale = 'en', offerDetails = [], disableTagsDetails = {}}) {
|
|
42
47
|
console.log('populating tags', (tagsList || []).length);
|
|
43
48
|
const mainTags = {};
|
|
49
|
+
const { disableRelatedTags, childTagsToDisable, parentTagstoDisable} = disableTagsDetails;
|
|
50
|
+
|
|
44
51
|
|
|
45
52
|
_.forEach(tagsList, (temp) => {
|
|
46
53
|
const tag = temp.definition;
|
|
@@ -48,6 +55,7 @@ export function getTreeStructuredTags({tagsList, userLocale = 'en', offerDetails
|
|
|
48
55
|
mainTags[tag.value] = {
|
|
49
56
|
name: tag.label[userLocale] || tag.label.en,
|
|
50
57
|
value: tag.value,
|
|
58
|
+
disabled: disableRelatedTags ? childTagsToDisable.includes(tag.value) : false,
|
|
51
59
|
};
|
|
52
60
|
} else if (tag['tag-header'] && mainTags[tag.value]) {
|
|
53
61
|
// to check it this tag header is already available in mainTags object,
|
|
@@ -60,6 +68,7 @@ export function getTreeStructuredTags({tagsList, userLocale = 'en', offerDetails
|
|
|
60
68
|
"name": tag.label[userLocale] || tag.label.en,
|
|
61
69
|
"subtags": tag.subtags,
|
|
62
70
|
"value": tag.value,
|
|
71
|
+
"disabled": disableRelatedTags ? parentTagstoDisable.includes(tag.value) : false,
|
|
63
72
|
};
|
|
64
73
|
}
|
|
65
74
|
});
|
|
@@ -175,17 +184,19 @@ function populateTagForChildren(targetTag, tagsObject, tagValue) {
|
|
|
175
184
|
function getTreeStructureData(data) {
|
|
176
185
|
const result = [];
|
|
177
186
|
_.forOwn(data, (mainTag) => {
|
|
178
|
-
const { name, value, subtags = [] } = mainTag;
|
|
187
|
+
const { name, value, subtags = [], disabled } = mainTag;
|
|
179
188
|
if (!mainTag['tag-header']) {
|
|
180
189
|
result.push({
|
|
181
190
|
title: name,
|
|
182
191
|
value: `{{${value}}}`,
|
|
192
|
+
disabled,
|
|
183
193
|
});
|
|
184
194
|
} else {
|
|
185
195
|
const obj = {
|
|
186
196
|
title: name,
|
|
187
197
|
value: `{{${value}}}`,
|
|
188
198
|
selectable: false,
|
|
199
|
+
disabled,
|
|
189
200
|
};
|
|
190
201
|
obj.children = getSubTags(subtags);
|
|
191
202
|
result.push(obj);
|
|
@@ -197,17 +208,19 @@ function getTreeStructureData(data) {
|
|
|
197
208
|
function getSubTags(subtagsParam) {
|
|
198
209
|
const result = [];
|
|
199
210
|
_.forOwn(subtagsParam, (subTag) => {
|
|
200
|
-
const { name, value, subtags = [] } = subTag;
|
|
211
|
+
const { name, value, subtags = [], disabled } = subTag;
|
|
201
212
|
if (_.isEmpty(subtags)) {
|
|
202
213
|
result.push({
|
|
203
214
|
title: name,
|
|
204
215
|
value: `{{${value}}}`,
|
|
216
|
+
disabled,
|
|
205
217
|
});
|
|
206
218
|
} else {
|
|
207
219
|
const obj = {
|
|
208
220
|
title: name,
|
|
209
221
|
value: `{{${value}}}`,
|
|
210
222
|
selectable: false,
|
|
223
|
+
disabled,
|
|
211
224
|
};
|
|
212
225
|
obj.children = getSubTags(subtags);
|
|
213
226
|
result.push(obj);
|
|
@@ -5,19 +5,20 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
|
-
|
|
9
8
|
import React from 'react';
|
|
9
|
+
import { connect } from 'react-redux';
|
|
10
10
|
// import styled from 'styled-components';
|
|
11
|
-
import { CapSpin, CapModal, CapButton, CapPopover, CapInput, CapTree, CapSelect } from '@capillarytech/cap-ui-library';
|
|
11
|
+
import { CapSpin, CapModal, CapButton, CapPopover, CapInput, CapTree, CapSelect, CapTooltip } from '@capillarytech/cap-ui-library';
|
|
12
12
|
|
|
13
13
|
import _ from 'lodash';
|
|
14
|
-
import { injectIntl, intlShape } from 'react-intl';
|
|
14
|
+
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
|
15
|
+
import { createStructuredSelector } from 'reselect';
|
|
15
16
|
import messages from './messages';
|
|
17
|
+
import { makeSelectLoyaltyPromotionDisplay } from '../../v2Containers/Cap/selectors';
|
|
16
18
|
|
|
17
19
|
const {Search} = CapInput;
|
|
18
20
|
const {CapTreeNode} = CapTree;
|
|
19
21
|
class CapTagList extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
20
|
-
|
|
21
22
|
constructor(props) {
|
|
22
23
|
super(props);
|
|
23
24
|
this.state = {
|
|
@@ -132,23 +133,39 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
132
133
|
};
|
|
133
134
|
|
|
134
135
|
renderTags(tags, searchString = '') {
|
|
136
|
+
const { disableRelatedTags, childTagsToDisable, parentTagstoDisable} = this.props.disableTagsDetails;
|
|
135
137
|
const list = [];
|
|
138
|
+
const loyaltyAttrDisableText = <FormattedMessage {...messages.loyaltyAttributeDisable} />;
|
|
136
139
|
_.forEach(tags, (val = '', key) => {
|
|
137
140
|
let supportedTagsString = '';
|
|
138
141
|
_.forEach(val.supportedTags, (supportedTag) => {
|
|
139
142
|
supportedTagsString += `${supportedTag} ,`;
|
|
140
143
|
});
|
|
141
144
|
supportedTagsString = supportedTagsString.replace(/,\s*$/, "");
|
|
142
|
-
|
|
143
145
|
if (_.has(val, 'subtags')) {
|
|
144
|
-
const
|
|
146
|
+
const disabled = disableRelatedTags ? parentTagstoDisable.includes(key) : false;
|
|
147
|
+
const temp = this.renderTags(val.subtags, '', disabled);
|
|
145
148
|
list.push((
|
|
146
|
-
<CapTreeNode
|
|
149
|
+
<CapTreeNode
|
|
150
|
+
title={disabled ? <CapTooltip title={loyaltyAttrDisableText}>{val.name}</CapTooltip> : val.name}
|
|
151
|
+
tag={val}
|
|
152
|
+
key={val.couponSeriesId ? `${key}(${val.couponSeriesId})` : `${key}`}
|
|
153
|
+
disabled={disabled}
|
|
154
|
+
>
|
|
147
155
|
{temp}
|
|
148
156
|
</CapTreeNode>
|
|
149
157
|
));
|
|
150
158
|
} else if (searchString === '' || !searchString || ((val.name || '').toLowerCase().indexOf(searchString.toLowerCase()) !== -1)) {
|
|
151
|
-
const
|
|
159
|
+
const childDisabled = disableRelatedTags ? childTagsToDisable.includes(key) : false;
|
|
160
|
+
const tempNode = (
|
|
161
|
+
<CapTreeNode
|
|
162
|
+
title={childDisabled ? <CapTooltip title={loyaltyAttrDisableText}>{val.desc || val.name}</CapTooltip> : (val.desc || val.name)}
|
|
163
|
+
tag={val}
|
|
164
|
+
isLeaf
|
|
165
|
+
key={val.couponSeriesId ? `${key}(${val.couponSeriesId})` : `${key}`}
|
|
166
|
+
disabled={childDisabled}
|
|
167
|
+
>
|
|
168
|
+
</CapTreeNode>);
|
|
152
169
|
list.push(tempNode);
|
|
153
170
|
}
|
|
154
171
|
});
|
|
@@ -253,10 +270,22 @@ CapTagList.propTypes = {
|
|
|
253
270
|
visibleTaglist: PropTypes.bool,
|
|
254
271
|
hidePopover: PropTypes.bool,
|
|
255
272
|
modalProps: PropTypes.any,
|
|
273
|
+
disableTagsDetails: PropTypes.object,
|
|
256
274
|
};
|
|
257
275
|
|
|
258
276
|
CapTagList.defaultValue = {
|
|
259
277
|
hidePopover: false,
|
|
260
278
|
};
|
|
261
279
|
|
|
262
|
-
|
|
280
|
+
function mapDispatchToProps() {
|
|
281
|
+
return {
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const mapStateToProps = createStructuredSelector({
|
|
286
|
+
disableTagsDetails: makeSelectLoyaltyPromotionDisplay(),
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(CapTagList));
|
|
291
|
+
|
|
@@ -42,4 +42,8 @@ export default defineMessages({
|
|
|
42
42
|
id: 'creatives.componentsV2.CapTagList.search',
|
|
43
43
|
defaultMessage: 'Search',
|
|
44
44
|
},
|
|
45
|
+
"loyaltyAttributeDisable": {
|
|
46
|
+
id: `creatives.componentsV2.CapTagList.loyaltyAttributeDisable`,
|
|
47
|
+
defaultMessage: 'You won’t be able to add loyalty related attributes since the loyalty program/ card series is None.',
|
|
48
|
+
},
|
|
45
49
|
});
|
|
@@ -28,6 +28,8 @@ export const GET_TOPBAR_MENU_DATA_SUCCESS = 'creatives/cap/GET_TOPBAR_MENU_DATA_
|
|
|
28
28
|
export const GET_TOPBAR_MENU_DATA_FAILURE = 'creatives/cap/GET_TOPBAR_MENU_DATA_FAILURE';
|
|
29
29
|
export const CLEAR_TOPBAR_MENU_DATA = 'creatives/cap/CLEAR_TOPBAR_MENU_DATA';
|
|
30
30
|
|
|
31
|
+
export const SET_LOYALTY_PROMOTION_RELATED_CREATIVE_TAGS_DISPLAY = 'SET_LOYALTY_PROMOTION_RELATED_CREATIVE_TAGS_DISPLAY';
|
|
32
|
+
|
|
31
33
|
export const CAMPAIGN_SETTINGS_URL = '/creatives/settings/message';
|
|
32
34
|
export const ORG_SETTINGS_URL = '/org/index';
|
|
33
35
|
export const HELP_URL = 'https://support.capillarytech.com/en/support/solutions/4000007853';
|
|
@@ -9,7 +9,7 @@ import { createStructuredSelector } from 'reselect';
|
|
|
9
9
|
import _ from 'lodash';
|
|
10
10
|
import moment from 'moment';
|
|
11
11
|
// import 'moment/locale/zh-cn';
|
|
12
|
-
import { GA, multipleOrgSwitch, utilsSessionStorageApi } from '@capillarytech/cap-ui-utils';
|
|
12
|
+
import { GA, multipleOrgSwitch, utilsSessionStorageApi, Auth } from '@capillarytech/cap-ui-utils';
|
|
13
13
|
import { injectIntl, FormattedMessage, intlShape, FormattedHTMLMessage } from 'react-intl';
|
|
14
14
|
import messages from './messages';
|
|
15
15
|
import { makeSelectAuthenticated, makeSelectUser } from './selectors';
|
|
@@ -28,7 +28,6 @@ import {
|
|
|
28
28
|
ORG_CHANGED,
|
|
29
29
|
} from './constants';
|
|
30
30
|
import './_cap.scss';
|
|
31
|
-
|
|
32
31
|
const gtm = window.dataLayer || [];
|
|
33
32
|
const {
|
|
34
33
|
logNewTab,
|
|
@@ -75,12 +74,20 @@ export class Cap extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
75
74
|
const { pathname } = this.props.location;
|
|
76
75
|
const parentModule = pathname.substring(pathname.lastIndexOf('/') + 1);
|
|
77
76
|
this.props.actions.getUserData((userData) => {
|
|
77
|
+
const { currentOrgDetails } = this.props.Global || {};
|
|
78
|
+
const { accessibleFeatures = [] } = currentOrgDetails || {};
|
|
78
79
|
if (!userData.accessiblePermissions.includes(CREATIVES_UI_VIEW)) {
|
|
79
80
|
this.setState({ isCreativesAccessible: false });
|
|
80
81
|
}
|
|
81
82
|
const userGtmData = this.getUserGtmData();
|
|
82
83
|
this.setDimensionData(userGtmData);
|
|
83
84
|
gtm.push({...userGtmData, event: 'userAuthenticated'});
|
|
85
|
+
Auth.initialize({
|
|
86
|
+
permissions: userData.accessiblePermissions,
|
|
87
|
+
isCapUser: userData.isCapUser,
|
|
88
|
+
roles: Object.keys(userData.accessRoles),
|
|
89
|
+
accessibleFeatures,
|
|
90
|
+
});
|
|
84
91
|
});
|
|
85
92
|
this.props.actions.getTopbarMenuData(parentModule);
|
|
86
93
|
if (this.props.Global.orgID !== undefined) {
|
|
@@ -82,7 +82,6 @@ function capReducer(state = fromJS(initialState.cap), action) {
|
|
|
82
82
|
.set('fetchingSchema', false);
|
|
83
83
|
case types.GET_SCHEMA_FOR_ENTITY_SUCCESS: {
|
|
84
84
|
const stateMeta = state.get('metaEntities');
|
|
85
|
-
|
|
86
85
|
return state
|
|
87
86
|
.set('fetchingSchema', false)
|
|
88
87
|
.set('metaEntities', {
|
|
@@ -117,6 +116,11 @@ function capReducer(state = fromJS(initialState.cap), action) {
|
|
|
117
116
|
);
|
|
118
117
|
case types.CLEAR_TOPBAR_MENU_DATA:
|
|
119
118
|
return state.set('topbarMenuData', fromJS({}));
|
|
119
|
+
case types.SET_LOYALTY_PROMOTION_RELATED_CREATIVE_TAGS_DISPLAY: {
|
|
120
|
+
return state.set('disableLoyaltyPromotionRelatedTags', action.disable)
|
|
121
|
+
.set('tagsToDisable', action.tagsToDisable)
|
|
122
|
+
.set('parentTagsToDisable', action.parentTagsToDisable);
|
|
123
|
+
}
|
|
120
124
|
default:
|
|
121
125
|
return state;
|
|
122
126
|
}
|
|
@@ -31,7 +31,6 @@ const setInjectedTags = () => createSelector(
|
|
|
31
31
|
const { tags } = metaEntities;
|
|
32
32
|
const customTags = tags && (tags.custom || {});
|
|
33
33
|
const extendedTags = tags && (tags.extended || {});
|
|
34
|
-
|
|
35
34
|
return (injectedTags = _.merge({}, injectedTags, customTags, extendedTags));
|
|
36
35
|
}
|
|
37
36
|
);
|
|
@@ -74,6 +73,15 @@ const makeSelectFetchingSchema = () => createSelector(
|
|
|
74
73
|
(globalState) => globalState.get('fetchingSchema')
|
|
75
74
|
);
|
|
76
75
|
|
|
76
|
+
const makeSelectLoyaltyPromotionDisplay = () => createSelector(
|
|
77
|
+
selectCapDomain,
|
|
78
|
+
(globalState) => ({
|
|
79
|
+
disableRelatedTags: globalState.get('disableLoyaltyPromotionRelatedTags'),
|
|
80
|
+
childTagsToDisable: globalState.get('tagsToDisable') || [],
|
|
81
|
+
parentTagstoDisable: globalState.get('parentTagsToDisable') || [],
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
|
|
77
85
|
export {
|
|
78
86
|
makeSelectLocationState,
|
|
79
87
|
makeSelectAuthenticated,
|
|
@@ -85,4 +93,5 @@ export {
|
|
|
85
93
|
isLoadingMetaEntities,
|
|
86
94
|
makeSelectFetchingSchema,
|
|
87
95
|
setInjectedTags,
|
|
96
|
+
makeSelectLoyaltyPromotionDisplay,
|
|
88
97
|
};
|
|
@@ -5,8 +5,8 @@ import get from 'lodash/get';
|
|
|
5
5
|
import cloneDeep from 'lodash/cloneDeep';
|
|
6
6
|
import TemplatesV2 from '../TemplatesV2';
|
|
7
7
|
import TemplatePreview from '../../v2Components/TemplatePreview';
|
|
8
|
-
import
|
|
9
|
-
import SmsEdit from '../Sms/Edit';
|
|
8
|
+
import SmsWrapper from '../SmsWrapper';
|
|
9
|
+
// import SmsEdit from '../Sms/Edit';
|
|
10
10
|
import Email from '../Email';
|
|
11
11
|
import EmailWrapper from '../EmailWrapper';
|
|
12
12
|
import MobilepushWrapper from '../MobilepushWrapper';
|
|
@@ -394,8 +394,9 @@ function SlideBoxContent(props) {
|
|
|
394
394
|
/>
|
|
395
395
|
}
|
|
396
396
|
{isEditSms && (
|
|
397
|
-
<
|
|
397
|
+
<SmsWrapper
|
|
398
398
|
setIsLoadingContent={setIsLoadingContent}
|
|
399
|
+
isEditSms={isEditSms}
|
|
399
400
|
location={creativesLocationProps}
|
|
400
401
|
isFullMode={isFullMode}
|
|
401
402
|
route={{ name: 'sms' }}
|
|
@@ -408,6 +409,8 @@ function SlideBoxContent(props) {
|
|
|
408
409
|
selectedOfferDetails={selectedOfferDetails}
|
|
409
410
|
onPreviewContentClicked={onPreviewContentClicked}
|
|
410
411
|
onTestContentClicked={onTestContentClicked}
|
|
412
|
+
handleClose={handleClose}
|
|
413
|
+
onCreateComplete={onCreateComplete}
|
|
411
414
|
/>
|
|
412
415
|
)}
|
|
413
416
|
{isEditFTP && (
|
|
@@ -440,10 +443,11 @@ function SlideBoxContent(props) {
|
|
|
440
443
|
/>
|
|
441
444
|
}
|
|
442
445
|
{isCreateSms && (
|
|
443
|
-
<
|
|
446
|
+
<SmsWrapper
|
|
444
447
|
setIsLoadingContent={setIsLoadingContent}
|
|
445
448
|
location={creativesLocationProps}
|
|
446
449
|
route={{ name: 'sms' }}
|
|
450
|
+
isCreateSms={isCreateSms}
|
|
447
451
|
isComponent
|
|
448
452
|
isGetFormData={isGetFormData}
|
|
449
453
|
getFormSubscriptionData={getFormData}
|
|
@@ -453,8 +457,10 @@ function SlideBoxContent(props) {
|
|
|
453
457
|
selectedOfferDetails={selectedOfferDetails}
|
|
454
458
|
onPreviewContentClicked={onPreviewContentClicked}
|
|
455
459
|
onTestContentClicked={onTestContentClicked}
|
|
460
|
+
onCreateComplete={onCreateComplete}
|
|
456
461
|
/>
|
|
457
462
|
)}
|
|
463
|
+
|
|
458
464
|
{isEmailCreate && (
|
|
459
465
|
<EmailWrapper
|
|
460
466
|
key="creatives-email-wrapper"
|