263 lines
7.0 KiB
JavaScript
Raw Normal View History

/**
*
* Admin
*
*/
import React from 'react';
2019-04-03 13:05:18 +02:00
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { bindActionCreators, compose } from 'redux';
2019-04-03 13:05:18 +02:00
import { Switch, Route } from 'react-router-dom';
2019-11-07 10:48:02 +01:00
import { injectIntl } from 'react-intl';
2019-09-10 12:14:07 +02:00
import { isEmpty } from 'lodash';
2019-04-03 13:05:18 +02:00
// Components from strapi-helper-plugin
import {
2019-10-08 11:51:10 +02:00
difference,
GlobalContextProvider,
LoadingIndicatorPage,
OverlayBlocker,
} from 'strapi-helper-plugin';
2019-07-12 09:30:32 +02:00
import { SHOW_TUTORIALS } from '../../config';
2019-04-03 13:05:18 +02:00
import Header from '../../components/Header/index';
import Logout from '../../components/Logout';
2019-09-05 17:13:17 +02:00
import NavTopRightWrapper from '../../components/NavTopRightWrapper';
2019-04-03 13:05:18 +02:00
import LeftMenu from '../LeftMenu';
2019-04-16 11:53:29 +02:00
import ListPluginsPage from '../ListPluginsPage';
2019-04-03 13:05:18 +02:00
import LocaleToggle from '../LocaleToggle';
2019-04-16 11:53:29 +02:00
import HomePage from '../HomePage';
import Marketplace from '../Marketplace';
import NotFoundPage from '../NotFoundPage';
2019-04-03 14:10:42 +02:00
import Onboarding from '../Onboarding';
2019-04-03 13:05:18 +02:00
import PluginDispatcher from '../PluginDispatcher';
2019-04-12 18:23:26 +02:00
import {
disableGlobalOverlayBlocker,
enableGlobalOverlayBlocker,
updatePlugin,
} from '../App/actions';
2019-04-03 13:05:18 +02:00
import makeSelecApp from '../App/selectors';
import injectSaga from '../../utils/injectSaga';
import injectReducer from '../../utils/injectReducer';
2019-09-10 10:37:02 +02:00
import { emitEvent, setAppError } from './actions';
import makeSelectAdmin from './selectors';
import reducer from './reducer';
import saga from './saga';
2019-09-17 17:19:10 +02:00
import Wrapper from './Wrapper';
import Content from './Content';
2019-04-03 13:05:18 +02:00
export class Admin extends React.Component {
// eslint-disable-line react/prefer-stateless-function
2019-04-03 13:05:18 +02:00
helpers = {
updatePlugin: this.props.updatePlugin,
};
componentDidMount() {
this.props.emitEvent('didAccessAuthenticatedAdministration');
}
2019-09-10 12:14:07 +02:00
shouldComponentUpdate(prevProps) {
return !isEmpty(difference(prevProps, this.props));
}
2019-04-03 13:05:18 +02:00
/* istanbul ignore next */
componentDidCatch(error, info) {
/* eslint-disable */
console.log('An error has occured');
console.log('--------------------');
console.log(error);
console.log('Here is some infos');
console.log(info);
/* eslint-enable */
// Display the error log component which is not designed yet
this.props.setAppError();
}
hasApluginNotReady = props => {
const {
global: { plugins },
} = props;
return !Object.keys(plugins).every(
2019-07-12 09:30:32 +02:00
plugin => plugins[plugin].isReady === true
2019-04-03 13:05:18 +02:00
);
};
/**
* Display the app loader until the app is ready
* @returns {Boolean}
*/
showLoader = () => {
return this.hasApluginNotReady(this.props);
};
renderInitializers = () => {
const {
global: { plugins },
} = this.props;
return Object.keys(plugins).reduce((acc, current) => {
const InitializerComponent = plugins[current].initializer;
const key = plugins[current].id;
acc.push(
2019-07-12 09:30:32 +02:00
<InitializerComponent key={key} {...this.props} {...this.helpers} />
);
2019-04-03 13:05:18 +02:00
return acc;
}, []);
};
renderMarketPlace = props => <Marketplace {...props} {...this.props} />;
renderPluginDispatcher = props => {
// NOTE: Send the needed props instead of everything...
return <PluginDispatcher {...this.props} {...props} {...this.helpers} />;
};
2019-08-21 09:23:51 +02:00
renderRoute = (props, Component) => <Component {...this.props} {...props} />;
render() {
2019-04-03 13:05:18 +02:00
const {
global: {
blockApp,
overlayBlockerData,
plugins,
showGlobalAppBlocker,
strapiVersion,
},
2019-04-03 13:05:18 +02:00
} = this.props;
// We need the admin data in order to make the initializers work
if (this.showLoader()) {
return (
<>
2019-04-03 13:05:18 +02:00
{this.renderInitializers()}
<LoadingIndicatorPage />
</>
2019-04-03 13:05:18 +02:00
);
}
return (
<GlobalContextProvider
emitEvent={this.props.emitEvent}
currentEnvironment={this.props.global.currentEnvironment}
disableGlobalOverlayBlocker={this.props.disableGlobalOverlayBlocker}
enableGlobalOverlayBlocker={this.props.enableGlobalOverlayBlocker}
2019-11-07 10:48:02 +01:00
formatMessage={this.props.intl.formatMessage}
plugins={this.props.global.plugins}
updatePlugin={this.props.updatePlugin}
>
2019-09-17 17:19:10 +02:00
<Wrapper>
<LeftMenu version={strapiVersion} plugins={plugins} />
<NavTopRightWrapper>
{/* Injection zone not ready yet */}
<Logout />
<LocaleToggle isLogged />
</NavTopRightWrapper>
2019-09-17 17:19:10 +02:00
<div className="adminPageRightWrapper">
<Header />
2019-09-17 17:19:10 +02:00
<Content>
<Switch>
<Route
path="/"
render={props => this.renderRoute(props, HomePage)}
exact
/>
<Route
path="/plugins/:pluginId"
render={this.renderPluginDispatcher}
/>
<Route
path="/list-plugins"
render={props => this.renderRoute(props, ListPluginsPage)}
exact
/>
<Route
path="/marketplace"
render={this.renderMarketPlace}
exact
/>
<Route key="7" path="" component={NotFoundPage} />
<Route key="8" path="404" component={NotFoundPage} />
</Switch>
2019-09-17 17:19:10 +02:00
</Content>
2019-04-03 13:05:18 +02:00
</div>
<OverlayBlocker
key="overlayBlocker"
isOpen={blockApp && showGlobalAppBlocker}
{...overlayBlockerData}
/>
{SHOW_TUTORIALS && <Onboarding />}
2019-09-17 17:19:10 +02:00
</Wrapper>
</GlobalContextProvider>
2019-04-03 13:05:18 +02:00
);
}
}
Admin.defaultProps = {
intl: {
formatMessage: () => {},
},
};
2019-04-03 13:05:18 +02:00
Admin.propTypes = {
admin: PropTypes.shape({
appError: PropTypes.bool,
}).isRequired,
disableGlobalOverlayBlocker: PropTypes.func.isRequired,
emitEvent: PropTypes.func.isRequired,
enableGlobalOverlayBlocker: PropTypes.func.isRequired,
global: PropTypes.shape({
blockApp: PropTypes.bool,
currentEnvironment: PropTypes.string,
2019-04-03 13:05:18 +02:00
overlayBlockerData: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
plugins: PropTypes.object,
showGlobalAppBlocker: PropTypes.bool,
strapiVersion: PropTypes.string,
2019-04-03 13:05:18 +02:00
}).isRequired,
2019-11-07 10:48:02 +01:00
intl: PropTypes.shape({
formatMessage: PropTypes.func,
}),
2019-04-03 13:05:18 +02:00
location: PropTypes.object.isRequired,
setAppError: PropTypes.func.isRequired,
updatePlugin: PropTypes.func.isRequired,
};
const mapStateToProps = createStructuredSelector({
admin: makeSelectAdmin(),
2019-04-03 13:05:18 +02:00
global: makeSelecApp(),
});
2019-04-03 13:05:18 +02:00
export function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
disableGlobalOverlayBlocker,
emitEvent,
enableGlobalOverlayBlocker,
setAppError,
updatePlugin,
},
2019-07-12 09:30:32 +02:00
dispatch
2019-04-03 13:05:18 +02:00
);
}
const withConnect = connect(
mapStateToProps,
2019-07-12 09:30:32 +02:00
mapDispatchToProps
);
2019-04-03 13:05:18 +02:00
const withReducer = injectReducer({ key: 'admin', reducer });
const withSaga = injectSaga({ key: 'admin', saga });
export default compose(
2019-11-07 10:48:02 +01:00
injectIntl,
withReducer,
withSaga,
2019-09-10 10:37:02 +02:00
withConnect
)(Admin);