mirror of
https://github.com/strapi/strapi.git
synced 2025-10-23 22:10:19 +00:00
Update recursively schema on change
This commit is contained in:
parent
c0c99d443a
commit
cc49c29f99
@ -7,7 +7,7 @@ const bootstrap = (plugin) => new Promise((resolve, reject) => {
|
|||||||
.then(models => {
|
.then(models => {
|
||||||
const menu = [{
|
const menu = [{
|
||||||
name: 'Content Types',
|
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,
|
label: model.labelPlural || model.label || key,
|
||||||
destination: key,
|
destination: key,
|
||||||
})),
|
})),
|
||||||
|
|||||||
@ -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 }) => (
|
||||||
|
<div className="col-md-12">
|
||||||
|
<div className={styles.ctmBlock}>
|
||||||
|
<div className={styles.ctmBlockTitle}>
|
||||||
|
<FormattedMessage id={title} />
|
||||||
|
<FormattedMessage id={description}>
|
||||||
|
{msg => <p>{msg}</p>}
|
||||||
|
</FormattedMessage>
|
||||||
|
</div>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
Block.defaultProps = {
|
||||||
|
children: null,
|
||||||
|
description: 'app.utils.defaultMessage',
|
||||||
|
title: 'app.utils.defaultMessage',
|
||||||
|
};
|
||||||
|
|
||||||
|
Block.propTypes = {
|
||||||
|
children: PropTypes.any,
|
||||||
|
description: PropTypes.string,
|
||||||
|
title: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Block;
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
.ctmBlock{
|
||||||
|
background: #ffffff;
|
||||||
|
padding: 22px 28px 0px;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: 0 2px 4px #E3E9F3;
|
||||||
|
webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ctmBlockTitle {
|
||||||
|
padding-top: 0px;
|
||||||
|
line-height: 18px;
|
||||||
|
font-weight: 400;
|
||||||
|
> span {
|
||||||
|
color: #333740;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
> p {
|
||||||
|
color: #787E8F;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,12 +4,14 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { includes } from 'lodash';
|
||||||
import {
|
import {
|
||||||
EMPTY_STORE,
|
EMPTY_STORE,
|
||||||
GET_MODEL_ENTRIES,
|
GET_MODEL_ENTRIES,
|
||||||
GET_MODEL_ENTRIES_SUCCEEDED,
|
GET_MODEL_ENTRIES_SUCCEEDED,
|
||||||
LOAD_MODELS,
|
LOAD_MODELS,
|
||||||
LOADED_MODELS,
|
LOADED_MODELS,
|
||||||
|
ON_CHANGE,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
|
|
||||||
export function emptyStore() {
|
export function emptyStore() {
|
||||||
@ -45,3 +47,13 @@ export function loadedModels(models) {
|
|||||||
models,
|
models,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function onChange({ target }) {
|
||||||
|
const value = includes(target.name, 'pageEntries') ? parseInt(target.value, 10) : target.value;
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: ON_CHANGE,
|
||||||
|
keys: target.name.split('.'),
|
||||||
|
value,
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -9,3 +9,4 @@ export const GET_MODEL_ENTRIES = 'contentManager/App/GET_MODEL_ENTRIES';
|
|||||||
export const GET_MODEL_ENTRIES_SUCCEEDED = 'contentManager/App/GET_MODEL_ENTRIES_SUCCEEDED';
|
export const GET_MODEL_ENTRIES_SUCCEEDED = 'contentManager/App/GET_MODEL_ENTRIES_SUCCEEDED';
|
||||||
export const LOAD_MODELS = 'contentManager/App/LOAD_MODELS';
|
export const LOAD_MODELS = 'contentManager/App/LOAD_MODELS';
|
||||||
export const LOADED_MODELS = 'contentManager/App/LOADED_MODELS';
|
export const LOADED_MODELS = 'contentManager/App/LOADED_MODELS';
|
||||||
|
export const ON_CHANGE = 'contentManager/App/ON_CHANGE';
|
||||||
|
|||||||
@ -16,9 +16,9 @@ import { Switch, Route } from 'react-router-dom';
|
|||||||
import injectSaga from 'utils/injectSaga';
|
import injectSaga from 'utils/injectSaga';
|
||||||
import getQueryParameters from 'utils/getQueryParameters';
|
import getQueryParameters from 'utils/getQueryParameters';
|
||||||
|
|
||||||
import Home from 'containers/Home';
|
|
||||||
import EditPage from 'containers/EditPage';
|
import EditPage from 'containers/EditPage';
|
||||||
import ListPage from 'containers/ListPage';
|
import ListPage from 'containers/ListPage';
|
||||||
|
import SettingsPage from 'containers/SettingsPage';
|
||||||
import LoadingIndicatorPage from 'components/LoadingIndicatorPage';
|
import LoadingIndicatorPage from 'components/LoadingIndicatorPage';
|
||||||
import EmptyAttributesView from 'components/EmptyAttributesView';
|
import EmptyAttributesView from 'components/EmptyAttributesView';
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ class App extends React.Component {
|
|||||||
|
|
||||||
const currentModelName = this.props.location.pathname.split('/')[3];
|
const currentModelName = this.props.location.pathname.split('/')[3];
|
||||||
const source = getQueryParameters(this.props.location.search, 'source');
|
const source = getQueryParameters(this.props.location.search, 'source');
|
||||||
const attrPath = source === 'content-manager' ? [currentModelName, 'fields'] : ['plugins', source, currentModelName, 'fields'];
|
const attrPath = source === 'content-manager' ? ['models', currentModelName, 'fields'] : ['models', 'plugins', source, currentModelName, 'fields'];
|
||||||
|
|
||||||
if (currentModelName && source && isEmpty(get(this.props.schema, attrPath))) {
|
if (currentModelName && source && isEmpty(get(this.props.schema, attrPath))) {
|
||||||
return <EmptyAttributesView currentModelName={currentModelName} history={this.props.history} modelEntries={this.props.modelEntries} />;
|
return <EmptyAttributesView currentModelName={currentModelName} history={this.props.history} modelEntries={this.props.modelEntries} />;
|
||||||
@ -50,7 +50,7 @@ class App extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="content-manager">
|
<div className="content-manager">
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/plugins/content-manager/ctm-configurations" component={Home} />
|
<Route path="/plugins/content-manager/ctm-configurations" component={SettingsPage} />
|
||||||
<Route path="/plugins/content-manager/:slug/:id" component={EditPage} />
|
<Route path="/plugins/content-manager/:slug/:id" component={EditPage} />
|
||||||
<Route path="/plugins/content-manager/:slug" component={ListPage} />
|
<Route path="/plugins/content-manager/:slug" component={ListPage} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|||||||
@ -5,8 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { fromJS, List } from 'immutable';
|
import { fromJS, List } from 'immutable';
|
||||||
|
import {
|
||||||
import { EMPTY_STORE, GET_MODEL_ENTRIES_SUCCEEDED, LOAD_MODELS, LOADED_MODELS } from './constants';
|
EMPTY_STORE,
|
||||||
|
GET_MODEL_ENTRIES_SUCCEEDED,
|
||||||
|
LOAD_MODELS,
|
||||||
|
LOADED_MODELS,
|
||||||
|
ON_CHANGE,
|
||||||
|
} from './constants';
|
||||||
|
|
||||||
const initialState = fromJS({
|
const initialState = fromJS({
|
||||||
modelEntries: 0,
|
modelEntries: 0,
|
||||||
@ -27,6 +32,32 @@ function appReducer(state = initialState, action) {
|
|||||||
return state
|
return state
|
||||||
.update('schema', () => fromJS(action.models.models))
|
.update('schema', () => fromJS(action.models.models))
|
||||||
.set('loading', false);
|
.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:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,11 +100,6 @@ export class EditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidCatch(error, info) {
|
|
||||||
console.log('err', err);
|
|
||||||
console.log('info', info);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.props.resetProps();
|
this.props.resetProps();
|
||||||
}
|
}
|
||||||
@ -128,7 +123,7 @@ export class EditPage extends React.Component {
|
|||||||
* Retrieve the model
|
* Retrieve the model
|
||||||
* @type {Object}
|
* @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
|
* Retrieve specific attribute
|
||||||
@ -153,8 +148,8 @@ export class EditPage extends React.Component {
|
|||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
getSchema = () => this.getSource() !== 'content-manager' ?
|
getSchema = () => this.getSource() !== 'content-manager' ?
|
||||||
get(this.props.schema, ['plugins', this.getSource(), this.getModelName()])
|
get(this.props.schema, ['models', 'plugins', this.getSource(), this.getModelName()])
|
||||||
: get(this.props.schema, [this.getModelName()]);
|
: get(this.props.schema, ['models', this.getModelName()]);
|
||||||
|
|
||||||
getPluginHeaderTitle = () => {
|
getPluginHeaderTitle = () => {
|
||||||
if (this.isCreating()) {
|
if (this.isCreating()) {
|
||||||
|
|||||||
@ -107,8 +107,8 @@ export class ListPage extends React.Component {
|
|||||||
* @return {Object} the current model
|
* @return {Object} the current model
|
||||||
*/
|
*/
|
||||||
getCurrentModel = () => (
|
getCurrentModel = () => (
|
||||||
get(this.props.schema, [this.getCurrentModelName()]) ||
|
get(this.props.schema, ['models', this.getCurrentModelName()]) ||
|
||||||
get(this.props.schema, ['plugins', this.getSource(), this.getCurrentModelName()])
|
get(this.props.schema, ['models', 'plugins', this.getSource(), this.getCurrentModelName()])
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -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": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -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 (
|
||||||
|
<div className={cn('container-fluid', styles.containerFluid)}>
|
||||||
|
<PluginHeader
|
||||||
|
actions={this.getPluginHeaderActions()}
|
||||||
|
title="Content Manager"
|
||||||
|
description={{ id: 'content-manager.containers.SettingsPage.pluginHeaderDescription' }}
|
||||||
|
/>
|
||||||
|
<div className={cn('row', styles.container)}>
|
||||||
|
<Block
|
||||||
|
description="content-manager.containers.SettingsPage.Block.generalSettings.description"
|
||||||
|
title="content-manager.containers.SettingsPage.Block.generalSettings.title"
|
||||||
|
>
|
||||||
|
<form onSubmit={(e) => e.preventDefault()} className={styles.ctmForm}>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-10">
|
||||||
|
<div className="row">
|
||||||
|
{forms.inputs.map(input => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
key={input.name}
|
||||||
|
onChange={this.props.onChange}
|
||||||
|
value={this.getValue(input)}
|
||||||
|
{...input}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Block>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
@ -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;
|
||||||
@ -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;
|
||||||
@ -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;
|
||||||
@ -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;
|
||||||
|
}
|
||||||
@ -14,6 +14,9 @@
|
|||||||
"containers.List.pluginHeaderDescription.singular": "{label} entry found",
|
"containers.List.pluginHeaderDescription.singular": "{label} entry found",
|
||||||
"components.LimitSelect.itemsPerPage": "Items per page",
|
"components.LimitSelect.itemsPerPage": "Items per page",
|
||||||
"containers.List.errorFetchRecords": "Error",
|
"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.add": "Filters",
|
||||||
"components.AddFilterCTA.hide": "Filters",
|
"components.AddFilterCTA.hide": "Filters",
|
||||||
@ -71,6 +74,12 @@
|
|||||||
"error.validation.minSupMax": "Can't be superior",
|
"error.validation.minSupMax": "Can't be superior",
|
||||||
"error.validation.json": "This is not a JSON",
|
"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.",
|
"notification.error.relationship.fetch": "An error occurred during relationship fetch.",
|
||||||
|
|
||||||
"success.record.delete": "Deleted",
|
"success.record.delete": "Deleted",
|
||||||
|
|||||||
@ -15,6 +15,9 @@
|
|||||||
"containers.List.pluginHeaderDescription.singular": "{label} entrée trouvée",
|
"containers.List.pluginHeaderDescription.singular": "{label} entrée trouvée",
|
||||||
"components.LimitSelect.itemsPerPage": "Éléments par page",
|
"components.LimitSelect.itemsPerPage": "Éléments par page",
|
||||||
"containers.List.errorFetchRecords": "Erreur",
|
"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.add": "Filtres",
|
||||||
"components.AddFilterCTA.hide": "Filtres",
|
"components.AddFilterCTA.hide": "Filtres",
|
||||||
@ -71,6 +74,12 @@
|
|||||||
"error.validation.minSupMax": "Ne peut pas être plus grand",
|
"error.validation.minSupMax": "Ne peut pas être plus grand",
|
||||||
"error.validation.json": "Le format JSON n'est pas respecté",
|
"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.",
|
"notification.error.relationship.fetch": "Une erreur est survenue en récupérant les relations.",
|
||||||
|
|
||||||
"success.record.delete": "Supprimé",
|
"success.record.delete": "Supprimé",
|
||||||
|
|||||||
@ -27,7 +27,17 @@ module.exports = async cb => {
|
|||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
// Init schema
|
// Init schema
|
||||||
const schema = { plugins: {} };
|
const schema = {
|
||||||
|
generalSettings: {
|
||||||
|
search: true,
|
||||||
|
filters: true,
|
||||||
|
bulkActions: true,
|
||||||
|
pageEntries: 10,
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
plugins: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const buildSchema = (model, name, plugin = false) => {
|
const buildSchema = (model, name, plugin = false) => {
|
||||||
// Model data
|
// Model data
|
||||||
@ -38,7 +48,7 @@ module.exports = async cb => {
|
|||||||
search: true,
|
search: true,
|
||||||
filters: true,
|
filters: true,
|
||||||
bulkActions: true,
|
bulkActions: true,
|
||||||
pageEntries: 20,
|
pageEntries: 10,
|
||||||
defaultSort: 'id'
|
defaultSort: 'id'
|
||||||
}, model);
|
}, model);
|
||||||
|
|
||||||
@ -56,7 +66,12 @@ module.exports = async cb => {
|
|||||||
schemaModel.listDisplay = Object.keys(schemaModel.fields)
|
schemaModel.listDisplay = Object.keys(schemaModel.fields)
|
||||||
// Construct Array of attr ex { type: 'string', label: 'Foo', name: 'Foo', description: '' }
|
// Construct Array of attr ex { type: 'string', label: 'Foo', name: 'Foo', description: '' }
|
||||||
// NOTE: Do we allow sort on boolean?
|
// 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
|
// Retrieve only the fourth first items
|
||||||
.slice(0, 4);
|
.slice(0, 4);
|
||||||
|
|
||||||
@ -64,6 +79,8 @@ module.exports = async cb => {
|
|||||||
name: model.primaryKey || 'id',
|
name: model.primaryKey || 'id',
|
||||||
label: 'Id',
|
label: 'Id',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
sortable: true,
|
||||||
|
searchable: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (model.associations) {
|
if (model.associations) {
|
||||||
@ -88,11 +105,11 @@ module.exports = async cb => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (plugin) {
|
if (plugin) {
|
||||||
return _.set(schema.plugins, `${plugin}.${name}`, schemaModel);
|
return _.set(schema.models.plugins, `${plugin}.${name}`, schemaModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the formatted model to the schema
|
// Set the formatted model to the schema
|
||||||
schema[name] = schemaModel;
|
schema.models[name] = schemaModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
_.forEach(pluginsModel, (plugin, pluginName) => {
|
_.forEach(pluginsModel, (plugin, pluginName) => {
|
||||||
@ -130,11 +147,11 @@ module.exports = async cb => {
|
|||||||
|
|
||||||
if (!prevSchema) {
|
if (!prevSchema) {
|
||||||
pluginStore.set({ key: 'schema', value: schema });
|
pluginStore.set({ key: 'schema', value: schema });
|
||||||
cb();
|
return cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
const prevSchemaKeys = buildSchemaKeys(prevSchema);
|
const prevSchemaKeys = buildSchemaKeys(prevSchema.models);
|
||||||
const schemaKeys = buildSchemaKeys(schema);
|
const schemaKeys = buildSchemaKeys(schema.models);
|
||||||
|
|
||||||
// Update the store with the new created APIs
|
// Update the store with the new created APIs
|
||||||
if (!_.isEqual(prevSchemaKeys, schemaKeys)) {
|
if (!_.isEqual(prevSchemaKeys, schemaKeys)) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user