mirror of
https://github.com/strapi/strapi.git
synced 2025-12-11 23:15:15 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
d2eb881ca8
1
.gitignore
vendored
1
.gitignore
vendored
@ -78,6 +78,7 @@ $RECYCLE.BIN/
|
||||
*#
|
||||
.idea
|
||||
nbproject
|
||||
.vscode/
|
||||
|
||||
|
||||
############################
|
||||
|
||||
125
CONTRIBUTING.md
125
CONTRIBUTING.md
@ -1,6 +1,6 @@
|
||||
# Contribute to Strapi
|
||||
|
||||
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
|
||||
First off, thanks for taking the time to contribute! 🎉👍
|
||||
|
||||
The following is a set of guidelines for contributing to Strapi and its packages.
|
||||
|
||||
@ -21,51 +21,126 @@ Every user can send a feature request using the [issues](https://github.com/stra
|
||||
## Repository Organization
|
||||
We made the choice to use a monorepo design such as [React](https://github.com/facebook/react/tree/master/packages), [Babel](https://github.com/babel/babel/tree/master/packages), [Meteor](https://github.com/meteor/meteor/tree/devel/packages) or [Ember](https://github.com/emberjs/ember.js/tree/master/packages) do. It allows the community to easily maintain the whole ecosystem up-to-date and consistent.
|
||||
|
||||
The Babel team wrotes an excellent short post about [the pros and cons of the monorepo design](https://github.com/babel/babel/blob/master/doc/design/monorepo.md).
|
||||
The Babel team wrote an excellent short post about [the pros and cons of the monorepo design](https://github.com/babel/babel/blob/master/doc/design/monorepo.md).
|
||||
|
||||
We will do our best to keep the master branch clean as possible, with tests passing all the times. However, it can happen that the master branch moves faster than the release cycle. To ensure to use the latest stable version, please refers to the [release on npm](https://www.npmjs.com/package/strapi).
|
||||
We will do our best to keep the master branch as clean as possible, with tests passing all the times. However, it can happen that the master branch moves faster than the release cycle. To ensure you have the latest stable version, please refer to the [release on npm](https://www.npmjs.com/package/strapi).
|
||||
|
||||
If you send a pull request, please do it again the `master` branch. We are developing upcoming versions separately to ensure non-breaking changes from master to the latest stable major version.
|
||||
If you send a pull request, please do it against the `master` branch. We are developing upcoming versions separately to ensure non-breaking changes from master to the latest stable major version.
|
||||
|
||||
***
|
||||
|
||||
## Setup Development Environment
|
||||
To facilitate the contribution, we drastically reduce the amount of commands necessary to install the entire development environment. First of all, you need to check if you're using the recommended versions of Node.js (v8) and npm (v5).
|
||||
|
||||
**Then, please follow the instructions below:**
|
||||
Then, please follow the instructions below:
|
||||
|
||||
1. [Fork the repository](https://github.com/strapi/strapi) to your own GitHub account.
|
||||
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.
|
||||
#### 1. ▪️ Fork the repository
|
||||
|
||||
> 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.
|
||||
[Go to the repository](https://github.com/strapi/strapi) and fork it to your own GitHub account.
|
||||
|
||||
> Note: You can run `npm run setup:build` to build the plugins' admin (the setup time will be longer).
|
||||
#### 2. 💿 Clone the repository
|
||||
|
||||
```bash
|
||||
git clone git@github.com:strapi/strapi.git
|
||||
```
|
||||
|
||||
The development environment has been installed. Now, you have to create a development project to live-test your updates.
|
||||
#### 3. ⏳ Installation
|
||||
|
||||
Go to the root of the repository.
|
||||
```bash
|
||||
cd strapi
|
||||
```
|
||||
|
||||
1. Go to a folder on your computer `cd /path/to/my/folder`.
|
||||
2. Create a new project `strapi new myDevelopmentProject --dev`.
|
||||
3. Start your app with `strapi start`.
|
||||
**Two setup are available... with or without the front-end builds.**
|
||||
|
||||
Awesome! You are now able to make bug fixes or enhancements in the framework layer of Strapi. **To make updates in the administration panel, you need to go a little bit further.**
|
||||
Without the front-end builds, you won't be able to access the administration panel via http://localhost:1337/admin. You'll have to run the administration separately and access it through http://localhost:4000/admin.
|
||||
|
||||
4. Open a new tab or new terminal window.
|
||||
5. Go to the `my-app/admin` folder of your currently running app.
|
||||
6. Run `npm start` and go to the following url [http://localhost:4000/admin](http://localhost:4000/admin)
|
||||
<br>
|
||||
|
||||
Without the front-end builds (recommended)
|
||||
```bash
|
||||
npm run setup
|
||||
```
|
||||
or with the front-end builds
|
||||
```bash
|
||||
npm run setup:build
|
||||
```
|
||||
|
||||
> ⚠️ 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.
|
||||
|
||||
#### 4. 🏗 Create a new project
|
||||
|
||||
You can open a new terminal window and go into any folder you want for the next steps.
|
||||
```bash
|
||||
cd /.../workspace/
|
||||
```
|
||||
|
||||
The command to generate a project is the same, except you have to add the `--dev` argument at the end of line.
|
||||
```bash
|
||||
strapi new my-project --dev
|
||||
```
|
||||
|
||||
#### 5. 🚀 Start the project
|
||||
|
||||
First, you have to start the server.
|
||||
```bash
|
||||
cd ./my-project
|
||||
strapi start
|
||||
```
|
||||
|
||||
The server (API) is available at http://localhost:1337
|
||||
|
||||
> ⚠️ If you've followed the recommended setup, you should not be able to reach the administration panel at http://localhost:1337/admin.
|
||||
|
||||
Then, you have to start the Webpack server to build and run the administration.
|
||||
```bash
|
||||
cd ./my-project/admin
|
||||
npm run start
|
||||
```
|
||||
|
||||
The administration panel is available at http://localhost:4000/admin
|
||||
|
||||
**Awesome! You are now able to contribute to Strapi.**
|
||||
|
||||
---
|
||||
|
||||
## Plugin Development Setup
|
||||
|
||||
To create a new plugin, you'll have to run the following commands
|
||||
To create a new plugin, you'll have to run the following commands:
|
||||
|
||||
1. In your project folder `cd myDevelopmentProject && strapi generate:plugin my-plugin`.
|
||||
2. Make sure that the `strapi-helper-plugin` is linked to your plugin
|
||||
- In the folder where strapi is cloned `cd pathToStrapiRepo/strapi/packages/strapi-helper-plugin && npm link`.
|
||||
- In your project folder `cd pathToMyProject/myDevelopmentProject/plugins/my-plugin && npm link strapi-helper-plugin`.
|
||||
3. Start the server in the admin folder `cd pathToMyProject/myDevelopmentProject/admin && npm start` and go to the following url [http://localhost:4000/admin](http://localhost:4000/admin).
|
||||
#### 1. 🏗 Generate a new plugin
|
||||
|
||||
***
|
||||
```bash
|
||||
cd ./my-project
|
||||
strapi generate:plugin my-plugin
|
||||
```
|
||||
|
||||
#### 2. ✅ Verify the symlink
|
||||
|
||||
Make you that the `strapi-helper-plugin` is linked to your project.
|
||||
|
||||
Please run this command in the repository folder where Strapi is cloned:
|
||||
```bash
|
||||
cd /repository/strapi/packages/strapi-helper-plugin
|
||||
npm link
|
||||
```
|
||||
|
||||
Link the `strapi-helper-plugin` node_modules in the plugin folder:
|
||||
```bash
|
||||
cd ./my-project/plugins/my-plugin
|
||||
npm link strapi-helper-plugin
|
||||
```
|
||||
|
||||
#### 3. 🚀 Start the project
|
||||
|
||||
```bash
|
||||
cd ./my-project/admin
|
||||
npm run start
|
||||
```
|
||||
|
||||
The administration panel is available at http://localhost:4000/admin
|
||||
|
||||
---
|
||||
|
||||
## Reporting an issue
|
||||
|
||||
|
||||
110
README.md
110
README.md
@ -1,51 +1,95 @@
|
||||
<p align="center"><img src="https://blog.strapi.io/content/images/2017/10/logo.png" width="318px" /></p>
|
||||
<p align="center">
|
||||
<strong>We're hiring!</strong> Located in Paris 🇫🇷 and dreaming of being full-time on Strapi?
|
||||
<a href="https://strapi.io/company#looking-for-talents">Join us</a>!
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<a href="https://strapi.io">
|
||||
<img src="https://blog.strapi.io/content/images/2017/10/logo.png" width="318px" alt="Strapi logo" />
|
||||
</a>
|
||||
</p>
|
||||
<h3 align="center">API creation made simple, secure and fast.</h3>
|
||||
<p align="center">The most advanced open-source Content Management Framework to build powerful API with no effort.</p>
|
||||
<p align="center">The most advanced open-source Content Management Framework (headless-CMS) to build powerful API with no effort.</p>
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.org/package/strapi">
|
||||
<img src="https://img.shields.io/npm/v/strapi.svg" alt="Dependency Status" />
|
||||
<img src="https://img.shields.io/npm/v/strapi/alpha.svg" alt="NPM Version" />
|
||||
</a>
|
||||
<a href="https://www.npmjs.org/package/strapi">
|
||||
<img src="https://img.shields.io/npm/dm/strapi.svg" alt="Dependency Status" />
|
||||
<img src="https://img.shields.io/npm/dm/strapi.svg" alt="Monthly download on NPM" />
|
||||
</a>
|
||||
<a href="https://travis-ci.org/strapi/strapi">
|
||||
<img src="https://travis-ci.org/strapi/strapi.svg?branch=master" alt="Dependency Status" />
|
||||
<img src="https://travis-ci.org/strapi/strapi.svg?branch=master" alt="Travis Build Status" />
|
||||
</a>
|
||||
<a href="http://slack.strapi.io">
|
||||
<img src="http://strapi-slack.herokuapp.com/badge.svg" alt="Dependency Status" />
|
||||
<img src="https://strapi-slack.herokuapp.com/badge.svg" alt="Strapi on Slack" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<br>
|
||||
|
||||
<p align="center"><img src="https://blog.strapi.io/content/images/2017/10/Github-Preview.png" /></p>
|
||||
<p align="center">
|
||||
<a href="https://strapi.io">
|
||||
<img src="https://blog.strapi.io/content/images/2018/08/github_preview-2.png" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<br>
|
||||
|
||||
## Quick start
|
||||
## Getting Started
|
||||
|
||||
We've been working on a major update to Strapi for several months now, rewriting the core framework and the administration panel. Performances has been increased, Developer eXperience has been improved and a brand new plugins
|
||||
ecosystem has been introduced. **Both versions are available, we still recommend you to use v1 for production usage.**.
|
||||
<a href="https://strapi.io/getting-started" target="_blank">Read the Getting Started tutorial</a> or follow the steps below:
|
||||
|
||||
#### 🖐 Requirements
|
||||
|
||||
Node:
|
||||
* NodeJS >= 10.x
|
||||
* NPM >= 6.x
|
||||
|
||||
Database:
|
||||
* MongoDB >= 3.x
|
||||
* MySQL >= 5.6
|
||||
* MariaDB >= 10.1
|
||||
* PostgreSQL >= 10
|
||||
|
||||
#### ⏳ Installation
|
||||
|
||||
```bash
|
||||
npm install strapi@alpha -g
|
||||
````
|
||||
|
||||
**We recommend to use the latest version of Strapi to start your new project**.
|
||||
Some breaking changes might happen, new releases are shipped every two weeks to fix/enhance the product.
|
||||
|
||||
#### 🏗 Create a new project
|
||||
|
||||
```bash
|
||||
strapi new my-project
|
||||
```
|
||||
|
||||
It will generate a brand new project with the default features (authentication, permissions, content management, content type builder & file upload).
|
||||
|
||||
#### 🚀 Start your project
|
||||
|
||||
```bash
|
||||
cd my-project
|
||||
strapi start
|
||||
```
|
||||
|
||||
Congratulations, you made it! Enjoy 🎉
|
||||
|
||||
<br>
|
||||
|
||||
You can also give it a try using Heroku! Be aware that one of the content type builder won't work due to the writing files restriction on the Heroku servers.
|
||||
|
||||
<a href="https://heroku.com/deploy?template=https://github.com/strapi/strapi-heroku-app">
|
||||
<img src="https://www.herokucdn.com/deploy/button.svg" alt="Deploy">
|
||||
</a>
|
||||
|
||||
#### Alpha
|
||||
<br>
|
||||
|
||||
The alpha has support for the latest version of Node.js (v9) and npm (v5).
|
||||
```bash
|
||||
npm install strapi@alpha -g
|
||||
```
|
||||
|
||||
#### Stable
|
||||
This is the production-ready version of Strapi (v1). You should also consider that the migration to v3 will not be easy due to many breaking changes.
|
||||
```bash
|
||||
npm install strapi -g
|
||||
```
|
||||
|
||||
Read the [Getting started](https://strapi.io/getting-started) page to create your first project using Strapi.
|
||||
|
||||
## Features
|
||||
|
||||
@ -58,19 +102,17 @@ Read the [Getting started](https://strapi.io/getting-started) page to create you
|
||||
- **Powerful CLI:** Scaffold projects and APIs on the fly.
|
||||
- **SQL & NoSQL databases:** Work with Mongo as a main database, also supports Postgres, MySQL, etc.
|
||||
|
||||
## Philosophy ?
|
||||
**[See more on our website](https://strapi.io/overview)**
|
||||
|
||||
> At [Strapi](https://strapi.io), everything we do we believe in changing the status quo of web development. Our products are simple to use, user friendly and production-ready.
|
||||
## Contributing
|
||||
|
||||
Web and mobile applications needed a powerful, simple to use and production-ready API-driven solution. That's why we created Strapi, an open-source Content Management Framework (CMF) for exposing your content (data, media) accross multi-devices.
|
||||
|
||||
Halfway between a CMS and a framework, Strapi takes advantages of both worlds. A powerful dashboard to easily manage your content with a flexible framework layer to develop and integrate specific features.
|
||||
Please read our [Contributing Guide](./CONTRIBUTING.md) before submitting a Pull Request to the project.
|
||||
|
||||
## Support
|
||||
|
||||
For more information on the upcoming version, please take a look to our [ROADMAP](https://github.com/strapi/strapi/projects).
|
||||
|
||||
### Community support
|
||||
#### Community support
|
||||
|
||||
For general help using Strapi, please refer to [the official Strapi documentation](https://strapi.io/documentation/). For additional help, you can use one of this channel to ask question:
|
||||
|
||||
@ -80,13 +122,15 @@ For general help using Strapi, please refer to [the official Strapi documentatio
|
||||
- [Twitter](https://twitter.com/strapijs)
|
||||
- [Facebook](https://www.facebook.com/Strapi-616063331867161).
|
||||
|
||||
### Professional support
|
||||
#### Professional support
|
||||
|
||||
[Strapi Solutions](https://strapi.io), the company behind Strapi, provides a full range of solutions to get better results, faster. We're always looking for the next challenge: coaching, consulting, training, customization, etc. [Drop us an email](mailto:support@strapi.io) to see how we can help you.
|
||||
[Strapi Solutions](https://strapi.io), the company behind Strapi, provides a full range of solutions to get better results, faster. We're always looking for the next challenge: coaching, consulting, training, customization, etc.
|
||||
|
||||
### Migration
|
||||
[Drop us an email](mailto:support@strapi.io) to see how we can help you.
|
||||
|
||||
Follow our [migration guides](https://github.com/strapi/strapi/wiki) on the wiki to keep your Strapi projects updated.
|
||||
## Migration
|
||||
|
||||
Follow our [migration guides](https://github.com/strapi/strapi/wiki) on the wiki to keep your projects up-to-date.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@ -15,10 +15,10 @@ The most advanced open-source Content Management Framework to build powerful API
|
||||
|
||||
{% endcenter %}
|
||||
|
||||
## v3@alpha.12 is available!
|
||||
## v3@alpha.14 is available!
|
||||
We've been working on a major update for Strapi during the past months, rewriting the core framework and the dashboard.
|
||||
|
||||
This documentation is only related to Strapi v3@alpha.12 ([v1 documentation is still available](http://strapi.io/documentation/1.x.x)).
|
||||
This documentation is only related to Strapi v3@alpha.14 ([v1 documentation is still available](http://strapi.io/documentation/1.x.x)).
|
||||
|
||||
**[Get Started](getting-started/installation.md)**<br />
|
||||
Learn how to install Strapi and start developing your API.
|
||||
|
||||
@ -62,6 +62,8 @@ The panel will be available through [http://localhost:1337/dashboard](http://loc
|
||||
|
||||
### Development mode
|
||||
|
||||
Note that to modify the administration panel, your project needs to be created with using the `dev` flag, an example of such would be: `strapi new strapi --dev`.
|
||||
|
||||
**#1 — Install its own dependencies**
|
||||
|
||||
Run `npm install` from the `./admin` folder.
|
||||
@ -99,14 +101,16 @@ Note: make sure the size of your image is the same as the existing one (434px x
|
||||
|
||||
## Build
|
||||
|
||||
To build the administration, run the following command from the `./admin` folder:
|
||||
To build the administration, run the following command from the root directory of your project.
|
||||
|
||||
```
|
||||
npm run build
|
||||
npm run setup
|
||||
```
|
||||
|
||||
This will replace the folder's content located at `./admin/admin/build`. Visit http://localhost:1337/admin/ to make sure your updates have been taken in account.
|
||||
|
||||
After you have built the admininistration you can now create a new project to develop your API with the changes implemented. **Note:** You should now create a project without `--dev`
|
||||
|
||||
***
|
||||
|
||||
## Deployment
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Hooks
|
||||
|
||||
The hooks are modules that add functionality to the core. They are loaded during the server boot. For example, if your project needs to work with a SQL database, your will have to add the hook `strapi-bookshelf` to be able to connect your app with your database.
|
||||
The hooks are modules that add functionality to the core. They are loaded during the server boot. For example, if your project needs to work with a SQL database, your will have to add the hook `strapi-hook-bookshelf` to be able to connect your app with your database.
|
||||
|
||||
**Path —** `./hooks/documentation/lib/index.js`.
|
||||
```js
|
||||
@ -76,13 +76,13 @@ The `index.js` is the entry point to your hook. It should look like the example
|
||||
|
||||
## Dependencies
|
||||
|
||||
It happens that a hook has a dependency to another one. For example, the `strapi-bookshelf` has a dependency to `strapi-knex`. Without it, the `strapi-bookshelf` can't work correctly. It also means that the `strapi-knex` hook has to be loaded before.
|
||||
It happens that a hook has a dependency to another one. For example, the `strapi-hook-bookshelf` has a dependency to `strapi-hook-knex`. Without it, the `strapi-hook-bookshelf` can't work correctly. It also means that the `strapi-hook-knex` hook has to be loaded before.
|
||||
|
||||
To handle this case, you need to update the `package.json` at the root of your hook.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "strapi-bookshelf",
|
||||
"name": "strapi-hook-bookshelf",
|
||||
"version": "x.x.x",
|
||||
"description": "Bookshelf hook for the Strapi framework",
|
||||
"dependencies": {
|
||||
@ -90,10 +90,10 @@ To handle this case, you need to update the `package.json` at the root of your h
|
||||
},
|
||||
"strapi": {
|
||||
"dependencies": [
|
||||
"strapi-knex"
|
||||
"strapi-hook-knex"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Custom hooks
|
||||
@ -107,7 +107,9 @@ The framework allows to load hooks from the project directly without having to i
|
||||
└─── config
|
||||
└─── hooks
|
||||
│ └─── strapi-documentation
|
||||
│ - index.js
|
||||
│ └─── strapi-server-side-rendering
|
||||
│ - index.js
|
||||
└─── plugins
|
||||
└─── public
|
||||
- favicon.ico
|
||||
|
||||
@ -65,8 +65,12 @@ The core of Strapi embraces a small list of middlewares for performances, securi
|
||||
A middleware needs to follow the structure below:
|
||||
|
||||
```
|
||||
/lib
|
||||
- index.js
|
||||
/middleware
|
||||
└─── lib
|
||||
- index.js
|
||||
- LICENSE.md
|
||||
- package.json
|
||||
- README.md
|
||||
```
|
||||
|
||||
The `index.js` is the entry point to your middleware. It should look like the example above.
|
||||
@ -82,7 +86,9 @@ The framework allows the application to override the default middlewares and add
|
||||
└─── config
|
||||
└─── middlewares
|
||||
│ └─── responseTime // It will override the core default responseTime middleware
|
||||
│ - index.js
|
||||
│ └─── views // It will be added into the stack of middleware
|
||||
│ - index.js
|
||||
└─── plugins
|
||||
└─── public
|
||||
- favicon.ico
|
||||
|
||||
@ -13,7 +13,7 @@ Here is the list of the collected data and why we need them.
|
||||
*Understand how the developers are using the different configurations? How many projects are started in production mode?*
|
||||
- **Node modules names**
|
||||
*Are developers integrating Strapi with Stripe? It means that we should develop a plugin to simplify the development process with Stripe.
|
||||
Are developers using Strapi with strapi-bookshelf or strapi-mongoose? It helps us prioritize the issues.*
|
||||
Are developers using Strapi with strapi-hook-bookshelf or strapi-hook-mongoose? It helps us prioritize the issues.*
|
||||
- **OS**
|
||||
*Is the community using Windows, Linux or Mac? It helps us prioritize the issues.*
|
||||
- **Build configurations**
|
||||
|
||||
@ -11,7 +11,7 @@ Create a new project
|
||||
```bash
|
||||
strapi new <name>
|
||||
|
||||
options: [--dev|--dbclient=<dbclient> --dbhost=<dbhost> --dbport=<dbport> --dbname=<dbname> --dbusername=<dbusername> --dbpassword=<dbpassword>]
|
||||
options: [--dev|--dbclient=<dbclient> --dbhost=<dbhost> --dbport=<dbport> --dbname=<dbname> --dbusername=<dbusername> --dbpassword=<dbpassword> --dbssl=<dbssl> --dbauth=<dbauth>]
|
||||
```
|
||||
|
||||
- **strapi new <name>**<br/>
|
||||
@ -20,8 +20,8 @@ options: [--dev|--dbclient=<dbclient> --dbhost=<dbhost> --dbport=<dbport> --dbna
|
||||
- **strapi new <name> --dev**<br/>
|
||||
Generates a new project called **<name>** and creates symlinks for the `./admin` folder and each plugin inside the `./plugin` folder. It means that the Strapi's development workflow has been set up on the machine earlier.
|
||||
|
||||
- **strapi new <name> --dbclient=<dbclient> --dbhost=<dbhost> --dbport=<dbport> --dbname=<dbname> --dbusername=<dbusername> --dbpassword=<dbpassword>**<br/>
|
||||
Generates a new project called **<name>** and skip the interactive database configuration and initilize with these options. **<dbclient>** can be `mongo`, `postgres`, `mysql`, `sqlite3` or `redis`. **<dbusername>** and **<dbpassword>** are optional.
|
||||
- **strapi new <name> --dbclient=<dbclient> --dbhost=<dbhost> --dbport=<dbport> --dbname=<dbname> --dbusername=<dbusername> --dbpassword=<dbpassword> --dbssl=<dbssl> --dbauth=<dbauth>**<br/>
|
||||
Generates a new project called **<name>** and skip the interactive database configuration and initilize with these options. **<dbclient>** can be `mongo`, `postgres`, `mysql`, `sqlite3` or `redis`. **<dbssl>** and **<dbauth>** are optional.
|
||||
|
||||
|
||||
See the [CONTRIBUTING guide](https://github.com/strapi/strapi/blob/master/CONTRIBUTING.md) for more details.
|
||||
|
||||
@ -146,7 +146,7 @@ In this example, there is a `User` model which contains two attributes `firstnam
|
||||
|
||||
### Where are the models defined?
|
||||
|
||||
The models are defined in each `./api/**/models/` folder. Every JavaScript or JSON file in these folders will be loaded as a model. They are also available through the `strapi.models` and `strapi.api.**.models` global variables. Usable every where in the project, they contain the ORM model object that they are refer to. By convention, models' names should be Pascal-cased, so that every word in the file (including the first one) is capitalized `User.js`, `User.settings.json`, `LegalEntity.js`, `LegalEntity.settings.json`.
|
||||
The models are defined in each `./api/**/models/` folder. Every JavaScript or JSON file in these folders will be loaded as a model. They are also available through the `strapi.models` and `strapi.api.**.models` global variables. Usable every where in the project, they contain the ORM model object that they are refer to. By convention, models' names should be written in lowercase.
|
||||
|
||||
### Attributes
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Configurations
|
||||
|
||||
The main configurations of the project are located in the `./config` directory. Additional configs can be added in the `./api/**/config` folder of each APIs and plugins by creating JavaScript or JSON files.
|
||||
The main configurations of the project are located in the `./config` directory. Additional configs can be added in the `./api/**/config` folder of each API and plugin by creating JavaScript or JSON files.
|
||||
|
||||
## Application
|
||||
|
||||
@ -153,7 +153,7 @@ Each JSON file located in the folder must have the name of its corresponding tra
|
||||
|
||||
Most of the application's configurations are defined by environment. It means that you can specify settings for each environment (`development`, `production`, `test`, etc.).
|
||||
|
||||
> Note: You can access to the config of the current environment through `strapi.config.currentEnvironment`.
|
||||
> Note: You can access the config of the current environment through `strapi.config.currentEnvironment`.
|
||||
|
||||
***
|
||||
|
||||
@ -164,14 +164,9 @@ Most of the application's configurations are defined by environment. It means th
|
||||
- `defaultConnection` (string): Connection by default for models which are not related to a specific `connection`. Default value: `default`.
|
||||
- `connections` List of all available connections.
|
||||
- `default`
|
||||
- `connector` (string): Connector used by the current connection. Default value: `strapi-mongoose`.
|
||||
- `client` (string): Client used to store session. Default value: `cookie`.
|
||||
- `key` (string): Cookie key name. Default value: `strapi.sid`
|
||||
- `maxAge` (integer): Time in milliseconds before the session expire. Default value: `86400000`.
|
||||
- `rolling` (boolean): Force a session identifier cookie to be set on every response. Default value: `false`.
|
||||
- `signed` (boolean): httpOnly or not. Default value: `true`.
|
||||
- `overwrite` (boolean): Can overwrite or not. Default value: `true`.
|
||||
- `connector` (string): Connector used by the current connection. Default value: `strapi-hook-mongoose`.
|
||||
- `settings` Useful for external session stores such as Redis.
|
||||
- `client` (string): Database client to create the connection. Default value: `mongo`.
|
||||
- `host` (string): Database host name. Default value: `localhost`.
|
||||
- `port` (integer): Database port. Default value: `27017`.
|
||||
- `database` (string): Database name. Default value: `development`.
|
||||
@ -192,7 +187,7 @@ Most of the application's configurations are defined by environment. It means th
|
||||
"defaultConnection": "default",
|
||||
"connections": {
|
||||
"default": {
|
||||
"connector": "strapi-mongoose",
|
||||
"connector": "strapi-hook-mongoose",
|
||||
"settings": {
|
||||
"client": "mongo",
|
||||
"host": "localhost",
|
||||
@ -208,14 +203,14 @@ Most of the application's configurations are defined by environment. It means th
|
||||
}
|
||||
},
|
||||
"postgres": {
|
||||
"connector": "strapi-bookshelf",
|
||||
"connector": "strapi-hook-bookshelf",
|
||||
"settings": {
|
||||
"client": "postgres",
|
||||
"host": "localhost",
|
||||
"port": 5432,
|
||||
"username": "aureliengeorget",
|
||||
"password": "${process.env.USERNAME}",
|
||||
"database": "${process.env.PWD}",
|
||||
"username": "${process.env.USERNAME}",
|
||||
"password": "${process.env.PWD}",
|
||||
"database": "strapi",
|
||||
"schema": "public"
|
||||
},
|
||||
"options": {
|
||||
@ -223,12 +218,12 @@ Most of the application's configurations are defined by environment. It means th
|
||||
}
|
||||
},
|
||||
"mysql": {
|
||||
"connector": "strapi-bookshelf",
|
||||
"connector": "strapi-hook-bookshelf",
|
||||
"settings": {
|
||||
"client": "mysql",
|
||||
"host": "localhost",
|
||||
"port": 5432,
|
||||
"username": "aureliengeorget",
|
||||
"username": "strapi",
|
||||
"password": "root",
|
||||
"database": ""
|
||||
},
|
||||
@ -335,10 +330,18 @@ Most of the application's configurations are defined by environment. It means th
|
||||
|
||||
- `host` (string): Host name. Default value: `localhost`.
|
||||
- `port` (integer): Port on which the server should be running. Default value: `1337`.
|
||||
- `autoReload` (boolean): Enable or disabled server reload on files update. Default value: depends on the environment.
|
||||
- `autoReload`
|
||||
- `enabled` (boolean): Enable or disabled server reload on files update. Default value: depends on the environment.
|
||||
- `emitErrors` (boolean): Enable errors to be emited to `koa` when they happen in order to attach custom logic or use error reporting services.
|
||||
- `proxy`
|
||||
- `enabled` (boolean): Enable proxy support such as Apache or Nginx. Default value: `false`.
|
||||
- `ssl` (boolean): Enable proxy SSL support
|
||||
- `host` (string): Host name your proxy service uses for Strapi.
|
||||
- `port` (integer): Port that your proxy service accepts connections on.
|
||||
- [`cron`](https://en.wikipedia.org/wiki/Cron)
|
||||
- `enabled` (boolean): Enable or disable CRON tasks to schedule jobs at specific dates. Default value: `false`.
|
||||
- `admin`
|
||||
- `autoOpen` (boolean): Enable or disabled administration opening on start (default: `true`)
|
||||
- `path` (string): Allow to change the URL to access the admin (default: `/admin`).
|
||||
- `build`
|
||||
- `host` (string): URL to access the admin panel (default: `http://localhost:1337/admin`).
|
||||
@ -347,6 +350,33 @@ Most of the application's configurations are defined by environment. It means th
|
||||
- `source` (string): Define the source mode (origin, host, custom).
|
||||
- `folder` (string): Indicate what the plugins folder in `host` source mode.
|
||||
|
||||
#### Example
|
||||
|
||||
**Path —** `./config/environments/**/server.json`.
|
||||
|
||||
As an example using this configuration with Nginx your server would respond to `https://example.com:8443` instead of `http://localhost:1337`
|
||||
|
||||
**Note:** you will need to configure Nginx or Apache as a proxy before configuring this example.
|
||||
|
||||
```json
|
||||
{
|
||||
"host": "localhost",
|
||||
"port": 1337,
|
||||
"proxy": {
|
||||
"enabled": true,
|
||||
"ssl": true,
|
||||
"host": "example.com",
|
||||
"port": 8443
|
||||
},
|
||||
"autoReload": {
|
||||
"enabled": true
|
||||
},
|
||||
"cron": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Dynamic configurations
|
||||
@ -367,7 +397,7 @@ In any JSON configurations files in your project, you can inject dynamic values
|
||||
"defaultConnection": "default",
|
||||
"connections": {
|
||||
"default": {
|
||||
"connector": "strapi-mongoose",
|
||||
"connector": "strapi-hook-mongoose",
|
||||
"settings": {
|
||||
"client": "mongo",
|
||||
"uri": "${process.env.DATABASE_URI || ''}",
|
||||
|
||||
@ -77,7 +77,7 @@ At this point, your application is empty. To create your first API is to use the
|
||||
|
||||

|
||||
|
||||
**#2 —** Create a Content Type name `Product` and submit the form.
|
||||
**#2 —** Create a Content Type named `Product` and submit the form.
|
||||
|
||||

|
||||
|
||||
@ -92,7 +92,7 @@ At this point, your application is empty. To create your first API is to use the
|
||||
**#4 —** Save. That's it!
|
||||
|
||||
|
||||
> Note: See the [CLI documentation](../cli/CLI.md#strapi-generateapi) for informations about how to do it the hacker way.
|
||||
> Note: See the [CLI documentation](../cli/CLI.md#strapi-generateapi) for more information on how to do it the hacker way.
|
||||
|
||||
### Files structure
|
||||
|
||||
|
||||
@ -59,7 +59,8 @@ $.ajax({
|
||||
|
||||
Thanks to [Grant](https://github.com/simov/grant) and [Purest](https://github.com/simov/purest), you can easily use OAuth and OAuth2
|
||||
providers to enable authentication in your application. By default,
|
||||
Strapi comes with four providers:
|
||||
Strapi comes with the following providers:
|
||||
- [Discord](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/discord_setup.md)
|
||||
- [Facebook](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/fb_setup.md)
|
||||
- [Google](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/google_setup.md)
|
||||
- [Github](https://github.com/strapi/strapi-examples/blob/master/login-react/doc/github_setup.md)
|
||||
@ -189,6 +190,140 @@ The User object is available to successfully authenticated requests.
|
||||
```
|
||||
|
||||
|
||||
## Add a new provider
|
||||
|
||||
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/config/functions/bootstrap.js
|
||||
packages/strapi-plugin-users-permissions/admin/src/components/PopUpForm/index.js
|
||||
packages/strapi-plugin-users-permissions/admin/src/translations/en.json
|
||||
```
|
||||
|
||||
We will go step by step.
|
||||
|
||||
### Configure your Provider request
|
||||
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`.
|
||||
|
||||
As you can see, `getProfile` take three params:
|
||||
|
||||
1. provider :: The name of the used provider as a string.
|
||||
2. query :: The query is the result of the provider callback.
|
||||
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.
|
||||
|
||||
#### Configure your oauth generic information
|
||||
|
||||
```js
|
||||
case 'discord': {
|
||||
const discord = new Purest({
|
||||
provider: 'discord',
|
||||
config: {
|
||||
'discord': {
|
||||
'https://discordapp.com/api/': {
|
||||
'__domain': {
|
||||
'auth': {
|
||||
'auth': {'bearer': '[0]'}
|
||||
}
|
||||
},
|
||||
'{endpoint}': {
|
||||
'__path': {
|
||||
'alias': '__default'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
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)
|
||||
|
||||
You may also want to take a look onto the numerous already made configurations [here](https://github.com/simov/purest-providers/blob/master/config/providers.json).
|
||||
|
||||
#### Retrieve your user informations:
|
||||
```js
|
||||
discord.query().get('users/@me').auth(access_token).request((err, res, body) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
// Combine username and discriminator because discord username is not unique
|
||||
var username = `${body.username}#${body.discriminator}`;
|
||||
callback(null, {
|
||||
username: username,
|
||||
email: body.email
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
#### 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.
|
||||
|
||||
Into: `packages/strapi-plugin-users-permissions/config/functions/bootstrap.js`
|
||||
|
||||
Simply add the fields your provider need into the `grantConfig` object.
|
||||
For our discord provider it will look like:
|
||||
|
||||
```js
|
||||
discord: {
|
||||
enabled: false, // make this provider disabled by default
|
||||
icon: 'comments', // The icon to use on the UI
|
||||
key: '', // our provider app id (leave it blank, you will fill it with the content manager)
|
||||
secret: '', // our provider secret key (leave it blank, you will fill it with the content manager)
|
||||
callback: '/auth/discord/callback', // the callback endpoint of our provider
|
||||
scope: [ // the scope that we need from our user to retrieve infos
|
||||
'identify',
|
||||
'email'
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
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!
|
||||
|
||||
|
||||
<!-- #### Tests -->
|
||||
<!-- TODO Add documentation about how to configure unit test for the new provider -->
|
||||
|
||||
### Configure frontend for your new provider
|
||||
|
||||
First, let's edit: `packages/strapi-plugin-users-permissions/admin/src/components/PopUpForm/index.js`
|
||||
As for backend, we have a `switch...case` where we need to put our new provider info.
|
||||
|
||||
```js
|
||||
case 'discord':
|
||||
return `${strapi.backendURL}/connect/discord/callback`;
|
||||
```
|
||||
|
||||
Add the corresponding translation into: `packages/strapi-plugin-users-permissions/admin/src/translations/en.json`
|
||||
|
||||
```js
|
||||
"PopUpForm.Providers.discord.providerConfig.redirectURL": "The redirect URL to add in your Discord application configurations",
|
||||
````
|
||||
|
||||
These two change will set up the popup message who appear on the UI when we will configure our new provider.
|
||||
|
||||
That's it, now you should be able to use your new provider.
|
||||
|
||||
|
||||
## Email templates
|
||||
|
||||
[See the documentation on GitHub](https://github.com/strapi/strapi/blob/master/packages/strapi-plugin-users-permissions/docs/email-templates.md)
|
||||
|
||||
@ -18,6 +18,9 @@ Update the `production` settings with the IP and domain name where the project w
|
||||
}
|
||||
```
|
||||
|
||||
In case your database is not running on the same server, make sure that the environment of your production
|
||||
database (`./config/environments/production/database.json`) is set properly.
|
||||
|
||||
**⚠️ If you changed the path to access to the administration, the step #2 is required.**
|
||||
|
||||
#### #2 - Setup (optional)
|
||||
|
||||
@ -27,8 +27,8 @@ To install a new provider run:
|
||||
$ npm install strapi-email-sendgrid@alpha --save
|
||||
```
|
||||
|
||||
We have two providers available `strapi-email-sendgrid` and `strapi-upload-mailgun`, use the alpha tag to install one of them. Then, visit `/admin/plugins/email/configurations/development` and configure the provider.
|
||||
We have two providers available `strapi-email-sendgrid` and `strapi-upload-mailgun`, use the alpha tag to install one of them. Then, visit `/admin/plugins/email/configurations/development` on your web browser and configure the provider.
|
||||
|
||||
If you want to create your own, make sure the name starts with `strapi-email-` (duplicating an existing one will be easier to create), modify the `auth` config object and customize the `send` functions.
|
||||
|
||||
Check all community providers available on npmjs.org - [Providers list](https://www.npmjs.com/search?q=strapi-email-)
|
||||
Check all community providers available on npmjs.org - [Providers list](https://www.npmjs.com/search?q=strapi-email-)
|
||||
|
||||
@ -146,6 +146,149 @@ type Query {
|
||||
|
||||
The query will use the generated controller's actions as resolvers. It means that the `posts` query will execute the `Post.find` action and the `post` query will use the `Post.findOne` action.
|
||||
|
||||
## Aggregation & Grouping
|
||||
> This feature is only available on Mongoose ORM.
|
||||
|
||||
Strapi now supports Aggregation & Grouping.
|
||||
Let's consider again the model mentioned above:
|
||||
```
|
||||
type Post {
|
||||
_id: ID
|
||||
createdAt: String
|
||||
updatedAt: String
|
||||
title: String
|
||||
content: String
|
||||
nb_likes: Int,
|
||||
published: Boolean
|
||||
}
|
||||
|
||||
```
|
||||
Strapi will generate automatically for you the following queries & types:
|
||||
|
||||
### Aggregation
|
||||
```
|
||||
type PostConnection {
|
||||
values: [Post]
|
||||
groupBy: PostGroupBy
|
||||
aggregate: PostAggregator
|
||||
}
|
||||
|
||||
type PostGroupBy {
|
||||
_id: [PostConnection_id]
|
||||
createdAt: [PostConnectionCreatedAt]
|
||||
updatedAt: [PostConnectionUpdatedAt]
|
||||
title: [PostConnectionTitle]
|
||||
content: [PostConnectionContent]
|
||||
nb_likes: [PostConnectionNbLikes],
|
||||
published: [PostConnectionPublished]
|
||||
}
|
||||
|
||||
type PostConnectionPublished {
|
||||
key: Boolean
|
||||
connection: PostConnection
|
||||
}
|
||||
|
||||
type PostAggregator {
|
||||
count: Int
|
||||
sum: PostAggregatorSum
|
||||
avg: PostAggregatorAvg
|
||||
min: PostAggregatorMin
|
||||
max: PostAggregatorMax
|
||||
}
|
||||
|
||||
type PostAggregatorAvg {
|
||||
nb_likes: Float
|
||||
}
|
||||
|
||||
type PostAggregatorMin { // Same for max and sum
|
||||
nb_likes: Int
|
||||
}
|
||||
|
||||
type Query {
|
||||
postsConnection(sort: String, limit: Int, start: Int, where: JSON): PostConnection
|
||||
}
|
||||
```
|
||||
|
||||
Getting the total count and the average likes of posts:
|
||||
|
||||
```
|
||||
postsConnection {
|
||||
aggregate {
|
||||
count
|
||||
avg {
|
||||
nb_likes
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Let's say we want to do the same query but for only published posts
|
||||
```
|
||||
postsConnection(where: { published: true }) {
|
||||
aggregate {
|
||||
count
|
||||
avg {
|
||||
nb_likes
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Gettings the average likes of published and unpublished posts
|
||||
|
||||
```
|
||||
postsConnection {
|
||||
groupBy {
|
||||
published: {
|
||||
key
|
||||
connection {
|
||||
aggregate {
|
||||
avg {
|
||||
nb_likes
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Result
|
||||
```JSON
|
||||
{
|
||||
data: {
|
||||
postsConnection: {
|
||||
groupBy: {
|
||||
published: [
|
||||
{
|
||||
key: true,
|
||||
connection: {
|
||||
aggregate: {
|
||||
avg {
|
||||
nb_likes: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: false,
|
||||
connection: {
|
||||
aggregate: {
|
||||
avg {
|
||||
nb_likes: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Customise the GraphQL schema
|
||||
|
||||
If you want to define a new scalar, input or enum types, this section is for you. To do so, you will have to create a `schema.graphql` file. This file has to be placed into the config folder of each API `./api/*/config/schema.graphql` or plugin `./plugins/*/config/schema.graphql`.
|
||||
|
||||
@ -19,6 +19,11 @@ The info key on the model-json states information about the model. This informat
|
||||
- `description`: The description of the model.
|
||||
- `mainField`: Determines which model-attribute is shown when displaying the model.
|
||||
|
||||
## Model options
|
||||
The options key on the model-json states.
|
||||
- `idAttribute`: This tells the model which attribute to expect as the unique identifier for each database row (typically an auto-incrementing primary key named 'id').
|
||||
- `idAttributeType`: Data type of `idAttribute`, accepted list of value bellow:
|
||||
|
||||
## Define the attributes
|
||||
|
||||
The following types are currently available:
|
||||
|
||||
@ -11,7 +11,7 @@ There are several ways to create a policy.
|
||||
**Path —** `./config/policies/isAuthenticated.js`.
|
||||
```js
|
||||
module.exports = async (ctx, next) => {
|
||||
if (ctx.session.isAuthenticated === true) {
|
||||
if (ctx.state.user) {
|
||||
// Go to next policy or will reach the controller's action.
|
||||
return await next();
|
||||
}
|
||||
@ -22,7 +22,7 @@ module.exports = async (ctx, next) => {
|
||||
|
||||
In this example, we are verifying that a session is open. If it is the case, we call the `next()` method that will execute the next policy or controller's action. Otherwise, a 401 error is returned.
|
||||
|
||||
> Note: You can access to any controllers, services or models thanks to the global variable `strapi` in a policy.
|
||||
> Note: You can access any controllers, services, or models by using the global variable `strapi` in a policy.
|
||||
|
||||
## Usage
|
||||
|
||||
@ -87,7 +87,7 @@ The scoped policies can only be associated to the routes defined in the API wher
|
||||
**Path —** `./api/car/config/policies/isAdmin.js`.
|
||||
```js
|
||||
module.exports = async (ctx, next) => {
|
||||
if (ctx.session.user.role === 'administrator') {
|
||||
if (ctx.state.user.role.name === 'Administrator') {
|
||||
// Go to next policy or will reach the controller's action.
|
||||
return await next();
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ The plugin exposes a single route `POST /upload` to upload one or multiple files
|
||||
**Parameters**
|
||||
|
||||
- `files`: The file(s) to upload. The value(s) can be a Buffer or Stream.
|
||||
- `path`: (optional): The folder where the file(s) will be uploaded to (only supported on strapi-upload-aws-s3 now).
|
||||
- `refId`: (optional): The ID of the entry which the file(s) will be linked to.
|
||||
- `ref`: (optional): The name of the model which the file(s) will be linked to (see more below).
|
||||
- `source`: (optional): The name of the plugin where the model is located.
|
||||
@ -111,6 +112,7 @@ Let's say that you want to have a `User` model provided by the plugin `Users & P
|
||||
```js
|
||||
{
|
||||
"files": "...", // Buffer or stream of file(s)
|
||||
"path": "user/avatar", // Uploading folder of file(s).
|
||||
"refId": "5a993616b8e66660e8baf45c", // User's Id.
|
||||
"ref": "user", // Model name.
|
||||
"source": "users-permissions", // Plugin name.
|
||||
@ -133,7 +135,7 @@ To install a new provider run:
|
||||
$ npm install strapi-upload-aws-s3@alpha --save
|
||||
```
|
||||
|
||||
We have two providers available `strapi-upload-aws-s3` and `strapi-upload-cloudinary`, use the alpha tag to install one of them. Then, visit `/admin/plugins/upload/configurations/development` and configure the provider.
|
||||
We have two providers available `strapi-upload-aws-s3` and `strapi-upload-cloudinary`, use the alpha tag to install one of them. Then, visit `/admin/plugins/upload/configurations/development` on your web browser and configure the provider.
|
||||
|
||||
If you want to create your own, make sure the name starts with `strapi-upload-` (duplicating an existing one will be easier to create), modify the `auth` config object and customize the `upload` and `delete` functions.
|
||||
|
||||
|
||||
@ -346,7 +346,7 @@ const send = require('koa-send');
|
||||
|
||||
module.exports = {
|
||||
autoReload: async ctx => {
|
||||
ctx.send({ autoReload: _.get(strapi.config.environments, 'development.server.autoReload', false) });
|
||||
ctx.send({ autoReload: _.get(strapi.config.currentEnvironment, 'server.autoReload', { enabled: false }) });
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -374,8 +374,8 @@ import request from 'utils/request';
|
||||
const shouldRenderCompo = (plugin) => new Promise((resolve, request) => {
|
||||
request('/my-plugin/autoReload')
|
||||
.then(response => {
|
||||
// If autoReload is enabled the response is `{ autoReload: true }`
|
||||
plugin.preventComponentRendering = !response.autoReload;
|
||||
// If autoReload is enabled the response is `{ autoReload: { enabled: true } }`
|
||||
plugin.preventComponentRendering = !response.autoReload.enabled;
|
||||
// Set the BlockerComponent props
|
||||
plugin.blockerComponentProps = {
|
||||
blockerComponentTitle: 'my-plugin.blocker.title',
|
||||
@ -407,8 +407,8 @@ import MyCustomBlockerComponent from 'components/MyCustomBlockerComponent';
|
||||
const shouldRenderCompo = (plugin) => new Promise((resolve, request) => {
|
||||
request('/my-plugin/autoReload')
|
||||
.then(response => {
|
||||
// If autoReload is enabled the response is `{ autoReload: true }`
|
||||
plugin.preventComponentRendering = !response.autoReload;
|
||||
// If autoReload is enabled the response is `{ autoReload: { enabled: true } }`
|
||||
plugin.preventComponentRendering = !response.autoReload.enabled;
|
||||
|
||||
// Tell which component to be rendered instead
|
||||
plugin.blockerComponent = MyCustomBlockerComponent;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "3.0.0-alpha.12.7.1",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"assert": "~1.3.0",
|
||||
|
||||
1
packages/strapi-admin/.gitignore
vendored
1
packages/strapi-admin/.gitignore
vendored
@ -3,6 +3,7 @@ coverage
|
||||
node_modules
|
||||
stats.json
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Cruft
|
||||
.DS_Store
|
||||
|
||||
1
packages/strapi-admin/admin/.gitignore
vendored
1
packages/strapi-admin/admin/.gitignore
vendored
@ -5,6 +5,7 @@ manifest.json
|
||||
plugins.json
|
||||
stats.json
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Cruft
|
||||
.DS_Store
|
||||
|
||||
@ -129,7 +129,7 @@ if (window.location.port !== '4000') {
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
console.log(err); // eslint-disable-line no-console
|
||||
});
|
||||
} else if (findIndex(plugins, ['id', 'users-permissions']) === -1) {
|
||||
store.dispatch(unsetHasUserPlugin());
|
||||
|
||||
@ -15,7 +15,7 @@ const style = {
|
||||
top: '0',
|
||||
right: '0',
|
||||
display: 'flex',
|
||||
zIndex: '999',
|
||||
zIndex: '1050',
|
||||
};
|
||||
|
||||
CTAWrapper.propTypes = {
|
||||
|
||||
@ -7,14 +7,6 @@
|
||||
import React from 'react';
|
||||
import styles from './styles.scss';
|
||||
|
||||
class Header extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.header}>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default function Header() {
|
||||
return <div className={styles.header} />;
|
||||
}
|
||||
|
||||
export default Header;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
width: 100%;
|
||||
height: $header-height;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
z-index: 1040;
|
||||
left: $left-menu-width;
|
||||
|
||||
box-shadow: 0 1px 2px 0 rgba(40, 42, 49, 0.16);
|
||||
|
||||
@ -20,9 +20,10 @@ class LeftMenuLink extends React.Component {
|
||||
// We need to create our own active url checker,
|
||||
// because of the two levels router.
|
||||
const isLinkActive = startsWith(
|
||||
window.location.pathname.replace('/admin', ''),
|
||||
this.props.destination,
|
||||
window.location.pathname.replace('/admin', '').concat('/'),
|
||||
this.props.destination.concat('/'),
|
||||
);
|
||||
|
||||
const plugin =
|
||||
this.props.source !== 'content-manager' && this.props.source !== '' ? (
|
||||
<div className={styles.plugin}>
|
||||
|
||||
@ -69,13 +69,17 @@ function LeftMenuLinkContainer({ layout, plugins }) {
|
||||
// Check if the plugins list is empty or not and display plugins by name
|
||||
const pluginsLinks = !isEmpty(pluginsObject) ? (
|
||||
map(sortBy(pluginsObject, 'name'), plugin => {
|
||||
if (plugin.id !== 'email' && plugin.id !== 'content-manager' && plugin.id !== 'settings-manager') {
|
||||
if (plugin.id !== 'email' && plugin.id !== 'settings-manager') {
|
||||
const basePath = `/plugins/${get(plugin, 'id')}`;
|
||||
// NOTE: this should be dynamic
|
||||
const destination = plugin.id === 'content-manager' ? `${basePath}/ctm-configurations` : basePath;
|
||||
|
||||
return (
|
||||
<LeftMenuLink
|
||||
key={get(plugin, 'id')}
|
||||
icon={get(plugin, 'icon') || 'plug'}
|
||||
label={get(plugin, 'name')}
|
||||
destination={`/plugins/${get(plugin, 'id')}`}
|
||||
destination={destination}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ import Row from 'components/Row';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
class ListPlugins extends React.Component {
|
||||
class ListPlugins extends React.PureComponent {
|
||||
render() {
|
||||
const listSize = size(this.props.plugins);
|
||||
let titleType = listSize === 1 ? 'singular' : 'plural';
|
||||
|
||||
@ -14,6 +14,13 @@
|
||||
color: #333740;
|
||||
transition: all 0.15s ease;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
|
||||
// The last notification must appear from
|
||||
// the background of the previous one.
|
||||
&:last-child {
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.notification:hover {
|
||||
|
||||
@ -4,7 +4,11 @@
|
||||
.notificationsContainer { /* stylelint-disable */
|
||||
position: absolute;
|
||||
top: 72px;
|
||||
right: 15px;
|
||||
left: 240px;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
list-style: none;
|
||||
width: 300px;
|
||||
margin: 0 auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cn from 'classnames';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { includes, isEmpty } from 'lodash';
|
||||
|
||||
// Design
|
||||
import IcoContainer from 'components/IcoContainer';
|
||||
@ -17,6 +17,8 @@ import PopUpWarning from 'components/PopUpWarning';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
const PLUGINS_WITH_CONFIG = ['content-manager', 'email', 'upload'];
|
||||
|
||||
class Row extends React.Component {
|
||||
state = { showModal: false };
|
||||
|
||||
@ -33,8 +35,10 @@ class Row extends React.Component {
|
||||
|
||||
render() {
|
||||
// const uploadPath = `/plugins/upload/configurations/${this.context.currentEnvironment}`;
|
||||
const settingsPath = `/plugins/${this.props.name}/configurations/${this.context.currentEnvironment}`;
|
||||
const icons = this.props.name === 'upload' || this.props.name === 'email' ? [
|
||||
// Make sure to match the ctm config URI instead of content-type view URI
|
||||
const settingsPath = this.props.name === 'content-manager' ? '/plugins/content-manager/ctm-configurations' : `/plugins/${this.props.name}/configurations/${this.context.currentEnvironment}`;
|
||||
// const icons = this.props.name === 'upload' || this.props.name === 'email' ? [
|
||||
const icons = includes(PLUGINS_WITH_CONFIG, this.props.name) ? [
|
||||
{
|
||||
icoType: 'cog',
|
||||
onClick: (e) => {
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
{
|
||||
"languages": ["ar", "en", "fr", "de", "it", "ko", "pl", "pt", "pt-BR", "tr", "zh", "zh-Hans"]
|
||||
"languages": ["ar", "en", "es", "fr", "de", "it", "ko", "nl", "pl", "pt", "pt-BR", "tr", "zh", "zh-Hans"]
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -44,7 +44,7 @@ import ListPluginsPage from 'containers/ListPluginsPage/Loadable';
|
||||
import Logout from 'components/Logout';
|
||||
import NotFoundPage from 'containers/NotFoundPage/Loadable';
|
||||
import OverlayBlocker from 'components/OverlayBlocker';
|
||||
import PluginPage from 'containers/PluginPage/Loadable';
|
||||
import PluginPage from 'containers/PluginPage';
|
||||
|
||||
// Utils
|
||||
import auth from 'utils/auth';
|
||||
|
||||
@ -11,15 +11,15 @@ import { GET_GA_STATUS, GET_LAYOUT } from './constants';
|
||||
|
||||
function* getGaStatus() {
|
||||
try {
|
||||
const [allowGa, strapiVersion, currentEnvironment] = yield [
|
||||
const [{ allowGa }, { strapiVersion }, { currentEnvironment }] = yield [
|
||||
call(request, '/admin/gaConfig', { method: 'GET' }),
|
||||
call(request, '/admin/strapiVersion', { method: 'GET' }),
|
||||
call(request, '/admin/currentEnvironment', { method: 'GET' }),
|
||||
];
|
||||
|
||||
yield put(getCurrEnvSucceeded(currentEnvironment.currentEnvironment));
|
||||
yield put(getCurrEnvSucceeded(currentEnvironment));
|
||||
yield put(getGaStatusSucceeded(allowGa));
|
||||
yield put(getStrapiVersionSucceeded(strapiVersion.strapiVersion));
|
||||
yield put(getStrapiVersionSucceeded(strapiVersion));
|
||||
} catch(err) {
|
||||
strapi.notification.error('notification.error');
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ export class HomePage extends React.PureComponent {
|
||||
const data = this.showFirstBlock()
|
||||
? {
|
||||
className: styles.homePageTutorialButton,
|
||||
href: 'https://strapi.io/documentation/getting-started/quick-start.html',
|
||||
href: 'https://strapi.io/documentation/getting-started/quick-start.html#create-your-first-api',
|
||||
id: 'app.components.HomePage.button.quickStart',
|
||||
primary: true,
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
.blockLink {
|
||||
position: relative;
|
||||
width: calc(50% - 6px);
|
||||
height: 99px;
|
||||
height: auto;
|
||||
margin-top: 41px;
|
||||
padding: 22px 25px 0 96px;
|
||||
padding: 22px 25px 19px 96px;
|
||||
background: #F7F8F8;
|
||||
border-radius: 3px;
|
||||
line-height: 18px;
|
||||
|
||||
@ -8,8 +8,10 @@ import {
|
||||
DOWNLOAD_PLUGIN,
|
||||
DOWNLOAD_PLUGIN_ERROR,
|
||||
DOWNLOAD_PLUGIN_SUCCEEDED,
|
||||
GET_PLUGINS,
|
||||
GET_PLUGINS_SUCCEEDED,
|
||||
GET_AVAILABLE_PLUGINS,
|
||||
GET_AVAILABLE_PLUGINS_SUCCEEDED,
|
||||
GET_INSTALLED_PLUGINS,
|
||||
GET_INSTALLED_PLUGINS_SUCCEEDED,
|
||||
ON_CHANGE,
|
||||
} from './constants';
|
||||
|
||||
@ -32,19 +34,32 @@ export function downloadPluginSucceeded() {
|
||||
};
|
||||
}
|
||||
|
||||
export function getPlugins() {
|
||||
export function getAvailablePlugins() {
|
||||
return {
|
||||
type: GET_PLUGINS,
|
||||
type: GET_AVAILABLE_PLUGINS,
|
||||
};
|
||||
}
|
||||
|
||||
export function getPluginsSucceeded(availablePlugins) {
|
||||
export function getAvailablePluginsSucceeded(availablePlugins) {
|
||||
return {
|
||||
type: GET_PLUGINS_SUCCEEDED,
|
||||
type: GET_AVAILABLE_PLUGINS_SUCCEEDED,
|
||||
availablePlugins,
|
||||
};
|
||||
}
|
||||
|
||||
export function getInstalledPlugins() {
|
||||
return {
|
||||
type: GET_INSTALLED_PLUGINS,
|
||||
};
|
||||
}
|
||||
|
||||
export function getInstalledPluginsSucceeded(installedPlugins) {
|
||||
return {
|
||||
type: GET_INSTALLED_PLUGINS_SUCCEEDED,
|
||||
installedPlugins,
|
||||
};
|
||||
}
|
||||
|
||||
export function onChange({ target }) {
|
||||
return {
|
||||
type: ON_CHANGE,
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
export const DOWNLOAD_PLUGIN = 'StrapiAdmin/InstallPluginPage/DOWNLOAD_PLUGIN';
|
||||
export const DOWNLOAD_PLUGIN_ERROR = 'StrapiAdmin/InstallPluginPage/DOWNLOAD_PLUGIN_ERROR';
|
||||
export const DOWNLOAD_PLUGIN_SUCCEEDED = 'StrapiAdmin/InstallPluginPage/DOWNLOAD_PLUGIN_SUCCEEDED';
|
||||
export const GET_PLUGINS = 'StrapiAdmin/InstallPluginPage/GET_PLUGINS';
|
||||
export const GET_PLUGINS_SUCCEEDED = 'StrapiAdmin/InstallPluginPage/GET_PLUGINS_SUCCEEDED';
|
||||
export const GET_AVAILABLE_PLUGINS = 'StrapiAdmin/InstallPluginPage/GET_AVAILABLE_PLUGINS';
|
||||
export const GET_AVAILABLE_PLUGINS_SUCCEEDED = 'StrapiAdmin/InstallPluginPage/GET_AVAILABLE_PLUGINS_SUCCEEDED';
|
||||
export const GET_INSTALLED_PLUGINS = 'StrapiAdmin/InstallPluginPage/GET_INSTALLED_PLUGINS';
|
||||
export const GET_INSTALLED_PLUGINS_SUCCEEDED = 'StrapiAdmin/InstallPluginPage/GET_INSTALLED_PLUGINS_SUCCEEDED';
|
||||
export const ON_CHANGE = 'StrapiAdmin/InstallPluginPage/ON_CHANGE';
|
||||
|
||||
@ -11,7 +11,7 @@ import { Helmet } from 'react-helmet';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import cn from 'classnames';
|
||||
import { get, isUndefined, map } from 'lodash';
|
||||
import { map } from 'lodash';
|
||||
|
||||
import {
|
||||
disableGlobalOverlayBlocker,
|
||||
@ -32,7 +32,8 @@ import injectReducer from 'utils/injectReducer';
|
||||
|
||||
import {
|
||||
downloadPlugin,
|
||||
getPlugins,
|
||||
getAvailablePlugins,
|
||||
getInstalledPlugins,
|
||||
onChange,
|
||||
} from './actions';
|
||||
|
||||
@ -55,8 +56,11 @@ export class InstallPluginPage extends React.Component { // eslint-disable-line
|
||||
|
||||
// Don't fetch the available plugins if it has already been done
|
||||
if (!this.props.didFetchPlugins) {
|
||||
this.props.getPlugins();
|
||||
this.props.getAvailablePlugins();
|
||||
}
|
||||
|
||||
// Get installed plugins
|
||||
this.props.getInstalledPlugins();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -65,10 +69,10 @@ export class InstallPluginPage extends React.Component { // eslint-disable-line
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.props.didFetchPlugins) {
|
||||
if (!this.props.didFetchPlugins || !this.props.didFetchInstalledPlugins) {
|
||||
return <LoadingIndicatorPage />;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<OverlayBlocker isOpen={this.props.blockApp}>
|
||||
@ -112,7 +116,7 @@ export class InstallPluginPage extends React.Component { // eslint-disable-line
|
||||
key={plugin.id}
|
||||
plugin={plugin}
|
||||
showSupportUsButton={plugin.id === 'support-us'}
|
||||
isAlreadyInstalled={!isUndefined(get(this.context.plugins.toJS(), plugin.id))}
|
||||
isAlreadyInstalled={this.props.installedPlugins.includes(plugin.id)}
|
||||
downloadPlugin={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@ -134,19 +138,18 @@ InstallPluginPage.childContextTypes = {
|
||||
downloadPlugin: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
InstallPluginPage.contextTypes = {
|
||||
plugins: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
InstallPluginPage.propTypes = {
|
||||
availablePlugins: PropTypes.array.isRequired,
|
||||
blockApp: PropTypes.bool.isRequired,
|
||||
didFetchInstalledPlugins: PropTypes.bool.isRequired,
|
||||
didFetchPlugins: PropTypes.bool.isRequired,
|
||||
disableGlobalOverlayBlocker: PropTypes.func.isRequired,
|
||||
downloadPlugin: PropTypes.func.isRequired,
|
||||
enableGlobalOverlayBlocker: PropTypes.func.isRequired,
|
||||
getPlugins: PropTypes.func.isRequired,
|
||||
getAvailablePlugins: PropTypes.func.isRequired,
|
||||
getInstalledPlugins: PropTypes.func.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
installedPlugins: PropTypes.array.isRequired,
|
||||
// onChange: PropTypes.func.isRequired,
|
||||
// search: PropTypes.string.isRequired,
|
||||
};
|
||||
@ -159,7 +162,8 @@ function mapDispatchToProps(dispatch) {
|
||||
disableGlobalOverlayBlocker,
|
||||
downloadPlugin,
|
||||
enableGlobalOverlayBlocker,
|
||||
getPlugins,
|
||||
getAvailablePlugins,
|
||||
getInstalledPlugins,
|
||||
onChange,
|
||||
},
|
||||
dispatch,
|
||||
|
||||
@ -9,14 +9,17 @@ import {
|
||||
DOWNLOAD_PLUGIN,
|
||||
DOWNLOAD_PLUGIN_ERROR,
|
||||
DOWNLOAD_PLUGIN_SUCCEEDED,
|
||||
GET_PLUGINS_SUCCEEDED,
|
||||
GET_AVAILABLE_PLUGINS_SUCCEEDED,
|
||||
GET_INSTALLED_PLUGINS_SUCCEEDED,
|
||||
ON_CHANGE,
|
||||
} from './constants';
|
||||
|
||||
const initialState = fromJS({
|
||||
availablePlugins: List([]),
|
||||
installedPlugins: List([]),
|
||||
blockApp: false,
|
||||
didFetchPlugins: false,
|
||||
didFetchInstalledPlugins: false,
|
||||
pluginToDownload: '',
|
||||
search: '',
|
||||
});
|
||||
@ -35,10 +38,14 @@ function installPluginPageReducer(state = initialState, action) {
|
||||
return state
|
||||
.set('blockApp', false)
|
||||
.set('pluginToDownload', '');
|
||||
case GET_PLUGINS_SUCCEEDED:
|
||||
case GET_AVAILABLE_PLUGINS_SUCCEEDED:
|
||||
return state
|
||||
.set('didFetchPlugins', true)
|
||||
.set('availablePlugins', List(action.availablePlugins));
|
||||
case GET_INSTALLED_PLUGINS_SUCCEEDED:
|
||||
return state
|
||||
.set('didFetchInstalledPlugins', true)
|
||||
.set('installedPlugins', List(action.installedPlugins));
|
||||
case ON_CHANGE:
|
||||
return state.updateIn(action.keys, () => action.value);
|
||||
default:
|
||||
|
||||
@ -15,9 +15,10 @@ import { selectLocale } from '../LanguageProvider/selectors';
|
||||
import {
|
||||
downloadPluginError,
|
||||
downloadPluginSucceeded,
|
||||
getPluginsSucceeded,
|
||||
getAvailablePluginsSucceeded,
|
||||
getInstalledPluginsSucceeded,
|
||||
} from './actions';
|
||||
import { DOWNLOAD_PLUGIN, GET_PLUGINS } from './constants';
|
||||
import { DOWNLOAD_PLUGIN, GET_AVAILABLE_PLUGINS, GET_INSTALLED_PLUGINS } from './constants';
|
||||
import { makeSelectPluginToDownload } from './selectors';
|
||||
|
||||
|
||||
@ -49,7 +50,7 @@ export function* pluginDownload() {
|
||||
}
|
||||
}
|
||||
|
||||
export function* pluginsGet() {
|
||||
export function* getAvailablePlugins() {
|
||||
try {
|
||||
// Get current locale.
|
||||
const locale = yield select(selectLocale());
|
||||
@ -64,23 +65,53 @@ export function* pluginsGet() {
|
||||
},
|
||||
};
|
||||
|
||||
// Retrieve plugins list.
|
||||
const availablePlugins = yield call(request, 'https://marketplace.strapi.io/plugins', opts);
|
||||
let availablePlugins;
|
||||
|
||||
yield put(getPluginsSucceeded(availablePlugins));
|
||||
try {
|
||||
// Retrieve plugins list.
|
||||
availablePlugins = yield call(request, 'https://marketplace.strapi.io/plugins', opts);
|
||||
} catch (e) {
|
||||
availablePlugins = [];
|
||||
}
|
||||
|
||||
yield put(getAvailablePluginsSucceeded(availablePlugins));
|
||||
} catch(err) {
|
||||
strapi.notification.error('notification.error');
|
||||
}
|
||||
}
|
||||
|
||||
export function* getInstalledPlugins() {
|
||||
try {
|
||||
const opts = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
|
||||
let installedPlugins;
|
||||
|
||||
try {
|
||||
// Retrieve plugins list.
|
||||
installedPlugins = yield call(request, '/admin/plugins', opts);
|
||||
} catch (e) {
|
||||
installedPlugins = [];
|
||||
}
|
||||
|
||||
yield put(getInstalledPluginsSucceeded(Object.keys(installedPlugins.plugins)));
|
||||
} catch(err) {
|
||||
strapi.notification.error('notification.error');
|
||||
}
|
||||
}
|
||||
|
||||
// Individual exports for testing
|
||||
export default function* defaultSaga() {
|
||||
const loadPluginsWatcher = yield fork(takeLatest, GET_PLUGINS, pluginsGet);
|
||||
const loadAvailablePluginsWatcher = yield fork(takeLatest, GET_AVAILABLE_PLUGINS, getAvailablePlugins);
|
||||
const loadInstalledPluginsWatcher = yield fork(takeLatest, GET_INSTALLED_PLUGINS, getInstalledPlugins);
|
||||
yield fork(takeLatest, DOWNLOAD_PLUGIN, pluginDownload);
|
||||
|
||||
yield take(LOCATION_CHANGE);
|
||||
|
||||
yield cancel(loadPluginsWatcher);
|
||||
yield cancel(loadAvailablePluginsWatcher);
|
||||
yield cancel(loadInstalledPluginsWatcher);
|
||||
}
|
||||
|
||||
@ -14,16 +14,14 @@ import LeftMenuFooter from 'components/LeftMenuFooter';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
export class LeftMenu extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.leftMenu}>
|
||||
<LeftMenuHeader />
|
||||
<LeftMenuLinkContainer {...this.props} />
|
||||
<LeftMenuFooter plugins={this.props.plugins} version={this.props.version} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function LeftMenu(props) {
|
||||
return (
|
||||
<div className={styles.leftMenu}>
|
||||
<LeftMenuHeader />
|
||||
<LeftMenuLinkContainer {...props} />
|
||||
<LeftMenuFooter plugins={props.plugins} version={props.version} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
LeftMenu.defaultProps = {
|
||||
|
||||
@ -52,8 +52,14 @@ export function* pluginsGet() {
|
||||
},
|
||||
};
|
||||
|
||||
// Fetch plugins informations.
|
||||
const availablePlugins = yield call(request, 'https://marketplace.strapi.io/plugins', opts);
|
||||
let availablePlugins;
|
||||
|
||||
try {
|
||||
// Fetch plugins informations.
|
||||
availablePlugins = yield call(request, 'https://marketplace.strapi.io/plugins', opts);
|
||||
} catch (e) {
|
||||
availablePlugins = [];
|
||||
}
|
||||
|
||||
// Add logo URL to object.
|
||||
Object.keys(response[0].plugins).map(name => {
|
||||
|
||||
@ -4,22 +4,20 @@
|
||||
|
||||
.notification-enter {
|
||||
opacity: 0.01;
|
||||
right: -45rem;
|
||||
top: -60px;
|
||||
}
|
||||
|
||||
.notification-enter.notification-enter-active {
|
||||
opacity: 1;
|
||||
transition: all 400ms ease-in;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.notification-exit {
|
||||
opacity: 1;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.notification-exit.notification-exit-active {
|
||||
opacity: 0.01;
|
||||
transition: all 400ms ease-in;
|
||||
right: -45rem;
|
||||
}
|
||||
|
||||
@ -1,4 +1,12 @@
|
||||
{
|
||||
"app.components.Button.save": "Speichern",
|
||||
"app.components.Button.cancel": "Abbrechen",
|
||||
|
||||
"app.components.BlockLink.documentation": "Lese die Dokumentation",
|
||||
"app.components.BlockLink.documentation.content": "Entdecke die Konzepte, Referenzanleitungen und Tutorials.",
|
||||
"app.components.BlockLink.code": "Code Beispiele",
|
||||
"app.components.BlockLink.code.content": "Lerne durch das Testen realer Projekte, die die Community entwickelt haben.",
|
||||
|
||||
"app.components.ComingSoonPage.comingSoon": "Bald verfügbar",
|
||||
"app.components.ComingSoonPage.featuresNotAvailable": "Dieses Feature ist derzeit noch in aktiver Entwicklung.",
|
||||
|
||||
@ -6,13 +14,24 @@
|
||||
"app.components.DownloadInfo.text": "Dies könnte kurz dauern. Danke für deine Geduld.",
|
||||
|
||||
"app.components.HomePage.welcome": "Willkommen an Bord!",
|
||||
"app.components.HomePage.create": "Erstelle deinen ersten Content-Typ",
|
||||
"app.components.HomePage.welcomeBlock.content": "Wir freuen uns, dich als Mitglied der Community zu haben. Wir sind offen für Feedback, senden uns einfach eine direkt Nachricht an\u0020",
|
||||
"app.components.HomePage.welcomeBlock.content.issues": "Fehler",
|
||||
"app.components.HomePage.welcomeBlock.content.raise": "\u0020oder erhöhen\u0020",
|
||||
"app.components.HomePage.welcome.again": "Willkommen",
|
||||
"app.components.HomePage.create": "Erstelle deinen ersten Inhaltstyp",
|
||||
"app.components.HomePage.welcomeBlock.content": "Wir freuen uns, dich als Mitglied der Community zu haben. Wir sind offen für Feedback, senden uns einfach eine direkt Nachricht in\u0020",
|
||||
"app.components.HomePage.welcomeBlock.content.issues": "Ticket.",
|
||||
"app.components.HomePage.welcomeBlock.content.raise": "\u0020oder eröffne\u0020",
|
||||
"app.components.HomePage.createBlock.content.first": "Das\u0020",
|
||||
"app.components.HomePage.createBlock.content.second": "\u0020Plugin wird dir helfen, die Datenstruktur deiner Modelle zu definieren. Wenn du neu hier bist, empfehlen wir dir unsere\u0020",
|
||||
"app.components.HomePage.createBlock.content.tutorial": "\u0020Anleitung.",
|
||||
"app.components.HomePage.createBlock.content.second": "\u0020Plugin wird dir helfen, die Datenstruktur deiner Modelle zu definieren. Wenn du neu hier bist, empfehlen wir dir unser\u0020",
|
||||
"app.components.HomePage.createBlock.content.tutorial": "\u0020Tutorial.",
|
||||
"app.components.HomePage.welcomeBlock.content.again": "Wir hoffen, dass du Fortschritte bei deinem Projekt machst.... Lese das Neueste über Strapi. Wir geben unser Bestes, um das Produkt auf der Grundlage deines Feedbacks zu verbessern.",
|
||||
"app.components.HomePage.cta": "BESTÄTIGEN",
|
||||
"app.components.HomePage.community": "Finde die Community im Web",
|
||||
"app.components.HomePage.community.content": "Diskutiere mit Teammitgliedern, Mitwirkenden und Entwicklern auf verschiedenen Kanälen.",
|
||||
"app.components.HomePage.newsLetter": "Abonniere den Newsletter, um sich über Strapi zu informieren.",
|
||||
"app.components.HomePage.button.quickStart" : "STARTE DAS QUICK-START-TUTORIAL",
|
||||
"app.components.HomePage.button.blog": "MEHR DAZU IM BLOG",
|
||||
"app.components.HomePage.support": "UNTERSTÜTZE UNS",
|
||||
"app.components.HomePage.support.content": "Durch den Kauf des T-Shirts können wir unsere Arbeit am Projekt fortsetzen, um Ihnen das bestmögliche Erlebnis zu bieten!",
|
||||
"app.components.HomePage.support.link": "HOLE DIR JETZT DEIN T-SHIRT",
|
||||
|
||||
"app.components.InputFile.newFile": "Neue Datei hinzufügen",
|
||||
"app.components.InputFileDetails.open": "In einem neuen Tab öffnen",
|
||||
@ -25,7 +44,7 @@
|
||||
|
||||
"app.components.InstallPluginPage.helmet": "Marktplatz - Plugins",
|
||||
"app.components.InstallPluginPage.title": "Marktplatz - Plugins",
|
||||
"app.components.InstallPluginPage.description": "Erweitere problemlos deine App",
|
||||
"app.components.InstallPluginPage.description": "Erweitere problemlos deine App.",
|
||||
"app.components.InstallPluginPage.plugin.support-us.description": "Unterstütze uns durch den Kauf eines Strapi T-Shirts. Das erlaubt uns, weiter an dem Projekt arbeiten zu können und es so gut wie nur möglich zu gestalten!",
|
||||
"app.components.InstallPluginPage.InputSearch.label": " ",
|
||||
"app.components.InstallPluginPage.InputSearch.placeholder": "Suche nach einem Plugin... (z.B.: Authentifizierung)",
|
||||
@ -69,6 +88,8 @@
|
||||
|
||||
"app.utils.placeholder.defaultMessage": "\u0020",
|
||||
"app.utils.SelectOption.defaultMessage": "\u0020",
|
||||
"app.utils.defaultMessage": "",
|
||||
|
||||
|
||||
"components.AutoReloadBlocker.header": "Dieses Plugin benötigt das Neuladen-Feature.",
|
||||
"components.AutoReloadBlocker.description": "Öffne die folgende Datei und aktiviere das Feature.",
|
||||
@ -78,6 +99,8 @@
|
||||
"components.OverlayBlocker.title": "Auf Neustart warten...",
|
||||
"components.OverlayBlocker.description": "Du verwendest ein Feature, das einen Neustart des Servers erfordert. Bitte warte, bis der Server wieder gestartet wurde.",
|
||||
|
||||
"components.PageFooter.select": "Einträge pro Seite",
|
||||
|
||||
"components.ProductionBlocker.header": "Dieses Plugin ist nur in der Entwicklungsumgebung verfügbar.",
|
||||
"components.ProductionBlocker.description": "Aus Sicherheitsgründen müssen wir dieses Plugin in anderen Umgebungen deaktivieren.",
|
||||
|
||||
@ -93,6 +116,7 @@
|
||||
"components.Input.error.validation.min": "Dieser Wert ist zu niedrig.",
|
||||
"components.Input.error.validation.maxLength": "Dieser Wert ist zu lang.",
|
||||
"components.Input.error.validation.minLength": "Dieser Wert ist zu kurz.",
|
||||
"components.Input.error.validation.json": "Dies entspricht nicht dem JSON-Format.",
|
||||
"components.Input.error.contentTypeName.taken": "Dieser Name existiert bereits",
|
||||
"components.Input.error.attribute.taken": "Dieser Feldname ist bereits vergeben",
|
||||
"components.Input.error.attribute.key.taken": "Dieser Wert existiert bereits",
|
||||
@ -102,33 +126,41 @@
|
||||
|
||||
"components.ListRow.empty": "Es gibt keine Daten.",
|
||||
|
||||
"components.Wysiwyg.collapse": "Collapse",
|
||||
"components.Wysiwyg.selectOptions.title": "Add a title",
|
||||
"components.Wysiwyg.selectOptions.H1": "Title H1",
|
||||
"components.Wysiwyg.selectOptions.H2": "Title H2",
|
||||
"components.Wysiwyg.selectOptions.H3": "Title H3",
|
||||
"components.Wysiwyg.selectOptions.H4": "Title H4",
|
||||
"components.Wysiwyg.selectOptions.H5": "Title H5",
|
||||
"components.Wysiwyg.selectOptions.H6": "Title H6",
|
||||
"components.Wysiwyg.ToggleMode.markdown": "Switch to markdown",
|
||||
"components.Wysiwyg.ToggleMode.preview": "Switch to preview",
|
||||
"components.WysiwygBottomControls.charactersIndicators": "characters",
|
||||
"components.WysiwygBottomControls.uploadFiles": "Attach files by dragging & dropping, {browse}, or pasting from the clipboard.",
|
||||
"components.WysiwygBottomControls.uploadFiles.browse": "selecting them",
|
||||
"components.WysiwygBottomControls.fullscreen": "Expand",
|
||||
"components.Wysiwyg.collapse": "Verkleinern",
|
||||
"components.Wysiwyg.selectOptions.title": "Füge einen Überschrift hinzu",
|
||||
"components.Wysiwyg.selectOptions.H1": "Überschrift H1",
|
||||
"components.Wysiwyg.selectOptions.H2": "Überschrift H2",
|
||||
"components.Wysiwyg.selectOptions.H3": "Überschrift H3",
|
||||
"components.Wysiwyg.selectOptions.H4": "Überschrift H4",
|
||||
"components.Wysiwyg.selectOptions.H5": "Überschrift H5",
|
||||
"components.Wysiwyg.selectOptions.H6": "Überschrift H6",
|
||||
"components.Wysiwyg.ToggleMode.markdown": "Wechsel zu Markdown",
|
||||
"components.Wysiwyg.ToggleMode.preview": "Wechsel zur Vorschau",
|
||||
"components.WysiwygBottomControls.charactersIndicators": "Zeichen",
|
||||
"components.WysiwygBottomControls.uploadFiles": "Ziehe eine Datei hierher, {browse} eine Datei zum hochladen aus oder füge sie aus der Zwischenablage ein.",
|
||||
"components.WysiwygBottomControls.uploadFiles.browse": "wähle",
|
||||
"components.WysiwygBottomControls.fullscreen": "Vergrößern",
|
||||
|
||||
"HomePage.notification.newsLetter.success": "Newsletter erfolgreich abonniert",
|
||||
|
||||
"notification.error": "Ein Fehler ist aufgetreten",
|
||||
"notification.error.layout": "Das Layout konnte nicht abgerufen werden.",
|
||||
|
||||
"Analytics": "Analytics",
|
||||
"Auth & Permissions": "Authentifizierung & Berechtigungen",
|
||||
"Content Manager": "Content-Manager",
|
||||
"Content Type Builder": "Content-Typ-Manager",
|
||||
"Content Manager": "Inhalts-Manager",
|
||||
"Content Type Builder": "Inhaltstyp-Manager",
|
||||
"Files Upload": "Dateien hochladen",
|
||||
"Settings Manager": "Einstellungs-Manager",
|
||||
"Email": "E-Mail",
|
||||
"Password": "Passwort",
|
||||
"Users": "Benutzer",
|
||||
"Username": "Benutzername",
|
||||
"Users & Permissions": "Benutzer & Berechtigungen",
|
||||
"Provider": "Methode",
|
||||
"ResetPasswordToken": "Passwort-Token zurücksetzen",
|
||||
"Role": "Rolle",
|
||||
"Roles & Permissions" : "Rollen & Berechtigungen",
|
||||
"New entry": "Neuer Eintrag",
|
||||
"request.error.model.unknown": "Dieses Schema existiert nicht"
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
"app.components.DownloadInfo.download": "Download in progress...",
|
||||
"app.components.DownloadInfo.text": "This could take a minute. Thanks for your patience.",
|
||||
|
||||
"app.components.EmptyAttributes.title": "There are no fields yet",
|
||||
|
||||
"app.components.HomePage.welcome": "Welcome on board!",
|
||||
"app.components.HomePage.welcome.again": "Welcome ",
|
||||
"app.components.HomePage.cta": "CONFIRM",
|
||||
|
||||
165
packages/strapi-admin/admin/src/translations/es.json
Normal file
165
packages/strapi-admin/admin/src/translations/es.json
Normal file
@ -0,0 +1,165 @@
|
||||
{
|
||||
"app.components.Button.save": "Guardar",
|
||||
"app.components.Button.cancel": "Cancelar",
|
||||
|
||||
"app.components.ComingSoonPage.comingSoon": "Próximamente",
|
||||
"app.components.ComingSoonPage.featuresNotAvailable": "Esta característica está aún en desarrollo.",
|
||||
|
||||
"app.components.DownloadInfo.download": "Descarga en curso...",
|
||||
"app.components.DownloadInfo.text": "Esto puede tardar un minuto. Gracias por su paciencia.",
|
||||
|
||||
"app.components.HomePage.welcome": "¡Bienvenido a bordo!",
|
||||
"app.components.HomePage.welcome.again": "Bienvenido ",
|
||||
"app.components.HomePage.cta": "CONFIRMAR",
|
||||
"app.components.HomePage.community": "Encuentra la comunidad en la web",
|
||||
"app.components.HomePage.newsLetter": "Suscríbase al boletín de noticias para ponerse en contacto con Strapi",
|
||||
"app.components.HomePage.community.content": "Discutir con los miembros del equipo, colaboradores y desarrolladores en diferentes canales.",
|
||||
"app.components.HomePage.create": "Crea tu primer Tipo de Contenido",
|
||||
"app.components.HomePage.welcomeBlock.content": "Estamos felices de tenerlo como miembro de la comunidad. Estamos constantemente en busca de comentarios así que no dude en enviarnos un DM en\u0020",
|
||||
"app.components.HomePage.welcomeBlock.content.again": "Esperamos que estés progresando en tu proyecto.... Siéntase libre de leer las últimas novedades sobre Strapi. Estamos dando lo mejor de nosotros mismos para mejorar el producto basándonos en sus comentarios.",
|
||||
"app.components.HomePage.welcomeBlock.content.issues": "problema.",
|
||||
"app.components.HomePage.welcomeBlock.content.raise": "\u0020o reportar cualquier\u0020",
|
||||
"app.components.HomePage.createBlock.content.first": "El\u0020",
|
||||
"app.components.HomePage.createBlock.content.second": "\u0020le ayudará a definir la estructura de datos de sus modelos. Si eres nuevo aquí, te recomendamos encarecidamente que sigas nuestro\u0020",
|
||||
"app.components.HomePage.createBlock.content.tutorial": "\u0020",
|
||||
"app.components.HomePage.button.quickStart": "INICIAR EL TUTORIAL DE INICIO RÁPIDO",
|
||||
"app.components.HomePage.button.blog": "VER MÁS EN EL BLOG",
|
||||
"app.components.HomePage.support": "APÓYANOS",
|
||||
"app.components.HomePage.support.content": "¡Al comprar la camiseta, nos permitirá continuar nuestro trabajo en el proyecto para darle la mejor experiencia posible!",
|
||||
"app.components.HomePage.support.link": "CONSIGUE TU CAMISETA AHORA",
|
||||
|
||||
"app.components.BlockLink.documentation": "Lea la documentación",
|
||||
"app.components.BlockLink.documentation.content": "Descubra los conceptos, guías de referencia y tutoriales.",
|
||||
"app.components.BlockLink.code": "Ejemplos de código",
|
||||
"app.components.BlockLink.code.content": "Aprenda probando proyectos reales desarrollados por la comunidad.",
|
||||
|
||||
|
||||
"app.components.InputFile.newFile": "Añadir nuevo archivo",
|
||||
"app.components.InputFileDetails.open": "Abrir en una nueva pestaña",
|
||||
"app.components.InputFileDetails.remove": "Eliminar este archivo",
|
||||
"app.components.InputFileDetails.originalName": "Nombre original:",
|
||||
"app.components.InputFileDetails.size": "Tamaño:",
|
||||
|
||||
"app.components.ImgPreview.hint": "Arrastre y suelte el archivo en esta área o {browse} para cargar un archivo.",
|
||||
"app.components.ImgPreview.hint.browse": "buscar",
|
||||
|
||||
"app.components.InstallPluginPage.helmet": "Tienda - Plugins",
|
||||
"app.components.InstallPluginPage.title": "Tienda - Plugins",
|
||||
"app.components.InstallPluginPage.description": "Extienda su aplicación sin esfuerzo.",
|
||||
"app.components.InstallPluginPage.plugin.support-us.description": "¡Apóyanos comprando la camiseta Strapi. Eso nos permitirá seguir trabajando en el proyecto y tratar de darle la mejor experiencia posible!",
|
||||
"app.components.InstallPluginPage.InputSearch.label": " ",
|
||||
"app.components.InstallPluginPage.InputSearch.placeholder": "Buscar un plugin... (ej: autenticación)",
|
||||
"app.components.InstallPluginPopup.downloads": "descargar",
|
||||
"app.components.InstallPluginPopup.navLink.description": "Descripción",
|
||||
"app.components.InstallPluginPopup.navLink.screenshots": "Capturas de pantalla",
|
||||
"app.components.InstallPluginPopup.navLink.avis": "opinión",
|
||||
"app.components.InstallPluginPopup.navLink.faq": "preguntas frecuentes",
|
||||
"app.components.InstallPluginPopup.navLink.changelog": "changelog",
|
||||
"app.components.InstallPluginPopup.noDescription": "No hay descripción disponible",
|
||||
|
||||
"app.components.LeftMenuFooter.poweredBy": "Potenciado por ",
|
||||
"app.components.LeftMenuLinkContainer.configuration": "Configuraciones",
|
||||
"app.components.LeftMenuLinkContainer.general": "General",
|
||||
"app.components.LeftMenuLinkContainer.installNewPlugin": "Tienda",
|
||||
"app.components.LeftMenuLinkContainer.listPlugins": "Plugins",
|
||||
"app.components.LeftMenuLinkContainer.noPluginsInstalled": "No hay plugins instalados todavía",
|
||||
"app.components.LeftMenuLinkContainer.plugins": "Plugins",
|
||||
|
||||
"app.components.ListPluginsPage.helmet.title": "Lista de plugins",
|
||||
"app.components.ListPluginsPage.title": "Plugins",
|
||||
"app.components.ListPluginsPage.description": "Lista de los plugins instalados en el proyecto.",
|
||||
"app.components.listPluginsPage.deletePlugin.error": "Se ha producido un error al desinstalar el plugin",
|
||||
"app.components.listPlugins.title.singular": "{number} plugin está instalado",
|
||||
"app.components.listPlugins.title.plural": "{number} plugins están instalados",
|
||||
"app.components.listPlugins.title.none": "No hay plugins instalados",
|
||||
"app.components.listPlugins.button": "Añadir nuevo plugin",
|
||||
|
||||
"app.components.NotFoundPage.description": "No encontrado",
|
||||
"app.components.NotFoundPage.back": "Volver a la página de inicio",
|
||||
|
||||
"app.components.Official": "Oficial",
|
||||
|
||||
"app.components.PluginCard.compatible": "Compatible con su aplicación",
|
||||
"app.components.PluginCard.compatibleCommunity": "Compatible con la comunidad",
|
||||
"app.components.PluginCard.Button.label.download": "Descargar",
|
||||
"app.components.PluginCard.Button.label.install": "Ya instalado",
|
||||
"app.components.PluginCard.Button.label.support": "Apóyenos",
|
||||
"app.components.PluginCard.price.free": "Gratuito",
|
||||
"app.components.PluginCard.more-details": "Más detalles",
|
||||
|
||||
"app.utils.placeholder.defaultMessage": "\u0020",
|
||||
"app.utils.SelectOption.defaultMessage": "\u0020",
|
||||
"app.utils.defaultMessage": "\u0020",
|
||||
|
||||
"components.AutoReloadBlocker.header": "Es necesario recargar para este plugin.",
|
||||
"components.AutoReloadBlocker.description": "Abra el siguiente archivo y habilite la función.",
|
||||
|
||||
"components.ErrorBoundary.title": "Algo salió mal...",
|
||||
|
||||
"components.OverlayBlocker.title": "Esperando el reinicio...",
|
||||
"components.OverlayBlocker.description": "Está utilizando una función que necesita que el servidor se reinicie. Por favor, espere hasta que el servidor esté listo..",
|
||||
|
||||
"components.PageFooter.select": "entradas por página",
|
||||
|
||||
"components.ProductionBlocker.header": "Este plugin sólo está disponible en entornos de desarrollo.",
|
||||
"components.ProductionBlocker.description": "Por razones de seguridad tenemos que desactivar este plugin en otros entornos.",
|
||||
|
||||
"components.popUpWarning.button.cancel": "Cancelar",
|
||||
"components.popUpWarning.button.confirm": "Confirmar",
|
||||
"components.popUpWarning.title": "Por favor, confirme",
|
||||
"components.popUpWarning.message": "¿Estás seguro de que quieres borrar esto?",
|
||||
|
||||
"components.Input.error.validation.email": "Esto no es un email",
|
||||
"components.Input.error.validation.required": "Este valor es obligatorio.",
|
||||
"components.Input.error.validation.regex": "El valor no coincide con el de regex.",
|
||||
"components.Input.error.validation.max": "El valor es demasiado alto.",
|
||||
"components.Input.error.validation.min": "El valor es demasiado bajo.",
|
||||
"components.Input.error.validation.maxLength": "El valor es demasiado largo.",
|
||||
"components.Input.error.validation.minLength": "El valor es demasiado corto.",
|
||||
"components.Input.error.contentTypeName.taken": "Este nombre ya existe",
|
||||
"components.Input.error.attribute.taken": "Este nombre de campo ya existe",
|
||||
"components.Input.error.attribute.key.taken": "Este valor ya existe",
|
||||
"components.Input.error.attribute.sameKeyAndName": "No puede ser igual",
|
||||
"components.Input.error.validation.minSupMax": "No puede ser superior",
|
||||
"components.Input.error.custom-error": "{errorMessage} ",
|
||||
"components.Input.error.validation.json": "Esto no coincide con el formato JSON",
|
||||
|
||||
"components.ListRow.empty": "No hay datos que mostrar.",
|
||||
|
||||
"components.Wysiwyg.collapse": "Contraer menú",
|
||||
"components.Wysiwyg.selectOptions.title": "Añadir un título",
|
||||
"components.Wysiwyg.selectOptions.H1": "Título H1",
|
||||
"components.Wysiwyg.selectOptions.H2": "Título H2",
|
||||
"components.Wysiwyg.selectOptions.H3": "Título H3",
|
||||
"components.Wysiwyg.selectOptions.H4": "Título H4",
|
||||
"components.Wysiwyg.selectOptions.H5": "Título H5",
|
||||
"components.Wysiwyg.selectOptions.H6": "Título H6",
|
||||
"components.Wysiwyg.ToggleMode.markdown": "Cambiar a markdown",
|
||||
"components.Wysiwyg.ToggleMode.preview": "Cambiar a vista previa",
|
||||
"components.WysiwygBottomControls.charactersIndicators": "caracteres",
|
||||
"components.WysiwygBottomControls.uploadFiles": "Arrastrar y soltar archivos, pegar desde el portapapeles o {browse}.",
|
||||
"components.WysiwygBottomControls.uploadFiles.browse": "seleccionarlos",
|
||||
"components.WysiwygBottomControls.fullscreen": "Expandir",
|
||||
|
||||
"HomePage.notification.newsLetter.success": "Suscribirse con éxito al boletín de noticias",
|
||||
|
||||
"notification.error": "Se ha producido un error",
|
||||
"notification.error.layout": "No se pudo recuperar el esquema",
|
||||
|
||||
"Users & Permissions": "Usuarios y permisos",
|
||||
"Content Manager": "Gestor de Contenidos",
|
||||
"Content Type Builder": "Constructor de Tipos de Contenido",
|
||||
"Files Upload": "Carga de archivos",
|
||||
"Roles & Permissions": "Roles y Permisos",
|
||||
"Settings Manager": "Gestor de ajustes",
|
||||
"Email": "Email",
|
||||
"Password": "Contraseña",
|
||||
"Username": "Nombre de usuario",
|
||||
"Provider": "Proveedor",
|
||||
"ResetPasswordToken": "Restablecer Token de Contraseña",
|
||||
"Role": "Rol",
|
||||
"New entry": "Entrada nueva",
|
||||
"request.error.model.unknown": "Este modelo no existe",
|
||||
"Users": "Usuarios",
|
||||
"Analytics": "Analytics"
|
||||
}
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
"app.components.DownloadInfo.download": "Téléchargement en cours...",
|
||||
"app.components.DownloadInfo.text": "Cela peut prendre une minute. Merci de patienter.",
|
||||
"app.components.EmptyAttributes.title": "Il n'y a pas encore de champ",
|
||||
|
||||
"app.components.HomePage.welcome": "Bienvenue à bord!",
|
||||
"app.components.HomePage.welcome.again": "Bienvenue ",
|
||||
@ -26,6 +27,7 @@
|
||||
"app.components.HomePage.support": "SUPPORT US",
|
||||
"app.components.HomePage.support.content": "En achetant notre T-shirt, vous nous aidez à poursuivre à maintenir le projet pour que nous puissions vous donner la meilleure expérience possible!",
|
||||
"app.components.HomePage.support.link": "OBTENEZ VOTRE T-SHIRT!",
|
||||
"app.components.HomePage.newsLetter": "Inscrivez-vous à la newsletter pour être contacté à propos de Strapi",
|
||||
|
||||
"app.components.BlockLink.documentation": "Voir la documentation",
|
||||
"app.components.BlockLink.documentation.content": "Découvrez les concepts, guides et tutoriaux.",
|
||||
@ -144,16 +146,21 @@
|
||||
"notification.error": "Une erreur est survenue",
|
||||
"notification.error.layout": "Impossible de récupérer le layout de l'admin",
|
||||
|
||||
"Analytics": "Statistiques",
|
||||
"Auth & Permissions": "Auth & Permissions",
|
||||
"Content Manager": "Content Manager",
|
||||
"Content Type Builder": "Content Type Builder",
|
||||
"Files Upload": "Téléversement de fichiers",
|
||||
"Settings Manager": "Settings Manager",
|
||||
"Email": "Email",
|
||||
"Password": "Mot de passe",
|
||||
"Username": "Nom d'utilisateur",
|
||||
"Users": "Utilisateurs",
|
||||
"Users & Permissions": "Utilisateurs et autorisations",
|
||||
"Provider": "Provider",
|
||||
"ResetPasswordToken": "ResetPasswordToken",
|
||||
"Role": "Rôle",
|
||||
"Roles & Permissions": "Rôles et autorisations",
|
||||
"New entry": "Nouvelle entrée",
|
||||
"request.error.model.unknown": "Le model n'existe pas"
|
||||
}
|
||||
|
||||
@ -89,6 +89,7 @@
|
||||
"components.popUpWarning.title": "Per favore conferma",
|
||||
"components.popUpWarning.message": "Sei sicuro di volerlo cancellare?",
|
||||
"components.Input.error.validation.email": "Non è un'email",
|
||||
"components.Input.error.validation.json" : "Formato JSON non corrispondente",
|
||||
"components.Input.error.validation.required": "Valore obbligatorio.",
|
||||
"components.Input.error.validation.regex": "Questo valore non coincide con il regex.",
|
||||
"components.Input.error.validation.max": "Valore troppo alto.",
|
||||
@ -119,18 +120,21 @@
|
||||
"HomePage.notification.newsLetter.success": "Iscritto con successo alla newsletter",
|
||||
"notification.error": "Si è verificato un errore",
|
||||
"notification.error.layout": "Non è stato possibile recuperare il layout",
|
||||
"request.error.model.unknown" : "Questo modello non esiste",
|
||||
"Users & Permissions": "Utenti & Permessi",
|
||||
"Content Manager": "Gestione Contenuti",
|
||||
"Content Type Builder": "Generatore di Tipo Contenuti",
|
||||
"Settings Manager": "Gestione Impostazioni",
|
||||
"Email": "Email",
|
||||
"Files Upload" : "Caricamento Files",
|
||||
"Password": "Password",
|
||||
"Username": "Username",
|
||||
"Provider": "Provider",
|
||||
"ResetPasswordToken": "Reimposta Token Password",
|
||||
"Role": "Ruolo",
|
||||
"Roles & Permissions" : "Ruoli e Permessi",
|
||||
"New entry": "Nuovo elemento",
|
||||
"request.error.model.unknow": "Questo modello non esiste",
|
||||
"Users": "Utenti",
|
||||
"Analytics": "Analytics"
|
||||
}
|
||||
}
|
||||
|
||||
165
packages/strapi-admin/admin/src/translations/nl.json
Normal file
165
packages/strapi-admin/admin/src/translations/nl.json
Normal file
@ -0,0 +1,165 @@
|
||||
{
|
||||
"app.components.Button.save": "Opslaan",
|
||||
"app.components.Button.cancel": "Annuleren",
|
||||
|
||||
"app.components.ComingSoonPage.comingSoon": "Binnenkort beschikbaar",
|
||||
"app.components.ComingSoonPage.featuresNotAvailable": "Deze feature is nog in ontwikkeling",
|
||||
|
||||
"app.components.DownloadInfo.download": "Aan het downloaden...",
|
||||
"app.components.DownloadInfo.text": "Dit kan even duren. Bedankt voor je geduld.",
|
||||
|
||||
"app.components.HomePage.welcome": "Welkom aan boord!",
|
||||
"app.components.HomePage.welcome.again": "Welkom ",
|
||||
"app.components.HomePage.cta": "AKKOORD",
|
||||
"app.components.HomePage.community": "Vind de community op het web",
|
||||
"app.components.HomePage.newsLetter": "Abonneer op de nieuwsbrief om contact te houden met Strapi",
|
||||
"app.components.HomePage.community.content": "Bespreek met teamleden, bijdragers en ontwikkelaars op verschillende kanalen.",
|
||||
"app.components.HomePage.create": "Creëer je eerste Content Type",
|
||||
"app.components.HomePage.welcomeBlock.content": "We zijn blij met jou als community lid. Wij zijn constant op zoek naar feedback dus stuur gerust een DM op\u0020",
|
||||
"app.components.HomePage.welcomeBlock.content.again": "We hopen dat je voortgang boekt met je project... Je kant altijd het laatste nieuws van Strapi lezen. We doen ons best om het product te verbeteren met jouw feedback.",
|
||||
"app.components.HomePage.welcomeBlock.content.issues": "problemen.",
|
||||
"app.components.HomePage.welcomeBlock.content.raise": "\u0020of verhogen\u0020",
|
||||
"app.components.HomePage.createBlock.content.first": "De\u0020",
|
||||
"app.components.HomePage.createBlock.content.second": "\u0020plugin kan je helpen om de data structuur van je models aan te geven. Als je nieuw bent hier raden we je aan om onze\u0020 te volgen",
|
||||
"app.components.HomePage.createBlock.content.tutorial": "\u0020handleiding.",
|
||||
"app.components.HomePage.button.quickStart": "START DE SNELLE START HANDLEIDING",
|
||||
"app.components.HomePage.button.blog": "LEES MEER OP DE BLOG",
|
||||
"app.components.HomePage.support": "STEUN ONS",
|
||||
"app.components.HomePage.support.content": "Door een T-shirt te kopen kunnen we doorgaan met ons werk aan het project om jou de beste ervaring te geven!",
|
||||
"app.components.HomePage.support.link": "KOOP NU EEN T-SHIRT",
|
||||
|
||||
"app.components.BlockLink.documentation": "Lees de documentatie",
|
||||
"app.components.BlockLink.documentation.content": "Ontdek de concepten, referentie handleidingen en tutorials.",
|
||||
"app.components.BlockLink.code": "Code voorbeelden",
|
||||
"app.components.BlockLink.code.content": "Leer door echte projecten gemaakt door de community te testen",
|
||||
|
||||
|
||||
"app.components.InputFile.newFile": "Nieuw bestand toevoegen",
|
||||
"app.components.InputFileDetails.open": "Openen in nieuw tabblad",
|
||||
"app.components.InputFileDetails.remove": "Verwijder dit bestand",
|
||||
"app.components.InputFileDetails.originalName": "Orginele naam:",
|
||||
"app.components.InputFileDetails.size": "Grootte:",
|
||||
|
||||
"app.components.ImgPreview.hint": "Sleep je bestand in dit gedeelte of {browse} voor een bestand om te uploaden",
|
||||
"app.components.ImgPreview.hint.browse": "blader",
|
||||
|
||||
"app.components.InstallPluginPage.helmet": "Marktplaats - Extensies",
|
||||
"app.components.InstallPluginPage.title": "Marktplaats - Extensies",
|
||||
"app.components.InstallPluginPage.description": "Breid je app zonder moeite uit.",
|
||||
"app.components.InstallPluginPage.plugin.support-us.description": "Steun ons door een Strapi T-shirt te kopen. Hierdoor kunnen wij doorwerken aan het project en jou de best mogelijke ervaring bieden!",
|
||||
"app.components.InstallPluginPage.InputSearch.label": " ",
|
||||
"app.components.InstallPluginPage.InputSearch.placeholder": "Zoek naar een extensie... (bijv. authenticatie)",
|
||||
"app.components.InstallPluginPopup.downloads": "download",
|
||||
"app.components.InstallPluginPopup.navLink.description": "Beschrijving",
|
||||
"app.components.InstallPluginPopup.navLink.screenshots": "Schermopnames",
|
||||
"app.components.InstallPluginPopup.navLink.avis": "avis",
|
||||
"app.components.InstallPluginPopup.navLink.faq": "faq",
|
||||
"app.components.InstallPluginPopup.navLink.changelog": "logboek",
|
||||
"app.components.InstallPluginPopup.noDescription": "Geen beschrijving beschikbaar",
|
||||
|
||||
"app.components.LeftMenuFooter.poweredBy": "Mogelijk gemaakt door ",
|
||||
"app.components.LeftMenuLinkContainer.configuration": "Configuraties",
|
||||
"app.components.LeftMenuLinkContainer.general": "Algemeen",
|
||||
"app.components.LeftMenuLinkContainer.installNewPlugin": "Marktplaats",
|
||||
"app.components.LeftMenuLinkContainer.listPlugins": "Extensies",
|
||||
"app.components.LeftMenuLinkContainer.noPluginsInstalled": "Nog geen extensies geïnstalleerd",
|
||||
"app.components.LeftMenuLinkContainer.plugins": "Extensies",
|
||||
|
||||
"app.components.ListPluginsPage.helmet.title": "Alle extensies",
|
||||
"app.components.ListPluginsPage.title": "Extensies",
|
||||
"app.components.ListPluginsPage.description": "Lijst van alle plugins voor dit project",
|
||||
"app.components.listPluginsPage.deletePlugin.error": "Er is een fout opgetreden tijdens het verwijderen van de plugin",
|
||||
"app.components.listPlugins.title.singular": "{number} extensie is geïnstalleerd",
|
||||
"app.components.listPlugins.title.plural": "{number} extensies zijn geïnstalleerd",
|
||||
"app.components.listPlugins.title.none": "Geen extensies geïnstalleerd",
|
||||
"app.components.listPlugins.button": "Nieuwe extensie toevoegen",
|
||||
|
||||
"app.components.NotFoundPage.description": "Niets gevonden",
|
||||
"app.components.NotFoundPage.back": "Terug naar home pagina",
|
||||
|
||||
"app.components.Official": "Officieel",
|
||||
|
||||
"app.components.PluginCard.compatible": "Geschikt voor jouw app",
|
||||
"app.components.PluginCard.compatibleCommunity": "Geschikt voor de community",
|
||||
"app.components.PluginCard.Button.label.download": "Download",
|
||||
"app.components.PluginCard.Button.label.install": "Al geïnstalleerd",
|
||||
"app.components.PluginCard.Button.label.support": "Steun ons",
|
||||
"app.components.PluginCard.price.free": "Gratis",
|
||||
"app.components.PluginCard.more-details": "Meer details",
|
||||
|
||||
"app.utils.placeholder.defaultMessage": "\u0020",
|
||||
"app.utils.SelectOption.defaultMessage": "\u0020",
|
||||
"app.utils.defaultMessage": "\u0020",
|
||||
|
||||
"components.AutoReloadBlocker.header": "De herlaad feature is nodig voor deze extensie",
|
||||
"components.AutoReloadBlocker.description": "Open het volgende bestand en ze deze feature aan.",
|
||||
|
||||
"components.ErrorBoundary.title": "Er is iets fout gegaan...",
|
||||
|
||||
"components.OverlayBlocker.title": "Wachten op herstart...",
|
||||
"components.OverlayBlocker.description": "Je gebruikt een feature waardoor de server opnieuw op moet starten. Een moment geduld terwijl de server opnieuw opstart.",
|
||||
|
||||
"components.PageFooter.select": "inzendingen per pagina",
|
||||
|
||||
"components.ProductionBlocker.header": "Deze extensie is alleen beschikbaar in ontwikkel modus",
|
||||
"components.ProductionBlocker.description": "Om veiligheids redenen hebben we deze extensie uitgeschakeld in andere omgevingen.",
|
||||
|
||||
"components.popUpWarning.button.cancel": "Annuleren",
|
||||
"components.popUpWarning.button.confirm": "Akkoord",
|
||||
"components.popUpWarning.title": "Ga a.u.b. akkoord",
|
||||
"components.popUpWarning.message": "Weet je zeker dat je dit wilt verwijderen?",
|
||||
|
||||
"components.Input.error.validation.email": "Dit is geen email",
|
||||
"components.Input.error.validation.required": "Deze waarde is verplicht.",
|
||||
"components.Input.error.validation.regex": "De ingevoerde waarde komt niet overeen met de regex.",
|
||||
"components.Input.error.validation.max": "De waarde is te hoog.",
|
||||
"components.Input.error.validation.min": "De waarde is te laag.",
|
||||
"components.Input.error.validation.maxLength": "De waarde is te lang.",
|
||||
"components.Input.error.validation.minLength": "De waarde is te kort.",
|
||||
"components.Input.error.contentTypeName.taken": "Deze naam bestaat al",
|
||||
"components.Input.error.attribute.taken": "Deze veld naam bestaat al",
|
||||
"components.Input.error.attribute.key.taken": "Deze waarde bestaat al.",
|
||||
"components.Input.error.attribute.sameKeyAndName": "Mag niet gelijk zijn.",
|
||||
"components.Input.error.validation.minSupMax": "Mag niet superieur zijn.",
|
||||
"components.Input.error.custom-error": "{errorMessage} ",
|
||||
"components.Input.error.validation.json": "Dit komt niet overeen met het JSON formaat",
|
||||
|
||||
"components.ListRow.empty": "Er is geen data beschikbaar.",
|
||||
|
||||
"components.Wysiwyg.collapse": "Inklappen",
|
||||
"components.Wysiwyg.selectOptions.title": "Voeg een titel toe",
|
||||
"components.Wysiwyg.selectOptions.H1": "H1 titel",
|
||||
"components.Wysiwyg.selectOptions.H2": "H2 titel",
|
||||
"components.Wysiwyg.selectOptions.H3": "H3 titel",
|
||||
"components.Wysiwyg.selectOptions.H4": "H4 titel",
|
||||
"components.Wysiwyg.selectOptions.H5": "H5 titel",
|
||||
"components.Wysiwyg.selectOptions.H6": "H6 titel",
|
||||
"components.Wysiwyg.ToggleMode.markdown": "Overschakelen naar markdown",
|
||||
"components.Wysiwyg.ToggleMode.preview": "Overschakelen naar voorbeeld",
|
||||
"components.WysiwygBottomControls.charactersIndicators": "karakters",
|
||||
"components.WysiwygBottomControls.uploadFiles": "Sleep bestanden, plak ze of {browse}.",
|
||||
"components.WysiwygBottomControls.uploadFiles.browse": "selecteer ze",
|
||||
"components.WysiwygBottomControls.fullscreen": "Uitklappen",
|
||||
|
||||
"HomePage.notification.newsLetter.success": "Succesvol geabonneerd op de nieuwsbrief",
|
||||
|
||||
"notification.error": "Er is een fout opgetreden",
|
||||
"notification.error.layout": "Kon de opzet niet laden",
|
||||
|
||||
"Users & Permissions": "Gebruikers & Permissies",
|
||||
"Content Manager": "Inhoud Manager",
|
||||
"Content Type Builder": "Content Type Bouwer",
|
||||
"Files Upload": "Bestand Upload",
|
||||
"Roles & Permissions": "Rollen & Permissies",
|
||||
"Settings Manager": "Instellingen Manager",
|
||||
"Email": "E-mail",
|
||||
"Password": "Wachtwoord",
|
||||
"Username": "Gebruikersnaam",
|
||||
"Provider": "Leverancier",
|
||||
"ResetPasswordToken": "Wachtwoord Reset Token",
|
||||
"Role": "Rol",
|
||||
"New entry": "Nieuwe inzending",
|
||||
"request.error.model.unknown": "Dit model bestaat niet",
|
||||
"Users": "Gebruikers",
|
||||
"Analytics": "Analytics"
|
||||
}
|
||||
@ -149,6 +149,8 @@
|
||||
"Users & Permissions": "Usuários & Permissões",
|
||||
"Content Manager": "Gestão de conteúdo",
|
||||
"Content Type Builder": "Construtor de Conteúdo",
|
||||
"Files Upload": "Enviar arquivos",
|
||||
"Roles & Permissions": "Papéis e permissões",
|
||||
"Settings Manager": "Gerenciador de configurações",
|
||||
"Email": "E-mail",
|
||||
"Password": "Senha",
|
||||
|
||||
@ -17,10 +17,13 @@
|
||||
"app.components.HomePage.welcomeBlock.content": "Мы рады, что вы вступили в сообщество. Нам необходима обратная связь для развития проекта, поэтому не стесняйтесь писать нам\u0020",
|
||||
"app.components.HomePage.welcomeBlock.content.issues": "проблема.",
|
||||
"app.components.HomePage.welcomeBlock.content.raise": "\u0020или поднять\u0020",
|
||||
"app.components.HomePage.welcome.again": "Добро пожаловать",
|
||||
"app.components.HomePage.welcomeBlock.content.again": "Надеемся у вы делаете успехи в вашем проекте... Следите с последними новостями о Strapi. Мы стараемся изо всех сил, чтобы улучшить продукт основываясь на ваших пожеланиях.",
|
||||
"app.components.HomePage.createBlock.content.first": "\u0020",
|
||||
"app.components.HomePage.createBlock.content.second": "\u0020плагин поможет вам создать структуру ваших данных. Если вы новичок, мы настоятельно рекомендуем вам следить за нашими\u0020",
|
||||
"app.components.HomePage.createBlock.content.tutorial": "\u0020руководство.",
|
||||
"app.components.HomePage.button.quickStart": "ОЗНАКОМТЕСЬ С РУКОВОДСТВОМ ПО БЫСТРОМУ СТАРТУ",
|
||||
"app.components.HomePage.button.blog": "СМОТРИТЕ БОЛЬШЕ В БЛОГЕ",
|
||||
"app.components.HomePage.support": "ПОДДЕРЖИТЕ НАС",
|
||||
"app.components.HomePage.support.content": "Купите футболку, это поможет нам продолжать работу над проектом, чтобы предоставить вам наилучшее из возможных решений!",
|
||||
"app.components.HomePage.support.link": "ЗАКАЗАТЬ НАШУ ФУТБОЛКУ СЕЙЧАС",
|
||||
@ -113,6 +116,7 @@
|
||||
"components.Input.error.validation.min": "Слишком маленькое.",
|
||||
"components.Input.error.validation.maxLength": "Слишком длинное.",
|
||||
"components.Input.error.validation.minLength": "Слишком короткое.",
|
||||
"components.Input.error.validation.json": "Не соответствует JSON формату",
|
||||
"components.Input.error.contentTypeName.taken": "Это название уже существует",
|
||||
"components.Input.error.attribute.taken": "Поле с таким названием уже существует",
|
||||
"components.Input.error.attribute.key.taken": "Это значение уже существует",
|
||||
@ -136,6 +140,8 @@
|
||||
"components.WysiwygBottomControls.uploadFiles": "Перетащите файлы в эту область, добавляйте из буфер обмена или {browse}.",
|
||||
"components.WysiwygBottomControls.uploadFiles.browse": "выделите их",
|
||||
"components.WysiwygBottomControls.fullscreen": "Развернуть",
|
||||
"Files Upload": "Загрузка файлов",
|
||||
|
||||
|
||||
"HomePage.notification.newsLetter.success": "Успешная подписка на рассылку новостей",
|
||||
|
||||
@ -143,6 +149,7 @@
|
||||
"notification.error.layout": "Не удалось получить макет",
|
||||
|
||||
"Users & Permissions": "Пользователи & Доступы",
|
||||
"Roles & Permissions": "Роли и доступы",
|
||||
"Content Manager": "Редактор контента",
|
||||
"Content Type Builder": "Конструктор Типов Контента",
|
||||
"Settings Manager": "Менеджер Настроек",
|
||||
|
||||
@ -122,10 +122,11 @@
|
||||
"components.Input.error.attribute.sameKeyAndName": "Eşit olamaz",
|
||||
"components.Input.error.validation.minSupMax": "Üstü olamaz",
|
||||
"components.Input.error.custom-error": "{errorMessage} ",
|
||||
"components.Input.error.validation.json": "Bu JSON biçimi ile eşleşmiyor",
|
||||
|
||||
"components.ListRow.empty": "Gösterilecek veri bulunmamaktadır.",
|
||||
|
||||
"components.Wysiwyg.collapse": "Collapse",
|
||||
"components.Wysiwyg.collapse": "Daralt",
|
||||
"components.Wysiwyg.selectOptions.title": "Başlık ekle",
|
||||
"components.Wysiwyg.selectOptions.H1": "H1 başlık",
|
||||
"components.Wysiwyg.selectOptions.H2": "H2 başlık",
|
||||
@ -143,11 +144,13 @@
|
||||
"HomePage.notification.newsLetter.success": "Bültene başarıyla abone olundu",
|
||||
|
||||
"notification.error": "Bir hata oluştu",
|
||||
"notification.error.layout": "Couldn't retrieve the layout",
|
||||
"notification.error.layout": "Düzen alınamadı",
|
||||
|
||||
"Users & Permissions": "Kullanıcılar & İzinler",
|
||||
"Content Manager": "İçerik Yönetimi",
|
||||
"Content Type Builder": "İçerik Türü Oluşturucusu",
|
||||
"Files Upload": "Dosya yükleme",
|
||||
"Roles & Permissions": "Roller & İzinler",
|
||||
"Settings Manager": "Yönetici Ayarları",
|
||||
"Email": "E-posta",
|
||||
"Password": "Şifre",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const exec = require('child_process').execSync;
|
||||
const exec = require('child_process').spawnSync;
|
||||
const _ = require('lodash');
|
||||
|
||||
/**
|
||||
@ -53,8 +53,7 @@ module.exports = {
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
strapi.log.info(`Installing ${plugin}...`);
|
||||
|
||||
exec(`node "${strapiBin}" install ${plugin} ${port === '4000' ? '--dev' : ''}`);
|
||||
exec('node', [strapiBin, 'install', plugin, (port === '4000') ? '--dev' : '']);
|
||||
|
||||
ctx.send({ ok: true });
|
||||
|
||||
@ -87,7 +86,7 @@ module.exports = {
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
strapi.log.info(`Uninstalling ${plugin}...`);
|
||||
exec(`node "${strapiBin}" uninstall ${plugin}`);
|
||||
exec('node', [strapiBin, 'uninstall', plugin]);
|
||||
|
||||
ctx.send({ ok: true });
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-admin",
|
||||
"version": "3.0.0-alpha.12.7.1",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"description": "Strapi Admin",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -31,8 +31,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"sanitize.css": "^4.1.0",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12.7.1",
|
||||
"strapi-utils": "3.0.0-alpha.12.7.1"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.14",
|
||||
"strapi-utils": "3.0.0-alpha.14"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi",
|
||||
@ -51,4 +51,4 @@
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
0
packages/strapi-ejs/.editorconfig → packages/strapi-email-amazon-ses/.editorconfig
Executable file → Normal file
0
packages/strapi-ejs/.editorconfig → packages/strapi-email-amazon-ses/.editorconfig
Executable file → Normal file
1
packages/strapi-bookshelf/.gitignore → packages/strapi-email-amazon-ses/.gitignore
vendored
Executable file → Normal file
1
packages/strapi-bookshelf/.gitignore → packages/strapi-email-amazon-ses/.gitignore
vendored
Executable file → Normal file
@ -93,3 +93,4 @@ build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
104
packages/strapi-email-amazon-ses/.npmignore
Normal file
104
packages/strapi-email-amazon-ses/.npmignore
Normal file
@ -0,0 +1,104 @@
|
||||
############################
|
||||
# OS X
|
||||
############################
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
._*
|
||||
|
||||
|
||||
############################
|
||||
# Linux
|
||||
############################
|
||||
|
||||
*~
|
||||
|
||||
|
||||
############################
|
||||
# Windows
|
||||
############################
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
|
||||
############################
|
||||
# Packages
|
||||
############################
|
||||
|
||||
*.7z
|
||||
*.csv
|
||||
*.dat
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.seed
|
||||
*.so
|
||||
*.swo
|
||||
*.swp
|
||||
*.swn
|
||||
*.swm
|
||||
*.out
|
||||
*.pid
|
||||
|
||||
|
||||
############################
|
||||
# Logs and databases
|
||||
############################
|
||||
|
||||
.tmp
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
|
||||
############################
|
||||
# Misc.
|
||||
############################
|
||||
|
||||
*#
|
||||
ssl
|
||||
.editorconfig
|
||||
.gitattributes
|
||||
.idea
|
||||
nbproject
|
||||
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
############################
|
||||
|
||||
lib-cov
|
||||
lcov.info
|
||||
pids
|
||||
logs
|
||||
results
|
||||
build
|
||||
node_modules
|
||||
.node_history
|
||||
|
||||
|
||||
############################
|
||||
# Tests
|
||||
############################
|
||||
|
||||
test
|
||||
7
packages/strapi-email-amazon-ses/LICENSE.md
Normal file
7
packages/strapi-email-amazon-ses/LICENSE.md
Normal file
@ -0,0 +1,7 @@
|
||||
Copyright (c) 2018 Nikolay Tsenkov (nikolay@tsenkov.net).
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
11
packages/strapi-email-amazon-ses/README.md
Normal file
11
packages/strapi-email-amazon-ses/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# strapi-email-amazon-ses
|
||||
|
||||
## Resources
|
||||
|
||||
- [MIT License](LICENSE.md)
|
||||
|
||||
## Links
|
||||
|
||||
- [Strapi website](http://strapi.io/)
|
||||
- [Strapi community on Slack](http://slack.strapi.io)
|
||||
- [Strapi news on Twitter](https://twitter.com/strapijs)
|
||||
73
packages/strapi-email-amazon-ses/lib/index.js
Normal file
73
packages/strapi-email-amazon-ses/lib/index.js
Normal file
@ -0,0 +1,73 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
/* eslint-disable import/no-unresolved */
|
||||
/* eslint-disable prefer-template */
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const nodeSES = require('node-ses');
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
module.exports = {
|
||||
provider: 'amazon-ses',
|
||||
name: 'Amazon SES',
|
||||
auth: {
|
||||
amazon_ses_default_from: {
|
||||
label: 'Default From',
|
||||
type: 'text'
|
||||
},
|
||||
amazon_ses_default_replyto: {
|
||||
label: 'Default Reply-To',
|
||||
type: 'text'
|
||||
},
|
||||
amazon_ses_api_key: {
|
||||
label: 'Amazon Access key ID',
|
||||
type: 'text'
|
||||
},
|
||||
amazon_ses_secret: {
|
||||
label: 'Amazon Secret access key',
|
||||
type: 'text'
|
||||
}
|
||||
},
|
||||
|
||||
init: (config) => {
|
||||
|
||||
var client = nodeSES.createClient({
|
||||
key: config.amazon_ses_api_key,
|
||||
secret: config.amazon_ses_secret
|
||||
});
|
||||
|
||||
return {
|
||||
send: (options, cb) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Default values.
|
||||
options = _.isObject(options) ? options : {};
|
||||
options.from = options.from || config.amazon_ses_default_from;
|
||||
options.replyTo = options.replyTo || config.amazon_ses_default_replyto;
|
||||
options.text = options.text || options.html;
|
||||
options.html = options.html || options.text;
|
||||
|
||||
let msg = {
|
||||
from: options.from,
|
||||
to: options.to,
|
||||
replyTo: options.replyTo,
|
||||
subject: options.subject,
|
||||
altText: options.text,
|
||||
message: options.html
|
||||
};
|
||||
|
||||
client.sendEmail(msg, function (err) {
|
||||
if (err) {
|
||||
reject([{ messages: [{ id: 'Auth.form.error.email.invalid' }] }]);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
45
packages/strapi-email-amazon-ses/package.json
Normal file
45
packages/strapi-email-amazon-ses/package.json
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "strapi-email-amazon-ses",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"description": "Amazon SES provider for strapi email",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
"email",
|
||||
"strapi",
|
||||
"amazon",
|
||||
"ses"
|
||||
],
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"main": "./lib",
|
||||
"dependencies": {
|
||||
"node-ses": "^2.1.0"
|
||||
},
|
||||
"strapi": {
|
||||
"isProvider": true
|
||||
},
|
||||
"author": {
|
||||
"email": "nikolay@tsenkov.net",
|
||||
"name": "Nikolay tsenkov"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Strapi team",
|
||||
"email": "hi@strapi.io",
|
||||
"url": "http://strapi.io"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/strapi/strapi.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/strapi/strapi/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
"npm": ">= 5.3.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
1
packages/strapi-email-mailgun/.gitignore
vendored
1
packages/strapi-email-mailgun/.gitignore
vendored
@ -93,3 +93,4 @@ build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-email-mailgun",
|
||||
"version": "3.0.0-alpha.12.7.1",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"description": "Mailgun provider for strapi email plugin",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
1
packages/strapi-email-sendgrid/.gitignore
vendored
1
packages/strapi-email-sendgrid/.gitignore
vendored
@ -93,3 +93,4 @@ build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-email-sendgrid",
|
||||
"version": "3.0.0-alpha.12.7.1",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"description": "Sendgrid provider for strapi email",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
1
packages/strapi-email-sendmail/.gitignore
vendored
1
packages/strapi-email-sendmail/.gitignore
vendored
@ -93,3 +93,4 @@ build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-email-sendmail",
|
||||
"version": "3.0.0-alpha.12.7.1",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"description": "Sendmail provider for strapi email",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
1
packages/strapi-generate-admin/.gitignore
vendored
1
packages/strapi-generate-admin/.gitignore
vendored
@ -92,6 +92,7 @@ build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
|
||||
############################
|
||||
|
||||
@ -3,6 +3,7 @@ coverage
|
||||
node_modules
|
||||
stats.json
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Cruft
|
||||
.DS_Store
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-admin",
|
||||
"version": "3.0.0-alpha.12.7.1",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"description": "Generate the default admin panel for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -14,9 +14,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": "^4.0.1",
|
||||
"lodash": "^4.17.4",
|
||||
"strapi-admin": "3.0.0-alpha.12.7.1",
|
||||
"strapi-utils": "3.0.0-alpha.12.7.1"
|
||||
"lodash": "^4.17.5",
|
||||
"strapi-admin": "3.0.0-alpha.14",
|
||||
"strapi-utils": "3.0.0-alpha.14"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
|
||||
1
packages/strapi-generate-api/.gitignore
vendored
1
packages/strapi-generate-api/.gitignore
vendored
@ -93,6 +93,7 @@ build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
|
||||
############################
|
||||
|
||||
5
packages/strapi-generate-api/jest.config.js
Normal file
5
packages/strapi-generate-api/jest.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
name: 'generate-api',
|
||||
displayName: 'Generated API',
|
||||
testMatch: ['**/test/?(*.)+(spec|test).js']
|
||||
};
|
||||
@ -39,7 +39,7 @@ module.exports = (scope, cb) => {
|
||||
idPluralized: pluralize.plural(_.trim(_.camelCase(scope.id))),
|
||||
parentId: _.isEmpty(parent) ? undefined : _.trim(_.deburr(parent)),
|
||||
parentIdPluralized: _.isEmpty(scope.parentId) ? undefined : pluralize.plural(_.trim(_.camelCase(scope.parentId))),
|
||||
environment: process.NODE_ENV || 'development'
|
||||
environment: process.env.NODE_ENV || 'development'
|
||||
});
|
||||
|
||||
// Determine default values based on the available scope.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-api",
|
||||
"version": "3.0.0-alpha.12.7.1",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"description": "Generate an API for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -13,7 +13,7 @@
|
||||
"lib": "./lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.4",
|
||||
"lodash": "^4.17.5",
|
||||
"pluralize": "^6.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
const _ = require('lodash');
|
||||
|
||||
// Strapi utilities.
|
||||
const utils = require('strapi-bookshelf/lib/utils/');
|
||||
const utils = require('strapi-hook-bookshelf/lib/utils/');
|
||||
|
||||
module.exports = {
|
||||
|
||||
|
||||
@ -83,7 +83,7 @@ module.exports = {
|
||||
const entry = await <%= globalID %>.create(data);
|
||||
|
||||
// Create relational data and return the entry.
|
||||
return <%= globalID %>.updateRelations({ id: entry.id, values: relations });
|
||||
return <%= globalID %>.updateRelations({ _id: entry.id, values: relations });
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
843
packages/strapi-generate-api/test/endpoint.test.js
Normal file
843
packages/strapi-generate-api/test/endpoint.test.js
Normal file
@ -0,0 +1,843 @@
|
||||
// Helpers.
|
||||
const {login} = require('../../../test/helpers/auth');
|
||||
const form = require('../../../test/helpers/generators');
|
||||
const restart = require('../../../test/helpers/restart');
|
||||
const rq = require('../../../test/helpers/request');
|
||||
|
||||
const cleanDate = (entry) => {
|
||||
delete entry.updatedAt;
|
||||
delete entry.createdAt;
|
||||
delete entry.created_at;
|
||||
delete entry.updated_at;
|
||||
};
|
||||
|
||||
let data;
|
||||
|
||||
describe('App setup auth', () => {
|
||||
test(
|
||||
'Login admin user',
|
||||
async () => {
|
||||
await restart(rq);
|
||||
|
||||
const body = await login();
|
||||
|
||||
rq.defaults({
|
||||
headers: {
|
||||
'Authorization': `Bearer ${body.jwt}`
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('Generate test APIs', () => {
|
||||
beforeEach(async () => {
|
||||
await restart(rq);
|
||||
}, 60000);
|
||||
|
||||
test(
|
||||
'Create new article API',
|
||||
async () => {
|
||||
await rq({
|
||||
url: `/content-type-builder/models`,
|
||||
method: 'POST',
|
||||
body: form.article,
|
||||
json: true
|
||||
});
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create new tag API',
|
||||
async () => {
|
||||
await rq({
|
||||
url: `/content-type-builder/models`,
|
||||
method: 'POST',
|
||||
body: form.tag,
|
||||
json: true
|
||||
});
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create new category API',
|
||||
async () => {
|
||||
await rq({
|
||||
url: `/content-type-builder/models`,
|
||||
method: 'POST',
|
||||
body: form.category,
|
||||
json: true
|
||||
});
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create new reference API',
|
||||
async () => {
|
||||
await rq({
|
||||
url: `/content-type-builder/models`,
|
||||
method: 'POST',
|
||||
body: form.reference,
|
||||
json: true
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('Test manyToMany relation (article - tag) with Content Manager', () => {
|
||||
beforeAll(() => {
|
||||
data = {
|
||||
articles: [],
|
||||
tags: []
|
||||
};
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await restart(rq);
|
||||
}, 60000);
|
||||
|
||||
test(
|
||||
'Create tag1',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/tag`,
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: 'tag1'
|
||||
},
|
||||
json: true
|
||||
});
|
||||
|
||||
data.tags.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(Array.isArray(body.articles)).toBeTruthy();
|
||||
expect(body.name).toBe('tag1');
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create tag2',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/tag`,
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: 'tag2'
|
||||
},
|
||||
json: true
|
||||
});
|
||||
|
||||
data.tags.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(Array.isArray(body.articles)).toBeTruthy();
|
||||
expect(body.name).toBe('tag2');
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create tag3',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/tag`,
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: 'tag3'
|
||||
},
|
||||
json: true
|
||||
});
|
||||
|
||||
data.tags.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(Array.isArray(body.articles)).toBeTruthy();
|
||||
expect(body.name).toBe('tag3');
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create article1 without relation',
|
||||
async () => {
|
||||
const entry = {
|
||||
title: 'Article 1',
|
||||
content: 'My super content 1'
|
||||
};
|
||||
|
||||
let body = await rq({
|
||||
url: `/article`,
|
||||
method: 'POST',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(Array.isArray(body.tags)).toBeTruthy();
|
||||
expect(body.tags.length).toBe(0);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create article2 with tag1',
|
||||
async () => {
|
||||
const entry = {
|
||||
title: 'Article 2',
|
||||
content: 'Content 2',
|
||||
tags: [data.tags[0]]
|
||||
};
|
||||
|
||||
let body = await rq({
|
||||
url: `/article`,
|
||||
method: 'POST',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(Array.isArray(body.tags)).toBeTruthy();
|
||||
expect(body.tags.length).toBe(1);
|
||||
expect(body.tags[0].id).toBe(data.tags[0].id);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Update article1 add tag2',
|
||||
async () => {
|
||||
const entry = Object.assign({}, data.articles[0], {
|
||||
tags: [data.tags[1]]
|
||||
});
|
||||
|
||||
cleanDate(entry);
|
||||
|
||||
let body = await rq({
|
||||
url: `/article/${entry.id}`,
|
||||
method: 'PUT',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles[0] = body;
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(Array.isArray(body.tags)).toBeTruthy();
|
||||
expect(body.tags.length).toBe(1);
|
||||
expect(body.tags[0].id).toBe(data.tags[1].id);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Update article1 add tag1 and tag3',
|
||||
async () => {
|
||||
const entry = Object.assign({}, data.articles[0]);
|
||||
entry.tags.push(data.tags[0]);
|
||||
entry.tags.push(data.tags[2]);
|
||||
|
||||
cleanDate(entry);
|
||||
|
||||
let body = await rq({
|
||||
url: `/article/${entry.id}`,
|
||||
method: 'PUT',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles[0] = body;
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(Array.isArray(body.tags)).toBeTruthy();
|
||||
expect(body.tags.length).toBe(3);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Update article1 remove one tag',
|
||||
async () => {
|
||||
const entry = Object.assign({}, data.articles[0]);
|
||||
entry.tags = entry.tags.slice(1);
|
||||
|
||||
cleanDate(entry);
|
||||
|
||||
let body = await rq({
|
||||
url: `/article/${entry.id}`,
|
||||
method: 'PUT',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles[0] = body;
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(Array.isArray(body.tags)).toBeTruthy();
|
||||
expect(body.tags.length).toBe(2);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Update article1 remove all tag',
|
||||
async () => {
|
||||
const entry = Object.assign({}, data.articles[0], {
|
||||
tags: []
|
||||
});
|
||||
|
||||
cleanDate(entry);
|
||||
|
||||
let body = await rq({
|
||||
url: `/article/${entry.id}`,
|
||||
method: 'PUT',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles[0] = body;
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(Array.isArray(body.tags)).toBeTruthy();
|
||||
expect(body.tags.length).toBe(0);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('Test oneToMany - manyToOne relation (article - category) with Content Manager', () => {
|
||||
beforeAll(() => {
|
||||
data = {
|
||||
articles: [],
|
||||
categories: []
|
||||
};
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await restart(rq);
|
||||
}, 60000);
|
||||
|
||||
test(
|
||||
'Create cat1',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/category`,
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: 'cat1'
|
||||
},
|
||||
json: true
|
||||
});
|
||||
|
||||
data.categories.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(Array.isArray(body.articles)).toBeTruthy();
|
||||
expect(body.name).toBe('cat1');
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create cat2',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/category`,
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: 'cat2'
|
||||
},
|
||||
json: true
|
||||
});
|
||||
|
||||
data.categories.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(Array.isArray(body.articles)).toBeTruthy();
|
||||
expect(body.name).toBe('cat2');
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create article1 with cat1',
|
||||
async () => {
|
||||
const entry = {
|
||||
title: 'Article 1',
|
||||
content: 'Content 1',
|
||||
category: data.categories[0]
|
||||
};
|
||||
|
||||
let body = await rq({
|
||||
url: `/article`,
|
||||
method: 'POST',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(body.category.name).toBe(entry.category.name);
|
||||
expect(Array.isArray(body.tags)).toBeTruthy();
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Update article1 with cat2',
|
||||
async () => {
|
||||
const entry = Object.assign({}, data.articles[0], {
|
||||
category: data.categories[1]
|
||||
});
|
||||
|
||||
cleanDate(entry);
|
||||
|
||||
let body = await rq({
|
||||
url: `/article/${entry.id}`,
|
||||
method: 'PUT',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles[0] = body;
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(body.category.name).toBe(entry.category.name);
|
||||
expect(Array.isArray(body.tags)).toBeTruthy();
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create article2',
|
||||
async () => {
|
||||
const entry = {
|
||||
title: 'Article 2',
|
||||
content: 'Content 2'
|
||||
};
|
||||
|
||||
let body = await rq({
|
||||
url: `/article`,
|
||||
method: 'POST',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(Array.isArray(body.tags)).toBeTruthy();
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Update article2 with cat2',
|
||||
async () => {
|
||||
const entry = Object.assign({}, data.articles[1], {
|
||||
category: data.categories[1]
|
||||
});
|
||||
|
||||
cleanDate(entry);
|
||||
|
||||
let body = await rq({
|
||||
url: `/article/${entry.id}`,
|
||||
method: 'PUT',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles[1] = body;
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(body.category.name).toBe(entry.category.name);
|
||||
expect(Array.isArray(body.tags)).toBeTruthy();
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Update cat1 with article1',
|
||||
async () => {
|
||||
const entry = Object.assign({}, data.categories[0]);
|
||||
entry.articles.push(data.articles[0]);
|
||||
|
||||
cleanDate(entry);
|
||||
|
||||
let body = await rq({
|
||||
url: `/category/${entry.id}`,
|
||||
method: 'PUT',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.categories[0] = body;
|
||||
|
||||
expect(body.id);
|
||||
expect(Array.isArray(body.articles)).toBeTruthy();
|
||||
expect(body.articles.length).toBe(1);
|
||||
expect(body.name).toBe(entry.name);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create cat3 with article1',
|
||||
async () => {
|
||||
const entry = {
|
||||
name: 'cat3',
|
||||
articles: [data.articles[0]]
|
||||
};
|
||||
|
||||
let body = await rq({
|
||||
url: `/category`,
|
||||
method: 'POST',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.categories.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(Array.isArray(body.articles)).toBeTruthy();
|
||||
expect(body.articles.length).toBe(1);
|
||||
expect(body.name).toBe(entry.name);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Get article1 with cat3',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/article/${data.articles[0].id}`,
|
||||
method: 'GET',
|
||||
json: true
|
||||
});
|
||||
|
||||
expect(body.id);
|
||||
expect(body.category.id).toBe(data.categories[2].id)
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Get article2 with cat2',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/article/${data.articles[1].id}`,
|
||||
method: 'GET',
|
||||
json: true
|
||||
});
|
||||
|
||||
expect(body.id);
|
||||
expect(body.category.id).toBe(data.categories[1].id)
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Get cat1 without relations',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/category/${data.categories[0].id}`,
|
||||
method: 'GET',
|
||||
json: true
|
||||
});
|
||||
|
||||
expect(body.id);
|
||||
expect(body.articles.length).toBe(0);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Get cat2 with article2',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/category/${data.categories[1].id}`,
|
||||
method: 'GET',
|
||||
json: true
|
||||
});
|
||||
|
||||
expect(body.id);
|
||||
expect(body.articles.length).toBe(1);
|
||||
expect(body.articles[0].id).toBe(data.articles[1].id);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Get cat3 with article1',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/category/${data.categories[2].id}`,
|
||||
method: 'GET',
|
||||
json: true
|
||||
});
|
||||
|
||||
expect(body.id);
|
||||
expect(body.articles.length).toBe(1);
|
||||
expect(body.articles[0].id).toBe(data.articles[0].id);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('Test oneToOne relation (article - reference) with Content Manager', () => {
|
||||
beforeAll(() => {
|
||||
data = {
|
||||
articles: [],
|
||||
references: []
|
||||
};
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await restart(rq);
|
||||
}, 60000);
|
||||
|
||||
test(
|
||||
'Create ref1',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/reference`,
|
||||
method: 'POST',
|
||||
body: {
|
||||
name: 'ref1'
|
||||
},
|
||||
json: true
|
||||
});
|
||||
|
||||
data.references.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(body.name).toBe('ref1');
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create article1',
|
||||
async () => {
|
||||
const entry = {
|
||||
title: 'Article 1',
|
||||
content: 'Content 1'
|
||||
};
|
||||
|
||||
let body = await rq({
|
||||
url: `/article`,
|
||||
method: 'POST',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Update article1 with ref1',
|
||||
async () => {
|
||||
const entry = Object.assign({}, data.articles[0], {
|
||||
reference: data.references[0].id
|
||||
});
|
||||
|
||||
cleanDate(entry);
|
||||
|
||||
let body = await rq({
|
||||
url: `/article/${entry.id}`,
|
||||
method: 'PUT',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles[0] = body;
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(body.reference.id).toBe(entry.reference);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Create article2 with ref1',
|
||||
async () => {
|
||||
const entry = {
|
||||
title: 'Article 2',
|
||||
content: 'Content 2',
|
||||
reference: data.references[0].id
|
||||
};
|
||||
|
||||
let body = await rq({
|
||||
url: `/article`,
|
||||
method: 'POST',
|
||||
body: entry,
|
||||
json: true
|
||||
});
|
||||
|
||||
data.articles.push(body);
|
||||
|
||||
expect(body.id);
|
||||
expect(body.title).toBe(entry.title);
|
||||
expect(body.content).toBe(entry.content);
|
||||
expect(body.reference.id).toBe(entry.reference);
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Get article1 without relations',
|
||||
async () => {
|
||||
let body = await rq({
|
||||
url: `/article/${data.articles[0].id}`,
|
||||
method: 'GET',
|
||||
json: true
|
||||
});
|
||||
|
||||
expect(body.id);
|
||||
expect(body.reference).toBe(null);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('Test oneWay relation (reference - tag) with Content Manager', () => {
|
||||
beforeEach(async () => {
|
||||
await restart(rq);
|
||||
}, 60000);
|
||||
|
||||
test(
|
||||
'Attach Tag to a Reference',
|
||||
async () => {
|
||||
const tagToCreate = await rq({
|
||||
url: `/tag`,
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: {
|
||||
name: 'tag111'
|
||||
}
|
||||
});
|
||||
|
||||
const referenceToCreate = await rq({
|
||||
url: `/reference`,
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: {
|
||||
name: 'cat111',
|
||||
tag: tagToCreate
|
||||
}
|
||||
});
|
||||
|
||||
expect(referenceToCreate.tag.id).toBe(tagToCreate.id);
|
||||
}
|
||||
);
|
||||
|
||||
test(
|
||||
'Detach Tag to a Reference',
|
||||
async () => {
|
||||
const tagToCreate = await rq({
|
||||
url: `/tag`,
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: {
|
||||
name: 'tag111'
|
||||
}
|
||||
});
|
||||
|
||||
const referenceToCreate = await rq({
|
||||
url: `/reference`,
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: {
|
||||
name: 'cat111',
|
||||
tag: tagToCreate
|
||||
}
|
||||
});
|
||||
|
||||
expect(referenceToCreate.tag.id).toBe(tagToCreate.id);
|
||||
|
||||
const referenceToUpdate = await rq({
|
||||
url: `/reference/${referenceToCreate.id}`,
|
||||
method: 'PUT',
|
||||
json: true,
|
||||
body: {
|
||||
tag: null
|
||||
}
|
||||
});
|
||||
|
||||
expect(referenceToUpdate.tag).toBe(null);
|
||||
}
|
||||
);
|
||||
|
||||
test(
|
||||
'Delete Tag so the relation in the Reference side should be removed',
|
||||
async () => {
|
||||
const tagToCreate = await rq({
|
||||
url: `/tag`,
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: {
|
||||
name: 'tag111'
|
||||
}
|
||||
});
|
||||
|
||||
const referenceToCreate = await rq({
|
||||
url: `/reference`,
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: {
|
||||
name: 'cat111',
|
||||
tag: tagToCreate
|
||||
}
|
||||
});
|
||||
|
||||
const tagToDelete = await rq({
|
||||
url: `/tag/${tagToCreate.id}`,
|
||||
method: 'DELETE',
|
||||
json: true
|
||||
});
|
||||
|
||||
const referenceToGet = await rq({
|
||||
url: `/reference/${referenceToCreate.id}`,
|
||||
method: 'GET',
|
||||
json: true
|
||||
});
|
||||
|
||||
try {
|
||||
if (Object.keys(referenceToGet.tag).length == 0) {
|
||||
referenceToGet.tag = null;
|
||||
}
|
||||
} catch(err) {
|
||||
// Silent
|
||||
}
|
||||
|
||||
expect(referenceToGet.tag).toBe(null);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('Delete test APIs', () => {
|
||||
beforeEach(async () => {
|
||||
await restart(rq);
|
||||
}, 60000);
|
||||
|
||||
test(
|
||||
'Delete article API',
|
||||
async () => {
|
||||
await rq({
|
||||
url: `/content-type-builder/models/article`,
|
||||
method: 'DELETE',
|
||||
json: true
|
||||
});
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Delete tag API',
|
||||
async () => {
|
||||
await rq({
|
||||
url: `/content-type-builder/models/tag`,
|
||||
method: 'DELETE',
|
||||
json: true
|
||||
});
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Delete category API',
|
||||
async () => {
|
||||
await rq({
|
||||
url: `/content-type-builder/models/category`,
|
||||
method: 'DELETE',
|
||||
json: true
|
||||
});
|
||||
}
|
||||
);
|
||||
test(
|
||||
'Delete reference API',
|
||||
async () => {
|
||||
await rq({
|
||||
url: `/content-type-builder/models/reference`,
|
||||
method: 'DELETE',
|
||||
json: true
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
@ -93,6 +93,7 @@ build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
|
||||
############################
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-controller",
|
||||
"version": "3.0.0-alpha.12.7.1",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"description": "Generate a controller for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -14,7 +14,7 @@
|
||||
"lib": "./lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.4"
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"scripts": {
|
||||
"prepublish": "npm prune"
|
||||
|
||||
1
packages/strapi-generate-model/.gitignore
vendored
1
packages/strapi-generate-model/.gitignore
vendored
@ -93,6 +93,7 @@ build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
|
||||
############################
|
||||
|
||||
@ -33,7 +33,7 @@ module.exports = (scope, cb) => {
|
||||
_.defaults(scope, {
|
||||
id: _.trim(_.deburr(scope.id)),
|
||||
idPluralized: pluralize.plural(_.trim(_.deburr(scope.id))),
|
||||
environment: process.NODE_ENV || 'development'
|
||||
environment: process.env.NODE_ENV || 'development'
|
||||
});
|
||||
|
||||
// Determine default values based on the available scope.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-model",
|
||||
"version": "3.0.0-alpha.12.7.1",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"description": "Generate a model for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -14,7 +14,7 @@
|
||||
"lib": "./lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.4"
|
||||
"lodash": "^4.17.5"
|
||||
},
|
||||
"scripts": {
|
||||
"prepublish": "npm prune"
|
||||
|
||||
1
packages/strapi-generate-new/.gitignore
vendored
1
packages/strapi-generate-new/.gitignore
vendored
@ -92,6 +92,7 @@ build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
|
||||
############################
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{
|
||||
"host": "localhost",
|
||||
"port": 1337,
|
||||
"proxy": {
|
||||
"enabled": false
|
||||
},
|
||||
"autoReload": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"defaultConnection": "default",
|
||||
"connections": {
|
||||
"default": {
|
||||
"connector": "strapi-mongoose",
|
||||
"connector": "strapi-hook-mongoose",
|
||||
"settings": {
|
||||
"client": "mongo",
|
||||
"uri": "${process.env.DATABASE_URI || ''}",
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{
|
||||
"host": "localhost",
|
||||
"port": "${process.env.PORT || 1337}",
|
||||
"proxy": {
|
||||
"enabled": false
|
||||
},
|
||||
"autoReload": {
|
||||
"enabled": false
|
||||
},
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"defaultConnection": "default",
|
||||
"connections": {
|
||||
"default": {
|
||||
"connector": "strapi-mongoose",
|
||||
"connector": "strapi-hook-mongoose",
|
||||
"settings": {
|
||||
"client": "mongo",
|
||||
"uri": "${process.env.DATABASE_URI || ''}",
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{
|
||||
"host": "localhost",
|
||||
"port": "${process.env.PORT || 1337}",
|
||||
"proxy": {
|
||||
"enabled": false
|
||||
},
|
||||
"autoReload": {
|
||||
"enabled": false
|
||||
},
|
||||
|
||||
@ -187,10 +187,10 @@ module.exports = (scope, cb) => {
|
||||
console.log();
|
||||
console.log(`👌 Your new application ${green(scope.name)} is ready at ${cyan(scope.rootPath)}.`);
|
||||
console.log();
|
||||
console.log('⚡️ change directory:');
|
||||
console.log('⚡️ Change directory:');
|
||||
console.log(`$ ${green(`cd ${scope.name}`)}`);
|
||||
console.log();
|
||||
console.log('⚡️ start application:');
|
||||
console.log('⚡️ Start application:');
|
||||
console.log(`$ ${green('strapi start')}`);
|
||||
|
||||
cb();
|
||||
|
||||
@ -69,14 +69,14 @@ module.exports = (scope, cb) => {
|
||||
name: 'MongoDB (recommended)',
|
||||
value: {
|
||||
database: 'mongo',
|
||||
connector: 'strapi-mongoose'
|
||||
connector: 'strapi-hook-mongoose'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Postgres',
|
||||
value: {
|
||||
database: 'postgres',
|
||||
connector: 'strapi-bookshelf',
|
||||
connector: 'strapi-hook-bookshelf',
|
||||
module: 'pg'
|
||||
}
|
||||
},
|
||||
@ -84,7 +84,7 @@ module.exports = (scope, cb) => {
|
||||
name: 'MySQL',
|
||||
value: {
|
||||
database: 'mysql',
|
||||
connector: 'strapi-bookshelf',
|
||||
connector: 'strapi-hook-bookshelf',
|
||||
module: 'mysql'
|
||||
}
|
||||
}
|
||||
@ -132,7 +132,7 @@ module.exports = (scope, cb) => {
|
||||
type: 'input',
|
||||
name: 'database',
|
||||
message: 'Database name:',
|
||||
default: _.get(scope.database, 'database', 'strapi')
|
||||
default: _.get(scope.database, 'database', scope.name)
|
||||
},
|
||||
{
|
||||
when: !hasDatabaseConfig,
|
||||
@ -141,11 +141,18 @@ module.exports = (scope, cb) => {
|
||||
message: 'Host:',
|
||||
default: _.get(scope.database, 'host', '127.0.0.1')
|
||||
},
|
||||
{
|
||||
when: !hasDatabaseConfig && scope.client.database === 'mongo',
|
||||
type: 'boolean',
|
||||
name: 'srv',
|
||||
message: '+srv connection:',
|
||||
default: _.get(scope.database, 'srv', false)
|
||||
},
|
||||
{
|
||||
when: !hasDatabaseConfig,
|
||||
type: 'input',
|
||||
name: 'port',
|
||||
message: 'Port:',
|
||||
message: `Port${scope.client.database === 'mongo' ? ' (It will be ignored if you enable +srv)' : ''}:`,
|
||||
default: (answers) => { // eslint-disable-line no-unused-vars
|
||||
if (_.get(scope.database, 'port')) {
|
||||
return scope.database.port;
|
||||
@ -179,7 +186,7 @@ module.exports = (scope, cb) => {
|
||||
when: !hasDatabaseConfig && scope.client.database === 'mongo',
|
||||
type: 'input',
|
||||
name: 'authenticationDatabase',
|
||||
message: 'Authentication database:',
|
||||
message: 'Authentication database (Maybe "admin" or blank):',
|
||||
default: _.get(scope.database, 'authenticationDatabase', undefined)
|
||||
},
|
||||
{
|
||||
@ -192,10 +199,11 @@ module.exports = (scope, cb) => {
|
||||
])
|
||||
.then(answers => {
|
||||
if (hasDatabaseConfig) {
|
||||
answers = _.omit(scope.database.settings, ['client']);
|
||||
answers = _.merge((_.omit(scope.database.settings, ['client'])), scope.database.options);
|
||||
}
|
||||
|
||||
scope.database.settings.host = answers.host;
|
||||
scope.database.settings.srv = _.toString(answers.srv) === 'true';
|
||||
scope.database.settings.port = answers.port;
|
||||
scope.database.settings.database = answers.database;
|
||||
scope.database.settings.username = answers.username;
|
||||
@ -223,10 +231,10 @@ module.exports = (scope, cb) => {
|
||||
cmd += ` ${scope.client.module}`;
|
||||
}
|
||||
|
||||
if (scope.client.connector === 'strapi-bookshelf') {
|
||||
cmd += ' strapi-knex@alpha';
|
||||
if (scope.client.connector === 'strapi-hook-bookshelf') {
|
||||
cmd += ` strapi-hook-knex@alpha`;
|
||||
|
||||
scope.additionalsDependencies = ['strapi-knex', 'knex'];
|
||||
scope.additionalsDependencies = ['strapi-hook-knex', 'knex'];
|
||||
}
|
||||
|
||||
exec(cmd, () => {
|
||||
@ -234,8 +242,8 @@ module.exports = (scope, cb) => {
|
||||
const lock = require(path.join(`${scope.tmpPath}`, '/node_modules/', `${scope.client.module}/package.json`));
|
||||
scope.client.version = lock.version;
|
||||
|
||||
if (scope.developerMode === true && scope.client.connector === 'strapi-bookshelf') {
|
||||
const knexVersion = require(path.join(`${scope.tmpPath}`, '/node_modules/', 'knex/package.json'));
|
||||
if (scope.developerMode === true && scope.client.connector === 'strapi-hook-bookshelf') {
|
||||
const knexVersion = require(path.join(`${scope.tmpPath}`,`/node_modules/`,`knex/package.json`));
|
||||
scope.additionalsDependencies[1] = `knex@${knexVersion.version || 'latest'}`;
|
||||
}
|
||||
}
|
||||
@ -251,6 +259,7 @@ module.exports = (scope, cb) => {
|
||||
require(path.join(`${scope.tmpPath}`, '/node_modules/', `${scope.client.connector}/lib/utils/connectivity.js`))(scope, cb.success, connectionValidation);
|
||||
} catch(err) {
|
||||
shell.rm('-r', scope.tmpPath);
|
||||
console.log(err);
|
||||
cb.success();
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-new",
|
||||
"version": "3.0.0-alpha.12.7.1",
|
||||
"version": "3.0.0-alpha.14",
|
||||
"description": "Generate a new Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -17,9 +17,9 @@
|
||||
"fs-extra": "^4.0.0",
|
||||
"inquirer": "^4.0.2",
|
||||
"listr": "^0.14.1",
|
||||
"lodash": "^4.17.4",
|
||||
"lodash": "^4.17.5",
|
||||
"ora": "^2.1.0",
|
||||
"strapi-utils": "3.0.0-alpha.12.7.1",
|
||||
"strapi-utils": "3.0.0-alpha.14",
|
||||
"uuid": "^3.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
1
packages/strapi-generate-plugin/.gitignore
vendored
1
packages/strapi-generate-plugin/.gitignore
vendored
@ -93,6 +93,7 @@ build
|
||||
node_modules
|
||||
.node_history
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
|
||||
############################
|
||||
|
||||
@ -0,0 +1 @@
|
||||
{}
|
||||
1
packages/strapi-generate-plugin/files/admin/src/translations/es.json
Executable file
1
packages/strapi-generate-plugin/files/admin/src/translations/es.json
Executable file
@ -0,0 +1 @@
|
||||
{}
|
||||
@ -0,0 +1 @@
|
||||
{}
|
||||
@ -0,0 +1 @@
|
||||
{}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user