mirror of
https://github.com/strapi/strapi.git
synced 2025-11-03 11:25:17 +00:00
Merge branch 'master' into fix/bookshelf-upload-query-findone
This commit is contained in:
commit
e5c8afe24e
17
.github/PULL_REQUEST_TEMPLATE.md
vendored
17
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,27 +1,28 @@
|
||||
<!-- ⚠️ Your PR title will appear in the changelogs please make it short detailed and understandable for all. -->
|
||||
|
||||
<!-- Write a short description of what your PR does and link the concerned issues of your update. -->
|
||||
<!-- ⚠️ Please link issue(s) you close / fix by using GitHub keywords https://help.github.com/articles/closing-issues-using-keywords/ !-->
|
||||
#### Description:
|
||||
|
||||
|
||||
|
||||
<!-- Uncomment the correct contribution type. !-->
|
||||
|
||||
**My PR is a:**
|
||||
#### My PR is a:
|
||||
- [ ] 💥 Breaking change
|
||||
- [ ] 🐛 Bug fix #issueNumber
|
||||
- [ ] 💅 Enhancement
|
||||
- [ ] 🚀 New feature
|
||||
|
||||
**Main update on the:**
|
||||
#### Main update on the:
|
||||
- [ ] Admin
|
||||
- [ ] Documentation
|
||||
- [ ] Framework
|
||||
- [ ] Plugin
|
||||
|
||||
<!-- Please note that all databases should be tested and confirmed to be working prior to the PR being merged. -->
|
||||
**Manual testing done on the following databases:**
|
||||
#### Manual testing done on the following databases:
|
||||
- [ ] Not applicable
|
||||
- [ ] MongoDB
|
||||
- [ ] MySQL
|
||||
- [ ] Postgres
|
||||
|
||||
<!-- Write a short description of what your PR does and link the concerned issues of your update. -->
|
||||
**Description:**
|
||||
|
||||
<!-- ⚠️ Please link issue(s) you close / fix by using GitHub keywords https://help.github.com/articles/closing-issues-using-keywords/ !-->
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -13,7 +13,7 @@ const history = createHistory({
|
||||
const store = configureStore({}, history);
|
||||
|
||||
if (window.Cypress) {
|
||||
window.__store__ = Object.assign(window.__store__ || {}, { strapiAdmin: store });
|
||||
window.__store__ = Object.assign(window.__store__ || {}, { store });
|
||||
}
|
||||
|
||||
export { basename, history, store };
|
||||
export { basename, history, store };
|
||||
|
||||
@ -10,6 +10,8 @@ import {
|
||||
updatePlugin,
|
||||
} from 'containers/App/actions';
|
||||
import { showNotification } from 'containers/NotificationProvider/actions';
|
||||
import injectReducer from './utils/injectReducer';
|
||||
import injectSaga from './utils/injectSaga';
|
||||
import { history, store } from './createStore';
|
||||
import { translationMessages, languages } from './i18n';
|
||||
import './public-path';
|
||||
@ -94,4 +96,7 @@ window.strapi = Object.assign(window.strapi || {}, {
|
||||
currentLanguage: window.localStorage.getItem('strapi-admin-language') || window.navigator.language || window.navigator.userLanguage || 'en',
|
||||
lockApp,
|
||||
unlockApp,
|
||||
});
|
||||
injectReducer,
|
||||
injectSaga,
|
||||
store,
|
||||
});
|
||||
|
||||
@ -11,7 +11,7 @@ import getInjectors from './reducerInjectors';
|
||||
* @param {function} reducer A reducer that will be injected
|
||||
*
|
||||
*/
|
||||
export default ({ key, reducer }) => (WrappedComponent) => {
|
||||
export default ({ key, reducer, pluginId }) => (WrappedComponent) => {
|
||||
class ReducerInjector extends React.Component {
|
||||
static WrappedComponent = WrappedComponent;
|
||||
static displayName = `withReducer(${(WrappedComponent.displayName || WrappedComponent.name || 'Component')})`;
|
||||
@ -21,8 +21,9 @@ export default ({ key, reducer }) => (WrappedComponent) => {
|
||||
|
||||
componentWillMount() {
|
||||
const { injectReducer } = this.injectors;
|
||||
const reducerName = pluginId ? `${pluginId}_${key}` : key;
|
||||
|
||||
injectReducer(key, reducer);
|
||||
injectReducer(reducerName, reducer);
|
||||
}
|
||||
|
||||
injectors = getInjectors(this.context.store);
|
||||
|
||||
@ -15,7 +15,7 @@ import getInjectors from './sagaInjectors';
|
||||
* - constants.ONCE_TILL_UNMOUNT—behaves like 'RESTART_ON_REMOUNT' but never runs it again.
|
||||
*
|
||||
*/
|
||||
export default ({ key, saga, mode }) => (WrappedComponent) => {
|
||||
export default ({ key, saga, mode, pluginId }) => (WrappedComponent) => {
|
||||
class InjectSaga extends React.Component {
|
||||
static WrappedComponent = WrappedComponent;
|
||||
static displayName = `withSaga(${(WrappedComponent.displayName || WrappedComponent.name || 'Component')})`;
|
||||
@ -25,14 +25,16 @@ export default ({ key, saga, mode }) => (WrappedComponent) => {
|
||||
|
||||
componentWillMount() {
|
||||
const { injectSaga } = this.injectors;
|
||||
const sagaName = pluginId ? `${pluginId}_${key}` : key;
|
||||
|
||||
injectSaga(key, { saga, mode }, this.props);
|
||||
injectSaga(sagaName, { saga, mode }, this.props);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { ejectSaga } = this.injectors;
|
||||
const sagaName = pluginId ? `${pluginId}_${key}` : key;
|
||||
|
||||
ejectSaga(key);
|
||||
ejectSaga(sagaName);
|
||||
}
|
||||
|
||||
injectors = getInjectors(this.context.store);
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
"presetup": "node ./scripts/preSetup.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"intl": "^1.2.5",
|
||||
"react-ga": "^2.4.1",
|
||||
"remove-markdown": "^0.2.2",
|
||||
"shelljs": "^0.7.8"
|
||||
|
||||
@ -13,7 +13,7 @@ import { Switch, Route } from 'react-router-dom';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
|
||||
// Utils
|
||||
import { pluginId } from 'app';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
// Containers
|
||||
import HomePage from 'containers/HomePage';
|
||||
@ -21,6 +21,7 @@ import NotFoundPage from 'containers/NotFoundPage';
|
||||
// When you're done studying the ExamplePage container, remove the following line and delete the ExamplePage container
|
||||
import ExamplePage from 'containers/ExamplePage';
|
||||
|
||||
import reducer from './reducer';
|
||||
|
||||
class App extends React.Component {
|
||||
// When you're done studying the ExamplePage container, remove the following lines and delete the ExamplePage container
|
||||
@ -44,7 +45,6 @@ class App extends React.Component {
|
||||
|
||||
App.contextTypes = {
|
||||
plugins: PropTypes.object,
|
||||
router: PropTypes.object.isRequired,
|
||||
updatePlugin: PropTypes.func,
|
||||
};
|
||||
|
||||
@ -63,7 +63,9 @@ const mapStateToProps = createStructuredSelector({});
|
||||
|
||||
// Wrap the component to inject dispatch and state into it
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
const withReducer = strapi.injectReducer({ key: 'global', reducer, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
withConnect,
|
||||
)(App);
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
// import { createSelector } from 'reselect';
|
||||
// import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the list state domain
|
||||
*/
|
||||
|
||||
// const selectGlobalDomain = () => state => state.get('global');
|
||||
// const selectGlobalDomain = () => state => state.get(`${pluginId}-global`);
|
||||
|
||||
export {};
|
||||
|
||||
@ -4,5 +4,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
export const LOAD_DATA = 'ExamplePage/LOAD_DATA';
|
||||
export const LOADED_DATA = 'ExamplePage/LOADED_DATA';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
export const LOAD_DATA = `${pluginId}/ExamplePage/LOAD_DATA`;
|
||||
export const LOADED_DATA = `${pluginId}/ExamplePage/LOADED_DATA`;
|
||||
|
||||
@ -10,9 +10,7 @@ import { connect } from 'react-redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
import Button from 'components/Button';
|
||||
|
||||
@ -90,8 +88,8 @@ const mapStateToProps = createStructuredSelector({
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withReducer = injectReducer({ key: 'examplePage', reducer });
|
||||
const withSaga = injectSaga({ key: 'examplePage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'examplePage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'examplePage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the examplePage state domain
|
||||
*/
|
||||
const selectExamplePageDomain = () => state => state.get('examplePage');
|
||||
const selectExamplePageDomain = () => state => state.get(`${pluginId}-examplePage`);
|
||||
|
||||
/**
|
||||
* Default selector used by HomePage
|
||||
|
||||
@ -4,4 +4,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
export const DEFAULT_ACTION = 'HomePage/DEFAULT_ACTION';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
export const DEFAULT_ACTION = `${pluginId}/HomePage/DEFAULT_ACTION`;
|
||||
|
||||
@ -10,9 +10,7 @@ import { connect } from 'react-redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
// Selectors
|
||||
import selectHomePage from './selectors';
|
||||
@ -55,8 +53,8 @@ const mapStateToProps = createStructuredSelector({
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withReducer = injectReducer({ key: 'homePage', reducer });
|
||||
const withSaga = injectSaga({ key: 'homePage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'homePage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'homePage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import pluginId from 'pluginId';
|
||||
/**
|
||||
* Direct selector to the homePage state domain
|
||||
*/
|
||||
const selectHomePageDomain = () => state => state.get('homePage');
|
||||
const selectHomePageDomain = () => state => state.get(`${pluginId}-homePage`);
|
||||
|
||||
/**
|
||||
* Default selector used by HomePage
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
const pluginPkg = require('../../package.json');
|
||||
const pluginId = pluginPkg.name.replace(
|
||||
/^strapi-plugin-/i,
|
||||
''
|
||||
);
|
||||
|
||||
module.exports = pluginId;
|
||||
@ -17,6 +17,7 @@ import { FormattedMessage } from 'react-intl';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
{{/if}}
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
// import pluginId from 'pluginId';
|
||||
|
||||
{{#if wantSaga}}
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
@ -72,7 +73,7 @@ const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
/* Remove this line if the container doesn't have a route and
|
||||
* check the documentation to see how to create the container's store
|
||||
*/
|
||||
const withReducer = injectReducer({ key: '{{ camelCase name }}', reducer });
|
||||
const withReducer = injectReducer({ key: '{{ camelCase name }}', reducer, pluginId });
|
||||
{{else}}
|
||||
const withConnect = connect(null, mapDispatchToProps);
|
||||
{{/if}}
|
||||
@ -81,7 +82,7 @@ const withConnect = connect(null, mapDispatchToProps);
|
||||
/* Remove the line below the container doesn't have a route and
|
||||
* check the documentation to see how to create the container's store
|
||||
*/
|
||||
const withSaga = injectSaga({ key: '{{ camelCase name }}', saga });
|
||||
const withSaga = injectSaga({ key: '{{ camelCase name }}', saga, pluginId });
|
||||
{{/if}}
|
||||
|
||||
export default compose(
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the {{ camelCase name }} state domain
|
||||
*/
|
||||
const select{{ properCase name }}Domain = () => (state) => state.get('{{ camelCase name }}');
|
||||
const select{{ properCase name }}Domain = () => (state) => state.get(`${pluginId}-{{ camelCase name }}`);
|
||||
|
||||
/**
|
||||
* Other specific selectors
|
||||
|
||||
@ -11,12 +11,9 @@ import './public-path.js'; // eslint-disable-line import/extensions
|
||||
|
||||
import React from 'react';
|
||||
import Loadable from 'react-loadable';
|
||||
import { Provider } from 'react-redux';
|
||||
import LoadingIndicatorPage from 'components/LoadingIndicatorPage';
|
||||
import configureStore from './store';
|
||||
import { translationMessages } from './i18n';
|
||||
|
||||
|
||||
const LoadableApp = Loadable({
|
||||
loader: () => import('containers/App'),
|
||||
loading: LoadingIndicatorPage,
|
||||
@ -61,23 +58,16 @@ const apiUrl = `${strapi.backendURL}/${pluginId}`;
|
||||
const router = strapi.router;
|
||||
|
||||
// Create redux store with Strapi admin history
|
||||
const store = configureStore({}, strapi.router, pluginName);
|
||||
// const store = configureStore({}, strapi.router, pluginName);
|
||||
const store = strapi.store;
|
||||
|
||||
// Define the plugin root component
|
||||
function Comp(props) {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<LoadableApp {...props} />
|
||||
</Provider>
|
||||
<LoadableApp {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
if (window.Cypress) {
|
||||
window.__store__ = Object.assign(window.__store__ || {}, {
|
||||
[pluginId]: store,
|
||||
});
|
||||
}
|
||||
|
||||
// Hot reloadable translation json files
|
||||
if (module.hot) {
|
||||
// modules.hot.accept does not accept dynamic dependencies,
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
/**
|
||||
* Combine all reducers in this file and export the combined reducers.
|
||||
* If we were to do this in store.js, reducers wouldn't be hot reloadable.
|
||||
*/
|
||||
|
||||
import { combineReducers } from 'redux-immutable';
|
||||
import { fromJS } from 'immutable';
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
|
||||
import globalReducer from 'containers/App/reducer'; // eslint-disable-line
|
||||
|
||||
/*
|
||||
* routeReducer
|
||||
*
|
||||
* The reducer merges route location changes into our immutable state.
|
||||
* The change is necessitated by moving to react-router-redux@4
|
||||
*
|
||||
*/
|
||||
|
||||
// Initial routing state
|
||||
const routeInitialState = fromJS({
|
||||
locationBeforeTransitions: null,
|
||||
});
|
||||
|
||||
/**
|
||||
* Merge route into the global application state
|
||||
*/
|
||||
function routeReducer(state = routeInitialState, action) {
|
||||
switch (action.type) {
|
||||
/* istanbul ignore next */
|
||||
case LOCATION_CHANGE:
|
||||
return state.merge({
|
||||
locationBeforeTransitions: action.payload,
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the main reducer with the asynchronously loaded ones
|
||||
*/
|
||||
export default function createReducer(asyncReducers) {
|
||||
return combineReducers({
|
||||
route: routeReducer,
|
||||
global: globalReducer,
|
||||
...asyncReducers,
|
||||
});
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
// These are the pages you can go to.
|
||||
// They are all wrapped in the App component, which should contain the navbar etc
|
||||
// See http://blog.mxstbr.com/2016/01/react-apps-with-pages for more information
|
||||
// about the code splitting business
|
||||
import { camelCase, map } from 'lodash';
|
||||
import { getAsyncInjectors } from 'utils/asyncInjectors';
|
||||
import routes from 'routes.json'; // eslint-disable-line
|
||||
|
||||
// Try to require a node module without throwing an error
|
||||
const tryRequire = (path) => {
|
||||
try {
|
||||
return require(`containers/${path}.js`); // eslint-disable-line global-require
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export default function createRoutes(store) {
|
||||
// Create reusable async injectors using getAsyncInjectors factory
|
||||
const { injectReducer, injectSagas } = getAsyncInjectors(store); // eslint-disable-line no-unused-vars
|
||||
|
||||
// Inject app sagas
|
||||
const appSagas = tryRequire('App/sagas');
|
||||
if (appSagas) injectSagas(appSagas.default);
|
||||
|
||||
return map(routes, (route, key) => ({
|
||||
path: key === '/' ? '' : key,
|
||||
name: route.name,
|
||||
getComponent(nextState, cb) {
|
||||
const reducer = tryRequire(`${route.container}/reducer`); // eslint-disable-line global-require
|
||||
const sagas = tryRequire(`${route.container}/sagas`); // eslint-disable-line global-require
|
||||
const component = tryRequire(`${route.container}/index`); // eslint-disable-line global-require
|
||||
|
||||
process.nextTick(() => {
|
||||
if (reducer) injectReducer(camelCase(route.container), reducer.default);
|
||||
if (sagas) injectSagas(sagas.default);
|
||||
cb(null, component.default);
|
||||
});
|
||||
},
|
||||
}));
|
||||
}
|
||||
@ -1,61 +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 = {}, history, name) {
|
||||
// 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,
|
||||
routerMiddleware(history),
|
||||
];
|
||||
|
||||
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: `Plugin - ${name}`,
|
||||
})
|
||||
: compose;
|
||||
/* eslint-enable */
|
||||
|
||||
const store = createStore(
|
||||
createReducer(),
|
||||
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;
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
import { conformsTo, isEmpty, isFunction, isObject, isString } from 'lodash';
|
||||
import invariant from 'invariant';
|
||||
import warning from 'warning';
|
||||
import createReducer from 'reducers';
|
||||
|
||||
/**
|
||||
* Validate the shape of redux store
|
||||
*/
|
||||
export function checkStore(store) {
|
||||
const shape = {
|
||||
dispatch: isFunction,
|
||||
subscribe: isFunction,
|
||||
getState: isFunction,
|
||||
replaceReducer: isFunction,
|
||||
runSaga: isFunction,
|
||||
asyncReducers: isObject,
|
||||
};
|
||||
invariant(
|
||||
conformsTo(store, shape),
|
||||
'(src/utils...) asyncInjectors: Expected a valid redux store'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject an asynchronously loaded reducer
|
||||
*/
|
||||
export function injectAsyncReducer(store, isValid) {
|
||||
return function injectReducer(name, asyncReducer) {
|
||||
if (!isValid) checkStore(store);
|
||||
|
||||
invariant(
|
||||
isString(name) && !isEmpty(name) && isFunction(asyncReducer),
|
||||
'(src/utils...) injectAsyncReducer: Expected `asyncReducer` to be a reducer function'
|
||||
);
|
||||
|
||||
store.asyncReducers[name] = asyncReducer; // eslint-disable-line no-param-reassign
|
||||
store.replaceReducer(createReducer(store.asyncReducers));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject an asynchronously loaded saga
|
||||
*/
|
||||
export function injectAsyncSagas(store, isValid) {
|
||||
return function injectSagas(sagas) {
|
||||
if (!isValid) checkStore(store);
|
||||
|
||||
invariant(
|
||||
Array.isArray(sagas),
|
||||
'(src/utils...) injectAsyncSagas: Expected `sagas` to be an array of generator functions'
|
||||
);
|
||||
|
||||
warning(
|
||||
!isEmpty(sagas),
|
||||
'(src/utils...) injectAsyncSagas: Received an empty `sagas` array'
|
||||
);
|
||||
|
||||
sagas.map(store.runSaga);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for creating injectors
|
||||
*/
|
||||
export function getAsyncInjectors(store) {
|
||||
checkStore(store);
|
||||
|
||||
return {
|
||||
injectReducer: injectAsyncReducer(store, true),
|
||||
injectSagas: injectAsyncSagas(store, true),
|
||||
};
|
||||
}
|
||||
@ -1,23 +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,36 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||||
|
||||
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 }) => (WrappedComponent) => {
|
||||
class ReducerInjector extends React.Component {
|
||||
static WrappedComponent = WrappedComponent;
|
||||
static displayName = `withReducer(${(WrappedComponent.displayName || WrappedComponent.name || 'Component')})`;
|
||||
static contextTypes = {
|
||||
store: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
const { injectReducer } = this.injectors;
|
||||
|
||||
injectReducer(key, reducer);
|
||||
}
|
||||
|
||||
injectors = getInjectors(this.context.store);
|
||||
|
||||
render() {
|
||||
return <WrappedComponent {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
return hoistNonReactStatics(ReducerInjector, WrappedComponent);
|
||||
};
|
||||
@ -1,46 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||||
|
||||
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 }) => (WrappedComponent) => {
|
||||
class InjectSaga extends React.Component {
|
||||
static WrappedComponent = WrappedComponent;
|
||||
static displayName = `withSaga(${(WrappedComponent.displayName || WrappedComponent.name || 'Component')})`;
|
||||
static contextTypes = {
|
||||
store: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
const { injectSaga } = this.injectors;
|
||||
|
||||
injectSaga(key, { saga, mode }, this.props);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { ejectSaga } = this.injectors;
|
||||
|
||||
ejectSaga(key);
|
||||
}
|
||||
|
||||
injectors = getInjectors(this.context.store);
|
||||
|
||||
render() {
|
||||
return <WrappedComponent {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
return hoistNonReactStatics(InjectSaga, WrappedComponent);
|
||||
};
|
||||
@ -1,30 +0,0 @@
|
||||
import invariant from 'invariant';
|
||||
import { isEmpty, isFunction, isString } from 'lodash';
|
||||
|
||||
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,86 +0,0 @@
|
||||
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),
|
||||
};
|
||||
}
|
||||
@ -27,9 +27,6 @@
|
||||
"lint:admin"
|
||||
],
|
||||
"devDependencies": {
|
||||
"plop": "^2.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"add-asset-html-webpack-plugin": "^2.1.2",
|
||||
"babel-cli": "6.26.0",
|
||||
"babel-core": "6.26.0",
|
||||
@ -42,35 +39,25 @@
|
||||
"babel-plugin-transform-react-constant-elements": "6.23.0",
|
||||
"babel-plugin-transform-react-inline-elements": "6.22.0",
|
||||
"babel-plugin-transform-react-remove-prop-types": "0.4.18",
|
||||
"babel-polyfill": "6.26.0",
|
||||
"babel-preset-env": "1.6.1",
|
||||
"babel-preset-react": "6.24.1",
|
||||
"babel-preset-react-hmre": "1.1.1",
|
||||
"babel-preset-stage-0": "6.24.1",
|
||||
"bootstrap": "^4.0.0-alpha.6",
|
||||
"chalk": "^2.1.0",
|
||||
"classnames": "^2.2.5",
|
||||
"copy-webpack-plugin": "^4.3.1",
|
||||
"cross-env": "^5.0.5",
|
||||
"css-loader": "^0.28.5",
|
||||
"cross-env": "^5.0.5",
|
||||
"exports-loader": "^0.6.4",
|
||||
"express": "^4.15.4",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"express": "^4.15.4",
|
||||
"file-loader": "^0.11.2",
|
||||
"history": "^4.6.3",
|
||||
"html-loader": "^0.5.1",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"image-webpack-loader": "^4.3.1",
|
||||
"immutable": "^3.8.2",
|
||||
"imports-loader": "^0.7.1",
|
||||
"intl": "^1.2.5",
|
||||
"invariant": "2.2.1",
|
||||
"json-loader": "^0.5.7",
|
||||
"lodash": "^4.17.5",
|
||||
"lodash-webpack-plugin": "^0.11.4",
|
||||
"moment": "^2.16.0",
|
||||
"node-sass": "^4.5.3",
|
||||
"null-loader": "^0.1.1",
|
||||
"plop": "^2.2.0",
|
||||
"postcss-cssnext": "^2.11.0",
|
||||
"postcss-focus": "^2.0.0",
|
||||
"postcss-loader": "^2.0.6",
|
||||
@ -78,6 +65,27 @@
|
||||
"postcss-smart-import": "^0.7.5",
|
||||
"precss": "^2.0.0",
|
||||
"prettier": "^1.5.3",
|
||||
"rimraf": "^2.6.1",
|
||||
"sass-loader": "^6.0.6",
|
||||
"shelljs": "^0.7.8",
|
||||
"style-loader": "^0.18.2",
|
||||
"url-loader": "^1.1.1",
|
||||
"webpack": "^3.5.5",
|
||||
"webpack-bundle-analyzer": "^2.9.0",
|
||||
"webpack-dev-middleware": "^1.12.0",
|
||||
"webpack-hot-middleware": "^2.18.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-polyfill": "6.26.0",
|
||||
"bootstrap": "^4.0.0-alpha.6",
|
||||
"classnames": "^2.2.5",
|
||||
"history": "^4.6.3",
|
||||
"immutable": "^3.8.2",
|
||||
"imports-loader": "^0.7.1",
|
||||
"invariant": "2.2.1",
|
||||
"json-loader": "^0.5.7",
|
||||
"lodash": "^4.17.5",
|
||||
"moment": "^2.16.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "^16.5.2",
|
||||
"react-copy-to-clipboard": "^5.0.1",
|
||||
@ -97,16 +105,7 @@
|
||||
"redux-immutable": "^4.0.0",
|
||||
"redux-saga": "^0.16.0",
|
||||
"reselect": "^3.0.1",
|
||||
"rimraf": "^2.6.1",
|
||||
"sass-loader": "^6.0.6",
|
||||
"shelljs": "^0.7.8",
|
||||
"style-loader": "^0.18.2",
|
||||
"styled-components": "^3.2.6",
|
||||
"url-loader": "^1.1.1",
|
||||
"webpack": "^3.5.5",
|
||||
"webpack-bundle-analyzer": "^2.9.0",
|
||||
"webpack-dev-middleware": "^1.12.0",
|
||||
"webpack-hot-middleware": "^2.18.2",
|
||||
"whatwg-fetch": "^2.0.3"
|
||||
}
|
||||
}
|
||||
@ -471,7 +471,7 @@ module.exports = function(strapi) {
|
||||
const type = getType(attribute, attr);
|
||||
|
||||
if (type) {
|
||||
acc.push(`${quote}${attr}${quote} ${type}`);
|
||||
acc.push(`${quote}${attr}${quote} ${type} ${attribute.required ? 'NOT' : ''} NULL `);
|
||||
}
|
||||
|
||||
return acc;
|
||||
@ -544,14 +544,12 @@ module.exports = function(strapi) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (!tableExist) {
|
||||
const createTable = async (table) => {
|
||||
const defaultAttributeDifinitions = {
|
||||
mysql: [`id INT AUTO_INCREMENT NOT NULL PRIMARY KEY`],
|
||||
pg: [`id SERIAL NOT NULL PRIMARY KEY`],
|
||||
sqlite3: ['id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL']
|
||||
};
|
||||
|
||||
let idAttributeBuilder = defaultAttributeDifinitions[definition.client];
|
||||
if (definition.primaryKeyType === 'uuid' && definition.client === 'pg') {
|
||||
idAttributeBuilder = ['id uuid NOT NULL DEFAULT uuid_generate_v4() NOT NULL PRIMARY KEY'];
|
||||
@ -566,13 +564,16 @@ module.exports = function(strapi) {
|
||||
${columns}
|
||||
)
|
||||
`);
|
||||
};
|
||||
|
||||
if (!tableExist) {
|
||||
await createTable(table);
|
||||
|
||||
// Generate indexes.
|
||||
await generateIndexes(table, attributes);
|
||||
|
||||
await storeTable(table, attributes);
|
||||
} else {
|
||||
|
||||
const columns = Object.keys(attributes);
|
||||
|
||||
// Fetch existing column
|
||||
@ -594,6 +595,14 @@ module.exports = function(strapi) {
|
||||
// Generate indexes for new attributes.
|
||||
await generateIndexes(table, columnsToAdd);
|
||||
|
||||
let previousAttributes;
|
||||
try {
|
||||
previousAttributes = JSON.parse((await StrapiConfigs.forge({key: `db_model_${table}`}).fetch()).toJSON().value);
|
||||
} catch (err) {
|
||||
await storeTable(table, attributes);
|
||||
previousAttributes = JSON.parse((await StrapiConfigs.forge({key: `db_model_${table}`}).fetch()).toJSON().value);
|
||||
}
|
||||
|
||||
// Generate and execute query to add missing column
|
||||
if (Object.keys(columnsToAdd).length > 0) {
|
||||
const columns = generateColumns(columnsToAdd, []);
|
||||
@ -605,31 +614,28 @@ module.exports = function(strapi) {
|
||||
await Promise.all(queries.map(query => ORM.knex.raw(query)));
|
||||
}
|
||||
|
||||
let previousAttributes;
|
||||
try {
|
||||
previousAttributes = JSON.parse((await StrapiConfigs.forge({key: `db_model_${table}`}).fetch()).toJSON().value);
|
||||
} catch (err) {
|
||||
await storeTable(table, attributes);
|
||||
previousAttributes = JSON.parse((await StrapiConfigs.forge({key: `db_model_${table}`}).fetch()).toJSON().value);
|
||||
}
|
||||
let sqlite3Change = false;
|
||||
|
||||
// Execute query to update column type
|
||||
await Promise.all(columns.map(attribute =>
|
||||
new Promise(async (resolve) => {
|
||||
if (JSON.stringify(previousAttributes[attribute]) === JSON.stringify(attributes[attribute])) {
|
||||
return resolve();
|
||||
} else {
|
||||
sqlite3Change = true;
|
||||
}
|
||||
|
||||
const type = getType(attributes[attribute], attribute);
|
||||
|
||||
if (type) {
|
||||
const changeType = definition.client === 'pg' || definition.client === 'sqlite3'
|
||||
if (type && definition.client !== 'sqlite3') {
|
||||
const changeType = definition.client === 'pg'
|
||||
? `ALTER COLUMN ${quote}${attribute}${quote} TYPE ${type} USING ${quote}${attribute}${quote}::${type}`
|
||||
: `CHANGE ${quote}${attribute}${quote} ${quote}${attribute}${quote} ${type} `;
|
||||
|
||||
const changeRequired = definition.client === 'pg' || definition.client === 'sqlite3'
|
||||
const changeRequired = definition.client === 'pg'
|
||||
? `ALTER COLUMN ${quote}${attribute}${quote} ${attributes[attribute].required ? 'SET' : 'DROP'} NOT NULL`
|
||||
: `CHANGE ${quote}${attribute}${quote} ${quote}${attribute}${quote} ${type} ${attributes[attribute].required ? 'NOT' : ''} NULL`;
|
||||
|
||||
await ORM.knex.raw(`ALTER TABLE ${quote}${table}${quote} ${changeType}`);
|
||||
await ORM.knex.raw(`ALTER TABLE ${quote}${table}${quote} ${changeRequired}`);
|
||||
}
|
||||
@ -638,6 +644,28 @@ module.exports = function(strapi) {
|
||||
})
|
||||
));
|
||||
|
||||
if (sqlite3Change) {
|
||||
await createTable(`tmp_${table}`);
|
||||
|
||||
try {
|
||||
await ORM.knex.raw(`INSERT INTO ${quote}tmp_${table}${quote}(${Object.keys(attributes).join(' ,')}) SELECT ${Object.keys(attributes).join(' ,')} FROM ${quote}${table}${quote}`);
|
||||
} catch (err) {
|
||||
console.log('Warning!');
|
||||
console.log('We can\'t migrate your data due to the following error.');
|
||||
console.log();
|
||||
console.log(err);
|
||||
console.log();
|
||||
console.log(`We created a new table "tmp_${table}" with your latest changes.`);
|
||||
console.log(`We suggest you manually migrate your data from "${table}" to "tmp_${table}" and then to DROP and RENAME the tables.`);
|
||||
|
||||
return false;
|
||||
}
|
||||
await ORM.knex.raw(`DROP TABLE ${quote}${table}${quote}`);
|
||||
await ORM.knex.raw(`ALTER TABLE ${quote}tmp_${table}${quote} RENAME TO ${quote}${table}${quote}`);
|
||||
|
||||
await generateIndexes(table, attributes);
|
||||
}
|
||||
|
||||
await storeTable(table, attributes);
|
||||
}
|
||||
};
|
||||
|
||||
@ -46,6 +46,7 @@ class InputJSON extends React.Component {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: 'application/json',
|
||||
readOnly: this.props.disabled,
|
||||
smartIndent: true,
|
||||
styleSelectedText: true,
|
||||
tabSize: 2,
|
||||
@ -186,12 +187,14 @@ class InputJSON extends React.Component {
|
||||
}
|
||||
|
||||
InputJSON.defaultProps = {
|
||||
disabled: false,
|
||||
onBlur: () => {},
|
||||
onChange: () => {},
|
||||
value: null,
|
||||
};
|
||||
|
||||
InputJSON.propTypes = {
|
||||
disabled: PropTypes.bool,
|
||||
name: PropTypes.string.isRequired,
|
||||
onBlur: PropTypes.func,
|
||||
onChange: PropTypes.func,
|
||||
|
||||
@ -12,8 +12,8 @@ import { createStructuredSelector } from 'reselect';
|
||||
import PropTypes from 'prop-types';
|
||||
import { isEmpty, get } from 'lodash';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import getQueryParameters from 'utils/getQueryParameters';
|
||||
|
||||
import EditPage from 'containers/EditPage';
|
||||
@ -28,6 +28,7 @@ import {
|
||||
} from './actions';
|
||||
import { makeSelectLoading, makeSelectModelEntries, makeSelectSchema } from './selectors';
|
||||
|
||||
import reducer from './reducer';
|
||||
import saga from './sagas';
|
||||
|
||||
class App extends React.Component {
|
||||
@ -93,9 +94,11 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
const withSaga = injectSaga({ key: 'global', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'global', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'global', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
withSaga,
|
||||
withConnect,
|
||||
)(App);
|
||||
|
||||
@ -49,7 +49,6 @@ export function* defaultSaga() {
|
||||
yield take(LOCATION_CHANGE);
|
||||
|
||||
yield cancel(loadModelsWatcher);
|
||||
yield cancel(loadedModelsWatcher);
|
||||
yield cancel(loadEntriesWatcher);
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import pluginId from 'pluginId';
|
||||
/**
|
||||
* Direct selector to the list state domain
|
||||
*/
|
||||
const selectGlobalDomain = () => state => state.get('global');
|
||||
const selectGlobalDomain = () => state => state.get(`${pluginId}_global`);
|
||||
|
||||
/**
|
||||
* Other specific selectors
|
||||
|
||||
@ -23,6 +23,7 @@ import {
|
||||
import HTML5Backend from 'react-dnd-html5-backend';
|
||||
import { DragDropContext } from 'react-dnd';
|
||||
import cn from 'classnames';
|
||||
import pluginId from 'pluginId';
|
||||
// You can find these components in either
|
||||
// ./node_modules/strapi-helper-plugin/lib/src
|
||||
// or strapi/packages/strapi-helper-plugin/lib/src
|
||||
@ -37,8 +38,6 @@ import Edit from 'components/Edit';
|
||||
import EditRelations from 'components/EditRelations';
|
||||
// App selectors
|
||||
import { makeSelectSchema } from 'containers/App/selectors';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import getQueryParameters from 'utils/getQueryParameters';
|
||||
import { bindLayout } from 'utils/bindLayout';
|
||||
import inputValidations from 'utils/inputsValidations';
|
||||
@ -601,8 +600,8 @@ const withConnect = connect(
|
||||
mapDispatchToProps,
|
||||
);
|
||||
|
||||
const withReducer = injectReducer({ key: 'editPage', reducer });
|
||||
const withSaga = injectSaga({ key: 'editPage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'editPage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'editPage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
// import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import { findIndex, get, isArray, isEmpty, includes, isNumber, isString, map } from 'lodash';
|
||||
import {
|
||||
all,
|
||||
call,
|
||||
cancel,
|
||||
// cancel,
|
||||
fork,
|
||||
put,
|
||||
select,
|
||||
take,
|
||||
// take,
|
||||
takeLatest,
|
||||
} from 'redux-saga/effects';
|
||||
import { makeSelectSchema } from 'containers/App/selectors';
|
||||
@ -185,13 +185,15 @@ export function* submit() {
|
||||
}
|
||||
|
||||
function* defaultSaga() {
|
||||
const loadDataWatcher = yield fork(takeLatest, GET_DATA, dataGet);
|
||||
yield fork(takeLatest, GET_DATA, dataGet);
|
||||
// TODO fix router (Other PR)
|
||||
// const loadDataWatcher = yield fork(takeLatest, GET_DATA, dataGet);
|
||||
yield fork(takeLatest, DELETE_DATA, deleteData);
|
||||
yield fork(takeLatest, SUBMIT, submit);
|
||||
|
||||
yield take(LOCATION_CHANGE);
|
||||
// yield take(LOCATION_CHANGE);
|
||||
|
||||
yield cancel(loadDataWatcher);
|
||||
// yield cancel(loadDataWatcher);
|
||||
}
|
||||
|
||||
export default defaultSaga;
|
||||
|
||||
@ -5,11 +5,12 @@
|
||||
*/
|
||||
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the listPage state domain
|
||||
*/
|
||||
const selectEditPageDomain = () => state => state.get('editPage');
|
||||
const selectEditPageDomain = () => state => state.get(`${pluginId}_editPage`);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Home
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import PluginHeader from 'components/PluginHeader';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
export class Home extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div className={`container-fluid ${styles.containerFluid}`}>
|
||||
<PluginHeader
|
||||
title={{
|
||||
id: 'content-manager.containers.Home.pluginHeaderTitle',
|
||||
}}
|
||||
description={{
|
||||
id: 'content-manager.containers.Home.pluginHeaderDescription',
|
||||
}}
|
||||
actions={[]}
|
||||
/>
|
||||
<p>
|
||||
<FormattedMessage id="content-manager.containers.Home.introduction" />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Home.propTypes = {};
|
||||
|
||||
export function mapDispatchToProps() {
|
||||
return {};
|
||||
}
|
||||
|
||||
const mapStateToProps = createStructuredSelector({});
|
||||
|
||||
// Wrap the component to inject dispatch and state into it
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Home);
|
||||
@ -1,10 +0,0 @@
|
||||
{
|
||||
"pluginHeaderDescription": {
|
||||
"id": "contentManager.containers.Home.pluginHeaderDescription",
|
||||
"defaultMessage": "A powerful UI to easily manage your data."
|
||||
},
|
||||
"introduction": {
|
||||
"id": "contentManager.containers.Home.introduction",
|
||||
"defaultMessage": "To edit your content's entries go to the specific link in the left menu."
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
/**
|
||||
* styles.scss
|
||||
*
|
||||
* Home container styles
|
||||
*/
|
||||
|
||||
.containerFluid { /* stylelint-disable */
|
||||
padding: 18px 30px;
|
||||
|
||||
p {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding-bottom: 14px;
|
||||
line-height: 18px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,7 @@ import { capitalize, findIndex, get, isUndefined, toInteger, upperFirst } from '
|
||||
import { ButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import cn from 'classnames';
|
||||
import pluginId from 'pluginId';
|
||||
// App selectors
|
||||
import { makeSelectSchema } from 'containers/App/selectors';
|
||||
// You can find these components in either
|
||||
@ -30,8 +31,6 @@ import Search from 'components/Search';
|
||||
import Table from 'components/Table';
|
||||
// Utils located in `strapi/packages/strapi-helper-plugin/lib/src/utils`;
|
||||
import getQueryParameters from 'utils/getQueryParameters';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import storeData from 'utils/storeData';
|
||||
import Div from './Div';
|
||||
import {
|
||||
@ -681,7 +680,7 @@ const mapStateToProps = createStructuredSelector({
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withReducer = injectReducer({ key: 'listPage', reducer });
|
||||
const withSaga = injectSaga({ key: 'listPage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'listPage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'listPage', saga, pluginId });
|
||||
|
||||
export default compose(withReducer, withSaga, withConnect)(ListPage);
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
// Dependencies.
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
// import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import {
|
||||
all,
|
||||
call,
|
||||
cancel,
|
||||
// cancel,
|
||||
fork,
|
||||
put,
|
||||
select,
|
||||
take,
|
||||
// take,
|
||||
takeLatest,
|
||||
} from 'redux-saga/effects';
|
||||
// Utils.
|
||||
@ -114,13 +114,16 @@ export function* dataDeleteAll({ entriesToDelete, model, source }) {
|
||||
|
||||
// All sagas to be loaded
|
||||
function* defaultSaga() {
|
||||
const loadDataWatcher = yield fork(takeLatest, GET_DATA, dataGet);
|
||||
yield fork(takeLatest, GET_DATA, dataGet);
|
||||
|
||||
// TODO fix router (Other PR)
|
||||
// const loadDataWatcher = yield fork(takeLatest, GET_DATA, dataGet);
|
||||
yield fork(takeLatest, DELETE_DATA, dataDelete);
|
||||
yield fork(takeLatest, DELETE_SEVERAL_DATA, dataDeleteAll);
|
||||
|
||||
yield take(LOCATION_CHANGE);
|
||||
// yield take(LOCATION_CHANGE);
|
||||
|
||||
yield cancel(loadDataWatcher);
|
||||
// yield cancel(loadDataWatcher);
|
||||
}
|
||||
|
||||
export default defaultSaga;
|
||||
|
||||
@ -5,11 +5,12 @@
|
||||
*/
|
||||
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the listPage state domain
|
||||
*/
|
||||
const selectListPageDomain = () => state => state.get('listPage');
|
||||
const selectListPageDomain = () => state => state.get(`${pluginId}_listPage`);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -14,6 +14,7 @@ import { DragDropContext } from 'react-dnd';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { ButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
|
||||
import PropTypes from 'prop-types';
|
||||
import pluginId from 'pluginId';
|
||||
import {
|
||||
beginMove,
|
||||
endMove,
|
||||
@ -54,9 +55,6 @@ import PluginHeader from 'components/PluginHeader';
|
||||
import PopUpWarning from 'components/PopUpWarning';
|
||||
import VariableDraggableAttr from 'components/VariableDraggableAttr';
|
||||
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
|
||||
import { onClickEditField, onClickEditListItem, onClickEditRelation } from './actions';
|
||||
import reducer from './reducer';
|
||||
import saga from './saga';
|
||||
@ -1161,8 +1159,8 @@ const withConnect = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
);
|
||||
const withReducer = injectReducer({ key: 'settingPage', reducer });
|
||||
const withSaga = injectSaga({ key: 'settingPage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'settingPage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'settingPage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -4,11 +4,12 @@
|
||||
*/
|
||||
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the settingPage state domain
|
||||
*/
|
||||
const selectSettingPageDomain = () => state => state.get('settingPage');
|
||||
const selectSettingPageDomain = () => state => state.get(`${pluginId}_settingPage`);
|
||||
|
||||
|
||||
/**
|
||||
@ -21,4 +22,4 @@ const makeSelectSettingPage = () => createSelector(
|
||||
);
|
||||
|
||||
|
||||
export default makeSelectSettingPage;
|
||||
export default makeSelectSettingPage;
|
||||
|
||||
@ -10,6 +10,7 @@ import { createStructuredSelector } from 'reselect';
|
||||
import cn from 'classnames';
|
||||
import { get, sortBy } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import pluginId from 'pluginId';
|
||||
import { onChange, onSubmit, onReset } from 'containers/App/actions';
|
||||
import { makeSelectModifiedSchema, makeSelectSubmitSuccess } from 'containers/App/selectors';
|
||||
import Input from 'components/InputsIndex';
|
||||
@ -17,8 +18,6 @@ import PluginHeader from 'components/PluginHeader';
|
||||
import PopUpWarning from 'components/PopUpWarning';
|
||||
import Block from 'components/Block';
|
||||
import SettingsRow from 'components/SettingsRow';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import reducer from './reducer';
|
||||
import saga from './saga';
|
||||
import styles from './styles.scss';
|
||||
@ -211,8 +210,8 @@ const mapStateToProps = createStructuredSelector({
|
||||
submitSuccess: makeSelectSubmitSuccess(),
|
||||
});
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
const withReducer = injectReducer({ key: 'settingsPage', reducer });
|
||||
const withSaga = injectSaga({ key: 'settingsPage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'settingsPage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'settingsPage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -4,11 +4,12 @@
|
||||
*/
|
||||
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the settingsPage state domain
|
||||
*/
|
||||
const selectSettingsPageDomain = () => state => state.get('settingsPage');
|
||||
const selectSettingsPageDomain = () => state => state.get(`${pluginId}_settingsPage`);
|
||||
|
||||
|
||||
/**
|
||||
@ -21,4 +22,4 @@ const makeSelectSettingsPage = () => createSelector(
|
||||
);
|
||||
|
||||
|
||||
export default makeSelectSettingsPage;
|
||||
export default makeSelectSettingsPage;
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
const pluginPkg = require('../../package.json');
|
||||
const pluginId = pluginPkg.name.replace(
|
||||
/^strapi-plugin-/i,
|
||||
''
|
||||
);
|
||||
|
||||
module.exports = pluginId;
|
||||
@ -1,11 +0,0 @@
|
||||
{
|
||||
"/": {
|
||||
"container": "Home"
|
||||
},
|
||||
"/:slug": {
|
||||
"container": "List"
|
||||
},
|
||||
"/:slug/:id": {
|
||||
"container": "Edit"
|
||||
}
|
||||
}
|
||||
@ -67,7 +67,7 @@ describe('Testing Content Manager createPages', function() {
|
||||
.wait(1000)
|
||||
.window()
|
||||
.its('__store__')
|
||||
.its('content-manager')
|
||||
.its('store');
|
||||
});
|
||||
});
|
||||
|
||||
@ -196,11 +196,11 @@ describe('Testing Content Manager createPages', function() {
|
||||
.wait(2000)
|
||||
.window()
|
||||
.its('__store__')
|
||||
.its('content-manager')
|
||||
.its('store')
|
||||
.then(pluginStore => {
|
||||
const records = pluginStore
|
||||
.getState()
|
||||
.getIn(['listPage', 'records', 'tag'])
|
||||
.getIn(['content-manager_listPage', 'records', 'tag'])
|
||||
.toJS();
|
||||
|
||||
expect(records).to.have.length(0);
|
||||
@ -411,7 +411,7 @@ describe('Testing Content Manager createPages', function() {
|
||||
.then(pluginStore => {
|
||||
const category = pluginStore
|
||||
.getState()
|
||||
.getIn(['editPage', 'record', 'category'])
|
||||
.getIn(['content-manager_editPage', 'record', 'category'])
|
||||
|
||||
expect(category).to.equal(null);
|
||||
});
|
||||
@ -420,7 +420,7 @@ describe('Testing Content Manager createPages', function() {
|
||||
.then(pluginStore => {
|
||||
const category = pluginStore
|
||||
.getState()
|
||||
.getIn(['editPage', 'record', 'category', 'name'])
|
||||
.getIn(['content-manager_editPage', 'record', 'category', 'name'])
|
||||
|
||||
expect(category).to.equal('french food');
|
||||
})
|
||||
@ -428,7 +428,7 @@ describe('Testing Content Manager createPages', function() {
|
||||
.then(pluginStore => {
|
||||
const category = pluginStore
|
||||
.getState()
|
||||
.getIn(['editPage', 'record', 'category', 'name'])
|
||||
.getIn(['content-manager_editPage', 'record', 'category', 'name'])
|
||||
|
||||
expect(category).to.equal('french food');
|
||||
});
|
||||
@ -440,4 +440,4 @@ describe('Testing Content Manager createPages', function() {
|
||||
.deleteAllModelData('product', jwt);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -12,7 +12,7 @@ import { bindActionCreators, compose } from 'redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { Switch, Route, withRouter } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { pluginId } from 'app';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
import HomePage from 'containers/HomePage';
|
||||
import ModelPage from 'containers/ModelPage';
|
||||
@ -24,12 +24,13 @@ import formReducer from 'containers/Form/reducer';
|
||||
import { makeSelectShouldRefetchContentType } from 'containers/Form/selectors';
|
||||
|
||||
// Utils
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
// import injectSaga from 'utils/injectSaga';
|
||||
// import injectReducer from 'utils/injectReducer';
|
||||
import { storeData } from '../../utils/storeData';
|
||||
|
||||
import styles from './styles.scss';
|
||||
import { modelsFetch } from './actions';
|
||||
import reducer from './reducer';
|
||||
import saga from './sagas';
|
||||
|
||||
/* eslint-disable consistent-return */
|
||||
@ -92,10 +93,13 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
const withSaga = injectSaga({ key: 'global', saga });
|
||||
const withFormReducer = injectReducer({ key: 'form', reducer: formReducer });
|
||||
const withFormSaga = injectSaga({ key: 'form', saga: formSaga });
|
||||
const withReducer = strapi.injectReducer({ key: 'global', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'global', saga, pluginId });
|
||||
const withFormReducer = strapi.injectReducer({ key: 'form', reducer: formReducer, pluginId });
|
||||
const withFormSaga = strapi.injectSaga({ key: 'form', saga: formSaga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
withFormReducer,
|
||||
withFormSaga,
|
||||
withSaga,
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the list state domain
|
||||
*/
|
||||
|
||||
const selectGlobalDomain = () => state => state.get('global');
|
||||
const selectGlobalDomain = () => state => state.get(`${pluginId}_global`);
|
||||
|
||||
const makeSelectLoading = () => createSelector(
|
||||
selectGlobalDomain(),
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the form state domain
|
||||
*/
|
||||
const selectFormDomain = () => state => state.get('form');
|
||||
const selectFormDomain = () => state => state.get(`${pluginId}_form`);
|
||||
|
||||
/**
|
||||
* Other specific selectors
|
||||
|
||||
@ -12,6 +12,7 @@ import { size } from 'lodash';
|
||||
import Helmet from 'react-helmet';
|
||||
import PropTypes from 'prop-types';
|
||||
import { router } from 'app';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
import { makeSelectLoading, makeSelectMenu, makeSelectModels } from 'containers/App/selectors';
|
||||
import { deleteContentType } from 'containers/App/actions';
|
||||
@ -23,8 +24,7 @@ import ContentHeader from 'components/ContentHeader';
|
||||
import EmptyContentTypeView from 'components/EmptyContentTypeView';
|
||||
import TableList from 'components/TableList';
|
||||
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
// Utils
|
||||
import { storeData } from '../../utils/storeData';
|
||||
|
||||
import selectHomePage from './selectors';
|
||||
@ -140,8 +140,8 @@ function mapDispatchToProps(dispatch) {
|
||||
}
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
const withReducer = injectReducer({ key: 'homePage', reducer });
|
||||
const withSaga = injectSaga({ key: 'homePage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'homePage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'homePage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the homePage state domain
|
||||
*/
|
||||
const selectHomePageDomain = () => state => state.get('homePage');
|
||||
const selectHomePageDomain = () => state => state.get(`${pluginId}_homePage`);
|
||||
|
||||
/**
|
||||
* Other specific selectors
|
||||
|
||||
@ -13,6 +13,7 @@ import { FormattedMessage } from 'react-intl';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { router } from 'app';
|
||||
import pluginId from 'pluginId';
|
||||
// Global selectors
|
||||
import { makeSelectMenu } from 'containers/App/selectors';
|
||||
import { makeSelectContentTypeUpdated } from 'containers/Form/selectors';
|
||||
@ -23,8 +24,6 @@ import Form from 'containers/Form';
|
||||
import List from 'components/List';
|
||||
import PluginLeftMenu from 'components/PluginLeftMenu';
|
||||
import forms from 'containers/Form/forms.json';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import { storeData } from '../../utils/storeData';
|
||||
import {
|
||||
cancelChanges,
|
||||
@ -355,8 +354,8 @@ function mapDispatchToProps(dispatch) {
|
||||
}
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
const withSaga = injectSaga({ key: 'modelPage', saga });
|
||||
const withReducer = injectReducer({ key: 'modelPage', reducer });
|
||||
const withSaga = strapi.injectSaga({ key: 'modelPage', saga, pluginId });
|
||||
const withReducer = strapi.injectReducer({ key: 'modelPage', reducer, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
// import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import {
|
||||
capitalize,
|
||||
cloneDeep,
|
||||
@ -13,7 +13,15 @@ import {
|
||||
unset,
|
||||
} from 'lodash';
|
||||
import pluralize from 'pluralize';
|
||||
import { takeLatest, call, take, put, fork, cancel, select } from 'redux-saga/effects';
|
||||
import {
|
||||
takeLatest,
|
||||
call,
|
||||
// take,
|
||||
put,
|
||||
fork,
|
||||
// cancel,
|
||||
select,
|
||||
} from 'redux-saga/effects';
|
||||
|
||||
import request from 'utils/request';
|
||||
|
||||
@ -139,13 +147,18 @@ export function* submitChanges(action) {
|
||||
}
|
||||
|
||||
function* defaultSaga() {
|
||||
const loadModelWatcher = yield fork(takeLatest, MODEL_FETCH, fetchModel);
|
||||
const loadSubmitChanges = yield fork(takeLatest, SUBMIT, submitChanges);
|
||||
yield fork(takeLatest, MODEL_FETCH, fetchModel);
|
||||
yield fork(takeLatest, SUBMIT, submitChanges);
|
||||
|
||||
yield take(LOCATION_CHANGE);
|
||||
// TODO fix Router (Other PR);
|
||||
|
||||
// const loadModelWatcher = yield fork(takeLatest, MODEL_FETCH, fetchModel);
|
||||
// const loadSubmitChanges = yield fork(takeLatest, SUBMIT, submitChanges);
|
||||
|
||||
yield cancel(loadModelWatcher);
|
||||
yield cancel(loadSubmitChanges);
|
||||
// yield take(LOCATION_CHANGE);
|
||||
|
||||
// yield cancel(loadModelWatcher);
|
||||
// yield cancel(loadSubmitChanges);
|
||||
}
|
||||
|
||||
export default defaultSaga;
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the modelPage state domain
|
||||
*/
|
||||
const selectModelPageDomain = () => state => state.get('modelPage');
|
||||
const selectModelPageDomain = () => state => state.get(`${pluginId}_modelPage`);
|
||||
|
||||
/**
|
||||
* Other specific selectors
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
const pluginPkg = require('../../package.json');
|
||||
const pluginId = pluginPkg.name.replace(
|
||||
/^strapi-plugin-/i,
|
||||
''
|
||||
);
|
||||
|
||||
module.exports = pluginId;
|
||||
@ -1,10 +0,0 @@
|
||||
{
|
||||
"/": {
|
||||
"name": "homePage",
|
||||
"container": "HomePage"
|
||||
},
|
||||
"/models/:modelName": {
|
||||
"name": "modelPage",
|
||||
"container": "ModelPage"
|
||||
}
|
||||
}
|
||||
@ -167,11 +167,11 @@ describe('Test CTB', () => {
|
||||
|
||||
cy.window()
|
||||
.its('__store__')
|
||||
.its('content-manager')
|
||||
.its('store')
|
||||
.then(pluginStore => {
|
||||
const displayedFields = pluginStore
|
||||
.getState()
|
||||
.getIn(['global', 'schema', 'models', 'product', 'editDisplay', 'fields'])
|
||||
.getIn(['content-manager_global', 'schema', 'models', 'product', 'editDisplay', 'fields'])
|
||||
.toJS();
|
||||
|
||||
expect(displayedFields).to.include.members([
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App actions
|
||||
*
|
||||
*/
|
||||
@ -1,5 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App constants
|
||||
*
|
||||
*/
|
||||
@ -6,41 +6,22 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
// Utils
|
||||
import { pluginId } from 'app';
|
||||
import pluginId from 'pluginId';
|
||||
// Containers
|
||||
import HomePage from 'containers/HomePage';
|
||||
import NotFoundPage from 'containers/NotFoundPage';
|
||||
|
||||
class App extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div className={pluginId}>
|
||||
<Switch>
|
||||
<Route path={`/plugins/${pluginId}`} component={HomePage} exact />
|
||||
<Route component={NotFoundPage} />
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function App() {
|
||||
return (
|
||||
<div className={pluginId}>
|
||||
<Switch>
|
||||
<Route path={`/plugins/${pluginId}`} component={HomePage} exact />
|
||||
<Route component={NotFoundPage} />
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
App.propTypes = {};
|
||||
|
||||
export function mapDispatchToProps(dispatch) {
|
||||
return bindActionCreators({}, dispatch);
|
||||
}
|
||||
|
||||
const mapStateToProps = createStructuredSelector({});
|
||||
|
||||
// Wrap the component to inject dispatch and state into it
|
||||
const withConnect = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
);
|
||||
|
||||
export default compose(withConnect)(App);
|
||||
export default App;
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App reducer
|
||||
*
|
||||
*/
|
||||
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
const initialState = fromJS({});
|
||||
|
||||
function appReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default appReducer;
|
||||
@ -1,9 +0,0 @@
|
||||
// import { createSelector } from 'reselect';
|
||||
|
||||
/**
|
||||
* Direct selector to the list state domain
|
||||
*/
|
||||
|
||||
// const selectGlobalDomain = () => state => state.get('global');
|
||||
|
||||
export {};
|
||||
@ -12,6 +12,7 @@ import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import { get, isEmpty } from 'lodash';
|
||||
import cn from 'classnames';
|
||||
import pluginId from 'pluginId';
|
||||
// Components
|
||||
import PluginHeader from 'components/PluginHeader';
|
||||
import PopUpWarning from 'components/PopUpWarning';
|
||||
@ -19,11 +20,8 @@ import Block from 'components/Block';
|
||||
import Row from 'components/Row';
|
||||
import LoadingIndicatorPage from 'components/LoadingIndicatorPage';
|
||||
import Input from 'components/InputsIndex';
|
||||
import { pluginId } from 'app';
|
||||
// Utils
|
||||
import auth from 'utils/auth';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import openWithNewTab from 'utils/openWithNewTab';
|
||||
// Actions
|
||||
import {
|
||||
@ -245,8 +243,8 @@ const withConnect = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
);
|
||||
const withReducer = injectReducer({ key: 'homePage', reducer });
|
||||
const withSaga = injectSaga({ key: 'homePage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'homePage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'homePage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -47,7 +47,7 @@ function* submit() {
|
||||
}, init);
|
||||
};
|
||||
const body = createBody(cloneDeep(form));
|
||||
console.log({ form, body });
|
||||
|
||||
if (body.restrictedAccess && body.password === '') {
|
||||
return yield put(
|
||||
setFormErrors({ password: [{ id: 'components.Input.error.validation.required' }] }),
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the homePage state domain
|
||||
*/
|
||||
const selectHomePageDomain = () => state => state.get('homePage');
|
||||
const selectHomePageDomain = () => state => state.get(`${pluginId}_homePage`);
|
||||
|
||||
/**
|
||||
* Default selector used by HomePage
|
||||
@ -30,4 +31,4 @@ const makeSelectVersionToDelete = () => createSelector(
|
||||
);
|
||||
|
||||
export default selectHomePage;
|
||||
export { makeSelectForm, makeSelectVersionToDelete, makeSelectPrefix };
|
||||
export { makeSelectForm, makeSelectVersionToDelete, makeSelectPrefix };
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
const pluginPkg = require('../../package.json');
|
||||
const pluginId = pluginPkg.name.replace(
|
||||
/^strapi-plugin-/i,
|
||||
''
|
||||
);
|
||||
|
||||
module.exports = pluginId;
|
||||
@ -7,9 +7,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
|
||||
// Utils
|
||||
import { pluginId } from 'app';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
// Containers
|
||||
import ConfigPage from 'containers/ConfigPage';
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App reducer
|
||||
*
|
||||
*/
|
||||
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
const initialState = fromJS({});
|
||||
|
||||
function appReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default appReducer;
|
||||
@ -1,9 +0,0 @@
|
||||
// import { createSelector } from 'reselect';
|
||||
|
||||
/**
|
||||
* Direct selector to the list state domain
|
||||
*/
|
||||
|
||||
// const selectGlobalDomain = () => state => state.get('global');
|
||||
|
||||
export {};
|
||||
@ -9,6 +9,7 @@ import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import { findIndex, get, isEmpty } from 'lodash';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
// You can find these components in either
|
||||
// ./node_modules/strapi-helper-plugin/lib/src
|
||||
@ -20,12 +21,6 @@ import PluginHeader from 'components/PluginHeader';
|
||||
// Plugin's components
|
||||
import EditForm from 'components/EditForm';
|
||||
|
||||
// You can find these utils in either
|
||||
// ./node_modules/strapi-helper-plugin/lib/src
|
||||
// or strapi/packages/strapi-helper-plugin/lib/src
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
|
||||
import {
|
||||
getSettings,
|
||||
onCancel,
|
||||
@ -180,8 +175,8 @@ const mapStateToProps = selectConfigPage();
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withReducer = injectReducer({ key: 'configPage', reducer });
|
||||
const withSaga = injectSaga({ key: 'configPage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'configPage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'configPage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the configPage state domain
|
||||
*/
|
||||
const selectConfigPageDomain = () => state => state.get('configPage');
|
||||
const selectConfigPageDomain = () => state => state.get(`${pluginId}_configPage`);
|
||||
|
||||
/**
|
||||
* Default selector used by ConfigPage
|
||||
|
||||
7
packages/strapi-plugin-email/admin/src/pluginId.js
Normal file
7
packages/strapi-plugin-email/admin/src/pluginId.js
Normal file
@ -0,0 +1,7 @@
|
||||
const pluginPkg = require('../../package.json');
|
||||
const pluginId = pluginPkg.name.replace(
|
||||
/^strapi-plugin-/i,
|
||||
''
|
||||
);
|
||||
|
||||
module.exports = pluginId;
|
||||
@ -14,9 +14,7 @@ import 'flag-icon-css/css/flag-icon.css';
|
||||
import 'react-select/dist/react-select.css';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { pluginId } from 'app';
|
||||
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
import HomePage from 'containers/HomePage';
|
||||
|
||||
@ -24,6 +22,7 @@ import { menuFetch, environmentsFetch } from './actions';
|
||||
import { makeSelectLoading, makeSelectSections } from './selectors';
|
||||
import styles from './styles.scss';
|
||||
|
||||
import reducer from './reducer';
|
||||
import saga from './sagas';
|
||||
|
||||
/* eslint-disable react/require-default-props */
|
||||
@ -95,9 +94,11 @@ const mapStateToProps = createStructuredSelector({
|
||||
// Wrap the component to inject dispatch and state into it
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withSaga = injectSaga({ key: 'global', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'global', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'global', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
withSaga,
|
||||
withConnect,
|
||||
)(App);
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the list state domain
|
||||
*/
|
||||
|
||||
const selectGlobalDomain = () => state => state.get('global');
|
||||
const selectGlobalDomain = () => state => state.get(`${pluginId}_global`);
|
||||
|
||||
const selectLocationState = () => {
|
||||
let prevRoutingState;
|
||||
|
||||
@ -9,6 +9,7 @@ import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
import {
|
||||
endsWith,
|
||||
@ -45,8 +46,6 @@ import { makeSelectSections, makeSelectEnvironments } from 'containers/App/selec
|
||||
|
||||
// utils
|
||||
import unknowFlag from 'assets/images/unknow_flag.png';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import supportedFlags from 'utils/supportedFlags.json';
|
||||
import { checkFormValidity, getRequiredInputsDb } from '../../utils/inputValidations';
|
||||
import getFlag, { formatLanguageLocale } from '../../utils/getFlag';
|
||||
@ -564,8 +563,8 @@ HomePage.propTypes = {
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withReducer = injectReducer({ key: 'homePage', reducer });
|
||||
const withSaga = injectSaga({ key: 'homePage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'homePage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'homePage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -1,6 +1,15 @@
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
// import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import { forEach, set, map, replace } from 'lodash';
|
||||
import { all, call, take, put, fork, cancel, select, takeLatest } from 'redux-saga/effects';
|
||||
import {
|
||||
all,
|
||||
call,
|
||||
// take,
|
||||
put,
|
||||
fork,
|
||||
// cancel,
|
||||
select,
|
||||
takeLatest,
|
||||
} from 'redux-saga/effects';
|
||||
import request from 'utils/request';
|
||||
// selectors
|
||||
import { makeSelectModifiedData } from './selectors';
|
||||
@ -240,28 +249,40 @@ export function* fetchSpecificDatabase(action) {
|
||||
|
||||
// Individual exports for testing
|
||||
export function* defaultSaga() {
|
||||
const loadConfigWatcher = yield fork(takeLatest, CONFIG_FETCH, fetchConfig);
|
||||
const loadLanguagesWatcher = yield fork(takeLatest, LANGUAGES_FETCH, fetchLanguages);
|
||||
const editConfigWatcher = yield fork(takeLatest, EDIT_SETTINGS, settingsEdit);
|
||||
const postLanguageWatcher = yield fork(takeLatest, NEW_LANGUAGE_POST, postLanguage);
|
||||
const deleteLanguageWatcher = yield fork(takeLatest, LANGUAGE_DELETE, deleteLanguage);
|
||||
const loadDatabasesWatcher = yield fork(takeLatest, DATABASES_FETCH, fetchDatabases);
|
||||
const postDatabaseWatcher = yield fork(takeLatest, NEW_DATABASE_POST, postDatabase);
|
||||
const deleteDatabaseWatcher = yield fork(takeLatest, DATABASE_DELETE, deleteDatabase);
|
||||
const fetchSpecificDatabaseWatcher = yield fork(takeLatest, SPECIFIC_DATABASE_FETCH, fetchSpecificDatabase);
|
||||
const editDatabaseWatcher = yield fork(takeLatest, DATABASE_EDIT, editDatabase);
|
||||
yield fork(takeLatest, CONFIG_FETCH, fetchConfig);
|
||||
yield fork(takeLatest, LANGUAGES_FETCH, fetchLanguages);
|
||||
yield fork(takeLatest, EDIT_SETTINGS, settingsEdit);
|
||||
yield fork(takeLatest, NEW_LANGUAGE_POST, postLanguage);
|
||||
yield fork(takeLatest, LANGUAGE_DELETE, deleteLanguage);
|
||||
yield fork(takeLatest, DATABASES_FETCH, fetchDatabases);
|
||||
yield fork(takeLatest, NEW_DATABASE_POST, postDatabase);
|
||||
yield fork(takeLatest, DATABASE_DELETE, deleteDatabase);
|
||||
yield fork(takeLatest, SPECIFIC_DATABASE_FETCH, fetchSpecificDatabase);
|
||||
yield fork(takeLatest, DATABASE_EDIT, editDatabase);
|
||||
|
||||
yield take(LOCATION_CHANGE);
|
||||
yield cancel(loadConfigWatcher);
|
||||
yield cancel(loadLanguagesWatcher);
|
||||
yield cancel(editConfigWatcher);
|
||||
yield cancel(postLanguageWatcher);
|
||||
yield cancel(deleteLanguageWatcher);
|
||||
yield cancel(loadDatabasesWatcher);
|
||||
yield cancel(postDatabaseWatcher);
|
||||
yield cancel(deleteDatabaseWatcher);
|
||||
yield cancel(fetchSpecificDatabaseWatcher);
|
||||
yield cancel(editDatabaseWatcher);
|
||||
// TODO Fix router (Other PR)
|
||||
// const loadConfigWatcher = yield fork(takeLatest, CONFIG_FETCH, fetchConfig);
|
||||
// const loadLanguagesWatcher = yield fork(takeLatest, LANGUAGES_FETCH, fetchLanguages);
|
||||
// const editConfigWatcher = yield fork(takeLatest, EDIT_SETTINGS, settingsEdit);
|
||||
// const postLanguageWatcher = yield fork(takeLatest, NEW_LANGUAGE_POST, postLanguage);
|
||||
// const deleteLanguageWatcher = yield fork(takeLatest, LANGUAGE_DELETE, deleteLanguage);
|
||||
// const loadDatabasesWatcher = yield fork(takeLatest, DATABASES_FETCH, fetchDatabases);
|
||||
// const postDatabaseWatcher = yield fork(takeLatest, NEW_DATABASE_POST, postDatabase);
|
||||
// const deleteDatabaseWatcher = yield fork(takeLatest, DATABASE_DELETE, deleteDatabase);
|
||||
// const fetchSpecificDatabaseWatcher = yield fork(takeLatest, SPECIFIC_DATABASE_FETCH, fetchSpecificDatabase);
|
||||
// const editDatabaseWatcher = yield fork(takeLatest, DATABASE_EDIT, editDatabase);
|
||||
|
||||
// yield take(LOCATION_CHANGE);
|
||||
// yield cancel(loadConfigWatcher);
|
||||
// yield cancel(loadLanguagesWatcher);
|
||||
// yield cancel(editConfigWatcher);
|
||||
// yield cancel(postLanguageWatcher);
|
||||
// yield cancel(deleteLanguageWatcher);
|
||||
// yield cancel(loadDatabasesWatcher);
|
||||
// yield cancel(postDatabaseWatcher);
|
||||
// yield cancel(deleteDatabaseWatcher);
|
||||
// yield cancel(fetchSpecificDatabaseWatcher);
|
||||
// yield cancel(editDatabaseWatcher);
|
||||
}
|
||||
|
||||
// All sagas to be loaded
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the home state domain
|
||||
*/
|
||||
const selectHomePageDomain = () => state => state.get('homePage');
|
||||
const selectHomePageDomain = () => state => state.get(`${pluginId}_homePage`);
|
||||
|
||||
/**
|
||||
* Other specific selectors
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
const pluginPkg = require('../../package.json');
|
||||
const pluginId = pluginPkg.name.replace(
|
||||
/^strapi-plugin-/i,
|
||||
''
|
||||
);
|
||||
|
||||
module.exports = pluginId;
|
||||
@ -1,6 +0,0 @@
|
||||
{
|
||||
"(/:slug(/:env))": {
|
||||
"name": "homePage",
|
||||
"container": "HomePage"
|
||||
}
|
||||
}
|
||||
@ -8,8 +8,7 @@
|
||||
import React from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
|
||||
// Utils
|
||||
import { pluginId } from 'app';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
// Containers
|
||||
import ConfigPage from 'containers/ConfigPage';
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App reducer
|
||||
*
|
||||
*/
|
||||
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
const initialState = fromJS({});
|
||||
|
||||
function appReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default appReducer;
|
||||
@ -1,9 +0,0 @@
|
||||
// import { createSelector } from 'reselect';
|
||||
|
||||
/**
|
||||
* Direct selector to the list state domain
|
||||
*/
|
||||
|
||||
// const selectGlobalDomain = () => state => state.get('global');
|
||||
|
||||
export {};
|
||||
@ -9,6 +9,7 @@ import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import { findIndex, get, isEmpty } from 'lodash';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
// You can find these components in either
|
||||
// ./node_modules/strapi-helper-plugin/lib/src
|
||||
@ -20,12 +21,6 @@ import PluginHeader from 'components/PluginHeader';
|
||||
// Plugin's components
|
||||
import EditForm from 'components/EditForm';
|
||||
|
||||
// You can find these utils in either
|
||||
// ./node_modules/strapi-helper-plugin/lib/src
|
||||
// or strapi/packages/strapi-helper-plugin/lib/src
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
|
||||
import {
|
||||
getSettings,
|
||||
onCancel,
|
||||
@ -180,8 +175,8 @@ const mapStateToProps = selectConfigPage();
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withReducer = injectReducer({ key: 'configPage', reducer });
|
||||
const withSaga = injectSaga({ key: 'configPage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'configPage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'configPage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the configPage state domain
|
||||
*/
|
||||
const selectConfigPageDomain = () => state => state.get('configPage');
|
||||
const selectConfigPageDomain = () => state => state.get(`${pluginId}_configPage`);
|
||||
|
||||
/**
|
||||
* Default selector used by ConfigPage
|
||||
|
||||
@ -11,6 +11,7 @@ import { connect } from 'react-redux';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import { isEmpty } from 'lodash';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
// You can find these components in either
|
||||
// ./node_modules/strapi-helper-plugin/lib/src
|
||||
@ -28,8 +29,6 @@ import PluginInputFile from 'components/PluginInputFile';
|
||||
|
||||
// Utils
|
||||
import getQueryParameters from 'utils/getQueryParameters';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
|
||||
// Actions
|
||||
import {
|
||||
@ -221,8 +220,8 @@ const mapStateToProps = selectHomePage();
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withReducer = injectReducer({ key: 'homePage', reducer });
|
||||
const withSaga = injectSaga({ key: 'homePage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'homePage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'homePage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -1,7 +1,16 @@
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
// import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import { Map } from 'immutable';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { all, call, fork, put, select, take, takeLatest } from 'redux-saga/effects';
|
||||
import {
|
||||
all,
|
||||
call,
|
||||
// cancel,
|
||||
fork,
|
||||
put,
|
||||
select,
|
||||
// take,
|
||||
takeLatest,
|
||||
} from 'redux-saga/effects';
|
||||
import request from 'utils/request';
|
||||
|
||||
import {
|
||||
@ -106,11 +115,13 @@ export function* defaultSaga() {
|
||||
yield fork(takeLatest, ON_DROP, uploadFiles);
|
||||
yield fork(takeLatest, ON_SEARCH, search);
|
||||
|
||||
const loadDataWatcher = yield fork(takeLatest, GET_DATA, dataGet);
|
||||
yield fork(takeLatest, GET_DATA, dataGet);
|
||||
// TODO: Fix router (Other PR)
|
||||
// const loadDataWatcher = yield fork(takeLatest, GET_DATA, dataGet);
|
||||
|
||||
yield take(LOCATION_CHANGE);
|
||||
// yield take(LOCATION_CHANGE);
|
||||
|
||||
yield cancel(loadDataWatcher);
|
||||
// yield cancel(loadDataWatcher);
|
||||
}
|
||||
|
||||
// All sagas to be loaded
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the homePage state domain
|
||||
*/
|
||||
const selectHomePageDomain = () => state => state.get('homePage');
|
||||
const selectHomePageDomain = () => state => state.get(`${pluginId}_homePage`);
|
||||
|
||||
/**
|
||||
* Default selector used by HomePage
|
||||
|
||||
7
packages/strapi-plugin-upload/admin/src/pluginId.js
Normal file
7
packages/strapi-plugin-upload/admin/src/pluginId.js
Normal file
@ -0,0 +1,7 @@
|
||||
const pluginPkg = require('../../package.json');
|
||||
const pluginId = pluginPkg.name.replace(
|
||||
/^strapi-plugin-/i,
|
||||
''
|
||||
);
|
||||
|
||||
module.exports = pluginId;
|
||||
@ -1,5 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App actions
|
||||
*
|
||||
*/
|
||||
@ -1,5 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App constants
|
||||
*
|
||||
*/
|
||||
@ -7,13 +7,8 @@
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
|
||||
// Utils
|
||||
import { pluginId } from 'app';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
// Containers
|
||||
import AuthPage from 'containers/AuthPage';
|
||||
@ -59,18 +54,4 @@ App.propTypes = {
|
||||
location: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export function mapDispatchToProps(dispatch) {
|
||||
return bindActionCreators(
|
||||
{},
|
||||
dispatch,
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = createStructuredSelector({});
|
||||
|
||||
// Wrap the component to inject dispatch and state into it
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
export default compose(
|
||||
withConnect,
|
||||
)(App);
|
||||
export default App;
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App reducer
|
||||
*
|
||||
*/
|
||||
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
const initialState = fromJS({});
|
||||
|
||||
function appReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default appReducer;
|
||||
@ -1,7 +0,0 @@
|
||||
// import { createSelector } from 'reselect';
|
||||
|
||||
/**
|
||||
* Direct selector to the list state domain
|
||||
*/
|
||||
|
||||
// const selectGlobalDomain = () => state => state.get('global');
|
||||
@ -12,6 +12,7 @@ import { Link } from 'react-router-dom';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { findIndex, get, isBoolean, isEmpty, map, replace } from 'lodash';
|
||||
import cn from 'classnames';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
// Logo
|
||||
import LogoStrapi from 'assets/images/logo_strapi.png';
|
||||
@ -22,8 +23,6 @@ import Input from 'components/InputsIndex';
|
||||
|
||||
// Utils
|
||||
import auth from 'utils/auth';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
|
||||
import {
|
||||
hideLoginErrorsInput,
|
||||
@ -328,16 +327,8 @@ function mapDispatchToProps(dispatch) {
|
||||
}
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
/* Remove this line if the container doesn't have a route and
|
||||
* check the documentation to see how to create the container's store
|
||||
*/
|
||||
const withReducer = injectReducer({ key: 'authPage', reducer });
|
||||
|
||||
/* Remove the line below the container doesn't have a route and
|
||||
* check the documentation to see how to create the container's store
|
||||
*/
|
||||
const withSaga = injectSaga({ key: 'authPage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'authPage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'authPage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the authPage state domain
|
||||
*/
|
||||
const selectAuthPageDomain = () => (state) => state.get('authPage');
|
||||
const selectAuthPageDomain = () => (state) => state.get(`${pluginId}_authPage`);
|
||||
|
||||
/**
|
||||
* Default selector used by AuthPage
|
||||
|
||||
@ -12,6 +12,7 @@ import { bindActionCreators, compose } from 'redux';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { findIndex, get, isEmpty, isEqual, size } from 'lodash';
|
||||
import cn from 'classnames';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
// Design
|
||||
import BackHeader from 'components/BackHeader';
|
||||
@ -23,9 +24,6 @@ import PluginHeader from 'components/PluginHeader';
|
||||
import Plugins from 'components/Plugins';
|
||||
import Policies from 'components/Policies';
|
||||
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import injectReducer from 'utils/injectReducer';
|
||||
|
||||
// Actions
|
||||
import {
|
||||
addUser,
|
||||
@ -326,16 +324,8 @@ function mapDispatchToProps(dispatch) {
|
||||
}
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
/* Remove this line if the container doesn't have a route and
|
||||
* check the documentation to see how to create the container's store
|
||||
*/
|
||||
const withReducer = injectReducer({ key: 'editPage', reducer });
|
||||
|
||||
/* Remove the line below the container doesn't have a route and
|
||||
* check the documentation to see how to create the container's store
|
||||
*/
|
||||
const withSaga = injectSaga({ key: 'editPage', saga });
|
||||
const withReducer = strapi.injectReducer({ key: 'editPage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'editPage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user