Fix hook bug and remove useless admin containers

This commit is contained in:
soupette 2018-04-13 14:37:46 +02:00
parent 0ac7c435f3
commit a66ca698ee
19 changed files with 12 additions and 396 deletions

View File

@ -12,6 +12,8 @@ strapi install graphql
Then, start your app and open your browser at [http://localhost:1337/graphiql](http://localhost:1337/graphiql). You should see the interface (GraphiQL) that will help you to write GraphQL query to explore your data.
> Install the [ModHeader](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj/related) extension to set the `Authorization` header in your request
## Configurations
By default, the [Shadow CRUD](#shadow-crud) feature is enabled and the GraphQL is set to `/graphql`. You can edit these configurations in the following files.

View File

@ -8,5 +8,12 @@
"appearance": "WYSIWYG"
}
}
},
"product": {
"attributes": {
"name": {
"appearance": ""
}
}
}
}

View File

@ -12,46 +12,16 @@ import { createStructuredSelector } from 'reselect';
import { Switch, Route } from 'react-router-dom';
import { bindActionCreators, compose } from 'redux';
// Utils
import { pluginId } from 'app';
// Containers
import HomePage from 'containers/HomePage';
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';
class App extends React.Component {
// When you're done studying the ExamplePage container, remove the following lines and delete the ExamplePage container
componentDidMount() {
this.props.history.push(`/plugins/${pluginId}/example`);
}
render() {
return (
<div className={pluginId}>
<Switch>
<Route path={`/plugins/${pluginId}`} component={HomePage} exact />
{/* When you're done studying the ExamplePage container, remove the following line and delete the ExamplePage container */}
<Route path={`/plugins/${pluginId}/example`} component={ExamplePage} exact />
<Route component={NotFoundPage} />
</Switch>
<div>
</div>
);
}
}
App.contextTypes = {
plugins: PropTypes.object,
router: PropTypes.object.isRequired,
updatePlugin: PropTypes.func,
};
App.propTypes = {
history: PropTypes.object.isRequired,
};
export function mapDispatchToProps(dispatch) {
return bindActionCreators(
{},

View File

@ -1,20 +0,0 @@
/*
*
* ExamplePage actions
*
*/
import { LOAD_DATA, LOADED_DATA } from './constants';
export function loadData() {
return {
type: LOAD_DATA,
};
}
export function loadedData(data) {
return {
type: LOADED_DATA,
data,
};
}

View File

@ -1,8 +0,0 @@
/*
*
* ExamplePage constants
*
*/
export const LOAD_DATA = 'ExamplePage/LOAD_DATA';
export const LOADED_DATA = 'ExamplePage/LOADED_DATA';

View File

@ -1,100 +0,0 @@
/*
*
* ExamplePage
*
*/
import React from 'react';
import PropTypes from 'prop-types';
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 Button from 'components/Button';
import styles from './styles.scss';
import { loadData } from './actions';
import { makeSelectLoading, makeSelectData } from './selectors';
import reducer from './reducer';
import saga from './saga';
export class ExamplePage extends React.Component {
generateDataBlock() {
if (this.props.data) {
const items = this.props.data.map((item, i) => <li key={i}>{item}</li>);
return (
<div>
<p>Data:</p>
<ul>{items}</ul>
</div>
);
}
return;
}
render() {
console.log('Don\'t forget to delete the ExampleContainer when you\'re done studying it');
// Generate the data block
const dataBlock = this.generateDataBlock();
return (
<div className={styles.examplePage}>
<div className="row">
<div className="col-md-12">
<p>This is an example of a fake API call.</p>
<p>Loading: {this.props.loading ? 'yes' : 'no'}.</p>
{dataBlock}
<Button
label={this.props.loading ? 'Loading...' : 'Submit'}
disabled={this.props.loading}
onClick={this.props.loadData}
primary
/>
</div>
</div>
</div>
);
}
}
ExamplePage.contextTypes = {
router: PropTypes.object,
};
ExamplePage.propTypes = {
data: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.object,
]).isRequired,
loadData: PropTypes.func.isRequired,
loading: PropTypes.bool.isRequired,
};
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
loadData,
},
dispatch,
);
}
const mapStateToProps = createStructuredSelector({
loading: makeSelectLoading(),
data: makeSelectData(),
});
const withConnect = connect(mapStateToProps, mapDispatchToProps);
const withReducer = injectReducer({ key: 'examplePage', reducer });
const withSaga = injectSaga({ key: 'examplePage', saga });
export default compose(
withReducer,
withSaga,
withConnect,
)(injectIntl(ExamplePage));

View File

@ -1,27 +0,0 @@
/*
*
* ExamplePage reducer
*
*/
import { fromJS } from 'immutable';
import { LOAD_DATA, LOADED_DATA } from './constants';
const initialState = fromJS({
loading: false,
data: false,
});
function examplePageReducer(state = initialState, action) {
switch (action.type) {
case LOAD_DATA:
return state.set('loading', true);
case LOADED_DATA:
return state.set('loading', false).set('data', fromJS(action.data));
default:
return state;
}
}
export default examplePageReducer;

View File

@ -1,31 +0,0 @@
import { LOCATION_CHANGE } from 'react-router-redux';
import { takeLatest, put, fork, take, cancel } from 'redux-saga/effects';
import { loadedData } from './actions';
import { LOAD_DATA } from './constants';
export function* loadData() {
// Fake API request delay
yield new Promise(resolve => {
setTimeout(() => {
resolve();
}, 1000);
});
// Generate a random array
const data = Array(4).fill(0).map(() => Math.floor(Math.random() * 100));
yield put(loadedData(data));
}
// Individual exports for testing
export function* defaultSaga() {
const loadDataWatcher = yield fork(takeLatest, LOAD_DATA, loadData);
// Suspend execution until location changes
yield take(LOCATION_CHANGE);
yield cancel(loadDataWatcher);
}
// All sagas to be loaded
export default defaultSaga;

View File

@ -1,18 +0,0 @@
import { createSelector } from 'reselect';
/**
* Direct selector to the examplePage state domain
*/
const selectExamplePageDomain = () => state => state.get('examplePage');
/**
* Default selector used by HomePage
*/
const makeSelectLoading = () =>
createSelector(selectExamplePageDomain(), substate => substate.get('loading'));
const makeSelectData = () =>
createSelector(selectExamplePageDomain(), substate => substate.get('data'));
export { makeSelectLoading, makeSelectData };

View File

@ -1,13 +0,0 @@
/*
*
* HomePage actions
*
*/
import { DEFAULT_ACTION } from './constants';
export function defaultAction() {
return {
type: DEFAULT_ACTION,
};
}

View File

@ -1,7 +0,0 @@
/*
*
* HomePage constants
*
*/
export const DEFAULT_ACTION = 'HomePage/DEFAULT_ACTION';

View File

@ -1,65 +0,0 @@
/*
*
* HomePage
*
*/
import React from 'react';
import PropTypes from 'prop-types';
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';
// Selectors
import selectHomePage from './selectors';
// Styles
import styles from './styles.scss';
import reducer from './reducer';
import saga from './saga';
export class HomePage extends React.Component {
render() {
return (
<div className={styles.homePage}>
</div>
);
}
}
HomePage.contextTypes = {
router: PropTypes.object,
};
HomePage.propTypes = {
// homePage: PropTypes.object,
};
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
// Your actions here
},
dispatch,
);
}
const mapStateToProps = createStructuredSelector({
homePage: selectHomePage(),
});
const withConnect = connect(mapStateToProps, mapDispatchToProps);
const withReducer = injectReducer({ key: 'homePage', reducer });
const withSaga = injectSaga({ key: 'homePage', saga });
export default compose(
withReducer,
withSaga,
withConnect,
)(injectIntl(HomePage));

View File

@ -1,22 +0,0 @@
/*
*
* HomePage reducer
*
*/
import { fromJS } from 'immutable';
import { DEFAULT_ACTION } from './constants';
const initialState = fromJS({});
function homePageReducer(state = initialState, action) {
switch (action.type) {
case DEFAULT_ACTION:
return state;
default:
return state;
}
}
export default homePageReducer;

View File

@ -1,9 +0,0 @@
// import { LOCATION_CHANGE } from 'react-router-redux';
// import { takeLatest, put, fork, take, cancel } from 'redux-saga/effects';
// Individual exports for testing
export function* defaultSaga() {
}
// All sagas to be loaded
export default defaultSaga;

View File

@ -1,17 +0,0 @@
import { createSelector } from 'reselect';
/**
* Direct selector to the homePage state domain
*/
const selectHomePageDomain = () => state => state.get('homePage');
/**
* Default selector used by HomePage
*/
const selectHomePage = () => createSelector(
selectHomePageDomain(),
(substate) => substate.toJS(),
);
export default selectHomePage;

View File

@ -1,20 +0,0 @@
/**
* NotFoundPage
*
* This is the page we show when the user visits a url that doesn't have a route
*
* NOTE: while this component should technically be a stateless functional
* component (SFC), hot reloading does not currently support SFCs. If hot
* reloading is not a neccessity for you then you can refactor it and remove
* the linting exception.
*/
import React from 'react';
import NotFound from 'components/NotFound';
export default class NotFoundPage extends React.Component {
render() {
return <NotFound {...this.props} />;
}
}

View File

@ -71,7 +71,7 @@ module.exports = strapi => {
_.set(strapi.plugins.graphql, 'config._schema.graphql', { definition: ``, query: ``, type : {}, resolver: {} });
// Merge user API.
Object.keys(strapi.api).reduce((acc, current) => {
Object.keys(strapi.api || {}).reduce((acc, current) => {
const { definition, query, type, resolver } = _.get(strapi.api[current], 'config.schema.graphql', {});
acc.definition += definition || ``;
@ -84,7 +84,7 @@ module.exports = strapi => {
}, strapi.plugins.graphql.config._schema.graphql);
// Merge plugins API.
Object.keys(strapi.plugins).reduce((acc, current) => {
Object.keys(strapi.plugins || {}).reduce((acc, current) => {
const { definition, query, type, resolver } = _.get(strapi.plugins[current], 'config.schema.graphql', {});
acc.definition += definition || ``;