mirror of
https://github.com/strapi/strapi.git
synced 2025-08-23 08:09:10 +00:00
Auto generate admin fields
This commit is contained in:
parent
feaaf3a4eb
commit
1fb39080c3
@ -40,7 +40,7 @@ class EditFormRelation extends React.Component { // eslint-disable-line react/pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Request URL
|
// Request URL
|
||||||
const requestUrlSuffix = query ? '' : this.props.record.get(this.props.relation.attribute);
|
const requestUrlSuffix = query && this.props.record.get(this.props.relation.attribute) ? this.props.record.get(this.props.relation.attribute) : '';
|
||||||
const requestUrl = `/content-manager/explorer/${this.props.relation.model}/${requestUrlSuffix}`;
|
const requestUrl = `/content-manager/explorer/${this.props.relation.model}/${requestUrlSuffix}`;
|
||||||
|
|
||||||
// Call our request helper (see 'utils/request')
|
// Call our request helper (see 'utils/request')
|
||||||
@ -51,11 +51,11 @@ class EditFormRelation extends React.Component { // eslint-disable-line react/pr
|
|||||||
.then(response => {
|
.then(response => {
|
||||||
const options = _.isArray(response)
|
const options = _.isArray(response)
|
||||||
? _.map(response, item => ({
|
? _.map(response, item => ({
|
||||||
value: Number(item.id),
|
value: item.id,
|
||||||
label: item[this.props.relation.displayedAttribute],
|
label: item[this.props.relation.displayedAttribute],
|
||||||
}))
|
}))
|
||||||
: [{
|
: [{
|
||||||
value: Number(response.id),
|
value: response.id,
|
||||||
label: response[this.props.relation.displayedAttribute],
|
label: response[this.props.relation.displayedAttribute],
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
@ -8,21 +8,33 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createStructuredSelector } from 'reselect';
|
import { createStructuredSelector } from 'reselect';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
import config from '../../../../config/admin.json';
|
|
||||||
import { loadModels, updateSchema } from './actions';
|
import { loadModels, updateSchema } from './actions';
|
||||||
import { makeSelectModels, makeSelectLoading } from './selectors';
|
import { makeSelectLoading } from './selectors';
|
||||||
|
|
||||||
|
const tryRequire = (path) => {
|
||||||
|
try {
|
||||||
|
return require(`containers/${path}.js`); // eslint-disable-line global-require
|
||||||
|
} catch (err) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class App extends React.Component {
|
class App extends React.Component {
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.loadModels();
|
const config = tryRequire('../../../../config/admin.json');
|
||||||
|
if (!_.isEmpty(_.get(config, 'admin.schema'))) {
|
||||||
this.props.updateSchema(config.admin.schema);
|
this.props.updateSchema(config.admin.schema);
|
||||||
|
} else {
|
||||||
|
this.props.loadModels();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let content = <div />;
|
let content = <div />;
|
||||||
|
|
||||||
if (this.props.models) {
|
if (!this.props.loading) {
|
||||||
// Assign plugin component to children
|
// Assign plugin component to children
|
||||||
content = React.Children.map(this.props.children, child =>
|
content = React.Children.map(this.props.children, child =>
|
||||||
React.cloneElement(child, {
|
React.cloneElement(child, {
|
||||||
@ -46,11 +58,8 @@ App.contextTypes = {
|
|||||||
App.propTypes = {
|
App.propTypes = {
|
||||||
children: React.PropTypes.node.isRequired,
|
children: React.PropTypes.node.isRequired,
|
||||||
exposedComponents: React.PropTypes.object.isRequired,
|
exposedComponents: React.PropTypes.object.isRequired,
|
||||||
|
loading: React.PropTypes.bool,
|
||||||
loadModels: React.PropTypes.func.isRequired,
|
loadModels: React.PropTypes.func.isRequired,
|
||||||
models: React.PropTypes.oneOfType([
|
|
||||||
React.PropTypes.object,
|
|
||||||
React.PropTypes.bool,
|
|
||||||
]),
|
|
||||||
updateSchema: React.PropTypes.func.isRequired,
|
updateSchema: React.PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,7 +72,6 @@ export function mapDispatchToProps(dispatch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
models: makeSelectModels(),
|
|
||||||
loading: makeSelectLoading(),
|
loading: makeSelectLoading(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import { fromJS } from 'immutable';
|
|||||||
import { LOAD_MODELS, LOADED_MODELS, UPDATE_SCHEMA } from './constants';
|
import { LOAD_MODELS, LOADED_MODELS, UPDATE_SCHEMA } from './constants';
|
||||||
|
|
||||||
const initialState = fromJS({
|
const initialState = fromJS({
|
||||||
loading: false,
|
loading: true,
|
||||||
models: false,
|
models: false,
|
||||||
schema: false,
|
schema: false,
|
||||||
});
|
});
|
||||||
@ -17,11 +17,14 @@ const initialState = fromJS({
|
|||||||
function appReducer(state = initialState, action) {
|
function appReducer(state = initialState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case LOAD_MODELS:
|
case LOAD_MODELS:
|
||||||
return state.set('loading', true);
|
return state;
|
||||||
case LOADED_MODELS:
|
case LOADED_MODELS:
|
||||||
return state.set('loading', false).set('models', action.models);
|
return state
|
||||||
|
.set('models', action.models);
|
||||||
case UPDATE_SCHEMA:
|
case UPDATE_SCHEMA:
|
||||||
return state.set('schema', action.schema);
|
return state
|
||||||
|
.set('loading', false)
|
||||||
|
.set('schema', action.schema);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { takeLatest } from 'redux-saga';
|
import { takeLatest } from 'redux-saga';
|
||||||
import {fork, put} from 'redux-saga/effects';
|
import { fork, put, select } from 'redux-saga/effects';
|
||||||
|
|
||||||
|
import { generateSchema } from 'utils/schema';
|
||||||
|
|
||||||
|
import { loadedModels, updateSchema } from './actions';
|
||||||
|
import { LOAD_MODELS, LOADED_MODELS, UPDATE_SCHEMA } from './constants';
|
||||||
|
import { makeSelectModels } from './selectors';
|
||||||
|
|
||||||
import {loadedModels} from './actions';
|
|
||||||
import {LOAD_MODELS, UPDATE_SCHEMA} from './constants';
|
|
||||||
|
|
||||||
export function* getModels() {
|
export function* getModels() {
|
||||||
try {
|
try {
|
||||||
@ -26,6 +30,22 @@ export function* getModels() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function* modelsLoaded() {
|
||||||
|
const models = yield select(makeSelectModels());
|
||||||
|
let schema;
|
||||||
|
|
||||||
|
try {
|
||||||
|
schema = generateSchema(models);
|
||||||
|
} catch (err) {
|
||||||
|
window.Strapi.notification.error(
|
||||||
|
'An error occurred during schema generation.'
|
||||||
|
);
|
||||||
|
throw new Error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield put(updateSchema(schema));
|
||||||
|
}
|
||||||
|
|
||||||
export function* schemaUpdated(action) {
|
export function* schemaUpdated(action) {
|
||||||
// Display the links only if the `displayed` attribute is not set to false
|
// Display the links only if the `displayed` attribute is not set to false
|
||||||
const displayedModels = _.pickBy(action.schema, model => (model.displayed !== false));
|
const displayedModels = _.pickBy(action.schema, model => (model.displayed !== false));
|
||||||
@ -44,6 +64,7 @@ export function* schemaUpdated(action) {
|
|||||||
export function* defaultSaga() {
|
export function* defaultSaga() {
|
||||||
yield fork(takeLatest, LOAD_MODELS, getModels);
|
yield fork(takeLatest, LOAD_MODELS, getModels);
|
||||||
yield fork(takeLatest, UPDATE_SCHEMA, schemaUpdated);
|
yield fork(takeLatest, UPDATE_SCHEMA, schemaUpdated);
|
||||||
|
yield fork(takeLatest, LOADED_MODELS, modelsLoaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All sagas to be loaded
|
// All sagas to be loaded
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
import pluralize from 'pluralize';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a schema according to the models
|
||||||
|
* of the Strapi application.
|
||||||
|
*
|
||||||
|
* @param models
|
||||||
|
*/
|
||||||
|
const generateSchema = (models) => {
|
||||||
|
// Init `schema` object
|
||||||
|
const schema = {};
|
||||||
|
|
||||||
|
_.forEach(models, (model, name) => {
|
||||||
|
// Model data
|
||||||
|
const schemaModel = {
|
||||||
|
label: _.upperFirst(name),
|
||||||
|
labelPlural: _.upperFirst(pluralize(name)),
|
||||||
|
orm: model.orm || 'mongoose',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fields (non relation)
|
||||||
|
schemaModel.fields = _.mapValues(_.pickBy(model.attributes, attribute =>
|
||||||
|
!attribute.model && !attribute.collection
|
||||||
|
), (value, attribute) => ({
|
||||||
|
label: _.upperFirst(attribute),
|
||||||
|
description: '',
|
||||||
|
type: value.type || 'string',
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Select fields displayed in list view
|
||||||
|
schemaModel.list = _.slice(_.keys(schemaModel.fields), 0, 4);
|
||||||
|
|
||||||
|
// Model relations
|
||||||
|
schemaModel.relations = _.mapValues(_.pickBy(model.attributes, attribute =>
|
||||||
|
attribute.model
|
||||||
|
), (value, attribute) => ({
|
||||||
|
columnName: attribute,
|
||||||
|
model: value.model,
|
||||||
|
attribute,
|
||||||
|
label: _.upperFirst(attribute),
|
||||||
|
description: '',
|
||||||
|
displayedAttribute: _.findKey(models[value.model].attributes, { type: 'string' }) || 'id',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set the formatted model to the schema
|
||||||
|
schema[name] = schemaModel;
|
||||||
|
});
|
||||||
|
|
||||||
|
return schema;
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
generateSchema,
|
||||||
|
};
|
@ -23,7 +23,7 @@ module.exports = {
|
|||||||
|
|
||||||
find: async ctx => {
|
find: async ctx => {
|
||||||
const model = strapi.models[ctx.params.model];
|
const model = strapi.models[ctx.params.model];
|
||||||
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']);
|
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']) || model.orm;
|
||||||
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
||||||
const primaryKey = model.primaryKey;
|
const primaryKey = model.primaryKey;
|
||||||
const {limit, skip = 0, sort = primaryKey, query, queryAttribute} = ctx.request.query;
|
const {limit, skip = 0, sort = primaryKey, query, queryAttribute} = ctx.request.query;
|
||||||
@ -44,7 +44,7 @@ module.exports = {
|
|||||||
|
|
||||||
count: async ctx => {
|
count: async ctx => {
|
||||||
const model = strapi.models[ctx.params.model];
|
const model = strapi.models[ctx.params.model];
|
||||||
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']);
|
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']) || model.orm;
|
||||||
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
||||||
|
|
||||||
// Count using `queries` system
|
// Count using `queries` system
|
||||||
@ -57,7 +57,7 @@ module.exports = {
|
|||||||
|
|
||||||
findOne: async ctx => {
|
findOne: async ctx => {
|
||||||
const model = strapi.models[ctx.params.model];
|
const model = strapi.models[ctx.params.model];
|
||||||
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']);
|
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']) || model.orm;
|
||||||
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
||||||
const primaryKey = model.primaryKey;
|
const primaryKey = model.primaryKey;
|
||||||
const id = ctx.params.id;
|
const id = ctx.params.id;
|
||||||
@ -79,7 +79,7 @@ module.exports = {
|
|||||||
|
|
||||||
create: async ctx => {
|
create: async ctx => {
|
||||||
const model = strapi.models[ctx.params.model];
|
const model = strapi.models[ctx.params.model];
|
||||||
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']);
|
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']) || model.orm;
|
||||||
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
||||||
const values = ctx.request.body;
|
const values = ctx.request.body;
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ module.exports = {
|
|||||||
|
|
||||||
update: async ctx => {
|
update: async ctx => {
|
||||||
const model = strapi.models[ctx.params.model];
|
const model = strapi.models[ctx.params.model];
|
||||||
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']);
|
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']) || model.orm;
|
||||||
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
||||||
const primaryKey = model.primaryKey;
|
const primaryKey = model.primaryKey;
|
||||||
const id = ctx.params.id;
|
const id = ctx.params.id;
|
||||||
@ -113,7 +113,7 @@ module.exports = {
|
|||||||
|
|
||||||
delete: async ctx => {
|
delete: async ctx => {
|
||||||
const model = strapi.models[ctx.params.model];
|
const model = strapi.models[ctx.params.model];
|
||||||
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']);
|
const orm = _.get(strapi.plugins, ['content-manager', 'config', 'admin', 'schema', ctx.params.model, 'orm']) || model.orm;
|
||||||
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
const queries = _.get(strapi.plugins, ['content-manager', 'config', 'queries', orm]);
|
||||||
const primaryKey = model.primaryKey;
|
const primaryKey = model.primaryKey;
|
||||||
const id = ctx.params.id;
|
const id = ctx.params.id;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user