@capillarytech/creatives-library 2.0.79 → 2.0.81

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.
Files changed (108) hide show
  1. package/components/CardGrid/index.js +1 -0
  2. package/components/EmailPreview/assets/images/iPad.svg +10 -0
  3. package/components/EmailPreview/assets/images/mobile.png +0 -0
  4. package/components/FormBuilder/index.js +3 -2
  5. package/components/FormBuilder/test +1845 -0
  6. package/containers/CallTask/_callTask.scss +5 -0
  7. package/containers/CallTask/actions.js +15 -0
  8. package/containers/CallTask/constants.js +7 -0
  9. package/containers/CallTask/index.js +141 -0
  10. package/containers/CallTask/messages.js +21 -0
  11. package/containers/CallTask/reducer.js +23 -0
  12. package/containers/CallTask/sagas.js +11 -0
  13. package/containers/CallTask/selectors.js +25 -0
  14. package/containers/CallTask/tests/actions.test.js +18 -0
  15. package/containers/CallTask/tests/index.test.js +10 -0
  16. package/containers/CallTask/tests/reducer.test.js +9 -0
  17. package/containers/CallTask/tests/sagas.test.js +15 -0
  18. package/containers/CallTask/tests/selectors.test.js +10 -0
  19. package/containers/ChannelTemplates/actions.js +20 -0
  20. package/containers/ChannelTemplates/constants.js +8 -0
  21. package/containers/ChannelTemplates/index.js +48 -0
  22. package/containers/ChannelTemplates/messages.js +13 -0
  23. package/containers/ChannelTemplates/reducer.js +34 -0
  24. package/containers/ChannelTemplates/sagas.js +32 -0
  25. package/containers/ChannelTemplates/selectors.js +25 -0
  26. package/containers/ChannelTemplates/tests/actions.test.js +18 -0
  27. package/containers/ChannelTemplates/tests/index.test.js +10 -0
  28. package/containers/ChannelTemplates/tests/reducer.test.js +9 -0
  29. package/containers/ChannelTemplates/tests/sagas.test.js +15 -0
  30. package/containers/ChannelTemplates/tests/selectors.test.js +10 -0
  31. package/containers/CreativesContainer/SlideBoxContent.js +248 -0
  32. package/containers/CreativesContainer/SlideBoxFooter.js +38 -0
  33. package/containers/CreativesContainer/SlideBoxHeader.js +65 -0
  34. package/containers/CreativesContainer/actions.js +27 -0
  35. package/containers/CreativesContainer/constants.js +13 -0
  36. package/containers/CreativesContainer/index.js +418 -0
  37. package/containers/CreativesContainer/index.scss +27 -0
  38. package/containers/CreativesContainer/messages.js +17 -0
  39. package/containers/CreativesContainer/reducer.js +29 -0
  40. package/containers/CreativesContainer/sagas.js +11 -0
  41. package/containers/CreativesContainer/selectors.js +30 -0
  42. package/containers/CreativesContainer/tests/actions.test.js +18 -0
  43. package/containers/CreativesContainer/tests/index.test.js +10 -0
  44. package/containers/CreativesContainer/tests/reducer.test.js +9 -0
  45. package/containers/CreativesContainer/tests/sagas.test.js +15 -0
  46. package/containers/CreativesContainer/tests/selectors.test.js +10 -0
  47. package/containers/EmailWrapper/actions.js +15 -0
  48. package/containers/EmailWrapper/constants.js +7 -0
  49. package/containers/EmailWrapper/index.js +238 -0
  50. package/containers/EmailWrapper/messages.js +57 -0
  51. package/containers/EmailWrapper/reducer.js +23 -0
  52. package/containers/EmailWrapper/sagas.js +11 -0
  53. package/containers/EmailWrapper/selectors.js +25 -0
  54. package/containers/EmailWrapper/tests/actions.test.js +18 -0
  55. package/containers/EmailWrapper/tests/index.test.js +10 -0
  56. package/containers/EmailWrapper/tests/reducer.test.js +9 -0
  57. package/containers/EmailWrapper/tests/sagas.test.js +15 -0
  58. package/containers/EmailWrapper/tests/selectors.test.js +10 -0
  59. package/containers/Line/Create/index.js +1 -1
  60. package/containers/MobilePush/Create/selectors.js +1 -1
  61. package/containers/MobilePush/Edit/selectors.js +1 -1
  62. package/containers/MobilePush/commonMethods.js +249 -0
  63. package/containers/MobilePush/eventsMap.js +127 -0
  64. package/containers/MobilePush/initialSchema.js +1739 -0
  65. package/containers/MobilepushWrapper/_mobilepushWrapper.scss +18 -0
  66. package/containers/MobilepushWrapper/index.js +97 -0
  67. package/containers/MobilepushWrapper/messages.js +25 -0
  68. package/containers/MobilepushWrapper/tests/index.test.js +10 -0
  69. package/containers/Templates/index.js +18 -14
  70. package/containers/TemplatesV2/_templatesV2.scss +5 -0
  71. package/containers/TemplatesV2/actions.js +16 -0
  72. package/containers/TemplatesV2/constants.js +10 -0
  73. package/containers/TemplatesV2/index.js +207 -0
  74. package/containers/TemplatesV2/messages.js +29 -0
  75. package/containers/TemplatesV2/selectors.js +25 -0
  76. package/containers/TemplatesV2/tests/actions.test.js +18 -0
  77. package/containers/TemplatesV2/tests/index.test.js +10 -0
  78. package/containers/TemplatesV2/tests/reducer.test.js +9 -0
  79. package/containers/TemplatesV2/tests/sagas.test.js +15 -0
  80. package/containers/TemplatesV2/tests/selectors.test.js +10 -0
  81. package/containers/WeChat/RichmediaTemplates/Create/testschema.js +379 -0
  82. package/containers/WeChat/_wechat.scss +8 -0
  83. package/containers/WeChat/actions.js +52 -0
  84. package/containers/WeChat/constants.js +28 -0
  85. package/containers/WeChat/index.js +1635 -0
  86. package/containers/WeChat/messages.js +73 -0
  87. package/containers/WeChat/reducer.js +74 -0
  88. package/containers/WeChat/sagas.js +86 -0
  89. package/containers/WeChat/selectors.js +25 -0
  90. package/containers/WeChat/tests/actions.test.js +18 -0
  91. package/{components/SmsPreviewV2 → containers/WeChat}/tests/index.test.js +2 -2
  92. package/containers/WeChat/tests/reducer.test.js +9 -0
  93. package/containers/WeChat/tests/sagas.test.js +15 -0
  94. package/containers/WeChat/tests/selectors.test.js +10 -0
  95. package/index.js +4 -3
  96. package/package.json +1 -1
  97. package/v2Containers/MobilePush/Create/index.js +43 -9
  98. package/v2Containers/MobilePush/Create/messages.js +16 -0
  99. package/v2Containers/MobilePush/Create/selectors.js +2 -1
  100. package/v2Containers/MobilePush/Edit/index.js +54 -22
  101. package/v2Containers/MobilePush/Edit/messages.js +17 -1
  102. package/v2Containers/MobilePush/Edit/selectors.js +2 -1
  103. package/v2Containers/MobilePush/commonMethods.js +9 -7
  104. package/v2Containers/WeChat/MapTemplates/index.js +5 -5
  105. package/assets/android-message-gui-2.svg +0 -55
  106. package/components/SmsPreviewV2/_smsPreviewV2.scss +0 -353
  107. package/components/SmsPreviewV2/index.js +0 -69
  108. package/components/SmsPreviewV2/messages.js +0 -13
@@ -0,0 +1,73 @@
1
+ /*
2
+ * WeChat Messages
3
+ *
4
+ * This contains all the text for the WeChat component.
5
+ */
6
+ import { defineMessages } from 'react-intl';
7
+
8
+ export default defineMessages({
9
+ header: {
10
+ id: 'app.containers.WeChat.header',
11
+ defaultMessage: 'WeChat',
12
+ },
13
+ 'Template mapping': {
14
+ id: 'app.containers.WeChat.templateMapping',
15
+ defaultMessage: 'Template mapping',
16
+ },
17
+ 'Discard': {
18
+ id: 'app.containers.WeChat.discard',
19
+ defaultMessage: 'Discard',
20
+ },
21
+ 'Cancel': {
22
+ id: 'app.containers.WeChat.cancel',
23
+ defaultMessage: 'Cancel',
24
+ },
25
+ 'Save': {
26
+ id: 'app.containers.WeChat.save',
27
+ defaultMessage: 'Save',
28
+ },
29
+ 'Account Id': {
30
+ id: 'app.containers.WeChat.accountId',
31
+ defaultMessage: 'Account Id',
32
+ },
33
+ 'Select Wechat Account': {
34
+ id: 'app.containers.WeChat.selectWechatAccount',
35
+ defaultMessage: 'Select Wechat Account',
36
+ },
37
+ 'Template': {
38
+ id: 'app.containers.WeChat.template',
39
+ defaultMessage: 'Template',
40
+ },
41
+ 'Select Wechat Template': {
42
+ id: 'app.containers.WeChat.selectWechatTemplate',
43
+ defaultMessage: 'Select Wechat Template',
44
+ },
45
+ 'Link': {
46
+ id: 'app.containers.WeChat.link',
47
+ defaultMessage: 'Link',
48
+ },
49
+ 'Is this internal url': {
50
+ id: 'app.containers.WeChat.isInternalUrl',
51
+ defaultMessage: 'Is this internal url',
52
+ },
53
+ "Tags": {
54
+ id: 'app.containers.WeChat.tagsLabel',
55
+ defaultMessage: "Tags",
56
+ },
57
+ "gettingTemplateData": {
58
+ id: 'app.containers.WeChat.gettingTemplateData',
59
+ defaultMessage: "Getting Template Data..",
60
+ },
61
+ "wechatEditSuccess": {
62
+ id: 'app.containers.WeChat.wechatEditSuccess',
63
+ defaultMessage: "WeChat template unmapped successfully",
64
+ },
65
+ "wechatCreateSuccess": {
66
+ id: 'app.containers.WeChat.wechatCreateSuccess',
67
+ defaultMessage: "WeChat template mapped successfully",
68
+ },
69
+ "somethingWentWrong": {
70
+ id: 'app.containers.WeChat.somethingWentWrong',
71
+ defaultMessage: "Something Went Wrong!!",
72
+ },
73
+ });
@@ -0,0 +1,74 @@
1
+ /*
2
+ *
3
+ * WeChat reducer
4
+ *
5
+ */
6
+
7
+ import { fromJS } from 'immutable';
8
+ import * as types from './constants';
9
+
10
+ const initialState = fromJS({
11
+ weChatDefaultTemplate: fromJS({}),
12
+ fetchingDefaultTemplates: false,
13
+ errorFetchingDefaultTempalte: false,
14
+ });
15
+
16
+ function weChatReducer(state = initialState, action) {
17
+ switch (action.type) {
18
+ case types.GET_WECHAT_DEFAULT_TEMPLATES_REQUEST:
19
+ return state
20
+ .set('fetchingDefaultTemplates', true)
21
+ .set('weChatDefaultTemplate', fromJS({}))
22
+ .set('weChatTemplates', fromJS({}))
23
+ .set('errorFetchingDefaultTempalte', false);
24
+ case types.GET_WECHAT_DEFAULT_TEMPLATES_SUCCESS:
25
+ return state
26
+ .set('fetchingDefaultTemplates', false)
27
+ .set('weChatDefaultTemplate', fromJS(action.data))
28
+ .set('weChatTemplates', fromJS(action.templateData));
29
+ case types.GET_WECHAT_DEFAULT_TEMPLATES_FAILURE:
30
+ return state
31
+ .set('fetchingDefaultTemplates', false)
32
+ .set('errorFetchingDefaultTempalte', true);
33
+ case types.CREATE_TEMPLATE_REQUEST:
34
+ return state
35
+ .set('createTemplateInProgress', true)
36
+ .set('createTemplateError', false);
37
+ case types.CREATE_TEMPLATE_SUCCESS:
38
+ return state.set('createTemplateInProgress', false)
39
+ .set('createResponse', action.data)
40
+ .set('createTemplateError', (action.statusCode !== undefined && action.statusCode > 300));
41
+ case types.CREATE_TEMPLATE_FAILURE:
42
+ return state
43
+ .set('createTemplateInProgress', false)
44
+ .set('createTemplateError', true);
45
+ case types.CLEAR_CREATE_RESPONSE_REQUEST:
46
+ return state.set('createResponse', {});
47
+ case types.GET_WECRM_ACCOUNTS_REQUEST:
48
+ return state
49
+ .set('fetchingWeCrmAccounts', true)
50
+ .set('weCrmAccountFetchingError', false);
51
+ case types.GET_WECRM_ACCOUNTS_SUCCESS:
52
+ return state
53
+ .set('fetchingWeCrmAccounts', false)
54
+ .set('weCrmAccounts', fromJS(action.data));
55
+ case types.GET_WECRM_ACCOUNTS_FAILURE:
56
+ return state
57
+ .set('fetchingWeCrmAccounts', false)
58
+ .set('weCrmAccountFetchingError', true);
59
+ case types.GET_TEMPLATE_DETAILS_REQUEST:
60
+ return state.set('getTemplateDetailsInProgress', true);
61
+ case types.GET_TEMPLATE_DETAILS_SUCCESS:
62
+ return state.set('getTemplateDetailsInProgress', false)
63
+ .set('templateDetails', action.data);
64
+ case types.GET_TEMPLATE_DETAILS_FAILURE:
65
+ return state.set('getTemplateDetailsInProgress', false);
66
+ case types.SET_WECHAT_ACCOUNT:
67
+ return state
68
+ .set('selectedWeChatAccount', fromJS(action.weChatAccount));
69
+ default:
70
+ return state;
71
+ }
72
+ }
73
+
74
+ export default weChatReducer;
@@ -0,0 +1,86 @@
1
+ import { take, call, put, takeLatest, cancel } from 'redux-saga/effects';
2
+ import { LOCATION_CHANGE } from 'react-router-redux';
3
+ import * as Api from '../../services/api';
4
+ import * as types from './constants';
5
+
6
+ export function* getDefaultWeChatTemplates(params) {
7
+ try {
8
+ console.log('Saga param ', params.channel, params.queryParams);
9
+ const result = yield call(Api.getAllTemplates, {channel: params.channel, queryParams: params.queryParams});
10
+ yield put({ type: types.GET_WECHAT_DEFAULT_TEMPLATES_SUCCESS, data: result.response.unMapped, templateData: result.response.mapped});
11
+ } catch (error) {
12
+ yield put({ type: types.GET_WECHAT_DEFAULT_TEMPLATES_FAILURE, error });
13
+ }
14
+ }
15
+
16
+ export function* createTemplate(template) {
17
+ try {
18
+ const result = yield call(Api.createWeChatTemplate, template);
19
+ // const sidebar = result.response.sidebar;
20
+ yield put({ type: types.CREATE_TEMPLATE_SUCCESS, data: result.response, statusCode: result.status ? result.status.code : '' });
21
+ } catch (error) {
22
+ yield put({ type: types.CREATE_TEMPLATE_FAILURE, error });
23
+ }
24
+ }
25
+
26
+ export function* fetchWeCrmAccounts() {
27
+ try {
28
+ const result = yield call(Api.fetchWeCrmAccounts);
29
+ yield [
30
+ put({
31
+ type: types.GET_WECRM_ACCOUNTS_SUCCESS,
32
+ data: result.response,
33
+ }),
34
+ ];
35
+ } catch (error) {
36
+ yield [
37
+ put({
38
+ type: types.GET_WECRM_ACCOUNTS_FAILURE,
39
+ data: error,
40
+ }),
41
+ ];
42
+ }
43
+ }
44
+
45
+ export function* getTemplateDetails(id) {
46
+ try {
47
+ console.log('saga get Template details', id);
48
+ const result = yield call(Api.getTemplateDetails, id);
49
+ // const sidebar = result.response.sidebar;
50
+ yield put({ type: types.GET_TEMPLATE_DETAILS_SUCCESS, data: result.response });
51
+ } catch (error) {
52
+ yield put({ type: types.GET_TEMPLATE_DETAILS_FAILURE, error });
53
+ }
54
+ }
55
+
56
+ function* watchGetDefaultWechatTemplates() {
57
+ const watcher = yield takeLatest(types.GET_WECHAT_DEFAULT_TEMPLATES_REQUEST, getDefaultWeChatTemplates);
58
+ yield take(LOCATION_CHANGE);
59
+ yield cancel(watcher);
60
+ }
61
+
62
+ function* watchCreateTemplate() {
63
+ const watcher = yield takeLatest(types.CREATE_TEMPLATE_REQUEST, createTemplate);
64
+ yield take(LOCATION_CHANGE);
65
+ yield cancel(watcher);
66
+ }
67
+
68
+ function* watchFetchWeCrmAccounts() {
69
+ const watcher = yield takeLatest(types.GET_WECRM_ACCOUNTS_REQUEST, fetchWeCrmAccounts);
70
+ yield take(LOCATION_CHANGE);
71
+ yield cancel(watcher);
72
+ }
73
+
74
+ function* watchGetTemplateDetails() {
75
+ const watcher = yield takeLatest(types.GET_TEMPLATE_DETAILS_REQUEST, getTemplateDetails);
76
+ yield take(LOCATION_CHANGE);
77
+ yield cancel(watcher);
78
+ }
79
+
80
+ // All sagas to be loaded
81
+ export default [
82
+ watchGetDefaultWechatTemplates,
83
+ watchCreateTemplate,
84
+ watchFetchWeCrmAccounts,
85
+ watchGetTemplateDetails,
86
+ ];
@@ -0,0 +1,25 @@
1
+ import { createSelector } from 'reselect';
2
+
3
+ /**
4
+ * Direct selector to the weChat state domain
5
+ */
6
+ const selectWeChatDomain = () => (state) => state.get('weChat');
7
+
8
+ /**
9
+ * Other specific selectors
10
+ */
11
+
12
+
13
+ /**
14
+ * Default selector used by WeChat
15
+ */
16
+
17
+ const makeSelectWeChat = () => createSelector(
18
+ selectWeChatDomain(),
19
+ (substate) => substate.toJS()
20
+ );
21
+
22
+ export default makeSelectWeChat;
23
+ export {
24
+ selectWeChatDomain,
25
+ };
@@ -0,0 +1,18 @@
1
+
2
+ import {
3
+ defaultAction,
4
+ } from '../actions';
5
+ import {
6
+ DEFAULT_ACTION,
7
+ } from '../constants';
8
+
9
+ describe('WeChat actions', () => {
10
+ describe('Default Action', () => {
11
+ it('has a type of DEFAULT_ACTION', () => {
12
+ const expected = {
13
+ type: DEFAULT_ACTION,
14
+ };
15
+ expect(defaultAction()).toEqual(expected);
16
+ });
17
+ });
18
+ });
@@ -1,9 +1,9 @@
1
1
  // import React from 'react';
2
2
  // import { shallow } from 'enzyme';
3
3
 
4
- // import SmsPreviewV2 from '../index';
4
+ // import { WeChat } from '../index';
5
5
 
6
- describe('<SmsPreviewV2 />', () => {
6
+ describe('<WeChat />', () => {
7
7
  it('Expect to have unit tests specified', () => {
8
8
  expect(true).toEqual(false);
9
9
  });
@@ -0,0 +1,9 @@
1
+
2
+ import { fromJS } from 'immutable';
3
+ import weChatReducer from '../reducer';
4
+
5
+ describe('weChatReducer', () => {
6
+ it('returns the initial state', () => {
7
+ expect(weChatReducer(undefined, {})).toEqual(fromJS({}));
8
+ });
9
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Test sagas
3
+ */
4
+
5
+ /* eslint-disable redux-saga/yield-effects */
6
+ // import { take, call, put, select } from 'redux-saga/effects';
7
+ // import { defaultSaga } from '../sagas';
8
+
9
+ // const generator = defaultSaga();
10
+
11
+ describe('defaultSaga Saga', () => {
12
+ it('Expect to have unit tests specified', () => {
13
+ expect(true).toEqual(false);
14
+ });
15
+ });
@@ -0,0 +1,10 @@
1
+ // import { fromJS } from 'immutable';
2
+ // import { makeSelectWeChatDomain } from '../selectors';
3
+
4
+ // const selector = makeSelectWeChatDomain();
5
+
6
+ describe('makeSelectWeChatDomain', () => {
7
+ it('Expect to have unit tests specified', () => {
8
+ expect(true).toEqual(false);
9
+ });
10
+ });
package/index.js CHANGED
@@ -23,9 +23,9 @@ import CallTask from './v2Containers/CallTask/index';
23
23
  import callTaskReducer from './v2Containers/CallTask/reducer';
24
24
  import callTaskSaga from './v2Containers/CallTask/sagas';
25
25
 
26
- import WeChat from './containers/WeChat/MapTemplates';
27
- import wechatReduce from './containers/WeChat/MapTemplates/reducer';
28
- import wechatSaga from './containers/WeChat/MapTemplates/sagas';
26
+ import WeChat from './v2Containers/WeChat/MapTemplates';
27
+ import wechatReduce from './v2Containers/WeChat/MapTemplates/reducer';
28
+ import wechatSaga from './v2Containers/WeChat/MapTemplates/sagas';
29
29
 
30
30
  import MobilepushCreate from './v2Containers/MobilePush/Create';
31
31
  import mobilepushCreateReducer from './v2Containers/MobilePush/Create/reducer';
@@ -96,4 +96,5 @@ export { CapContainer,
96
96
  MobilePushEditContainer,
97
97
  TemplatesV2Container,
98
98
  CreativesContainer,
99
+ WeChat,
99
100
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "2.0.79",
4
+ "version": "2.0.81",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -110,7 +110,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
110
110
  const message = getMessageObject('error', (nextProps.Create.createTemplateErrorMessage && nextProps.Create.createTemplateErrorMessage !== '') ? nextProps.Create.createTemplateErrorMessage : this.props.intl.formatMessage(messages.somethingWentWrong), true);
111
111
  this.props.globalActions.addMessageToQueue(message);
112
112
  }
113
- if (nextProps.iosCtasData) {
113
+ if (nextProps.iosCtasData && isEmpty(this.state.templateCta)) {
114
114
  this.setState({showIosCtaTable: true});
115
115
  }
116
116
  if (nextProps.metaEntities && nextProps.metaEntities.layouts && nextProps.metaEntities.layouts.length > 0 && isEmpty(this.state.schema)) {
@@ -155,11 +155,11 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
155
155
  const newFormData = cloneDeep(formData);
156
156
  const {templateCta} = this.state;
157
157
  if (!isEmpty(templateCta)) {
158
- newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-label`] = templateCta.name;
159
- newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action`] = templateCta.ctaTemplateDetails[0].buttonText;
158
+ newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-label`] = get(templateCta, 'name');
159
+ newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action`] = get(templateCta, 'ctaTemplateDetails[0].buttonText');
160
160
  delete newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action2`];
161
- if (templateCta.ctaTemplateDetails[1]) {
162
- newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action2`] = templateCta.ctaTemplateDetails[1].buttonText;
161
+ if (get(templateCta, 'ctaTemplateDetails[1]')) {
162
+ newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action2`] = get(templateCta, 'ctaTemplateDetails[1].buttonText');
163
163
  }
164
164
  }
165
165
 
@@ -351,14 +351,46 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
351
351
  validity: this.state.isFormValid,
352
352
  type: templateData.type,
353
353
  };
354
- this.setState({checkValidation: true});
354
+ this.setState({checkValidation: true}, this.showError);
355
355
  if (e) {
356
356
  e.source.postMessage(JSON.stringify(response), e.origin);
357
357
  }
358
358
  return response;
359
359
  };
360
- setFormValidity = (isFormValid) => {
361
- this.setState({isFormValid});
360
+ showError = () => {
361
+ const {intl} = this.props;
362
+ const {errorData} = this.state;
363
+ const errorMessage = {key: 'validation-error', message: intl.formatMessage(messages.validationError)};
364
+ if (!isEmpty(this.state.formData) && !this.state.isFormValid) {
365
+ let tab = this.state.currentTab;
366
+ const isAndroidInvalid = Object.values(errorData[0]).includes(true);
367
+ const isIosInvalid = Object.values(errorData[1]).includes(true);
368
+ let isTagErrorExist = false;
369
+ if (isAndroidInvalid) {
370
+ tab = 1;
371
+ errorMessage.description = intl.formatMessage(messages.invalidAndroidMessage);
372
+ const invalidTags = errorData[0]['invalid-tags'];
373
+ if (!isEmpty(invalidTags)) {
374
+ isTagErrorExist = true;
375
+ errorMessage.description = `${intl.formatMessage(messages.invalidAndroidMessage)} ${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
376
+ }
377
+ } else if (isIosInvalid) {
378
+ tab = 2;
379
+ errorMessage.description = intl.formatMessage(messages.invalidIosMessage);
380
+ const invalidTags = errorData[1]['invalid-tags'];
381
+ if (!isEmpty(invalidTags)) {
382
+ isTagErrorExist = true;
383
+ errorMessage.description = `${intl.formatMessage(messages.invalidIosMessage)} ${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
384
+ }
385
+ }
386
+ if (tab !== this.state.currentTab || isTagErrorExist) {
387
+ CapNotification.error(errorMessage);
388
+ }
389
+ }
390
+ }
391
+ setFormValidity = (isFormValid, errorData) => {
392
+ const newState = {isFormValid, errorData};
393
+ this.setState(newState);
362
394
  };
363
395
  getTransformedData = (formData) => {
364
396
  const obj = {};
@@ -987,7 +1019,9 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
987
1019
 
988
1020
  ],
989
1021
  });
990
- if (selectedConfig && (selectedConfig.id !== "16589g0g" && selectedConfig.id !== "17543720" && selectedConfig.id !== "1a491g56")) {
1022
+ const selectedConfigTemplateCtaId = get(selectedConfig, 'ctaTemplateDetails[0].id');
1023
+ // the option to select deeplink and externa link should not come for these ctas
1024
+ if (selectedConfigTemplateCtaId && (selectedConfigTemplateCtaId.id !== "3heicig" && selectedConfigTemplateCtaId.id !== "6eigf4f" && selectedConfigTemplateCtaId.id !== "c97d0ed")) {
991
1025
  inputFields.splice(fieldIndex + 2, 0, {
992
1026
  rowClassName: "mobile-push-row",
993
1027
  cols: [
@@ -246,4 +246,20 @@ export default defineMessages({
246
246
  id: 'app.containers.MobilePush.Create.uploadImageSizeErrorDescription',
247
247
  defaultMessage: 'File size cannot be more than 3mb',
248
248
  },
249
+ "validationError": {
250
+ id: 'app.containers.MobilePush.Create.validationError',
251
+ defaultMessage: 'Validation error',
252
+ },
253
+ "invalidIosMessage": {
254
+ id: 'app.containers.MobilePush.Create.invalidIosMessage',
255
+ defaultMessage: 'Validation failed for IOS',
256
+ },
257
+ "invalidAndroidMessage": {
258
+ id: 'app.containers.MobilePush.Create.invalidAndroidMessage',
259
+ defaultMessage: 'Validation failed for Android',
260
+ },
261
+ "invalidTags": {
262
+ id: 'app.containers.MobilePush.Create.invalidTags',
263
+ defaultMessage: 'Invalid tags',
264
+ },
249
265
  });
@@ -1,9 +1,10 @@
1
1
  import { createSelector } from 'reselect';
2
+ import { fromJS } from 'immutable';
2
3
 
3
4
  /**
4
5
  * Direct selector to the create state domain
5
6
  */
6
- const selectPushMessageCreateDomain = () => (state) => state.get('mobileCreate');
7
+ const selectPushMessageCreateDomain = () => (state) => state.get('mobileCreate') || fromJS({});
7
8
  /**
8
9
  * Other specific selectors
9
10
  */
@@ -14,7 +14,7 @@ import { notification } from 'antd';
14
14
  import { createStructuredSelector } from 'reselect';
15
15
  import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
16
16
  import _, {get, findIndex, set, forEach, cloneDeep} from 'lodash';
17
- import { CapSpin, CapSlideBox, CapHeader, CapTable, CapLink, CapRow, CapColumn, CapIcons} from '@capillarytech/cap-ui-library';
17
+ import { CapSpin, CapSlideBox, CapHeader, CapTable, CapLink, CapRow, CapColumn, CapIcons, CapNotification} from '@capillarytech/cap-ui-library';
18
18
  import styled from 'styled-components';
19
19
  import {makeSelectEdit, makeSelectEditResponse, makeSelectTemplateDetailsResponse, makeSelectIosCta} from "./selectors";
20
20
  import {makeSelectMetaEntities, setInjectedTags, isLoadingMetaEntities} from "../../Cap/selectors";
@@ -168,7 +168,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
168
168
  this.setState({formData});
169
169
  this.props.actions.clearAsset();
170
170
  }
171
- if (nextProps.iosCtasData) {
171
+ if (nextProps.iosCtasData && _.isEmpty(this.state.templateCta)) {
172
172
  this.setState({showIosCtaTable: true});
173
173
  }
174
174
  if (nextProps.Edit.editTemplateError && !_.isEqual(nextProps.Edit.editTemplateError, this.props.Edit.editTemplateError)) {
@@ -194,11 +194,11 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
194
194
  const newFormData = _.cloneDeep(formData);
195
195
  const {templateCta} = this.state;
196
196
  if (!_.isEmpty(templateCta) && this.state.currentTab === 2) {
197
- newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-label`] = templateCta.name;
198
- newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action`] = templateCta.ctaTemplateDetails[0].buttonText;
197
+ newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-label`] = get(templateCta, 'name');
198
+ newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action`] = get(templateCta, 'ctaTemplateDetails[0].buttonText');
199
199
  delete newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action2`];
200
- if (templateCta.ctaTemplateDetails[1]) {
201
- newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action2`] = templateCta.ctaTemplateDetails[1].buttonText;
200
+ if (get(templateCta, 'ctaTemplateDetails[1]')) {
201
+ newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action2`] = get(templateCta, 'ctaTemplateDetails[1].buttonText');
202
202
  }
203
203
  }
204
204
  if (newFormData["mobilepush-accounts"] !== this.state.formData["mobilepush-accounts"]) {
@@ -239,7 +239,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
239
239
  // if (field.id === "cta-deeplink-secondary-cta-1" && (tabIndex > 1 || this.state.currentTab > 1)) {
240
240
  // inputId = `${inputId}${tabIndex || this.state.currentTab}`;
241
241
  // }
242
- const newInputFields = this.getLinkTypeFields({inputFieldsArgs: inputFields, fieldIndex, deepLinkOptions, formData, field});
242
+ const newInputFields = this.getLinkTypeFields({inputFieldsArgs: inputFields, fieldIndex, deepLinkOptions, formData, field, tab: currentTab});
243
243
  set(schema, `containers[0].panes[${tabIndex - 1}].sections[0].childSections[0].childSections[0].inputFields`, newInputFields);
244
244
 
245
245
  if (currentTab) { // identifying where ist called from setEditData or by event handler
@@ -512,7 +512,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
512
512
  actionLabel: ios['secondary-cta-1-action'],
513
513
  actionLabel2: ios['secondary-cta-1-action2'],
514
514
  type: ios['cta-deeplink-secondary-cta-1'] && (ios['cta-deeplink-secondary-cta-1'].toLowerCase() === "deeplink" ? "DEEP_LINK" : "EXTERNAL_URL"),
515
- actionLink: ios['cta-deeplink-secondary-cta-1'] && (ios['cta-deeplink-secondary-cta-1'].toLowerCase() === "deeplink" ? ios['cta-deeplink-secondary-cta-1-select2'] : ios['cta-deeplink-secondary-cta-1-text2']),
515
+ actionLink: ios['cta-deeplink-secondary-cta-1'] && (ios['cta-deeplink-secondary-cta-1'].toLowerCase() === "deeplink" ? ios['cta-deeplink-secondary-cta-1-select2'] : ios['cta-deeplink-secondary-cta-1-text']),
516
516
  ioscdeepLinkName: this.getLinkName(ios['cta-deeplink-secondary-cta-1-select']),
517
517
  templateCtaId,
518
518
  };
@@ -546,9 +546,41 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
546
546
  }
547
547
  return undefined;
548
548
  };
549
+ showError = () => {
550
+ const {intl} = this.props;
551
+ const {errorData} = this.state;
552
+ const errorMessage = {key: 'validation-error', message: intl.formatMessage(messages.validationError)};
553
+ let isTagErrorExist = false;
554
+ if (!_.isEmpty(this.state.formData) && !this.state.isFormValid) {
555
+ let tab = this.state.currentTab;
556
+ const isAndroidInvalid = Object.values(errorData[0]).includes(true);
557
+ const isIosInvalid = Object.values(errorData[1]).includes(true);
558
+ if (isAndroidInvalid) {
559
+ tab = 1;
560
+ errorMessage.description = intl.formatMessage(messages.invalidAndroidMessage);
561
+ const invalidTags = errorData[0]['invalid-tags'];
562
+ if (!_.isEmpty(invalidTags)) {
563
+ isTagErrorExist = true;
564
+ errorMessage.description = `${intl.formatMessage(messages.invalidAndroidMessage)} ${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
565
+ }
566
+ } else if (isIosInvalid) {
567
+ tab = 2;
568
+ errorMessage.description = intl.formatMessage(messages.invalidIosMessage);
569
+ const invalidTags = errorData[1]['invalid-tags'];
570
+ if (!_.isEmpty(invalidTags)) {
571
+ isTagErrorExist = true;
572
+ errorMessage.description = `${intl.formatMessage(messages.invalidIosMessage)} ${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
573
+ }
574
+ }
549
575
 
550
- setFormValidity = (isFormValid) => {
551
- this.setState({isFormValid});
576
+ if (tab !== this.state.currentTab || isTagErrorExist) {
577
+ CapNotification.error(errorMessage);
578
+ }
579
+ }
580
+ }
581
+ setFormValidity = (isFormValid, errorData) => {
582
+ const newState = {isFormValid, errorData};
583
+ this.setState(newState);
552
584
  };
553
585
 
554
586
  getMappedEvent = (id, event) => {
@@ -577,7 +609,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
577
609
  validity: this.state.isFormValid,
578
610
  };
579
611
  console.log('GetForm Data ', response);
580
- this.setState({checkValidation: true});
612
+ this.setState({checkValidation: true}, this.showError);
581
613
  if (e) {
582
614
  e.source.postMessage(JSON.stringify(response), e.origin);
583
615
  }
@@ -693,14 +725,14 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
693
725
  ios.image = iosData.expandableDetails.image;
694
726
  }
695
727
  if (iosData.expandableDetails && iosData.expandableDetails.ctas && iosData.expandableDetails.ctas.length) {
696
- iosData['add-sec-cta-ios'] = true;
728
+ ios['add-sec-cta-ios'] = true;
697
729
  if (iosData.expandableDetails.ctas[0].type) {
698
730
  ios['cta-deeplink-secondary-cta-1'] = iosData.expandableDetails.ctas[0].type === "DEEP_LINK" ? "Deeplink" : "External Link";
699
731
  }
700
732
  if (iosData.expandableDetails.ctas[0].type === "DEEP_LINK") {
701
733
  ios['cta-deeplink-secondary-cta-1-select2'] = iosData.expandableDetails.ctas[0].actionLink;
702
734
  } else {
703
- ios['cta-deeplink-secondary-cta-1-text2'] = iosData.expandableDetails.ctas[0].actionLink;
735
+ ios['cta-deeplink-secondary-cta-1-text'] = iosData.expandableDetails.ctas[0].actionLink;
704
736
  }
705
737
  ios['secondary-cta-1-label'] = iosData.expandableDetails.ctas[0].actionText;
706
738
  if (iosData.expandableDetails.ctas[0].type === "DEEP_LINK" && ios['cta-deeplink-secondary-cta-1-select2']) {
@@ -768,7 +800,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
768
800
  if (formData[1]['secondary-cta-1-action']) {
769
801
  formData[1]['add-sec-cta-ios'] = true;
770
802
 
771
- schema = this.showSelectedIosCta(schema, {id: 'add-sec-cta-ios'}, 2, undefined, formData[1]['cta-deeplink-secondary-cta-1']);
803
+ schema = this.showSelectedIosCta(schema, {id: 'add-sec-cta-ios'}, 2, this.state.templateCta, formData[1]['cta-deeplink-secondary-cta-1']);
772
804
  schema = this.onLinkTypeChange(true, formData, {id: 'cta-deeplink-secondary-cta-1'}, 2, schema);
773
805
  schema = this.showCtaKeys(true, formData, {id: 'cta-deeplink-secondary-cta-1-select2'}, 2, schema);
774
806
  }
@@ -966,7 +998,9 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
966
998
 
967
999
  ],
968
1000
  });
969
- if (selectedConfig && (selectedConfig.id !== "16589g0g" && selectedConfig.id !== "17543720" && selectedConfig.id !== "1a491g56")) {
1001
+ const selectedConfigTemplateCtaId = get(selectedConfig, 'ctaTemplateDetails[0].id');
1002
+ // the option to select deeplink and externa link should not come for these ctas
1003
+ if (selectedConfigTemplateCtaId && (selectedConfigTemplateCtaId.id !== "3heicig" && selectedConfigTemplateCtaId.id !== "6eigf4f" && selectedConfigTemplateCtaId.id !== "c97d0ed")) {
970
1004
  inputFields.splice(fieldIndex + 2, 0, {
971
1005
  rowClassName: "mobile-push-row",
972
1006
  identifier: `cta-deeplink-${inputId}`,
@@ -1028,10 +1062,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1028
1062
  }
1029
1063
  });
1030
1064
  });
1031
- if (!inputSchema) {
1032
- this.setState({schema, initialState: this.state.initialState ? this.state.initialState : this.state.schema, isSchemaChanged: true});
1033
- this.injectEvents(schema);
1034
- }
1065
+ this.setState({schema, initialState: this.state.initialState ? this.state.initialState : this.state.schema, isSchemaChanged: true}, () => { this.injectEvents(schema); });
1035
1066
  return schema;
1036
1067
  };
1037
1068
 
@@ -1553,7 +1584,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1553
1584
  const fieldIndex = findIndex(inputFields, {identifier: id});
1554
1585
  let newInputFields;
1555
1586
  if (formData[tabIndex - 1][id]) {
1556
- newInputFields = this.getPrimaryCtaFields({inputFields, fieldIndex, deepLinkOptions});
1587
+ newInputFields = this.getPrimaryCtaFields({inputFields, fieldIndex, deepLinkOptions, tab: currentTab});
1557
1588
  } else {
1558
1589
  const identifier = (tabIndex - 1) ? 'add-sec-cta-ios' : 'add-sec-cta';
1559
1590
  const indexOfNextField = findIndex(inputFields, {identifier});
@@ -1564,8 +1595,9 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1564
1595
  if (inputSchema) {
1565
1596
  return schema;
1566
1597
  }
1567
- this.setState({schema, initialState: this.state.initialState ? this.state.initialState : this.state.schema, isSchemaChanged: true});
1568
- this.injectEvents(schema);
1598
+ this.setState({schema, initialState: this.state.initialState ? this.state.initialState : this.state.schema, isSchemaChanged: true}, () => {
1599
+ this.injectEvents(schema);
1600
+ });
1569
1601
  return schema;
1570
1602
  };
1571
1603