mirror of
https://github.com/strapi/strapi.git
synced 2025-09-26 00:39:49 +00:00
Merge branch 'master' into fix-1885
This commit is contained in:
commit
c4cb9ccfab
BIN
docs/3.x.x/en/assets/internationalization.gif
Normal file
BIN
docs/3.x.x/en/assets/internationalization.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 875 KiB |
@ -117,7 +117,8 @@ This action sends an email to a user with the link of you reset password page. T
|
|||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
- `email` is your user email.
|
- `email` is your user email.
|
||||||
- `url` is the url link that user will receive.
|
- `url` is the url link that user will receive. After the user triggers a new password reset,
|
||||||
|
it is used to redirect the user to the new-password form.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -125,7 +126,7 @@ $.ajax({
|
|||||||
url: 'http://localhost:1337/auth/forgot-password',
|
url: 'http://localhost:1337/auth/forgot-password',
|
||||||
data: {
|
data: {
|
||||||
email: 'user@strapi.io',
|
email: 'user@strapi.io',
|
||||||
url: 'http://mon-site.com/rest-password'
|
url: 'http:/localhost:1337/admin/plugins/users-permissions/auth/reset-password'
|
||||||
},
|
},
|
||||||
done: function() {
|
done: function() {
|
||||||
console.log('Your user received an email');
|
console.log('Your user received an email');
|
||||||
@ -136,8 +137,6 @@ $.ajax({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
> Received link url format http://mon-site.com/rest-password?code=privateCode
|
|
||||||
|
|
||||||
## Reset user password.
|
## Reset user password.
|
||||||
|
|
||||||
This action will reset the user password.
|
This action will reset the user password.
|
||||||
@ -165,7 +164,7 @@ $.ajax({
|
|||||||
```
|
```
|
||||||
|
|
||||||
## User Object In Strapi Context
|
## User Object In Strapi Context
|
||||||
The User object is available to successfully authenticated requests.
|
The `user` object is available to successfully authenticated requests.
|
||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
- The authenticated `user` object is a property of `ctx.state`.
|
- The authenticated `user` object is a property of `ctx.state`.
|
||||||
@ -189,10 +188,9 @@ The User object is available to successfully authenticated requests.
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Add a new provider
|
## Add a new provider
|
||||||
|
|
||||||
To add a new provider on strapi, you will need to perform changes onto the following files:
|
To add a new provider on Strapi, you will need to perform changes onto the following files:
|
||||||
|
|
||||||
```
|
```
|
||||||
packages/strapi-plugin-users-permissions/services/Providers.js
|
packages/strapi-plugin-users-permissions/services/Providers.js
|
||||||
@ -203,7 +201,7 @@ packages/strapi-plugin-users-permissions/admin/src/translations/en.json
|
|||||||
|
|
||||||
We will go step by step.
|
We will go step by step.
|
||||||
|
|
||||||
### Configure your Provider request
|
### Configure your Provider Request
|
||||||
First, we need to configure our new provider onto `Provider.js` file.
|
First, we need to configure our new provider onto `Provider.js` file.
|
||||||
|
|
||||||
Jump onto the `getProfile` function, you will see the list of currently available providers in the form of a `switch...case`.
|
Jump onto the `getProfile` function, you will see the list of currently available providers in the form of a `switch...case`.
|
||||||
@ -212,9 +210,10 @@ As you can see, `getProfile` take three params:
|
|||||||
|
|
||||||
1. provider :: The name of the used provider as a string.
|
1. provider :: The name of the used provider as a string.
|
||||||
2. query :: The query is the result of the provider callback.
|
2. query :: The query is the result of the provider callback.
|
||||||
3. callback :: The callback function who will continue the internal strapi login logic.
|
3. callback :: The callback function who will continue the internal Strapi login logic.
|
||||||
|
|
||||||
Let's take the `discord` one as an example since it's not the easier, it should cover most of the case you may encounter trying to implement your own provider.
|
Let's take the `discord` one as an example since it's not the easier, it should cover most of the case you
|
||||||
|
may encounter trying to implement your own provider.
|
||||||
|
|
||||||
#### Configure your oauth generic information
|
#### Configure your oauth generic information
|
||||||
|
|
||||||
@ -239,9 +238,11 @@ Let's take the `discord` one as an example since it's not the easier, it should
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
So here, you can see that we use a module called `Purest`. This module gives us with a generic way to interact with the REST API.
|
So here, you can see that we use a module called `Purest`. This module gives us with a generic way to interact
|
||||||
|
with the REST API.
|
||||||
|
|
||||||
To understand each value usage, and the templating syntax, I invite you to read the [Official Purest Documentation](https://github.com/simov/purest/tree/2.x)
|
To understand each value usage, and the templating syntax, I invite you to read the [Official Purest Documentation](https://github.com/simov/purest/tree/2.x)
|
||||||
|
|
||||||
@ -265,17 +266,21 @@ You may also want to take a look onto the numerous already made configurations [
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Here is the next part of our switch. Now that we have properly configured our provider, we want to use it to retrieve user information.
|
Here is the next part of our switch. Now that we have properly configured our provider, we want to use it to retrieve
|
||||||
|
user information.
|
||||||
|
|
||||||
Here you see the real power of `purest`, you can simply make a get request on the desired URL, using the `access_token` from the `query` parameter to authenticate.
|
Here you see the real power of `purest`, you can simply make a get request on the desired URL, using the `access_token`
|
||||||
|
from the `query` parameter to authenticate.
|
||||||
|
|
||||||
That way, you should be able to retrieve the user info you need.
|
That way, you should be able to retrieve the user info you need.
|
||||||
|
|
||||||
Now, you can simply call the `callback` function with the username and email of your user. That way, strapi will be able to retrieve your user from the database and log you in.
|
Now, you can simply call the `callback` function with the username and email of your user. That way, strapi will be able
|
||||||
|
to retrieve your user from the database and log you in.
|
||||||
|
|
||||||
#### Configure the new provider model onto database
|
#### Configure the new provider model onto database
|
||||||
|
|
||||||
Now, we need to configure our 'model' for our new provider. That way, our settings can be stored in the database, and managed from the admin panel.
|
Now, we need to configure our 'model' for our new provider. That way, our settings can be stored in the database, and
|
||||||
|
managed from the admin panel.
|
||||||
|
|
||||||
Into: `packages/strapi-plugin-users-permissions/config/functions/bootstrap.js`
|
Into: `packages/strapi-plugin-users-permissions/config/functions/bootstrap.js`
|
||||||
|
|
||||||
@ -296,9 +301,8 @@ For our discord provider it will look like:
|
|||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You have already done the hard part, now, we simply need to make our new provider available from the front
|
||||||
You have already done the hard part, now, we simply need to make our new provider available from the front side of our application. So let's do it!
|
side of our application. So let's do it!
|
||||||
|
|
||||||
|
|
||||||
<!-- #### Tests -->
|
<!-- #### Tests -->
|
||||||
<!-- TODO Add documentation about how to configure unit test for the new provider -->
|
<!-- TODO Add documentation about how to configure unit test for the new provider -->
|
||||||
@ -323,7 +327,6 @@ These two change will set up the popup message who appear on the UI when we will
|
|||||||
|
|
||||||
That's it, now you should be able to use your new provider.
|
That's it, now you should be able to use your new provider.
|
||||||
|
|
||||||
|
|
||||||
## Email templates
|
## Email templates
|
||||||
|
|
||||||
[See the documentation on GitHub](https://github.com/strapi/strapi/blob/master/packages/strapi-plugin-users-permissions/docs/email-templates.md)
|
[See the documentation on GitHub](https://github.com/strapi/strapi/blob/master/packages/strapi-plugin-users-permissions/docs/email-templates.md)
|
||||||
|
@ -60,3 +60,17 @@ You need to define the english and french translation for this key.
|
|||||||
```
|
```
|
||||||
|
|
||||||
That's all! The request `GET /hello/John?locale=en_US` will return `Hello John` and `GET /hello/Tom?locale=fr_FR` will return `Bonjour Tom`.
|
That's all! The request `GET /hello/John?locale=en_US` will return `Hello John` and `GET /hello/Tom?locale=fr_FR` will return `Bonjour Tom`.
|
||||||
|
|
||||||
|
## Content Internationalization
|
||||||
|
|
||||||
|
Translating content from a language to another has been requested by many of you. As you may have seen on our website, the [Internationalization plugin](https://strapi.io/marketplace/internationalization) is not available yet because we need to go out of alpha before developing new plugins.
|
||||||
|
|
||||||
|
But, no worries, we have a good **work around to help you internationalize your content**!
|
||||||
|
|
||||||
|
The solution is simple: **suffix your fields**.
|
||||||
|
|
||||||
|
For example if you are building a blog with posts, you may have a Content Type `post` with two fields: `title` and `content`. To make them available in english and french for example, simply replace them by `title_en`, `title_fr`, `content_en` and `content_fr`.
|
||||||
|
|
||||||
|
Then, when you request your API, you will get all these fields in your response payload. If you want to select only some of them (in a specific language) we recommend you to use the [GraphQL plugin](graphql.md).
|
||||||
|
|
||||||
|

|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
"strapi-lint": "file:packages/strapi-lint"
|
"strapi-lint": "file:packages/strapi-lint"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "npm run removesymlinkdependencies && rm -rf package-lock.json && rm -rf packages/*/package-lock.json",
|
"clean": "npm run removesymlinkdependencies && npx rimraf package-lock.json && npx rimraf packages/*/package-lock.json",
|
||||||
"clean:all": "npm run removesymlinkdependencies && rm -rf package-lock.json && rm -rf packages/*/package-lock.json && rm -rf packages/*/node_modules",
|
"clean:all": "npm run removesymlinkdependencies && npx rimraf package-lock.json && npx rimraf packages/*/package-lock.json && npx rimraf packages/*/node_modules",
|
||||||
"doc": "node ./scripts/documentation.js",
|
"doc": "node ./scripts/documentation.js",
|
||||||
"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",
|
||||||
|
@ -9,5 +9,8 @@
|
|||||||
},
|
},
|
||||||
"cron": {
|
"cron": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"autoOpen": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,8 @@
|
|||||||
},
|
},
|
||||||
"cron": {
|
"cron": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"autoOpen": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,8 @@
|
|||||||
},
|
},
|
||||||
"cron": {
|
"cron": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"autoOpen": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,7 +260,7 @@ module.exports = (scope, cb) => {
|
|||||||
} catch(err) {
|
} catch(err) {
|
||||||
shell.rm('-r', scope.tmpPath);
|
shell.rm('-r', scope.tmpPath);
|
||||||
console.log(err);
|
console.log(err);
|
||||||
cb.success();
|
cb.error();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Node.js core.
|
|
||||||
const execSync = require('child_process').execSync;
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
// Public node modules
|
// Public node modules
|
||||||
const inquirer = require('inquirer');
|
const inquirer = require('inquirer');
|
||||||
|
const rimraf = require('rimraf');
|
||||||
|
|
||||||
module.exports = (scope, success, error) => {
|
module.exports = (scope, success, error) => {
|
||||||
const knex = require(path.resolve(`${scope.tmpPath}/node_modules/knex`))({
|
const knex = require('knex')({
|
||||||
client: scope.client.module,
|
client: scope.client.module,
|
||||||
connection: Object.assign({}, scope.database.settings, {
|
connection: Object.assign({}, scope.database.settings, {
|
||||||
user: scope.database.settings.username
|
user: scope.database.settings.username
|
||||||
@ -20,9 +17,12 @@ module.exports = (scope, success, error) => {
|
|||||||
knex.destroy();
|
knex.destroy();
|
||||||
|
|
||||||
const next = () => {
|
const next = () => {
|
||||||
execSync(`rm -r "${scope.tmpPath}"`);
|
rimraf(scope.tmpPath, (err) => {
|
||||||
|
if (err) {
|
||||||
success();
|
console.log(`Error removing connection test folder: ${scope.tmpPath}`);
|
||||||
|
}
|
||||||
|
success();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (tables.rows && tables.rows.length !== 0) {
|
if (tables.rows && tables.rows.length !== 0) {
|
||||||
@ -33,7 +33,7 @@ module.exports = (scope, success, error) => {
|
|||||||
name: 'confirm',
|
name: 'confirm',
|
||||||
message: `Are you sure you want to continue with the ${scope.database.settings.database} database:`,
|
message: `Are you sure you want to continue with the ${scope.database.settings.database} database:`,
|
||||||
}])
|
}])
|
||||||
.then(({confirm}) => {
|
.then(({ confirm }) => {
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"inquirer": "^5.2.0",
|
"inquirer": "^5.2.0",
|
||||||
"lodash": "^4.17.5",
|
"lodash": "^4.17.5",
|
||||||
"pluralize": "^6.0.0",
|
"pluralize": "^6.0.0",
|
||||||
|
"rimraf": "^2.6.2",
|
||||||
"strapi-hook-knex": "3.0.0-alpha.14.1.1",
|
"strapi-hook-knex": "3.0.0-alpha.14.1.1",
|
||||||
"strapi-utils": "3.0.0-alpha.14.1.1"
|
"strapi-utils": "3.0.0-alpha.14.1.1"
|
||||||
},
|
},
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Node.js core.
|
// Public node modules
|
||||||
const execSync = require('child_process').execSync;
|
const rimraf = require('rimraf');
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
module.exports = (scope, success, error) => {
|
module.exports = (scope, success, error) => {
|
||||||
const Mongoose = require(path.resolve(`${scope.tmpPath}/node_modules/mongoose`));
|
const Mongoose = require('mongoose');
|
||||||
|
|
||||||
const { username, password, srv } = scope.database.settings;
|
const { username, password, srv } = scope.database.settings;
|
||||||
const { authenticationDatabase, ssl } = scope.database.options;
|
const { authenticationDatabase, ssl } = scope.database.options;
|
||||||
@ -36,8 +35,11 @@ module.exports = (scope, success, error) => {
|
|||||||
|
|
||||||
Mongoose.connection.close();
|
Mongoose.connection.close();
|
||||||
|
|
||||||
execSync(`rm -r "${scope.tmpPath}"`);
|
rimraf(scope.tmpPath, (err) => {
|
||||||
|
if (err) {
|
||||||
success();
|
console.log(`Error removing connection test folder: ${scope.tmpPath}`);
|
||||||
|
}
|
||||||
|
success();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
"mongoose": "^5.0.16",
|
"mongoose": "^5.0.16",
|
||||||
"mongoose-float": "^1.0.2",
|
"mongoose-float": "^1.0.2",
|
||||||
"pluralize": "^6.0.0",
|
"pluralize": "^6.0.0",
|
||||||
|
"rimraf": "^2.6.2",
|
||||||
"strapi-utils": "3.0.0-alpha.14.1.1"
|
"strapi-utils": "3.0.0-alpha.14.1.1"
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* eslint-disable import/no-unresolved */
|
// Public node modules
|
||||||
// Node.js core.
|
const rimraf = require('rimraf');
|
||||||
const execSync = require('child_process').execSync;
|
|
||||||
|
|
||||||
// Logger.
|
// Logger.
|
||||||
const logger = require('strapi-utils').logger;
|
const logger = require('strapi-utils').logger;
|
||||||
|
|
||||||
module.exports = (scope, success, error) => {
|
module.exports = (scope, success, error) => {
|
||||||
const Redis = require(`${scope.tmpPath}/node_modules/ioredis`);
|
const Redis = require(`ioredis`);
|
||||||
const redis = new Redis({
|
const redis = new Redis({
|
||||||
port: scope.database.settings.port,
|
port: scope.database.settings.port,
|
||||||
host: scope.database.settings.host,
|
host: scope.database.settings.host,
|
||||||
@ -26,10 +25,14 @@ module.exports = (scope, success, error) => {
|
|||||||
|
|
||||||
logger.info('The app has been connected to the database successfully!');
|
logger.info('The app has been connected to the database successfully!');
|
||||||
|
|
||||||
execSync(`rm -r "${scope.tmpPath}"`);
|
rimraf(scope.tmpPath, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(`Error removing connection test folder: ${scope.tmpPath}`);
|
||||||
|
}
|
||||||
|
logger.info('Copying the dashboard...');
|
||||||
|
|
||||||
logger.info('Copying the dashboard...');
|
success();
|
||||||
|
});
|
||||||
|
|
||||||
success();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ioredis": "^3.1.2",
|
"ioredis": "^3.1.2",
|
||||||
"lodash": "^4.17.5",
|
"lodash": "^4.17.5",
|
||||||
|
"rimraf": "^2.6.2",
|
||||||
"stack-trace": "0.0.10",
|
"stack-trace": "0.0.10",
|
||||||
"strapi-utils": "3.0.0-alpha.14.1.1"
|
"strapi-utils": "3.0.0-alpha.14.1.1"
|
||||||
},
|
},
|
||||||
|
@ -173,9 +173,7 @@ class Wysiwyg extends React.Component {
|
|||||||
if (selectedText !== '') {
|
if (selectedText !== '') {
|
||||||
return this.setState(
|
return this.setState(
|
||||||
{
|
{
|
||||||
// Move the cursor to the end (this line forces the cursor to be at the end of the content)
|
editorState: newEditorState,
|
||||||
// It may go at the end of the last block
|
|
||||||
editorState: EditorState.moveFocusToEnd(newEditorState),
|
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this.focus();
|
this.focus();
|
||||||
@ -309,7 +307,14 @@ class Wysiwyg extends React.Component {
|
|||||||
const newContentState = this.createNewContentStateFromBlock(newBlock);
|
const newContentState = this.createNewContentStateFromBlock(newBlock);
|
||||||
const newEditorState = this.createNewEditorState(newContentState, text);
|
const newEditorState = this.createNewEditorState(newContentState, text);
|
||||||
|
|
||||||
return this.setState({ editorState: EditorState.moveFocusToEnd(newEditorState) });
|
return this.setState(
|
||||||
|
{
|
||||||
|
editorState: newEditorState,
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.focus();
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -143,7 +143,7 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if user is adding a relation with the same content type
|
// Check if user is adding a relation with the same content type
|
||||||
|
|
||||||
if (includes(this.props.hash, 'attributerelation') && this.props.modifiedDataAttribute.params.target === this.props.modelName && get(this.props.modifiedDataAttribute, ['params', 'nature'], '') !== 'oneWay') {
|
if (includes(this.props.hash, 'attributerelation') && this.props.modifiedDataAttribute.params.target === this.props.modelName && get(this.props.modifiedDataAttribute, ['params', 'nature'], '') !== 'oneWay') {
|
||||||
// Insert two attributes
|
// Insert two attributes
|
||||||
this.props.addAttributeRelationToContentType(this.props.modifiedDataAttribute);
|
this.props.addAttributeRelationToContentType(this.props.modifiedDataAttribute);
|
||||||
@ -418,7 +418,7 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
|
|||||||
if (includes(this.props.hash, 'choose')) {
|
if (includes(this.props.hash, 'choose')) {
|
||||||
const { nodeToFocus } = this.state;
|
const { nodeToFocus } = this.state;
|
||||||
let toAdd = 0;
|
let toAdd = 0;
|
||||||
|
|
||||||
switch(e.keyCode) {
|
switch(e.keyCode) {
|
||||||
case 37: // Left arrow
|
case 37: // Left arrow
|
||||||
case 39: // Right arrow
|
case 39: // Right arrow
|
||||||
@ -446,7 +446,7 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
|
|||||||
toAdd = 0;
|
toAdd = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(prevState => ({ nodeToFocus: prevState.nodeToFocus + toAdd }));
|
this.setState(prevState => ({ nodeToFocus: prevState.nodeToFocus + toAdd }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -456,7 +456,6 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
|
|||||||
const hashArray = split(this.props.hash, ('::'));
|
const hashArray = split(this.props.hash, ('::'));
|
||||||
const valueToReplace = includes(this.props.hash, '#create') ? '#create' : '#edit';
|
const valueToReplace = includes(this.props.hash, '#create') ? '#create' : '#edit';
|
||||||
const contentTypeName = replace(hashArray[0], valueToReplace, '');
|
const contentTypeName = replace(hashArray[0], valueToReplace, '');
|
||||||
|
|
||||||
let cbSuccess;
|
let cbSuccess;
|
||||||
let dataSucces = null;
|
let dataSucces = null;
|
||||||
let cbFail;
|
let cbFail;
|
||||||
@ -466,7 +465,7 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
|
|||||||
// Check if the user is editing the attribute
|
// Check if the user is editing the attribute
|
||||||
const isAttribute = includes(hashArray[1], 'attribute');
|
const isAttribute = includes(hashArray[1], 'attribute');
|
||||||
cbSuccess = isAttribute ? () => this.editTempContentTypeAttribute(redirectToChoose) : this.createContentType;
|
cbSuccess = isAttribute ? () => this.editTempContentTypeAttribute(redirectToChoose) : this.createContentType;
|
||||||
dataSucces = isAttribute ? null : this.props.modifiedDataEdit;
|
dataSucces = isAttribute ? null : this.getModelWithCamelCaseName(this.props.modifiedDataEdit);
|
||||||
cbFail = isAttribute ? () => this.editContentTypeAttribute(redirectToChoose) : this.contentTypeEdit;
|
cbFail = isAttribute ? () => this.editContentTypeAttribute(redirectToChoose) : this.contentTypeEdit;
|
||||||
return this.testContentType(contentTypeName, cbSuccess, dataSucces, cbFail);
|
return this.testContentType(contentTypeName, cbSuccess, dataSucces, cbFail);
|
||||||
}
|
}
|
||||||
@ -476,11 +475,24 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
|
|||||||
return this.testContentType(contentTypeName, cbSuccess, dataSucces, cbFail);
|
return this.testContentType(contentTypeName, cbSuccess, dataSucces, cbFail);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return this.createContentType(this.props.modifiedData);
|
return this.createContentType(
|
||||||
|
this.getModelWithCamelCaseName(this.props.modifiedData)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getModelWithCamelCaseName = (model = {}) => {
|
||||||
|
if (isEmpty(model) || isEmpty(model.name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...model,
|
||||||
|
name: camelCase(model.name),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
initComponent = (props, condition) => {
|
initComponent = (props, condition) => {
|
||||||
if (!isEmpty(props.hash)) {
|
if (!isEmpty(props.hash)) {
|
||||||
this.setState({ showModal: true });
|
this.setState({ showModal: true });
|
||||||
@ -514,7 +526,7 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderModalBodyChooseAttributes = () => {
|
renderModalBodyChooseAttributes = () => {
|
||||||
const attributesDisplay = has(this.context.plugins.toJS(), 'upload')
|
const attributesDisplay = has(this.context.plugins.toJS(), 'upload')
|
||||||
? forms.attributesDisplay.items
|
? forms.attributesDisplay.items
|
||||||
: forms.attributesDisplay.items.filter(obj => obj.type !== 'media'); // Don't display the media field if the upload plugin isn't installed
|
: forms.attributesDisplay.items.filter(obj => obj.type !== 'media'); // Don't display the media field if the upload plugin isn't installed
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@ module.exports = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let options = ctx.request.body;
|
let options = ctx.request.body;
|
||||||
|
|
||||||
await strapi.plugins.email.services.send(options, config);
|
await strapi.plugins.email.services.email.send(options, config);
|
||||||
|
|
||||||
// Send 200 `ok`
|
// Send 200 `ok`
|
||||||
ctx.send({});
|
ctx.send({});
|
||||||
@ -48,7 +48,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getSettings: async (ctx) => {
|
getSettings: async (ctx) => {
|
||||||
let config = await strapi.plugins.email.services.email.getProviderConfig(ctx.params.environment);
|
let config = await strapi.plugins.email.services.email.getProviderConfig(ctx.params.environment);
|
||||||
|
|
||||||
ctx.send({
|
ctx.send({
|
||||||
providers: strapi.plugins.email.config.providers,
|
providers: strapi.plugins.email.config.providers,
|
||||||
|
@ -113,14 +113,16 @@ button {
|
|||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flexed {
|
.flexed,
|
||||||
|
.label {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
width: 15rem;
|
width: 15rem;
|
||||||
height: 5.2rem;
|
height: 5.2rem;
|
||||||
line-height: 5.2rem;
|
|
||||||
margin-left: 5rem;
|
margin-left: 5rem;
|
||||||
color: #333740;
|
color: #333740;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
@ -2,24 +2,23 @@ const path = require('path');
|
|||||||
const shell = require('shelljs');
|
const shell = require('shelljs');
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
const eslintErrorsFormatter = require('./eslintErrorsFormatter');
|
const eslintErrorsFormatter = require('./eslintErrorsFormatter');
|
||||||
const glob = require('glob');
|
|
||||||
const fs = require('fs');
|
|
||||||
const listChangedFiles = require('../packages/strapi-lint/lib/internals/shared/listChangedFiles.js');
|
const listChangedFiles = require('../packages/strapi-lint/lib/internals/shared/listChangedFiles.js');
|
||||||
const changedFiles = listChangedFiles();
|
const changedFiles = listChangedFiles();
|
||||||
const { includes, take } = require('lodash');
|
const { take, template } = require('lodash');
|
||||||
|
|
||||||
const frontCmd =
|
const cmdEslint = template(
|
||||||
'node ../../node_modules/strapi-lint/node_modules/.bin/eslint --ignore-path .gitignore --ignore-pattern \'/admin/build/\' --config ../../node_modules/strapi-lint/lib/internals/eslint/front/.eslintrc.json admin';
|
'node ../../node_modules/strapi-lint/node_modules/.bin/eslint --ignore-path .gitignore --ignore-pattern "${ignore}"'
|
||||||
const helperCmd =
|
+ ' --config ../../node_modules/strapi-lint/lib/internals/eslint/${conf}/.eslintrc.json ${params}'
|
||||||
'node ../../node_modules/strapi-lint/node_modules/.bin/eslint --ignore-path .gitignore --ignore-pattern \'/admin/build/\' --config ../../node_modules/strapi-lint/lib/internals/eslint/front/.eslintrc.json lib/src';
|
);
|
||||||
const backCmd =
|
|
||||||
'node ../../node_modules/strapi-lint/node_modules/.bin/eslint --ignore-path .gitignore --ignore-pattern \'/admin\' --config ../../node_modules/strapi-lint/lib/internals/eslint/back/.eslintrc.json controllers config services bin lib';
|
|
||||||
|
|
||||||
|
const cmdFront = cmdEslint({ ignore: '/admin/build/', conf: 'front', params: 'admin' });
|
||||||
|
const cmdHelper = cmdEslint({ ignore: '/admin/build/', conf: 'front', params: 'lib/src' });
|
||||||
|
const cmdBack = cmdEslint({ ignore: '/admin', conf: 'back', params: 'controllers config services bin lib' });
|
||||||
|
|
||||||
const watcher = (label, pckgName, type = 'front') => {
|
const watcher = (label, pckgName) => {
|
||||||
shell.echo(label);
|
shell.echo(label);
|
||||||
shell.cd(pckgName);
|
shell.cd(pckgName);
|
||||||
const cmd = includes(pckgName, 'strapi-helper-plugin') ? helperCmd : `${frontCmd} && ${backCmd}`;
|
const cmd = pckgName.includes('strapi-helper-plugin') ? cmdHelper : `${cmdFront} && ${cmdBack}`;
|
||||||
|
|
||||||
const data = shell.exec(cmd, { silent: true });
|
const data = shell.exec(cmd, { silent: true });
|
||||||
shell.echo(chalk(eslintErrorsFormatter(data.stdout)));
|
shell.echo(chalk(eslintErrorsFormatter(data.stdout)));
|
||||||
@ -31,19 +30,17 @@ const watcher = (label, pckgName, type = 'front') => {
|
|||||||
shell.echo('');
|
shell.echo('');
|
||||||
};
|
};
|
||||||
|
|
||||||
const files = glob
|
const except = [
|
||||||
.sync('**/*.js', { ignore: '**/node_modules/**' })
|
'jest.config.js',
|
||||||
.filter(f => changedFiles.has(f))
|
'scripts',
|
||||||
.filter(
|
'strapi-lint',
|
||||||
package =>
|
'strapi-middleware-views',
|
||||||
!package.includes('README.md') &&
|
'strapi-plugin-settings-manager',
|
||||||
!package.includes('strapi-middleware-views') &&
|
'test',
|
||||||
!package.includes('strapi-lint') &&
|
];
|
||||||
!package.includes('strapi-plugin-settings-manager') &&
|
|
||||||
!package.includes('scripts') &&
|
const changedDirs = [...changedFiles]
|
||||||
!package.includes('test') &&
|
.filter(file => path.extname(file) === '.js' && !except.some(path => file.includes(path)))
|
||||||
!package.includes('jest.config.js')
|
|
||||||
)
|
|
||||||
.map(file => {
|
.map(file => {
|
||||||
const directoryArray = file.split('/');
|
const directoryArray = file.split('/');
|
||||||
const toTake = directoryArray.length === 2 ? 1 : 2;
|
const toTake = directoryArray.length === 2 ? 1 : 2;
|
||||||
@ -51,9 +48,7 @@ const files = glob
|
|||||||
return take(directoryArray, toTake).join('/');
|
return take(directoryArray, toTake).join('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
[...new Set(changedDirs)]
|
||||||
files
|
.forEach(directory => {
|
||||||
.filter((directory, index) => files.indexOf(directory) === index)
|
watcher(`Testing ${directory}`, directory);
|
||||||
.forEach(package => {
|
});
|
||||||
watcher(`Testing ${package}`, package);
|
|
||||||
});
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user