mirror of
https://github.com/strapi/strapi.git
synced 2025-09-09 08:39:45 +00:00
Clean files
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
dd71bf28ef
commit
ddc7a3d60b
@ -10,7 +10,7 @@ import App from './containers/App';
|
||||
import Fonts from './components/Fonts';
|
||||
|
||||
// TODO
|
||||
import { translationMessages } from './i18n';
|
||||
import translationMessages from './translations';
|
||||
|
||||
// const App = () => 'todo';
|
||||
|
||||
|
@ -1,228 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* app.js
|
||||
*
|
||||
* Entry point of the application
|
||||
*/
|
||||
|
||||
// NOTE TO PLUGINS DEVELOPERS:
|
||||
// If you modify this file by adding new options to a plugin entry point
|
||||
// Here's the file: strapi/docs/3.0.0-beta.x/plugin-development/frontend-field-api.md
|
||||
// Here's the file: strapi/docs/3.0.0-beta.x/guides/registering-a-field-in-admin.md
|
||||
// Also the strapi-generate-plugins/files/admin/src/index.js needs to be updated
|
||||
// IF THE DOC IS NOT UPDATED THE PULL REQUEST WILL NOT BE MERGED
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
// import '@babel/polyfill';
|
||||
import 'sanitize.css/sanitize.css';
|
||||
|
||||
// Third party css library needed
|
||||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
import 'font-awesome/css/font-awesome.min.css';
|
||||
import '@fortawesome/fontawesome-free/css/all.css';
|
||||
import '@fortawesome/fontawesome-free/js/all.min.js';
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
// Strapi provider with the internal APIs
|
||||
import { StrapiProvider } from '@strapi/helper-plugin';
|
||||
import { merge } from 'lodash';
|
||||
import Fonts from './components/Fonts';
|
||||
import { freezeApp, pluginLoaded, unfreezeApp, updatePlugin } from './containers/App/actions';
|
||||
import { showNotification } from './containers/NotificationProvider/actions';
|
||||
import { showNotification as showNewNotification } from './containers/NewNotification/actions';
|
||||
|
||||
import basename from './utils/basename';
|
||||
import injectReducer from './utils/injectReducer';
|
||||
import injectSaga from './utils/injectSaga';
|
||||
import Strapi from './utils/Strapi';
|
||||
|
||||
// Import root component
|
||||
import App from './containers/App';
|
||||
// Import Language provider
|
||||
import LanguageProvider from './containers/LanguageProvider';
|
||||
|
||||
import configureStore from './configureStore';
|
||||
|
||||
// Import i18n messages
|
||||
import { translationMessages, languages } from './i18n';
|
||||
|
||||
import history from './utils/history';
|
||||
|
||||
import plugins from './plugins';
|
||||
|
||||
const strapi = Strapi();
|
||||
|
||||
const pluginsReducers = {};
|
||||
const pluginsToLoad = [];
|
||||
|
||||
Object.keys(plugins).forEach(current => {
|
||||
const registerPlugin = plugin => {
|
||||
strapi.registerPlugin(plugin);
|
||||
|
||||
return plugin;
|
||||
};
|
||||
const currentPluginFn = plugins[current];
|
||||
|
||||
// By updating this by adding required methods
|
||||
// to load a plugin you need to update this file
|
||||
// strapi-generate-plugins/files/admin/src/index.js needs to be updated
|
||||
const plugin = currentPluginFn({
|
||||
registerComponent: strapi.componentApi.registerComponent,
|
||||
registerField: strapi.fieldApi.registerField,
|
||||
registerPlugin,
|
||||
middlewares: strapi.middlewares,
|
||||
});
|
||||
|
||||
const pluginTradsPrefixed = languages.reduce((acc, lang) => {
|
||||
const currentLocale = plugin.trads[lang];
|
||||
|
||||
if (currentLocale) {
|
||||
const localeprefixedWithPluginId = Object.keys(currentLocale).reduce((acc2, current) => {
|
||||
acc2[`${plugin.id}.${current}`] = currentLocale[current];
|
||||
|
||||
return acc2;
|
||||
}, {});
|
||||
|
||||
acc[lang] = localeprefixedWithPluginId;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// Retrieve all reducers
|
||||
const pluginReducers = plugin.reducers || {};
|
||||
|
||||
Object.keys(pluginReducers).forEach(reducerName => {
|
||||
pluginsReducers[reducerName] = pluginReducers[reducerName];
|
||||
});
|
||||
|
||||
try {
|
||||
merge(translationMessages, pluginTradsPrefixed);
|
||||
pluginsToLoad.push(plugin);
|
||||
} catch (err) {
|
||||
console.log({ err });
|
||||
}
|
||||
});
|
||||
|
||||
const initialState = {};
|
||||
const store = configureStore(initialState, pluginsReducers, strapi);
|
||||
const { dispatch } = store;
|
||||
|
||||
// Load plugins, this will be removed in the v4, temporary fix until the plugin API
|
||||
// https://plugin-api-rfc.vercel.app/plugin-api/admin.html
|
||||
pluginsToLoad.forEach(plugin => {
|
||||
const bootPlugin = plugin.boot;
|
||||
|
||||
if (bootPlugin) {
|
||||
bootPlugin(strapi);
|
||||
}
|
||||
|
||||
dispatch(pluginLoaded(plugin));
|
||||
});
|
||||
|
||||
const displayNotification = (message, status) => {
|
||||
console.warn(
|
||||
// Validate the text
|
||||
'Deprecated: Will be deleted.\nPlease use strapi.notification.toggle(config).\nDocs : https://strapi.io/documentation/developer-docs/latest/development/local-plugins-customization.html#strapi-notification'
|
||||
);
|
||||
dispatch(showNotification(message, status));
|
||||
};
|
||||
const displayNewNotification = config => {
|
||||
dispatch(showNewNotification(config));
|
||||
};
|
||||
const lockApp = data => {
|
||||
dispatch(freezeApp(data));
|
||||
};
|
||||
const unlockApp = () => {
|
||||
dispatch(unfreezeApp());
|
||||
};
|
||||
|
||||
const lockAppWithOverlay = () => {
|
||||
const overlayblockerParams = {
|
||||
children: <div />,
|
||||
noGradient: true,
|
||||
};
|
||||
|
||||
lockApp(overlayblockerParams);
|
||||
};
|
||||
|
||||
window.strapi = Object.assign(window.strapi || {}, {
|
||||
backendURL: BACKEND_URL === '/' ? window.location.origin : BACKEND_URL,
|
||||
notification: {
|
||||
// New notification api
|
||||
toggle: config => {
|
||||
displayNewNotification(config);
|
||||
},
|
||||
success: message => {
|
||||
displayNotification(message, 'success');
|
||||
},
|
||||
warning: message => {
|
||||
displayNotification(message, 'warning');
|
||||
},
|
||||
error: message => {
|
||||
displayNotification(message, 'error');
|
||||
},
|
||||
info: message => {
|
||||
displayNotification(message, 'info');
|
||||
},
|
||||
},
|
||||
refresh: pluginId => ({
|
||||
translationMessages: translationMessagesUpdated => {
|
||||
render(merge({}, translationMessages, translationMessagesUpdated));
|
||||
},
|
||||
leftMenuSections: leftMenuSectionsUpdated => {
|
||||
store.dispatch(updatePlugin(pluginId, 'leftMenuSections', leftMenuSectionsUpdated));
|
||||
},
|
||||
}),
|
||||
router: history,
|
||||
languages,
|
||||
currentLanguage:
|
||||
window.localStorage.getItem('strapi-admin-language') ||
|
||||
window.navigator.language ||
|
||||
window.navigator.userLanguage ||
|
||||
'en',
|
||||
lockApp,
|
||||
lockAppWithOverlay,
|
||||
unlockApp,
|
||||
injectReducer,
|
||||
injectSaga,
|
||||
store,
|
||||
});
|
||||
|
||||
const MOUNT_NODE = document.getElementById('app') || document.createElement('div');
|
||||
|
||||
const render = messages => {
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<StrapiProvider strapi={strapi}>
|
||||
<Fonts />
|
||||
<LanguageProvider messages={messages}>
|
||||
<BrowserRouter basename={basename}>
|
||||
<App store={store} />
|
||||
</BrowserRouter>
|
||||
</LanguageProvider>
|
||||
</StrapiProvider>
|
||||
</Provider>,
|
||||
MOUNT_NODE
|
||||
);
|
||||
};
|
||||
|
||||
// Not needed we will use a plugin for this
|
||||
// if (module.hot) {
|
||||
// module.hot.accept(['./i18n', './containers/App'], () => {
|
||||
// ReactDOM.unmountComponentAtNode(MOUNT_NODE);
|
||||
|
||||
// render(translationMessages);
|
||||
// });
|
||||
// }
|
||||
|
||||
if (NODE_ENV !== 'test') {
|
||||
render(translationMessages);
|
||||
}
|
||||
|
||||
// @Pierre Burgy exporting dispatch for the notifications...
|
||||
export { dispatch };
|
@ -1,60 +0,0 @@
|
||||
/**
|
||||
* Create the store with dynamic reducers
|
||||
*/
|
||||
|
||||
import { createStore, applyMiddleware, compose } from 'redux';
|
||||
import { fromJS } from 'immutable';
|
||||
// import { routerMiddleware } from 'react-router-redux';
|
||||
import createSagaMiddleware from 'redux-saga';
|
||||
import createReducer from './reducers';
|
||||
|
||||
const sagaMiddleware = createSagaMiddleware();
|
||||
|
||||
export default function configureStore(initialState = {}, reducers, strapi) {
|
||||
// Create the store with two middlewares
|
||||
// 1. sagaMiddleware: Makes redux-sagas work
|
||||
// 2. routerMiddleware: Syncs the location/URL path to the state
|
||||
const middlewares = [sagaMiddleware];
|
||||
|
||||
strapi.middlewares.middlewares.forEach(middleware => {
|
||||
middlewares.push(middleware());
|
||||
});
|
||||
|
||||
const enhancers = [applyMiddleware(...middlewares)];
|
||||
|
||||
// If Redux DevTools Extension is installed use it, otherwise use Redux compose
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
const composeEnhancers =
|
||||
process.env.NODE_ENV !== 'production' &&
|
||||
typeof window === 'object' &&
|
||||
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|
||||
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
|
||||
// TODO Try to remove when `react-router-redux` is out of beta, LOCATION_CHANGE should not be fired more than once after hot reloading
|
||||
// Prevent recomputing reducers for `replaceReducer`
|
||||
shouldHotReload: false,
|
||||
name: 'Strapi - Dashboard',
|
||||
})
|
||||
: compose;
|
||||
/* eslint-enable */
|
||||
|
||||
const store = createStore(
|
||||
createReducer(reducers),
|
||||
fromJS(initialState),
|
||||
composeEnhancers(...enhancers)
|
||||
);
|
||||
|
||||
// Extensions
|
||||
store.runSaga = sagaMiddleware.run;
|
||||
store.injectedReducers = {}; // Reducer registry
|
||||
store.injectedSagas = {}; // Saga registry
|
||||
|
||||
// Make reducers hot reloadable, see http://mxs.is/googmo
|
||||
/* istanbul ignore next */
|
||||
if (module.hot) {
|
||||
module.hot.accept('./reducers', () => {
|
||||
store.replaceReducer(createReducer(store.injectedReducers));
|
||||
});
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
@ -48,6 +48,9 @@ window.strapi = Object.assign(window.strapi || {}, {
|
||||
toggle: () => {},
|
||||
},
|
||||
backendURL: BACKEND_URL,
|
||||
lockApp: () => console.log('todo lockApp'),
|
||||
unlockApp: () => console.log('todo unlockApp'),
|
||||
lockAppWithOverlay: () => console.log('todo unlockAppWithOverlay'),
|
||||
});
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
|
@ -11,18 +11,5 @@ const selectApp = () => state => state.app;
|
||||
|
||||
const makeSelectApp = () => createSelector(selectApp(), appState => appState.toJS());
|
||||
|
||||
const makeSelectShowGlobalAppBlocker = () =>
|
||||
createSelector(selectApp(), appState => appState.get('showGlobalAppBlocker'));
|
||||
|
||||
const makeSelectBlockApp = () => createSelector(selectApp(), appState => appState.get('blockApp'));
|
||||
|
||||
const makeSelectOverlayBlockerProps = () =>
|
||||
createSelector(selectApp(), appState => appState.get('overlayBlockerData'));
|
||||
|
||||
export default makeSelectApp;
|
||||
export {
|
||||
selectApp,
|
||||
makeSelectBlockApp,
|
||||
makeSelectOverlayBlockerProps,
|
||||
makeSelectShowGlobalAppBlocker,
|
||||
};
|
||||
export { selectApp };
|
||||
|
@ -1,11 +1,6 @@
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
import makeSelectApp, {
|
||||
selectApp,
|
||||
makeSelectBlockApp,
|
||||
makeSelectOverlayBlockerProps,
|
||||
makeSelectShowGlobalAppBlocker,
|
||||
} from '../selectors';
|
||||
import makeSelectApp, { selectApp } from '../selectors';
|
||||
|
||||
describe('<App /> selectors', () => {
|
||||
describe('selectApp', () => {
|
||||
@ -29,41 +24,4 @@ describe('<App /> selectors', () => {
|
||||
expect(makeSelectApp()(mockedState)).toEqual(appState.toJS());
|
||||
});
|
||||
});
|
||||
|
||||
describe('makeSelectBlockApp', () => {
|
||||
it('should select the blockApp', () => {
|
||||
const mockedState = fromJS({
|
||||
app: {
|
||||
blockApp: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(makeSelectBlockApp()(mockedState)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('makeSelectOverlayBlockerProps', () => {
|
||||
it('should select the overlayBlockerData', () => {
|
||||
const overlayBlockerData = fromJS({ title: 'title' });
|
||||
const mockedState = {
|
||||
app: {
|
||||
overlayBlockerData,
|
||||
},
|
||||
};
|
||||
|
||||
expect(makeSelectOverlayBlockerProps()(mockedState)).toEqual(overlayBlockerData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('makeSelectShowGlobalAppBlocker', () => {
|
||||
it('should select the showGlobalAppBlocker', () => {
|
||||
const mockedState = {
|
||||
app: {
|
||||
showGlobalAppBlocker: true,
|
||||
},
|
||||
};
|
||||
|
||||
expect(makeSelectShowGlobalAppBlocker()(mockedState)).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -11,11 +11,13 @@ import { createStructuredSelector } from 'reselect';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import cn from 'classnames';
|
||||
import { ButtonDropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'reactstrap';
|
||||
import translationMessages, { languageNativeNames } from '../../translations';
|
||||
import makeSelectLocale from '../LanguageProvider/selectors';
|
||||
import { changeLocale } from '../LanguageProvider/actions';
|
||||
import { languages, languageNativeNames } from '../../i18n';
|
||||
import Wrapper from './Wrapper';
|
||||
|
||||
// TODO
|
||||
const languages = Object.keys(translationMessages);
|
||||
export class LocaleToggle extends React.Component {
|
||||
// eslint-disable-line
|
||||
state = { isOpen: false };
|
||||
|
@ -4,7 +4,7 @@ import { Padded, Text } from '@buffetjs/core';
|
||||
import { Col } from 'reactstrap';
|
||||
import { get } from 'lodash';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { languages, languageNativeNames } from '../../i18n';
|
||||
import translationMessages, { languageNativeNames } from '../../translations';
|
||||
import ContainerFluid from '../../components/ContainerFluid';
|
||||
import PageTitle from '../../components/PageTitle';
|
||||
import SizedInput from '../../components/SizedInput';
|
||||
@ -15,6 +15,8 @@ import useChangeLanguage from '../LanguageProvider/hooks/useChangeLanguage';
|
||||
import ProfilePageLabel from './components';
|
||||
import { form, schema } from './utils';
|
||||
|
||||
const languages = Object.keys(translationMessages);
|
||||
|
||||
const ProfilePage = () => {
|
||||
const changeLanguage = useChangeLanguage();
|
||||
const { formatMessage } = useIntl();
|
||||
|
@ -1,17 +0,0 @@
|
||||
/**
|
||||
* i18n.js
|
||||
*
|
||||
* This will setup the i18n language files and locale data for your plugin.
|
||||
*
|
||||
*/
|
||||
|
||||
// NOTE TO PLUGINS DEVELOPERS:
|
||||
// If you modify this file you also need to update the documentation accordingly
|
||||
// Here's the file: strapi/docs/3.0.0-beta.x/admin-panel/customization.md#customize-the-strapi-admin-package
|
||||
// IF THE DOC IS NOT UPDATED THE PULL REQUEST WILL NOT BE MERGED
|
||||
|
||||
import translationMessages, { languageNativeNames } from './translations';
|
||||
|
||||
const languages = Object.keys(translationMessages);
|
||||
|
||||
export { languages, translationMessages, languageNativeNames };
|
@ -1,34 +0,0 @@
|
||||
/* eslint-disable */
|
||||
|
||||
const injectReducer = require('./utils/injectReducer').default;
|
||||
const useInjectReducer = require('./utils/injectReducer').useInjectReducer;
|
||||
const injectSaga = require('./utils/injectSaga').default;
|
||||
const useInjectSaga = require('./utils/injectSaga').useInjectSaga;
|
||||
const { languages } = require('./i18n');
|
||||
|
||||
window.strapi = Object.assign(window.strapi || {}, {
|
||||
backendURL: BACKEND_URL === '/' ? window.location.origin : BACKEND_URL,
|
||||
languages,
|
||||
currentLanguage:
|
||||
window.localStorage.getItem('strapi-admin-language') ||
|
||||
window.navigator.language ||
|
||||
window.navigator.userLanguage ||
|
||||
'en',
|
||||
injectReducer,
|
||||
injectSaga,
|
||||
useInjectReducer,
|
||||
useInjectSaga,
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
// FIXME:
|
||||
'strapi-plugin-documentation': require('../../../../plugins/documentation/admin/src').default,
|
||||
'strapi-plugin-users-permissions': require('../../../../plugins/users-permissions/admin/src')
|
||||
.default,
|
||||
'strapi-plugin-content-manager': require('../../../content-manager/admin/src').default,
|
||||
'strapi-plugin-content-type-builder': require('../../../content-type-builder/admin/src').default,
|
||||
'strapi-plugin-email': require('../../../email/admin/src').default,
|
||||
'strapi-plugin-upload': require('../../../upload/admin/src').default,
|
||||
'strapi-plugin-graphql': require('../../../../plugins/graphql/admin/src').default,
|
||||
'strapi-plugin-i18n': require('../../../../plugins/i18n/admin/src').default,
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
import conformsTo from 'lodash/conformsTo';
|
||||
import isFunction from 'lodash/isFunction';
|
||||
import isObject from 'lodash/isObject';
|
||||
import invariant from 'invariant';
|
||||
|
||||
/**
|
||||
* Validate the shape of redux store
|
||||
*/
|
||||
export default function checkStore(store) {
|
||||
const shape = {
|
||||
dispatch: isFunction,
|
||||
subscribe: isFunction,
|
||||
getState: isFunction,
|
||||
replaceReducer: isFunction,
|
||||
runSaga: isFunction,
|
||||
injectedReducers: isObject,
|
||||
injectedSagas: isObject,
|
||||
};
|
||||
|
||||
invariant(conformsTo(store, shape), '(app/utils...) injectors: Expected a valid redux store');
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export const RESTART_ON_REMOUNT = '@@saga-injector/restart-on-remount';
|
||||
export const DAEMON = '@@saga-injector/daemon';
|
||||
export const ONCE_TILL_UNMOUNT = '@@saga-injector/once-till-unmount';
|
@ -1,6 +0,0 @@
|
||||
import { createBrowserHistory } from 'history';
|
||||
import basename from './basename';
|
||||
|
||||
const history = createBrowserHistory({ basename });
|
||||
|
||||
export default history;
|
@ -1,56 +0,0 @@
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||||
import { ReactReduxContext } from 'react-redux';
|
||||
|
||||
import getInjectors from './reducerInjectors';
|
||||
|
||||
/**
|
||||
* Dynamically injects a reducer
|
||||
*
|
||||
* @param {string} key A key of the reducer
|
||||
* @param {function} reducer A reducer that will be injected
|
||||
*
|
||||
*/
|
||||
export default ({ key, reducer, pluginId }) => WrappedComponent => {
|
||||
class ReducerInjector extends React.Component {
|
||||
static WrappedComponent = WrappedComponent;
|
||||
static displayName = `withReducer(${WrappedComponent.displayName ||
|
||||
WrappedComponent.name ||
|
||||
'Component'})`;
|
||||
|
||||
static contextType = ReactReduxContext;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
const reducerName = pluginId ? `${pluginId}_${key}` : key;
|
||||
|
||||
console.warn(
|
||||
'Warning: strapi.injectReducer will be removed in the next major release. \n Please update your code.'
|
||||
);
|
||||
|
||||
getInjectors(context.store).injectReducer(reducerName, reducer);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <WrappedComponent {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
return hoistNonReactStatics(ReducerInjector, WrappedComponent);
|
||||
};
|
||||
|
||||
const useInjectReducer = ({ key, reducer, pluginId }) => {
|
||||
const context = React.useContext(ReactReduxContext);
|
||||
const reducerName = pluginId ? `${pluginId}_${key}` : key;
|
||||
|
||||
React.useEffect(() => {
|
||||
console.warn(
|
||||
'Warning: strapi.useInjectReducer will be removed in the next major release. \n Please update your code.'
|
||||
);
|
||||
|
||||
getInjectors(context.store).injectReducer(reducerName, reducer);
|
||||
}, []);
|
||||
};
|
||||
|
||||
export { useInjectReducer };
|
@ -1,76 +0,0 @@
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||||
import { ReactReduxContext } from 'react-redux';
|
||||
|
||||
import getInjectors from './sagaInjectors';
|
||||
|
||||
/**
|
||||
* Dynamically injects a saga, passes component's props as saga arguments
|
||||
*
|
||||
* @param {string} key A key of the saga
|
||||
* @param {function} saga A root saga that will be injected
|
||||
* @param {string} [mode] By default (constants.RESTART_ON_REMOUNT) the saga will be started on component mount and
|
||||
* cancelled with `task.cancel()` on component un-mount for improved performance. Another two options:
|
||||
* - constants.DAEMON—starts the saga on component mount and never cancels it or starts again,
|
||||
* - constants.ONCE_TILL_UNMOUNT—behaves like 'RESTART_ON_REMOUNT' but never runs it again.
|
||||
*
|
||||
*/
|
||||
export default ({ key, saga, mode, pluginId }) => WrappedComponent => {
|
||||
class InjectSaga extends React.Component {
|
||||
static WrappedComponent = WrappedComponent;
|
||||
static displayName = `withSaga(${WrappedComponent.displayName ||
|
||||
WrappedComponent.name ||
|
||||
'Component'})`;
|
||||
|
||||
static contextType = ReactReduxContext;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.injectors = getInjectors(context.store);
|
||||
const sagaName = pluginId ? `${pluginId}_${key}` : key;
|
||||
|
||||
console.warn(
|
||||
'Warning: strapi.injectSaga will be removed in the next major release. \n Please update your code.'
|
||||
);
|
||||
|
||||
this.injectors.injectSaga(sagaName, { saga, mode }, this.props);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { ejectSaga } = this.injectors;
|
||||
const sagaName = pluginId ? `${pluginId}_${key}` : key;
|
||||
|
||||
ejectSaga(sagaName);
|
||||
}
|
||||
|
||||
injectors = getInjectors(this.context.store);
|
||||
|
||||
render() {
|
||||
return <WrappedComponent {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
return hoistNonReactStatics(InjectSaga, WrappedComponent);
|
||||
};
|
||||
|
||||
const useInjectSaga = ({ key, saga, mode, pluginId }) => {
|
||||
const context = React.useContext(ReactReduxContext);
|
||||
const sagaName = pluginId ? `${pluginId}_${key}` : key;
|
||||
|
||||
React.useEffect(() => {
|
||||
const injectors = getInjectors(context.store);
|
||||
injectors.injectSaga(sagaName, { saga, mode });
|
||||
|
||||
console.warn(
|
||||
'Warning: strapi.useInjectSaga will be removed in the next major release. \n Please update your code.'
|
||||
);
|
||||
|
||||
return () => {
|
||||
injectors.ejectSaga(sagaName);
|
||||
};
|
||||
}, []);
|
||||
};
|
||||
|
||||
export { useInjectSaga };
|
@ -1,34 +0,0 @@
|
||||
/* eslint-disable */
|
||||
|
||||
import invariant from 'invariant';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import isFunction from 'lodash/isFunction';
|
||||
import isString from 'lodash/isString';
|
||||
|
||||
import createReducer from '../reducers';
|
||||
import checkStore from './checkStore';
|
||||
|
||||
export function injectReducerFactory(store, isValid) {
|
||||
return function injectReducer(key, reducer) {
|
||||
if (!isValid) checkStore(store);
|
||||
|
||||
invariant(
|
||||
isString(key) && !isEmpty(key) && isFunction(reducer),
|
||||
'(app/utils...) injectReducer: Expected `reducer` to be a reducer function'
|
||||
);
|
||||
|
||||
// Check `store.injectedReducers[key] === reducer` for hot reloading when a key is the same but a reducer is different
|
||||
if (Reflect.has(store.injectedReducers, key) && store.injectedReducers[key] === reducer) return;
|
||||
|
||||
store.injectedReducers[key] = reducer; // eslint-disable-line no-param-reassign
|
||||
store.replaceReducer(createReducer(store.injectedReducers));
|
||||
};
|
||||
}
|
||||
|
||||
export default function getInjectors(store) {
|
||||
checkStore(store);
|
||||
|
||||
return {
|
||||
injectReducer: injectReducerFactory(store, true),
|
||||
};
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
/* eslint-disable */
|
||||
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import isFunction from 'lodash/isFunction';
|
||||
import isString from 'lodash/isString';
|
||||
import invariant from 'invariant';
|
||||
import conformsTo from 'lodash/conformsTo';
|
||||
|
||||
import checkStore from './checkStore';
|
||||
import { DAEMON, ONCE_TILL_UNMOUNT, RESTART_ON_REMOUNT } from './constants';
|
||||
|
||||
const allowedModes = [RESTART_ON_REMOUNT, DAEMON, ONCE_TILL_UNMOUNT];
|
||||
|
||||
const checkKey = key =>
|
||||
invariant(
|
||||
isString(key) && !isEmpty(key),
|
||||
'(app/utils...) injectSaga: Expected `key` to be a non empty string'
|
||||
);
|
||||
|
||||
const checkDescriptor = descriptor => {
|
||||
const shape = {
|
||||
saga: isFunction,
|
||||
mode: mode => isString(mode) && allowedModes.includes(mode),
|
||||
};
|
||||
invariant(
|
||||
conformsTo(descriptor, shape),
|
||||
'(app/utils...) injectSaga: Expected a valid saga descriptor'
|
||||
);
|
||||
};
|
||||
|
||||
export function injectSagaFactory(store, isValid) {
|
||||
return function injectSaga(key, descriptor = {}, args) {
|
||||
if (!isValid) checkStore(store);
|
||||
|
||||
const newDescriptor = {
|
||||
...descriptor,
|
||||
mode: descriptor.mode || RESTART_ON_REMOUNT,
|
||||
};
|
||||
const { saga, mode } = newDescriptor;
|
||||
|
||||
checkKey(key);
|
||||
checkDescriptor(newDescriptor);
|
||||
|
||||
let hasSaga = Reflect.has(store.injectedSagas, key);
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const oldDescriptor = store.injectedSagas[key];
|
||||
// enable hot reloading of daemon and once-till-unmount sagas
|
||||
if (hasSaga && oldDescriptor.saga !== saga) {
|
||||
oldDescriptor.task.cancel();
|
||||
hasSaga = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasSaga || (hasSaga && mode !== DAEMON && mode !== ONCE_TILL_UNMOUNT)) {
|
||||
store.injectedSagas[key] = {
|
||||
...newDescriptor,
|
||||
task: store.runSaga(saga, args),
|
||||
}; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function ejectSagaFactory(store, isValid) {
|
||||
return function ejectSaga(key) {
|
||||
if (!isValid) checkStore(store);
|
||||
|
||||
checkKey(key);
|
||||
|
||||
if (Reflect.has(store.injectedSagas, key)) {
|
||||
const descriptor = store.injectedSagas[key];
|
||||
if (descriptor.mode !== DAEMON) {
|
||||
descriptor.task.cancel();
|
||||
// Clean up in production; in development we need `descriptor.saga` for hot reloading
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
// Need some value to be able to detect `ONCE_TILL_UNMOUNT` sagas in `injectSaga`
|
||||
store.injectedSagas[key] = 'done'; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function getInjectors(store) {
|
||||
checkStore(store);
|
||||
|
||||
return {
|
||||
injectSaga: injectSagaFactory(store, true),
|
||||
ejectSaga: ejectSagaFactory(store, true),
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user