@capillarytech/creatives-library 7.17.91 → 7.17.92
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/index.js +6 -0
- package/package.json +1 -1
- package/routes.js +5 -0
- package/services/api.js +5 -0
- package/v2Components/CapDeviceContent/index.js +338 -0
- package/v2Components/CapDeviceContent/index.scss +115 -0
- package/v2Components/CapDeviceContent/messages.js +107 -0
- package/v2Components/CapDeviceContent/tests/index.test.js +75 -0
- package/v2Components/CapImageUpload/index.js +10 -3
- package/v2Components/CapImageUpload/messages.js +4 -0
- package/v2Components/CapInAppCTA/constants.js +25 -0
- package/v2Components/CapInAppCTA/index.js +281 -0
- package/v2Components/CapInAppCTA/index.scss +93 -0
- package/v2Components/CapInAppCTA/messages.js +85 -0
- package/v2Components/MobilePushPreviewV2/index.js +81 -23
- package/v2Components/TemplatePreview/_templatePreview.scss +448 -0
- package/v2Components/TemplatePreview/assets/images/inapp_mobile_android_bottom.svg +11 -0
- package/v2Components/TemplatePreview/assets/images/inapp_mobile_android_full.svg +11 -0
- package/v2Components/TemplatePreview/assets/images/inapp_mobile_android_modal.svg +11 -0
- package/v2Components/TemplatePreview/assets/images/inapp_mobile_android_top.svg +11 -0
- package/v2Components/TemplatePreview/assets/images/inapp_mobile_ios_bottom.svg +6 -0
- package/v2Components/TemplatePreview/assets/images/inapp_mobile_ios_full.svg +18 -0
- package/v2Components/TemplatePreview/assets/images/inapp_mobile_ios_modal.svg +7 -0
- package/v2Components/TemplatePreview/assets/images/inapp_mobile_ios_top.svg +13 -0
- package/v2Components/TemplatePreview/index.js +660 -375
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Containers/App/constants.js +1 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +43 -0
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +4 -1
- package/v2Containers/CreativesContainer/constants.js +1 -0
- package/v2Containers/CreativesContainer/index.js +94 -27
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/InApp/actions.js +64 -0
- package/v2Containers/InApp/constants.js +95 -0
- package/v2Containers/InApp/index.js +745 -0
- package/v2Containers/InApp/index.scss +47 -0
- package/v2Containers/InApp/messages.js +86 -0
- package/v2Containers/InApp/reducer.js +109 -0
- package/v2Containers/InApp/sagas.js +143 -0
- package/v2Containers/InApp/selectors.js +12 -0
- package/v2Containers/InApp/tests/action.test.js +53 -0
- package/v2Containers/InApp/tests/index.test.js +152 -0
- package/v2Containers/InApp/tests/mockData.js +897 -0
- package/v2Containers/InApp/tests/reducer.test.js +177 -0
- package/v2Containers/InApp/tests/sagas.test.js +391 -0
- package/v2Containers/Templates/_templates.scss +7 -0
- package/v2Containers/Templates/index.js +103 -23
- package/v2Containers/Templates/messages.js +20 -0
- package/v2Containers/TemplatesV2/index.js +8 -2
- package/v2Containers/TemplatesV2/messages.js +4 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
@import '~@capillarytech/cap-ui-library/styles/_variables.scss';
|
|
2
|
+
|
|
3
|
+
.cap-inapp-creatives {
|
|
4
|
+
.inapp-template-name-input {
|
|
5
|
+
width: 23.286rem;
|
|
6
|
+
margin-top: $CAP_SPACE_04;
|
|
7
|
+
}
|
|
8
|
+
.inapp-creative-layout {
|
|
9
|
+
margin-top: $CAP_SPACE_24;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.inapp-creative-layout-desc {
|
|
13
|
+
font-size: $CAP_SPACE_12;
|
|
14
|
+
color: $CAP_G04;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.inapp-layout-radio {
|
|
18
|
+
margin-top: $CAP_SPACE_16;
|
|
19
|
+
font-weight: 500;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.inapp-template-device-tab {
|
|
23
|
+
margin-top: $CAP_SPACE_24;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
#inapp-template-name-input {
|
|
27
|
+
height: $CAP_SPACE_40;
|
|
28
|
+
width: 23.286rem;
|
|
29
|
+
margin-top: $CAP_SPACE_04;
|
|
30
|
+
}
|
|
31
|
+
#inapp-title-name-input {
|
|
32
|
+
height: $CAP_SPACE_40;
|
|
33
|
+
}
|
|
34
|
+
.inapp-media-radio .ant-radio-wrapper {
|
|
35
|
+
margin-right: $CAP_SPACE_24;
|
|
36
|
+
}
|
|
37
|
+
.inapp-footer {
|
|
38
|
+
background-color: $CAP_WHITE;
|
|
39
|
+
bottom: 0;
|
|
40
|
+
width: 100%;
|
|
41
|
+
padding: $CAP_SPACE_20 0;
|
|
42
|
+
z-index: 1;
|
|
43
|
+
margin-top: $CAP_SPACE_12;
|
|
44
|
+
.ant-btn {
|
|
45
|
+
margin-right: $CAP_SPACE_16;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { defineMessages } from "react-intl";
|
|
2
|
+
|
|
3
|
+
const prefix = "app.v2Container.InApp";
|
|
4
|
+
|
|
5
|
+
export default defineMessages({
|
|
6
|
+
creativeName: {
|
|
7
|
+
id: `${prefix}.creativeName`,
|
|
8
|
+
defaultMessage: "Creative Name",
|
|
9
|
+
},
|
|
10
|
+
creativeLayout: {
|
|
11
|
+
id: `${prefix}.creativeLayout`,
|
|
12
|
+
defaultMessage: "Creative layout",
|
|
13
|
+
},
|
|
14
|
+
creativeLayoutDesc: {
|
|
15
|
+
id: `${prefix}.creativeLayoutDesc`,
|
|
16
|
+
defaultMessage: "Select how the creative will be displayed on the screen",
|
|
17
|
+
},
|
|
18
|
+
layoutModal: {
|
|
19
|
+
id: `${prefix}.layoutModal`,
|
|
20
|
+
defaultMessage: "Modal",
|
|
21
|
+
},
|
|
22
|
+
layoutTopBanner: {
|
|
23
|
+
id: `${prefix}.layoutTopBanner`,
|
|
24
|
+
defaultMessage: "Top banner",
|
|
25
|
+
},
|
|
26
|
+
layoutBottomBanner: {
|
|
27
|
+
id: `${prefix}.layoutBottomBanner`,
|
|
28
|
+
defaultMessage: "Bottom banner",
|
|
29
|
+
},
|
|
30
|
+
layoutFullScreen: {
|
|
31
|
+
id: `${prefix}.layoutFullScreen`,
|
|
32
|
+
defaultMessage: "Full screen",
|
|
33
|
+
},
|
|
34
|
+
Android: {
|
|
35
|
+
id: `${prefix}.Android`,
|
|
36
|
+
defaultMessage: 'Android',
|
|
37
|
+
},
|
|
38
|
+
Ios: {
|
|
39
|
+
id: `${prefix}.Ios`,
|
|
40
|
+
defaultMessage: 'IOS',
|
|
41
|
+
},
|
|
42
|
+
select: {
|
|
43
|
+
id: `${prefix}.select`,
|
|
44
|
+
defaultMessage: "Select",
|
|
45
|
+
},
|
|
46
|
+
inAppCreateNotification: {
|
|
47
|
+
id: `${prefix}.inAppCreateNotification`,
|
|
48
|
+
defaultMessage: "{name} template created successfully",
|
|
49
|
+
},
|
|
50
|
+
inAppEditNotification: {
|
|
51
|
+
id: `${prefix}.inAppCreateNotification`,
|
|
52
|
+
defaultMessage: "{name} template edited successfully",
|
|
53
|
+
},
|
|
54
|
+
templateNameMinCharacters: {
|
|
55
|
+
id: `${prefix}.templateNameMinCharacters`,
|
|
56
|
+
defaultMessage: 'Template name should contain atleast 3 characters',
|
|
57
|
+
},
|
|
58
|
+
btnDisabledTooltip: {
|
|
59
|
+
id: `${prefix}.btnDisabledTooltip`,
|
|
60
|
+
defaultMessage: 'Please add all mandatory fields to proceed further',
|
|
61
|
+
},
|
|
62
|
+
create: {
|
|
63
|
+
id: `${prefix}.create`,
|
|
64
|
+
defaultMessage: 'Create',
|
|
65
|
+
},
|
|
66
|
+
update: {
|
|
67
|
+
id: `${prefix}.update`,
|
|
68
|
+
defaultMessage: 'Update',
|
|
69
|
+
},
|
|
70
|
+
mediaText: {
|
|
71
|
+
id: `${prefix}.mediaText`,
|
|
72
|
+
defaultMessage: "Text",
|
|
73
|
+
},
|
|
74
|
+
mediaImage: {
|
|
75
|
+
id: `${prefix}.mediaImage`,
|
|
76
|
+
defaultMessage: "Image",
|
|
77
|
+
},
|
|
78
|
+
templateMessageLength: {
|
|
79
|
+
id: `${prefix}.templateMessageLength`,
|
|
80
|
+
defaultMessage: 'Characters count: {currentLength}/{maxLength}',
|
|
81
|
+
},
|
|
82
|
+
templateNameRegexErrorMessage: {
|
|
83
|
+
id: `${prefix}.templateNameRegexErrorMessage`,
|
|
84
|
+
defaultMessage: 'Template name can only contain lowercase alphanumeric characters and underscores',
|
|
85
|
+
},
|
|
86
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { fromJS } from 'immutable';
|
|
2
|
+
import {
|
|
3
|
+
INAPP_TEMPLATE_CREATE_REQUEST,
|
|
4
|
+
INAPP_TEMPLATE_CREATE_SUCCESS,
|
|
5
|
+
INAPP_TEMPLATE_CREATE_FAILURE,
|
|
6
|
+
CLEAR_CREATE_RESPONSE_REQUEST,
|
|
7
|
+
GET_INAPP_TEMPLATE_DETAILS_REQUEST,
|
|
8
|
+
GET_INAPP_TEMPLATE_DETAILS_SUCCESS,
|
|
9
|
+
GET_INAPP_TEMPLATE_DETAILS_FAILURE,
|
|
10
|
+
RESET_EDIT_TEMPLATE,
|
|
11
|
+
UPLOAD_INAPP_ASSET_REQUEST,
|
|
12
|
+
UPLOAD_INAPP_ASSET_SUCCESS,
|
|
13
|
+
UPLOAD_INAPP_ASSET_FAILURE,
|
|
14
|
+
CLEAR_INAPP_ASSET,
|
|
15
|
+
INAPP_EDIT_TEMPLATE_REQUEST,
|
|
16
|
+
INAPP_EDIT_TEMPLATE_SUCCESS,
|
|
17
|
+
INAPP_EDIT_TEMPLATE_FAILURE,
|
|
18
|
+
} from './constants';
|
|
19
|
+
|
|
20
|
+
const initialState = fromJS({
|
|
21
|
+
uploadedAssetData: {},
|
|
22
|
+
createTemplateInProgress: false,
|
|
23
|
+
editTemplateInProgress: false,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
function inAppReducer(state = initialState, action) {
|
|
27
|
+
switch (action.type) {
|
|
28
|
+
case INAPP_TEMPLATE_CREATE_REQUEST:
|
|
29
|
+
return state
|
|
30
|
+
.set('createTemplateInProgress', true)
|
|
31
|
+
.set('createTemplateError', false)
|
|
32
|
+
.set('createTemplateErrorMessage', fromJS(''));
|
|
33
|
+
case INAPP_TEMPLATE_CREATE_SUCCESS:
|
|
34
|
+
return state
|
|
35
|
+
.set('createTemplateInProgress', false)
|
|
36
|
+
.set('response', action.data)
|
|
37
|
+
.set(
|
|
38
|
+
'createTemplateError',
|
|
39
|
+
action.statusCode !== undefined && action.statusCode > 300,
|
|
40
|
+
)
|
|
41
|
+
.set('createTemplateErrorMessage', fromJS(action.errorMsg));
|
|
42
|
+
case INAPP_TEMPLATE_CREATE_FAILURE:
|
|
43
|
+
return state
|
|
44
|
+
.set('createTemplateInProgress', false)
|
|
45
|
+
.set('createTemplateError', true)
|
|
46
|
+
.set('createTemplateErrorMessage', fromJS(action.errorMsg));
|
|
47
|
+
// FOR EDIT
|
|
48
|
+
case INAPP_EDIT_TEMPLATE_REQUEST:
|
|
49
|
+
return state
|
|
50
|
+
.set('editTemplateInProgress', true)
|
|
51
|
+
.set('editTemplateError', false)
|
|
52
|
+
.set('editTemplateErrorMessage', fromJS(''));
|
|
53
|
+
case INAPP_EDIT_TEMPLATE_SUCCESS:
|
|
54
|
+
return state
|
|
55
|
+
.set('editTemplateInProgress', false)
|
|
56
|
+
.set('editResponse', action.data)
|
|
57
|
+
.set('editTemplateError', action.statusCode !== undefined && action.statusCode > 300)
|
|
58
|
+
.set('editTemplateErrorMessage', fromJS(action.errorMsg));
|
|
59
|
+
case INAPP_EDIT_TEMPLATE_FAILURE:
|
|
60
|
+
return state
|
|
61
|
+
.set('editTemplateInProgress', false)
|
|
62
|
+
.set('editTemplateError', true)
|
|
63
|
+
.set('editTemplateErrorMessage', fromJS(action.errorMsg));
|
|
64
|
+
case CLEAR_CREATE_RESPONSE_REQUEST:
|
|
65
|
+
return state.set('response', {});
|
|
66
|
+
// FOR EDIT
|
|
67
|
+
case GET_INAPP_TEMPLATE_DETAILS_REQUEST:
|
|
68
|
+
return state.set('getTemplateDetailsInProgress', true);
|
|
69
|
+
case GET_INAPP_TEMPLATE_DETAILS_SUCCESS:
|
|
70
|
+
return state
|
|
71
|
+
.set('getTemplateDetailsInProgress', false)
|
|
72
|
+
.set('templateDetails', action.data);
|
|
73
|
+
case GET_INAPP_TEMPLATE_DETAILS_FAILURE:
|
|
74
|
+
return state.set('getTemplateDetailsInProgress', false);
|
|
75
|
+
case RESET_EDIT_TEMPLATE:
|
|
76
|
+
return state.set('templateDetails', {});
|
|
77
|
+
case UPLOAD_INAPP_ASSET_REQUEST:
|
|
78
|
+
return state.set('uploadAssetSuccess', false).set('assetUploading', true);
|
|
79
|
+
case UPLOAD_INAPP_ASSET_SUCCESS:
|
|
80
|
+
return state
|
|
81
|
+
.set(
|
|
82
|
+
'uploadAssetSuccess',
|
|
83
|
+
action.statusCode !== undefined &&
|
|
84
|
+
action.statusCode !== '' &&
|
|
85
|
+
action.statusCode < 300,
|
|
86
|
+
)
|
|
87
|
+
.set('assetUploading', false)
|
|
88
|
+
.set(
|
|
89
|
+
action.templateType !== undefined
|
|
90
|
+
? `uploadedAssetData${action.templateType}`
|
|
91
|
+
: 'uploadedAssetData',
|
|
92
|
+
action.data,
|
|
93
|
+
);
|
|
94
|
+
case UPLOAD_INAPP_ASSET_FAILURE:
|
|
95
|
+
return state
|
|
96
|
+
.set('uploadAssetSuccess', false)
|
|
97
|
+
.set('assetUploading', false);
|
|
98
|
+
case CLEAR_INAPP_ASSET:
|
|
99
|
+
return state.delete(
|
|
100
|
+
action.templateType !== undefined
|
|
101
|
+
? `uploadedAssetData${action.templateType}`
|
|
102
|
+
: 'uploadedAssetData',
|
|
103
|
+
);
|
|
104
|
+
default:
|
|
105
|
+
return state;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export default inAppReducer;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { take, cancel, call, put, takeLatest } from 'redux-saga/effects';
|
|
2
|
+
import { LOCATION_CHANGE } from 'react-router-redux';
|
|
3
|
+
import * as Api from '../../services/api';
|
|
4
|
+
import {
|
|
5
|
+
INAPP_TEMPLATE_CREATE_REQUEST,
|
|
6
|
+
INAPP_TEMPLATE_CREATE_SUCCESS,
|
|
7
|
+
INAPP_TEMPLATE_CREATE_FAILURE,
|
|
8
|
+
UPLOAD_INAPP_ASSET_REQUEST,
|
|
9
|
+
UPLOAD_INAPP_ASSET_SUCCESS,
|
|
10
|
+
UPLOAD_INAPP_ASSET_FAILURE,
|
|
11
|
+
INAPP_EDIT_TEMPLATE_SUCCESS,
|
|
12
|
+
INAPP_EDIT_TEMPLATE_FAILURE,
|
|
13
|
+
INAPP_EDIT_TEMPLATE_REQUEST,
|
|
14
|
+
GET_INAPP_TEMPLATE_DETAILS_SUCCESS,
|
|
15
|
+
GET_INAPP_TEMPLATE_DETAILS_FAILURE,
|
|
16
|
+
GET_INAPP_TEMPLATE_DETAILS_REQUEST,
|
|
17
|
+
} from './constants';
|
|
18
|
+
import { INAPP } from '../CreativesContainer/constants';
|
|
19
|
+
|
|
20
|
+
export function* uploadInAppAsset(params) {
|
|
21
|
+
try {
|
|
22
|
+
const result = yield call(Api.uploadFile, params);
|
|
23
|
+
yield put({
|
|
24
|
+
type: UPLOAD_INAPP_ASSET_SUCCESS,
|
|
25
|
+
data: result?.response?.asset,
|
|
26
|
+
statusCode: result?.status?.code || '',
|
|
27
|
+
templateType: params.templateType,
|
|
28
|
+
});
|
|
29
|
+
} catch (error) {
|
|
30
|
+
yield put({ type: UPLOAD_INAPP_ASSET_FAILURE, error });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function* watchUploadInAppAsset() {
|
|
34
|
+
const watcher = yield takeLatest(
|
|
35
|
+
UPLOAD_INAPP_ASSET_REQUEST,
|
|
36
|
+
uploadInAppAsset,
|
|
37
|
+
);
|
|
38
|
+
yield take(LOCATION_CHANGE);
|
|
39
|
+
yield cancel(watcher);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function* inAppTemplateCreate({ payload, callback }) {
|
|
43
|
+
let errorMsg;
|
|
44
|
+
try {
|
|
45
|
+
const result = yield call(Api.createChannelWiseTemplate, { channel: INAPP, template: payload });
|
|
46
|
+
if (result?.status?.code && result.status.code >= 400) {
|
|
47
|
+
errorMsg = result?.message || result.status.code;
|
|
48
|
+
throw errorMsg;
|
|
49
|
+
}
|
|
50
|
+
yield put({
|
|
51
|
+
type: INAPP_TEMPLATE_CREATE_SUCCESS,
|
|
52
|
+
data: result.response,
|
|
53
|
+
statusCode: result.status ? result.status.code : '',
|
|
54
|
+
errorMsg,
|
|
55
|
+
});
|
|
56
|
+
if (callback) {
|
|
57
|
+
callback(result.response);
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
yield put({
|
|
61
|
+
type: INAPP_TEMPLATE_CREATE_FAILURE,
|
|
62
|
+
error,
|
|
63
|
+
errorMsg,
|
|
64
|
+
});
|
|
65
|
+
if (callback) {
|
|
66
|
+
callback(null, errorMsg);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function* watchCreateTemplate() {
|
|
72
|
+
const watcher = yield takeLatest(
|
|
73
|
+
INAPP_TEMPLATE_CREATE_REQUEST,
|
|
74
|
+
inAppTemplateCreate,
|
|
75
|
+
);
|
|
76
|
+
yield take(LOCATION_CHANGE);
|
|
77
|
+
yield cancel(watcher);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// FOR EDIT
|
|
81
|
+
export function* editTemplate({ payload, callback }) {
|
|
82
|
+
let errorMsg;
|
|
83
|
+
try {
|
|
84
|
+
const result = yield call(Api.createChannelWiseTemplate, { channel: INAPP, template: payload });
|
|
85
|
+
if (result.status.code >= 400) {
|
|
86
|
+
errorMsg = result.message || result.status.code;
|
|
87
|
+
throw errorMsg;
|
|
88
|
+
}
|
|
89
|
+
yield put({
|
|
90
|
+
type: INAPP_EDIT_TEMPLATE_SUCCESS,
|
|
91
|
+
data: result.response,
|
|
92
|
+
statusCode: result?.status?.code || '',
|
|
93
|
+
errorMsg,
|
|
94
|
+
});
|
|
95
|
+
if (callback) {
|
|
96
|
+
callback(result.response);
|
|
97
|
+
}
|
|
98
|
+
} catch (error) {
|
|
99
|
+
yield put({ type: INAPP_EDIT_TEMPLATE_FAILURE, error, errorMsg });
|
|
100
|
+
if (callback) {
|
|
101
|
+
callback(null, errorMsg);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export function* watchEditTemplate() {
|
|
106
|
+
const watcher = yield takeLatest(INAPP_EDIT_TEMPLATE_REQUEST, editTemplate);
|
|
107
|
+
yield take(LOCATION_CHANGE);
|
|
108
|
+
yield cancel(watcher);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function* getTemplateDetails({ id, callback }) {
|
|
112
|
+
try {
|
|
113
|
+
const result = yield call(Api.getTemplateDetails, {
|
|
114
|
+
id,
|
|
115
|
+
channel: INAPP,
|
|
116
|
+
});
|
|
117
|
+
yield put({
|
|
118
|
+
type: GET_INAPP_TEMPLATE_DETAILS_SUCCESS,
|
|
119
|
+
data: result.response,
|
|
120
|
+
});
|
|
121
|
+
if (callback) {
|
|
122
|
+
callback(false);
|
|
123
|
+
}
|
|
124
|
+
} catch (error) {
|
|
125
|
+
yield put({ type: GET_INAPP_TEMPLATE_DETAILS_FAILURE, error });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function* watchGetTemplateDetails() {
|
|
130
|
+
const watcher = yield takeLatest(
|
|
131
|
+
GET_INAPP_TEMPLATE_DETAILS_REQUEST,
|
|
132
|
+
getTemplateDetails,
|
|
133
|
+
);
|
|
134
|
+
yield take(LOCATION_CHANGE);
|
|
135
|
+
yield cancel(watcher);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export default [
|
|
139
|
+
watchCreateTemplate,
|
|
140
|
+
watchGetTemplateDetails,
|
|
141
|
+
watchUploadInAppAsset,
|
|
142
|
+
watchEditTemplate,
|
|
143
|
+
];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createSelector } from 'reselect';
|
|
2
|
+
|
|
3
|
+
const selectInAppDomain = () => (state) => state.get('inapp');
|
|
4
|
+
const selectAccountDomain = () => (state) => state.get('templates');
|
|
5
|
+
|
|
6
|
+
const makeSelectInApp = () =>
|
|
7
|
+
createSelector(selectInAppDomain(), (substate) => substate?.toJS());
|
|
8
|
+
|
|
9
|
+
const makeSelectAccount = () =>
|
|
10
|
+
createSelector(selectAccountDomain(), (substate) => substate.toJS());
|
|
11
|
+
|
|
12
|
+
export { makeSelectInApp, makeSelectAccount };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as types from "../constants";
|
|
2
|
+
import * as actions from "../actions";
|
|
3
|
+
|
|
4
|
+
describe("Test inapp actions", () => {
|
|
5
|
+
it("has a type of INAPP_TEMPLATE_CREATE_REQUEST action", () => {
|
|
6
|
+
const payload = {};
|
|
7
|
+
const expected = {
|
|
8
|
+
type: types.INAPP_TEMPLATE_CREATE_REQUEST,
|
|
9
|
+
payload,
|
|
10
|
+
};
|
|
11
|
+
expect(actions.createInAppTemplate(payload)).toEqual(expected);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("has a type of CLEAR_CREATE_RESPONSE_REQUEST action", () => {
|
|
15
|
+
const expected = {
|
|
16
|
+
type: types.CLEAR_CREATE_RESPONSE_REQUEST,
|
|
17
|
+
};
|
|
18
|
+
expect(actions.clearCreateResponse()).toEqual(expected);
|
|
19
|
+
});
|
|
20
|
+
it("has a type of INAPP_EDIT_TEMPLATE_REQUEST action", () => {
|
|
21
|
+
const expected = {
|
|
22
|
+
type: types.INAPP_EDIT_TEMPLATE_REQUEST,
|
|
23
|
+
};
|
|
24
|
+
expect(actions.editTemplate()).toEqual(expected);
|
|
25
|
+
});
|
|
26
|
+
it("has a type of RESET_EDIT_TEMPLATE action", () => {
|
|
27
|
+
const expected = {
|
|
28
|
+
type: types.RESET_EDIT_TEMPLATE,
|
|
29
|
+
};
|
|
30
|
+
expect(actions.resetEditTemplate()).toEqual(expected);
|
|
31
|
+
});
|
|
32
|
+
it("has a type of GET_INAPP_TEMPLATE_DETAILS_REQUEST action", () => {
|
|
33
|
+
const expected = {
|
|
34
|
+
type: types.GET_INAPP_TEMPLATE_DETAILS_REQUEST,
|
|
35
|
+
callback: undefined,
|
|
36
|
+
channel: "INAPP",
|
|
37
|
+
id: undefined,
|
|
38
|
+
};
|
|
39
|
+
expect(actions.getTemplateDetails()).toEqual(expected);
|
|
40
|
+
});
|
|
41
|
+
it("has a type of UPLOAD_INAPP_ASSET_REQUEST action", () => {
|
|
42
|
+
const expected = {
|
|
43
|
+
type: types.UPLOAD_INAPP_ASSET_REQUEST,
|
|
44
|
+
};
|
|
45
|
+
expect(actions.uploadInAppAsset()).toEqual(expected);
|
|
46
|
+
});
|
|
47
|
+
it("has a type of CLEAR_INAPP_ASSET action", () => {
|
|
48
|
+
const expected = {
|
|
49
|
+
type: types.CLEAR_INAPP_ASSET,
|
|
50
|
+
};
|
|
51
|
+
expect(actions.clearInAppAsset()).toEqual(expected);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { injectIntl } from 'react-intl';
|
|
3
|
+
import { browserHistory } from 'react-router';
|
|
4
|
+
import '@testing-library/jest-dom';
|
|
5
|
+
import { Provider } from 'react-redux';
|
|
6
|
+
import configureStore from '../../../store';
|
|
7
|
+
import { InApp } from '../index';
|
|
8
|
+
import { render, screen, fireEvent, within } from '../../../utils/test-utils';
|
|
9
|
+
import {
|
|
10
|
+
editData,
|
|
11
|
+
accountData,
|
|
12
|
+
location,
|
|
13
|
+
editData1,
|
|
14
|
+
location1,
|
|
15
|
+
} from './mockData';
|
|
16
|
+
import { metaEntities, getDefaultTags, injectedTags } from '../../Zalo/tests/mockData';
|
|
17
|
+
|
|
18
|
+
const mockActions = {
|
|
19
|
+
getTemplateInfoById: jest.fn(),
|
|
20
|
+
resetEditTemplate: jest.fn(),
|
|
21
|
+
getTemplateDetails: jest.fn(),
|
|
22
|
+
editTemplate: jest.fn(),
|
|
23
|
+
};
|
|
24
|
+
const mockGlobalActions = {
|
|
25
|
+
fetchSchemaForEntity: jest.fn(),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
let store;
|
|
29
|
+
beforeAll(() => {
|
|
30
|
+
store = configureStore({}, browserHistory);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const ComponentToRender = injectIntl(InApp);
|
|
34
|
+
const renderComponent = (props) =>
|
|
35
|
+
render(
|
|
36
|
+
<Provider store={store}>
|
|
37
|
+
<ComponentToRender {...props} />
|
|
38
|
+
</Provider>,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
describe('Test activity inApp container', () => {
|
|
42
|
+
it('test case for inApp template update flow', async () => {
|
|
43
|
+
renderComponent({
|
|
44
|
+
actions: mockActions,
|
|
45
|
+
globalActions: mockGlobalActions,
|
|
46
|
+
location,
|
|
47
|
+
editData,
|
|
48
|
+
accountData,
|
|
49
|
+
isFullMode: true,
|
|
50
|
+
params: { id: 'test'},
|
|
51
|
+
});
|
|
52
|
+
const inputBox = await screen.findAllByPlaceholderText(
|
|
53
|
+
'Enter template name',
|
|
54
|
+
);
|
|
55
|
+
fireEvent.change(inputBox[0], { target: { value: 'Hello, welcome' } });
|
|
56
|
+
inputBox[0].focus();
|
|
57
|
+
const iosTab = screen.getByRole('tab', {
|
|
58
|
+
name: /ios/i,
|
|
59
|
+
});
|
|
60
|
+
fireEvent.click(within(iosTab).getByText(/ios/i));
|
|
61
|
+
const androidTab = screen.getByRole('tab', {
|
|
62
|
+
name: /android/i,
|
|
63
|
+
});
|
|
64
|
+
fireEvent.click(within(androidTab).getByText(/android/i));
|
|
65
|
+
const inputNameBox = await screen.findAllByPlaceholderText(
|
|
66
|
+
'Enter template name',
|
|
67
|
+
);
|
|
68
|
+
fireEvent.change(inputNameBox[0], { target: { value: 'Hello, welcome' } });
|
|
69
|
+
const msgBox = screen.getAllByPlaceholderText(/Please input in-app notification message content/i);
|
|
70
|
+
msgBox[0].focus();
|
|
71
|
+
fireEvent.change(msgBox[0], { target: { value: 'val' }});
|
|
72
|
+
const updateBtn = screen.getByRole('button', {
|
|
73
|
+
name: /update/i,
|
|
74
|
+
});
|
|
75
|
+
expect(updateBtn).toBeEnabled();
|
|
76
|
+
fireEvent.click(updateBtn);
|
|
77
|
+
expect(mockActions.editTemplate).toBeCalled();
|
|
78
|
+
});
|
|
79
|
+
it('test case for inApp template configuration', async () => {
|
|
80
|
+
renderComponent({
|
|
81
|
+
actions: mockActions,
|
|
82
|
+
globalActions: mockGlobalActions,
|
|
83
|
+
location: location1,
|
|
84
|
+
templateData: editData1?.templateDetails,
|
|
85
|
+
accountData,
|
|
86
|
+
isFullMode: false,
|
|
87
|
+
params: { id: 'test'},
|
|
88
|
+
getFormData: jest.fn(),
|
|
89
|
+
});
|
|
90
|
+
const inputBox = await screen.findAllByPlaceholderText(
|
|
91
|
+
'Enter template name',
|
|
92
|
+
);
|
|
93
|
+
fireEvent.change(inputBox[0], { target: { value: 'Hello, welcome' } });
|
|
94
|
+
inputBox[0].focus();
|
|
95
|
+
const iosTab = screen.getByRole('tab', {
|
|
96
|
+
name: /ios/i,
|
|
97
|
+
});
|
|
98
|
+
fireEvent.click(within(iosTab).getByText(/ios/i));
|
|
99
|
+
const androidTab = screen.getByRole('tab', {
|
|
100
|
+
name: /android/i,
|
|
101
|
+
});
|
|
102
|
+
fireEvent.click(within(androidTab).getByText(/android/i));
|
|
103
|
+
const inputNameBox = await screen.findAllByPlaceholderText(
|
|
104
|
+
'Enter template name',
|
|
105
|
+
);
|
|
106
|
+
inputNameBox[0].focus();
|
|
107
|
+
fireEvent.change(inputNameBox[0], { target: { value: 'Hello, welcome' } });
|
|
108
|
+
const msgBox = screen.getAllByPlaceholderText(/Please input in-app notification message content/i);
|
|
109
|
+
msgBox[0].focus();
|
|
110
|
+
fireEvent.change(msgBox[0], { target: { value: 'val' }});
|
|
111
|
+
const updateBtn = screen.getByRole('button', {
|
|
112
|
+
name: /update/i,
|
|
113
|
+
});
|
|
114
|
+
expect(updateBtn).toBeEnabled();
|
|
115
|
+
});
|
|
116
|
+
it('test case for inApp template copy content flow', async () => {
|
|
117
|
+
renderComponent({
|
|
118
|
+
actions: mockActions,
|
|
119
|
+
globalActions: mockGlobalActions,
|
|
120
|
+
location: {
|
|
121
|
+
pathname: '/inapp/edit',
|
|
122
|
+
query: {
|
|
123
|
+
type: false,
|
|
124
|
+
module: 'default',
|
|
125
|
+
},
|
|
126
|
+
search: '',
|
|
127
|
+
},
|
|
128
|
+
editData: editData1,
|
|
129
|
+
metaEntities,
|
|
130
|
+
getDefaultTags,
|
|
131
|
+
injectedTags,
|
|
132
|
+
accountData,
|
|
133
|
+
isFullMode: true,
|
|
134
|
+
params: { id: 'test'},
|
|
135
|
+
});
|
|
136
|
+
const layoutOption = screen.getByText(/top banner/i);
|
|
137
|
+
fireEvent.click(layoutOption);
|
|
138
|
+
const copyLink = screen.getByRole('link', {
|
|
139
|
+
name: /copy title and content from ios/i,
|
|
140
|
+
});
|
|
141
|
+
fireEvent.click(copyLink);
|
|
142
|
+
const iosTab = screen.getByRole('tab', {
|
|
143
|
+
name: /ios/i,
|
|
144
|
+
});
|
|
145
|
+
fireEvent.click(within(iosTab).getByText(/ios/i));
|
|
146
|
+
const copyLinkIos = screen.getByRole('link', {
|
|
147
|
+
name: /copy title and content from android/i,
|
|
148
|
+
});
|
|
149
|
+
fireEvent.click(copyLinkIos);
|
|
150
|
+
expect(copyLink).toBeInTheDocument();
|
|
151
|
+
});
|
|
152
|
+
});
|