@capillarytech/creatives-library 3.0.25 → 3.0.28

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/app.js CHANGED
@@ -10,7 +10,7 @@ import CapV2 from 'v2Containers/Cap';
10
10
  import Cap from 'containers/Cap';
11
11
  import { LocaleProvider } from 'antd';
12
12
  import { makeSelectLocationState } from 'containers/Cap/selectors';
13
- import LanguageProvider from 'containers/LanguageProvider';
13
+ import LanguageProvider from 'v2Containers/LanguageProvider';
14
14
  import FontFaceObserver from 'fontfaceobserver';
15
15
  /* eslint-disable import/no-unresolved, import/extensions */
16
16
  import '!file-loader?name=[name].[ext]!./favicon.ico';
@@ -11,6 +11,7 @@ import { FormattedMessage } from 'react-intl';
11
11
  import moment from "moment";
12
12
  import messages from "./messages";
13
13
  import './_emailPreview.scss';
14
+ import {removeLinksFromHtmlContent} from './../../utils/common';
14
15
  const tabletBody = require('./assets/images/iPad.svg');
15
16
  const mobileBody = require('./assets/images/mobile.png');
16
17
 
@@ -38,7 +39,8 @@ class EmailPreview extends React.Component { // eslint-disable-line react/prefer
38
39
  } else if (this.props.device === 'mobile') {
39
40
  messageContainerName = 'mobile-message-container';
40
41
  }
41
-
42
+ const { content } = this.props;
43
+ const copyContent = removeLinksFromHtmlContent(content);
42
44
  return (
43
45
  <div className={this.props.show ? "modal-emailPreivew-wrapper show-emailPreivew" : "modal-emailPreivew-wrapper hide-emailPreivew"}>
44
46
  <div id="emailPreivew-container">
@@ -66,7 +68,7 @@ class EmailPreview extends React.Component { // eslint-disable-line react/prefer
66
68
  {this.props.device === 'mobile' ?
67
69
  <img src={mobileBody} alt="capillary" width="85%" /> : ''}
68
70
  <div className={messageContainerName}>
69
- <iframe srcDoc={this.props.content} {...deviceAspectRatio[this.props.device]} >
71
+ <iframe srcDoc={copyContent} {...deviceAspectRatio[this.props.device]} >
70
72
  <p>Your browser does not support iframes.</p>
71
73
  </iframe>
72
74
  </div>
package/config/app.js CHANGED
@@ -5,6 +5,7 @@ const config = {
5
5
  production: {
6
6
  api_endpoint: '/arya/api/v1/creatives',
7
7
  auth_endpoint: '/arya/api/v1/auth',
8
+ arya_endpoint: '/arya/api/v1',
8
9
  login_url: 'auth/login',
9
10
  dashboard_url: '/sms',
10
11
  dashboard_url_v2: '/v2',
@@ -13,6 +14,7 @@ const config = {
13
14
  development: {
14
15
  api_endpoint: 'https://nightly.capillary.in/arya/api/v1/creatives',
15
16
  auth_endpoint: 'https://nightly.capillary.in/arya/api/v1/auth',
17
+ arya_endpoint: 'https://nightly.capillary.in/arya/api/v1',
16
18
  login_url: 'auth/login',
17
19
  dashboard_url: '/sms',
18
20
  dashboard_url_v2: '/v2',
@@ -2638,22 +2638,20 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2638
2638
  const formData = _.cloneDeep(this.state.formData);
2639
2639
  formData[0].selectedLanguages = [];
2640
2640
  let tabKey;
2641
- const isDragDrop = _.get(data, 'base.is_drag_drop');
2642
2641
  if (this.props.location.query.type === 'embedded' && (this.props.location.query.isLanguageSupport === undefined || this.props.location.query.isLanguageSupport === 'false')) {
2643
- formData['template-subject'] = _.get(data, 'base.subject', '');
2642
+ formData['template-subject'] = data.base.subject ? data.base.subject : '';
2644
2643
  const baseLanguage = this.props.Global.currentOrgDetails.basic_details.base_language;
2645
2644
  let languageIndex = _.findIndex(this.supportedLanguages, {iso_code: baseLanguage});
2646
2645
  console.log("startTemplatecreation before index", languageIndex, this.supportedLanguages, baseLanguage, formData);
2647
2646
  if (languageIndex === -1) {
2648
2647
  languageIndex = 0;
2649
2648
  }
2650
- const isDragDrop = _.get(data, 'base.is_drag_drop');
2651
2649
  const tempData = {
2652
- "is_drag_drop": isDragDrop,
2650
+ "is_drag_drop": data.base.is_drag_drop,
2653
2651
  "lang_id": this.supportedLanguages[languageIndex].lang_id,
2654
2652
  "iso_code": this.supportedLanguages[languageIndex].iso_code,
2655
2653
  "language": this.supportedLanguages[languageIndex].language,
2656
- "template-content": !isDragDrop && isDragDrop !== 1 ? _.get(data, 'base.html_content') : "",
2654
+ "template-content": !data.base.is_drag_drop && data.base.is_drag_drop !== 1 ? data.base.html_content : "",
2657
2655
  };
2658
2656
  formData[0].base = true;
2659
2657
  formData[0].selectedLanguages.push(this.supportedLanguages[languageIndex].iso_code);
@@ -2702,7 +2700,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2702
2700
  }
2703
2701
  formData.base = _.cloneDeep(formData[0]);
2704
2702
  console.log('startTemplateCreation final ', formData);
2705
- this.setState({formData, loading: false, injectedTags: data.tags, tabKey, isDragDrop: (isDragDrop !== 0 )}, () => {
2703
+ this.setState({formData, loading: false, injectedTags: data.tags, tabKey, isDragDrop: (data.base.is_drag_drop !== 0 )}, () => {
2706
2704
  // this.setState({tabKey: ''});
2707
2705
  _.forEach(formData[0].selectedLanguages, (language) => {
2708
2706
  if (formData[0][language].is_drag_drop) {
@@ -222,15 +222,13 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
222
222
  }
223
223
  }
224
224
  });
225
- if (!_.isEmpty(selectedAccount)) {
226
- this.setState({selectedAccount: selectedAccount.name}, () => {
227
- params.wecrmId = selectedAccount.configs.wecrm_app_id;
228
- params.wecrmToken = selectedAccount.configs.wecrm_token;
229
- params.originalId = selectedAccount.sourceAccountIdentifier;
230
- nextProps.actions.setWeChatAccount(selectedAccount);
231
- this.getAllTemplates({params});
232
- });
233
- }
225
+ this.setState({selectedAccount: selectedAccount.name}, () => {
226
+ params.wecrmId = selectedAccount.configs.wecrm_app_id;
227
+ params.wecrmToken = selectedAccount.configs.wecrm_token;
228
+ params.originalId = selectedAccount.sourceAccountIdentifier;
229
+ nextProps.actions.setWeChatAccount(selectedAccount);
230
+ this.getAllTemplates({params});
231
+ });
234
232
  } else if (this.state.channel.toLowerCase() === 'mobilepush' && (nextProps.location.query.account_id || nextProps.location.query.source_account_id)) {
235
233
  _.forEach(nextProps.Templates.weCrmAccounts, (account) => {
236
234
  if ((nextProps.location.query.account_id && account.id === Number(nextProps.location.query.account_id)) || (nextProps.location.query.source_account_id && account.sourceAccountIdentifier && account.sourceAccountIdentifier === nextProps.location.query.source_account_id)) {
package/index.js CHANGED
@@ -3,6 +3,10 @@ import capReducer from './v2Containers/Cap/reducer';
3
3
  import capSaga from './v2Containers/Cap/sagas';
4
4
  import Cap from './v2Containers/Cap/index';
5
5
 
6
+ import LanguageProvider from './v2Containers/LanguageProvider';
7
+ import LanguageProviderReducer from './v2Containers/LanguageProvider/reducer';
8
+ import LanguageProviderSaga from './v2Containers/LanguageProvider/sagas';
9
+
6
10
  import templateReducer from './v2Containers/Templates/reducer';
7
11
  import templateSaga from './v2Containers/Templates/sagas';
8
12
  import Templates from './v2Containers/Templates/index';
@@ -55,6 +59,7 @@ export {default as EbillSaga} from './v2Containers/Ebill/sagas';
55
59
 
56
60
 
57
61
  const CapContainer = {Cap, capReducer, capSaga};
62
+ const LanguageProviderContainer = {LanguageProvider, LanguageProviderReducer, LanguageProviderSaga};
58
63
  const TemplatesContainer = {Templates, templateReducer, templateSaga};
59
64
  const SmsCreateContainer = {SmsCreate, smsCreateReducer, smsCreateSaga};
60
65
  const SmsEditContainer = {SmsEdit, smsEditReducer, smsEditSaga};
@@ -79,6 +84,7 @@ export {default as MobilePushPreview} from './v2Components/MobilePushPreviewV2';
79
84
  CreativesContainer.CreativesContainerReducer = CreativesContainerReducer;
80
85
 
81
86
  export { CapContainer,
87
+ LanguageProviderContainer,
82
88
  TemplatesContainer,
83
89
  SmsCreateContainer,
84
90
  SmsEditContainer,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "3.0.25",
4
+ "version": "3.0.28",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
package/reducers.js CHANGED
@@ -7,7 +7,7 @@ import { combineReducers } from 'redux-immutable';
7
7
  import { fromJS } from 'immutable';
8
8
  import { LOCATION_CHANGE } from 'react-router-redux';
9
9
 
10
- import languageProviderReducer from 'containers/LanguageProvider/reducer';
10
+ import languageProviderReducer from 'v2Containers/LanguageProvider/reducer';
11
11
  import capReducer from 'containers/Cap/reducer';
12
12
  import appReducer from 'containers/App/reducer';
13
13
  import createSmsReducer from 'containers/Sms/Create/reducer';
package/routes.js CHANGED
@@ -11,6 +11,7 @@ import * as ebillSagas from 'containers/Ebill/sagas';
11
11
  import * as emailSagas from 'containers/Email/sagas';
12
12
  import * as templateSagas from 'containers/Templates/sagas';
13
13
  import * as lineSagas from 'containers/Line/Create/sagas';
14
+ import * as languageSaga from './v2Containers/LanguageProvider/sagas';
14
15
 
15
16
  const errorLoading = (err) => {
16
17
  console.error('Dynamic page loading failed', err); // eslint-disable-line no-console
@@ -24,6 +25,7 @@ export default function createRoutes(store) {
24
25
  // Create reusable async injectors using getAsyncInjectors factory
25
26
  const { injectReducer, injectSagas } = getAsyncInjectors(store); // eslint-disable-line no-unused-vars
26
27
  injectSagas(rootSaga.default);
28
+ injectSagas(languageSaga.default);
27
29
  return [
28
30
  {
29
31
  path: '/',
package/services/api.js CHANGED
@@ -9,9 +9,11 @@ import getSchema from './getSchema';
9
9
  import * as API from '../utils/ApiCaller';
10
10
  let API_ENDPOINT = config.development.api_endpoint;
11
11
  let API_AUTH_ENDPOINT = config.development.auth_endpoint;
12
+ let ARYA_ENDPOINT = config.development.arya_endpoint;
12
13
  if (process.env.NODE_ENV === 'production') {
13
14
  API_ENDPOINT = config.production.api_endpoint;
14
15
  API_AUTH_ENDPOINT = config.production.auth_endpoint;
16
+ ARYA_ENDPOINT = config.production.arya_endpoint;
15
17
  }
16
18
 
17
19
  const isProd = process.env.NODE_ENV === 'production';
@@ -56,8 +58,8 @@ function checkStatus(response) {
56
58
  if ((response.status >= 200 && response.status < 300) || response.status === 500) {
57
59
  return response;
58
60
  }
59
-
60
- redirectIfUnauthenticated(response);
61
+ const isLoginPage = window.location.pathname.indexOf('/login') !== -1;
62
+ if (!isLoginPage) redirectIfUnauthenticated(response);
61
63
 
62
64
  const error = new Error(response.statusText);
63
65
  error.response = response;
@@ -316,3 +318,9 @@ export const createLineTemplate = ({template}) => {
316
318
  const url = `${API_ENDPOINT}/templates/LINE`;
317
319
  return request(url, getAPICallObject('POST', template));
318
320
  };
321
+
322
+ export const getLocizMessage = (locale) => {
323
+ const appName = 'creatives_v2';
324
+ const url = `${ARYA_ENDPOINT}/translations/${appName}/${locale}`;
325
+ return request(url, getAPICallObject('GET'));
326
+ };
package/utils/common.js CHANGED
@@ -21,3 +21,12 @@ export function getMergedUserList(userList, isCapUser = true) {
21
21
  });
22
22
  return mergeUserList;
23
23
  }
24
+
25
+ export function removeLinksFromHtmlContent(content) {
26
+ const doc = document.createElement('html');
27
+ doc.innerHTML = content;
28
+ let copyContent = doc.cloneNode(true).outerHTML;
29
+ copyContent = copyContent.replace(/<a.+?>/g, '<a>');
30
+ doc.remove();
31
+ return copyContent;
32
+ }
@@ -14,6 +14,7 @@ import { CAP_G01, CAP_G06, FONT_SIZE_VL } from '@capillarytech/cap-ui-library/st
14
14
  import { FormattedMessage } from 'react-intl';
15
15
  import moment from "moment";
16
16
  import messages from "./messages";
17
+ import { removeLinksFromHtmlContent } from './../../utils/common';
17
18
  import './_emailPreview.scss';
18
19
  import tabletBody from '../../assets/iPad.svg';
19
20
  import mobileBody from '../../assets/mobile.png';
@@ -52,14 +53,14 @@ class EmailPreview extends React.Component { // eslint-disable-line react/prefer
52
53
  messageContainerName = 'mobile-message-container';
53
54
  subjectClassName = "email-subject-mobile";
54
55
  }
55
-
56
+ const copyContent = removeLinksFromHtmlContent(content);
56
57
  const emailSubjectLabel = emailSubject && (
57
58
  <CapLabel className={subjectClassName} type="label2">
58
59
  <FormattedMessage {...messages.subject} /> {emailSubject}</CapLabel>
59
60
  );
60
61
  const iframeDiv = (<div className={`${messageContainerName}`}>
61
62
  {emailSubjectLabel}
62
- <iframe srcDoc={content} {...deviceAspectRatio[device](emailSubject)} >
63
+ <iframe srcDoc={copyContent} {...deviceAspectRatio[device](emailSubject)} >
63
64
  <p>Your browser does not support iframes.</p>
64
65
  </iframe>
65
66
  </div>);
@@ -19,6 +19,7 @@ import messages from './messages';
19
19
  import './_emailPreviewV2.scss';
20
20
  import tabletBody from '../../assets/iPad.svg';
21
21
  import mobileBody from '../../assets/mobile.png';
22
+ import { removeLinksFromHtmlContent } from './../../utils/common';
22
23
 
23
24
  import {selectTemplateContent} from '../../v2Containers/Templates/selectors';
24
25
  import * as templateActions from '../../v2Containers/Templates/actions';
@@ -71,6 +72,7 @@ class EmailPreviewV2 extends React.Component {
71
72
  let messageContainerName = '';
72
73
  const {currentDevice} = this.state;
73
74
  const { templateContent, templateData = {}, templateSubject } = this.props;
75
+ const copyContent = removeLinksFromHtmlContent(templateContent);
74
76
  let subjectClassName = 'email-subject-desktop';
75
77
  if (currentDevice === devices.tablet) {
76
78
  messageContainerName = 'tablet-message-container';
@@ -86,7 +88,7 @@ class EmailPreviewV2 extends React.Component {
86
88
  );
87
89
  const iframeDiv = (<div className={`${messageContainerName}`}>
88
90
  {emailSubjectLabel}
89
- <iframe srcDoc={templateContent} {...deviceAspectRatio[currentDevice](emailSubject)} >
91
+ <iframe srcDoc={copyContent} {...deviceAspectRatio[currentDevice](emailSubject)} >
90
92
  <p>Your browser does not support iframes.</p>
91
93
  </iframe>
92
94
  </div>);
@@ -39,23 +39,10 @@ class NavigationBar extends React.Component {
39
39
  };
40
40
  }
41
41
 
42
- onBrandSettingsClick = () => {
43
- const { brandSettingsUrl } = this.props;
44
- if (brandSettingsUrl) {
45
- const stateObj = {
46
- page: "brand settings",
47
- };
48
- window.history.pushState(stateObj, 'BrandSettings', window.location.replace(brandSettingsUrl));
49
- }
50
- };
51
-
52
- onProfileSettingsClick = () => {
53
- const { profileSettingsUrl } = this.props;
54
- if (profileSettingsUrl) {
55
- const stateObj = {
56
- page: "profile settings",
57
- };
58
- window.history.pushState(stateObj, 'ProfileSettings', window.location.replace(profileSettingsUrl));
42
+ onOrgSettingsClick = () => {
43
+ const { orgSettingsUrl } = this.props;
44
+ if (orgSettingsUrl) {
45
+ window.open(orgSettingsUrl, '_blank');
59
46
  }
60
47
  };
61
48
 
@@ -101,6 +88,7 @@ class NavigationBar extends React.Component {
101
88
  };
102
89
 
103
90
  getProductsList = () => {
91
+ const { formatMessage } = this.props.intl;
104
92
  const { campaignOrgV2Status } = this.props;
105
93
  const { currentOrgDetails } = this.props.userData;
106
94
  const productsList = [];
@@ -122,7 +110,7 @@ class NavigationBar extends React.Component {
122
110
  }
123
111
  //adding insights+ to module list
124
112
  productsList.push({
125
- value: 'Insights+',
113
+ value: formatMessage(messages.insights),
126
114
  url: 'analytics/v2/',
127
115
  key: 'analytics/v2/',
128
116
  });
@@ -134,32 +122,30 @@ class NavigationBar extends React.Component {
134
122
  {
135
123
  iconType: 'help',
136
124
  key: 'help',
137
- onClickHandler: () => this.onHelpIconClick(),
125
+ onClickHandler: this.onHelpIconClick,
138
126
  },
139
127
  {
140
128
  iconType: 'settings',
141
129
  key: 'settings',
142
- onClickHandler: () => this.onSettingsIconClick(),
130
+ onClickHandler: this.onSettingsIconClick,
143
131
  },
144
132
  ];
145
133
 
146
- getDropdownMenu = () => [
147
- {
148
- label: 'Profile Settings',
149
- key: 'Profile Settings',
150
- onClickHandler: () => this.onProfileSettingsClick(),
151
- },
152
- {
153
- label: 'Brand Settings',
154
- key: 'Brand Settings',
155
- onClickHandler: () => this.onBrandSettingsClick(),
156
- },
157
- {
158
- label: 'Logout',
159
- key: 'Logout',
160
- onClickHandler: () => this.props.logout(),
161
- },
162
- ];
134
+ getDropdownMenu = () => {
135
+ const { formatMessage } = this.props.intl;
136
+ return [
137
+ {
138
+ label: formatMessage(messages.orgSettings),
139
+ key: formatMessage(messages.orgSettings),
140
+ onClickHandler: this.onOrgSettingsClick,
141
+ },
142
+ {
143
+ label: formatMessage(messages.logout),
144
+ key: formatMessage(messages.logout),
145
+ onClickHandler: this.props.logout,
146
+ },
147
+ ];
148
+ };
163
149
 
164
150
  handleTopbarMenuChange = (option) => {
165
151
  window.location.pathname = option.link;
@@ -234,8 +220,7 @@ NavigationBar.propTypes = {
234
220
  settingsUrl: PropTypes.string,
235
221
  children: PropTypes.node,
236
222
  helpUrl: PropTypes.string,
237
- profileSettingsUrl: PropTypes.string,
238
- brandSettingsUrl: PropTypes.string,
223
+ orgSettingsUrl: PropTypes.string,
239
224
  loggedIn: PropTypes.bool,
240
225
  intl: intlShape.isRequired,
241
226
  location: PropTypes.object,
@@ -17,4 +17,16 @@ export default defineMessages({
17
17
  id: `${scope}.selectedProductDefault`,
18
18
  defaultMessage: 'Engage+',
19
19
  },
20
+ insights: {
21
+ id: `${scope}.insights`,
22
+ defaultMessage: 'Insights+',
23
+ },
24
+ orgSettings: {
25
+ id: `${scope}.orgSettings`,
26
+ defaultMessage: 'Organisation settings',
27
+ },
28
+ logout: {
29
+ id: `${scope}.logout`,
30
+ defaultMessage: 'Logout',
31
+ },
20
32
  });
@@ -29,6 +29,5 @@ export const GET_TOPBAR_MENU_DATA_FAILURE = 'creatives/cap/GET_TOPBAR_MENU_DATA_
29
29
  export const CLEAR_TOPBAR_MENU_DATA = 'creatives/cap/CLEAR_TOPBAR_MENU_DATA';
30
30
 
31
31
  export const CAMPAIGN_SETTINGS_URL = '/creatives/settings/message';
32
- export const BRAND_SETTINGS_URL = '/org/index';
33
- export const PROFILE_SETTINGS_URL = '/org/users/NewProfile';
32
+ export const ORG_SETTINGS_URL = '/org/index';
34
33
  export const HELP_URL = 'https://support.capillarytech.com/en/support/solutions/4000007853';
@@ -19,8 +19,7 @@ import NavigationBar from '../../v2Components/NavigationBar';
19
19
  import { engagePlusPublicPath } from '../../config/path';
20
20
  import {
21
21
  HELP_URL,
22
- PROFILE_SETTINGS_URL,
23
- BRAND_SETTINGS_URL,
22
+ ORG_SETTINGS_URL,
24
23
  CAMPAIGN_SETTINGS_URL,
25
24
  } from './constants';
26
25
  const gtm = window.dataLayer || [];
@@ -177,8 +176,7 @@ export class Cap extends React.Component { // eslint-disable-line react/prefer-s
177
176
  changeOrg={this.changeOrg}
178
177
  logout={this.logout}
179
178
  settingsUrl={`${engagePlusPublicPath}${CAMPAIGN_SETTINGS_URL}`}
180
- brandSettingsUrl={BRAND_SETTINGS_URL}
181
- profileSettingsUrl={PROFILE_SETTINGS_URL}
179
+ orgSettingsUrl={ORG_SETTINGS_URL}
182
180
  helpUrl={HELP_URL}
183
181
  loggedIn={isLoggedIn}
184
182
  topbarMenuData={topbarMenuDataOptions}
@@ -4,14 +4,19 @@
4
4
  *
5
5
  */
6
6
 
7
- import {
8
- CHANGE_LOCALE,
9
- } from './constants';
7
+ import * as types from './constants';
10
8
 
11
9
  export function changeLocale(languageLocale) {
12
10
  console.log('trying to change locale', languageLocale);
13
11
  return {
14
- type: CHANGE_LOCALE,
12
+ type: types.CHANGE_LOCALE,
15
13
  locale: languageLocale,
16
14
  };
17
15
  }
16
+
17
+ export function getLocizMessage(locale) {
18
+ return {
19
+ type: types.GET_LOCIZ_MESSAGE_REQUEST,
20
+ locale,
21
+ };
22
+ }
@@ -6,3 +6,10 @@
6
6
 
7
7
  export const CHANGE_LOCALE = 'app/LanguageToggle/CHANGE_LOCALE';
8
8
  export const DEFAULT_LOCALE = 'en';
9
+
10
+ export const GET_LOCIZ_MESSAGE_REQUEST =
11
+ 'app/LanguageProvider/GET_LOCIZ_MESSAGE_REQUEST';
12
+ export const GET_LOCIZ_MESSAGE_SUCCESS =
13
+ 'app/LanguageProvider/GET_LOCIZ_MESSAGE_SUCCESS';
14
+ export const GET_LOCIZ_MESSAGE_FAILURE =
15
+ 'app/LanguageProvider/GET_LOCIZ_MESSAGE_FAILURE';
@@ -10,15 +10,36 @@ import PropTypes from 'prop-types';
10
10
 
11
11
  import React from 'react';
12
12
  import { connect } from 'react-redux';
13
- import { createSelector } from 'reselect';
13
+ import { createStructuredSelector } from 'reselect';
14
14
  import { IntlProvider } from 'react-intl';
15
-
15
+ import { bindActionCreators } from 'redux';
16
+ import * as actions from './actions';
16
17
  import { makeSelectLocale } from './selectors';
17
18
 
19
+
18
20
  export class LanguageProvider extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function
21
+ componentDidMount() {
22
+ const user = localStorage.getItem('user');
23
+ let locale = localStorage.getItem('jlocale') || 'en';
24
+ if (user) {
25
+ locale = JSON.parse(user).lang;
26
+ }
27
+ locale = this.getMappedLocale(locale);
28
+ this.props.actions.getLocizMessage(locale);
29
+ }
30
+
31
+ getMappedLocale = (locale) => {
32
+ const map = {
33
+ 'en': 'en-US',
34
+ 'zh-cn': 'zh',
35
+ };
36
+ return map[locale];
37
+ };
38
+
19
39
  render() {
40
+ const { locale, messages} = this.props.language;
20
41
  return (
21
- <IntlProvider locale={this.props.locale} key={this.props.locale} messages={this.props.messages[this.props.locale]}>
42
+ <IntlProvider locale={locale} key={locale} messages={messages}>
22
43
  {React.Children.only(this.props.children)}
23
44
  </IntlProvider>
24
45
  );
@@ -26,20 +47,19 @@ export class LanguageProvider extends React.PureComponent { // eslint-disable-li
26
47
  }
27
48
 
28
49
  LanguageProvider.propTypes = {
29
- locale: PropTypes.string,
30
- messages: PropTypes.object,
50
+ language: PropTypes.object,
51
+ actions: PropTypes.object,
31
52
  children: PropTypes.element.isRequired,
32
53
  };
33
54
 
34
55
 
35
- const mapStateToProps = createSelector(
36
- makeSelectLocale(),
37
- (locale) => ({ locale })
38
- );
56
+ const mapStateToProps = createStructuredSelector({
57
+ language: makeSelectLocale(),
58
+ });
39
59
 
40
60
  function mapDispatchToProps(dispatch) {
41
61
  return {
42
- dispatch,
62
+ actions: bindActionCreators(actions, dispatch),
43
63
  };
44
64
  }
45
65
 
@@ -6,22 +6,30 @@
6
6
 
7
7
  import { fromJS } from 'immutable';
8
8
 
9
- import {
10
- CHANGE_LOCALE,
11
- } from './constants';
9
+ import * as types from './constants';
12
10
  import {
13
11
  DEFAULT_LOCALE,
14
12
  } from '../Cap/constants'; // eslint-disable-line
15
13
 
16
14
  const initialState = fromJS({
17
15
  locale: DEFAULT_LOCALE,
16
+ messages: [],
17
+ localeLoading: false,
18
18
  });
19
19
 
20
20
  function languageProviderReducer(state = initialState, action) {
21
21
  switch (action.type) {
22
- case CHANGE_LOCALE:
22
+ case types.CHANGE_LOCALE:
23
23
  return state
24
24
  .set('locale', action.locale);
25
+ case types.GET_LOCIZ_MESSAGE_REQUEST:
26
+ return state.set('localeLoading', true);
27
+ case types.GET_LOCIZ_MESSAGE_SUCCESS:
28
+ return state
29
+ .set('localeLoading', false)
30
+ .set('messages', fromJS(action.data));
31
+ case types.GET_LOCIZ_MESSAGE_FAILURE:
32
+ return state.set('localeLoading', false);
25
33
  default:
26
34
  return state;
27
35
  }
@@ -0,0 +1,39 @@
1
+ import { takeLatest, take, all, cancel, call, put } 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
+ function* getLocizMessage(action) {
7
+ try {
8
+ const result = yield call(Api.getLocizMessage, action.locale);
9
+ yield [
10
+ put({
11
+ type: types.GET_LOCIZ_MESSAGE_SUCCESS,
12
+ data: result,
13
+ }),
14
+ ];
15
+ } catch (error) {
16
+ yield [
17
+ put({
18
+ type: types.GET_LOCIZ_MESSAGE_FAILURE,
19
+ data: error,
20
+ }),
21
+ ];
22
+ }
23
+ }
24
+ export function* watchGetLocizMessage() {
25
+ const watcher = yield takeLatest(
26
+ types.GET_LOCIZ_MESSAGE_REQUEST,
27
+ getLocizMessage,
28
+ );
29
+ yield take(LOCATION_CHANGE);
30
+ yield cancel(watcher);
31
+ }
32
+
33
+ export default [watchGetLocizMessage];
34
+
35
+ export function* LanguageProviderRootSaga() {
36
+ yield all([
37
+ watchGetLocizMessage(),
38
+ ]);
39
+ }
@@ -11,7 +11,7 @@ const selectLanguage = (state) => state.get('language');
11
11
 
12
12
  const makeSelectLocale = () => createSelector(
13
13
  selectLanguage,
14
- (languageState) => languageState.get('locale')
14
+ (languageState) => languageState.toJS()
15
15
  );
16
16
 
17
17
  export {