From eceede450b871173cc5e548b4c75435720ae4b1c Mon Sep 17 00:00:00 2001 From: Aurelsicoko Date: Mon, 27 Nov 2017 17:27:16 +0100 Subject: [PATCH] Handle plugin model in Content Manager --- .../src/components/LeftMenuLink/index.js | 13 +++- .../components/LeftMenuLinkContainer/index.js | 5 +- .../lib/src/utils/getQueryParameters.js | 4 ++ .../admin/src/components/EditForm/index.js | 22 +++++-- .../src/components/EditFormRelations/index.js | 14 +++- .../admin/src/containers/App/actions.js | 3 +- .../admin/src/containers/App/index.js | 32 +++------ .../admin/src/containers/App/sagas.js | 7 +- .../admin/src/containers/Edit/actions.js | 9 ++- .../admin/src/containers/Edit/index.js | 31 +++++++-- .../admin/src/containers/Edit/sagas.js | 32 +++++++-- .../admin/src/containers/List/actions.js | 6 +- .../admin/src/containers/List/index.js | 45 +++++++------ .../admin/src/containers/List/sagas.js | 21 ++++-- .../admin/src/utils/schema.js | 26 ++++++-- .../controllers/ContentManager.js | 65 ++++++++++++------- .../admin/src/bootstrap.js | 4 +- .../config/roles.json | 8 +-- scripts/test.sh | 4 ++ 19 files changed, 240 insertions(+), 111 deletions(-) create mode 100644 packages/strapi-helper-plugin/lib/src/utils/getQueryParameters.js diff --git a/packages/strapi-admin/admin/src/components/LeftMenuLink/index.js b/packages/strapi-admin/admin/src/components/LeftMenuLink/index.js index 0fb8a45fb1..61a0caf3fb 100755 --- a/packages/strapi-admin/admin/src/components/LeftMenuLink/index.js +++ b/packages/strapi-admin/admin/src/components/LeftMenuLink/index.js @@ -20,7 +20,13 @@ class LeftMenuLink extends React.Component { // eslint-disable-line react/prefer return (
  • - + { - link.plugin = !isEmpty(pluginsObject[link.plugin] ? link.plugin : pluginsObject[current].id); + link.source = current; + link.plugin = !isEmpty(pluginsObject[link.plugin]) ? link.plugin : pluginsObject[current].id; return link; })), @@ -38,7 +39,7 @@ function LeftMenuLinkContainer({ plugins }) {

    {pluginsSections[current].name}

      {sortBy(pluginsSections[current].links, 'label').map(link => - + )}
    diff --git a/packages/strapi-helper-plugin/lib/src/utils/getQueryParameters.js b/packages/strapi-helper-plugin/lib/src/utils/getQueryParameters.js new file mode 100644 index 0000000000..727eb5f8ed --- /dev/null +++ b/packages/strapi-helper-plugin/lib/src/utils/getQueryParameters.js @@ -0,0 +1,4 @@ +export default (location, n) => { + const half = location.split(n + '=')[1]; + return half !== undefined ? decodeURIComponent(half.split('&')[0]) : null; +}; diff --git a/packages/strapi-plugin-content-manager/admin/src/components/EditForm/index.js b/packages/strapi-plugin-content-manager/admin/src/components/EditForm/index.js index 76e81848f6..5e393b300d 100755 --- a/packages/strapi-plugin-content-manager/admin/src/components/EditForm/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/components/EditForm/index.js @@ -12,6 +12,9 @@ import { findIndex, get, omit, isFunction, merge } from 'lodash'; // Components. import Input from 'components/Input'; +// Utils. +import getQueryParameters from 'utils/getQueryParameters'; + // Styles. import styles from './styles.scss'; @@ -42,8 +45,12 @@ class EditForm extends React.Component { } render() { + const source = getQueryParameters(this.props.location.search, 'source'); + const currentSchema = get(this.props.schema, [this.props.currentModelName]) || get(this.props.schema, ['plugins', source, this.props.currentModelName]); + const currentLayout = source === undefined || source === 'content-manager' ? get(this.props.layout, [this.props.currentModelName]) : get(this.props.layout, ['plugins', source, this.props.currentModelName]); + // Remove `id` field - const displayedFields = merge(this.props.layout[this.props.currentModelName], omit(this.props.schema[this.props.currentModelName].fields, 'id')); + const displayedFields = merge(currentLayout, omit(currentSchema.fields, 'id')); // List fields inputs const fields = Object.keys(displayedFields).map(attr => { @@ -53,14 +60,14 @@ class EditForm extends React.Component { const validationsIndex = findIndex(this.props.formValidations, ['name', attr]); const validations = get(this.props.formValidations[validationsIndex], 'validations') || {}; - const layout = Object.keys(get(this.props.layout[this.props.currentModelName], attr, {})).reduce((acc, current) => { - acc[current] = isFunction(this.props.layout[this.props.currentModelName][attr][current]) ? - this.props.layout[this.props.currentModelName][attr][current](this) : - this.props.layout[this.props.currentModelName][attr][current]; + const layout = Object.keys(get(currentLayout, attr, {})).reduce((acc, current) => { + acc[current] = isFunction(currentLayout[attr][current]) ? + currentLayout[attr][current](this) : + currentLayout[attr][current]; return acc; }, {}); - + return ( { + const source = getQueryParameters(this.props.location.search, 'source'); + const currentSchema = get(this.props.schema, [this.props.currentModelName]) || get(this.props.schema, ['plugins', source, this.props.currentModelName]); + + const relations = map(currentSchema.relations, (relation, i) => { switch (relation.nature) { case 'oneToOne': @@ -75,6 +84,9 @@ EditFormRelations.propTypes = { PropTypes.string, ]).isRequired, isNull: PropTypes.bool.isRequired, + location: PropTypes.shape({ + search: PropTypes.string, + }).isRequired, record: PropTypes.oneOfType([ PropTypes.object, PropTypes.bool, diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/App/actions.js b/packages/strapi-plugin-content-manager/admin/src/containers/App/actions.js index 33dfb8f0e7..5a4bbb306c 100755 --- a/packages/strapi-plugin-content-manager/admin/src/containers/App/actions.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/App/actions.js @@ -19,10 +19,11 @@ export function emptyStore() { }; } -export function getModelEntries(modelName) { +export function getModelEntries(modelName, source) { return { type: GET_MODEL_ENTRIES, modelName, + source, }; } diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/App/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/App/index.js index e0f1de0818..371d062f5d 100755 --- a/packages/strapi-plugin-content-manager/admin/src/containers/App/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/App/index.js @@ -14,39 +14,26 @@ import { isEmpty, get } from 'lodash'; import { Switch, Route } from 'react-router-dom'; import injectSaga from 'utils/injectSaga'; +import getQueryParameters from 'utils/getQueryParameters'; import Home from 'containers/Home'; import Edit from 'containers/Edit'; import List from 'containers/List'; import EmptyAttributesView from 'components/EmptyAttributesView'; -import { emptyStore, getModelEntries, loadModels, updateSchema } from './actions'; +import { emptyStore, getModelEntries, loadModels } from './actions'; import { makeSelectLoading, makeSelectModels, makeSelectModelEntries } from './selectors'; import saga from './sagas'; -const tryRequire = (path) => { - try { - return require(`containers/${path}.js`); // eslint-disable-line global-require - } catch (err) { - return null; - } -}; - class App extends React.Component { componentDidMount() { - const config = tryRequire('../../../../config/admin.json'); - - if (!isEmpty(get(config, 'admin.schema'))) { - this.props.updateSchema(config.admin.schema); - } else { - this.props.loadModels(); - } + this.props.loadModels(); const modelName = this.props.location.pathname.split('/')[3]; if (modelName) { - this.props.getModelEntries(modelName); + this.props.getModelEntries(modelName, getQueryParameters(this.props.location.search, 'source')); } } @@ -54,7 +41,7 @@ class App extends React.Component { const currentModelName = this.props.location.pathname.split('/')[3]; if (prevProps.location.pathname !== this.props.location.pathname && currentModelName) { - this.props.getModelEntries(currentModelName); + this.props.getModelEntries(currentModelName, getQueryParameters(this.props.location.search, 'source')); } } @@ -68,9 +55,12 @@ class App extends React.Component { } const currentModelName = this.props.location.pathname.split('/')[3]; + const source = getQueryParameters(this.props.location.search, 'source'); - if (currentModelName && isEmpty(get(this.props.models, [currentModelName, 'attributes']))) { - return ; + if (currentModelName && source && isEmpty(get(this.props.models.plugins, [source, 'models', currentModelName, 'attributes']))) { + if (currentModelName && isEmpty(get(this.props.models.models, [currentModelName, 'attributes']))) { + return ; + } } return ( @@ -101,7 +91,6 @@ App.propTypes = { PropTypes.bool, PropTypes.object, ]).isRequired, - updateSchema: PropTypes.func.isRequired, }; export function mapDispatchToProps(dispatch) { @@ -110,7 +99,6 @@ export function mapDispatchToProps(dispatch) { emptyStore, getModelEntries, loadModels, - updateSchema, }, dispatch, ); diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/App/sagas.js b/packages/strapi-plugin-content-manager/admin/src/containers/App/sagas.js index 2d9abb8fdd..ce68b13674 100755 --- a/packages/strapi-plugin-content-manager/admin/src/containers/App/sagas.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/App/sagas.js @@ -1,4 +1,4 @@ -import { map } from 'lodash'; +import { map, omit } from 'lodash'; import { fork, put, select, call, takeLatest } from 'redux-saga/effects'; import request from 'utils/request'; @@ -10,7 +10,8 @@ import { makeSelectModels } from './selectors'; export function* modelEntriesGet(action) { try { - const requestUrl = `${strapi.backendURL}/content-manager/explorer/${action.modelName}/count`; + const requestUrl = `${strapi.backendURL}/content-manager/explorer/${action.modelName}/count${action.source !== undefined ? `?source=${action.source}`: ''}`; + const response = yield call(request, requestUrl, { method: 'GET' }); yield put(getModelEntriesSucceeded(response.count)); @@ -27,7 +28,7 @@ export const generateMenu = function () { .then(displayedModels => { return [{ name: 'Content Types', - links: map(displayedModels, (model, key) => ({ + links: map(omit(displayedModels, 'plugins'), (model, key) => ({ label: model.labelPlural || model.label || key, destination: key, })), diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/Edit/actions.js b/packages/strapi-plugin-content-manager/admin/src/containers/Edit/actions.js index fd991a11cc..feb5a6db25 100755 --- a/packages/strapi-plugin-content-manager/admin/src/containers/Edit/actions.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/Edit/actions.js @@ -33,24 +33,27 @@ export function cancelChanges() { }; } -export function deleteRecord(id, modelName) { +export function deleteRecord(id, modelName, source) { return { type: DELETE_RECORD, id, modelName, + source, }; } -export function editRecord() { +export function editRecord(source) { return { type: EDIT_RECORD, + source, }; } -export function loadRecord(id) { +export function loadRecord(id, source) { return { type: LOAD_RECORD, id, + source, }; } diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/Edit/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/Edit/index.js index 87bbe28527..71510c9f5c 100755 --- a/packages/strapi-plugin-content-manager/admin/src/containers/Edit/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/Edit/index.js @@ -24,6 +24,7 @@ import PluginHeader from 'components/PluginHeader'; import { makeSelectModels, makeSelectSchema } from 'containers/App/selectors'; // Utils. +import getQueryParameters from 'utils/getQueryParameters'; import injectReducer from 'utils/injectReducer'; import injectSaga from 'utils/injectSaga'; import templateObject from 'utils/templateObject'; @@ -97,15 +98,20 @@ export class Edit extends React.Component { } componentDidMount() { + const source = getQueryParameters(this.props.location.search, 'source'); + const attributes = + get(this.props.models, ['models', this.props.match.params.slug.toLowerCase(), 'attributes']) || + get(this.props.models, ['plugins', source, 'models', this.props.match.params.slug.toLowerCase(), 'attributes']); + this.props.setInitialState(); this.props.setCurrentModelName(this.props.match.params.slug.toLowerCase()); - this.props.setFormValidations(this.props.models[this.props.match.params.slug.toLowerCase()].attributes); - this.props.setForm(this.props.models[this.props.match.params.slug.toLowerCase()].attributes); + this.props.setFormValidations(attributes); + this.props.setForm(attributes); // Detect that the current route is the `create` route or not if (this.props.match.params.id === 'create') { this.props.setIsCreating(); } else { - this.props.loadRecord(this.props.match.params.id); + this.props.loadRecord(this.props.match.params.id, source); } } @@ -127,11 +133,14 @@ export class Edit extends React.Component { } handleChange = (e) => { + const source = getQueryParameters(this.props.location.search, 'source'); + const currentSchema = get(this.props.schema, [this.props.currentModelName]) || get(this.props.schema, ['plugins', source, this.props.currentModelName]); + let formattedValue = e.target.value; if (isObject(e.target.value) && e.target.value._isAMomentObject === true) { formattedValue = moment(e.target.value, 'YYYY-MM-DD HH:mm:ss').format(); - } else if (['float', 'integer', 'bigint'].indexOf(this.props.schema[this.props.currentModelName].fields[e.target.name].type) !== -1) { + } else if (['float', 'integer', 'bigint'].indexOf(currentSchema.fields[e.target.name].type) !== -1) { formattedValue = toNumber(e.target.value); } @@ -140,12 +149,15 @@ export class Edit extends React.Component { handleSubmit = (e) => { e.preventDefault(); + const form = this.props.form.toJS(); map(this.props.record.toJS(), (value, key) => form[key] = value); const formErrors = checkFormValidity(form, this.props.formValidations.toJS()); + const source = getQueryParameters(this.props.location.search, 'source'); + if (isEmpty(formErrors)) { - this.props.editRecord(); + this.props.editRecord(source); } else { this.props.setFormErrors(formErrors); } @@ -156,9 +168,12 @@ export class Edit extends React.Component { return

    Loading...

    ; } + const source = getQueryParameters(this.props.location.search, 'source'); + const currentModel = get(this.props.models, ['models', this.props.currentModelName]) || get(this.props.models, ['plugins', source, 'models', this.props.currentModelName]); + // Plugin header config - const primaryKey = this.props.models[this.props.currentModelName].primaryKey; - const mainField = get(this.props.models, `${this.props.currentModelName}.info.mainField`) || primaryKey; + const primaryKey = currentModel.primaryKey; + const mainField = get(currentModel, 'info.mainField') || primaryKey; const pluginHeaderTitle = this.props.isCreating ? 'New entry' : templateObject({ mainField }, this.props.record.toJS()).mainField; const pluginHeaderDescription = this.props.isCreating ? 'New entry' : `#${this.props.record && this.props.record.get(primaryKey)}`; @@ -192,6 +207,7 @@ export class Edit extends React.Component { didCheckErrors={this.props.didCheckErrors} formValidations={this.props.formValidations.toJS()} layout={this.layout} + location={this.props.location} /> @@ -204,6 +220,7 @@ export class Edit extends React.Component { setRecordAttribute={this.props.setRecordAttribute} isNull={this.props.isRelationComponentNull} toggleNull={this.props.toggleNull} + location={this.props.location} /> diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/Edit/sagas.js b/packages/strapi-plugin-content-manager/admin/src/containers/Edit/sagas.js index e870f816a6..ca0fde4a50 100755 --- a/packages/strapi-plugin-content-manager/admin/src/containers/Edit/sagas.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/Edit/sagas.js @@ -19,15 +19,21 @@ import { makeSelectIsCreating, } from './selectors'; -export function* getRecord(params) { +export function* getRecord(action) { const currentModelName = yield select(makeSelectCurrentModelName()); + const params = {}; + + if (action.source !== undefined) { + params.source = action.source; + } try { - const requestUrl = `${strapi.backendURL}/content-manager/explorer/${currentModelName}/${params.id}`; + const requestUrl = `${strapi.backendURL}/content-manager/explorer/${currentModelName}/${action.id}`; // Call our request helper (see 'utils/request') const response = yield request(requestUrl, { method: 'GET', + params, }); yield put(recordLoaded(response)); @@ -36,7 +42,7 @@ export function* getRecord(params) { } } -export function* editRecord() { +export function* editRecord(action) { const currentModelName = yield select(makeSelectCurrentModelName()); const record = yield select(makeSelectRecord()); const recordJSON = record.toJSON(); @@ -49,6 +55,11 @@ export function* editRecord() { const isCreating = yield select(makeSelectIsCreating()); const id = isCreating ? '' : recordCleaned.id; + const params = {}; + + if (action.source !== undefined) { + params.source = action.source; + } try { const requestUrl = `${strapi.backendURL}/content-manager/explorer/${currentModelName}/${id}`; @@ -57,6 +68,7 @@ export function* editRecord() { yield call(request, requestUrl, { method: isCreating ? 'POST' : 'PUT', body: recordCleaned, + params, }); yield put(recordEdited()); @@ -67,21 +79,31 @@ export function* editRecord() { } } -export function* deleteRecord({ id, modelName }) { +export function* deleteRecord({ id, modelName, source }) { function* httpCall(id, modelName) { try { const requestUrl = `${strapi.backendURL}/content-manager/explorer/${modelName}/${id}`; + const params = {}; + if (action.source !== undefined) { + params.source = action.source; + } // Call our request helper (see 'utils/request') yield call(request, requestUrl, { method: 'DELETE', + params, }); yield put(recordDeleted(id)); strapi.notification.success('content-manager.success.record.delete'); // Redirect to the list page. - router.push(`/plugins/content-manager/${modelName}`); + router.push({ + pathname: `/plugins/content-manager/${modelName}`, + state: { + source, + }, + }); } catch (err) { yield put(recordDeleteError()); strapi.notification.error('content-manager.error.record.delete'); diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/List/actions.js b/packages/strapi-plugin-content-manager/admin/src/containers/List/actions.js index b5671067f0..0daef010c6 100755 --- a/packages/strapi-plugin-content-manager/admin/src/containers/List/actions.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/List/actions.js @@ -42,15 +42,17 @@ export function changeSort(sort) { }; } -export function loadCount() { +export function loadCount(source) { return { type: LOAD_COUNT, + source, }; } -export function loadRecords() { +export function loadRecords(source) { return { type: LOAD_RECORDS, + source, }; } diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/List/index.js b/packages/strapi-plugin-content-manager/admin/src/containers/List/index.js index f1d39a5c90..8f44c81d4d 100755 --- a/packages/strapi-plugin-content-manager/admin/src/containers/List/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/List/index.js @@ -9,7 +9,7 @@ import { connect } from 'react-redux'; import { bindActionCreators, compose } from 'redux'; import { createStructuredSelector } from 'reselect'; import PropTypes from 'prop-types'; -import { isEmpty, isUndefined, map, replace, split } from 'lodash'; +import { isEmpty, isUndefined, map, get, toInteger } from 'lodash'; import { router } from 'app'; // Selectors. @@ -24,6 +24,9 @@ import PopUpWarning from 'components/PopUpWarning'; import injectReducer from 'utils/injectReducer'; import injectSaga from 'utils/injectSaga'; +// Utils +import getQueryParameters from 'utils/getQueryParameters'; + // Actions. import { deleteRecord, @@ -88,24 +91,24 @@ export class List extends React.Component { // Set current model name this.props.setCurrentModelName(slug.toLowerCase()); - const searchParams = split(replace(props.location.search, '?', ''), '&'); + const source = getQueryParameters(props.location.search, 'source'); - const sort = isEmpty(props.location.search) ? - this.props.models[slug.toLowerCase()].primaryKey || 'id' : - replace(searchParams[2], 'sort=', ''); + const sort = (isEmpty(props.location.search) ? + get(this.props.models, ['models', slug.toLowerCase(), 'primaryKey']) || get(this.props.models.plugins, [source, 'models', slug.toLowerCase(), 'primaryKey']) : + getQueryParameters('sort')) || 'id'; if (!isEmpty(props.location.search)) { - this.props.changePage(parseInt(replace(searchParams[0], 'page=', ''), 10)); - this.props.changeLimit(parseInt(replace(searchParams[1], 'limit=', ''), 10)); + this.props.changePage(toInteger(getQueryParameters('page'))); + this.props.changeLimit(toInteger(getQueryParameters('limit'))); } this.props.changeSort(sort); // Load records - this.props.loadRecords(); + this.props.loadRecords(source); // Get the records count - this.props.loadCount(); + this.props.loadCount(source); // Define the `create` route url this.addRoute = `${this.props.match.path.replace(':slug', slug)}/create`; @@ -139,7 +142,9 @@ export class List extends React.Component { e.preventDefault(); e.stopPropagation(); - this.props.deleteRecord(this.state.target, this.props.currentModelName); + const source = getQueryParameters(this.props.location.search, 'source'); + + this.props.deleteRecord(this.state.target, this.props.currentModelName, source); this.setState({ showWarning: false }); } @@ -156,18 +161,20 @@ export class List extends React.Component { } render() { - if (!this.props.currentModelName || !this.props.schema) { + // Detect current model structure from models list + const source = getQueryParameters(this.props.location.search, 'source'); + const currentModel = get(this.props.models, ['models', this.props.currentModelName]) || get(this.props.models, ['plugins', source, 'models', this.props.currentModelName]); + const currentSchema = get(this.props.schema, [this.props.currentModelName]) || get(this.props.schema, ['plugins', source, this.props.currentModelName]); + + if (!this.props.currentModelName || !currentSchema) { return
    ; } - // Detect current model structure from models list - const currentModel = this.props.models[this.props.currentModelName]; - // Define table headers - const tableHeaders = map(this.props.schema[this.props.currentModelName].list, (value) => ({ + const tableHeaders = map(currentSchema.list, (value) => ({ name: value, - label: this.props.schema[this.props.currentModelName].fields[value].label, - type: this.props.schema[this.props.currentModelName].fields[value].type, + label: currentSchema.fields[value].label, + type: currentSchema.fields[value].type, })); tableHeaders.splice(0, 0, { name: currentModel.primaryKey || 'id', label: 'Id', type: 'string' }); @@ -183,12 +190,12 @@ export class List extends React.Component { history={this.props.history} primaryKey={currentModel.primaryKey || 'id'} handleDelete={this.toggleModalWarning} - redirectUrl={`?redirectUrl=/plugins/content-manager/${this.props.currentModelName.toLowerCase()}/?page=${this.props.currentPage}&limit=${this.props.limit}&sort=${this.props.sort}`} + redirectUrl={`?redirectUrl=/plugins/content-manager/${this.props.currentModelName.toLowerCase()}/?page=${this.props.currentPage}&limit=${this.props.limit}&sort=${this.props.sort}&source=${source}`} /> ); // Plugin header config - const pluginHeaderTitle = this.props.schema[this.props.currentModelName].label || 'Content Manager'; + const pluginHeaderTitle = currentSchema.label || 'Content Manager'; // Define plugin header actions const pluginHeaderActions = [ diff --git a/packages/strapi-plugin-content-manager/admin/src/containers/List/sagas.js b/packages/strapi-plugin-content-manager/admin/src/containers/List/sagas.js index b4776238d0..910b3e74eb 100755 --- a/packages/strapi-plugin-content-manager/admin/src/containers/List/sagas.js +++ b/packages/strapi-plugin-content-manager/admin/src/containers/List/sagas.js @@ -25,7 +25,7 @@ import { makeSelectSort, } from './selectors'; -export function* getRecords() { +export function* getRecords(action) { const currentModel = yield select(makeSelectCurrentModelName()); const limit = yield select(makeSelectLimit()); const currentPage = yield select(makeSelectCurrentPage()); @@ -40,6 +40,10 @@ export function* getRecords() { sort, }; + if (action.source !== undefined) { + params.source = action.source; + } + try { const requestUrl = `${strapi.backendURL}/content-manager/explorer/${currentModel}`; // Call our request helper (see 'utils/request') @@ -54,14 +58,19 @@ export function* getRecords() { } } -export function* getCount() { +export function* getCount(action) { const currentModel = yield select(makeSelectCurrentModelName()); + const params = {}; + + if (action.source !== undefined) { + params.source = action.source; + } try { - const response = yield call( - request, - `${strapi.backendURL}/content-manager/explorer/${currentModel}/count`, - ); + const response = yield call(request,`${strapi.backendURL}/content-manager/explorer/${currentModel}/count`, { + method: 'GET', + params, + }); yield put(loadedCount(response.count)); } catch (err) { diff --git a/packages/strapi-plugin-content-manager/admin/src/utils/schema.js b/packages/strapi-plugin-content-manager/admin/src/utils/schema.js index a3a0fdb5e0..b6f84d3454 100755 --- a/packages/strapi-plugin-content-manager/admin/src/utils/schema.js +++ b/packages/strapi-plugin-content-manager/admin/src/utils/schema.js @@ -1,4 +1,4 @@ -import { forEach, upperFirst, mapValues, pickBy, slice, findKey, keys, get } from 'lodash'; +import { forEach, upperFirst, mapValues, pickBy, slice, findKey, keys, get, set } from 'lodash'; import pluralize from 'pluralize'; /** @@ -7,11 +7,13 @@ import pluralize from 'pluralize'; * * @param models */ -const generateSchema = (models) => { +const generateSchema = (responses) => { // Init `schema` object - const schema = {}; + const schema = { + plugins: {}, + }; - forEach(models, (model, name) => { + const buildSchema = (model, name, plugin = false) => { // Model data const schemaModel = { label: upperFirst(name), @@ -46,8 +48,24 @@ const generateSchema = (models) => { }, {}); } + if (plugin) { + return set(schema.plugins, `${plugin}.${name}`, schemaModel); + } + // Set the formatted model to the schema schema[name] = schemaModel; + }; + + // Generate schema for plugins. + forEach(responses.plugins, (plugin, pluginName) => { + forEach(plugin.models, (model, name) => { + buildSchema(model, name, pluginName); + }); + }); + + // Generate schema for models. + forEach(responses.models, (model, name) => { + buildSchema(model, name); }); return schema; diff --git a/packages/strapi-plugin-content-manager/controllers/ContentManager.js b/packages/strapi-plugin-content-manager/controllers/ContentManager.js index f5fcb6fe9d..8481040c27 100755 --- a/packages/strapi-plugin-content-manager/controllers/ContentManager.js +++ b/packages/strapi-plugin-content-manager/controllers/ContentManager.js @@ -8,28 +8,37 @@ const _ = require('lodash'); module.exports = { models: async ctx => { - ctx.body = _.mapValues(strapi.models, model => - _.pick(model, [ - 'info', - 'connection', - 'collectionName', - 'attributes', - 'identity', - 'globalId', - 'globalName', - 'orm', - 'loadedModel', - 'primaryKey', - 'associations' - ]) - ); + const pickData = (model) => _.pick(model, [ + 'info', + 'connection', + 'collectionName', + 'attributes', + 'identity', + 'globalId', + 'globalName', + 'orm', + 'loadedModel', + 'primaryKey', + 'associations' + ]); + + ctx.body = { + models: _.mapValues(strapi.models, pickData), + plugins: Object.keys(strapi.plugins).reduce((acc, current) => { + acc[current] = { + models: _.mapValues(strapi.plugins[current].models, pickData) + }; + + return acc; + }, {}) + }; }, find: async ctx => { - const { limit, skip = 0, sort, query, queryAttribute } = ctx.request.query; + const { limit, skip = 0, sort, query, queryAttribute, source } = ctx.request.query; // Find entries using `queries` system - const entries = await strapi.query(ctx.params.model).find({ + const entries = await strapi.query(ctx.params.model, source).find({ limit, skip, sort, @@ -41,8 +50,10 @@ module.exports = { }, count: async ctx => { + const { source } = ctx.request.query; + // Count using `queries` system - const count = await strapi.query(ctx.params.model).count(); + const count = await strapi.query(ctx.params.model, source).count(); ctx.body = { count: _.isNumber(count) ? count : _.toNumber(count) @@ -50,8 +61,10 @@ module.exports = { }, findOne: async ctx => { + const { source } = ctx.request.query; + // Find an entry using `queries` system - const entry = await strapi.query(ctx.params.model).findOne({ + const entry = await strapi.query(ctx.params.model, source).findOne({ id: ctx.params.id }); @@ -64,8 +77,10 @@ module.exports = { }, create: async ctx => { + const { source } = ctx.request.query; + // Create an entry using `queries` system - const entryCreated = await strapi.query(ctx.params.model).create({ + const entryCreated = await strapi.query(ctx.params.model, source).create({ values: ctx.request.body }); @@ -73,8 +88,10 @@ module.exports = { }, update: async ctx => { + const { source } = ctx.request.query; + // Add current model to the flow of updates. - const entry = strapi.query(ctx.params.model).update({ + const entry = strapi.query(ctx.params.model, source).update({ id: ctx.params.id, values: ctx.request.body }); @@ -84,7 +101,9 @@ module.exports = { }, delete: async ctx => { + const { source } = ctx.request.query; const params = ctx.params; + const response = await strapi.query(params.model).findOne({ id: params.id }); @@ -102,11 +121,11 @@ module.exports = { if (!_.isEmpty(params.values)) { // Run update to remove all relationships. - await strapi.query(params.model).update(params); + await strapi.query(params.model, source).update(params); } // Delete an entry using `queries` system - const entryDeleted = await strapi.query(params.model).delete({ + const entryDeleted = await strapi.query(params.model, source).delete({ id: params.id }); diff --git a/packages/strapi-plugin-users-permissions/admin/src/bootstrap.js b/packages/strapi-plugin-users-permissions/admin/src/bootstrap.js index 7b02cb89b0..8807e96c4c 100644 --- a/packages/strapi-plugin-users-permissions/admin/src/bootstrap.js +++ b/packages/strapi-plugin-users-permissions/admin/src/bootstrap.js @@ -11,9 +11,9 @@ const bootstrap = (plugin) => new Promise((resolve, reject) => { links: [{ label: 'Users', destination: 'user', - plugin: 'content-manager' + plugin: 'content-manager', }], - name: 'Content Types' + name: 'Content Types', }); return resolve(plugin); diff --git a/packages/strapi-plugin-users-permissions/config/roles.json b/packages/strapi-plugin-users-permissions/config/roles.json index 2e22c65787..afd9f7f7d9 100644 --- a/packages/strapi-plugin-users-permissions/config/roles.json +++ b/packages/strapi-plugin-users-permissions/config/roles.json @@ -6,6 +6,10 @@ "content-manager": { "controllers": { "contentmanager": { + "identity": { + "enabled": false, + "policy": "" + }, "models": { "enabled": false, "policy": "" @@ -33,10 +37,6 @@ "delete": { "enabled": false, "policy": "" - }, - "identity": { - "enabled": false, - "policy": "" } } } diff --git a/scripts/test.sh b/scripts/test.sh index 178a61f44a..a70b27d652 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -22,3 +22,7 @@ npm run test # Test `strapi-plugin-content-type-builder` cd ../strapi-plugin-content-type-builder npm run test + +# Test `strapi-plugin-content-type-builder` +cd ../strapi-plugin-users-permissions +npm run test