mirror of
https://github.com/strapi/strapi.git
synced 2025-11-12 08:08:05 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
f2cb6d7af8
@ -13,6 +13,12 @@ This will create two files located at `./api/user/models`:
|
|||||||
|
|
||||||
> Note: when you create a new API using the CLI (`strapi generate:api <name>`), a model is automatically created.
|
> Note: when you create a new API using the CLI (`strapi generate:api <name>`), a model is automatically created.
|
||||||
|
|
||||||
|
## Model Information
|
||||||
|
The info key on the model-json states information about the model. This information is used in the admin interface, when showing the model.
|
||||||
|
- `name`: The name of the model, as shown in admin interface.
|
||||||
|
- `description`: The description of the model.
|
||||||
|
- `mainField`: Determines which model-attribute is shown when displaying the model.
|
||||||
|
|
||||||
## Define the attributes
|
## Define the attributes
|
||||||
|
|
||||||
The following types are currently available:
|
The following types are currently available:
|
||||||
@ -59,7 +65,8 @@ To improve the Developer eXperience when developing or using the administration
|
|||||||
"connection": "default",
|
"connection": "default",
|
||||||
"info": {
|
"info": {
|
||||||
"name": "user",
|
"name": "user",
|
||||||
"description": "This represents the User Model"
|
"description": "This represents the User Model",
|
||||||
|
"mainField": "email"
|
||||||
},
|
},
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"firstname": {
|
"firstname": {
|
||||||
|
|||||||
@ -10,6 +10,8 @@ To setup the development environment please **follow the instructions below:**
|
|||||||
2. Clone it to your computer `git clone git@github.com:strapi/strapi.git`.
|
2. Clone it to your computer `git clone git@github.com:strapi/strapi.git`.
|
||||||
3. Run `npm run setup` at the root of the directory.
|
3. Run `npm run setup` at the root of the directory.
|
||||||
|
|
||||||
|
> You can run `npm run setup:build` to build the plugins' admin (the setup time will be longer)
|
||||||
|
|
||||||
> Note: If the installation failed, please remove the global packages related to Strapi. The command `npm ls strapi` will help you to find where your packages are installed globally.
|
> Note: If the installation failed, please remove the global packages related to Strapi. The command `npm ls strapi` will help you to find where your packages are installed globally.
|
||||||
|
|
||||||
## Plugin development Setup
|
## Plugin development Setup
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
"release": "npm run clean:all && npm install && npm run createsymlinkdependencies && lerna exec --concurrency 1 -- npm install && npm run removesymlinkdependencies && node ./scripts/publish.js $TAG",
|
"release": "npm run clean:all && npm install && npm run createsymlinkdependencies && lerna exec --concurrency 1 -- npm install && npm run removesymlinkdependencies && node ./scripts/publish.js $TAG",
|
||||||
"createsymlinkdependencies": "node ./scripts/createSymlinkDependencies.js",
|
"createsymlinkdependencies": "node ./scripts/createSymlinkDependencies.js",
|
||||||
"removesymlinkdependencies": "node ./scripts/removeSymlinkDependencies.js",
|
"removesymlinkdependencies": "node ./scripts/removeSymlinkDependencies.js",
|
||||||
|
"setup:build": "npm run setup --build",
|
||||||
"setup": "npm run clean:all && npm install && node ./scripts/setup.js && npm run clean",
|
"setup": "npm run clean:all && npm install && node ./scripts/setup.js && npm run clean",
|
||||||
"test": "make test"
|
"test": "make test"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -55,16 +55,6 @@ const FIRST_BLOCK = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const WELCOME_AGAIN_BLOCK = [
|
|
||||||
{
|
|
||||||
title: {
|
|
||||||
id: 'app.components.HomePage.welcome.again',
|
|
||||||
},
|
|
||||||
name: upperFirst(`${get(auth.getUserInfo(), 'username')}!`),
|
|
||||||
content: () => <WelcomeContent hasContent />,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const FIRST_BLOCK_LINKS = [
|
const FIRST_BLOCK_LINKS = [
|
||||||
{
|
{
|
||||||
link: 'https://strapi.io/documentation/',
|
link: 'https://strapi.io/documentation/',
|
||||||
@ -169,6 +159,15 @@ export class HomePage extends React.PureComponent {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { homePage: { articles, body } } = this.props;
|
const { homePage: { articles, body } } = this.props;
|
||||||
|
const WELCOME_AGAIN_BLOCK = [
|
||||||
|
{
|
||||||
|
title: {
|
||||||
|
id: 'app.components.HomePage.welcome.again',
|
||||||
|
},
|
||||||
|
name: upperFirst(`${get(auth.getUserInfo(), 'username')}!`),
|
||||||
|
content: () => <WelcomeContent hasContent />,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn('container-fluid', styles.containerFluid)}>
|
<div className={cn('container-fluid', styles.containerFluid)}>
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 9.0.0",
|
"node": ">= 9.0.0",
|
||||||
"npm": ">= 3.0.0"
|
"npm": ">= 5.0.0"
|
||||||
},
|
},
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
@ -709,6 +709,10 @@ module.exports = function(strapi) {
|
|||||||
acc[current] = params.values[current];
|
acc[current] = params.values[current];
|
||||||
} else {
|
} else {
|
||||||
switch (association.nature) {
|
switch (association.nature) {
|
||||||
|
case 'oneWay':
|
||||||
|
acc[current] = _.get(params.values[current], this.primaryKey, params.values[current]) || null;
|
||||||
|
|
||||||
|
break;
|
||||||
case 'oneToOne':
|
case 'oneToOne':
|
||||||
if (response[current] !== params.values[current]) {
|
if (response[current] !== params.values[current]) {
|
||||||
const value = _.isNull(params.values[current]) ? response[current] : params.values;
|
const value = _.isNull(params.values[current]) ? response[current] : params.values;
|
||||||
|
|||||||
@ -48,9 +48,12 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
add: async (values) => {
|
add: async (values) => {
|
||||||
const data = await <%= globalID %>.create(_.omit(values, _.keys(_.groupBy(strapi.models.<%= id %>.associations, 'alias'))));
|
const query = await <%= globalID %>.create(_.omit(values, _.keys(_.groupBy(strapi.models.<%= id %>.associations, 'alias'))));
|
||||||
await strapi.hook.mongoose.manageRelations('<%= id %>', _.merge(_.clone(data), { values }));
|
const data = query.toJSON ? query.toJSON() : query;
|
||||||
return data;
|
|
||||||
|
await strapi.hook.mongoose.manageRelations('<%= id %>', _.merge(data, { values }));
|
||||||
|
|
||||||
|
return query;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -71,8 +71,8 @@ module.exports = scope => {
|
|||||||
'uuid': uuid()
|
'uuid': uuid()
|
||||||
},
|
},
|
||||||
'engines': {
|
'engines': {
|
||||||
'node': '>= 7.0.0',
|
'node': '>= 9.0.0',
|
||||||
'npm': '>= 3.0.0'
|
'npm': '>= 5.0.0'
|
||||||
},
|
},
|
||||||
'license': scope.license || 'MIT'
|
'license': scope.license || 'MIT'
|
||||||
});
|
});
|
||||||
|
|||||||
@ -29,7 +29,7 @@ module.exports = scope => {
|
|||||||
'analyze:clean': 'node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json',
|
'analyze:clean': 'node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json',
|
||||||
'preanalyze': 'npm run analyze:clean',
|
'preanalyze': 'npm run analyze:clean',
|
||||||
'analyze': 'node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js',
|
'analyze': 'node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js',
|
||||||
'prebuild': 'npm run build:clean && npm run test',
|
'prebuild': 'npm run build:clean',
|
||||||
'build:dev': 'node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress',
|
'build:dev': 'node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress',
|
||||||
'build': 'node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress',
|
'build': 'node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress',
|
||||||
'build:clean': 'node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build',
|
'build:clean': 'node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build',
|
||||||
|
|||||||
@ -116,6 +116,11 @@ module.exports = function (strapi) {
|
|||||||
[`${association.via}.${association.filter}`]: association.alias,
|
[`${association.via}.${association.filter}`]: association.alias,
|
||||||
[`${association.via}.kind`]: definition.globalId
|
[`${association.via}.kind`]: definition.globalId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select last related to an entity.
|
||||||
|
this._mongooseOptions.populate[association.alias].options = {
|
||||||
|
sort: '-createdAt'
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this._mongooseOptions.populate[association.alias].path = `${association.alias}.ref`;
|
this._mongooseOptions.populate[association.alias].path = `${association.alias}.ref`;
|
||||||
}
|
}
|
||||||
@ -144,6 +149,8 @@ module.exports = function (strapi) {
|
|||||||
save: 'afterSave'
|
save: 'afterSave'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Mongoose doesn't allow post 'remove' event on model.
|
||||||
|
// See https://github.com/Automattic/mongoose/issues/3054
|
||||||
_.forEach(postLifecycle, (fn, key) => {
|
_.forEach(postLifecycle, (fn, key) => {
|
||||||
if (_.isFunction(target[model.toLowerCase()][fn])) {
|
if (_.isFunction(target[model.toLowerCase()][fn])) {
|
||||||
collection.schema.post(key, function (doc, next) {
|
collection.schema.post(key, function (doc, next) {
|
||||||
@ -178,6 +185,7 @@ module.exports = function (strapi) {
|
|||||||
break;
|
break;
|
||||||
case 'manyMorphToMany':
|
case 'manyMorphToMany':
|
||||||
case 'manyMorphToOne':
|
case 'manyMorphToOne':
|
||||||
|
|
||||||
returned[association.alias] = returned[association.alias].map(obj => obj.ref);
|
returned[association.alias] = returned[association.alias].map(obj => obj.ref);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -465,7 +473,10 @@ module.exports = function (strapi) {
|
|||||||
break;
|
break;
|
||||||
case '_contains':
|
case '_contains':
|
||||||
result.key = `where.${key}`;
|
result.key = `where.${key}`;
|
||||||
result.value = new RegExp('\\b' + value + '\\b', 'i');
|
result.value = {
|
||||||
|
$regex: value,
|
||||||
|
$options: 'i',
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
case '_containss':
|
case '_containss':
|
||||||
result.key = `where.${key}.$regex`;
|
result.key = `where.${key}.$regex`;
|
||||||
@ -502,10 +513,13 @@ module.exports = function (strapi) {
|
|||||||
acc[current] = params.values[current];
|
acc[current] = params.values[current];
|
||||||
} else {
|
} else {
|
||||||
switch (association.nature) {
|
switch (association.nature) {
|
||||||
|
case 'oneWay':
|
||||||
|
acc[current] = _.get(params.values[current], this.primaryKey, params.values[current]) || null;
|
||||||
|
|
||||||
|
break;
|
||||||
case 'oneToOne':
|
case 'oneToOne':
|
||||||
if (response[current] !== params.values[current]) {
|
if (response[current] !== params.values[current]) {
|
||||||
const value = _.isNull(params.values[current]) ? response[current] : params.values;
|
const value = _.isNull(params.values[current]) ? response[current] : params.values;
|
||||||
|
|
||||||
const recordId = _.isNull(params.values[current]) ? value[Model.primaryKey] || value.id || value._id : value[current];
|
const recordId = _.isNull(params.values[current]) ? value[Model.primaryKey] || value.id || value._id : value[current];
|
||||||
|
|
||||||
if (response[current] && _.isObject(response[current]) && response[current][Model.primaryKey] !== value[current]) {
|
if (response[current] && _.isObject(response[current]) && response[current][Model.primaryKey] !== value[current]) {
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
"main": "./lib",
|
"main": "./lib",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"mongoose": "^5.0.4",
|
"mongoose": "^5.0.15",
|
||||||
"mongoose-float": "^1.0.2",
|
"mongoose-float": "^1.0.2",
|
||||||
"pluralize": "^6.0.0",
|
"pluralize": "^6.0.0",
|
||||||
"strapi-utils": "3.0.0-alpha.12"
|
"strapi-utils": "3.0.0-alpha.12"
|
||||||
|
|||||||
@ -8,39 +8,51 @@ import React from 'react';
|
|||||||
import Select from 'react-select';
|
import Select from 'react-select';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import 'react-select/dist/react-select.css';
|
import 'react-select/dist/react-select.css';
|
||||||
import { isArray, isNull, isUndefined, get, findIndex } from 'lodash';
|
import { cloneDeep, isArray, isNull, isUndefined, get, findIndex, includes } from 'lodash';
|
||||||
|
|
||||||
import request from 'utils/request';
|
import request from 'utils/request';
|
||||||
import templateObject from 'utils/templateObject';
|
import templateObject from 'utils/templateObject';
|
||||||
|
|
||||||
import styles from './styles.scss';
|
import styles from './styles.scss';
|
||||||
|
|
||||||
class SelectMany extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
class SelectMany extends React.Component {
|
||||||
|
// eslint-disable-line react/prefer-stateless-function
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
|
options: [],
|
||||||
|
toSkip: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getOptions = (query) => {
|
componentDidMount() {
|
||||||
|
this.getOptions('');
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps, prevState) {
|
||||||
|
if (prevState.toSkip !== this.state.toSkip) {
|
||||||
|
this.getOptions('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getOptions = query => {
|
||||||
const params = {
|
const params = {
|
||||||
limit: 20,
|
limit: 20,
|
||||||
|
skip: this.state.toSkip,
|
||||||
source: this.props.relation.plugin || 'content-manager',
|
source: this.props.relation.plugin || 'content-manager',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set `query` parameter if necessary
|
// Set `query` parameter if necessary
|
||||||
if (query) {
|
if (query) {
|
||||||
params.query = query;
|
delete params.limit,
|
||||||
params.queryAttribute = this.props.relation.displayedAttribute;
|
delete params.skip,
|
||||||
|
params[`${this.props.relation.displayedAttribute}_contains`] = query;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request URL
|
// Request URL
|
||||||
const requestUrlSuffix = query && this.props.record.get(this.props.relation.alias) ? this.props.record.get(this.props.relation.alias) : '';
|
const requestUrl = `/content-manager/explorer/${this.props.relation.model ||
|
||||||
// NOTE: keep this line if we rollback to the old container
|
this.props.relation.collection}`;
|
||||||
// const requestUrlSuffix = query && this.props.record.get(this.props.relation.alias).toJS() ? this.props.record.get(this.props.relation.alias).toJS() : '';
|
|
||||||
const requestUrl = `/content-manager/explorer/${this.props.relation.model || this.props.relation.collection}/${requestUrlSuffix}`;
|
|
||||||
|
|
||||||
// Call our request helper (see 'utils/request')
|
// Call our request helper (see 'utils/request')
|
||||||
return request(requestUrl, {
|
return request(requestUrl, {
|
||||||
@ -48,25 +60,41 @@ class SelectMany extends React.Component { // eslint-disable-line react/prefer-s
|
|||||||
params,
|
params,
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const options = isArray(response) ?
|
const options = isArray(response)
|
||||||
response.map(item => ({
|
? response.map(item => ({
|
||||||
value: item,
|
value: item,
|
||||||
label: templateObject({ mainField: this.props.relation.displayedAttribute }, item).mainField,
|
label: templateObject({ mainField: this.props.relation.displayedAttribute }, item)
|
||||||
})) :
|
.mainField,
|
||||||
[{
|
}))
|
||||||
|
: [
|
||||||
|
{
|
||||||
value: response,
|
value: response,
|
||||||
label: response[this.props.relation.displayedAttribute],
|
label: response[this.props.relation.displayedAttribute],
|
||||||
}];
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return { options };
|
const newOptions = cloneDeep(this.state.options);
|
||||||
|
options.map(option => {
|
||||||
|
// Don't add the values when searching
|
||||||
|
if (findIndex(newOptions, o => o.value.id === option.value.id) === -1) {
|
||||||
|
return newOptions.push(option);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.setState({
|
||||||
|
options: newOptions,
|
||||||
|
isLoading: false,
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
strapi.notification.error('content-manager.notification.error.relationship.fetch');
|
strapi.notification.error('content-manager.notification.error.relationship.fetch');
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
handleChange = (value) => {
|
handleChange = value => {
|
||||||
const filteredValue = value.filter((data, index ) => findIndex(value, (o) => o.value.id === data.value.id) === index);
|
const filteredValue = value.filter(
|
||||||
|
(data, index) => findIndex(value, o => o.value.id === data.value.id) === index
|
||||||
|
);
|
||||||
const target = {
|
const target = {
|
||||||
name: `record.${this.props.relation.alias}`,
|
name: `record.${this.props.relation.alias}`,
|
||||||
type: 'select',
|
type: 'select',
|
||||||
@ -74,37 +102,62 @@ class SelectMany extends React.Component { // eslint-disable-line react/prefer-s
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.props.setRecordAttribute({ target });
|
this.props.setRecordAttribute({ target });
|
||||||
// NOTE: keep this line if we rollback to the old container
|
};
|
||||||
// this.props.setRecordAttribute(this.props.relation.alias, filteredValue);
|
|
||||||
|
handleBottomScroll = () => {
|
||||||
|
this.setState(prevState => {
|
||||||
|
return {
|
||||||
|
toSkip: prevState.toSkip + 20,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleInputChange = (value) => {
|
||||||
|
const clonedOptions = this.state.options;
|
||||||
|
const filteredValues = clonedOptions.filter(data => includes(data.label, value));
|
||||||
|
|
||||||
|
if (filteredValues.length === 0) {
|
||||||
|
return this.getOptions(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const description = this.props.relation.description
|
const description = this.props.relation.description ? (
|
||||||
? <p>{this.props.relation.description}</p>
|
<p>{this.props.relation.description}</p>
|
||||||
: '';
|
) : (
|
||||||
|
''
|
||||||
|
);
|
||||||
|
|
||||||
const value = get(this.props.record, this.props.relation.alias);
|
const value = get(this.props.record, this.props.relation.alias);
|
||||||
// NOTE: keep this line if we rollback to the old container
|
|
||||||
// const value = this.props.record.get(this.props.relation.alias);
|
|
||||||
|
|
||||||
/* eslint-disable jsx-a11y/label-has-for */
|
/* eslint-disable jsx-a11y/label-has-for */
|
||||||
return (
|
return (
|
||||||
<div className={`form-group ${styles.selectMany}`}>
|
<div className={`form-group ${styles.selectMany}`}>
|
||||||
<label htmlFor={this.props.relation.alias}>{this.props.relation.alias}</label>
|
<label htmlFor={this.props.relation.alias}>{this.props.relation.alias}</label>
|
||||||
{description}
|
{description}
|
||||||
<Select.Async
|
<Select
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
loadOptions={this.getOptions}
|
options={this.state.options}
|
||||||
id={this.props.relation.alias}
|
id={this.props.relation.alias}
|
||||||
|
isLoading={this.state.isLoading}
|
||||||
|
onMenuScrollToBottom={this.handleBottomScroll}
|
||||||
|
onInputChange={this.handleInputChange}
|
||||||
multi
|
multi
|
||||||
value={isNull(value) || isUndefined(value) || value.size === 0 ? null : value.map(item => {
|
value={
|
||||||
|
isNull(value) || isUndefined(value) || value.size === 0
|
||||||
|
? null
|
||||||
|
: value.map(item => {
|
||||||
if (item) {
|
if (item) {
|
||||||
return {
|
return {
|
||||||
value: get(item, 'value') || item,
|
value: get(item, 'value') || item,
|
||||||
label: get(item, 'label') || templateObject({ mainField: this.props.relation.displayedAttribute }, item).mainField || item.value.id,
|
label:
|
||||||
|
get(item, 'label') ||
|
||||||
|
templateObject({ mainField: this.props.relation.displayedAttribute }, item)
|
||||||
|
.mainField ||
|
||||||
|
item.value.id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
})}
|
})
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -113,10 +166,7 @@ class SelectMany extends React.Component { // eslint-disable-line react/prefer-s
|
|||||||
}
|
}
|
||||||
|
|
||||||
SelectMany.propTypes = {
|
SelectMany.propTypes = {
|
||||||
record: PropTypes.oneOfType([
|
record: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]).isRequired,
|
||||||
PropTypes.object,
|
|
||||||
PropTypes.bool,
|
|
||||||
]).isRequired,
|
|
||||||
relation: PropTypes.object.isRequired,
|
relation: PropTypes.object.isRequired,
|
||||||
setRecordAttribute: PropTypes.func.isRequired,
|
setRecordAttribute: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import React from 'react';
|
|||||||
import Select from 'react-select';
|
import Select from 'react-select';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import 'react-select/dist/react-select.css';
|
import 'react-select/dist/react-select.css';
|
||||||
import { map, isArray, isNull, isUndefined, isFunction, get } from 'lodash';
|
import { cloneDeep, map, includes, isArray, isNull, isUndefined, isFunction, get, findIndex } from 'lodash';
|
||||||
|
|
||||||
import request from 'utils/request';
|
import request from 'utils/request';
|
||||||
import templateObject from 'utils/templateObject';
|
import templateObject from 'utils/templateObject';
|
||||||
@ -21,23 +21,37 @@ class SelectOne extends React.Component { // eslint-disable-line react/prefer-st
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
|
options: [],
|
||||||
|
toSkip: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getOptions('');
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps, prevState) {
|
||||||
|
if (prevState.toSkip !== this.state.toSkip) {
|
||||||
|
this.getOptions('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getOptions = (query) => {
|
getOptions = (query) => {
|
||||||
const params = {
|
const params = {
|
||||||
limit: 20,
|
limit: 20,
|
||||||
|
skip: this.state.toSkip,
|
||||||
source: this.props.relation.plugin || 'content-manager',
|
source: this.props.relation.plugin || 'content-manager',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set `query` parameter if necessary
|
// Set `query` parameter if necessary
|
||||||
if (query) {
|
if (query) {
|
||||||
params.query = query;
|
delete params.limit,
|
||||||
params.queryAttribute = this.props.relation.displayedAttribute;
|
delete params.skip,
|
||||||
|
params[`${this.props.relation.displayedAttribute}_contains`] = query;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request URL
|
// Request URL
|
||||||
const requestUrlSuffix = query && this.props.record.get(this.props.relation.alias) ? this.props.record.get(this.props.relation.alias) : '';
|
const requestUrlSuffix = query && get(this.props.record, [this.props.relation.alias]) ? get(this.props.record, [this.props.relation.alias]) : '';
|
||||||
const requestUrl = `/content-manager/explorer/${this.props.relation.model || this.props.relation.collection}/${requestUrlSuffix}`;
|
const requestUrl = `/content-manager/explorer/${this.props.relation.model || this.props.relation.collection}/${requestUrlSuffix}`;
|
||||||
|
|
||||||
// Call our request helper (see 'utils/request')
|
// Call our request helper (see 'utils/request')
|
||||||
@ -56,7 +70,18 @@ class SelectOne extends React.Component { // eslint-disable-line react/prefer-st
|
|||||||
label: templateObject({ mainField: this.props.relation.displayedAttribute }, response).mainField,
|
label: templateObject({ mainField: this.props.relation.displayedAttribute }, response).mainField,
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return {options};
|
const newOptions = cloneDeep(this.state.options);
|
||||||
|
options.map(option => {
|
||||||
|
// Don't add the values when searching
|
||||||
|
if (findIndex(newOptions, o => o.value.id === option.value.id) === -1) {
|
||||||
|
return newOptions.push(option);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.setState({
|
||||||
|
options: newOptions,
|
||||||
|
isLoading: false,
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
strapi.notification.error('content-manager.notification.relationship.fetch');
|
strapi.notification.error('content-manager.notification.relationship.fetch');
|
||||||
@ -71,8 +96,23 @@ class SelectOne extends React.Component { // eslint-disable-line react/prefer-st
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.props.setRecordAttribute({ target });
|
this.props.setRecordAttribute({ target });
|
||||||
// NOTE: keep this line if we rollback to the old container
|
}
|
||||||
// this.props.setRecordAttribute(this.props.relation.alias, value);
|
|
||||||
|
handleBottomScroll = () => {
|
||||||
|
this.setState(prevState => {
|
||||||
|
return {
|
||||||
|
toSkip: prevState.toSkip + 20,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleInputChange = (value) => {
|
||||||
|
const clonedOptions = this.state.options;
|
||||||
|
const filteredValues = clonedOptions.filter(data => includes(data.label, value));
|
||||||
|
|
||||||
|
if (filteredValues.length === 0) {
|
||||||
|
return this.getOptions(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -81,17 +121,18 @@ class SelectOne extends React.Component { // eslint-disable-line react/prefer-st
|
|||||||
: '';
|
: '';
|
||||||
|
|
||||||
const value = get(this.props.record, this.props.relation.alias);
|
const value = get(this.props.record, this.props.relation.alias);
|
||||||
// NOTE: keep this line if we rollback to the old container
|
|
||||||
// const value = this.props.record.get(this.props.relation.alias);
|
|
||||||
|
|
||||||
/* eslint-disable jsx-a11y/label-has-for */
|
/* eslint-disable jsx-a11y/label-has-for */
|
||||||
return (
|
return (
|
||||||
<div className={`form-group ${styles.selectOne}`}>
|
<div className={`form-group ${styles.selectOne}`}>
|
||||||
<label htmlFor={this.props.relation.alias}>{this.props.relation.alias}</label>
|
<label htmlFor={this.props.relation.alias}>{this.props.relation.alias}</label>
|
||||||
{description}
|
{description}
|
||||||
<Select.Async
|
<Select
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
loadOptions={this.getOptions}
|
options={this.state.options}
|
||||||
|
isLoading={this.state.isLoading}
|
||||||
|
onMenuScrollToBottom={this.handleBottomScroll}
|
||||||
|
onInputChange={this.handleInputChange}
|
||||||
simpleValue
|
simpleValue
|
||||||
value={isNull(value) || isUndefined(value) ? null : {
|
value={isNull(value) || isUndefined(value) ? null : {
|
||||||
value: isFunction(value.toJS) ? value.toJS() : value,
|
value: isFunction(value.toJS) ? value.toJS() : value,
|
||||||
|
|||||||
@ -235,7 +235,7 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (association.type === 'model') {
|
if (association.type === 'model' || (association.type === 'collection' && _.isObject(array))) {
|
||||||
return _.isEmpty(array) ? [] : transformToArrayID([array]);
|
return _.isEmpty(array) ? [] : transformToArrayID([array]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -220,7 +220,7 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (association.type === 'model') {
|
if (association.type === 'model' || (association.type === 'collection' && _.isObject(array))) {
|
||||||
return _.isEmpty(array) ? [] : transformToArrayID([array]);
|
return _.isEmpty(array) ? [] : transformToArrayID([array]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||||
"preanalyze": "npm run analyze:clean",
|
"preanalyze": "npm run analyze:clean",
|
||||||
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
||||||
"prebuild": "npm run build:clean && npm run test",
|
"prebuild": "npm run build:clean",
|
||||||
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
||||||
@ -44,7 +44,7 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 9.0.0",
|
"node": ">= 9.0.0",
|
||||||
"npm": ">= 3.0.0"
|
"npm": ">= 5.0.0"
|
||||||
},
|
},
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
@ -11,7 +11,7 @@
|
|||||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||||
"preanalyze": "npm run analyze:clean",
|
"preanalyze": "npm run analyze:clean",
|
||||||
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
||||||
"prebuild": "npm run build:clean && npm run test",
|
"prebuild": "npm run build:clean",
|
||||||
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
||||||
@ -48,7 +48,7 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 9.0.0",
|
"node": ">= 9.0.0",
|
||||||
"npm": ">= 3.0.0"
|
"npm": ">= 5.0.0"
|
||||||
},
|
},
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
@ -11,7 +11,7 @@
|
|||||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||||
"preanalyze": "npm run analyze:clean",
|
"preanalyze": "npm run analyze:clean",
|
||||||
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
||||||
"prebuild": "npm run build:clean && npm run test",
|
"prebuild": "npm run build:clean",
|
||||||
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
||||||
@ -45,8 +45,8 @@
|
|||||||
"url": "git://github.com/strapi/strapi.git"
|
"url": "git://github.com/strapi/strapi.git"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 7.0.0",
|
"node": ">= 9.0.0",
|
||||||
"npm": ">= 3.0.0"
|
"npm": ">= 5.0.0"
|
||||||
},
|
},
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
@ -11,7 +11,7 @@
|
|||||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||||
"preanalyze": "npm run analyze:clean",
|
"preanalyze": "npm run analyze:clean",
|
||||||
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
||||||
"prebuild": "npm run build:clean && npm run test",
|
"prebuild": "npm run build:clean",
|
||||||
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
||||||
@ -45,7 +45,7 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 9.0.0",
|
"node": ">= 9.0.0",
|
||||||
"npm": ">= 3.0.0"
|
"npm": ">= 5.0.0"
|
||||||
},
|
},
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
@ -34,8 +34,8 @@ module.exports = async cb => {
|
|||||||
size text,
|
size text,
|
||||||
url text,
|
url text,
|
||||||
provider text,
|
provider text,
|
||||||
updated_at ${Model.client === 'pg' ? 'timestamp with time zone' : 'timestamp'},
|
updated_at ${Model.client === 'pg' ? 'timestamp with time zone' : 'timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'},
|
||||||
created_at ${Model.client === 'pg' ? 'timestamp with time zone' : 'timestamp'}
|
created_at ${Model.client === 'pg' ? 'timestamp with time zone' : 'timestamp DEFAULT CURRENT_TIMESTAMP'}
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE ${quote}upload_file_morph${quote} (
|
CREATE TABLE ${quote}upload_file_morph${quote} (
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||||
"preanalyze": "npm run analyze:clean",
|
"preanalyze": "npm run analyze:clean",
|
||||||
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
||||||
"prebuild": "npm run build:clean && npm run test",
|
"prebuild": "npm run build:clean",
|
||||||
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||||
"preanalyze": "npm run analyze:clean",
|
"preanalyze": "npm run analyze:clean",
|
||||||
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
"analyze": "node ./node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js",
|
||||||
"prebuild": "npm run build:clean && npm run test",
|
"prebuild": "npm run build:clean",
|
||||||
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build:dev": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=development node ./node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
"build": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/cross-env NODE_ENV=production node node_modules/strapi-helper-plugin/node_modules/.bin/webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress",
|
||||||
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
"build:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf admin/build",
|
||||||
@ -51,8 +51,8 @@
|
|||||||
"url": "git://github.com/strapi/strapi.git"
|
"url": "git://github.com/strapi/strapi.git"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 7.0.0",
|
"node": ">= 9.0.0",
|
||||||
"npm": ">= 3.0.0"
|
"npm": ">= 5.0.0"
|
||||||
},
|
},
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
@ -460,8 +460,8 @@ CREATE TABLE ${quote}${details[currentModel].tableName}${quote} (
|
|||||||
role ${details[currentModel].client === 'pg' ? 'integer' : 'int'},
|
role ${details[currentModel].client === 'pg' ? 'integer' : 'int'},
|
||||||
${quote}resetPasswordToken${quote} text,
|
${quote}resetPasswordToken${quote} text,
|
||||||
password text,
|
password text,
|
||||||
updated_at ${details[currentModel].client === 'pg' ? 'timestamp with time zone' : 'timestamp'},
|
updated_at ${details[currentModel].client === 'pg' ? 'timestamp with time zone' : 'timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'},
|
||||||
created_at ${details[currentModel].client === 'pg' ? 'timestamp with time zone' : 'timestamp'}
|
created_at ${details[currentModel].client === 'pg' ? 'timestamp with time zone' : 'timestamp DEFAULT CURRENT_TIMESTAMP'}
|
||||||
);`);
|
);`);
|
||||||
break;
|
break;
|
||||||
case 'role':
|
case 'role':
|
||||||
|
|||||||
@ -1,8 +1,21 @@
|
|||||||
const shell = require('shelljs');
|
const shell = require('shelljs');
|
||||||
|
// Check npm version
|
||||||
|
const npm = shell.exec('npm -v').stdout;
|
||||||
|
|
||||||
|
if (parseFloat(npm) < 5) {
|
||||||
|
throw new Error('[ERROR: Strapi] You need npm version @>=5');
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeVersion = shell.exec('node -v').stdout.replace('v', '');
|
||||||
|
|
||||||
|
if (parseFloat(nodeVersion) < 8.6) {
|
||||||
|
throw new Error('[ERROR: Strapi] You need to use node version @>=9');
|
||||||
|
}
|
||||||
|
|
||||||
// Store installation start date.
|
// Store installation start date.
|
||||||
const silent = process.env.npm_config_debug !== 'true';
|
const silent = process.env.npm_config_debug !== 'true';
|
||||||
const installationStartDate = new Date();
|
const installationStartDate = new Date();
|
||||||
|
|
||||||
const watcher = (label, cmd, withSuccess = true) => {
|
const watcher = (label, cmd, withSuccess = true) => {
|
||||||
if (label.length > 0) {
|
if (label.length > 0) {
|
||||||
shell.echo(label);
|
shell.echo(label);
|
||||||
@ -21,6 +34,22 @@ const watcher = (label, cmd, withSuccess = true) => {
|
|||||||
shell.echo('✅ Success');
|
shell.echo('✅ Success');
|
||||||
shell.echo('');
|
shell.echo('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const asyncWatcher = (label, cmd, withSuccess = true, resolve) => {
|
||||||
|
if (label.length > 0) {
|
||||||
|
shell.echo(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shell.exec(cmd, { silent, async: true }, (code, stdout, stderr) => {
|
||||||
|
if (stderr && code !== 0) {
|
||||||
|
console.error(stderr);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolve();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
shell.echo('');
|
shell.echo('');
|
||||||
@ -57,7 +86,6 @@ if (shell.test('-e', 'admin/src/config/plugins.json') === false) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
watcher('📦 Linking strapi-admin', 'npm link --no-optional', false);
|
watcher('📦 Linking strapi-admin', 'npm link --no-optional', false);
|
||||||
watcher('🏗 Building...', 'npm run build');
|
|
||||||
|
|
||||||
shell.cd('../strapi-generate-admin');
|
shell.cd('../strapi-generate-admin');
|
||||||
watcher('', 'npm install ../strapi-admin');
|
watcher('', 'npm install ../strapi-admin');
|
||||||
@ -83,6 +111,14 @@ shell.cd('../strapi');
|
|||||||
watcher('', 'npm install ../strapi-generate ../strapi-generate-admin ../strapi-generate-api ../strapi-generate-new ../strapi-generate-plugin ../strapi-generate-policy ../strapi-generate-service ../strapi-utils');
|
watcher('', 'npm install ../strapi-generate ../strapi-generate-admin ../strapi-generate-api ../strapi-generate-new ../strapi-generate-plugin ../strapi-generate-policy ../strapi-generate-service ../strapi-utils');
|
||||||
watcher('📦 Linking strapi...', 'npm link');
|
watcher('📦 Linking strapi...', 'npm link');
|
||||||
|
|
||||||
|
// Upload plugins
|
||||||
|
shell.cd('../strapi-upload-local');
|
||||||
|
watcher('📦 Linking strapi-upload-local...', 'npm link --no-optional', false);
|
||||||
|
shell.cd('../strapi-upload-aws-s3');
|
||||||
|
watcher('📦 Linking strapi-upload-aws-s3...', 'npm link --no-optional', false);
|
||||||
|
|
||||||
|
|
||||||
|
// Plugins with admin
|
||||||
shell.cd('../strapi-plugin-email');
|
shell.cd('../strapi-plugin-email');
|
||||||
shell.rm('-f', 'package-lock.json');
|
shell.rm('-f', 'package-lock.json');
|
||||||
watcher('📦 Linking strapi-plugin-email...', 'npm link --no-optional', false);
|
watcher('📦 Linking strapi-plugin-email...', 'npm link --no-optional', false);
|
||||||
@ -91,32 +127,24 @@ shell.cd('../strapi-plugin-users-permissions');
|
|||||||
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
||||||
shell.rm('-f', 'package-lock.json');
|
shell.rm('-f', 'package-lock.json');
|
||||||
watcher('📦 Linking strapi-plugin-users-permissions...', 'npm link --no-optional', false);
|
watcher('📦 Linking strapi-plugin-users-permissions...', 'npm link --no-optional', false);
|
||||||
watcher('🏗 Building...', 'npm run build');
|
|
||||||
|
|
||||||
shell.cd('../strapi-plugin-content-manager');
|
shell.cd('../strapi-plugin-content-manager');
|
||||||
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
||||||
shell.rm('-f', 'package-lock.json');
|
shell.rm('-f', 'package-lock.json');
|
||||||
watcher('📦 Linking strapi-plugin-content-manager...', 'npm link --no-optional', false);
|
watcher('📦 Linking strapi-plugin-content-manager...', 'npm link --no-optional', false);
|
||||||
watcher('🏗 Building...', 'npm run build');
|
|
||||||
|
|
||||||
shell.cd('../strapi-plugin-settings-manager');
|
shell.cd('../strapi-plugin-settings-manager');
|
||||||
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
||||||
shell.rm('-f', 'package-lock.json');
|
shell.rm('-f', 'package-lock.json');
|
||||||
watcher('📦 Linking strapi-plugin-settings-manager...', 'npm link --no-optional', false);
|
watcher('📦 Linking strapi-plugin-settings-manager...', 'npm link --no-optional', false);
|
||||||
watcher('🏗 Building...', 'npm run build');
|
|
||||||
|
|
||||||
|
|
||||||
shell.cd('../strapi-upload-local');
|
// Plugins with admin and other plugin's dependencies
|
||||||
watcher('📦 Linking strapi-upload-local...', 'npm link --no-optional', false);
|
|
||||||
shell.cd('../strapi-upload-aws-s3');
|
|
||||||
watcher('📦 Linking strapi-upload-aws-s3...', 'npm link --no-optional', false);
|
|
||||||
|
|
||||||
shell.cd('../strapi-plugin-upload');
|
shell.cd('../strapi-plugin-upload');
|
||||||
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
||||||
watcher('', 'npm install ../strapi-upload-local --no-optional');
|
watcher('', 'npm install ../strapi-upload-local --no-optional');
|
||||||
shell.rm('-f', 'package-lock.json');
|
shell.rm('-f', 'package-lock.json');
|
||||||
watcher('📦 Linking strapi-plugin-upload...', 'npm link --no-optional', false);
|
watcher('📦 Linking strapi-plugin-upload...', 'npm link --no-optional', false);
|
||||||
watcher('🏗 Building...', 'npm run build');
|
|
||||||
|
|
||||||
shell.cd('../strapi-plugin-content-type-builder');
|
shell.cd('../strapi-plugin-content-type-builder');
|
||||||
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
||||||
@ -124,15 +152,39 @@ watcher('', 'npm install ../strapi-generate --no-optional');
|
|||||||
watcher('', 'npm install ../strapi-generate-api --no-optional');
|
watcher('', 'npm install ../strapi-generate-api --no-optional');
|
||||||
shell.rm('-f', 'package-lock.json');
|
shell.rm('-f', 'package-lock.json');
|
||||||
watcher('📦 Linking strapi-plugin-content-type-builder...', 'npm link --no-optional', false);
|
watcher('📦 Linking strapi-plugin-content-type-builder...', 'npm link --no-optional', false);
|
||||||
watcher('🏗 Building...', 'npm run build');
|
|
||||||
|
|
||||||
shell.cd('../strapi-plugin-graphql');
|
const pluginsToBuild = ['admin', 'content-manager', 'content-type-builder', 'upload', 'users-permissions', 'settings-manager'];
|
||||||
watcher('', 'npm install ../strapi-utils --no-optional');
|
|
||||||
shell.rm('-f', 'package-lock.json');
|
|
||||||
watcher('📦 Linking strapi-plugin-graphql...', 'npm link --no-optional', false);
|
|
||||||
|
|
||||||
// Log installation duration.
|
const buildPlugins = async () => {
|
||||||
const installationEndDate = new Date();
|
const build = (pckgName) => {
|
||||||
const duration = (installationEndDate.getTime() - installationStartDate.getTime()) / 1000;
|
return new Promise(resolve => {
|
||||||
shell.echo('✅ Strapi has been succesfully installed.');
|
const name = pckgName === 'admin' ? pckgName: `plugin-${pckgName}`;
|
||||||
shell.echo(`⏳ The installation took ${Math.floor(duration / 60) > 0 ? `${Math.floor(duration / 60)} minutes and ` : ''}${Math.floor(duration % 60)} seconds.`);
|
asyncWatcher(`🏗 Building ${name}...`, `cd ../strapi-${name} && npm run build`, false, resolve);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return Promise.all(pluginsToBuild.map(plugin => build(plugin)));
|
||||||
|
};
|
||||||
|
|
||||||
|
const setup = async () => {
|
||||||
|
if (process.env.npm_config_build) {
|
||||||
|
if (process.platform === 'darwin') { // Allow async build for darwin platform
|
||||||
|
await buildPlugins();
|
||||||
|
} else {
|
||||||
|
pluginsToBuild.map(name => {
|
||||||
|
const pluginName = name === 'admin' ? name : `plugin-${name}`;
|
||||||
|
shell.cd(`../strapi-${pluginName}`);
|
||||||
|
|
||||||
|
return watcher(`🏗 Building ${pluginName}...`, 'npm run build');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log installation duration.
|
||||||
|
const installationEndDate = new Date();
|
||||||
|
const duration = (installationEndDate.getTime() - installationStartDate.getTime()) / 1000;
|
||||||
|
shell.echo('✅ Strapi has been succesfully installed.');
|
||||||
|
shell.echo(`⏳ The installation took ${Math.floor(duration / 60) > 0 ? `${Math.floor(duration / 60)} minutes and ` : ''}${Math.floor(duration % 60)} seconds.`);
|
||||||
|
};
|
||||||
|
|
||||||
|
setup();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user