mirror of
https://github.com/strapi/strapi.git
synced 2025-11-10 23:29:33 +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.
|
||||
|
||||
## 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
|
||||
|
||||
The following types are currently available:
|
||||
@ -59,7 +65,8 @@ To improve the Developer eXperience when developing or using the administration
|
||||
"connection": "default",
|
||||
"info": {
|
||||
"name": "user",
|
||||
"description": "This represents the User Model"
|
||||
"description": "This represents the User Model",
|
||||
"mainField": "email"
|
||||
},
|
||||
"attributes": {
|
||||
"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`.
|
||||
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.
|
||||
|
||||
## 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",
|
||||
"createsymlinkdependencies": "node ./scripts/createSymlinkDependencies.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",
|
||||
"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 = [
|
||||
{
|
||||
link: 'https://strapi.io/documentation/',
|
||||
@ -169,6 +159,15 @@ export class HomePage extends React.PureComponent {
|
||||
|
||||
render() {
|
||||
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 (
|
||||
<div className={cn('container-fluid', styles.containerFluid)}>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -709,6 +709,10 @@ module.exports = function(strapi) {
|
||||
acc[current] = params.values[current];
|
||||
} else {
|
||||
switch (association.nature) {
|
||||
case 'oneWay':
|
||||
acc[current] = _.get(params.values[current], this.primaryKey, params.values[current]) || null;
|
||||
|
||||
break;
|
||||
case 'oneToOne':
|
||||
if (response[current] !== params.values[current]) {
|
||||
const value = _.isNull(params.values[current]) ? response[current] : params.values;
|
||||
|
||||
@ -48,9 +48,12 @@ module.exports = {
|
||||
*/
|
||||
|
||||
add: async (values) => {
|
||||
const data = await <%= globalID %>.create(_.omit(values, _.keys(_.groupBy(strapi.models.<%= id %>.associations, 'alias'))));
|
||||
await strapi.hook.mongoose.manageRelations('<%= id %>', _.merge(_.clone(data), { values }));
|
||||
return data;
|
||||
const query = await <%= globalID %>.create(_.omit(values, _.keys(_.groupBy(strapi.models.<%= id %>.associations, 'alias'))));
|
||||
const data = query.toJSON ? query.toJSON() : query;
|
||||
|
||||
await strapi.hook.mongoose.manageRelations('<%= id %>', _.merge(data, { values }));
|
||||
|
||||
return query;
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@ -71,8 +71,8 @@ module.exports = scope => {
|
||||
'uuid': uuid()
|
||||
},
|
||||
'engines': {
|
||||
'node': '>= 7.0.0',
|
||||
'npm': '>= 3.0.0'
|
||||
'node': '>= 9.0.0',
|
||||
'npm': '>= 5.0.0'
|
||||
},
|
||||
'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',
|
||||
'preanalyze': 'npm run analyze:clean',
|
||||
'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': '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',
|
||||
|
||||
@ -116,6 +116,11 @@ module.exports = function (strapi) {
|
||||
[`${association.via}.${association.filter}`]: association.alias,
|
||||
[`${association.via}.kind`]: definition.globalId
|
||||
}
|
||||
|
||||
// Select last related to an entity.
|
||||
this._mongooseOptions.populate[association.alias].options = {
|
||||
sort: '-createdAt'
|
||||
}
|
||||
} else {
|
||||
this._mongooseOptions.populate[association.alias].path = `${association.alias}.ref`;
|
||||
}
|
||||
@ -144,6 +149,8 @@ module.exports = function (strapi) {
|
||||
save: 'afterSave'
|
||||
};
|
||||
|
||||
// Mongoose doesn't allow post 'remove' event on model.
|
||||
// See https://github.com/Automattic/mongoose/issues/3054
|
||||
_.forEach(postLifecycle, (fn, key) => {
|
||||
if (_.isFunction(target[model.toLowerCase()][fn])) {
|
||||
collection.schema.post(key, function (doc, next) {
|
||||
@ -178,6 +185,7 @@ module.exports = function (strapi) {
|
||||
break;
|
||||
case 'manyMorphToMany':
|
||||
case 'manyMorphToOne':
|
||||
|
||||
returned[association.alias] = returned[association.alias].map(obj => obj.ref);
|
||||
break;
|
||||
default:
|
||||
@ -465,7 +473,10 @@ module.exports = function (strapi) {
|
||||
break;
|
||||
case '_contains':
|
||||
result.key = `where.${key}`;
|
||||
result.value = new RegExp('\\b' + value + '\\b', 'i');
|
||||
result.value = {
|
||||
$regex: value,
|
||||
$options: 'i',
|
||||
};
|
||||
break;
|
||||
case '_containss':
|
||||
result.key = `where.${key}.$regex`;
|
||||
@ -502,10 +513,13 @@ module.exports = function (strapi) {
|
||||
acc[current] = params.values[current];
|
||||
} else {
|
||||
switch (association.nature) {
|
||||
case 'oneWay':
|
||||
acc[current] = _.get(params.values[current], this.primaryKey, params.values[current]) || null;
|
||||
|
||||
break;
|
||||
case 'oneToOne':
|
||||
if (response[current] !== params.values[current]) {
|
||||
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];
|
||||
|
||||
if (response[current] && _.isObject(response[current]) && response[current][Model.primaryKey] !== value[current]) {
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
"main": "./lib",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.4",
|
||||
"mongoose": "^5.0.4",
|
||||
"mongoose": "^5.0.15",
|
||||
"mongoose-float": "^1.0.2",
|
||||
"pluralize": "^6.0.0",
|
||||
"strapi-utils": "3.0.0-alpha.12"
|
||||
|
||||
@ -8,39 +8,51 @@ import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import PropTypes from 'prop-types';
|
||||
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 templateObject from 'utils/templateObject';
|
||||
|
||||
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) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
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 = {
|
||||
limit: 20,
|
||||
skip: this.state.toSkip,
|
||||
source: this.props.relation.plugin || 'content-manager',
|
||||
};
|
||||
|
||||
// Set `query` parameter if necessary
|
||||
if (query) {
|
||||
params.query = query;
|
||||
params.queryAttribute = this.props.relation.displayedAttribute;
|
||||
delete params.limit,
|
||||
delete params.skip,
|
||||
params[`${this.props.relation.displayedAttribute}_contains`] = query;
|
||||
}
|
||||
|
||||
// Request URL
|
||||
const requestUrlSuffix = query && this.props.record.get(this.props.relation.alias) ? this.props.record.get(this.props.relation.alias) : '';
|
||||
// NOTE: keep this line if we rollback to the old container
|
||||
// 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}`;
|
||||
const requestUrl = `/content-manager/explorer/${this.props.relation.model ||
|
||||
this.props.relation.collection}`;
|
||||
|
||||
// Call our request helper (see 'utils/request')
|
||||
return request(requestUrl, {
|
||||
@ -48,25 +60,41 @@ class SelectMany extends React.Component { // eslint-disable-line react/prefer-s
|
||||
params,
|
||||
})
|
||||
.then(response => {
|
||||
const options = isArray(response) ?
|
||||
response.map(item => ({
|
||||
const options = isArray(response)
|
||||
? response.map(item => ({
|
||||
value: item,
|
||||
label: templateObject({ mainField: this.props.relation.displayedAttribute }, item).mainField,
|
||||
})) :
|
||||
[{
|
||||
label: templateObject({ mainField: this.props.relation.displayedAttribute }, item)
|
||||
.mainField,
|
||||
}))
|
||||
: [
|
||||
{
|
||||
value: response,
|
||||
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(() => {
|
||||
strapi.notification.error('content-manager.notification.error.relationship.fetch');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleChange = (value) => {
|
||||
const filteredValue = value.filter((data, index ) => findIndex(value, (o) => o.value.id === data.value.id) === index);
|
||||
handleChange = value => {
|
||||
const filteredValue = value.filter(
|
||||
(data, index) => findIndex(value, o => o.value.id === data.value.id) === index
|
||||
);
|
||||
const target = {
|
||||
name: `record.${this.props.relation.alias}`,
|
||||
type: 'select',
|
||||
@ -74,37 +102,62 @@ class SelectMany extends React.Component { // eslint-disable-line react/prefer-s
|
||||
};
|
||||
|
||||
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() {
|
||||
const description = this.props.relation.description
|
||||
? <p>{this.props.relation.description}</p>
|
||||
: '';
|
||||
const description = this.props.relation.description ? (
|
||||
<p>{this.props.relation.description}</p>
|
||||
) : (
|
||||
''
|
||||
);
|
||||
|
||||
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 */
|
||||
return (
|
||||
<div className={`form-group ${styles.selectMany}`}>
|
||||
<label htmlFor={this.props.relation.alias}>{this.props.relation.alias}</label>
|
||||
{description}
|
||||
<Select.Async
|
||||
<Select
|
||||
onChange={this.handleChange}
|
||||
loadOptions={this.getOptions}
|
||||
options={this.state.options}
|
||||
id={this.props.relation.alias}
|
||||
isLoading={this.state.isLoading}
|
||||
onMenuScrollToBottom={this.handleBottomScroll}
|
||||
onInputChange={this.handleInputChange}
|
||||
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) {
|
||||
return {
|
||||
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>
|
||||
);
|
||||
@ -113,10 +166,7 @@ class SelectMany extends React.Component { // eslint-disable-line react/prefer-s
|
||||
}
|
||||
|
||||
SelectMany.propTypes = {
|
||||
record: PropTypes.oneOfType([
|
||||
PropTypes.object,
|
||||
PropTypes.bool,
|
||||
]).isRequired,
|
||||
record: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]).isRequired,
|
||||
relation: PropTypes.object.isRequired,
|
||||
setRecordAttribute: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
@ -8,7 +8,7 @@ import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import PropTypes from 'prop-types';
|
||||
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 templateObject from 'utils/templateObject';
|
||||
@ -21,23 +21,37 @@ class SelectOne extends React.Component { // eslint-disable-line react/prefer-st
|
||||
|
||||
this.state = {
|
||||
isLoading: true,
|
||||
options: [],
|
||||
toSkip: 0,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getOptions('');
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevState.toSkip !== this.state.toSkip) {
|
||||
this.getOptions('');
|
||||
}
|
||||
}
|
||||
|
||||
getOptions = (query) => {
|
||||
const params = {
|
||||
limit: 20,
|
||||
skip: this.state.toSkip,
|
||||
source: this.props.relation.plugin || 'content-manager',
|
||||
};
|
||||
|
||||
// Set `query` parameter if necessary
|
||||
if (query) {
|
||||
params.query = query;
|
||||
params.queryAttribute = this.props.relation.displayedAttribute;
|
||||
delete params.limit,
|
||||
delete params.skip,
|
||||
params[`${this.props.relation.displayedAttribute}_contains`] = query;
|
||||
}
|
||||
|
||||
// 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}`;
|
||||
|
||||
// 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,
|
||||
}];
|
||||
|
||||
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(() => {
|
||||
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 });
|
||||
// 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() {
|
||||
@ -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);
|
||||
// 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 */
|
||||
return (
|
||||
<div className={`form-group ${styles.selectOne}`}>
|
||||
<label htmlFor={this.props.relation.alias}>{this.props.relation.alias}</label>
|
||||
{description}
|
||||
<Select.Async
|
||||
<Select
|
||||
onChange={this.handleChange}
|
||||
loadOptions={this.getOptions}
|
||||
options={this.state.options}
|
||||
isLoading={this.state.isLoading}
|
||||
onMenuScrollToBottom={this.handleBottomScroll}
|
||||
onInputChange={this.handleInputChange}
|
||||
simpleValue
|
||||
value={isNull(value) || isUndefined(value) ? null : {
|
||||
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]);
|
||||
}
|
||||
|
||||
|
||||
@ -220,7 +220,7 @@ module.exports = {
|
||||
})
|
||||
}
|
||||
|
||||
if (association.type === 'model') {
|
||||
if (association.type === 'model' || (association.type === 'collection' && _.isObject(array))) {
|
||||
return _.isEmpty(array) ? [] : transformToArrayID([array]);
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||
"preanalyze": "npm run analyze:clean",
|
||||
"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": "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",
|
||||
@ -44,7 +44,7 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -11,7 +11,7 @@
|
||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||
"preanalyze": "npm run analyze:clean",
|
||||
"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": "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",
|
||||
@ -48,7 +48,7 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -11,7 +11,7 @@
|
||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||
"preanalyze": "npm run analyze:clean",
|
||||
"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": "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",
|
||||
@ -45,8 +45,8 @@
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 7.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -11,7 +11,7 @@
|
||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||
"preanalyze": "npm run analyze:clean",
|
||||
"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": "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",
|
||||
@ -45,7 +45,7 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -34,8 +34,8 @@ module.exports = async cb => {
|
||||
size text,
|
||||
url text,
|
||||
provider text,
|
||||
updated_at ${Model.client === 'pg' ? 'timestamp with time zone' : 'timestamp'},
|
||||
created_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 DEFAULT CURRENT_TIMESTAMP'}
|
||||
);
|
||||
|
||||
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",
|
||||
"preanalyze": "npm run analyze:clean",
|
||||
"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": "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",
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
"analyze:clean": "node ./node_modules/strapi-helper-plugin/node_modules/.bin/rimraf stats.json",
|
||||
"preanalyze": "npm run analyze:clean",
|
||||
"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": "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",
|
||||
@ -51,8 +51,8 @@
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 7.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -460,8 +460,8 @@ CREATE TABLE ${quote}${details[currentModel].tableName}${quote} (
|
||||
role ${details[currentModel].client === 'pg' ? 'integer' : 'int'},
|
||||
${quote}resetPasswordToken${quote} text,
|
||||
password text,
|
||||
updated_at ${details[currentModel].client === 'pg' ? 'timestamp with time zone' : 'timestamp'},
|
||||
created_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 DEFAULT CURRENT_TIMESTAMP'}
|
||||
);`);
|
||||
break;
|
||||
case 'role':
|
||||
|
||||
@ -1,8 +1,21 @@
|
||||
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.
|
||||
const silent = process.env.npm_config_debug !== 'true';
|
||||
const installationStartDate = new Date();
|
||||
|
||||
const watcher = (label, cmd, withSuccess = true) => {
|
||||
if (label.length > 0) {
|
||||
shell.echo(label);
|
||||
@ -21,6 +34,22 @@ const watcher = (label, cmd, withSuccess = true) => {
|
||||
shell.echo('✅ Success');
|
||||
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('');
|
||||
@ -57,7 +86,6 @@ if (shell.test('-e', 'admin/src/config/plugins.json') === false) {
|
||||
}
|
||||
|
||||
watcher('📦 Linking strapi-admin', 'npm link --no-optional', false);
|
||||
watcher('🏗 Building...', 'npm run build');
|
||||
|
||||
shell.cd('../strapi-generate-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('📦 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.rm('-f', 'package-lock.json');
|
||||
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');
|
||||
shell.rm('-f', 'package-lock.json');
|
||||
watcher('📦 Linking strapi-plugin-users-permissions...', 'npm link --no-optional', false);
|
||||
watcher('🏗 Building...', 'npm run build');
|
||||
|
||||
shell.cd('../strapi-plugin-content-manager');
|
||||
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
||||
shell.rm('-f', 'package-lock.json');
|
||||
watcher('📦 Linking strapi-plugin-content-manager...', 'npm link --no-optional', false);
|
||||
watcher('🏗 Building...', 'npm run build');
|
||||
|
||||
shell.cd('../strapi-plugin-settings-manager');
|
||||
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
||||
shell.rm('-f', 'package-lock.json');
|
||||
watcher('📦 Linking strapi-plugin-settings-manager...', 'npm link --no-optional', false);
|
||||
watcher('🏗 Building...', 'npm run build');
|
||||
|
||||
|
||||
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 and other plugin's dependencies
|
||||
shell.cd('../strapi-plugin-upload');
|
||||
watcher('', 'npm install ../strapi-helper-plugin --no-optional');
|
||||
watcher('', 'npm install ../strapi-upload-local --no-optional');
|
||||
shell.rm('-f', 'package-lock.json');
|
||||
watcher('📦 Linking strapi-plugin-upload...', 'npm link --no-optional', false);
|
||||
watcher('🏗 Building...', 'npm run build');
|
||||
|
||||
shell.cd('../strapi-plugin-content-type-builder');
|
||||
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');
|
||||
shell.rm('-f', 'package-lock.json');
|
||||
watcher('📦 Linking strapi-plugin-content-type-builder...', 'npm link --no-optional', false);
|
||||
watcher('🏗 Building...', 'npm run build');
|
||||
|
||||
shell.cd('../strapi-plugin-graphql');
|
||||
watcher('', 'npm install ../strapi-utils --no-optional');
|
||||
shell.rm('-f', 'package-lock.json');
|
||||
watcher('📦 Linking strapi-plugin-graphql...', 'npm link --no-optional', false);
|
||||
const pluginsToBuild = ['admin', 'content-manager', 'content-type-builder', 'upload', 'users-permissions', 'settings-manager'];
|
||||
|
||||
// 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.`);
|
||||
const buildPlugins = async () => {
|
||||
const build = (pckgName) => {
|
||||
return new Promise(resolve => {
|
||||
const name = pckgName === 'admin' ? pckgName: `plugin-${pckgName}`;
|
||||
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