mirror of
https://github.com/strapi/strapi.git
synced 2025-08-30 19:56:05 +00:00
Merge branch 'master' into allow-new-input
This commit is contained in:
commit
06555cf4d4
@ -139,14 +139,14 @@ In order to do so, you'll need to allow access to other users (identified as 'Gu
|
|||||||
|
|
||||||
To retrieve the list of products, use the `GET /your-content-type` route.
|
To retrieve the list of products, use the `GET /your-content-type` route.
|
||||||
|
|
||||||
Generated APIs provide a handy way to filter and order queries. In that way, ordering products by price is as easy as `GET http://localhost:1337/product?_order=price:asc`. For more informations, read the [filters documentation](../guides/filters.md)
|
Generated APIs provide a handy way to filter and order queries. In that way, ordering products by price is as easy as `GET http://localhost:1337/product?_sort=price:asc`. For more informations, read the [filters documentation](../guides/filters.md)
|
||||||
|
|
||||||
Here is an example using jQuery.
|
Here is an example using jQuery.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url: 'http://localhost:1337/product?_order=price:asc', // Order by price.
|
url: 'http://localhost:1337/product?_sort=price:asc', // Order by price.
|
||||||
done: function(products) {
|
done: function(products) {
|
||||||
console.log('Well done, here is the list of products: ', products);
|
console.log('Well done, here is the list of products: ', products);
|
||||||
},
|
},
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, FormattedMessage } from 'react-intl';
|
import { defineMessages, FormattedMessage } from 'react-intl';
|
||||||
|
import { PropTypes } from 'prop-types';
|
||||||
|
|
||||||
import LocaleToggle from 'containers/LocaleToggle';
|
import LocaleToggle from 'containers/LocaleToggle';
|
||||||
|
|
||||||
@ -13,15 +14,19 @@ import styles from './styles.scss';
|
|||||||
import messages from './messages.json';
|
import messages from './messages.json';
|
||||||
defineMessages(messages);
|
defineMessages(messages);
|
||||||
|
|
||||||
class LeftMenuFooter extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
function LeftMenuFooter({ version }) { // eslint-disable-line react/prefer-stateless-function
|
||||||
render() {
|
return (
|
||||||
return (
|
<div className={styles.leftMenuFooter}>
|
||||||
<div className={styles.leftMenuFooter}>
|
<FormattedMessage {...messages.poweredBy} />
|
||||||
<FormattedMessage {...messages.poweredBy} /> <a href="http://strapi.io" target="_blank">Strapi</a>
|
<a href="http://strapi.io" target="_blank"> Strapi</a>
|
||||||
<LocaleToggle />
|
<span> (v{version})</span>
|
||||||
</div>
|
<LocaleToggle />
|
||||||
);
|
</div>
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LeftMenuFooter.propTypes = {
|
||||||
|
version: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
export default LeftMenuFooter;
|
export default LeftMenuFooter;
|
||||||
|
File diff suppressed because one or more lines are too long
@ -8,6 +8,7 @@ import {
|
|||||||
GET_GA_STATUS_SUCCEEDED,
|
GET_GA_STATUS_SUCCEEDED,
|
||||||
GET_LAYOUT,
|
GET_LAYOUT,
|
||||||
GET_LAYOUT_SUCCEEDED,
|
GET_LAYOUT_SUCCEEDED,
|
||||||
|
GET_STRAPI_VERSION_SUCCEEDED,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
|
|
||||||
export function getGaStatus() {
|
export function getGaStatus() {
|
||||||
@ -35,3 +36,10 @@ export function getLayoutSucceeded(layout) {
|
|||||||
layout,
|
layout,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getStrapiVersionSucceeded(strapiVersion) {
|
||||||
|
return {
|
||||||
|
type: GET_STRAPI_VERSION_SUCCEEDED,
|
||||||
|
strapiVersion,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -8,3 +8,4 @@ export const GET_GA_STATUS = 'app/Admin/GET_GA_STATUS';
|
|||||||
export const GET_GA_STATUS_SUCCEEDED = 'app/Admin/GET_GA_STATUS_SUCCEEDED';
|
export const GET_GA_STATUS_SUCCEEDED = 'app/Admin/GET_GA_STATUS_SUCCEEDED';
|
||||||
export const GET_LAYOUT = 'app/Admin/GET_LAYOUT';
|
export const GET_LAYOUT = 'app/Admin/GET_LAYOUT';
|
||||||
export const GET_LAYOUT_SUCCEEDED = 'app/Admin/GET_LAYOUT_SUCCEEDED';
|
export const GET_LAYOUT_SUCCEEDED = 'app/Admin/GET_LAYOUT_SUCCEEDED';
|
||||||
|
export const GET_STRAPI_VERSION_SUCCEEDED = 'app/Admin/GET_STRAPI_VERSION_SUCCEEDED';
|
||||||
|
@ -137,13 +137,19 @@ export class AdminPage extends React.Component { // eslint-disable-line react/pr
|
|||||||
showLeftMenu = () => !includes(this.props.location.pathname, 'users-permissions/auth/');
|
showLeftMenu = () => !includes(this.props.location.pathname, 'users-permissions/auth/');
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const leftMenu = this.showLeftMenu() ? <LeftMenu plugins={this.props.plugins} layout={this.props.adminPage.layout} /> : '';
|
const { adminPage } = this.props;
|
||||||
const header = this.showLeftMenu() ? <Header /> : '';
|
const header = this.showLeftMenu() ? <Header /> : '';
|
||||||
const style = this.showLeftMenu() ? {} : { width: '100%' };
|
const style = this.showLeftMenu() ? {} : { width: '100%' };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.adminPage}>
|
<div className={styles.adminPage}>
|
||||||
{leftMenu}
|
{this.showLeftMenu() && (
|
||||||
|
<LeftMenu
|
||||||
|
plugins={this.props.plugins}
|
||||||
|
layout={adminPage.layout}
|
||||||
|
version={adminPage.strapiVersion}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{ auth.getToken() && this.props.hasUserPlugin && this.isUrlProtected(this.props) ? (
|
{ auth.getToken() && this.props.hasUserPlugin && this.isUrlProtected(this.props) ? (
|
||||||
<Logout />
|
<Logout />
|
||||||
) : ''}
|
) : ''}
|
||||||
|
@ -6,11 +6,16 @@
|
|||||||
|
|
||||||
import { fromJS, Map } from 'immutable';
|
import { fromJS, Map } from 'immutable';
|
||||||
|
|
||||||
import { GET_GA_STATUS_SUCCEEDED, GET_LAYOUT_SUCCEEDED } from './constants';
|
import {
|
||||||
|
GET_GA_STATUS_SUCCEEDED,
|
||||||
|
GET_LAYOUT_SUCCEEDED,
|
||||||
|
GET_STRAPI_VERSION_SUCCEEDED,
|
||||||
|
} from './constants';
|
||||||
|
|
||||||
const initialState = fromJS({
|
const initialState = fromJS({
|
||||||
allowGa: true,
|
allowGa: true,
|
||||||
layout: Map({}),
|
layout: Map({}),
|
||||||
|
strapiVersion: '3',
|
||||||
});
|
});
|
||||||
|
|
||||||
function adminPageReducer(state = initialState, action) {
|
function adminPageReducer(state = initialState, action) {
|
||||||
@ -19,6 +24,8 @@ function adminPageReducer(state = initialState, action) {
|
|||||||
return state.update('allowGa', () => action.allowGa);
|
return state.update('allowGa', () => action.allowGa);
|
||||||
case GET_LAYOUT_SUCCEEDED:
|
case GET_LAYOUT_SUCCEEDED:
|
||||||
return state.update('layout', () => Map(action.layout));
|
return state.update('layout', () => Map(action.layout));
|
||||||
|
case GET_STRAPI_VERSION_SUCCEEDED:
|
||||||
|
return state.update('strapiVersion', () => action.strapiVersion);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,23 @@
|
|||||||
|
import { take } from 'lodash';
|
||||||
import { fork, call, put, takeLatest } from 'redux-saga/effects';
|
import { fork, call, put, takeLatest } from 'redux-saga/effects';
|
||||||
import request from 'utils/request';
|
import request from 'utils/request';
|
||||||
|
|
||||||
import { getGaStatusSucceeded, getLayoutSucceeded } from './actions';
|
import {
|
||||||
|
getGaStatusSucceeded,
|
||||||
|
getLayoutSucceeded,
|
||||||
|
getStrapiVersionSucceeded,
|
||||||
|
} from './actions';
|
||||||
import { GET_GA_STATUS, GET_LAYOUT } from './constants';
|
import { GET_GA_STATUS, GET_LAYOUT } from './constants';
|
||||||
|
|
||||||
function* getGaStatus() {
|
function* getGaStatus() {
|
||||||
try {
|
try {
|
||||||
const response = yield call(request, '/admin/gaConfig', { method: 'GET' });
|
const [allowGa, strapiVersion] = yield [
|
||||||
yield put(getGaStatusSucceeded(response.allowGa));
|
call(request, '/admin/gaConfig', { method: 'GET' }),
|
||||||
|
call(request, '/admin/strapiVersion', { method: 'GET' }),
|
||||||
|
];
|
||||||
|
yield put(getGaStatusSucceeded(allowGa));
|
||||||
|
const version = take(`${strapiVersion.strapiVersion.split('.')[0]}${strapiVersion.strapiVersion.split('alpha')[1]}`, 4).join('');
|
||||||
|
yield put(getStrapiVersionSucceeded(version));
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
strapi.notification.error('notification.error');
|
strapi.notification.error('notification.error');
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,21 @@ export class LeftMenu extends React.Component { // eslint-disable-line react/pre
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className={styles.leftMenu}>
|
<div className={styles.leftMenu}>
|
||||||
<LeftMenuHeader></LeftMenuHeader>
|
<LeftMenuHeader />
|
||||||
<LeftMenuLinkContainer {...this.props}></LeftMenuLinkContainer>
|
<LeftMenuLinkContainer {...this.props} />
|
||||||
<LeftMenuFooter plugins={this.props.plugins}></LeftMenuFooter>
|
<LeftMenuFooter plugins={this.props.plugins} version={this.props.version} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LeftMenu.defaultProps = {
|
||||||
|
version: '3',
|
||||||
|
};
|
||||||
|
|
||||||
LeftMenu.propTypes = {
|
LeftMenu.propTypes = {
|
||||||
plugins: PropTypes.object.isRequired,
|
plugins: PropTypes.object.isRequired,
|
||||||
|
version: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
|
@ -20,6 +20,12 @@
|
|||||||
"handler": "Admin.getGaConfig",
|
"handler": "Admin.getGaConfig",
|
||||||
"policies": []
|
"policies": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/strapiVersion",
|
||||||
|
"handler": "Admin.getStrapiVersion",
|
||||||
|
"policies": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"path": "/layout",
|
"path": "/layout",
|
||||||
|
@ -17,6 +17,15 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getStrapiVersion: async ctx => {
|
||||||
|
try {
|
||||||
|
const strapiVersion = _.get(strapi.config, 'info.strapi', null);
|
||||||
|
return ctx.send({ strapiVersion });
|
||||||
|
} catch(err) {
|
||||||
|
return ctx.badRequest(null, [{ messages: [{ id: 'The version is not available' }] }]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
getGaConfig: async ctx => {
|
getGaConfig: async ctx => {
|
||||||
try {
|
try {
|
||||||
const allowGa = _.get(strapi.config, 'info.customs.allowGa', true);
|
const allowGa = _.get(strapi.config, 'info.customs.allowGa', true);
|
||||||
|
@ -132,6 +132,9 @@ module.exports = (options) => ({
|
|||||||
require.resolve('babel-plugin-transform-react-remove-prop-types'),
|
require.resolve('babel-plugin-transform-react-remove-prop-types'),
|
||||||
require.resolve('babel-plugin-transform-react-constant-elements'),
|
require.resolve('babel-plugin-transform-react-constant-elements'),
|
||||||
require.resolve('babel-plugin-transform-react-inline-elements'),
|
require.resolve('babel-plugin-transform-react-inline-elements'),
|
||||||
|
require.resolve('babel-plugin-transform-es2015-destructuring'),
|
||||||
|
require.resolve('babel-plugin-transform-es2015-parameters'),
|
||||||
|
require.resolve('babel-plugin-transform-object-rest-spread'),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
|
@ -34,6 +34,9 @@
|
|||||||
"babel-eslint": "^7.2.3",
|
"babel-eslint": "^7.2.3",
|
||||||
"babel-loader": "^7.1.1",
|
"babel-loader": "^7.1.1",
|
||||||
"babel-plugin-istanbul": "^4.1.5",
|
"babel-plugin-istanbul": "^4.1.5",
|
||||||
|
"babel-plugin-transform-es2015-destructuring": "^6.23.0",
|
||||||
|
"babel-plugin-transform-es2015-parameters": "^6.24.1",
|
||||||
|
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||||
"babel-plugin-transform-react-constant-elements": "^6.23.0",
|
"babel-plugin-transform-react-constant-elements": "^6.23.0",
|
||||||
"babel-plugin-transform-react-inline-elements": "^6.22.0",
|
"babel-plugin-transform-react-inline-elements": "^6.22.0",
|
||||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.8",
|
"babel-plugin-transform-react-remove-prop-types": "^0.4.8",
|
||||||
|
@ -30,8 +30,9 @@ function EditRelations(props) {
|
|||||||
{(message) => <h3>{message}</h3>}
|
{(message) => <h3>{message}</h3>}
|
||||||
</FormattedMessage>
|
</FormattedMessage>
|
||||||
{map(filterRelationsUpload(props.schema.relations), (relation, key) => {
|
{map(filterRelationsUpload(props.schema.relations), (relation, key) => {
|
||||||
|
if (relation.nature.toLowerCase().includes('morph') && relation[key]) return '';
|
||||||
|
|
||||||
const Select = ['oneWay', 'oneToOne', 'manyToOne'].includes(relation.nature) && relation.dominant ? SelectOne : SelectMany;
|
const Select = ['oneWay', 'oneToOne', 'manyToOne', 'oneToManyMorph', 'oneToOneMorph'].includes(relation.nature) && relation.dominant ? SelectOne : SelectMany;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
|
@ -223,7 +223,8 @@ export class EditPage extends React.Component {
|
|||||||
|
|
||||||
isRelationComponentNull = () => (
|
isRelationComponentNull = () => (
|
||||||
Object.keys(get(this.getSchema(), 'relations', {})).filter(relation => (
|
Object.keys(get(this.getSchema(), 'relations', {})).filter(relation => (
|
||||||
get(this.getSchema(), ['relations', relation, 'plugin']) !== 'upload'
|
get(this.getSchema(), ['relations', relation, 'plugin']) !== 'upload' &&
|
||||||
|
(!get(this.getSchema(), ['relations', relation, 'nature'], '').toLowerCase().includes('morph') || !get(this.getSchema(), ['relations', relation, relation]))
|
||||||
)).length === 0
|
)).length === 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,13 +14,14 @@ module.exports = {
|
|||||||
.count());
|
.count());
|
||||||
},
|
},
|
||||||
|
|
||||||
findOne: async function (params, populate) {
|
findOne: async function (params, populate, raw = true) {
|
||||||
return this
|
const query = this
|
||||||
.findOne({
|
.findOne({
|
||||||
[this.primaryKey]: params[this.primaryKey] || params.id
|
[this.primaryKey]: params[this.primaryKey] || params.id
|
||||||
})
|
})
|
||||||
.populate(populate || this.associations.map(x => x.alias).join(' '))
|
.populate(populate || this.associations.map(x => x.alias).join(' '));
|
||||||
.lean();
|
|
||||||
|
return raw ? query.lean() : query;
|
||||||
},
|
},
|
||||||
|
|
||||||
create: async function (params) {
|
create: async function (params) {
|
||||||
@ -300,18 +301,18 @@ module.exports = {
|
|||||||
However the upload doesn't need this method. It only uses the `removeRelationMorph`.
|
However the upload doesn't need this method. It only uses the `removeRelationMorph`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const entry = await module.exports.findOne.call(this, params, []);
|
const entry = (await module.exports.findOne.call(this, params, [], false)).toJSON();
|
||||||
const value = entry[params.alias] || [];
|
const value = [];
|
||||||
|
|
||||||
// Retrieve association.
|
// Retrieve association.
|
||||||
const association = this.associations.find(association => association.via === params.alias)[0];
|
const association = this.associations.find(association => association.alias === params.alias);
|
||||||
|
|
||||||
if (!association) {
|
if (!association) {
|
||||||
throw Error(`Impossible to create relationship with ${params.ref} (${params.refId})`);
|
throw Error(`Impossible to create relationship with ${params.ref} (${params.refId})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve if the association is already existing.
|
// Resolve if the association is already existing.
|
||||||
const isExisting = entry[params.alias].find(obj => {
|
const isExisting = value.find(obj => {
|
||||||
if (obj.kind === params.ref && obj.ref.toString() === params.refId.toString() && obj.field === params.field) {
|
if (obj.kind === params.ref && obj.ref.toString() === params.refId.toString() && obj.field === params.field) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -326,9 +327,10 @@ module.exports = {
|
|||||||
|
|
||||||
// Push new relation to the association array.
|
// Push new relation to the association array.
|
||||||
value.push({
|
value.push({
|
||||||
ref: params.refId,
|
ref: params.ref,
|
||||||
|
refId: params.refId,
|
||||||
kind: params.ref,
|
kind: params.ref,
|
||||||
field: association.filter
|
field: params.field
|
||||||
});
|
});
|
||||||
|
|
||||||
entry[params.alias] = value;
|
entry[params.alias] = value;
|
||||||
|
@ -59,7 +59,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Then, request plugin upload.
|
// Then, request plugin upload.
|
||||||
if (strapi.plugins.upload) {
|
if (strapi.plugins.upload && !_.isEmpty(values.files)) {
|
||||||
// Upload new files and attach them to this entity.
|
// Upload new files and attach them to this entity.
|
||||||
await strapi.plugins.upload.services.upload.uploadToEntity({
|
await strapi.plugins.upload.services.upload.uploadToEntity({
|
||||||
id: entry.id || entry._id,
|
id: entry.id || entry._id,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user