Improve plugin structure

This commit is contained in:
Pierre Burgy 2017-05-11 15:52:22 +02:00
parent 4d01c55d01
commit d95ef7f2fa
9 changed files with 40 additions and 96 deletions

View File

@ -15,6 +15,14 @@ import configureStore from './store';
import { selectLocationState } from './containers/App/selectors'; import { selectLocationState } from './containers/App/selectors';
import { translationMessages } from './i18n'; import { translationMessages } from './i18n';
// Plugin identifier based on the package.json `name` value
const pluginId = require('../package.json').name.replace(
/^strapi-plugin-/i,
''
);
const apiUrl = window.Strapi && `${window.Strapi.apiUrl}/${pluginId}`;
const router = window.Strapi.router;
// Create redux store with history // Create redux store with history
// this uses the singleton browserHistory provided by react-router // this uses the singleton browserHistory provided by react-router
// Optionally, this could be changed to leverage a created history // Optionally, this could be changed to leverage a created history
@ -28,31 +36,17 @@ syncHistoryWithStore(window.Strapi.router, store, {
selectLocationState: selectLocationState(), selectLocationState: selectLocationState(),
}); });
// Plugin identifier based on the package.json `name` value // Define the plugin root component
const pluginId = require('../package.json').name.replace( function Comp(props) {
/^strapi-plugin-/i, return (
'' <Provider store={store}>
); <App {...props} />
</Provider>
// Define Strapi admin router );
let router; // eslint-disable-line import/no-mutable-exports
class comp extends React.Component {
componentWillMount() {
// Expose Strapi admin router
router = this.context.router;
}
render() {
return (
<Provider store={store}>
<App {...this.props} />
</Provider>
);
}
} }
comp.contextTypes = { // Add contextTypes to get access to the admin router
Comp.contextTypes = {
router: React.PropTypes.object.isRequired, router: React.PropTypes.object.isRequired,
}; };
@ -63,30 +57,11 @@ if (window.Strapi) {
icon: 'ion-document-text', icon: 'ion-document-text',
id: pluginId, id: pluginId,
leftMenuLinks: [], leftMenuLinks: [],
mainComponent: comp, mainComponent: Comp,
routes: createRoutes(store), routes: createRoutes(store),
translationMessages, translationMessages,
}); });
} }
// Hot reloadable translation json files
if (module.hot) {
// modules.hot.accept does not accept dynamic dependencies,
// have to be constants at compile-time
module.hot.accept('./i18n', () => {
if (window.Strapi) {
System.import('./i18n').then(result => {
const translationMessagesUpdated = result.translationMessages;
window.Strapi
.refresh(pluginId)
.translationMessages(translationMessagesUpdated);
});
}
});
}
// API
const apiUrl = window.Strapi && `${window.Strapi.apiUrl}/${pluginId}`;
// Export store // Export store
export { store, apiUrl, pluginId, router }; export { store, apiUrl, pluginId, router };

View File

@ -1,5 +1,5 @@
/* /*
* HomePage * Home
*/ */
import React from 'react'; import React from 'react';
@ -11,7 +11,7 @@ import Container from '../../components/Container';
import styles from './styles.scss'; import styles from './styles.scss';
export class HomePage extends React.Component { export class Home extends React.Component {
render() { render() {
const PluginHeader = this.props.exposedComponents.PluginHeader; const PluginHeader = this.props.exposedComponents.PluginHeader;
@ -40,7 +40,7 @@ export class HomePage extends React.Component {
} }
} }
HomePage.propTypes = { Home.propTypes = {
exposedComponents: React.PropTypes.object.isRequired, exposedComponents: React.PropTypes.object.isRequired,
}; };
@ -52,5 +52,5 @@ const mapStateToProps = createStructuredSelector({});
// Wrap the component to inject dispatch and state into it // Wrap the component to inject dispatch and state into it
export default connect(mapStateToProps, mapDispatchToProps)( export default connect(mapStateToProps, mapDispatchToProps)(
injectIntl(HomePage) injectIntl(Home)
); );

View File

@ -10,7 +10,7 @@
border: 0; border: 0;
} }
p{ p {
display: block; display: block;
margin: 0; margin: 0;
padding-bottom: 14px; padding-bottom: 14px;

View File

@ -1,10 +0,0 @@
/*
* Constants
* Each action has a corresponding type, which the reducer knows and picks up on.
* To avoid weird typos between the reducer and the actions, we save them as
* constants here. We prefix them with 'yourplugin/YourComponent' so we avoid
* reducers accidentally picking up actions they shouldn't.
*
* Follow this format:
* export const YOUR_ACTION_CONSTANT = 'your-plugin/YourContainer/YOUR_ACTION_CONSTANT';
*/

View File

@ -1,25 +0,0 @@
/*
* Reducer
*
* The reducer takes care of our data. Using actions, we can change our
* application state.
* To add a new action, add it to the switch statement in the reducer function
*
* Example:
* case YOUR_ACTION_CONSTANT:
* return state.set('yourStateVariable', true);
*/
import { fromJS } from 'immutable';
// The initial state of the App
const initialState = fromJS({});
function appReducer(state = initialState, action) {
switch (action.type) {
default:
return state;
}
}
export default appReducer;

View File

@ -1,7 +0,0 @@
/**
* The home state selectors
*/
const selectHome = state => state.get('home');
export { selectHome };

View File

@ -19,4 +19,20 @@ const define = messages => {
defineMessages(messages); defineMessages(messages);
}; };
// Hot reloadable translation json files
if (module.hot) {
// modules.hot.accept does not accept dynamic dependencies,
// have to be constants at compile-time
module.hot.accept('./i18n', () => {
if (window.Strapi) {
System.import('./i18n').then(result => {
const translationMessagesUpdated = result.translationMessages;
window.Strapi
.refresh(pluginId)
.translationMessages(translationMessagesUpdated);
});
}
});
}
export { translationMessages, define }; export { translationMessages, define };

View File

@ -21,13 +21,11 @@ export default function createRoutes(store) {
path: '', path: '',
name: 'home', name: 'home',
getComponent(nextState, cb) { getComponent(nextState, cb) {
const reducer = require('./containers/HomePage/reducer'); // eslint-disable-line global-require const component = require('./containers/Home'); // eslint-disable-line global-require
const component = require('./containers/HomePage'); // eslint-disable-line global-require
const renderRoute = loadModule(cb); const renderRoute = loadModule(cb);
process.nextTick(() => { process.nextTick(() => {
injectReducer('home', reducer.default);
renderRoute(component); renderRoute(component);
}); });
}, },