From fe1cb9585b54b8eecdf2eabf23a387e8b754b6dc Mon Sep 17 00:00:00 2001 From: chrisgarrity <chrisg@media.mit.edu> Date: Mon, 12 Feb 2018 09:29:54 -0500 Subject: [PATCH] Pass intl as prop to GUI Allow intl to be passed in to GUI as a prop (rather than having to be already in the store) --- .eslintignore | 1 + .gitignore | 1 + src/containers/language-selector.jsx | 4 +- src/lib/app-state-hoc.jsx | 40 ++++++++++++++----- src/{examples => playground}/blocks-only.css | 0 src/{examples => playground}/blocks-only.jsx | 2 +- .../compatibility-testing.jsx | 2 +- src/{ => playground}/index.css | 0 src/{ => playground}/index.ejs | 0 src/{ => playground}/index.jsx | 8 ++-- src/playground/intl.js | 25 ++++++++++++ src/{examples => playground}/player.css | 0 src/{examples => playground}/player.jsx | 2 +- .../project-loader-hoc.jsx | 6 +-- src/reducers/intl.js | 28 ++----------- test/unit/util/project-loader-hoc.test.jsx | 2 +- webpack.config.js | 16 ++++---- 17 files changed, 79 insertions(+), 58 deletions(-) rename src/{examples => playground}/blocks-only.css (100%) rename src/{examples => playground}/blocks-only.jsx (93%) rename src/{examples => playground}/compatibility-testing.jsx (97%) rename src/{ => playground}/index.css (100%) rename src/{ => playground}/index.ejs (100%) rename src/{ => playground}/index.jsx (76%) create mode 100644 src/playground/intl.js rename src/{examples => playground}/player.css (100%) rename src/{examples => playground}/player.jsx (97%) rename src/{lib => playground}/project-loader-hoc.jsx (96%) diff --git a/.eslintignore b/.eslintignore index 3675648e8..93c033154 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ node_modules/* build/* +dist/* diff --git a/.gitignore b/.gitignore index 8f98cc55b..0b8a0db40 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ npm-* # Build /build +/dist /.opt-in # generated translation files diff --git a/src/containers/language-selector.jsx b/src/containers/language-selector.jsx index ae0d2405c..316b1577a 100644 --- a/src/containers/language-selector.jsx +++ b/src/containers/language-selector.jsx @@ -1,5 +1,4 @@ import {connect} from 'react-redux'; -import {updateIntl} from '../reducers/intl.js'; import LanguageSelectorComponent from '../components/language-selector/language-selector.jsx'; @@ -7,10 +6,9 @@ const mapStateToProps = state => ({ currentLocale: state.intl.locale }); -const mapDispatchToProps = dispatch => ({ +const mapDispatchToProps = () => ({ onChange: e => { e.preventDefault(); - dispatch(updateIntl(e.target.value)); } }); diff --git a/src/lib/app-state-hoc.jsx b/src/lib/app-state-hoc.jsx index 2894cda13..158ac40d0 100644 --- a/src/lib/app-state-hoc.jsx +++ b/src/lib/app-state-hoc.jsx @@ -3,7 +3,9 @@ import {Provider} from 'react-redux'; import {createStore, applyMiddleware, compose} from 'redux'; import throttle from 'redux-throttle'; -import {intlInitialState, IntlProvider} from '../reducers/intl.js'; +import {intlShape} from 'react-intl'; +import {IntlProvider, updateIntl} from 'react-intl-redux'; +import {intlInitialState} from '../reducers/intl.js'; import reducer from '../reducers/gui'; const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; @@ -12,7 +14,6 @@ const enhancer = composeEnhancers( throttle(300, {leading: true, trailing: true}) ) ); -const store = createStore(reducer, intlInitialState, enhancer); import ErrorBoundary from '../containers/error-boundary.jsx'; @@ -22,15 +23,32 @@ import ErrorBoundary from '../containers/error-boundary.jsx'; * @returns {React.Component} component with redux and intl state provided */ const AppStateHOC = function (WrappedComponent) { - const AppStateWrapper = ({...props}) => ( - <Provider store={store}> - <IntlProvider> - <ErrorBoundary> - <WrappedComponent {...props} /> - </ErrorBoundary> - </IntlProvider> - </Provider> - ); + class AppStateWrapper extends React.Component { + constructor (props) { + super(props); + this.store = createStore(reducer, (props.intl || intlInitialState), enhancer); + } + componentDidUpdate (prevProps) { + if (prevProps.intl !== this.props.intl) updateIntl(this.props.intl); + } + render () { + return ( + <Provider store={this.store}> + <IntlProvider> + <ErrorBoundary> + <WrappedComponent {...this.props} /> + </ErrorBoundary> + </IntlProvider> + </Provider> + ); + + } + + + } + AppStateWrapper.propTypes = { + intl: intlShape + }; return AppStateWrapper; }; diff --git a/src/examples/blocks-only.css b/src/playground/blocks-only.css similarity index 100% rename from src/examples/blocks-only.css rename to src/playground/blocks-only.css diff --git a/src/examples/blocks-only.jsx b/src/playground/blocks-only.jsx similarity index 93% rename from src/examples/blocks-only.jsx rename to src/playground/blocks-only.jsx index 8d5159e82..417ab85c9 100644 --- a/src/examples/blocks-only.jsx +++ b/src/playground/blocks-only.jsx @@ -6,7 +6,7 @@ import AppStateHOC from '../lib/app-state-hoc.jsx'; import Controls from '../containers/controls.jsx'; import Blocks from '../containers/blocks.jsx'; import GUI from '../containers/gui.jsx'; -import ProjectLoaderHOC from '../lib/project-loader-hoc.jsx'; +import ProjectLoaderHOC from './project-loader-hoc.jsx'; import styles from './blocks-only.css'; diff --git a/src/examples/compatibility-testing.jsx b/src/playground/compatibility-testing.jsx similarity index 97% rename from src/examples/compatibility-testing.jsx rename to src/playground/compatibility-testing.jsx index 3fa8e71d9..513758023 100644 --- a/src/examples/compatibility-testing.jsx +++ b/src/playground/compatibility-testing.jsx @@ -7,7 +7,7 @@ import Controls from '../containers/controls.jsx'; import Stage from '../containers/stage.jsx'; import Box from '../components/box/box.jsx'; import GUI from '../containers/gui.jsx'; -import ProjectLoaderHOC from '../lib/project-loader-hoc.jsx'; +import ProjectLoaderHOC from './project-loader-hoc.jsx'; const mapStateToProps = state => ({vm: state.vm}); diff --git a/src/index.css b/src/playground/index.css similarity index 100% rename from src/index.css rename to src/playground/index.css diff --git a/src/index.ejs b/src/playground/index.ejs similarity index 100% rename from src/index.ejs rename to src/playground/index.ejs diff --git a/src/index.jsx b/src/playground/index.jsx similarity index 76% rename from src/index.jsx rename to src/playground/index.jsx index 114c45ce0..0574c8d09 100644 --- a/src/index.jsx +++ b/src/playground/index.jsx @@ -3,10 +3,10 @@ import React from 'react'; import ReactDOM from 'react-dom'; import Modal from 'react-modal'; -import analytics from './lib/analytics'; -import AppStateHOC from './lib/app-state-hoc.jsx'; -import GUI from './containers/gui.jsx'; -import ProjectLoaderHOC from './lib/project-loader-hoc.jsx'; +import analytics from '../lib/analytics'; +import AppStateHOC from '../lib/app-state-hoc.jsx'; +import GUI from '../containers/gui.jsx'; +import ProjectLoaderHOC from './project-loader-hoc.jsx'; import styles from './index.css'; diff --git a/src/playground/intl.js b/src/playground/intl.js new file mode 100644 index 000000000..bc427c402 --- /dev/null +++ b/src/playground/intl.js @@ -0,0 +1,25 @@ +import {addLocaleData} from 'react-intl'; +import defaultsDeep from 'lodash.defaultsdeep'; + +import localeData from 'scratch-l10n'; +import guiMessages from 'scratch-l10n/locales/gui-msgs'; +import paintMessages from 'scratch-l10n/locales/paint-msgs'; +import penMessages from 'scratch-l10n/locales/pen-msgs'; + +const combinedMessages = defaultsDeep({}, guiMessages.messages, paintMessages.messages, penMessages.messages); + +Object.keys(localeData).forEach(locale => { + // TODO: will need to handle locales not in the default intl - see www/custom-locales + addLocaleData(localeData[locale].localeData); +}); + +const intlDefault = { + defaultLocale: 'en', + locale: 'en', + messages: combinedMessages.en.messages +}; + +export { + intlDefault as default, + combinedMessages +}; diff --git a/src/examples/player.css b/src/playground/player.css similarity index 100% rename from src/examples/player.css rename to src/playground/player.css diff --git a/src/examples/player.jsx b/src/playground/player.jsx similarity index 97% rename from src/examples/player.jsx rename to src/playground/player.jsx index ab50527cd..30b18e8ed 100644 --- a/src/examples/player.jsx +++ b/src/playground/player.jsx @@ -7,7 +7,7 @@ import Controls from '../containers/controls.jsx'; import Stage from '../containers/stage.jsx'; import Box from '../components/box/box.jsx'; import GUI from '../containers/gui.jsx'; -import ProjectLoaderHOC from '../lib/project-loader-hoc.jsx'; +import ProjectLoaderHOC from './project-loader-hoc.jsx'; import './player.css'; diff --git a/src/lib/project-loader-hoc.jsx b/src/playground/project-loader-hoc.jsx similarity index 96% rename from src/lib/project-loader-hoc.jsx rename to src/playground/project-loader-hoc.jsx index 5ccb382b2..3ebacee17 100644 --- a/src/lib/project-loader-hoc.jsx +++ b/src/playground/project-loader-hoc.jsx @@ -1,8 +1,8 @@ import React from 'react'; -import analytics from './analytics'; -import log from './log'; -import storage from './storage'; +import analytics from '../lib/analytics'; +import log from '../lib/log'; +import storage from '../lib/storage'; /* Higher Order Component to provide behavior for loading projects by id from * the window's hash (#this part in the url) diff --git a/src/reducers/intl.js b/src/reducers/intl.js index 15a2d307b..8c49ee104 100644 --- a/src/reducers/intl.js +++ b/src/reducers/intl.js @@ -1,36 +1,14 @@ -import {addLocaleData} from 'react-intl'; -import {updateIntl as superUpdateIntl} from 'react-intl-redux'; -import {IntlProvider, intlReducer} from 'react-intl-redux'; -import defaultsDeep from 'lodash.defaultsdeep'; - -import localeData from 'scratch-l10n'; -import guiMessages from 'scratch-l10n/locales/gui-msgs'; -import paintMessages from 'scratch-l10n/locales/paint-msgs'; -import penMessages from 'scratch-l10n/locales/pen-msgs'; - -const combinedMessages = defaultsDeep({}, guiMessages.messages, paintMessages.messages, penMessages.messages); - -Object.keys(localeData).forEach(locale => { - // TODO: will need to handle locales not in the default intl - see www/custom-locales - addLocaleData(localeData[locale].localeData); -}); +import {intlReducer} from 'react-intl-redux'; const intlInitialState = { intl: { defaultLocale: 'en', locale: 'en', - messages: combinedMessages.en.messages + messages: {} } }; -const updateIntl = locale => superUpdateIntl({ - locale: locale, - messages: combinedMessages[locale].messages || combinedMessages.en.messages -}); - export { intlReducer as default, - IntlProvider, - intlInitialState, - updateIntl + intlInitialState }; diff --git a/test/unit/util/project-loader-hoc.test.jsx b/test/unit/util/project-loader-hoc.test.jsx index 5acde098e..997224e74 100644 --- a/test/unit/util/project-loader-hoc.test.jsx +++ b/test/unit/util/project-loader-hoc.test.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import ProjectLoaderHOC from '../../../src/lib/project-loader-hoc.jsx'; +import ProjectLoaderHOC from '../../../src/playground/project-loader-hoc.jsx'; import storage from '../../../src/lib/storage'; import {mount} from 'enzyme'; diff --git a/webpack.config.js b/webpack.config.js index 389cf8abd..4a94a9a0d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -19,10 +19,10 @@ module.exports = { devtool: 'cheap-module-source-map', entry: { lib: ['react', 'react-dom'], - gui: './src/index.jsx', - blocksonly: './src/examples/blocks-only.jsx', - compatibilitytesting: './src/examples/compatibility-testing.jsx', - player: './src/examples/player.jsx' + gui: './src/playground/index.jsx', + blocksonly: './src/playground/blocks-only.jsx', + compatibilitytesting: './src/playground/compatibility-testing.jsx', + player: './src/playground/player.jsx' }, output: { path: path.resolve(__dirname, 'build'), @@ -82,24 +82,24 @@ module.exports = { }), new HtmlWebpackPlugin({ chunks: ['lib', 'gui'], - template: 'src/index.ejs', + template: 'src/playground/index.ejs', title: 'Scratch 3.0 GUI' }), new HtmlWebpackPlugin({ chunks: ['lib', 'blocksonly'], - template: 'src/index.ejs', + template: 'src/playground/index.ejs', filename: 'blocks-only.html', title: 'Scratch 3.0 GUI: Blocks Only Example' }), new HtmlWebpackPlugin({ chunks: ['lib', 'compatibilitytesting'], - template: 'src/index.ejs', + template: 'src/playground/index.ejs', filename: 'compatibility-testing.html', title: 'Scratch 3.0 GUI: Compatibility Testing' }), new HtmlWebpackPlugin({ chunks: ['lib', 'player'], - template: 'src/index.ejs', + template: 'src/playground/index.ejs', filename: 'player.html', title: 'Scratch 3.0 GUI: Player Example' }), -- GitLab