diff --git a/packages/strapi-plugin-content-manager/admin/src/bootstrap.js b/packages/strapi-plugin-content-manager/admin/src/bootstrap.js
index cff6c2deaf..524be693df 100644
--- a/packages/strapi-plugin-content-manager/admin/src/bootstrap.js
+++ b/packages/strapi-plugin-content-manager/admin/src/bootstrap.js
@@ -7,7 +7,7 @@ const bootstrap = (plugin) => new Promise((resolve, reject) => {
.then(models => {
const menu = [{
name: 'Content Types',
- links: map(omit(models.models, 'plugins'), (model, key) => ({
+ links: map(omit(models.models.models, 'plugins'), (model, key) => ({
label: model.labelPlural || model.label || key,
destination: key,
})),
diff --git a/packages/strapi-plugin-content-manager/admin/src/components/Block/index.js b/packages/strapi-plugin-content-manager/admin/src/components/Block/index.js
new file mode 100644
index 0000000000..042ede09d0
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/components/Block/index.js
@@ -0,0 +1,39 @@
+/**
+ *
+ * Block
+ */
+
+import React from 'react';
+import PropTypes from 'prop-types';
+import { FormattedMessage } from 'react-intl';
+
+import styles from './styles.scss';
+
+const Block = ({ children, description, title }) => (
+
-
+
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/App/reducer.js b/packages/strapi-plugin-content-manager/admin/src/containers/App/reducer.js
index bc68aa3c95..65426c21f4 100755
--- a/packages/strapi-plugin-content-manager/admin/src/containers/App/reducer.js
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/App/reducer.js
@@ -5,8 +5,13 @@
*/
import { fromJS, List } from 'immutable';
-
-import { EMPTY_STORE, GET_MODEL_ENTRIES_SUCCEEDED, LOAD_MODELS, LOADED_MODELS } from './constants';
+import {
+ EMPTY_STORE,
+ GET_MODEL_ENTRIES_SUCCEEDED,
+ LOAD_MODELS,
+ LOADED_MODELS,
+ ON_CHANGE,
+} from './constants';
const initialState = fromJS({
modelEntries: 0,
@@ -27,6 +32,32 @@ function appReducer(state = initialState, action) {
return state
.update('schema', () => fromJS(action.models.models))
.set('loading', false);
+ case ON_CHANGE:
+ return state
+ .updateIn(['schema'].concat(action.keys), () => action.value)
+ .updateIn(['schema', 'models'], models => {
+ return models
+ .keySeq()
+ .reduce((acc, current) => {
+
+ if (current !== 'plugins') {
+ return acc.setIn([current, action.keys[1]], action.value);
+ }
+
+ return acc
+ .get(current)
+ .keySeq()
+ .reduce((acc1, curr) => {
+ return acc1
+ .getIn([current, curr])
+ .keySeq()
+ .reduce((acc2, curr1) => {
+
+ return acc2.setIn([ current, curr, curr1, action.keys[1]], action.value);
+ }, acc1);
+ }, acc);
+ }, models);
+ });
default:
return state;
}
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/index.js
index 72b6ad8ac5..9adcb7a892 100644
--- a/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/index.js
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/EditPage/index.js
@@ -100,11 +100,6 @@ export class EditPage extends React.Component {
}
}
- componentDidCatch(error, info) {
- console.log('err', err);
- console.log('info', info);
- }
-
componentWillUnmount() {
this.props.resetProps();
}
@@ -128,7 +123,7 @@ export class EditPage extends React.Component {
* Retrieve the model
* @type {Object}
*/
- getModel = () => get(this.props.schema, [this.getModelName()]) || get(this.props.schema, ['plugins', this.getSource(), this.getModelName()]);
+ getModel = () => get(this.props.schema, ['models', this.getModelName()]) || get(this.props.schema, ['models', 'plugins', this.getSource(), this.getModelName()]);
/**
* Retrieve specific attribute
@@ -153,8 +148,8 @@ export class EditPage extends React.Component {
* @return {Object}
*/
getSchema = () => this.getSource() !== 'content-manager' ?
- get(this.props.schema, ['plugins', this.getSource(), this.getModelName()])
- : get(this.props.schema, [this.getModelName()]);
+ get(this.props.schema, ['models', 'plugins', this.getSource(), this.getModelName()])
+ : get(this.props.schema, ['models', this.getModelName()]);
getPluginHeaderTitle = () => {
if (this.isCreating()) {
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/index.js
index 601669154a..7cf91b42ec 100644
--- a/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/index.js
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/ListPage/index.js
@@ -107,8 +107,8 @@ export class ListPage extends React.Component {
* @return {Object} the current model
*/
getCurrentModel = () => (
- get(this.props.schema, [this.getCurrentModelName()]) ||
- get(this.props.schema, ['plugins', this.getSource(), this.getCurrentModelName()])
+ get(this.props.schema, ['models', this.getCurrentModelName()]) ||
+ get(this.props.schema, ['models', 'plugins', this.getSource(), this.getCurrentModelName()])
);
/**
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/actions.js b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/actions.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/constants.js b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/constants.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/forms.json b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/forms.json
new file mode 100644
index 0000000000..93392fa681
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/forms.json
@@ -0,0 +1,42 @@
+{
+ "inputs": [
+ {
+ "label": { "id": "content-manager.form.Input.search" },
+ "customBootstrapClass": "col-md-5",
+ "didCheckErrors": false,
+ "errors": [],
+ "name": "generalSettings.search",
+ "type": "toggle",
+ "validations": {}
+ },
+ {
+ "label": { "id": "content-manager.form.Input.filters" },
+ "customBootstrapClass": "col-md-5",
+ "didCheckErrors": false,
+ "errors": [],
+ "name": "generalSettings.filters",
+ "type": "toggle",
+ "validations": {}
+ },
+ {
+ "label": { "id": "content-manager.form.Input.bulkActions" },
+ "customBootstrapClass": "col-md-2",
+ "didCheckErrors": false,
+ "errors": [],
+ "name": "generalSettings.bulkActions",
+ "type": "toggle",
+ "validations": {}
+ },
+ {
+ "label": { "id": "content-manager.form.Input.pageEntries" },
+ "customBootstrapClass": "col-md-3",
+ "didCheckErrors": false,
+ "errors": [],
+ "inputDescription": { "id": "content-manager.form.Input.pageEntries.inputDescription" },
+ "name": "generalSettings.pageEntries",
+ "selectOptions": ["10", "20", "50", "100"],
+ "type": "select",
+ "validations": {}
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/index.js
new file mode 100644
index 0000000000..1a9fec6632
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/index.js
@@ -0,0 +1,125 @@
+/**
+ *
+ * SettingsPage
+ */
+
+import React from 'react';
+import { connect } from 'react-redux';
+import { bindActionCreators, compose } from 'redux';
+import { createStructuredSelector } from 'reselect';
+import cn from 'classnames';
+import { get } from 'lodash';
+import PropTypes from 'prop-types';
+
+import { onChange } from 'containers/App/actions';
+import { makeSelectSchema } from 'containers/App/selectors';
+
+import PluginHeader from 'components/PluginHeader';
+import Input from 'components/InputsIndex';
+
+import Block from 'components/Block';
+
+import injectReducer from 'utils/injectReducer';
+import injectSaga from 'utils/injectSaga';
+
+import reducer from './reducer';
+import saga from './saga';
+import makeSelectSettingsPage from './selectors';
+import styles from './styles.scss';
+
+import forms from './forms.json';
+
+class SettingsPage extends React.PureComponent {
+ getPluginHeaderActions = () => (
+ [
+ {
+ label: 'content-manager.popUpWarning.button.cancel',
+ kind: 'secondary',
+ onClick: () => {},
+ type: 'button',
+ },
+ {
+ kind: 'primary',
+ label: 'content-manager.containers.Edit.submit',
+ onClick: () => {},
+ type: 'submit',
+ },
+ ]
+ );
+
+ getValue = (input) => {
+ const { schema: { generalSettings } } = this.props;
+ const value = get(generalSettings, input.name.split('.')[1], input.type === 'toggle' ? false : 10);
+
+ return input.type === 'toggle' ? value : value.toString();
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+SettingsPage.defaultProps = {};
+
+SettingsPage.propTypes = {
+ onChange: PropTypes.func.isRequired,
+ schema: PropTypes.object.isRequired,
+};
+
+const mapDispatchToProps = (dispatch) => (
+ bindActionCreators(
+ {
+ onChange,
+ },
+ dispatch,
+ )
+);
+
+const mapStateToProps = createStructuredSelector({
+ schema: makeSelectSchema(),
+ settingsPage: makeSelectSettingsPage(),
+});
+
+const withConnect = connect(mapStateToProps, mapDispatchToProps);
+const withReducer = injectReducer({ key: 'settingsPage', reducer });
+const withSaga = injectSaga({ key: 'settingsPage', saga });
+
+export default compose(
+ withReducer,
+ withSaga,
+ withConnect,
+)(SettingsPage);
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/reducer.js b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/reducer.js
new file mode 100644
index 0000000000..0649137672
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/reducer.js
@@ -0,0 +1,19 @@
+/**
+ *
+ * SettingsPage reducer
+ */
+
+import { fromJS } from 'immutable';
+
+const initialState = fromJS({
+ foo: 'bar',
+});
+
+function settingsPageReducer(state = initialState, action) {
+ switch (action.type) {
+ default:
+ return state;
+ }
+}
+
+export default settingsPageReducer;
\ No newline at end of file
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/saga.js b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/saga.js
new file mode 100644
index 0000000000..4c7caa7fa2
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/saga.js
@@ -0,0 +1,14 @@
+// import { LOCATION_CHANGE } from 'react-router-redux'
+// import {
+// call,
+// cancel,
+// fork,
+// put,
+// select,
+// take,
+// takeLatest,
+// } from 'redux-saga/effects';
+
+function* defaultSaga() {}
+
+export default defaultSaga;
\ No newline at end of file
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/selectors.js b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/selectors.js
new file mode 100644
index 0000000000..8153dd3770
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/selectors.js
@@ -0,0 +1,24 @@
+/**
+ *
+ * SettingsPage selectors
+ */
+
+import { createSelector } from 'reselect';
+
+/**
+* Direct selector to the settingsPage state domain
+*/
+const selectSettingsPageDomain = () => state => state.get('settingsPage');
+
+
+/**
+ * Default selector used by EditPage
+ */
+
+const makeSelectSettingsPage = () => createSelector(
+ selectSettingsPageDomain(),
+ (substate) => substate.toJS()
+);
+
+
+export default makeSelectSettingsPage;
\ No newline at end of file
diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/styles.scss b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/styles.scss
new file mode 100644
index 0000000000..944eb6d40f
--- /dev/null
+++ b/packages/strapi-plugin-content-manager/admin/src/containers/SettingsPage/styles.scss
@@ -0,0 +1,21 @@
+.containerFluid {
+ padding: 18px 30px;
+ > div:first-child {
+ max-height: 33px;
+ }
+}
+
+.container {
+ padding-top: 18px;
+}
+
+.main_wrapper{
+ background: #ffffff;
+ padding: 22px 28px 0px;
+ border-radius: 2px;
+ box-shadow: 0 2px 4px #E3E9F3;
+}
+
+.ctmForm {
+ padding-top: 2.6rem;
+}
\ No newline at end of file
diff --git a/packages/strapi-plugin-content-manager/admin/src/translations/en.json b/packages/strapi-plugin-content-manager/admin/src/translations/en.json
index a44c540879..760b7eda7c 100755
--- a/packages/strapi-plugin-content-manager/admin/src/translations/en.json
+++ b/packages/strapi-plugin-content-manager/admin/src/translations/en.json
@@ -14,6 +14,9 @@
"containers.List.pluginHeaderDescription.singular": "{label} entry found",
"components.LimitSelect.itemsPerPage": "Items per page",
"containers.List.errorFetchRecords": "Error",
+ "containers.SettingsPage.pluginHeaderDescription": "Configure the default settings for all your content types",
+ "containers.SettingsPage.Block.generalSettings.description": "Configure the default options for your content types",
+ "containers.SettingsPage.Block.generalSettings.title": "General",
"components.AddFilterCTA.add": "Filters",
"components.AddFilterCTA.hide": "Filters",
@@ -71,6 +74,12 @@
"error.validation.minSupMax": "Can't be superior",
"error.validation.json": "This is not a JSON",
+ "form.Input.search": "Enable search",
+ "form.Input.filters": "Enable filters",
+ "form.Input.bulkActions": "Enable bulk actions",
+ "form.Input.pageEntries": "Entries per page",
+ "form.Input.pageEntries.inputDescription": "Note: You can override this value in the Content Type settings page.",
+
"notification.error.relationship.fetch": "An error occurred during relationship fetch.",
"success.record.delete": "Deleted",
diff --git a/packages/strapi-plugin-content-manager/admin/src/translations/fr.json b/packages/strapi-plugin-content-manager/admin/src/translations/fr.json
index 6fe8272067..6d3727164b 100755
--- a/packages/strapi-plugin-content-manager/admin/src/translations/fr.json
+++ b/packages/strapi-plugin-content-manager/admin/src/translations/fr.json
@@ -15,6 +15,9 @@
"containers.List.pluginHeaderDescription.singular": "{label} entrée trouvée",
"components.LimitSelect.itemsPerPage": "Éléments par page",
"containers.List.errorFetchRecords": "Erreur",
+ "containers.SettingsPage.pluginHeaderDescription": "Configurez les paramètres par défaut de vos modèles",
+ "containers.SettingsPage.Block.generalSettings.description": "Configurez les options par défault de vos modèles",
+ "containers.SettingsPage.Block.generalSettings.title": "Général",
"components.AddFilterCTA.add": "Filtres",
"components.AddFilterCTA.hide": "Filtres",
@@ -71,6 +74,12 @@
"error.validation.minSupMax": "Ne peut pas être plus grand",
"error.validation.json": "Le format JSON n'est pas respecté",
+ "form.Input.search": "Autoriser la search",
+ "form.Input.filters": "Autoriser les filtres",
+ "form.Input.bulkActions": "Autoriser les bulk actions",
+ "form.Input.pageEntries": "Nombre d'entrées par page",
+ "form.Input.pageEntries.inputDescription": "Note: Vous pouvez les modifier ces valeurs par modèle",
+
"notification.error.relationship.fetch": "Une erreur est survenue en récupérant les relations.",
"success.record.delete": "Supprimé",
diff --git a/packages/strapi-plugin-content-manager/config/functions/bootstrap.js b/packages/strapi-plugin-content-manager/config/functions/bootstrap.js
index 626edd6434..f740d37dc6 100644
--- a/packages/strapi-plugin-content-manager/config/functions/bootstrap.js
+++ b/packages/strapi-plugin-content-manager/config/functions/bootstrap.js
@@ -27,7 +27,17 @@ module.exports = async cb => {
}, {});
// Init schema
- const schema = { plugins: {} };
+ const schema = {
+ generalSettings: {
+ search: true,
+ filters: true,
+ bulkActions: true,
+ pageEntries: 10,
+ },
+ models: {
+ plugins: {},
+ },
+ };
const buildSchema = (model, name, plugin = false) => {
// Model data
@@ -38,7 +48,7 @@ module.exports = async cb => {
search: true,
filters: true,
bulkActions: true,
- pageEntries: 20,
+ pageEntries: 10,
defaultSort: 'id'
}, model);
@@ -56,7 +66,12 @@ module.exports = async cb => {
schemaModel.listDisplay = Object.keys(schemaModel.fields)
// Construct Array of attr ex { type: 'string', label: 'Foo', name: 'Foo', description: '' }
// NOTE: Do we allow sort on boolean?
- .map(attr => Object.assign(schemaModel.fields[attr], { name: attr, sortable: true, searchable: true }))
+ .map(attr => {
+ const attrType = schemaModel.fields[attr].type;
+ const sortable = attrType !== 'json' && attrType !== 'array';
+
+ return Object.assign(schemaModel.fields[attr], { name: attr, sortable, searchable: sortable });
+ })
// Retrieve only the fourth first items
.slice(0, 4);
@@ -64,6 +79,8 @@ module.exports = async cb => {
name: model.primaryKey || 'id',
label: 'Id',
type: 'string',
+ sortable: true,
+ searchable: true,
});
if (model.associations) {
@@ -88,11 +105,11 @@ module.exports = async cb => {
}
if (plugin) {
- return _.set(schema.plugins, `${plugin}.${name}`, schemaModel);
+ return _.set(schema.models.plugins, `${plugin}.${name}`, schemaModel);
}
// Set the formatted model to the schema
- schema[name] = schemaModel;
+ schema.models[name] = schemaModel;
};
_.forEach(pluginsModel, (plugin, pluginName) => {
@@ -130,11 +147,11 @@ module.exports = async cb => {
if (!prevSchema) {
pluginStore.set({ key: 'schema', value: schema });
- cb();
+ return cb();
}
- const prevSchemaKeys = buildSchemaKeys(prevSchema);
- const schemaKeys = buildSchemaKeys(schema);
+ const prevSchemaKeys = buildSchemaKeys(prevSchema.models);
+ const schemaKeys = buildSchemaKeys(schema.models);
// Update the store with the new created APIs
if (!_.isEqual(prevSchemaKeys, schemaKeys)) {